pax_global_header00006660000000000000000000000064146762267160014533gustar00rootroot0000000000000052 comment=9f92319a2c8ce95ea0643179791fc3136b412505 instead-3.5.2+dfsg/000077500000000000000000000000001467622671600141105ustar00rootroot00000000000000instead-3.5.2+dfsg/AUTHORS000066400000000000000000000014541467622671600151640ustar00rootroot00000000000000INSTEAD was written by: Peter Kosyh Initial port to Windows: Ilya Ryndin Port to Android: Mahno Aleksey Anton Kolosov Boris Timofeev Port to macOS: .dm Port to Windows CE: Andrey Afletdinov Debian package: Sam Protsenko FreeBSD port, cmake support and fixes: Dmitry Marakasov Right-to-Left and multilingual mixed text support: Mehdi Sadeghi Ideas, games, advices, testing, bug reports, fixes ... Vadim Balashoff Evgeniy Efremov (jhekasoft) Oleg Gvozdev Heorhiy Kharvat (zaynyatyi) Serj Kalichev Vladimir Podobaev Alexander Soborov Vasily Voronkov Alexander Yakovlev Vladimir Zhirov Andrew Lobanov And many, many others... instead-3.5.2+dfsg/CMakeLists.txt000066400000000000000000000051701467622671600166530ustar00rootroot00000000000000PROJECT(instead) CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0) SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) IF("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") MESSAGE(FATAL_ERROR "In-source builds are not allowed. Please read ./INSTALL") ENDIF("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}") # global constants SET(INSTEAD_VERSION "3.5.2") # options OPTION(WITH_GTK2 "Use GTK2 file open dialog" OFF) OPTION(WITH_GTK3 "Use GTK3 file open dialog" ON) OPTION(WITH_ICONV "Build with iconv support" ON) OPTION(WITH_LUAJIT "Use LuaJIT instead of Lua" ON) OPTION(WITH_HARFBUZZ "Build with HarfBuzz for RTL language support" OFF) # Note: there are three build modes for instead: # - SYSTEMWIDE # use it if you want to install it into your (unix) system # - STANDALONE # used to generate standalone relocatable package which # may be run from anywhere. `install' target stages all # required files in ${STANDALONEDIR} for you # - neither (both options disabled) # instead may be run from build directory, useful for # development OPTION(SYSTEMWIDE "Build for systemwide install" ON) OPTION(STANDALONE "Build for standalone package creation" OFF) OPTION(APPIMAGE "Build for appimage package creation" OFF) IF(WITH_GTK2 AND WITH_GTK3) MESSAGE(WARNING "WITH_GTK2 and WITH_GTK3 are mutually exclusive, disabling WITH_GTK2") SET(WITH_GTK2 OFF) ENDIF(WITH_GTK2 AND WITH_GTK3) IF(SYSTEMWIDE AND STANDALONE) MESSAGE(WARNING "Both STANDALONE and SYSTEMWIDE specified, disabling SYSTEMWIDE") SET(SYSTEMWIDE OFF) ENDIF(SYSTEMWIDE AND STANDALONE) IF(APPIMAGE) SET(CMAKE_INSTALL_PREFIX "/usr") ENDIF(APPIMAGE) SET(BINDIR "bin" CACHE STRING "Where to install binaries") SET(DATADIR "share/instead" CACHE STRING "Where to install data files") SET(STEADDIR "${DATADIR}/stead" CACHE STRING "Where to install stead files") SET(THEMESDIR "${DATADIR}/themes" CACHE STRING "Where to install themes") SET(GAMESDIR "${DATADIR}/games" CACHE STRING "Where to install games") SET(ICONDIR "share/pixmaps" CACHE STRING "Where to install icons") SET(DOCDIR "share/doc/instead" CACHE STRING "Where to install documentation") SET(LANGDIR "${DATADIR}/lang" CACHE STRING "Where to install language files") SET(MANDIR "share/man" CACHE STRING "Where to install man pages") SET(DESKTOPDIR "share/applications" CACHE STRING "Where to install .desktop files") SET(STANDALONEDIR "${PROJECT_BINARY_DIR}/standalone" CACHE STRING "Where to stage stanalone package") # subdirectories ADD_SUBDIRECTORY(desktop) ADD_SUBDIRECTORY(doc) ADD_SUBDIRECTORY(games) ADD_SUBDIRECTORY(icon) ADD_SUBDIRECTORY(lang) ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(stead) ADD_SUBDIRECTORY(themes) instead-3.5.2+dfsg/COPYING000066400000000000000000000032211467622671600151410ustar00rootroot00000000000000Copyright 2009-2023 Peter Kosyh 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. Please see each individual source file for a list of they copyright holders. INSTEAD links with the following libraries/sources: Lua (MIT) SDL_gif.c (Zlib) SDL2 (Zlib) SDL2_image (Zlib) SDL2_ttf (Zlib) SDL2_mixer (Zlib) SDL2_gfx (Zlib) Freetype (LGPL) FFmpeg (LGPL) jpeg (JPEG License) libpng (PNG license) zlib (Zlib License) list routines (MIT) (http://ccodearchive.net/info/list.html) LuaFileSystem (http://keplerproject.github.io/luafilesystem/license.html) tinymt32 (The 3-clause BSD License) HarfBuzz (old MIT) GLib (LGPL) instead-3.5.2+dfsg/ChangeLog000066400000000000000000000741041467622671600156700ustar00rootroot000000000000003.5.2 * enh: redesigned installer for Windows; * enh: gamepad triggers simulate mouse wheel up/down; * fix: theme.reset(); * fix: documentation. -- Peter Kosyh Sun, 1 Sep 2024 12:00:00 +0300 3.5.1 * enh: gamepads support; * fix: anigif logic; * fix: sprite alpha artefacts; * fix: cleanups in instead library and docs; * fix: Windows XP build; * fix: -software parameter in Windows; * fix: dbg keyboard input fix; * fix: segfault in pixels (line). -- Peter Kosyh Fri, 1 Sep 2023 12:00:00 +0300 3.5.0 * fix: menu font scaling; * fix: get_bool; * new: tutorial in stead3 API; * new: wheel input event (grab_events mode); * enh: do not scale-down non scalable themes via dpi scale < 1.0; * enh: be strict while open game via file; * enh: tiny2 better games compatible; * enh: WITH_LUAJIT is now on by default (cmake); * enh: Windows build updated SDL2 libs; * enh: github workflow for CI/emscripten/windows/appimage builds; * doc: embedding manual; * rem: S60, MAEMO, WinCE ports removed; * rem: SDL1 code removed. -- Peter Kosyh Sat, 27 Aug 2022 11:07:00 +0300 3.4.1 * fix: game pic scaling on dpi < 96. -- Peter Kosyh Wed, 08 Sep 2021 21:33:00 +0300 3.4.0 * fix: pxl:fill_triangle cw order normalization; * fix: build with new SDL_image; * new: dpi awarness for win; * new: high dpi ready (scale by dpi/96 when HQ option is on); * new: -dpi parameter; * new: instead.screen_dpi(); * new: theme scr.gfx.scale; * new: theme scr.dpi; * new: theme scr.scale_aware (1|2) - adaptive themes support; * new: run game from command line via path to main?.lua file; * enh: better scene pic scaling; * enh: SDL 2.0.14 for win build; * enh: use GetModuleName to detect exe path (win build); * new: pxl:tosprite (convert pxl to sprite with scaling); * enh: pxl:fill speedup when alpha is 255; * new: experimental gtk4.0 support. -- Peter Kosyh Tue, 31 Aug 2021 12:38:00 +0300 3.3.4 * fix: regression with direct mode and theme. -- Peter Kosyh Wed, 24 Mar 2021 09:11:00 +0300 3.3.3 * new: scr.col.brd in theme.ini; * new: rtl support (_USE_HARFBUZZ and new SDL_ttf needed); * new: instead.tiny flag in tiny; * enh: emscripten 2.0.12 ready; * enh: gtk3 build is enabled by default; * enh: APPIMAGE define; * enh: new anigif realization (LGPL code removed); * enh: lua5.4 ready; * enh: fixes and cleanups in code. -- Peter Kosyh Wed, 20 Jan 2021 16:00:00 +0300 3.3.2 * fix: -lua parameter; * fix: WM minimized state fix; * fix: anigif and decorators fix; * fix: gtk3 build warning; * new: initial gamepad support; * new: utf8 tiny library; * enh: loadstring sandboxed; * enh: stead3 debugger uses native text input; * enh: doc fixes; -- Peter Kosyh Sun, 19 Apr 2020 11:00:00 +0300 3.3.1 * fix: build with SDL 2.0.10; * enh: discord bot can be sticked to channel(s); * enh: english doc fixes; -- Peter Kosyh Fri, 4 Oct 2019 18:21:00 +0300 3.3.0 * new: input:text() event; * new: tiny instead for metaparser; * new: telegram, vk and discord bots; * enh: english documentation; * enh: Android port; * fix: list:add() and order; * fix: some compilation warnings; * fix: makefile and source code cleanups; * fix: possible segfault; * fix: do not eat keyboard input; -- Peter Kosyh Fri, 8 Mar 2019 09:28:00 +0300 3.2.2 * new: mobile theme; * new: -lang parameter; * new: -notheme parameter; * new: instead.screen_size(); * enh: themes cleanups; * new: cmake and LuaJIT build (-DWITH_LUAJIT=1); * enh: autosave in emscripten build; * enh: load status in emscripten build; * new: machine-translated English manual; * fix: Lua5.3 compatibility; * fix: ini method and load parameter; * fix: -appdata and system build; * fix: build with zlib; * fix: std.fmt and substitutions ($); * fix: segfault on restart; * fix: build with old gcc. -- Peter Kosyh Sat, 1 Sep 2018 09:21:00 +0300 3.2.1 * fix: save in lua 5.2 (proxy objects); * new: {$fmt ... } substitution; * fix: instead.set_sound() and snd.play(); * fix: direct mode fix; * fix: bugs in documentation. * new: project moved to https://instead-hub.github.io -- Peter Kosyh Sun, 22 Apr 2018 13:34:00 +0300 3.2.0 * fix: segfault on path overflow fix; * fix: segfault in std.readdir fix; * fix: forever loop bug (unpaired {}); * fix: theme.restore(); * fix: fmt.anchor(), theme.snd.click(), push(), pop(); * fix: snapshots module bugs; * fix: gamefile with main3.lua; * fix: noinv/nolife modules ('step' mod_call error); * fix: xact booleans parameters; * fix: chnage_pl with string argument; * fix: always = true in dialog phrase; * fix: use opengl on Windows instead d3d (nvidia fullscreen bug); * fix: win32 and path encoding problem; * fix: instead.menu(); * fix: save declared functions in tables; * fix: sprite font:size with style; * enh: Android port improvements; * enh: click on bg not passed when xref selected (module click); * enh: documentation; * enh: speed improvements while theme updates; * enh: code cleanups; * new: walkback() in stdlib; * new: math.round; * new: std.var for variable extensions; * new: -renderer parameter; * new: -nocursor parameter; * new: SailfishOS port; * new: WinRT patches for upcoming port; * new: sprite.scr() returns background in non direct mode; * new: sprite.render_callback() (yahoooo!); * new: instead.clipboard() added (SDL2 only); * new: instead.wait_use(); * new: instead.grab_events(); * new: theme.scr.w(), theme.scr.h() (read only); -- Peter Kosyh Fri, 9 Feb 2018 21:07:00 +0300 3.1.2 * regression fix in fading and menu; -- Peter Kosyh Mon, 21 Aug 2017 16:45:00 +0300 3.1.1 * regression fix in fading (Android); * code cleanups; * doc cleanups; -- Peter Kosyh Mon, 21 Aug 2017 08:50:00 +0300 3.1.0 * emscripten port; * fix div by zero in rnd; * fix in loadmod (from gamefile); * fix in path (.walk as function); * fixes in doc; * code cleanups (compilation warnings); * instead.noise1/2/3/4 (Perlin Noise); * pixels:scale()/rotate(); -- Peter Kosyh Sun, 20 Aug 2017 10:16:00 +0300 3.0.1 * fix segfault while pause/resume; * stead3: start() logic fix; -- Peter Kosyh Wed, 24 May 2017 21:03:00 +0300 3.0.0 * refactoring (src/instead); * tiny-instead; * bug fixes; * completely new stead3; * sound.load_mem; * sprite.pixels; -- Peter Kosyh Wed, 19 Apr 2017 17:45:00 +0300 2.4.1 * sprite from sprite load bug fixed with scaling; * fix in themes pager; * fix in stead.menu_toggle(); * memory leak in free_font (sprtites) fixed; * new stead.mouse_show(); * fix in txtnb() escaping; * fix in stead.busy(); * fixes in fonts,cutscene and keyboard example modules; * ua -> uk language, fixes in translation; -- Peter Kosyh Sat, 16 Apr 2016 13:50:00 +0300 2.4.0 * txty (iface.y) -- y position in text; * menu_toggle ("themes", "settings" added), w/o return to top menu; * win.ways.mode = top|bottom in themes; * game themes support (themes/ directory in game); * set theme vars is not working when not using own themes; * fix stead.api_atleast/atleast when using with vv.mm format; * be more strict while loading combined images; * in -debug mode any "resource not found" messages are errors; * be more simple with walk from enter/exit (>= 2.4.0); * About menu shows game information; * -standalone mode; * scr.gfx.icon added (SDL2 only, experimental); * -noconfig parameter; * profiles support added (-profile parameter); * -hires parameter and HQ option (enabled by default); * -modes parameter; * Android-NG and IOS ports improvements; * font size scale is displayed in percents; * -fontscale argument; -- Peter Kosyh Thu, 18 Feb 2016 15:09:00 +0300 2.3.0 * audio default is 44100 hz; * fix segfault in windows version; * visits/visited -> stead.visits, stead.visited; * -nosound fix (volume 0 problem); * fix bug in fingers module; * fixes in Android version; * -resizable parameter and config option (resizable window mode); * SDL2: graphics rewrite (better full screen handling, resize, etc.) * SDL2: fix with alpha blended bg; -- Peter Kosyh Sun, 18 Oct 2015 13:15:00 +0300 2.2.7 * fix bug with fingers positions (forgotten patch) (SDL2); -- Peter Kosyh Sun, 20 Sep 2015 13:49:00 +0300 2.2.6 * fix bug with SDL2 and cursor draw; * fix bug with fingers and click modules; * fix bug with fingers positions (SDL2); * fix bug with cursor positions (SDL2); * fix bug with menu and 32 bit float (S60); * fix SDL window title on S60; -- Peter Kosyh Sun, 20 Sep 2015 13:22:00 +0300 2.2.5 * fix bug with SDL2 and idf format (segfault); * fix bug with SDL2 windows build (cursor coordinates); * fix some bugs with SDL2; * fix bug with music paused while run fullscreen mode; -- Peter Kosyh Sun, 30 Aug 2015 16:15:00 +0300 2.2.4 * fix in prefs module (Windows); * German language and tutorial; -- Peter Kosyh Sun, 2 Aug 2015 11:22:00 +0300 2.2.3 * fix in player_save; * always reset LC_CTYPE to C; * fallback to software renderer if can not create texture; * remove game dialog cleanup; * fix in gamereset() and init() call; * fix with gtk dialog open and SDL2; -- Peter Kosyh Fri, 20 Mar 2015 18:56:00 +0300 2.2.2 * last_disp regression fixed; -- Peter Kosyh Fri, 6 Feb 2015 19:17:00 +0300 2.2.1 * -alsa option removed, use SDL_AUDIODRIVER env instead; * -vsync added for SDL2 vsync feature; * *gray* and *grey* colors are both valid; * fix in sandbox with stead.type; * fix in sprites dirty screen logic; * no 48000 hz sound anymore; * windows build uses SDL2 and luajit; * debug and vsync options in rc file; -- Peter Kosyh Sat, 31 Jan 2015 16:27:00 +0300 2.2.0 * fix in debugger; * fix in links hl with events module; * fix in fr language; * fix segfault in fgetsesc; * space added in fixed gfx theme mode when ways are empty; * rnd is now Tiny Mersenne Twister algo; * scr.gfx.scalable & 4 -> disable font scaling; * stead.life_moved() to detect moves in life; * stead.last_disp() added; * stead.nop() added; * stead.rndseed() added; * ready for IOS build; * touch events via input.finger (finger module); * stead.mouse_pos now returns buttons mask; * do gfx sync in direct mode only after timer event (speedup); * SDL2: do not send key repeats in direct mode (speedup); * SDL2: use scancodes instead keycodes (dvorak fixed); * updated doc/examples/fonts.lua; * fix dropf with 2nd parameter; * added forgotten function dropto; * updated documentation (en/ru); -- Peter Kosyh Thu, 1 Jan 2015 10:52:00 +0300 2.1.1 * -debug parameter fixed; -- Peter Kosyh Wed, 9 Jul 2014 13:30:00 +0400 2.1.0 * fr.ini added; * fix in highlighting links; * sprites colorkey function; * events module (pause, resume, quit events); * stead.stop_sound/sound.stop second [fadeout] parameter; -- Peter Kosyh Tue, 3 Jun 2014 17:28:00 +0400 2.0.3 * sandbox fix for win32 systems; * fix bug while changing HZ; -- Peter Kosyh Thu, 20 Feb 2014 17:19:00 +0400 2.0.2 * sandbox fixes; * be more compatible with lua 5.2; * SDL2.0 gfx mode initialization; -- Peter Kosyh Thu, 30 Jan 2014 08:30:00 +0400 2.0.1 * lua5.2 compatible; -- Peter Kosyh Mon, 27 Jan 2014 19:40:00 +0400 2.0.0 * GPL2 code removed. Now INSTEAD is covered by MIT license; * code in now hosted on github (fixes in Makefiles); * sandbox (no write access from lua outside game); * window title contains the game name; * sdl-instead start variant; * fixes in Makefiles (PREFIX and DESTDIR); * experimental cmake support; * doc/examples addons; * -lua and -luac parameters; * in windows do not close -debug console until press return; * game.gui.hidetitle; * stead.api_atleast() and stead.atleast(); * stead.tonum, stead.tostr, stead.type, stead.ipairs, stead.pairs, stead.opairs; * potential bug with non ascii save path and non UTF-8 game codepage; * bug with language changing; * bug with anigif rotate and scale; * bug with anigif and cursor; * typo in Please, wait message; -- Peter Kosyh Sun, 26 Jan 2014 13:12:00 +0400 1.9.1 * INSTEAD moved to sourceforge.net; * pt_BR language added; * example code fixes; * -hinting option; * fixes in Makefiles and configure script; * lua5.2 fix; * bug fix in new/delete; -- Peter Kosyh Sat, 13 Jul 2013 14:30:00 +0400 1.9.0 * music track from svenzzon!!!; * SDL2.0 ready; * -owntheme option; * -noautosave option is not saved; * -software option; * bug fix: segfault while change and restart game; * img_t refactoring for future architecture upgrade; * fix in anigif scale; * fix in stead.dialog_rescan; * mp3 fix in windows binary; -- Peter Kosyh Fri, 12 Apr 2013 08:00:00 +0400 1.8.3 * bug fix in start() from gamefile; * bug fix do not remove xwalk after gamereset; * bug fix in txtnb (lua5.2 compat); * stead.savename function to redefine saves; * stead.restart() to restart current game; * p/pr/pn now do error when called from global context; * now math. and os. moved to stead; * debian friendly release; * ctrl-r is alt-r, ctrl-q is alt-q alias; * New documentation; * stead.menu_toggle 'load/save/quit' parameters; -- Peter Kosyh Sat, 26 Jan 2013 14:50:00 +0400 1.8.2 * bug fix in gfx_chnage_screen (sigsegv); * bug fix in sound system (sigsegv); * bug fix in input.lua and lua 5.2; * bug fix filter scr.w scr.h changing from lua; * fixes in ua tutorial; * icon fix in windows; * cleanup code for clang; -- Peter Kosyh Wed, 19 Dec 2012 10:34:00 +0400 1.8.1 * bug fix in onact (stop act on non-nil return); * bug fix in instead_gamespath/instead_themespath/instead_steadpath; * bug fix in vars, now do not empty [k] indexes in obj; * bug fix flickering while theme update; * new theme parameter: win.scroll.mode = [0|1|2|3] * new iface.anchor feature; * faster working with layouts; -- Peter Kosyh Sat, 17 Nov 2012 10:32:00 +0400 1.8.0 * bug fix in stead.need_scene() with parameter; * bug fix in click on sprite; * bug fix in save logic (table keys); * bug fixes in dbg; * bug fix in proxy_menu - possible to work with nam = true objects; * bug fix much more faster text output; * bug fix if use returns nil and used returns true; * bug fix in change theme on the fly via theme module (segfault); * bug fix in restore_snapshot (extra call to main.enter); * internal functions are moved in stead. table; * dbg module: use f7 key again to exit debugger; * enable and disable methods in list; * sprite.rotate, sprite.scale smooth parameter; * much better scr.gfx.scalable handling, uses /2^x scaler; * CPPFLAGS added in Makefile; * scaler is updated from SDL_gfx 2.0.24; -- Peter Kosyh Sat, 1 Sep 2012 12:08:00 +0400 1.7.0 * bug fix in phrase handling w/o parameter; * bug fix in zip unpack; * fix in doc/menu; * svg logo added; * busy dialog; * opt_fading; * normal fonts in MAEMO build; * wroom module added; * nouse module added; * nolife module added; * hideinv module is better now, noinv added; * new dlg module: * - better dlg syntax; * - psub/pret/pjump/pstart; * - stead.phrase_prefix; * compose in sprite; * game.onact/onwalk/onuse/oninv handlers; * counters module; * proxymenu module; * configure.sh now checks gtk+-3.0; * sprite.box and sprite.blank; * stead.add_var internal command; * stead.gui.hideways added; * xact now searches recursive; * xwalk xact added; * lifeon with order; * correct output from life methods while moving; * stead.need_scene() added; * stead.last_act() added; * move/purge/remove/replace now works with lists too; * dialog:visible added; -- Peter Kosyh Thu, 17 Apr 2012 13:40:00 +0400 1.6.2 * bugfix in build with SDL_mixer 1.2.12; * configure.sh script is now compatible with BSD; -- Peter Kosyh Thu, 08 Feb 2012 19:52:00 +0400 1.6.1 * bugfix in prefs; * justify text option; * new track in tutorial3 (svenzzon - The Titan Turrican, CC BY-NC-SA 3.0); * SDL_mixer 1.2.12 ready; * gentoo build fix; * fix build on systems w/o PATH_MAX; * fix SDL icon; -- Peter Kosyh Thu, 19 Jan 2012 09:43:00 +0400 1.6.0 * CJK support; * set_music_fading(out, in); * 1 bit transparent icon added for SDL; * stead.space_delim added; * get_themespath, get_gamespath; * goto -> walk, goXX -> walkXX; * lua5.2 ready; -- Peter Kosyh Tue, 20 Dec 2011 08:37:00 +0400 1.5.2 * bug fix in release kbd event; * improved motion mode; * align in float gfx mode; -- Peter Kosyh Sun, 10 Oct 2011 09:49:00 +0400 1.5.1 * bug fix in game_cmd logic; * bug fix in highlight logic; * bug fix in click sound logic; * bug fix in RAW_TEXT; * INSTEAD SDL -> INSTEAD; * languages are sorted now; * set_timer moved to stead; * code cleanup (no warnings); -- Peter Kosyh Mon, 05 Sep 2011 16:11:00 +0400 1.5.0 * bug fix in gamefile; * bug fix in lifes output; * bug fix in PLAYER_MOVED and lifes; * bug fix in stop_sound; * bug fix in set_music with parameter; * bug fix in highlighting; -- Peter Kosyh Mon, 17 Aug 2011 15:40:00 +0400 1.4.5 * bug fix in rnd() w/o parameter; * bug fix in for_each; * bug fix in txtnb and \; * bug fix in original theme picture scaling; * bug fix in left/right image alignment; * bug fix in change_pl; * callpush/callpop/cctx/strip do_ini and some others moved to stead; * win.align added to theme; * theme_name added; * now fading first value is new scene flag; * more information in error messages while checking lists; * fixes in input module; * added PLATFORM variable; -- Peter Kosyh Mon, 01 Aug 2011 12:24:00 +0400 1.4.4 * bug fix in direct mode (memory leak); -- Peter Kosyh Thu, 21 Jun 2011 08:57:00 +0400 1.4.3 * bug fix in nopara logic; * ukranian translation and tutorial; * multilang tutorial3; * sprites small fix (predefined handles); * cursor changing from direct mode support; -- Peter Kosyh Thu, 19 Jun 2011 10:24:00 +0400 1.4.2 * bug fix in idf gets; * bug fix in kbd hooking; -- Peter Kosyh Thu, 19 May 2011 20:14:00 +0400 1.4.1 * bug fix in use; -- Peter Kosyh Thu, 12 May 2011 23:53:00 +0400 1.4.0 * bug fix in imgl/imgr; * bug fix in xact; * bug fix in jump to pos logic; * bug fix lags in sound; * bug fix with wince/windows with themes load; * experemental sprites technology; * global dir is now readdir; * multichannal sound system (add_sound, stop_sound); * -appdata parameter; * -chunksize parameter; * show dir to be deleted while remove game; * theme reset features; * mouse_pos added; * start() init function added; * idf files support (instead data format); * menu font is now scalable too; * toggle_menu added; * get_ticks added; * bit_xxx bitwise operations added; * visits() added; -- Peter Kosyh Mon, 2 May 2011 08:35:00 +0400 1.3.4 * bug fix in text renderer with italic text; * bug fix with imgl/imgr in inv; * bug fix in video init; * bug fix in theme.get 'inv.mode' * font faces { } syntax; * new default font; * set light hinting for font; * added stead.dir iterator; * modules doc fix; * languages dir renamed to lang; * updated manual.pdf; -- Peter Kosyh Fri, 11 Mar 2011 12:10:00 +0300 1.3.3 * bug fix (kbd input); * modules docs; -- Peter Kosyh Thu, 27 Feb 2011 20:27:00 +0300 1.3.2 * bug fix (dates in save slots); * bug fix (dbg fixes); * bug fix (f8 and f9 error msg); * small bug fixes; * s60 build; * SDL 1.3 ready; * it lang and tutorial; -- Peter Kosyh Thu, 24 Feb 2011 13:12:00 +0300 1.3.1 * bug fix (imgl and justify); * bug fix (languages in WinCE version); * bug fix (prefs do not create save dir); * bug fix (alt+f4 != f4); * bug fix ( tag parsing) * visual.lua moved to doc/; -- Peter Kosyh Mon, 29 Nov 2010 15:44:00 +0300 1.3.0 * bug fix (resample sounds while HZ change); * bug fix (empty bg); * bug fix (cursor center scaling); * changing themes from game; * strike ougth text; * *.fnt.height theme parameter; * scroller positions in theme; * escaping ^ and delim; * box: and blank:; * pad: ; * speed up; * picture flow; * prefs:purge now removes vars; * dialog:empty added; * txttab; * tutorial update; -- Peter Kosyh Tue, 12 Nov 2010 22:42:00 +0300 1.2.3 * android build; * bug in xact; -- Peter Kosyh Sat, 2 Oct 2010 16:53:00 +0300 1.2.2 * xact now can be used from everywhere; * much speed improvments; * get_gamepath, get_steadpath; * wince port; * internal cleanups; -- Peter Kosyh Fri, 25 Sep 2010 13:59:00 +0300 1.2.1 * clearlooks bg; * fading fix; * fix in disable autosave; * disp fix; * savevars optimization; -- Peter Kosyh Sat, 28 Aug 2010 19:47:00 +0300 1.2.0 * unpack/install feature; * browse feature (win32 and gtk); * clever game/themes sorting; * time of save slots; * remove games; * aligned width for themes/games dialog; * local appdata mode (portable app); * clearlooks theme; * inv align modes; * prefs object; * init() function; * snapshots (not documented?); * hook and inherit; * entered/left human friendly actions; * stead.cmd, stead.args added; * require added (modules: goto, xact, input, click, vars, dbg, snapshot, prefs, format, kbd, hotkeys); * instead_version added; * taketo/takef added; * disable/enable/disable_all/enable_all added; * exist() added (seen over disabled objects); * path() added; * visited() added; * live() added; * nameof() added; * goback() added; * goin()/goout() added; * disp attribute added; * improved debugger; * save vars in _G; * no duplicated games while looking gamespaths; * code function!!!; * args in call; * var and global; * self() is now self; * psen/punseen for dlg; * no return goto needed; * disable_all/enable_all for lists; * purge and list_purge; * undocumented gamefile; * undocumented LANG; * many bugfixes... * mac os x port -- Peter Kosyh Wed, 04 Aug 2010 20:59:00 +0300 1.1.6 * bugfix (no closed files) * bugfix in line breaking with gfx * pr() function added in stead -- Peter Kosyh Wed, 19 May 2010 17:31:00 +0300 1.1.5 * multiple anigif in one layout fix * click in picture event * game.action callback * bug in parsing * pause game while minimize (-nopause option added) * 8 bit scaler fix -- Peter Kosyh Wed, 10 Mar 2010 15:20:51 +0300 1.1.4 * keyboard navigation fix * cursor while menu and lost focus * lower cpu usage (no gif logic if no gifs are drawn) -- Peter Kosyh Fri, 05 Mar 2010 18:28:40 +0300 1.1.3 * unix_path in get_img * " in variable names (save) * \\, in ways and inv * 32 bit bmp fix -- Peter Kosyh Wed, 16 Feb 2010 11:10:40 +0300 1.1.2 * bug in saves -- Peter Kosyh Wed, 10 Feb 2010 13:39:47 +0300 1.1.1 * encode path in save (' in paths); * mouse focus win problem; * cleanups in stead.lua; * doc updates; * alt-r in debug mode (restart game); * -version arg * timer * kbd input * mouse input * bluesteel theme * nop cmd added in stead.lua * anigif while menu bug * add inv.mode disabled * txtnb added to stead.lua * bg scaling fix * broken codepage fix * esc strings in tag * themes and games sorting -- Peter Kosyh Thu, 14 Jan 2010 15:47:50 +0300 1.0.5 * segfault while is_sound with -nosound * snd volume hack * arctic theme added -- Peter Kosyh Thu, 7 Jan 2010 14:34:00 +0300 1.0.4 * xref hl optimization * now, write save slots in game/saves if game/saves exist -- Peter Kosyh Tue, 12 Dec 2009 17:15:00 +0300 1.0.3 * autojump to text change * no cursor flickering * sdl_path (i18n M$ win sdl paths) -- Peter Kosyh Tue, 01 Dec 2009 14:12:36 +0300 1.0.2 * fix in box normalize * fix in scaling * fixed f5 key -- Peter Kosyh Tue, 24 Nov 2009 11:00:20 +0300 1.0.1 * bug: no fclose :( * i18n + esp lang and tutorial * cat removed -- Peter Kosyh Fri, 20 Nov 2009 13:33:36 +0300 1.0.0 * another mouse buttons -- escape * escape as use cancel * lifeoff from life method * bug fix in anigif logic * bug fix in img() * more clever linebreaking * kill empty lines at end of layout * typo in color table (graphics.c) by Alexander * manual.tex by Alexander and commiters * default-large theme is default * combined images! * page up, page down clever logic; * f8/f9 - quicksave/quickload * game.enable_save * lua stack overflow??? * autosave function -- Peter Kosyh Tue, 3 Nov 2009 19:43:00 +0400 0.9.3 * have and seen fixes * -encode option + doencfile * print reregister * from() with argument * new()/delete() (allocator object) * game:ini() fix * theme scaling (yahoo!!!) * scene_use attribute (scene objects using on each other) -- Peter Kosyh Mon, 12 Oct 2009 11:09:19 +0400 0.9.2 * animated gif support * graphics everywhere!!! (img cmd) * sound support (set_sound) * some cleanups -- Peter Kosyh Sun, 4 Oct 2009 16:10:09 +0400 0.9.1 * mouse gfx bug * noautosave option * make uninstall * === STEAD FIXES ==== * gui.lua is separated file * menus in gfx mode!!! :) * stead.lua fixes: * ref fix * phrases saver * player is object * disable_all enable_all for object * inherited inventory * save game bug * own stead namespace (table problem fixed!) * recurse for exit breaking * wrap into vroom not call exit twice -- Peter Kosyh Sun, 15 Sep 2009 14:42:44 +0400 0.9 * fixes in localization * srch method for player * english tutorial * separated games? * font with apache license :) * debian cleanups -- Peter Kosyh Tue, 15 Sep 2009 13:29:55 +0400 0.8.9 * -gamespath -game -themespath -theme options * runtime languages * disabled() function in stead * list_zap, list_concat * remove added * stead.lua fixes * full keyboard control! * alt enter fix * gfx cursor support! * no reset video while change game/theme * tutorial2 -- Peter Kosyh Sat, 5 Aug 2009 11:25:01 +0400 0.8.8 * Makefiles fixes * cat game fix * .insteadrc now in .instead/ by default * small fixes -- Peter Kosyh Mon, 31 Aug 2009 11:25:01 +0400 0.8.7 * highlight bug in nohl mode with filter * windows version now looks games and themes in appdir. -- Peter Kosyh Fri, 28 Aug 2009 12:51:08 +0400 0.8.6 * cat game fixes * seen extra parameter -- Peter Kosyh Thu, 27 Aug 2009 08:32:00 +0400 0.8.5 * possible segfaults in timer functions. * ways, objs, drop, take - extra parameters * put - function * set_music fixes -- Peter Kosyh Thu, 24 Aug 2009 08:32:00 +0400 0.8.4 * bug in savevar * bug in long strings -- Peter Kosyh Thu, 20 Aug 2009 14:09:14 +0400 0.8.3 * sge forgotten * set_music with loop argument bug -- Peter Kosyh Wed, 19 Aug 2009 14:09:14 +0400 0.8.2 * gfx_load_img -- Peter Kosyh Sat, 15 Aug 2009 14:09:14 +0400 0.8 * key_name attribute!!!! * do_ini * version in stead.lua * opairs!!! * vroom fix * typos * backtrace * list_set -- Peter Kosyh Fri, 07 Aug 2009 14:09:14 +0400 0.7.7-4 * Fixes :) -- Peter Kosyh Wed, 05 Aug 2009 17:26:55 +0400 0.7.7 * typos in games * local games now can be placed in ~/.instead/games * console version disabled by default * -- $Name: tag -- full name of games, not only dirname * fix of link color for title/ways * bug in text layout logic (last period in line) * embedded mode (picture and ways inside text!!!) * float mode (for books) * faster text renderer (x2-x5 times) * free motion mode of scrolling * click sound support in themes (in default theme too) * new options (click sound, music) * default theme changes * fullscreen with Alt-Enter * options -alsa, -fullscreen, -window * now italic font used for events * 48000Hz added in sound preferences * now scroll position is saved in embedded mode * themes support, one new theme added * vway and vroom added * updated tutorial * set_music now take an loop parameter * autosave is now default * now vars saved if they begins from uppercase letter (undescore too); * save slots !!! * a lot of bugs fixed (memory leaks, SDL cavities.. ) -- Peter Kosyh Thu, 30 Jul 2009 18:12:19 +0400 0.7.6-1 * debian file fixes -- Peter Kosyh Fri, 29 May 2009 14:17:01 +0400 0.7.6 * Keyboard scrolling * Font scaling * inv.horiz option -- Peter Kosyh Mon, 25 May 2009 10:58:29 +0400 0.7.5 * Initial release -- Peter Kosyh Thu, 21 May 2009 11:40:29 +0400 instead-3.5.2+dfsg/INSTALL000066400000000000000000000066121467622671600151460ustar00rootroot00000000000000INSTEAD 3.5.2 ============= WARNING! For successfull building you must install these development packages (names may vary in your distribution): sdl2, sdl2-mixer, sdl2-image, sdl2-ttf, lua5.1/luajit, iconv and gtk+2(3) (to build with open file dialog) Optionally you may use: lua5.2/lua5.3/lua5.4 HarfBuzz and SDL2_ttf compiled with HarfBuzz support 0) Prepare for building ======================= Unpack source package with this command: $ tar xzvf instead_.tar.gz Change current dir to project's build dir: $ cd instead- There are several ways to build package. 1) On Ubuntu ============ Install stable (old) version from repo: $ apt-get install instead Or use ppa with latest version: https://launchpad.net/~gl00my/+archive/ubuntu/instead 2) On Debian based systems you can build deb package ==================================================== $ sudo apt-get install liblua5.1-dev libsdl2-dev libsdl2-ttf-dev libsdl2-image-dev libsdl2-mixer-dev $ sudo apt-get install build-essential debhelper $ debuild $ cd .. $ sudo dpkg -i instead_.deb 3) On arch linux ================ Install stable version from AUR: $ yay -S instead Or build from svn: $ make PKGBUILD $ makepkg -s And, I think, you have enough skills to build package yourself. ;) 4) On FreeBSD ============= Install instead from ports with pkgng: # pkg install instead Or: # cd /usr/ports/games/instead # make install Or build from tarball: $ ./configure.sh $ gmake 5) On RPM based system ====================== There is .spec file in tarball. 6) For other distributions ========================== You have three choices: a) try to use cmake rules b) try run ./configure.sh and follow instructions c) do all things manually 7) Build using cmake ==================== $ mkdir build $ cd build $ cmake .. $ make $ sudo make install Warning, in some systems (like Arch linux) you need to define LUA dir, to help cmake. For example (Arch linux): $ LUA_DIR=/usr/include/lua5.1/ cmake .. To build standalone version, use this (in ./build/ directory): $ cmake .. -DSTANDALONE=1 $ make && make install $ cd standalone $ ./sdl-instead Some options: WITH_GTK2 Use GTK2 file open dialog WITH_GTK3 Use GTK3 file open dialog (default on) WITH_LUAJIT Use LuaJIT instead of Lua (default on)) WITH_HARFBUZZ RTL support. SDL2_ttf should be compiled with HarfBuzz too (default off) For example, to build standalone version without LuaJIT, use: $ cmake .. -DWITH_LUAJIT=0 -DSTANDALONE=1 8) Manual build =============== To build game, that runs just from build dir use Rules.make.standalone ---------------------------------------------------------------------- $ rm -f Rules.make $ ln -s Rules.make.standalone Rules.make $ make clean $ make If build process has failed check Rules.make.standalone and make changes if needed. $ ./sdl-instead To build game for system install -------------------------------- $ rm -f Rules.make $ ln -s Rules.make.system Rules.make $ make clean $ make If build process has failed check Rules.make.system and make changes if needed. $ sudo make install $ sdl-instead 8) Right-to-left support ======================== In order to build INSTEAD with right-to-left support, the SDL2_ttf underlying library and INSTEAD should be compiled with HarfBuzz support (see section 7 for cmake). SDL2_ttf has a flag for it (TTF_USE_HARFBUZZ) which should be set in SDL_ttf.c at the time of writing. Enjoy. instead-3.5.2+dfsg/Makefile000066400000000000000000000042211467622671600155470ustar00rootroot00000000000000include Rules.make include config.make VERTITLE := instead-$(VERSION) ARCHIVE := instead_$(VERSION).tar.gz# SUBDIRS += src/ stead games themes icon desktop doc lang all: @for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir $(@) || exit 1; \ done; Rules.make: ln -sf Rules.make.standalone Rules.make config.make: echo "# you can define own flags here" > config.make svnclean: { test -d .svn && svn st; } | grep "^?" | awk '{ print $$2 }' | grep -v "config.make" | while read l; do $(RM) -rf $$l; done gitclean: { test -d .git && git status -s; } | grep "^??" | awk '{ print $$2 }' | grep -v "config.make" | while read l; do $(RM) -rf $$l; done rules: $(RM) -f Rules.make ln -sf Rules.make.standalone Rules.make docs: rules make docs -C doc/ PKGBUILD: PKGBUILD.in tarball cat PKGBUILD.in | sed -e s/MD5SUM/`md5sum $(ARCHIVE) | cut -f1 -d' '`/g > PKGBUILD windows-sdl2.tar.gz: wget "http://sourceforge.net/projects/instead/files/instead/build-bin-data/windows-sdl2-2.0.24.2.tar.gz/download" -O $(@) # wget "http://sourceforge.net/projects/instead/files/instead/build-bin-data/windows-sdl2-2.0.24.tar.gz/download" -O $(@) # wget "http://sourceforge.net/projects/instead/files/instead/build-bin-data/windows-sdl2-2.0.22.tar.gz/download" -O $(@) # wget "http://sourceforge.net/projects/instead/files/instead/build-bin-data/windows-sdl2-2.0.14.tar.gz/download" -O $(@) build-bin-data: windows-sdl2.tar.gz tarball: clean svnclean gitclean docs rules echo "# you can define own flags here" > config.make ln -sf ./ $(VERTITLE) tar -cz --exclude $(VERTITLE)/$(VERTITLE) --exclude CJK.zip --exclude .git --exclude .svn --exclude $(ARCHIVE) --exclude windows-sdl2.tar.gz -f $(ARCHIVE) $(VERTITLE)/* $(RM) -f $(VERTITLE) clean: @for dir in $(SUBDIRS); do \ $(MAKE) clean -C $$dir $(@) || exit 1; \ done; $(RM) -f $(ARCHIVE) $(RM) -f PKGBUILD install: all ifeq ($(SYSTEMSETUP), yes) @for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir install || exit 1; \ done; else echo No install needed endif uninstall: ifeq ($(SYSTEMSETUP), yes) @for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir uninstall || exit 1; \ done; $(RM) -rf $(STEADPATH) else echo No uninstall needed endif instead-3.5.2+dfsg/Makefile.mingw000066400000000000000000000015211467622671600166670ustar00rootroot00000000000000MAKE=make ISCC = wine ~/.wine/drive_c/Program\ Files\ \(x86\)/Inno\ Setup\ 5/ISCC.exe all: config.make src/windows $(MAKE) -C src/zlib all $(MAKE) -C src all $(MAKE) -C themes all src/windows: tar xzvf windows-sdl2.tar.gz config.make: echo "# you can define own flags here" > config.make clean: $(RM) -rf bin $(RM) -rf src/windows $(MAKE) -C src/sdl-instead clean docs: # $(MAKE) pdf -C doc/ # man doc/instead.6 > doc/instead.txt # $(MAKE) wiki -C doc/ install: all cp src/sdl-instead.exe bin cp COPYING bin $(MAKE) DESTDIR=../bin/ -C themes install $(MAKE) DESTDIR=../bin/ -C games install $(MAKE) DESTDIR=../bin/ -C stead install $(MAKE) DESTDIR=../bin/ -C icon install $(MAKE) DESTDIR=../bin/ -C lang install $(MAKE) DESTDIR=../bin/ -C doc install setup: install docs cp contrib/setup.iss bin cd bin; $(ISCC) setup.iss instead-3.5.2+dfsg/PKGBUILD.in000066400000000000000000000011651467622671600156440ustar00rootroot00000000000000# Contributor: Peter Kosyh pkgname=instead pkgver=3.5.2 pkgrel=1 pkgdesc="instead quest interpreter" arch=('i686' 'x86_64') url="http://instead.sourceforge.net/" license=('MIT') depends=('sdl2_image' 'sdl2_mixer' 'sdl2_ttf' 'lua') source=(http://downloads.sourceforge.net/project/instead/instead/${pkgver}/instead_${pkgver}.tar.gz) md5sums=(MD5SUM) optdepends=('instead-launcher: install and update INSTEAD games from net') build() { cd "${srcdir}/instead-${pkgver}" echo "2" | ./configure.sh make PREFIX=/usr } package() { cd "${srcdir}/instead-${pkgver}" make DESTDIR="${pkgdir}" PREFIX=/usr install } instead-3.5.2+dfsg/README.md000066400000000000000000000014071467622671600153710ustar00rootroot00000000000000![Build status](https://github.com/instead-hub/instead/actions/workflows/CI.yml/badge.svg) # INSTEAD This program is covered by the terms of the MIT license. Check the [COPYING](COPYING) file for license. Check the [INSTALL](INSTALL) file for install instructions. ## Web resources - [Homepage](https://instead-hub.github.io) - [Code](https://github.com/instead-hub/instead) - [Community](https://instead-games.ru) - [Documentation](https://instead-hub.github.io/#doc) ## Install games To run games you may: - Unzip game archive into ~/.instead/games/; - Or run zip-packed game: $ instead ; - Or press [f4] to open file dialog (build with gtk2/gtl3 only). ## Contacts - Join the irc channel #instead on irc.oftc.net; - Check the [AUTHORS](AUTHORS) file. instead-3.5.2+dfsg/Rules.make000077700000000000000000000000001467622671600221142Rules.make.standaloneustar00rootroot00000000000000instead-3.5.2+dfsg/Rules.make.macosx000066400000000000000000000017401467622671600173340ustar00rootroot00000000000000VERSION := 3.5.2 DESTDIR= BIN= DATAPATH=__private__ STEADPATH=$(DATAPATH)/stead THEMESPATH=$(DATAPATH)/themes GAMESPATH=$(DATAPATH)/games ICONPATH=$(DATAPATH)/icon LANGPATH=$(DATAPATH)/lang DOCPATH= MANPATH= SYSTEMSETUP=no ZLIB_CFLAGS= ZLIB_LFLAGS=-lz LUA_CFLAGS=$(shell pkg-config --cflags lua5.1) LUA_LFLAGS=$(shell pkg-config --libs lua5.1) # for arch linux, fedora (may be others) use this # # LUA_CFLAGS=$(shell pkg-config --cflags lua) # LUA_LFLAGS=$(shell pkg-config --libs lua) # SDL_CFLAGS=$(shell sdl2-config --cflags) SDL_LFLAGS=$(shell sdl2-config --libs) -lSDL2_ttf -lSDL2_mixer -lSDL2_image CFLAGS += -Wall -Dunix -D_USE_UNPACK -D_USE_BROWSE INSTALLD=echo "Do not install standalone version!" INSTALLB=echo "Do not install standalone version!" INSTALL=echo "Do not install standalone version!" LN=echo "Do not install standalone version!" EXE= PLATFORM=macosx.m ADDOBJ=macosx.o macosx.o : macosx.m $(CC) -c $(<) $(I) $(CFLAGS) RESOURCES= RM=rm AR=ar rc RANLIB=ranlib instead-3.5.2+dfsg/Rules.make.standalone000066400000000000000000000016331467622671600201730ustar00rootroot00000000000000VERSION := 3.5.2 DESTDIR= BIN= DATAPATH=. STEADPATH=$(DATAPATH)/stead THEMESPATH=$(DATAPATH)/themes GAMESPATH=$(DATAPATH)/games ICONPATH=$(DATAPATH)/icon LANGPATH=$(DATAPATH)/lang DOCPATH= MANPATH= SYSTEMSETUP=no ZLIB_CFLAGS= ZLIB_LFLAGS=-lz LUA_CFLAGS=$(shell pkg-config --cflags lua5.1) LUA_LFLAGS=$(shell pkg-config --libs lua5.1) # for arch linux, fedora (may be others) use this # # LUA_CFLAGS=$(shell pkg-config --cflags lua) # LUA_LFLAGS=$(shell pkg-config --libs lua) # SDL_CFLAGS=$(shell sdl2-config --cflags) SDL_LFLAGS=$(shell sdl2-config --libs) -lSDL2_ttf -lSDL2_mixer -lSDL2_image -lm CFLAGS += -O2 -Wall -Dunix -D_USE_UNPACK -D_LOCAL_APPDATA INSTALLD=echo "Do not install standalone version!" INSTALLB=echo "Do not install standalone version!" INSTALL=echo "Do not install standalone version!" LN=echo "Do not install standalone version!" EXE= PLATFORM=unix.c RESOURCES= RM=rm AR=ar rc RANLIB=ranlib instead-3.5.2+dfsg/Rules.make.system000066400000000000000000000016151467622671600173670ustar00rootroot00000000000000VERSION := 3.5.2 PREFIX=/usr/local DESTDIR= BIN=$(PREFIX)/bin/ DATAPATH=$(PREFIX)/share/instead STEADPATH=$(DATAPATH)/stead THEMESPATH=$(DATAPATH)/themes GAMESPATH=$(DATAPATH)/games ICONPATH=$(PREFIX)/share/pixmaps DOCPATH=$(PREFIX)/share/doc/instead LANGPATH=$(DATAPATH)/lang MANPATH=$(PREFIX)/share/man/man6 SYSTEMSETUP=yes ZLIB_CFLAGS= ZLIB_LFLAGS=-lz LUA_CFLAGS=$(shell pkg-config --cflags lua5.1) LUA_LFLAGS=$(shell pkg-config --libs lua5.1) # for arch and gentoo linux use this # # LUA_CFLAGS=$(shell pkg-config --cflags lua) # LUA_LFLAGS=$(shell pkg-config --libs lua) # SDL_CFLAGS=$(shell sdl2-config --cflags) SDL_LFLAGS=$(shell sdl2-config --libs) -lSDL2_ttf -lSDL2_mixer -lSDL2_image -lm CFLAGS += -Wall -Dunix -D_USE_UNPACK # -D_SDL_MOD_BUG INSTALLD=install -d -m 0755 INSTALLB=install -m 0755 INSTALL=install -m 0644 LN=ln -sf EXE= PLATFORM=unix.c RESOURCES= RM=rm AR=ar rc RANLIB=ranlib instead-3.5.2+dfsg/Rules.mingw000066400000000000000000000015261467622671600162510ustar00rootroot00000000000000VERSION := 3.5.2 PREFIX=./ DESTDIR= BIN=$(PREFIX) STEADPATH=$(PREFIX)stead THEMESPATH=$(PREFIX)themes GAMESPATH=$(PREFIX)games ICONPATH=$(PREFIX)icon DOCPATH=$(PREFIX)doc LANGPATH=$(PREFIX)lang MANPATH=$(PREFIX)doc WINDOWS=yes ZLIB_CFLAGS=-Izlib ZLIB_LFLAGS=zlib/libz.a LUA_CFLAGS=-I./windows/ LUA_LFLAGS=-llua5.1 -L./windows/ SDL_CFLAGS=-I./windows/SDL SDL_LFLAGS=-lSDL2 -lSDL2main -lSDL2_ttf -lSDL2_mixer -lSDL2_image -L./windows/SDL CFLAGS += -Wall -mwindows -D_HAVE_ICONV -D_USE_UNPACK -D_USE_BROWSE -D_LOCAL_APPDATA LDFLAGS += -liconv MINGW=i686-w64-mingw32- CC=$(MINGW)gcc AR=$(MINGW)ar rc RANLIB=$(MINGW)ranlib RM=rm EXE=.exe INSTALLD=install -d -m 0755 INSTALLB=install -m 0755 INSTALL=install -m 0644 LN=echo PLATFORM=windows.c iowin32.c RESOURCES=resources.o resources.o: resources.rc $(MINGW)windres -i resources.rc -o resources.o instead-3.5.2+dfsg/cmake/000077500000000000000000000000001467622671600151705ustar00rootroot00000000000000instead-3.5.2+dfsg/cmake/FindGLIB.cmake000066400000000000000000000015311467622671600175100ustar00rootroot00000000000000# - Try to locate glib3 # This module defines: # # GLIB_INCLUDE_DIRS # GLIB_LIBRARIES # GLIB_FOUND # GLIB_DEFINITIONS # FIND_PACKAGE(PkgConfig) PKG_CHECK_MODULES(PC_GLIB REQUIRED glib-2.0) SET(GLIB_INCLUDE_DIRS ${PC_GLIB_INCLUDE_DIRS}) FOREACH(LIB ${PC_GLIB_LIBRARIES}) FIND_LIBRARY(FOUND${LIB} HINTS ${PC_GLIB_LIBRARY_DIRS} NAMES ${LIB}) LIST(APPEND GLIB_LIBRARIES ${FOUND${LIB}}) ENDFOREACH(LIB) IF(GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES) SET(GLIB_FOUND TRUE) ENDIF(GLIB_INCLUDE_DIRS AND GLIB_LIBRARIES) IF(GLIB_FOUND) IF(NOT GLIB_FIND_QUIETLY) MESSAGE(STATUS "Found GLIB: -I${GLIB_INCLUDE_DIRS}, ${GLIB_LIBRARIES}") ENDIF(NOT GLIB_FIND_QUIETLY) ELSE(GLIB_FOUND) IF(GLIB_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find GLIB") ENDIF(GLIB_FIND_REQUIRED) ENDIF(GLIB_FOUND) MARK_AS_ADVANCED(GLIB_INCLUDE_DIRS GLIB_LIBRARIES GLIB_FOUND) instead-3.5.2+dfsg/cmake/FindGTK3.cmake000066400000000000000000000015301467622671600175020ustar00rootroot00000000000000# - Try to locate GTK3 # This module defines: # # GTK3_INCLUDE_DIRS # GTK3_LIBRARIES # GTK3_FOUND # GTK3_DEFINITIONS # FIND_PACKAGE(PkgConfig) PKG_CHECK_MODULES(PC_GTK3 REQUIRED gtk+-3.0) SET(GTK3_INCLUDE_DIRS ${PC_GTK3_INCLUDE_DIRS}) FOREACH(LIB ${PC_GTK3_LIBRARIES}) FIND_LIBRARY(FOUND${LIB} HINTS ${PC_GTK3_LIBRARY_DIRS} NAMES ${LIB}) LIST(APPEND GTK3_LIBRARIES ${FOUND${LIB}}) ENDFOREACH(LIB) IF(GTK3_INCLUDE_DIRS AND GTK3_LIBRARIES) SET(GTK3_FOUND TRUE) ENDIF(GTK3_INCLUDE_DIRS AND GTK3_LIBRARIES) IF(GTK3_FOUND) IF(NOT GTK3_FIND_QUIETLY) MESSAGE(STATUS "Found GTK3: -I${GTK3_INCLUDE_DIRS}, ${GTK3_LIBRARIES}") ENDIF(NOT GTK3_FIND_QUIETLY) ELSE(GTK3_FOUND) IF(GTK3_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find GTK3") ENDIF(GTK3_FIND_REQUIRED) ENDIF(GTK3_FOUND) MARK_AS_ADVANCED(GTK3_INCLUDE_DIRS GTK3_LIBRARIES GTK3_FOUND) instead-3.5.2+dfsg/cmake/FindHarfBuzz.cmake000066400000000000000000000013471467622671600205330ustar00rootroot00000000000000# - Try to locate HarfBuzz # This module defines: # # HARFBUZZ_INCLUDE_DIR # HARFBUZZ_LIBRARY # HARFBUZZ_FOUND # FIND_PATH(HARFBUZZ_INCLUDE_DIR NAMES hb.h PATH_SUFFIXES harfbuzz) FIND_LIBRARY(HARFBUZZ_LIBRARY NAMES harfbuzz) IF(HARFBUZZ_INCLUDE_DIR AND HARFBUZZ_LIBRARY) SET(HARFBUZZ_FOUND TRUE) ENDIF(HARFBUZZ_INCLUDE_DIR AND HARFBUZZ_LIBRARY) IF(HARFBUZZ_FOUND) IF(NOT HarfBuzz_FIND_QUIETLY) MESSAGE(STATUS "Found HarfBuzz: -I${HARFBUZZ_INCLUDE_DIR}, ${HARFBUZZ_LIBRARY}") ENDIF(NOT HarfBuzz_FIND_QUIETLY) ELSE(HARFBUZZ_FOUND) IF(HarfBuzz_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find HarfBuzz") ENDIF(HarfBuzz_FIND_REQUIRED) ENDIF(HARFBUZZ_FOUND) MARK_AS_ADVANCED(HARFBUZZ_INCLUDE_DIR HARFBUZZ_LIBRARY HARFBUZZ_FOUND) instead-3.5.2+dfsg/cmake/FindIconv.cmake000066400000000000000000000026001467622671600200470ustar00rootroot00000000000000# - Locate Iconv # This module defines: # # ICONV_INCLUDE_DIR # ICONV_LIBRARY # ICONV_FOUND # # Look for header file FIND_PATH(ICONV_INCLUDE_DIR NAMES iconv.h) # Check if library is needed IF(ICONV_INCLUDE_DIR) SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) TRY_COMPILE(ICONV_LIBRARY_NOT_NEEDED ${CMAKE_BINARY_DIR} ${CMAKE_MODULE_PATH}/iconv_test.c CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${ICONV_INCLUDE_DIR}" ) IF(NOT ICONV_LIBRARY_NOT_NEEDED) # Locate library FIND_LIBRARY(ICONV_LIBRARY NAMES iconv libiconv) IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARY) SET(ICONV_FOUND TRUE) ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARY) ELSE(NOT ICONV_LIBRARY_NOT_NEEDED) # Library not needed SET(ICONV_LIBRARY) IF(ICONV_INCLUDE_DIR) SET(ICONV_FOUND TRUE) ENDIF(ICONV_INCLUDE_DIR) ENDIF(NOT ICONV_LIBRARY_NOT_NEEDED) ENDIF(ICONV_INCLUDE_DIR) # Show status IF(ICONV_FOUND) IF(NOT Iconv_FIND_QUIETLY) IF(ICONV_LIBRARY_NOT_NEEDED) MESSAGE(STATUS "Found Iconv: -I${ICONV_INCLUDE_DIR}, library not needed") ELSE(ICONV_LIBRARY_NOT_NEEDED) MESSAGE(STATUS "Found Iconv: -I${ICONV_INCLUDE_DIR}, ${ICONV_LIBRARY}") ENDIF(ICONV_LIBRARY_NOT_NEEDED) ENDIF(NOT Iconv_FIND_QUIETLY) ELSE(ICONV_FOUND) IF(Iconv_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find ICONV") ENDIF(Iconv_FIND_REQUIRED) ENDIF(ICONV_FOUND) MARK_AS_ADVANCED(ICONV_INCLUDE_DIR ICONV_LIBRARY ICONV_FOUND) instead-3.5.2+dfsg/cmake/FindLuaJIT.cmake000066400000000000000000000034661467622671600200740ustar00rootroot00000000000000# Locate LuaJIT library # This module defines # LUAJIT_FOUND, if false, do not try to link to Lua # LUA_LIBRARIES # LUA_INCLUDE_DIR, where to find lua.h # LUAJIT_VERSION_STRING, the version of Lua found (since CMake 2.8.8) ## Copied from default CMake FindLua51.cmake find_path(LUA_INCLUDE_DIR luajit.h HINTS ENV LUA_DIR PATH_SUFFIXES include/luajit-2.0 include/luajit-2.1 include PATHS ~/Library/Frameworks /Library/Frameworks /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /opt ) find_library(LUA_LIBRARY NAMES luajit-5.1 HINTS ENV LUA_DIR PATH_SUFFIXES lib PATHS ~/Library/Frameworks /Library/Frameworks /sw /opt/local /opt/csw /opt ) if(LUA_LIBRARY) # include the math library for Unix if(UNIX AND NOT APPLE) find_library(LUA_MATH_LIBRARY m) set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") # For Windows and Mac, don't need to explicitly include the math library else() set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") endif() endif() if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h") file(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" luajit_version_str REGEX "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT .+\"") string(REGEX REPLACE "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUAJIT_VERSION_STRING "${luajit_version_str}") unset(luajit_version_str) endif() include(FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if # all listed variables are TRUE FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR VERSION_VAR LUAJIT_VERSION_STRING) mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY) instead-3.5.2+dfsg/cmake/FindSDL2.cmake000066400000000000000000000011741467622671600175020ustar00rootroot00000000000000# - Try to locate SDL2 # This module defines: # # SDL2_INCLUDE_DIR # SDL2_LIBRARY # SDL2_FOUND # FIND_PATH(SDL2_INCLUDE_DIR NAMES SDL.h PATH_SUFFIXES SDL2) FIND_LIBRARY(SDL2_LIBRARY NAMES SDL2) IF(SDL2_INCLUDE_DIR AND SDL2_LIBRARY) SET(SDL2_FOUND TRUE) ENDIF(SDL2_INCLUDE_DIR AND SDL2_LIBRARY) IF(SDL2_FOUND) IF(NOT SDL2_FIND_QUIETLY) MESSAGE(STATUS "Found SDL2: -I${SDL2_INCLUDE_DIR}, ${SDL2_LIBRARY}") ENDIF(NOT SDL2_FIND_QUIETLY) ELSE(SDL2_FOUND) IF(SDL2_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find SDL2") ENDIF(SDL2_FIND_REQUIRED) ENDIF(SDL2_FOUND) MARK_AS_ADVANCED(SDL2_INCLUDE_DIR SDL2_LIBRARY SDL2_FOUND) instead-3.5.2+dfsg/cmake/FindSDL2_image.cmake000066400000000000000000000014141467622671600206410ustar00rootroot00000000000000# - Try to locate SDL2_image # This module defines: # # SDL2IMAGE_INCLUDE_DIR # SDL2IMAGE_LIBRARY # SDL2IMAGE_FOUND # FIND_PATH(SDL2IMAGE_INCLUDE_DIR NAMES SDL_image.h PATH_SUFFIXES SDL2) FIND_LIBRARY(SDL2IMAGE_LIBRARY NAMES SDL2_image) IF(SDL2IMAGE_INCLUDE_DIR AND SDL2IMAGE_LIBRARY) SET(SDL2IMAGE_FOUND TRUE) ENDIF(SDL2IMAGE_INCLUDE_DIR AND SDL2IMAGE_LIBRARY) IF(SDL2IMAGE_FOUND) IF(NOT SDL2_image_FIND_QUIETLY) MESSAGE(STATUS "Found SDL2_image: -I${SDL2IMAGE_INCLUDE_DIR}, ${SDL2IMAGE_LIBRARY}") ENDIF(NOT SDL2_image_FIND_QUIETLY) ELSE(SDL2IMAGE_FOUND) IF(SDL2_image_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find SDL2_image") ENDIF(SDL2_image_FIND_REQUIRED) ENDIF(SDL2IMAGE_FOUND) MARK_AS_ADVANCED(SDL2IMAGE_INCLUDE_DIR SDL2IMAGE_LIBRARY SDL2IMAGE_FOUND) instead-3.5.2+dfsg/cmake/FindSDL2_mixer.cmake000066400000000000000000000014141467622671600207030ustar00rootroot00000000000000# - Try to locate SDL2_mixer # This module defines: # # SDL2MIXER_INCLUDE_DIR # SDL2MIXER_LIBRARY # SDL2MIXER_FOUND # FIND_PATH(SDL2MIXER_INCLUDE_DIR NAMES SDL_mixer.h PATH_SUFFIXES SDL2) FIND_LIBRARY(SDL2MIXER_LIBRARY NAMES SDL2_mixer) IF(SDL2MIXER_INCLUDE_DIR AND SDL2MIXER_LIBRARY) SET(SDL2MIXER_FOUND TRUE) ENDIF(SDL2MIXER_INCLUDE_DIR AND SDL2MIXER_LIBRARY) IF(SDL2MIXER_FOUND) IF(NOT SDL2_mixer_FIND_QUIETLY) MESSAGE(STATUS "Found SDL2_mixer: -I${SDL2MIXER_INCLUDE_DIR}, ${SDL2MIXER_LIBRARY}") ENDIF(NOT SDL2_mixer_FIND_QUIETLY) ELSE(SDL2MIXER_FOUND) IF(SDL2_mixer_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find SDL2_mixer") ENDIF(SDL2_mixer_FIND_REQUIRED) ENDIF(SDL2MIXER_FOUND) MARK_AS_ADVANCED(SDL2MIXER_INCLUDE_DIR SDL2MIXER_LIBRARY SDL2MIXER_FOUND) instead-3.5.2+dfsg/cmake/FindSDL2_ttf.cmake000066400000000000000000000013261467622671600203560ustar00rootroot00000000000000# - Try to locate SDL2_ttf # This module defines: # # SDL2TTF_INCLUDE_DIR # SDL2TTF_LIBRARY # SDL2TTF_FOUND # FIND_PATH(SDL2TTF_INCLUDE_DIR NAMES SDL_ttf.h PATH_SUFFIXES SDL2) FIND_LIBRARY(SDL2TTF_LIBRARY NAMES SDL2_ttf) IF(SDL2TTF_INCLUDE_DIR AND SDL2TTF_LIBRARY) SET(SDL2TTF_FOUND TRUE) ENDIF(SDL2TTF_INCLUDE_DIR AND SDL2TTF_LIBRARY) IF(SDL2TTF_FOUND) IF(NOT SDL2_ttf_FIND_QUIETLY) MESSAGE(STATUS "Found SDL2_ttf: -I${SDL2TTF_INCLUDE_DIR}, ${SDL2TTF_LIBRARY}") ENDIF(NOT SDL2_ttf_FIND_QUIETLY) ELSE(SDL2TTF_FOUND) IF(SDL2_ttf_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find SDL2_ttf") ENDIF(SDL2_ttf_FIND_REQUIRED) ENDIF(SDL2TTF_FOUND) MARK_AS_ADVANCED(SDL2TTF_INCLUDE_DIR SDL2TTF_LIBRARY SDL2TTF_FOUND) instead-3.5.2+dfsg/cmake/InstallSymlink.cmake000066400000000000000000000010411467622671600211430ustar00rootroot00000000000000MACRO(INSTALL_SYMLINK linktarget linkname destination) IF(UNIX) IF(IS_ABSOLUTE ${destination}) SET(FULL_DESTINATION "\$ENV{DESTDIR}${destination}/${linkname}") ELSE(IS_ABSOLUTE ${destination}) SET(FULL_DESTINATION "\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${destination}/${linkname}") ENDIF(IS_ABSOLUTE ${destination}) INSTALL(CODE "MESSAGE(STATUS \"Symlink: ${FULL_DESTINATION} -> ${linktarget}\") EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E create_symlink ${linktarget} ${FULL_DESTINATION})") ENDIF() ENDMACRO() instead-3.5.2+dfsg/cmake/iconv_test.c000066400000000000000000000001031467622671600175030ustar00rootroot00000000000000#include int main() { iconv_open("", ""); return 0; } instead-3.5.2+dfsg/config.make000066400000000000000000000000401467622671600162060ustar00rootroot00000000000000# you can define own flags here instead-3.5.2+dfsg/configure-mingw32.sh000077500000000000000000000003371467622671600177170ustar00rootroot00000000000000#!/bin/sh rm -f config.make rm -f Rules.make ln -sf Rules.mingw Rules.make rm -f sdl-instead ln -sf src/sdl-instead sdl-instead echo "Ok. We are ready to build. Use this command:" echo " \$ make -f Makefile.mingw setup" instead-3.5.2+dfsg/configure.sh000077500000000000000000000147321467622671600164370ustar00rootroot00000000000000#!/bin/sh echo -n "Checking pkg-config..." if ! pkg-config --version >/dev/null 2>&1; then echo "error: no pkg-config in \$PATH." exit 1 fi echo "ok" echo -n "Checking pkg-config --cflags zlib..." if ! pkg-config --cflags zlib >/dev/null 2>&1; then if [ -f /usr/include/zlib.h ]; then echo "not found, but /usr/include/zlib.h exists..." zlib_cflags="x" zlib_libs= else echo "internal" zlib_cflags= zlib_libs= fi else echo "system" zlib_cflags="pkg-config --cflags zlib" zlib_libs="pkg-config --libs zlib" fi echo -n "Checking pkg-config --cflags gtk+-3.0..." if ! pkg-config --cflags gtk+-3.0 >/dev/null 2>&1; then echo "no" echo -n "Checking pkg-config --cflags gtk+-2.0..." if ! pkg-config --cflags gtk+-2.0 >/dev/null 2>&1; then echo "no open file dialog" gtk_cflags= gtk_libs= else echo "yes" gtk_cflags="pkg-config --cflags gtk+-2.0" gtk_libs="pkg-config --libs gtk+-2.0" fi else echo "yes" gtk_cflags="pkg-config --cflags gtk+-3.0" gtk_libs="pkg-config --libs gtk+-3.0" fi echo -n "Checking pkg-config --cflags lua[jit|5.1|5.2|51|52]..." if [ "x$LUA" = "x" ]; then lua_ver="luajit lua5.1 lua5.2 lua lua-5.1 lua-5.2 lua51 lua52" else lua_ver=$LUA fi for v in $lua_ver; do if pkg-config --cflags "$v" >/dev/null 2>&1; then echo "$v" lua_cflags="pkg-config --cflags $v" lua_libs="pkg-config --libs $v" break fi done if test "x$lua_libs" = "x"; then echo "failed: no package lua/lua5.1/lua5.2/lua-5.1/lua-5.2/lua51/lua52" echo "Please install lua development package." exit 1 fi echo -n "Checking sdl2-config..." if ! sdl2-config --version >/dev/null 2>&1; then echo "error: no sdl2-config in \$PATH." echo "Please install sdl2, sdl2_ttf, sdl2_mixer and sdl2_image development packages." exit 1 else echo "ok" sdl_config="sdl2-config" sdl_libs="-lSDL2_ttf -lSDL2_mixer -lSDL2_image -lm" fi echo -n "Checking sdl-config --cflags..." if ! $sdl_config --cflags >/dev/null 2>&1; then echo "failed." exit 1 fi echo "ok" ops="$CPPFLAGS $CFLAGS $LDFLAGS" ops=$ops" "`$lua_cflags` ops=$ops" "`$lua_libs` echo -n "Looking for compiler..." if ! $CC --version >/dev/null 2>&1; then if ! cc --version >/dev/null 2>&1; then if ! gcc --version >/dev/null 2>&1; then echo "cc, gcc, \$(CC) are not valid compilers... Please export CC for valid one..."; exit 1; else cc="gcc"; fi else cc="cc" fi else cc=$CC fi cat << EOF >/tmp/sdl-test.c #include #include #include #include #include int main(int argc, char **argv) { return 0; } EOF echo $cc echo -n "Checking test build...(" echo -n $cc /tmp/sdl-test.c $ops `$sdl_config --cflags` `$sdl_config --libs` $sdl_libs -o /tmp/sdl-test ")..." if ! $cc /tmp/sdl-test.c $ops `$sdl_config --cflags` `$sdl_config --libs` $sdl_libs -o /tmp/sdl-test; then echo "failed". echo "Please sure if these development packages are installed: sdl, sdl_ttf, sdl_mixer, sdl_image." rm -f /tmp/sdl-test.c /tmp/sdl-test exit 1 fi echo "ok" rm -f /tmp/sdl-test.c /tmp/sdl-test cat << EOF >/tmp/iconv-test.c #include int main(int argc, char **argv) { iconv_open("",""); } EOF echo $cc echo -n "Checking iconv...(" echo -n "$cc /tmp/iconv-test.c -o iconv-test)..." if $cc /tmp/iconv-test.c -o /tmp/iconv-test >/dev/null 2>&1; then CFLAGS="$CFLAGS -D_HAVE_ICONV -DLIBICONV_PLUG" # force FreeBSD to use iconv.h from base echo "ok" elif $cc /tmp/iconv-test.c -liconv -o /tmp/iconv-test >/dev/null 2>&1; then CFLAGS="$CFLAGS -D_HAVE_ICONV" LDFLAGS="$LDFLAGS -liconv" echo "ok, with -liconv" elif $cc /tmp/iconv-test.c -I/usr/local/include -L/usr/local/lib -liconv -o /tmp/iconv-test >/dev/null 2>&1; then CFLAGS="$CFLAGS -I/usr/local/include -D_HAVE_ICONV" LDFLAGS="$LDFLAGS -L/usr/local/lib -liconv" echo "ok, with -liconv and -L/usr/local/lib" else echo -n "failed. Build without iconv.". fi rm -f /tmp/iconv-test.c /tmp/iconv-test if ! make clean >/dev/null 2>&1; then echo " * Warning!!! Can not do make clean..." fi echo -n "Generating config.make..." echo "# autamatically generated by configure.sh" >config.make if [ ! -z "$CFLAGS" ]; then echo "EXTRA_CFLAGS+=$CFLAGS" >> config.make fi if [ ! -z "$LDFLAGS" ]; then echo "EXTRA_LDFLAGS+=$LDFLAGS" >> config.make fi if [ ! -z "$gtk_cflags" ]; then echo "EXTRA_CFLAGS+=-D_USE_GTK -D_USE_BROWSE" >> config.make echo "EXTRA_CFLAGS+=\$(shell $gtk_cflags)" >> config.make echo "EXTRA_LDFLAGS+=\$(shell $gtk_libs)" >> config.make fi if [ -z "$zlib_cflags" ]; then echo "SUBDIRS=src/zlib" >> config.make echo "ZLIB_CFLAGS=-Izlib" >> config.make echo "ZLIB_LFLAGS=zlib/libz.a" >> config.make elif [ "$zlib_cflags" = "x" ]; then echo "ZLIB_CFLAGS=" >> config.make echo "ZLIB_LFLAGS=-lz" >> config.make else echo "ZLIB_CFLAGS=\$(shell $zlib_cflags)" >> config.make echo "ZLIB_LFLAGS=\$(shell $zlib_libs)" >> config.make fi echo "LUA_CFLAGS=\$(shell $lua_cflags)" >> config.make echo "LUA_LFLAGS=\$(shell $lua_libs)" >> config.make echo "SDL_CFLAGS=\$(shell $sdl_config --cflags)" >> config.make echo "SDL_LFLAGS=\$(shell $sdl_config --libs) $sdl_libs" >> config.make echo "ok" if [ "x$PREFIX" = "x" ]; then echo -n "Choose installation mode. Standalone(1) or system(2) [1]: " read ans else ans="2" fi if [ "x$ans" = "x1" -o "x$ans" = "x" ]; then echo " * Standalone version" rm -f Rules.make ln -sf Rules.make.standalone Rules.make rm -f sdl-instead ln -sf src/sdl-instead sdl-instead echo "Ok. We are ready to build. Use these commands:" echo " \$ make" echo " \$ ./sdl-instead" elif [ "x$ans" = "x2" ]; then if [ "x$PREFIX" = "x" ]; then echo -n "Enter prefix path [/usr/local]: " read ans else ans="$PREFIX" fi if [ "x$ans" = "x" ]; then prefix="/usr/local" else prefix="$ans" fi rm -f Rules.make ln -s Rules.make.system Rules.make echo " * System version with prefix: $prefix" echo "PREFIX=$prefix" >> config.make echo "BIN=\$(PREFIX)/bin/" >> config.make echo "DATAPATH=\$(PREFIX)/share/instead" >> config.make echo "STEADPATH=\$(DATAPATH)/stead" >> config.make echo "THEMESPATH=\$(DATAPATH)/themes" >> config.make echo "GAMESPATH=\$(DATAPATH)/games" >> config.make echo "ICONPATH=\$(PREFIX)/share/pixmaps" >> config.make echo "DOCPATH=\$(PREFIX)/share/doc/instead" >> config.make echo "LANGPATH=\$(DATAPATH)/lang" >> config.make echo "MANPATH=\$(PREFIX)/share/man/man6" >> config.make echo "Ok. We are ready to build and install. Use these commands:" echo " \$ make" echo " \$ sudo make install" echo " \$ sdl-instead" else echo "Huh!!! Wrong answer." exit 1 fi echo " Enjoy..." instead-3.5.2+dfsg/contrib/000077500000000000000000000000001467622671600155505ustar00rootroot00000000000000instead-3.5.2+dfsg/contrib/instead-em-build.sh000077500000000000000000000201331467622671600212310ustar00rootroot00000000000000#!/usr/bin/env bash # build INSTEAD with emscripten set -e # export WORKSPACE="/home/peter/Devel/emsdk/env" if [ ! -f ./emsdk_env.sh ]; then echo "Run this script in emsdk directory" exit 1 fi if [ -z "$WORKSPACE" ]; then echo "Define WORKSPACE path in $0" exit 1 fi if [ ! -d "$WORKSPACE" ]; then echo "Please, create build directory $WORKSPACE" exit 1 fi . ./emsdk_env.sh # some general flags export PATH="$WORKSPACE/bin:$PATH" export CFLAGS="-g0 -O2" export CXXFLAGS="$CFLAGS" export EM_CFLAGS="-Wno-warn-absolute-paths" export EMCC_CFLAGS="$EM_CFLAGS" export PKG_CONFIG_PATH="$WORKSPACE/lib/pkgconfig" export MAKEFLAGS="-j2" # flags to fake emconfigure and emmake export CC="emcc" export CXX="em++" export LD="$CC" export LDSHARED="$LD" export RANLIB="emranlib" export AR="emar" export CC_BUILD=cc deps() { # Lua cd $WORKSPACE if ! test -r .stamp_lua; then rm -rf lua-5.1.5 [ -f lua-5.1.5.tar.gz ] || wget -nv 'https://www.lua.org/ftp/lua-5.1.5.tar.gz' || wget -nv 'https://www.tecgraf.puc-rio.br/lua/mirror/ftp/lua-5.1.5.tar.gz' tar xf lua-5.1.5.tar.gz cd lua-5.1.5 cat src/luaconf.h | sed -e 's/#define LUA_USE_POPEN//g' -e 's/#define LUA_USE_ULONGJMP//g'>src/luaconf.h.new mv src/luaconf.h.new src/luaconf.h emmake make posix CC=emcc emmake make install INSTALL_TOP=$WORKSPACE touch ../.stamp_lua fi # libiconv cd $WORKSPACE if ! test -r .stamp_iconv; then rm -rf libiconv-1.15 [ -f libiconv-1.15.tar.gz ] || wget -nv 'https://ftp.gnu.org/gnu/libiconv/libiconv-1.15.tar.gz' tar xf libiconv-1.15.tar.gz cd libiconv-1.15 emconfigure ./configure --prefix=$WORKSPACE emmake make install touch ../.stamp_iconv fi # zlib cd $WORKSPACE if ! test -r .stamp_zlib; then rm -rf zlib-1.3.1/ [ -f zlib-1.3.1.tar.gz ] || wget -nv 'http://zlib.net/zlib-1.3.1.tar.gz' tar xf zlib-1.3.1.tar.gz cd zlib-1.3.1 emconfigure ./configure --prefix=$WORKSPACE emmake make install touch ../.stamp_zlib fi # libmikmod cd $WORKSPACE if ! test -r .stamp_libmikmod; then rm -rf libmikmod-3.1.12/ [ -f SDL2_mixer-2.0.1.tar.gz ] || wget -nv https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.tar.gz tar xf SDL2_mixer-2.0.1.tar.gz mv SDL2_mixer-2.0.1/external/libmikmod-3.1.12/ libmikmod-3.1.12/ cd libmikmod-3.1.12/ emconfigure ./configure --prefix=$WORKSPACE --disable-shared --enable-static emmake make install SHELL="${SHELL}" touch ../.stamp_libmikmod fi # freetype2 cd $WORKSPACE if ! test -r .stamp_ft2; then rm -rf freetype-2.8 wget --no-check-certificate https://download.savannah.gnu.org/releases/freetype/freetype-2.8.tar.gz tar -xvf freetype-2.8.tar.gz cd freetype-2.8 ./autogen.sh emconfigure ./configure --build=amd64-unknown-linux --host=asmjs-linux --prefix=$WORKSPACE CPPFLAGS="-I$WORKSPACE/include" LDFLAGS="-L$WORKSPACE/lib" --disable-shared emmake make install touch ../.stamp_ft2 fi # SDL2_ttf cd $WORKSPACE if ! test -r .stamp_sdl2_ttf; then rm -rf SDL2_ttf git clone https://github.com/emscripten-ports/SDL2_ttf.git cd SDL2_ttf git checkout master git pull sed -i -e 's/noinst_PROGRAMS = showfont glfont//' Makefile.am ./autogen.sh emconfigure ./configure --build=amd64-unknown-linux --host=asmjs-unknown-linux --prefix=$WORKSPACE CPPFLAGS="-I$WORKSPACE/include -I$WORKSPACE/include/SDL2 -I$WORKSPACE/include/freetype2" LDFLAGS="-L$WORKSPACE/lib" --disable-sdltest --disable-shared CFLAGS="-sUSE_SDL=2" emmake make install touch ../.stamp_sdl2_ttf fi # SDL2_mixer cd $WORKSPACE if ! test -r .stamp_sdl2_mixer; then rm -rf SDL_mixer-2.0.2 [ -f SDL2_mixer-2.0.2.tar.gz ] || wget -nv https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.2.tar.gz tar xf SDL2_mixer-2.0.2.tar.gz && cd SDL2_mixer-2.0.2 cat configure.in | sed -e 's/AC_CHECK_LIB(\[modplug\], /AC_CHECK_LIB(\[modplug\], \[ModPlug_Load\], /' -e 's/have_libmikmod=no/have_libmikmod=yes/g' > configure.in.new mv -f configure.in.new configure.in ./autogen.sh export have_ogg_lib=yes export have_ogg_h=yes export have_libmikmod=yes emconfigure ./configure --host=asmjs-unknown-emscripten --prefix=$WORKSPACE CPPFLAGS="-I$WORKSPACE/include -I$WORKSPACE/include/SDL2 -s USE_VORBIS=1 -s USE_OGG=1" LDFLAGS="-L$WORKSPACE/lib" --disable-sdltest --disable-shared \ --disable-music-mp3-mad-gpl --enable-music-ogg --disable-music-ogg-shared --enable-music-mod-mikmod --disable-music-mod-mikmod-shared \ --disable-music-midi-fluidsynth --disable-music-midi-fluidsynth-shared \ --disable-music-mp3-smpeg --disable-music-mp3-smpeg-shared CFLAGS="-sUSE_SDL=2" cat Makefile | sed -e 's| \$(objects)/playwave\$(EXE) \$(objects)/playmus\$(EXE)||g' > Makefile.new mv -f Makefile.new Makefile emmake make emmake make install touch ../.stamp_sdl2_mixer fi } deps # INSTEAD echo "INSTEAD" cd $WORKSPACE [ -d instead-em ] || git clone https://github.com/instead-hub/instead.git instead-em cd instead-em git checkout . git pull [ -e Rules.make ] || ln -s Rules.standalone Rules.make cat < config.make EXTRA_CFLAGS+= -DNOMAIN -D_HAVE_ICONV -I../../include SDL_CFLAGS=-I../../include/SDL2 -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 SDL_LFLAGS= LUA_CFLAGS= LUA_LFLAGS= ZLIB_LFLAGS= EOF emmake make clean sed -i -e 's/^EXE=$/EXE=.bc/' Rules.make.standalone LDFLAGS=-r emmake make cd $WORKSPACE [ -d instead-em-js ] || mkdir instead-em-js [ -d instead-em-js/fs ] || mkdir instead-em-js/fs cp -R instead-em/icon instead-em-js/fs/ cp -R instead-em/stead instead-em-js/fs/ cp -R instead-em/themes instead-em-js/fs/ cp -R instead-em/lang instead-em-js/fs/ cp -R instead-em/games instead-em-js/fs/ rm -rf instead-em-js/fs/games # without games find instead-em-js/fs/ \( -name '*.svg' -o -name Makefile -o -name CMakeLists.txt \) -exec rm {} \; cat < post.js var Module; FS.mkdir('/appdata'); FS.mount(IDBFS,{},'/appdata'); Module['postRun'].push(function() { var argv = [] var req if (typeof window === "object") { argv = window.location.search.substr(1).trim().split('&'); if (!argv[0]) argv = []; } var url = argv[0]; if (!url) { FS.syncfs(true, function (error) { if (error) { console.log("Error while syncing: ", error); }; console.log("Running..."); Module.ccall('instead_main', 'number'); }); return; } req = new XMLHttpRequest(); req.open("GET", url, true); req.responseType = "arraybuffer"; console.log("Get: ", url); setTimeout(function() { var spinnerElement = document.getElementById('spinner'); spinnerElement.style.display = 'inline-block'; Module['setStatus']('Downloading data file...'); }, 3); req.onload = function() { var basename = function(path) { parts = path.split( '/' ); return parts[parts.length - 1]; } var data = req.response; console.log("Data loaded..."); FS.syncfs(true, function (error) { if (error) { console.log("Error while syncing: ", error); } url = basename(url); console.log("Writing: ", url); FS.writeFile(url, new Int8Array(data), { encoding: 'binary' }, "w"); console.log("Running..."); var args = stackAlloc(7 * 4); args[6] = 0; [ "instead-em", url, "-standalone", "-window", "-resizable", "-mode" ].forEach(function(item, i) { HEAP32[(args >> 2) + i] = allocateUTF8OnStack(item); }) setTimeout(function() { Module.setStatus(''); document.getElementById('status').style.display = 'none'; }, 3); window.onclick = function(){ window.focus() }; Module.ccall('instead_main', 'number', ["number", "number"], [6, args ]); }); } req.send(null); }); EOF unzip -o -j instead-em/contrib/instead-em.zip -d instead-em-js/ cd instead-em-js ln -f -s ../instead-em/src/sdl-instead.bc sdl-instead.bc ln -f -s ../lib lib emcc -O2 sdl-instead.bc lib/libz.a lib/libiconv.so lib/liblua.a lib/libSDL2_ttf.a lib/libfreetype.a lib/libSDL2_mixer.a lib/libmikmod.a \ -lidbfs.js \ -s EXPORTED_FUNCTIONS="['_instead_main']" \ -s 'SDL2_IMAGE_FORMATS=["png","jpg","gif"]' \ -s 'EXPORTED_RUNTIME_METHODS=["ccall", "Pointer_stringify"]' \ -s 'DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=["$autoResumeAudioContext", "$dynCall"]' \ -s QUANTUM_SIZE=4 \ -s WASM=1 \ -s PRECISE_F32=1 \ -s STACK_SIZE=131072 \ -s USE_OGG=1 -s USE_VORBIS=1 -s USE_SDL=2 -s USE_SDL_IMAGE=2 \ -o instead-em.html -s SAFE_HEAP=0 -s TOTAL_MEMORY=167772160 -s ALLOW_MEMORY_GROWTH=1 \ --post-js post.js \ --preload-file fs@/ echo "Happy hacking" # python2.7 -m SimpleHTTPServer 8000 instead-3.5.2+dfsg/contrib/instead-sailfish-game.spec000066400000000000000000000024671467622671600225730ustar00rootroot00000000000000Summary: Color Lines game Name: instead-ilines Version: 1.1 Release: 1%{?dist} License: GPL URL: http://instead-games.ru Source0: %{name}-%{version}.zip Group: Amusements/Games BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildArch: noarch Requires: instead %description Classic Color Lines game %prep cd %{_builddir} b=`echo %{name} | sed -e 's/instead-//g'` rm -rf %{name} unzip %{name}-%{version}.zip mv "$b" %{name} %setup %build %install rm -rf $RPM_BUILD_ROOT install -d -m 0755 $RPM_BUILD_ROOT/usr/share/instead/games/%{name} cd %{name} tar cf - . | (cd $RPM_BUILD_ROOT/usr/share/instead/games/%{name} && tar xBf -) cat >%{name}.desktop <>config.make </home/nemo/.instead/profile < ; Description of application ; (File Description property value of installer's File) VersionInfoDescription={#AppName} - {#AppDescription} ; Potentially localizable name of application plus its version number AppVerName={#AppName} {#AppVersion} ; Publisher of application (Publisher value in Add/Remove Programs applet) AppPublisher={#AppPublisher} ; Link to help page (Help Link value in Add/Remove Programs applet) AppSupportURL={#AppURL} ; Link to update page (Update Link value in Add/Remove Programs applet) AppUpdatesURL={#AppUpdatesURL} ; Text of comments (Comments value in Add/Remove Programs applet) AppComments={cm:AppComments} ; Default destination directory path in installer's dialog DefaultDirName={pf}\{#AppName} ; Default Start Menu folder name in installer's dialog DefaultGroupName={#AppName} ; Allow user to disable Start Menu folder creation AllowNoIcons=yes ; Minimum version of Windows that application being installed runs on. ; Currently minimum compatible version is undeclared, ; but INSTEAD runs even on very old versions of Windows. ;MinVersion= ; Processor architecture(s) on which installer is allowed to run on. ; Currently installer is allowed to run on all processor architectures ; capable of executing its 32-bit code (including ones it doesn't recognize). ; Normally 32-bit binaries run in user mode will run without issue ; on the x64 and Itanium editions of Windows via the WOW64 emulator. ;ArchitecturesAllowed= ; 64-bit processor architecture(s) on which installer should install ; in 64-bit mode. ; Currently INSTEAD is always installed in 32-bit mode. ;ArchitecturesInstallIn64BitMode= ; Name of resulting installer file OutputBaseFilename={#OutputFileName}-{#AppVersion} ; Directory of resulting installer file OutputDir={#OutputDir} ; Custom program icon to use for Setup/Uninstall SetupIconFile={#SetupIconFile} ; Icon file (executable or .ico file) to display for Uninstall entry ; in Add/Remove Programs applet UninstallDisplayIcon={#ExeFile} ; Tell Windows Explorer to refresh its file associations information ; at the end of installation and uninstallation of the application ChangesAssociations=yes ; Installer will notify other running applications (notably Windows Explorer) ; that they should reload their environment variables from registry ChangesEnvironment=yes ; how installer will show Select Destination Location wizard page. ; If this is set to auto, at installer will look in the registry to see ; if the same application is already installed, and if so, ; it will not show Select Destination Location wizard page. DisableDirPage=auto ; how installer will show Select Start Menu Folder wizard page. ; If this is set to auto, at startup installer will look in registry to see ; if the same application is already installed, and if so, ; it will not show Select Start Menu Folder wizard page. DisableProgramGroupPage=auto ; Installer will use task settings of previous installation as default settings UsePreviousTasks=yes ; Method of compression to use on files, and optionally level of compression Compression=lzma ; Enable solid compression ; (all files to be compressed at once instead of separately) SolidCompression=yes ; User-customizable tasks installer will perform during installation [Tasks] ; Checked checkbox to create desktop icon Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; \ GroupDescription: "{cm:AdditionalIcons}" ; Unchecked checkbox to create Quick Launch icon Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; \ GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked ; Checked checkbox to associate application with .idf file extension Name: "associate"; Description: "{cm:AssocFileExtension,{#AppName},.idf}"; \ GroupDescription: "{cm:OtherTasks}" ; Unchecked checkbox to add application directory to Path Name: "addtopath"; Description: "{cm:AddToPath,{#AppName}}"; \ GroupDescription: "{cm:OtherTasks}"; Flags: unchecked ; Files to install on user's system [Files] #define DirFlags "recursesubdirs createallsubdirs" #define FileFlags "ignoreversion sortfilesbyextension sortfilesbyname" ; Directories: Source: "doc\*"; DestDir: "{app}\doc"; Flags: {#DirFlags} {#FileFlags} Source: "games\*"; DestDir: "{app}\games"; Flags: {#DirFlags} {#FileFlags} Source: "icon\*"; DestDir: "{app}\icon"; Flags: {#DirFlags} {#FileFlags} Source: "lang\*"; DestDir: "{app}\lang"; Flags: {#DirFlags} {#FileFlags} Source: "Microsoft.VC80.CRT\*"; DestDir: "{app}\Microsoft.VC80.CRT"; \ Flags: {#DirFlags} {#FileFlags} Source: "stead\*"; DestDir: "{app}\stead"; Flags: {#DirFlags} {#FileFlags} Source: "themes\*"; DestDir: "{app}\themes"; Flags: {#DirFlags} {#FileFlags} ; Files: Source: "*.dll"; DestDir: "{app}"; Flags: {#FileFlags} Source: "COPYING"; DestDir: "{app}"; Flags: {#FileFlags} Source: "sdl-instead.exe"; DestDir: "{app}"; Flags: {#FileFlags} ; Shortcuts to create in Start Menu and/or other locations [Icons] ; Shortcuts in the Start Menu Name: "{group}\{#AppName}"; Filename: "{#ExeFile}"; WorkingDir: "{app}"; \ Comment: "{cm:AppComments}"; Flags: runmaximized Name: "{group}\{cm:ProgramOnTheWeb,{#AppName}}"; Filename: "{#AppURL}"; \ Flags: runmaximized Name: "{group}\{cm:UninstallProgram,{#AppName}}"; Filename: "{uninstallexe}"; \ WorkingDir: "{app}"; Flags: runmaximized ; Shortcut on desktop Name: "{commondesktop}\{#AppName}"; Filename: "{#ExeFile}"; \ WorkingDir: "{app}"; Comment: "{cm:AppComments}"; Flags: runmaximized; \ Tasks: desktopicon ; Shortcut in Quick Launch toolbar Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#AppName}"; \ Filename: "{#ExeFile}"; WorkingDir: "{app}"; Comment: "{cm:AppComments}"; \ Flags: runmaximized; Tasks: quicklaunchicon ; Languages available for selection in installer [Languages] Name: "en"; MessagesFile: "compiler:Default.isl"; \ LicenseFile: "COPYING" Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"; \ LicenseFile: "COPYING" ; To fully localize installer into other languages, ; need to include Inno Setup message translation file (.isl) and ; to prepare translations of additional messages in [CustomMessages] section ; Custom message values for {cm:...} constants [CustomMessages] ; Text of comments (Comments value in Add/Remove Programs applet) en.AppComments={#AppDescription} ru.AppComments=Интерпретатор тексто-графических приключений. ; Label of Other tasks task group (displayed in application install dialog) en.OtherTasks=Other tasks: ru.OtherTasks=Другие задачи: ; Label of Add to Path task checkbox (displayed in application install dialog) en.AddToPath=Add %1 to the &Path ru.AddToPath=До&бавить %1 в Path ; Text of delete settings dialog (displayed at end of uninstallation) en.DeleteSettings=Would you like to delete settings and saved games? ru.DeleteSettings=Вы хотите удалить настройки и сохранённые игры? ; Text of delete directory from Path dialog (displayed at end of uninstallation) en.DeleteFromPath=Would you like to delete the %1 directory from the Path environment variable?%nThe directory is located at the path%n%2 ru.DeleteFromPath=Вы хотите удалить директорию %1 из переменной среды Path?%nДиректория находится по пути%n%2 ; Registry keys/values to create, modify, or delete on user's system [Registry] ; Association of .idf files with application in common settings for all users. ; These keys are created/recreated during installation ; and deleted during uninstallation. Root: HKLM; Subkey: "SOFTWARE\Classes\.idf"; \ ValueType: string; ValueName: ""; ValueData: "INSTEAD.DATA"; \ Flags: deletekey uninsdeletekey; Tasks: associate Root: HKLM; Subkey: "SOFTWARE\Classes\INSTEAD.DATA"; \ ValueType: string; ValueName: ""; ValueData: "INSTEAD data file"; \ Flags: deletekey uninsdeletekey; Tasks: associate Root: HKLM; Subkey: "SOFTWARE\Classes\INSTEAD.DATA\DefaultIcon"; \ ValueType: string; ValueName: ""; ValueData: "{#ExeFile},0"; \ Tasks: associate Root: HKLM; Subkey: "SOFTWARE\Classes\INSTEAD.DATA\shell\open\command"; \ ValueType: string; ValueName: ""; ValueData: """{#ExeFile}"" ""%1"""; \ Tasks: associate ; Association of .idf files with application in settings for current user. ; These keys are deleted during uninstallation, ; but are not creating during installation. Root: HKCU; Subkey: "SOFTWARE\Classes\.idf"; \ Flags: dontcreatekey uninsdeletekey; Tasks: associate Root: HKCU; Subkey: "SOFTWARE\Classes\idf_auto_file"; \ Flags: dontcreatekey uninsdeletekey; Tasks: associate Root: HKCU; Subkey: "SOFTWARE\Classes\INSTEAD.DATA"; \ Flags: dontcreatekey uninsdeletekey; Tasks: associate Root: HKCU; \ Subkey: "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.idf"; \ Flags: dontcreatekey uninsdeletekey; Tasks: associate ; Operations to execute after application has been successfully installed [Run] ; Checked checkbox to run application in maximized window Filename: "{#ExeFile}"; Description: "{cm:LaunchProgram,{#AppName}}"; \ WorkingDir: "{app}"; Flags: nowait postinstall runmaximized ; Pascal script to customize Setup or Uninstall in many ways [Code] // Function returns True if passed directory exists // in Path environment variable for all users in HKEY_LOCAL_MACHINE, // and False if it doesn't exist function DirExistsInPath(sDir: String): Boolean; var sPath: String; sDirWithoutBS: String; sDirWithBS: String; begin if not RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', sPath) then begin Result := False; exit; end; sDir := AnsiLowercase(sDir); sDirWithoutBS := ';' + RemoveBackslashUnlessRoot(sDir) + ';'; sDirWithBS := ';' + AddBackslash(sDir) + ';'; sPath := ';' + AnsiLowercase(sPath) + ';'; Result := (Pos(sDirWithoutBS, sPath) > 0) or (Pos(sDirWithBS, sPath) > 0); end; // Procedure adds passed directory to Path environment variable // for all users in HKEY_LOCAL_MACHINE procedure AddDirToPath(sDir: String); var sPath: String; iLen: Integer; begin RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', sPath); iLen := Length(sPath); if (iLen > 0) and (Copy(sPath, iLen, 1) <> ';') then sPath := sPath + ';'; sPath := sPath + sDir; RegWriteExpandStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', sPath); end; // Procedure deletes passed directory from Path environment variable // for all users in HKEY_LOCAL_MACHINE procedure DelDirFromPath(sDir: String); var sPath: String; sPathLC: String; sDirLC: String; iPos: Integer; iLen: Integer; begin RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', sPath); sPath := ';' + sPath + ';'; sDir := ';' + sDir + ';'; sPathLC := AnsiLowercase(sPath); sDirLC := AnsiLowercase(sDir); iPos := Pos(sDirLC, sPathLC); if iPos = 0 then exit; iLen := Length(sDir); sDir := Copy(sPath, iPos, iLen); StringChangeEx(sPath, sDir, ';', True); iLen := Length(sPath); sPath := Copy(sPath, 2, iLen - 2); RegWriteExpandStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', sPath); end; // Procedure deletes passed directory from Path environment variable // for all users in HKEY_LOCAL_MACHINE // Smart procedure deletes both directory without trailing backslash and with it procedure DelDirFromPathSmart(sDir: String); var sDirWithoutBS: String; sDirWithBS: String; begin sDirWithoutBS := RemoveBackslashUnlessRoot(sDir); sDirWithBS := AddBackslash(sDir); DelDirFromPath(sDirWithoutBS); DelDirFromPath(sDirWithBS); end; // Event procedure to perform additional pre-install and post-install tasks procedure CurStepChanged(CurStep: TSetupStep); var sApp: String; begin case CurStep of ssPostInstall: // Code to perform post-install tasks begin sApp := ExpandConstant('{app}'); if IsTaskSelected('addtopath') and not DirExistsInPath(sApp) then AddDirToPath(sApp); end; end; end; // Event procedure to perform additional pre-uninstall and post-uninstall tasks procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); var sAppData: String; sApp: String; begin case CurUninstallStep of usPostUninstall: // Code to perform post-uninstall tasks begin sAppData := ExpandConstant('{localappdata}\instead'); if DirExists(sAppData) and (MsgBox(CustomMessage('DeleteSettings'), mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = idYes) then begin // Delete directory and everything inside it DelTree(sAppData, True, True, True); end; sApp := ExpandConstant('{app}'); if DirExistsInPath(sApp) then begin if not DirExists(sApp) or (MsgBox( FmtMessage(CustomMessage('DeleteFromPath'), \ [ExpandConstant('{#AppName}'), sApp]), mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = idYes) then DelDirFromPathSmart(sApp); end; end; end; end; instead-3.5.2+dfsg/contrib/webinst.lua000066400000000000000000000266231467622671600177370ustar00rootroot00000000000000-- -- this is the network game installer -- Usage: instead -lua webinst.lua [] -- You must have installed luasocket module. -- local https = require("ssl.https") local ltn12 = require("ltn12") INSTEAD = instead_exepath() --[[ Copyright (c) 2013 Gavin Kistner 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. Status API Training Shop Blog About Pricing ]]-- local SLAXML = { VERSION = "0.7", _call = { pi = function(target,content) print(string.format("",target,content)) end, comment = function(content) print(string.format("",content)) end, startElement = function(name,nsURI,nsPrefix) io.write("<") if nsPrefix then io.write(nsPrefix,":") end io.write(name) if nsURI then io.write(" (ns='",nsURI,"')") end print(">") end, attribute = function(name,value,nsURI,nsPrefix) io.write(' ') if nsPrefix then io.write(nsPrefix,":") end io.write(name,'=',string.format('%q',value)) if nsURI then io.write(" (ns='",nsURI,"')") end io.write("\n") end, text = function(text) print(string.format(" text: %q",text)) end, closeElement = function(name,nsURI,nsPrefix) print(string.format("",name)) end, } } function SLAXML:parser(callbacks) return { _call=callbacks or self._call, parse=SLAXML.parse } end function SLAXML:parse(xml,options) if not options then options = { stripWhitespace=false } end -- Cache references for maximum speed local find, sub, gsub, char, push, pop, concat = string.find, string.sub, string.gsub, string.char, table.insert, table.remove, table.concat local first, last, match1, match2, match3, pos2, nsURI local unpack = unpack or table.unpack local pos = 1 local state = "text" local textStart = 1 local currentElement={} local currentAttributes={} local currentAttributeCt -- manually track length since the table is re-used local nsStack = {} local anyElement = false local utf8markers = { {0x7FF,192}, {0xFFFF,224}, {0x1FFFFF,240} } local function utf8(decimal) -- convert unicode code point to utf-8 encoded character string if decimal<128 then return char(decimal) end local charbytes = {} for bytes,vals in ipairs(utf8markers) do if decimal<=vals[1] then for b=bytes+1,2,-1 do local mod = decimal%64 decimal = (decimal-mod)/64 charbytes[b] = char(128+mod) end charbytes[1] = char(vals[2]+decimal) return concat(charbytes) end end end local entityMap = { ["lt"]="<", ["gt"]=">", ["amp"]="&", ["quot"]='"', ["apos"]="'" } local entitySwap = function(orig,n,s) return entityMap[s] or n=="#" and utf8(tonumber('0'..s)) or orig end local function unescape(str) return gsub( str, '(&(#?)([%d%a]+);)', entitySwap ) end local function finishText() if first>textStart and self._call.text then local text = sub(xml,textStart,first-1) if options.stripWhitespace then text = gsub(text,'^%s+','') text = gsub(text,'%s+$','') if #text==0 then text=nil end end if text then self._call.text(unescape(text)) end end end local function findPI() first, last, match1, match2 = find( xml, '^<%?([:%a_][:%w_.-]*) ?(.-)%?>', pos ) if first then finishText() if self._call.pi then self._call.pi(match1,match2) end pos = last+1 textStart = pos return true end end local function findComment() first, last, match1 = find( xml, '^', pos ) if first then finishText() if self._call.comment then self._call.comment(match1) end pos = last+1 textStart = pos return true end end local function nsForPrefix(prefix) if prefix=='xml' then return 'http://www.w3.org/XML/1998/namespace' end -- http://www.w3.org/TR/xml-names/#ns-decl for i=#nsStack,1,-1 do if nsStack[i][prefix] then return nsStack[i][prefix] end end error(("Cannot find namespace for prefix %s"):format(prefix)) end local function startElement() anyElement = true first, last, match1 = find( xml, '^<([%a_][%w_.-]*)', pos ) if first then currentElement[2] = nil -- reset the nsURI, since this table is re-used currentElement[3] = nil -- reset the nsPrefix, since this table is re-used finishText() pos = last+1 first,last,match2 = find(xml, '^:([%a_][%w_.-]*)', pos ) if first then currentElement[1] = match2 currentElement[3] = match1 -- Save the prefix for later resolution match1 = match2 pos = last+1 else currentElement[1] = match1 for i=#nsStack,1,-1 do if nsStack[i]['!'] then currentElement[2] = nsStack[i]['!']; break end end end currentAttributeCt = 0 push(nsStack,{}) return true end end local function findAttribute() first, last, match1 = find( xml, '^%s+([:%a_][:%w_.-]*)%s*=%s*', pos ) if first then pos2 = last+1 first, last, match2 = find( xml, '^"([^<"]*)"', pos2 ) -- FIXME: disallow non-entity ampersands if first then pos = last+1 match2 = unescape(match2) else first, last, match2 = find( xml, "^'([^<']*)'", pos2 ) -- FIXME: disallow non-entity ampersands if first then pos = last+1 match2 = unescape(match2) end end end if match1 and match2 then local currentAttribute = {match1,match2} local prefix,name = string.match(match1,'^([^:]+):([^:]+)$') if prefix then if prefix=='xmlns' then nsStack[#nsStack][name] = match2 else currentAttribute[1] = name currentAttribute[4] = prefix end else if match1=='xmlns' then nsStack[#nsStack]['!'] = match2 currentElement[2] = match2 end end currentAttributeCt = currentAttributeCt + 1 currentAttributes[currentAttributeCt] = currentAttribute return true end end local function findCDATA() first, last, match1 = find( xml, '^', pos ) if first then finishText() if self._call.text then self._call.text(match1) end pos = last+1 textStart = pos return true end end local function closeElement() first, last, match1 = find( xml, '^%s*(/?)>', pos ) if first then state = "text" pos = last+1 textStart = pos -- Resolve namespace prefixes AFTER all new/redefined prefixes have been parsed if currentElement[3] then currentElement[2] = nsForPrefix(currentElement[3]) end if self._call.startElement then self._call.startElement(unpack(currentElement)) end if self._call.attribute then for i=1,currentAttributeCt do if currentAttributes[i][4] then currentAttributes[i][3] = nsForPrefix(currentAttributes[i][4]) end self._call.attribute(unpack(currentAttributes[i])) end end if match1=="/" then pop(nsStack) if self._call.closeElement then self._call.closeElement(unpack(currentElement)) end end return true end end local function findElementClose() first, last, match1, match2 = find( xml, '^', pos ) if first then nsURI = nil for i=#nsStack,1,-1 do if nsStack[i]['!'] then nsURI = nsStack[i]['!']; break end end else first, last, match2, match1 = find( xml, '^', pos ) if first then nsURI = nsForPrefix(match2) end end if first then finishText() if self._call.closeElement then self._call.closeElement(match1,nsURI) end pos = last+1 textStart = pos pop(nsStack) return true end end while pos<#xml do if state=="text" then if not (findPI() or findComment() or findCDATA() or findElementClose()) then if startElement() then state = "attributes" else first, last = find( xml, '^[^<]+', pos ) pos = (first and last or pos) + 1 end end elseif state=="attributes" then if not findAttribute() then if not closeElement() then error("Was in an element and couldn't find attributes or the close.") end end end end if not anyElement then error("Parsing did not discover any elements") end if #nsStack > 0 then error("Parsing ended with unclosed elements") end end local games = {} function games_feed(url) local xml = '' https.request { url = url, sink = function(chunk, err) if not chunk then return 1 end xml = xml .. chunk return chunk:len() end } local game_name, game_title, game_size local tag local val = {} parser = SLAXML:parser { startElement = function(name, nsURI,nsPrefix) if name == 'game' then tag = false val = {} else tag = name end end, -- When "" or or "/>" is seen text = function(text) if tag and not val[tag] then val[tag] = text end end, -- text and CDATA nodes comment = function(content) end, -- comments pi = function(target,content) end, -- processing instructions e.g. "" } parser:parse(xml,{stripWhitespace = true}) end function game_lookup(name) local k, v for k,v in ipairs(games) do if v.name == name then return v end end end local function basename(str) local name = string.gsub(str, "(.*/)(.*)", "%2") return name end function game_download(name) local g = game_lookup(name) local url, size = g and g.url, g and g.size if not url then io.stderr:write("Game '"..name.."' not found.\n") return end local fname = instead_gamespath().."/"..basename(url) local fd = io.open(fname, "w") if not fd then return end io.stderr:write("Download: "..tostring(basename(url)).." [ ]") local sz = 0 https.request { url = url, sink = function(chunk, err) if not chunk then return 1 end sz = sz + chunk:len() local pcnt if size then pcnt = math.floor(sz * 100 / size) pcnt = string.format("%3d", pcnt); pcnt = pcnt .. '%' else pcnt = math.floor(sz / 1024 / 1024) pcnt = string.format("%4d", pcnt); end io.stderr:write("\b\b\b\b\b\b"..pcnt.." ]") return fd:write(chunk) end } io.stderr:write("]\n") fd:close() io.stderr:write("Written: "..fname.."\n") return fname end function games_list() local k, v for k, v in ipairs(games) do print(v.title..' ('..v.name..')') end end games_feed("https://instead-games.ru/xml.php") -- games_feed("https://instead-games.ru/xml2.php") local a = { ... } if #a == 0 then games_list() return end local f = game_download(a[1]) if f then os.execute(INSTEAD.." -install "..f.." -quit"); os.remove(f) end instead-3.5.2+dfsg/contrib/winrt.patch000066400000000000000000000264521467622671600177450ustar00rootroot00000000000000diff --git a/src/iowin32.c b/src/iowin32.c index 13a7dd73..56afa364 100644 --- a/src/iowin32.c +++ b/src/iowin32.c @@ -94,8 +94,16 @@ voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + // CreateFile has to be replaced with CreateFile2 because CreateFile can actually do a number of potentially unsafe (read: malware) things + // see: https://social.msdn.microsoft.com/Forums/office/en-US/e44eaf00-5be2-4683-868f-aca54dd658e0/u81not-able-to-create-file-using-universal-app-?forum=wpdevelop if ((filename!=NULL) && (dwDesiredAccess != 0)) + { +#ifndef _WIN_EXT hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#else + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#endif + } return win32_build_iowin(hFile); } @@ -110,7 +118,13 @@ voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); if ((filename!=NULL) && (dwDesiredAccess != 0)) + { +#ifndef _WIN_EXT hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#else + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#endif + } return win32_build_iowin(hFile); } @@ -125,7 +139,13 @@ voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); if ((filename!=NULL) && (dwDesiredAccess != 0)) + { +#ifndef _WIN_EXT hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#else + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#endif + } return win32_build_iowin(hFile); } @@ -140,7 +160,13 @@ voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mo win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); if ((filename!=NULL) && (dwDesiredAccess != 0)) + { +#ifndef _WIN_EXT hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#else + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#endif + } return win32_build_iowin(hFile); } @@ -197,7 +223,15 @@ long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { - DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); + DWORD dwSet; +#ifndef _WIN_EXT + dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); +#else + LARGE_INTEGER outPointer; + LARGE_INTEGER zero; + zero.QuadPart = 0; + dwSet = SetFilePointerEx(hFile, zero, &outPointer, FILE_CURRENT) ? outPointer.u.LowPart : INVALID_SET_FILE_POINTER; +#endif if (dwSet == INVALID_SET_FILE_POINTER) { DWORD dwErr = GetLastError(); @@ -221,7 +255,14 @@ ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) { LARGE_INTEGER li; li.QuadPart = 0; +#ifndef _WIN_EXT li.u.LowPart = SetFilePointer(hFile, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); +#else + LARGE_INTEGER zero; + LARGE_INTEGER outPointer; + zero.QuadPart = 0; + li.u.LowPart = SetFilePointerEx(hFile, zero, &outPointer, FILE_CURRENT) ? outPointer.u.LowPart : INVALID_SET_FILE_POINTER; +#endif if ( (li.LowPart == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) { DWORD dwErr = GetLastError(); @@ -259,7 +300,15 @@ long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,in if (hFile != NULL) { +#ifndef _WIN_EXT DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); +#else + LARGE_INTEGER outPointer; + LARGE_INTEGER loffset; + loffset.QuadPart = 0; + loffset.u.LowPart = offset; + DWORD dwSet = SetFilePointerEx(hFile, loffset, &outPointer, dwMoveMethod) ? outPointer.u.LowPart : INVALID_SET_FILE_POINTER; +#endif if (dwSet == INVALID_SET_FILE_POINTER) { DWORD dwErr = GetLastError(); @@ -297,8 +346,14 @@ long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T off if (hFile) { +#ifndef _WIN_EXT LARGE_INTEGER* li = (LARGE_INTEGER*)&offset; DWORD dwSet = SetFilePointer(hFile, li->u.LowPart, &li->u.HighPart, dwMoveMethod); +#else + LARGE_INTEGER outPointer; + LARGE_INTEGER* li = (LARGE_INTEGER*)&offset; + DWORD dwSet = SetFilePointerEx(hFile, *li, &outPointer, dwMoveMethod) ? outPointer.u.LowPart : INVALID_SET_FILE_POINTER; +#endif if (dwSet == INVALID_SET_FILE_POINTER) { DWORD dwErr = GetLastError(); diff --git a/src/unpack.c b/src/unpack.c index df4600ac..39589b21 100644 --- a/src/unpack.c +++ b/src/unpack.c @@ -65,11 +65,46 @@ tm_unz tmu_date; HANDLE hFile; FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite; +#ifndef _WIN_EXT hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); +#else + hFile = CreateFile2((LPCTSTR)filename, GENERIC_READ | GENERIC_WRITE, 0, OPEN_EXISTING, NULL); +#endif GetFileTime(hFile, &ftCreate, &ftLastAcc, &ftLastWrite); +#ifndef _WIN_EXT DosDateTimeToFileTime((WORD) (dosdate >> 16), (WORD) dosdate, &ftLocal); LocalFileTimeToFileTime(&ftLocal, &ftm); +#else + SYSTEMTIME systime; + /* + OMG, it's so lowlevel, but I'll try :) + wFatDate[in] + The MS - DOS date.The date is a packed value with the following format. + Bits Description + 0 - 4 Day of the month(1-31) + 5 - 8 Month(1 = January, 2 = February, and so on) + 9 - 15 Year offset from 1980 (add 1980 to get actual year) + + wFatTime[in] + The MS - DOS time.The time is a packed value with the following format. + Bits Description + 0 - 4 Second divided by 2 + 5 - 10 Minute(0-59) + 11 - 15 Hour(0-23 on a 24 - hour clock) + */ + WORD wFatDate = (WORD)(dosdate >> 16); + WORD wFatTime = (WORD)dosdate; + systime.wYear = (WORD)((wFatDate >> 8) + 1980); + systime.wMonth = (WORD)(((BYTE)wFatDate) >> 4); + systime.wDayOfWeek = 0; // ignored + systime.wDay = (WORD)(0x000F & wFatDate); + systime.wHour = (WORD)(wFatTime >> 10); + systime.wMinute = (WORD)((wFatTime >> 4) & 0x003F); + systime.wSecond = (WORD)(wFatTime & 0x000F) * 2; + systime.wMilliseconds = 0; + SystemTimeToFileTime(&systime, &ftm); +#endif SetFileTime(hFile, &ftm, &ftLastAcc, &ftm); CloseHandle(hFile); #else @@ -156,10 +191,23 @@ const char *newdir; return 1; } -static int do_extract_currentfile(uf, password) +static __inline char *get_full_path(full_path_buffer, dirname, filename) +char *full_path_buffer; +const char *dirname; +const char *filename; +{ + strcpy(full_path_buffer, dirname); + strcat(full_path_buffer, "/"); + strcat(full_path_buffer, filename); + return full_path_buffer; +} + +static int do_extract_currentfile(uf, password, dirname) unzFile uf; const char *password; +const char *dirname; { + char full_path_buffer[PATH_MAX]; char filename_inzip[256]; char dir_inzip[256]; char *filename_withoutpath; @@ -205,7 +253,7 @@ const char *password; goto out; } fprintf(stderr, "creating directory: %s\n", filename_inzip); - mymkdir(filename_inzip); + mymkdir(get_full_path(full_path_buffer, dirname, filename_inzip)); if (!*zip_game_dirname) strcpy(zip_game_dirname, dir_inzip); } else { @@ -222,16 +270,16 @@ const char *password; } if (skip == 0) { - fout = fopen64(write_filename, "wb"); + fout = fopen64(get_full_path(full_path_buffer, dirname, write_filename), "wb"); /* some zipfile don't contain directory alone before file */ if ((fout == NULL) && (filename_withoutpath != (char *)filename_inzip)) { char c = *(filename_withoutpath - 1); *(filename_withoutpath - 1) = '\0'; - makedir(write_filename); + makedir(get_full_path(full_path_buffer, dirname, write_filename)); *(filename_withoutpath - 1) = c; - fout = fopen64(write_filename, "wb"); + fout = fopen64(get_full_path(full_path_buffer, dirname, write_filename), "wb"); } if (fout == NULL) { @@ -269,7 +317,7 @@ const char *password; fclose(fout); if (err == 0) - change_file_date(write_filename, + change_file_date(get_full_path(full_path_buffer, dirname, write_filename), file_info.dosDate, file_info.tmu_date); } @@ -309,9 +357,10 @@ out: return err; } -static int do_extract(uf, password) +static int do_extract(uf, password, dirname) unzFile uf; const char *password; +const char *dirname; { uLong i; unz_global_info64 gi; @@ -321,7 +370,7 @@ const char *password; fprintf(stderr, "error %d with zipfile in unzGetGlobalInfo \n", err); for (i = 0; i < gi.number_entry; i++) { - if (do_extract_currentfile(uf, password) != UNZ_OK) + if (do_extract_currentfile(uf, password, dirname) != UNZ_OK) return -1; if ((i + 1) < gi.number_entry) { @@ -391,7 +440,7 @@ int unpack(const char *zipfilename, const char *dirname) fprintf(stderr, "Error changing dir to %s, aborting\n", dirname); goto out; } - ret_value = do_extract(uf, NULL); + ret_value = do_extract(uf, NULL, dirname); out: unzClose(uf); #ifdef _WIN32 diff --git a/src/unzip.c b/src/unzip.c index 6116f3b9..411c600c 100644 --- a/src/unzip.c +++ b/src/unzip.c @@ -612,12 +612,18 @@ local unzFile unzOpenInternal (const void *path, us.z_filefunc = *pzlib_filefunc64_32_def; us.is64bitOpenFunction = is64bitOpenFunction; - + void *_path = path; +#ifdef _WIDE_CHARS + wchar_t wpath[_MAX_PATH]; + mbstowcs(wpath, path, _MAX_PATH); + _path = (void*)wpath; +#endif us.filestream = ZOPEN64(us.z_filefunc, - path, + _path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) return NULL; diff --git a/src/winrt.c b/src/winrt.c index d3764322..f3bf9ec8 100644 --- a/src/winrt.c +++ b/src/winrt.c @@ -258,3 +258,45 @@ int debug_init(void) void debug_done() { } + + +BOOL GetFileTime( + HANDLE hFile, + LPFILETIME lpCreationTime, + LPFILETIME lpLastAccessTime, + LPFILETIME lpLastWriteTime +) +{ + // stub + return 1; +} + +BOOL SetFileTime( + HANDLE hFile, + const FILETIME *lpCreationTime, + const FILETIME *lpLastAccessTime, + const FILETIME *lpLastWriteTime +) +{ + // stub + return 1; +} + +// see https://docs.microsoft.com/en-us/cpp/cppcx/crt-functions-not-supported-in-universal-windows-platform-apps +// The concept of a working directory doesn't apply to Windows 8.x Store apps. Use full paths instead. +char *_getcwd( + char *buffer, + int maxlen +) +{ + // stub + return buffer; +} + +int _chdir( + const char *dirname +) +{ + // stub + return 0; +} instead-3.5.2+dfsg/desktop/000077500000000000000000000000001467622671600155615ustar00rootroot00000000000000instead-3.5.2+dfsg/desktop/CMakeLists.txt000066400000000000000000000003661467622671600203260ustar00rootroot00000000000000IF(SYSTEMWIDE) SET(BIN ${CMAKE_INSTALL_PREFIX}/${BINDIR}) # for following CONFIGURE_FILE CONFIGURE_FILE(instead.desktop.in instead.desktop) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/instead.desktop DESTINATION ${DESKTOPDIR}) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/desktop/Makefile000066400000000000000000000006521467622671600172240ustar00rootroot00000000000000include ../Rules.make include ../config.make clean: rm -rf instead.desktop all: instead.desktop instead.desktop: instead.desktop.in cat instead.desktop.in | sed -e "s|@BIN@|$(BIN)|g" > instead.desktop install: $(INSTALLD) $(DESTDIR)$(PREFIX)/share/applications $(INSTALL) instead.desktop $(DESTDIR)$(PREFIX)/share/applications/instead.desktop uninstall: $(RM) $(DESTDIR)$(PREFIX)/share/applications/instead.desktop instead-3.5.2+dfsg/desktop/instead.desktop.in000066400000000000000000000007571467622671600212210ustar00rootroot00000000000000[Desktop Entry] Version=1.0 Type=Application Name=INSTEAD Name[ru]=INSTEAD Name[uk]=INSTEAD Comment=Simple Text Adventures Interpreter Comment[ru]=Интерпретатор простых приключений Comment[uk]=Iнтерпретатор простих пригод Keywords=game;adventure;quest; Keywords[ru]=игра;приключения;квест; Keywords[uk]=гра;пригоди;квест; Exec=@BIN@/sdl-instead Icon=sdl_instead Terminal=false Categories=Game;LogicGame; instead-3.5.2+dfsg/doc/000077500000000000000000000000001467622671600146555ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/CMakeLists.txt000066400000000000000000000017241467622671600174210ustar00rootroot00000000000000SET(DOC_FILES ) SET(GENERATED_DOC_FILES stead3-ru.pdf modules3-ru.pdf stead3-en.pdf instead.txt ) FOREACH(FILE ${GENERATED_DOC_FILES}) IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) SET(DOC_FILES ${DOC_FILES} ${FILE}) ELSE(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) SET(MISSING_FILES ${MISSING_FILES} ${FILE}) ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) ENDFOREACH(FILE ${GENERATED_DOC_FILES}) IF(NOT "${MISSING_FILES}" STREQUAL "") MESSAGE(WARNING "This distribution lacks some documentation files: ${MISSING_FILES}. These may be generated (network access and additional tools required, see doc/makepdfs), or you may use instead source tarball from sourceforge which has these files included") ENDIF(NOT "${MISSING_FILES}" STREQUAL "") IF(SYSTEMWIDE) INSTALL(FILES ${DOC_FILES} DESTINATION ${DOCDIR}) INSTALL(FILES instead.6 DESTINATION ${MANDIR}/man6) ELSEIF(STANDALONE) INSTALL(FILES ${DOC_FILES} DESTINATION ${STANDALONEDIR}/doc) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/doc/Makefile000066400000000000000000000024351467622671600163210ustar00rootroot00000000000000include ../Rules.make include ../config.make all: clean: rm -f *.aux *.log *.out *.toc stead3-manual-ru.tex modules3-manual-ru.tex stead3-manual-en.tex # rm -f *.pdf instead.txt stead3-manual-ru.tex: stead3-ru.md multimarkdown stead3-ru.md -t latex -o stead3-manual-ru.tex stead3-ru.pdf: stead3-ru.tex stead3-manual-ru.tex xelatex stead3-ru.tex xelatex stead3-ru.tex xelatex stead3-ru.tex modules3-manual-ru.tex: modules3-ru.md multimarkdown modules3-ru.md -t latex -o modules3-manual-ru.tex modules3-ru.pdf: modules3-ru.tex modules3-manual-ru.tex xelatex modules3-ru.tex xelatex modules3-ru.tex xelatex modules3-ru.tex stead3-manual-en.tex: stead3-en.md multimarkdown stead3-en.md -t latex -o stead3-manual-en.tex stead3-en.pdf: stead3-en.tex stead3-manual-en.tex xelatex stead3-en.tex xelatex stead3-en.tex xelatex stead3-en.tex pdf: stead3-ru.pdf modules3-ru.pdf stead3-en.pdf rm -f *.aux *.log *.out *.toc stead3-manual-ru.tex modules3-manual-ru.tex stead3-manual-en.tex man: man ./instead.6 | col -b > instead.txt docs: man pdf install: $(INSTALLD) $(DESTDIR)$(DOCPATH) -$(INSTALL) instead.txt *.pdf $(DESTDIR)$(DOCPATH) $(INSTALLD) $(DESTDIR)$(MANPATH) $(INSTALL) *.6 $(DESTDIR)$(MANPATH) uninstall: $(RM) -rf $(DESTDIR)$(DOCPATH) $(RM) $(DESTDIR)$(MANPATH)/instead.* instead-3.5.2+dfsg/doc/embedding-ru.md000066400000000000000000000507671467622671600175600ustar00rootroot00000000000000# Библиотека INSTEAD INSTEAD-кросс-платформенное приложение, которое написано на C. Для удобства встраивания и создания своих вариантов интерпретатора, ядро интерпретатора выделено в отдельную часть. Эту часть, которая находится в каталоге src/instead/ (c и h файлы) и stead/ (lua файлы) можно назвать библиотекой (несмотря на то, что сборка осуществляется просто путём подключения этих файлов к проекту). В данном документе приводится информация об этом коде (далее -- библиотека). # Параметры сборки Единственная обязательная зависимость, это библиотека Lua. Поддерживаются: Lua5.1, Lua5.2, Lua5.3, Lua5.4, luajit. Некоторые определения препроцессора используются для условной компиляции: - \_USE\_SDL - сборка осуществляется вместе с библиотекой sdl; - \_HAVE\_ICONV - сборка с библиотекой iconv (только для совместимости с играми на URQL); - STEAD_PATH - путь по умолчанию к файлам .lua (каталог stead/); - ANDROID - сборка для Android; - \_WIN32 - сборка для Windows; - WINRT - сборка для Windows RT; - SAILFISHOS - сборка для Sailfish OS; - \_\_APPLE\_\_ - сборка для macOS; - IOS - сборка для iOS; - по умолчанию сборка осуществляется для Unix/Linux. Переменные препроцессора обычно задаются в виде параметров компиляции -D, например: -DSTEAD_PATH=\"./stead\" -DANDROID # API Библиотека не поддерживает мультимедиа возможности. Вместо этого, она позволяет загрузить и запустить игру, взаимодействовать с ней путём посылки и приёма текстовых строк (обычно, в UTF-8). А также зарегистрировать расширения функциональности. _Внимание!_ Библиотека не потоконезависима! Возможно создание одного экземпляра интерпретатора для одного процесса! ## Базовое API - int instead_set_debug(int mode); Задать режим отладки (1 или 0). Возвращает старое значение. Режим отладки удобен при разработке игры. Эта функция должна вызываться до instead_init(). - const char *instead_lua_path(const char *path); Позволяет переопределить путь к stead/ (переопределив STEAD_PATH). Если вызвать с параметром NULL вернёт текущий путь к stead/. Вызывать до instead_extension() и instead_init(). - int instead_extension(struct instead_ext *ext); Зарегистрировать расширения. О расширениях будет рассказано в дальнейшем. Должна вызываться до instead_init(). Возвращает 0 в случае успеха и -1 -- в случае ошибки. - int instead_init(const char *path); Открыть игру и подготовить её к запуску. В качестве параметра - путь к каталогу с игрой (в распакованном виде, или в виде idf). Возвращает -1 в случае ошибки, 0 -- в случае успеха. - int instead_load(char **info); Загрузить игру (запустить). Вызывать только после instead_init(). В качестве необязательного (можно передать NULL) параметра, указатель на указатель, в котором будет записан баннер игры. Обычно, это бесполезная информация (её не показывает даже стандартный плеер). Указатель должен быть освобождён вызовом free(). Возвращает -1 в случае ошибки, 0 -- в случае успеха. - char *instead_cmd(char *s, int *rc); Основная функция взаимодействия с игрой: выполнить команду. Вызывать после instead_load(). Команда передаётся в 1-м параметре. Статус возвращается в указатель 2-го параметра (может быть NULL). Возвращает строку, которую нужно освободить free(). Может вернуть NULL в случае ошибки. Статус команды не 0 если возникла какая-то ошибка функционирования игры (например, подаётся некорректная команда). Команды будут рассмотрены далее. - char *instead_file_cmd(char *s, int *rc); Если библиотека собрана с iconv, то каждый вызов instead_cmd транслирует текст в необходимую кодировку и обратно. Однако, при работе с файловой системой это не нужно. Этот вариант функции не занимается конвертированием и может быть использован для команд save и load. Если вы не используете сборку iconv (устаревшая функция), пользуйтесь instead_cmd() для любых команд. - const char *instead_err(void); Движок может сообщать о некоторых ошибках в виде текстовых сообщений. В таком случае, instead_err() возвращает указатель на сообщение (или NULL -- если ошибок не было). Строчку освобождать с помощью free() не нужно. - void instead_err_msg(const char *s); Задать сообщение об ошибке (например, из своего расширения). Если передать в качестве параметра NULL, то статус ошибки будет сброшен. - void instead_done(void); Выгрузить игру. Этой функцией заканчивается работа игры. ## Ввод и вывод игры instead_cmd() используется для выполнения команды, которая представляет собой просто текст. Строго говоря, формат команд и её реакция определяются полностью Lua частью (stead/ файлы). На данный момент библиотека поддерживает игры на stead2 и stead3 API которые имеют общие черты, но также имеют существенные отличия. instead_cmd() вызывает метод iface:cmd(команда) в запущенной Lua машине. И в stead2 и в stead3 команда выглядит так: <команда> [аргумент1,аргумент2,...] Команды: - look - осмотреться; - way - получить список переходов; - inv - получить инвентарь; - go <переход> - переход; - act <объект>[,<аргумент1>,<аргумент2>...] - действие на предмет; - <объект>[,<аргумент1>,<аргумент2>...] - действие на предмет; - use <предмет> - использование предмета инвентаря; - use <предмет1>,<предмет2>[,параметры] - использование предмета на предмет; - save <путь> - сохранить игру; - load <путь> - загрузить игру. _Внимание!_ Загрузка игр stead2 возможна только на "чистую" виртуальную машину Lua. Таким образом, для корректной загрузки нужно переинициализировать игру и первой командой выполнить load <файл сохранения>. В качестве параметров команд используются имена или идентификаторы объектов. Получить идентификаторы можно из текста вывода. Дело в том, что на каждый активный объект в тексте движком вызывается Lua метод iface:xref. Вы можете переопределить его для своих нужд. ``` function iface:xref(str, o, ...) -- TODO -- возвращает текст, который будет внедрён в вывод команды end ``` Параметры метода: строка, объект игрового мира, аргументы... Описание реализации iface:xref выходит за рамки данного руководства, но вы можете ознакомится с реализациями: - стандартная реализация для графического интерпретатора: stead/stead3/ext/gui.lua; - стандартная реализация для графического интерпретатора для stead2: stead/stead2/ext/gui.lua; - примитивная реализация для tiny instead (консольная версия): src/tiny/tiny3.lua. Идея в том, что в iface:xref вы точно знаете с каким игровым объектом вы работаете, а также знаете его числовую метку-идентификатор. Вы можете сформировать текстовый вывод, который опишет вам его в нужном формате, и на стороне проигрывателя вычленить эту информацию. Также, интерпретатор знает, какую команду он выполнял: way, inv или look и, тем самым, знает тип объекта: переход, инвентарь или осмотр сцены. Таким образом, он может выполнить нужную команду. Вы можете ознакомиться с следующими реализациями интерпретаторов: - примитивная реализация в 100 строк: src/tiny; - консольный интерпретатор: https://github.com/instead-hub/instead-cli. _Внимание!_: если в iface:xref передаются аргументы (...), вы должны их сохранить и использовать как часть идентификатора объекта! Обратите внимание на этот момент в стандартной реализации (stead/stead3/ext/gui.lua). Также обратите внимание на приём, который там используется: использование дополнительного словаря. В xref строится специальный словарь идентификаторов (dict), который хранит их вместе с аргументами. Вы можете повторить такой приём в своём плеере, чтобы в выводе всегда присутствовали виртуальные идентификаторы без параметров, но это не обязательно если вы не показываете их игроку. Главное -- сохраняйте идентификатор вместе с аргументами! ## Парсерные игры Для парсерных игр на stead3 существует отдельная команда: - @metaparser "команда" Команда заключается в кавычки. Пример тривиальной реализации парсера: src/tiny/metaparser.c # Расширения В базовом режиме игра выдаёт строки текста. Если интерпретатор должен поддерживать, например, проигрывание звуковых файлов, необходимо писать расширение. Расширение описывается структурой: ``` struct instead_ext { struct list_node list; int (*init)(void); int (*done)(void); int (*err)(void); int (*cmd)(void); }; ``` И регистрируется с помощью instead_extension(). Структура instead_ext содержит указатели на методы: - init() - инициализация расширения; - done() - деинициализация расширения; - cmd() - вызывается после каждой команды; - err() - вызывается во время ошибок (работа игры останавливается). ## init() Здесь происходит инициализация вашего расширения. Часто, в данном методе вызываются следующие функции: - int instead_api_register(const luaL_Reg *api); Регистрация lua функций в пространстве созданной виртуальной машины Lua, если это требуется. - int instead_loadfile(const char *name); Загрузить и выполнить Lua-скрипт в пространстве созданной виртуальной машины Lua. Скрипты-расширения принято хранить в каталогах ext/ (см stead/stead3/ext и sead/stead2/ext). Если вам необходимо повторить некоторые мультимедиа-функции графического интерпретатора, вам необходимо повторить расширения, которые в нём реализованы. Например: ``` static int _restart(lua_State *L) { need_restart = !lua_isboolean(L, 1) || lua_toboolean(L, 1); return 0; } static const luaL_Reg tiny_funcs[] = { { "instead_restart", _restart }, { NULL, NULL } }; static int tiny_init(void) { int rc; char path[1024]; instead_api_register(tiny_funcs); snprintf(path, sizeof(path), "%s/tiny.lua", instead_lua_path(NULL)); rc = instead_loadfile(path); if (rc) return rc; return 0; } static struct instead_ext ext = { .init = tiny_init, }; ... if (instead_extension(&ext)) { fprintf(stderr, "Can't register tiny extension\n"); exit(1); } ``` ## cmd() Обработчик cmd полезен, когда вы хотите делать что-то после такта игры. Например, музыкальный плеер может вызываться каждый такт команды, чтобы определить: появилась ли новая задача для проигрывателя музыки. Для вызова Lua из C кода вы можете воспользоваться функцией: - int instead_function(char *s, struct instead_args *args); Первый параметр: текстовое представление метода на Lua, который может содержать двоеточие или точку (вызов метода Lua). Например: ``` instead_function("instead.get_sound", NULL); ``` Второй параметр задаёт аргументы или NULL. Пример аргументов: ``` struct instead_args args[] = { { .val = "nil", .type = INSTEAD_NIL }, { .val = "-1", .type = INSTEAD_NUM }, { .val = NULL } }; ``` Как видно из примера, аргументы -- это пары: значение - тип. Допустимые типы: - INSTEAD_NIL - nil; - INSTEAD_NUM - целое число; - INSTEAD_STR - строка; - INSTEAD_BOOL - булево ("true" или "false"). В случае ошибки возвращается -1, в случае успеха -- 0. Lua метод может возвратить одно или несколько значений: строку, число, булево. Чтобы получит их используйте функции (все они получают в качестве параметра номер возвращаемого значения от 0): - extern char *instead_retval(int n); -- получить строку (освободить через free()) - int instead_iretval(int n); -- получить целое - int instead_bretval(int n); -- получить булево После того, как вы проанализировали возвращаемые значения, нужно вызвать: - void instead_clear(void); -- сбросить стек Lua _Внимание!_: функцию instead_clear() после вызова instead_function() необходимо вызывать всегда! ## Пример реализации расширения для проигрывания музыки Ниже, для наглядности, приводятся упрощённые фрагменты расширения для проигрывания музыки. Расширение регистрирует функции на Lua в (stead/stead3/ext/sound.lua). Полное расширение см. src/instead_sound.c. Кроме игры музыки оно поддерживает расширенную работу со звуком. ``` static void game_music_player(void) { int loop; char *mus; int cf_out = 0; int cf_in = 0; instead_function("instead.get_music", NULL); mus = instead_retval(0); loop = instead_iretval(1); instead_clear(); instead_function("instead.get_music_fading", NULL); cf_out = instead_iretval(0); cf_in = instead_iretval(1); instead_clear(); // в mus - трек // cf_out,cf_in -- параметры затухания // mus -- путь к файлу // loop -- число проигрываний // TODO реализовать плеер free(mus); } static int sound_init(void) { int rc; char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", instead_stead_path(), "/ext/sound.lua"); rc = instead_loadfile(dirpath(path)); if (rc) return rc; // TODO - инициализация звуковой подсистемы return 0; } static int sound_cmd(void) { game_music_player(); return 0; } static int sound_done(void) { // TODO: деинициализация звуковой подсистемы return 0; } static struct instead_ext ext = { .init = sound_init, .done = sound_done, .cmd = sound_cmd, }; int instead_sound_init(void) { return instead_extension(&ext); } ``` # Lua часть (stead/) Большая часть логики заключена в Lua файлах. Если вы хотите изучить как работает графический интерпретатор, смотрите ext/gui.lua. Функции instead.xxxxx - это те функции, которые вызывает графический интерпретатор с помощью instead_function(). - instead.get_title, instead.get_inv, instead.get_ways, instead.get_picture и др. Вы можете заметить, что такие функции как: instead.get_ways или instead.get_inv являются врапперами над командами way и inv. А instead.get_picture, например, получает картинку сцены. Это пример того, как расширение само устанавливает тот тип интерфейса с интерпретатором, который удобен для конкретной реализации. Всё есть Lua, поэтому вам решать - как именно вы будете взаимодействовать с интерпретатором для реализации конкретных расширений.instead-3.5.2+dfsg/doc/examples/000077500000000000000000000000001467622671600164735ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/examples/stead2/000077500000000000000000000000001467622671600176555ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/examples/stead2/cutscene.lua000066400000000000000000000077571467622671600222110ustar00rootroot00000000000000-- example module require "timer" require "xact" stead.cut_text = '>>>' local function get_token(txt, pos) if not pos then pos = 1 end local s,e; e = pos while true do s, e = txt:find("[\\{]", e); if not s then break end if txt:sub(s, s) == '\\' then e = e + 2 else break end end local nest = 1 local ss, ee ee = e while s do ss, ee = txt:find("[\\{}]", ee + 1); if ss then if txt:sub(ss, ss) == '\\' then ee = ee + 1 elseif txt:sub(ss, ss) == '{' then nest = nest + 1 else nest = nest - 1 end if nest == 0 then return s, ee end else break end end return nil end local function parse_token(txt) local s, e, t t = txt:sub(2, -2) local c = t:gsub("^([a-zA-Z]+)[ \t]*.*$", "%1"); local a = t:gsub("^[^ \t]+[ \t]*(.*)$", "%1"); if a then a = a:gsub("[ \t]+$", "") end return c, a end cutscene = function(v) v.txt = v.dsc if v.left then error ("Do not use left in cutscene.", 2) end v.left = function(s) timer:set(s._timer); s:reset() end; if v.timer then error ("Do not use timer in cutscene.", 2) end v.timer = function(s) if not s._to then if game.timer then return game:timer() end return end s._fading = nil s._state = s._state + 1 timer:stop() s:step() return true end; v.forcedsc = true if not v.pic then v.pic = function(s) return s._pic end; end if not v.fading then v.fading = function(s) return s._fading end end v.reset = function(s) s._state = 1 s._code = 1 s._fading = nil s._txt = nil s._dsc = nil s._pic = nil s._to = nil s._timer_fn = nil end v:reset() if v.entered then error ("Do not use entered in cutscene.", 2) end v.entered = function(self) self:reset() self._timer = timer:get() self:step(); end; v.step = function(self) local s, e, c, a local n = v._state local txt = '' local code = 0 local out = '' if not self._txt then if type(self.txt) == 'table' then local k,v for k,v in ipairs(self.txt) do if type(v) == 'function' then v = v() end txt = txt .. tostring(v) end else txt = stead.call(self, 'txt') end self._txt = txt else txt = self._txt end while n > 0 and txt do if not e then e = 1 end local oe = e s, e = get_token(txt, e) if not s then c = nil out = out..txt:sub(oe) break end local strip = false local para = false c, a = parse_token(txt:sub(s, e)) if c == "pause" or c == "cut" or c == "fading" then n = n - 1 strip = true para = true elseif c == "pic" then if a == '' then a = nil end self._pic = a strip = true elseif c == "code" then code = code + 1 if code >= self._code then local f = stead.eval(a) if not f then error ("Wrong expression in cutscene: "..tostring(a)) end self._code = self._code + 1 f() end strip = true elseif c == "walk" then if a and a ~= "" then return stead.walk(a) end elseif c == "cls" then out = '' strip = true end if strip then out = out..txt:sub(oe, s - 1) elseif c then out = out..txt:sub(oe, e) else out = out..txt:sub(oe) end if para and n == 1 and stead.cut_delim then out = out .. stead.cut_delim end e = e + 1 end if stead.cut_scroll then out = out..iface.anchor() end v._dsc = out if c == 'pause' then if not a or a == "" then a = 1000 end self._to = tonumber(a) timer:set(self._to) elseif c == 'cut' then self._state = self._state + 1 if not a or a == "" then a = stead.cut_text end v._dsc = v._dsc .. "{cut|"..a.."}"; elseif c == "fading" then if not a or a == "" then a = game.gui.fading end self._fading = tonumber(a) self._to = 10 timer:set(self._to) end end v.dsc = function(s) if s._dsc then return s._dsc end end if not v.obj then v.obj = {} end stead.table.insert(v.obj, 1, xact('cut', function() here():step(); return true; end )) return room(v) end instead-3.5.2+dfsg/doc/examples/stead2/dialog/000077500000000000000000000000001467622671600211145ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/examples/stead2/dialog/main.lua000066400000000000000000000256571467622671600225620ustar00rootroot00000000000000-- $Name: Диалог$ instead_version "1.6.3" require "para" require "dash" require "quotes" require "hotkeys" main = dlg { nam = '...'; entered = function(s) p [[У тебя одна минута на то, чтобы объяснить мне, как добраться до хранилища.^ — Что?^ Бац! В глазах сверкнуло и боль такая сильная, что кажется, будто она — единственное, что я сейчас чувствую. Даже сильнее страха.^ — Одна минута, — говорит он и прижимает холодный кружок дула к моему лбу.]]; end; phr = { { 'Что?', [[Бац! Оказывается, может быть ещё больнее, чем в первый раз.^ — Ещё раз скажешь "что", выстрелю.]], [[ pon 'что?' ]] }; { false, tag = 'что?', 'Что?', [[Он стискивает зубы и стреля...]], [[ walk 'theend' ]] }; { 'Но я здесь не работаю...', [[ — Но я здесь не работаю, я вообще не знаю, где тут что!^ — Какого чёрта тогда ты делаешь в кабинке оператора? ]], [[ pjump 'кто ты?' ]] }; { tag = 'про подвал', 'Хранилище в подвале.', [[— Хранилище находится в подвале...^ — Уже лучше. А теперь, как туда добраться?]], [[ pjump 'хранилище' ]] }, { }, { tag = 'кто ты?', }, { 'Я техник.', [[— Я просто техник, мне позвонили и попросили починить компьютер. Они иногда вызывают меня сюда, но я не знаю, где тут сейф, честное слово!^ — Занятно. Тогда почему на твоём бейдже написано "Старший кассир"?]], [[ pjump 'бейдж' ]] }, { 'Я от вас прячусь.', [[ — Я тут от вас прячусь...^ — А, ты один из посетителей?^ — Да.^ — Я вот не видел, как ты сюда пробегал, ты сюда зашёл ещё до того, как я вошёл в здание?^ — Да!^ — А как же ты через турникет прошёл?]], [[ pon('что?'); pjump 'лжец' ]], }, { 'Тоже решил денег взять.', [[— Да я вот решил тоже денег взять. Под шумок, так сказать. Хе-хе.^ — А, вон оно что. Но на тебе форма сотрудника банка. То есть, ты не только лжец, но ещё и вор? Двадцать секунд. Хе-хе.]], [[ poff('что?'); pjump 'лжец' ]], }, { }, { tag = 'бейдж', 'Я его одолжил, чтобы через турникет пройти.', [[— Я его одолжил, чтобы пройти через турникет, я часто так делаю, а то они никак мне собственный не сделают...^ — У кого одолжил?^ Пальцем в толстого очкарика на полу, тут же затрясшего головой.^ — Окей, спасибо, техник, — и спускает куро...]], [[ walk 'theend' ]] }, { }, { tag = 'лжец' }, { alias = 'что?' }, { alias = 'про подвал' }, { }, { tag = 'хранилище', empty = function() pon "нет пути" end, }, { "По лестнице...", [[— Вон за той дверью в подвал ведёт лестница, по ней можно спуститься до главного коридора, из него в архив, а уже через архив к двери хранилища.^ — Ещё что-нибудь, о чём мне как грабителю полезно было бы узнать?]], [[ psub 'лестница' ]] }, { tag = 'на лифте', "На лифте...", [[— В кабинете управляющего есть лифт, спускающийся прямо в хранилище. Только вряд ли вы до него доберётесь.^ — Почему это?]], [[ psub 'лифт' ]] }, { false, tag = "нет пути", "Нет", [[— К сожалению, больше путей нет.^ — Вот же задачка. Монетку бросить что ли... Это всё? Может ещё что-нибудь знаешь?]], [[ pjump "про деньги" ]] }, { }, { tag = 'лестница', empty = function(s) p "^— А другой путь есть?" pret(); end, }, { "О лестинце...", [[— На лестнице сторожит охранник с оружием.^ — Каким оружием?]], [[ psub 'оружие' ]] }, { "О коридоре...", [[— Поперёк коридора идут лазерные лучи.^ — Красные или зелёные?]], [[ psub 'коридор' ]] }, { "Об архиве...", [[— В архиве люди пропадают...^ — Что?!^ — Люди, говорю, в архиве пропадают.^ — Да это я понял! Почему пропадают?^ — Не знаю, но, поговаривают, что нужно быть поосторожнее со шкафами F.^ — Почему?^ — Пропали сотрудники Фриманн, Фрекель, Фаркопс и Фонг. У вас какая фамилия?^ — Фицжеральд.^ — О... ]], [[ if not here():empty 'лестница' then p '^— Дальше.' end]] }, { "О двери в хранилищие...", [[— Толщина двери в хранилище полтора метра.^ — Ого... — И замок «Sargent & Greenleaf».^ — Ой...^ — Пол внутри под напряжением десять тысяч вольт.^ — Ох...^ — А снаружи камеры. ]], [[ if not here():empty 'лестница' then p '^— Понятно. Дальше.' end]] }, {}, { tag = 'коридор', "Красные.", [[— Красные, кажется. А что есть какая-то разница?]], [[ if not here():empty 'лестница' then p '^— Не твоего ума дело, дальше давай.'; pret() end]] }, { "Зелёные.", [[— Зелёные, кажется, а что?^ — Проклятье, у меня дейтеранопия.^ — Зелёный цвет не различаете?^ — Да.^ — Сочувствую.]], [[ if not here():empty 'лестница' then p '^— Спасибо. Дальше.'; pret() end]] }, {}, { tag = 'оружие', "Ружьё какое-то...", [[— Не знаю, я не разбираюсь.]], [[ if not here():empty 'лестница' then p '^— Дальше.'; end pret()]] }, { "Benelli M4...", [[— Benelli M4 Super 90, шестизарядный, с телескопическим прикладом, пистолетной рукояткой, планкой Пикатинни...]], [[ if not here():empty 'лестница' then p '^— Всё, заткнись, давай дальше.'; end pret()]] }, {}, { tag = "лифт", empty = function() p "— А другой путь есть?" pret() end}, { "Управляющий.", [[— В кабинете скорее всего сидит сам управляющий.^ — И чего?^ — Он чемпион города по гарлемскому боксу.^ — Впервые слышу про такой бокс.^ — Основная особенность его в том, что во время боя разрешено использовать кастеты, биты и автоматическое оружие.]], [[ if not here():empty() then p "— Хмм, ну ладно, допустим, я с ним разберусь, что ещё?" end ]], }, { "Собаки.", [[— Собаки.^ — Собаки?^ — Да.^ — Большие?^ — Очень.^ — Много?^ — Четыре.]], [[ if not here():empty() then p "— Ох... Ну допустим, с собаками я как-нибудь управлюсь. Что-то ещё?." end]], }, { "Системы идентификации.", [[— В лифте стоят системы идентификации, которые пропускают только управляющего.^ — Какие системы?]], [[ psub 'идентификация' ]], }, {}, { tag = "идентификация", empty = function() pon "по системам все"; end}, { false, tag = 'по системам все', [[По системам идентификации всё.]], code = [[ if not here():empty('лифт') then p "— Ещё что-нибудь по лифту?" end pret() ]] }, { "Отпечатки.", [[— Сканер отпечатка правой ладони.^ — Это, теоретически, можно обойти. Дальше.]], }, { "Сетчатка глаза.", [[— Для этого у меня есть инструменты и необходимые навыки, — он зловеще ухмыляется. — Дальше.]], }, { "Вес.", [[— Датчик веса.^ — Хм. Сколько весит местный управляющий?^ — 124 килограмма. А вы сколько весите?^ — 61. Мда. Тут даже клонирующая машина бы не помогла. Ладно, дальше.]], }, {}, { tag = "про деньги", "Про деньги.", [[— Знаю про деньги в хранилище.^ — Так, и что с ними?^ — Их там нет.^ — Как нет?!^ — Ну мы переезжаем в другой район города и все деньги и ценности уже перевезли сегодня ночью.^ — Так почему ты сразу не сказал?!^ — Ну про это вы как раз не спрашивали.^ — Проклятье!^^ И с этими словами он выбегает из отделения банка, где его ловит экипаж инкассаторской машины, приехавшей, чтобы как раз перевезти содержимое хранилища в другой район города. Хе-хе.]], [[ walk 'theend' ]], }, {} } } theend = room { nam = 'Конец'; }instead-3.5.2+dfsg/doc/examples/stead2/fonts.lua000066400000000000000000000066361467622671600215240ustar00rootroot00000000000000-- example module require "sprites" require "theme" function font(name, size, scale) if scale == nil then scale = true end if not size then size = false end if not name then name = false end local v = obj { nam = 'styler'; fname = name; size = size; cache = { }; list = { }; scaled = scale; cache_get = function(s, w, color, t) local k = w..color..tostring(t) if s.cache[k].time ~= -1 then s.cache[k].time = stead.time() end return s.cache[k] end; cache_clear = function(self, age) local k, v local new_list = {} if not age then age = 0 end for k,v in ipairs(self.list) do local key = v.word..v.color..tostring(v.t) if v.time ~= -1 and stead.time() - v.time >= age then sprite.free(v.img); self.cache[key] = nil else stead.table.insert(new_list, v) if v.time ~= -1 then self:cache_add(v.word, v.color, v.t, v.img, nil) -- renew time else self:cache_add(v.word, v.color, v.t, v.img, -1) end end end self.list = new_list end; life = function(s) if player_moved() then s:cache_clear(2) end end; txt = function(st, txt, color, t) local s, e; local ss = 1 local res = '' if not color then color = theme.get 'win.col.fg' end if not t then t = 0 end while true do local start = ss while true do local s1, e1 = txt:find("\\", ss) s, e = txt:find("[ \t\n^]+", ss); if not s1 or not s then break end if s1 < s then s, e = s1, e1 ss = s + 2 else break end end ss = start local w if s then s = s - 1 end w = txt:sub(ss, s); local c if w then if s then c = txt:sub(s + 1, e) end w = w:gsub("\\(.)", "%1") w = w:gsub("[ \t\n]+$", ""); end if w and w ~= '' and w ~= '\n' then st:cache_add(w, color, t) res = res .. img(st:cache_get(w, color, t).img); end if not e then break end ss = e + 1 if not c then c = '' end res = res .. c; end return res; end; cache_add = function(s, w, color, t, key, time) local k = w..color..tostring(t) if not s.cache[k] then s.cache[k] = {} s.cache[k].img = sprite.text(s.font, w, color, t); if key and key ~= s.cache[k].img then stead.sprite_dup(s.cache[k].img, key); sprite.free(s.cache[k].img); s.cache[k].img = key end s.cache[k].word = w; s.cache[k].color = color; s.cache[k].t = t; s.cache[k].time = stead.time(); stead.table.insert(s.list, s.cache[k]); end if not stead.started and not time then time = -1 end if time then s.cache[k].time = time else s.cache[k].time = stead.time(); -- renew time end end; save = function(self, name, h, need) local n if self.fname then n = stead.string.format("%q", self.fname) else n = stead.tostr(self.fname) end h:write(stead.string.format("%s = font(%s, %s, %s);\n", name, n, tostring(self.size), stead.tostring(self.scaled))) local k, v for k,v in ipairs(self.list) do h:write(stead.string.format("%s:cache_add(%q, %q, %d, %q, %d);\n", name, v.word, v.color, v.t, v.img, v.time)) end end; } if not size then size = stead.tonum(theme.get 'win.fnt.size') end if v.scaled then size = sprite.font_scaled_size(size) end if not name then name = theme.get 'win.fnt.name' end v.font = sprite.font(name, size); lifeon(v); return v; end instead-3.5.2+dfsg/doc/examples/stead2/keyboard/000077500000000000000000000000001467622671600214555ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/examples/stead2/keyboard/keyboard.lua000066400000000000000000000144141467622671600237640ustar00rootroot00000000000000require "hideinv" require "kbd" local keyb = { { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", }, { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", }, { "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", [[\]], }, { "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", }, } local kbden = { shifted = { ["1"] = "!", ["2"] = "@", ["3"] = "#", ["4"] = "$", ["5"] = "%", ["6"] = "^", ["7"] = "&", ["8"] = "*", ["9"] = "(", ["0"] = ")", ["-"] = "_", ["="] = "+", ["["] = "{", ["]"] = "}", ["\\"] = "|", [";"] = ":", ["'"] = "\"", [","] = "<", ["."] = ">", ["/"] = "?", } } local kbdru = { ["q"] = "й", ["w"] = "ц", ["e"] = "у", ["r"] = "к", ["t"] = "е", ["y"] = "н", ["u"] = "г", ["i"] = "ш", ["o"] = "щ", ["p"] = "з", ["["] = "х", ["]"] = "ъ", ["a"] = "ф", ["s"] = "ы", ["d"] = "в", ["f"] = "а", ["g"] = "п", ["h"] = "р", ["j"] = "о", ["k"] = "л", ["l"] = "д", [";"] = "ж", ["'"] = "э", ["z"] = "я", ["x"] = "ч", ["c"] = "с", ["v"] = "м", ["b"] = "и", ["n"] = "т", ["m"] = "ь", [","] = "б", ["."] = "ю", ["`"] = "ё", shifted = { ["q"] = "Й", ["w"] = "Ц", ["e"] = "У", ["r"] = "К", ["t"] = "Е", ["y"] = "Н", ["u"] = "Г", ["i"] = "Ш", ["o"] = "Щ", ["p"] = "З", ["["] = "Х", ["]"] = "Ъ", ["a"] = "Ф", ["s"] = "Ы", ["d"] = "В", ["f"] = "А", ["g"] = "П", ["h"] = "Р", ["j"] = "О", ["k"] = "Л", ["l"] = "Д", [";"] = "Ж", ["'"] = "Э", ["z"] = "Я", ["x"] = "Ч", ["c"] = "С", ["v"] = "М", ["b"] = "И", ["n"] = "Т", ["m"] = "Ь", [","] = "Б", ["."] = "Ю", ["`"] = "Ё", ["1"] = "!", ["2"] = "@", ["3"] = "#", ["4"] = ";", ["5"] = "%", ["6"] = ":", ["7"] = "?", ["8"] = "*", ["9"] = "(", ["0"] = ")", ["-"] = "_", ["="] = "+", } } local kbdlower = { ['А'] = 'а', ['Б'] = 'б', ['В'] = 'в', ['Г'] = 'г', ['Д'] = 'д', ['Е'] = 'е', ['Ё'] = 'ё', ['Ж'] = 'ж', ['З'] = 'з', ['И'] = 'и', ['Й'] = 'й', ['К'] = 'к', ['Л'] = 'л', ['М'] = 'м', ['Н'] = 'н', ['О'] = 'о', ['П'] = 'п', ['Р'] = 'р', ['С'] = 'с', ['Т'] = 'т', ['У'] = 'у', ['Ф'] = 'ф', ['Х'] = 'х', ['Ц'] = 'ц', ['Ч'] = 'ч', ['Ш'] = 'ш', ['Щ'] = 'щ', ['Ъ'] = 'ъ', ['Э'] = 'э', ['Ь'] = 'ь', ['Ы'] = 'ы', ['Ю'] = 'ю', ['Я'] = 'я', } local function tolow(s) if not s then return end s = s:lower(); local xlat = kbdlower if xlat then local k,v for k,v in pairs(xlat) do s = s:gsub(k,v); end end return s; end local function input_esc(s) local rep = function(s) return txtnb(s) end if not s then return end local r = s:gsub("[^ ]+", rep):gsub("[ \t]", rep):gsub("{","\\{"):gsub("}","\\}"); return r end local function kbdxlat(s, k) local kbd if k:len() > 1 then return end if s.alt_xlat and (game.codepage == 'UTF-8' or game.codepage == 'utf-8') then kbd = kbdru; else kbd = kbden end if kbd and s.shift then kbd = kbd.shifted; end if not kbd[k] then if s.shift then return k:upper(); end return k; end return kbd[k] end keyboard = function(v) stead.add_var(v, { text = '', alt = false, shift = false, alt_xlat = false}); v.hideinv = true if not v.cursor then v.cursor = '_' end if not v.msg then v.msg = 'Ввод: '; end v.ini = function(s, load) s.alt = false if load and here() == s then s._flt = stead.mouse_filter(0) end end; v.entered = function(s) s.text = ''; s.alt = false s.shift = false hook_keys('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'); hook_keys('1', '2', '3', '4', '5', '6', '7', '8', '9', '0'); hook_keys("-", "=", "[", "]", "\\", ";", "'", ",", ".", "/"); hook_keys('space') hook_keys('backspace'); hook_keys('left alt', 'right alt', 'alt') hook_keys('left shift', 'right shift', 'shift') hook_keys('return'); s._flt = stead.mouse_filter(0) end v.left = function(s) unhook_keys('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'); unhook_keys('1', '2', '3', '4', '5', '6', '7', '8', '9', '0'); unhook_keys("-", "=", "[", "]", "\\", ";", "'", ",", ".", "/"); unhook_keys('space') unhook_keys('backspace'); unhook_keys('left alt', 'right alt', 'alt') unhook_keys('left shift', 'right shift', 'shift') unhook_keys('return'); stead.mouse_filter(s._flt) end v.kbd = function(s, press, key) if key:find("alt") then s.alt = press if s.alt then s.alt_xlat = not s.alt_xlat end return true end if key:find("shift") then s.shift = press return true end if not press then return end if s.alt then return end local o = stead.here():srch('key'); return stead.call(o, 'act', key); end v.xdsc = function(s) p (s.msg) p (input_esc(s.text..s.cursor)) pn() local k,v for k, v in ipairs(keyb) do local kk, vv local row = '' for kk, vv in ipairs(v) do local a = kbdxlat(s, vv) if vv == ',' then vv = 'comma' end row = row.."{key("..vv..")|"..input_esc(a).."}"..txtnb " "; end pn(txtc(row)) end pn (txtc[[{key(alt)|«Alt»}    {key(shift)|«Shift»}    {key(cancel)|«Отмена»}    {key(backspace)|«Забой»}    {key(return)|«Ввод»}]]); end; v.obj = { obj { nam = 'key'; act = function(s, w) if w == 'comma' then w = ',' end if w:find("alt") then stead.here().alt_xlat = not stead.here().alt_xlat return true end if w:find("shift") then stead.here().shift = not stead.here().shift return true end if w == 'space' then w = ' ' end if w == 'backspace' then if not stead.here().text or stead.here().text == '' then return end if stead.here().text:byte(stead.here().text:len()) >= 128 then stead.here().text = stead.here().text:sub(1, stead.here().text:len() - 2); else stead.here().text = stead.here().text:sub(1, stead.here().text:len() - 1); end elseif w == 'cancel' then stead.here().text = ''; stead.back(); elseif w == 'return' then return stead.back(); else w = kbdxlat(stead.here(), w) stead.here().text = stead.here().text..w; end return true end } } return xroom(v) end instead-3.5.2+dfsg/doc/examples/stead2/keyboard/main.lua000066400000000000000000000005161467622671600231060ustar00rootroot00000000000000instead_version "1.7.0" require "keyboard" require "xact" input.verbose = true main = room { nam = '?'; dsc = function(s) if read.text ~= '' then p "Привет, " p (read.text,"!") else p [[Как вас {xwalk(read)|зовут}?]]; end end } read = keyboard { nam = 'Имя:'; msg = "Поле ввода:"; } instead-3.5.2+dfsg/doc/examples/stead2/menu-demo/000077500000000000000000000000001467622671600215435ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/examples/stead2/menu-demo/main.lua000066400000000000000000000071711467622671600232000ustar00rootroot00000000000000instead_version "1.6.3" require "proxymenu" require "hideinv" game.forcedsc = true minv = obj_menu('С СОБОЙ', 'exam', false, true); mlook = obj_menu('ОСМОТРЕТЬ', 'exam', true); mtake = obj_menu('ВЗЯТЬ', 'take', true); mdrop = obj_menu('БРОСИТЬ', 'drop', false, true); meat = obj_menu('ЕСТЬ', 'eat', true, true); mpush = obj_menu('ТОЛКАТЬ', 'push', true); muse = use_menu('ИСПОЛЬЗОВАТЬ', 'useon', 'used', 'useit', true, true); mgive = use_menu('ОТДАТЬ', 'give', 'accept', false, true, true, true); mwalk = obj_menu('ИДТИ', 'walk', false, false, true); game.useit = 'Не помогло.' game.use = 'Не сработает.' game.give = 'Отдать? Ни за что!' game.eat = 'Не буду это есть.' game.drop = 'Еще пригодится.' game.exam = 'Ничего необычного.' game.take = 'Стоит ли это брать?' game.push = 'Ничего не произошло.' game.after_take = function(s, w) take(w) end game.after_drop = function(s, w) drop(w) end put(minv, me()) put(mlook, me()) put(mtake, me()) put(mdrop, me()) put(meat, me()) put(mpush, me()) put(muse, me()) put(mgive, me()) -- put(mwalk, me()) status = stat { _Turns = 0, life = function(s) s._Turns = s._Turns + 1; end; nam = function(s) return 'Статус игрока: '..s._Turns..'^'; end }; lifeon 'status' put(status, me()); knife = obj { nam = 'ножик', dsc = 'На полу валяется ножик.', exam = 'Бесполезный перочинный ножик.', } main = room { nam = 'intro', hideinv = "true", dsc = 'Введение', exit = function(s) inv():add('knife'); end, obj = { vway('next','{Дальше}.', 'r1') } } cube = obj { nam = 'куб', dsc = 'В центре комнаты находится куб.', take = 'Вы взяли куб', exam = 'Мультифункциональный куб -- написано на кубе.', drop = 'Вы положили куб.', useit = 'Как можно использовать куб?', talk = 'Вы поговорили с кубом.', eat = function(s) return 'Вы не можете разгрызть куб.', false; end, open = 'Вы открыли куб.', close = 'Вы закрыли куб.', push = 'Вы толкаете куб.', give = function(s, w) return 'Вы пытаетесь отдать куб объекту: '..deref(w)..'.', false end, useon = function(s, w) return 'Вы пытаетесь юзать куб на объект: '..deref(w)..'. Получилось!' end, used = 'Куб поюзан.', }; sphere = obj { nam = 'сфера', dsc = 'В центре комнаты находится сфера.', take = 'Вы взяли сферу', exam = 'Мультифункциональная сфера -- написано на сфере.', drop = 'Вы положили сферу.', useit = 'Как можно использовать сферу?', talk = 'Вы поговорили с сферой.', eat = function(s) return 'Вы не можете разгрызть сферу.', false; end, open = 'Вы открыли сферу.', close = 'Вы закрыли сферу.', push = 'Вы толкаете сферу.', give = function(s, w) return 'Вы пытаетесь отдать сферу объекту: '..nameof(w)..'.', false end, useon = function(s, w) return 'Вы пытаетесь юзать сферу на объект: '..nameof(w)..'. Получилось!' end, used = 'Сфера поюзана.', }; r1 = room { nam = 'комната', dsc = 'Вы в комнате', obj = { cube, sphere }, } instead-3.5.2+dfsg/doc/examples/stead2/trigger.lua000066400000000000000000000012461467622671600220260ustar00rootroot00000000000000-- example module function trigger(act, cond) local v = {} v.nam = 'trigger'; if not act then error("Wrong parameter to trigger.", 2) end v.act = act; if not cond then cond = true elseif type(cond) == 'string' then cond = stead.eval('return '..cond); end v.cond = cond; v.life = function(s) if stead.call_bool(s, 'cond') then s:off() local r,v = stead.call(s, 'act') if r then return r, true end return r,v end end v.state = function(s) return s._state; end v.on = function(s, p) s._state = true stead.lifeon(s, p) return s end v.off = function(s) s._state = false stead.lifeoff(s) return s end return obj(v) end instead-3.5.2+dfsg/doc/examples/stead3/000077500000000000000000000000001467622671600176565ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/examples/stead3/dialog/000077500000000000000000000000001467622671600211155ustar00rootroot00000000000000instead-3.5.2+dfsg/doc/examples/stead3/dialog/main3.lua000066400000000000000000000260211467622671600226300ustar00rootroot00000000000000-- $Name: Диалог$ -- $API:stead3$ require "dlg" require "fmt" fmt.para = true fmt.dash = true dlg { nam = 'main'; disp = '...'; phr = { [[У тебя одна минута на то, чтобы объяснить мне, как добраться до хранилища.^ — Что?^ Бац! В глазах сверкнуло и боль такая сильная, что кажется, будто она — единственное, что я сейчас чувствую. Даже сильнее страха.^ — Одна минута, — говорит он и прижимает холодный кружок дула к моему лбу.]]; { '#что?', 'Что?', [[Бац! Оказывается, может быть ещё больнее, чем в первый раз.^ — Ещё раз скажешь "что", выстрелю.]] }, { '#что2', 'Что?', function(s) p [[Он стискивает зубы и стреля...]]; walk 'theend' end, cond = function(s) return closed '#что?' end, }, { 'Но я здесь не работаю...', [[ — Но я здесь не работаю, я вообще не знаю, где тут что!^ — Какого чёрта тогда ты делаешь в кабинке оператора? ]], next = '#кто ты?', }, { '#про подвал', 'Хранилище в подвале.', [[— Хранилище находится в подвале...^ — Уже лучше. А теперь, как туда добраться?]], next = '#хранилище'; } }; obj = { { '#кто ты?', { 'Я техник.', [[— Я просто техник, мне позвонили и попросили починить компьютер. Они иногда вызывают меня сюда, но я не знаю, где тут сейф, честное слово!^ — Занятно. Тогда почему на твоём бейдже написано "Старший кассир"?]], { 'Я его одолжил, чтобы через турникет пройти.', function() p [[— Я его одолжил, чтобы пройти через турникет, я часто так делаю, а то они никак мне собственный не сделают...^ — У кого одолжил?^ Пальцем в толстого очкарика на полу, тут же затрясшего головой.^ — Окей, спасибо, техник, — и спускает куро...]]; walk 'theend' end }, }, { 'Я от вас прячусь.', [[ — Я тут от вас прячусь...^ — А, ты один из посетителей?^ — Да.^ — Я вот не видел, как ты сюда пробегал, ты сюда зашёл ещё до того, как я вошёл в здание?^ — Да!^ — А как же ты через турникет прошёл?]], next = '#лжец' }, { 'Тоже решил денег взять.', [[— Да я вот решил тоже денег взять. Под шумок, так сказать. Хе-хе.^ — А, вон оно что. Но на тебе форма сотрудника банка. То есть, ты не только лжец, но ещё и вор? Двадцать секунд. Хе-хе.]], next = '#лжец' }, }, { '#лжец', { alias = '#что?' }, { alias = '#что2' }, { alias = '#про подвал' }, }; { '#хранилище', onempty = function() enable "#нет пути" end, { "По лестнице...", [[— Вон за той дверью в подвал ведёт лестница, по ней можно спуститься до главного коридора, из него в архив, а уже через архив к двери хранилища.^ — Ещё что-нибудь, о чём мне как грабителю полезно было бы узнать?]], next = '#лестница' }, { '#на лифте', "На лифте...", [[— В кабинете управляющего есть лифт, спускающийся прямо в хранилище. Только вряд ли вы до него доберётесь.^ — Почему это?]], next = '#лифт' }, { false, "#нет пути", "Нет", [[— К сожалению, больше путей нет.^ — Вот же задачка. Монетку бросить что ли... Это всё? Может ещё что-нибудь знаешь?]], next = "#про деньги", }, }, { '#лестница', onempty = function(s) p "— А другой путь есть?" pop(); end, { "О лестинце...", [[— На лестнице сторожит охранник с оружием.^ — Каким оружием?]], next = '#оружие', }, { "О коридоре...", [[— Поперёк коридора идут лазерные лучи.^ — Красные или зелёные?]], next = '#коридор' }, { "Об архиве...", function() p [[— В архиве люди пропадают...^ — Что?!^ — Люди, говорю, в архиве пропадают.^ — Да это я понял! Почему пропадают?^ — Не знаю, но, поговаривают, что нужно быть поосторожнее со шкафами F.^ — Почему?^ — Пропали сотрудники Фриманн, Фрекель, Фаркопс и Фонг. У вас какая фамилия?^ — Фицжеральд.^ — О...]]; if not empty '#лестница' then p '^— Дальше.' end end }, { "О двери в хранилищие...", function() p [[— Толщина двери в хранилище полтора метра.^ — Ого... — И замок «Sargent & Greenleaf».^ — Ой...^ — Пол внутри под напряжением десять тысяч вольт.^ — Ох...^ — А снаружи камеры.]]; if not empty '#лестница' then p '^— Понятно. Дальше.' end end } }, { '#коридор', { "Красные.", function() p [[— Красные, кажется. А что есть какая-то разница?]]; if not empty '#лестница' then p '^— Не твоего ума дело, дальше давай.'; end pop() end }, { "Зелёные.", function() p [[— Зелёные, кажется, а что?^ — Проклятье, у меня дейтеранопия.^ — Зелёный цвет не различаете?^ — Да.^ — Сочувствую.]]; if not empty '#лестница' then p '^— Спасибо. Дальше.'; end pop() end }, }, { '#оружие', { "Ружьё какое-то...", function() p [[— Не знаю, я не разбираюсь.]] if not empty '#лестница' then p '^— Дальше.'; end pop() end }, { "Benelli M4...", function() p [[— Benelli M4 Super 90, шестизарядный, с телескопическим прикладом, пистолетной рукояткой, планкой Пикатинни...]] if not empty '#лестница' then p '^— Всё, заткнись, давай дальше.'; end pop() end } }, { "#лифт", onempty = function() p "— А другой путь есть?" pop() end, { "Управляющий.", function() p [[— В кабинете скорее всего сидит сам управляющий.^ — И чего?^ — Он чемпион города по гарлемскому боксу.^ — Впервые слышу про такой бокс.^ — Основная особенность его в том, что во время боя разрешено использовать кастеты, биты и автоматическое оружие.]] if not empty '#лифт' then p "— Хмм, ну ладно, допустим, я с ним разберусь, что ещё?" end end }, { "Собаки.", function() p [[— Собаки.^ — Собаки?^ — Да.^ — Большие?^ — Очень.^ — Много?^ — Четыре.]] if not empty '#лифт' then p "— Ох... Ну допустим, с собаками я как-нибудь управлюсь. Что-то ещё?." end end }, { "Системы идентификации.", [[— В лифте стоят системы идентификации, которые пропускают только управляющего.^ — Какие системы?]], next = '#идентификация', }, }, { "#идентификация", onempty = function() enable "#по системам все"; end, { false, '#по системам все', [[- По системам идентификации всё.]]; function() if not empty '#лифт' then p "Ещё что-нибудь по лифту?" end pop() end }, { "Отпечатки.", [[— Сканер отпечатка правой ладони.^ — Это, теоретически, можно обойти. Дальше.]], }, { "Сетчатка глаза.", [[— Для этого у меня есть инструменты и необходимые навыки, — он зловеще ухмыляется. — Дальше.]], }, { "Вес.", [[— Датчик веса.^ — Хм. Сколько весит местный управляющий?^ — 124 килограмма. А вы сколько весите?^ — 61. Мда. Тут даже клонирующая машина бы не помогла. Ладно, дальше.]], }, }, { "#про деньги", { "Про деньги.", function(s) p [[— Знаю про деньги в хранилище.^ — Так, и что с ними?^ — Их там нет.^ — Как нет?!^ — Ну мы переезжаем в другой район города и все деньги и ценности уже перевезли сегодня ночью.^ — Так почему ты сразу не сказал?!^ — Ну про это вы как раз не спрашивали.^ — Проклятье!^^ И с этими словами он выбегает из отделения банка, где его ловит экипаж инкассаторской машины, приехавшей, чтобы как раз перевезти содержимое хранилища в другой район города. Хе-хе.]] walk 'theend' end }, } } } room { disp = 'Конец'; nam = 'theend'; } instead-3.5.2+dfsg/doc/instead.6000066400000000000000000000075501467622671600164020ustar00rootroot00000000000000.TH INSTEAD 6 "Version 3.3.2" Instead GAMES .SH NAME INSTEAD - Simple Text Adventure Engine, The Interpreter .SH DESCRIPTION The interpreter of STEAD (Simple Text Adventures) allows one to play games that combine visual novels, text adventures and classic quests of 1990-s. The STEAD games features are: .TP * very simple source code of the stories. (based on LUA); .TP * graphical game interface; .TP * supports music and images; .TP * theme support \- a game may change the interface look; .TP * portability (originally written for Linux, depends on SDL and lua). .SH SYNOPSIS .B sdl-instead .I [options] [game.zip or game.idf or path to game] .SH OPTIONS .TP .B -debug Debug mode (for game developers). .TP .B -nosound Run the game without sound. .TP .B -vsync Vsync output. (SDL2 only) .TP .B -gamespath Add path with games. .TP .B -themespath Add path with themes. .TP .B -nostdgames Do not use default games. .TP .B -nostdthemes Do not use default themes. .TP .B -game Select game in gamespath. .TP .B -theme Select theme in themespath. .TP .B -owntheme Force game to use own theme. .TP .B -notheme Do not use own game theme. .TP .B -fullscreen Run the game in fullscreen mode. .TP .B -nocursor Do not use game mouse cursors (use system one) .TP .B -hires / -nohires Set/unset the high resolution when run in fullscreen mode. .TP .B -window Run the game in windowed mode. .TP .B -resizable Resizable window (SDL2 only) .TP .B -scale Scale window (SDL2 only) .TP .B -noautosave Disable autosave load. .TP .B -encode [encoded file] Encode lua file. Encoded file can be executed with doencfile("encoded file"). .TP .B -idf Build idf file [INSTEAD data file] from directory. .TP .B -mode [WxH] Use WxH resolution. .TP .B -modes [,[,]] ... Define available resolutions. .TP .B -software Force software rendering .TP .B -renderer Select default renderer (SDL2 only) .TP .B -fontscale Font scaling. .TP .B -nopause Do not pause the game on window minimize. .TP .B -lang Select language. .TP .B -hinting 0|1|2|3 Set the font hinting mode (helpful with infinality). .TP .B -install [game in zip] Install game from zip archive .TP .B -quit Quit :) .TP .B -appdata [fullpath] Store saves and settings in appdata path. Path must exist! .TP .B -chunksize [size in bytes] Size for audio buffer. Try this if sound lags. .TP .B -version Show version and exit. .TP .B -lua [arguments] Exec lua script (for game developers). .TP .B -luac Check lua script (for game developers). .TP .B -standalone Run game in standalone mode (no sandbox, no games selection ...). .TP .B -noconfig Do not load saved config (run with defaults). .TP .B -profile Using configuration profile. Profile file is the ini-styled file with parameter = value pairs. Where is parameters are arguments without -. .PP Configuration file name is 'insteadrc' and it's located in ~/.instead/. Games can be downloaded from http://instead-games.sf.net. Unzip them in ~/.instead/games. .SH CONTROLS Please, see tutorial. .SH LICENCE This software is covered by the terms of the MIT license. .SH WARRANTY None. .SH COPYRIGHT AND CREDITS .TP .B Peter Kosyh INSTEAD author. .TP .B Ilya Ryndin Initial port to Windows. .TP .B Boris Timofeev, Anton Kolosov, Aleksey Mahno Port to Android. .TP .B .dm Port to Mac OS X. .TP .B Andrey Afletdinov Port to Windows CE. .TP .B Vadim Balashoff Advices. .TP .B Vladimir Zhirov Advices. .TP .B Alexander Yakovlev manual.tex support. .TP .B Serj Kalichev Advices and default theme correction. .TP .B Vladimir Podobaev, Oleg Gvozdev Testers. .TP .B Alexander Soborov Wiki support. .TP .B Andrew Lobanov Games repository, slackbuild. .TP Many others for comments, bug reports, games and ideas. .SH SEE ALSO .BR https://instead-hub.github.io instead-3.5.2+dfsg/doc/instead.txt000066400000000000000000000104301467622671600170430ustar00rootroot00000000000000INSTEAD(6) GAMES INSTEAD(6) NAME INSTEAD - Simple Text Adventure Engine, The Interpreter DESCRIPTION The interpreter of STEAD (Simple Text Adventures) allows one to play games that combine visual novels, text adventures and classic quests of 1990-s. The STEAD games features are: * very simple source code of the stories. (based on LUA); * graphical game interface; * supports music and images; * theme support - a game may change the interface look; * portability (originally written for Linux, depends on SDL and lua). SYNOPSIS sdl-instead [options] [game.zip or game.idf or path to game] OPTIONS -debug Debug mode (for game developers). -nosound Run the game without sound. -vsync Vsync output. (SDL2 only) -gamespath Add path with games. -themespath Add path with themes. -nostdgames Do not use default games. -nostdthemes Do not use default themes. -game Select game in gamespath. -theme Select theme in themespath. -owntheme Force game to use own theme. -notheme Do not use own game theme. -fullscreen Run the game in fullscreen mode. -nocursor Do not use game mouse cursors (use system one) -hires / -nohires Set/unset the high resolution when run in fullscreen mode. -window Run the game in windowed mode. -resizable Resizable window (SDL2 only) -scale Scale window (SDL2 only) -noautosave Disable autosave load. -encode [encoded file] Encode lua file. Encoded file can be executed with doencfile("encoded file"). -idf Build idf file [INSTEAD data file] from directory. -mode [WxH] Use WxH resolution. -modes [,[,]] ... Define available resolutions. -software Force software rendering -renderer Select default renderer (SDL2 only) -fontscale Font scaling. -nopause Do not pause the game on window minimize. -lang Select language. -hinting 0|1|2|3 Set the font hinting mode (helpful with infinality). -install [game in zip] Install game from zip archive -quit Quit :) -appdata [fullpath] Store saves and settings in appdata path. Path must exist! -chunksize [size in bytes] Size for audio buffer. Try this if sound lags. -version Show version and exit. -lua [arguments] Exec lua script (for game developers). -luac Check lua script (for game developers). -standalone Run game in standalone mode (no sandbox, no games selection ...). -noconfig Do not load saved config (run with defaults). -profile Using configuration profile. Profile file is the ini-styled file with parameter = value pairs. Where is parameters are arguments without -. Configuration file name is 'insteadrc' and it's located in ~/.instead/. Games can be downloaded from http://instead-games.sf.net. Unzip them in ~/.instead/games. CONTROLS Please, see tutorial. LICENCE This software is covered by the terms of the MIT license. WARRANTY None. COPYRIGHT AND CREDITS Peter Kosyh INSTEAD author. Ilya Ryndin Initial port to Windows. Boris Timofeev, Anton Kolosov, Aleksey Mahno Port to Android. .dm Port to Mac OS X. Andrey Afletdinov Port to Windows CE. Vadim Balashoff Advices. Vladimir Zhirov Advices. Alexander Yakovlev manual.tex support. Serj Kalichev Advices and default theme correction. Vladimir Podobaev, Oleg Gvozdev Testers. Alexander Soborov Wiki support. Andrew Lobanov Games repository, slackbuild. Many others for comments, bug reports, games and ideas. SEE ALSO https://instead-hub.github.io Instead Version 3.3.2 INSTEAD(6) instead-3.5.2+dfsg/doc/modules3-ru.md000066400000000000000000001032171467622671600173620ustar00rootroot00000000000000## Модули STEAD3 Данное руководство описывает основы разработки модулей STEAD3. Поэтому в дальнейшем изложении слово "модуль" означает именно модуль, написанный в рамках STEAD3. Что такое модуль? Часто ошибочно считают, что модуль -- это любой отдельный файл игры, содержащий служебные функции, структуры и объекты. На самом деле это не так. Если вам необходимо выделить служебный код в отдельные игровые файлы так, чтобы он выполнялся в момент старта игры -- вам достаточно включить такой файл инструкцией include: include "mylib" Модули stead3 пишутся, следуя специальным соглашениям, при нарушении которых вы получите нерабочую игру. Данные соглашения и описываются в этом руководстве. Очень часто в оформлении своего кода в виде модуля просто нет никакой необходимости. Написание модуля целесообразно в тех случаях, когда требуемая функциональность может быть реализована за счёт тесного взаимодействия с движком STEAD3 и представляет ценность не только в рамках вашей игры. Примерами модулей могут быть: - модуль форматирования вывода; - модуль нестандартного управления игрой; - модуль генерации изображений нотного стана... И так далее. ## Игровой мир Важным отличием модуля от просто библиотечного файла является время жизни модуля. Игровой мир (объект game, игрок, все объекты и переменные игры) создаётся в момент запуска игры. При подгрузке частей игры с помощью gamefile, а также при загрузке сохранений игры -- игровой мир уничтожается, чтобы затем снова создаться заново. В момент уничтожения мира, все созданные объекты и переменные перестают существовать. Когда вы включаете код с помощью include, весь этот код будет выполнятся в момент каждого создания мира. Обычно, это подразумевается автором как само собой разумеющееся поведение. Но в случае модуля, это не так! Модуль загружается один раз, во время создания игровой сессии и существует всё то время, пока выполняется игровой код. То есть, после уничтожении игрового мира и при его новом создании, уже загруженные ранее модули не загружаются повторно. Это означает, например, что в модуле _нельзя_ определять глобальные переменные, объекты и комнаты так, как это делается в обычном коде игры. Например, модуль не может содержать строки вида: -- мой неправильный модуль global 'MYVAR' (10); room { nam = 'комната'; }; Дело в том, что и MYVAR и комната будут уничтожены при первой же загрузки игры из файла сохранения, так как игровой мир уничтожается целиком, а переменная MYVAR и комната -- часть этого игрового мира. Если подумать, это становится понятным с той точки зрения, что модуль не должен в общем случае создавать какие-то объекты и глобальные переменные в игровом мире игры. Ведь модуль может работать с любой игрой, и не должен учитывать особенности игрового мира конкретной игры. Создание глобальных функций тоже не является хорошим тоном при написании модулей. Если вам нужна служебная функция в рамках самого модуля, объявляйте её с local (то же касается и переменных): ``` local A = 10 local function myfunc(a, b) return (a * b) / A end ``` Тогда такая функция будет доступна в рамках модуля. ## Системный объект как интерфейс После прочтения прошлой главы мог возникнуть резонный вопрос. Если все переменные и объекты модуля уничтожаются -- то как вообще взаимодействовать с модулем? Если модуль должен предоставлять какой-либо интерфейс, а также сохранять своё состояние, то в модуле следует создать системный объект (чьё имя начинается с символа '@'). Подробнее про системные объекты можно прочитать в документации STEAD3. Важно то, что такие объекты _не уничтожаются_ в процессе смерти мира, и таким образом играют роль интерфейса к модулю. Например: ``` -- модуль testmod.lua obj { nam = '@testmod'; hello = function(s) dprint("Hello world"); end; } ``` Такой модуль уже можно использовать: ``` loadmod 'testmod' _'@testmod'.hello() -- получили объект '@testmod' и вызвали метод hello() ``` Но это не слишком удобно. Следующий вариант модуля: ``` -- модуль mymodule.lua local mod = obj { -- локальная ссылка на объект nam = '@testmod'; } function mod.hello(a) -- вариант определения метода вне объекта dprint("Hello world") end testmod = mod -- глобальный объект testmod -- интерфейс к модулю ``` Использование модуля: ``` loadmod 'testmod' testmod.hello() ``` Сделаем вариант модуля с переменной, которая должна сохранятся: ``` -- модуль mymodule.lua local mod = obj { -- локальная ссылка на объект nam = '@testmod'; num = 0; -- переменная } function mod.hello(a) dprint("Hello world", mod.num) mod.num = mod.num + 1 end testmod = mod -- глобальный объект testmod -- интерфейс к модулю ``` Итак, подводя итоги: - интерфейсом к модулю служит системный объект, имя которого совпадает с именем модуля; - все переменные, которые нужно сохранять, должны быть переменными этого объекта; - вы можете вызывать методы через модуль.метод(). ## События Итак, модуль существует всё время жизни игровой сессии, во время которой игровой мир может неоднократно уничтожаться и создаваться снова. Допустим, автору модуля необходимо выполнять какие-то действия в момент создания игрового мира (например, помещать что-то в инвентарь игрока). Как это сделать? Модуль может регистрировать специальные функции-обработчики некоторых событий. Например, для отслеживания события "создание игрового мира", мы регистрируем обработчик init: ``` stead.mod_init(function() declare { game = std.ref 'game', pl = std.ref 'player', } end) ``` stead -- это интерфейсный объект для доступа к низкоуровневым функциям INSTEAD. Часто, удобно сделать локальную ссылку std, и пользоваться ей, например: ``` local std = stead -- сделали ссылку на stead std.mod_init(function() declare { game = std.ref 'game', pl = std.ref 'player', } end) ``` В дальнейшем изложении всегда будет использоваться std вместо stead. Приведённый код -- инициализация стандартной библиотеки stdlib из STEAD3. Как видим, тут происходит объявление переменных-ссылок game и pl для удобства работы с этими объектами. Итак, регистрация обработчика выполняется с помощью вызова: ``` std.mod_тип_события(функция, [приоритет]) ``` Параметр [приоритет] (чем меньше -- тем приоритетней) является необязательным и определяет порядок вызова вашей функции относительно других функций для данного события, например: ``` local function init() dprint("Очень ранний init"); end std.mod_init(init, -10); ``` Перечислим все события, для которых можно зарегистрировать свой обработчик. - init - инициализация мира. Вызывается перед init() игры; - done - деинициализация мира; - start - запуск игры после инициализации мира (непосредственно перед вызовом start() игры). В обработчик придёт параметр load (true -- если это загрузка из файла сохранения); - cmd - вызывается перед выполнением команды. Если вернёт не nil -- воспринимается движком как реакция на команду. В качестве параметра - массив (команда, параметр1, параметр2, ...); - step - вызывается после выполнения команды. В качестве параметра -- true (команда выполнена), или false (ошибочная команда); Выполняется после game:step(); - save - вызывается после сохранения динамических объектов игры в файл сохранения. В качестве параметра -- указатель на файл сохранения (Lua). ## Классы Все объекты в INSTEAD, кроме переменных, атрибутов и обработчиков содержат методы (функции), которые вызываются при работе движка. Когда в коде вашей игры, вы пишете что-то вроде: ``` obj { nam = 'стол'; dsc = "Тут стоит {стол}."; } ``` То вы создаёте таблицу Lua, в которой кроме nam и dsc определены многие другие вещи. Например, метод disable(). Когда вы пишете: ``` obj { nam = 'стол'; dsc = "Тут стоит {стол}."; }:disable() ``` Вы у созданного только что объекта 'стол' вызываете метод disable(). (Вызывается функция disable объекта и в качестве 1-го параметра передаётся этот же объект). На самом деле, даже когда вы создаёте объект с помощью obj, вы неявно вызываете метод (функцию) new у класса obj: obj.new { описатель объекта } Классы -- удобный способ описать иерархию объектов INSTEAD, а также реализовать свои типы объектов. Например, вот как определяется класс obj (с сокращениями): ``` std.obj = std.class { -- определяем класс __obj_type = true; -- тип объектов (функция is_obj) with = function(self, ...) -- ... реализация конструкции :with end; new = function(self, v) -- реализация конструктора obj { } end; -- другие методы -- ... display = function(self) -- отображение объекта local d = std.call(self, 'dsc') return d end; -- другие методы -- ... }; ``` Обратите внимание на метод display, этот метод служит для отображения объекта в сцене. Как видите, он просто вызывает 'dsc' у объекта, с помощью std.call (вызов функции или строки). Теперь представим себе, что вы хотите сделать класс объектов, у которых в темноте пропадает описатель. Признаком темноты является переменная darkroom в текущей комнате, тогда: ``` darkobj = std.class ({ -- определяем класс __darkobj_type = true; -- тип объектов (функция is_obj) display = function(self) -- отображение объекта if not here().darkroom then local d = std.call(self, 'dsc') return d end end; }, std.obj); darkobj { nam = 'кот'; dsc = '{Кот} виден при свете.' } ``` Обратите внимание на скобки () и std.obj в последней строке. Таким образом мы дали понять, что наследуемся от класса std.obj. Все методы объекта, созданного при помощи darkobj, будут такими же, как и у obj, кроме метода display(). Если говорить об иерархии объектов STEAD3, то: - room пронаследован от obj; - dlg пронаследован от room; - std.phr (фразы) пронаследован от obj; std.dlg, std.room, std.phr и std.obj это внутренние имена классов. В стандартной библиотеке stdlib, которая включается в вашу игру, определены такие переменные; ``` local std = stead local type = std.type std.rawset(_G, 'std', stead) -- определим std для всех include = std.include loadmod = std.loadmod rnd = std.rnd rnd_seed = std.rnd_seed p = std.p pr = std.pr pn = std.pn pf = std.pf obj = std.obj stat = std.stat room = std.room menu = std.menu dlg = std.dlg me = std.me here = std.here from = std.from new = std.new delete = std.delete gamefile = std.gamefile player = std.player dprint = std.dprint ``` Это сделано для удобства автора (легче написать include, вместо std.include или stead.include). Если же вы разрабатываете свой _модуль_, то рекомендуется пользоваться внутренними именами с префиксом std. Причём std определять в начале модуля: ``` local std = stead ``` Это обезопасит ваш модуль от коллизий с игровыми глобальными переменными. ## Цикл обработки команд Жизненный цикл игры на INSTEAD это обработка команд. Примерно как сервер отвечает на запросы клиентов, INSTEAD получает команды и отвечает на них текстом. Команды формируются интерпретатором в зависимости от того, какие действия выполняет игрок. Команда -- это слово, за которым может быть список аргументов. Примеры команд STEAD3: - load <файл>; - загрузка - save <файл>; - выгрузка - use <объект>,<объект>; - использование объекта на объект - use <объект>; - использование объекта в инвентаре - act <объект>; - действие на объект - act <$объект>,аргументы...; - ссылка на системный объект - go <переход>; - переход - look; - осмотреться - inv; - получить инвентарь - way; - получить список переходов В качестве объектов используются идентификаторы в виде цифр, которые движок сам сопоставляет каждому видимому на сцене объекту. Каким образом STEAD3 обрабатывает команды? Интерпретатор работает с Lua частью через специальный системный объект iface (переменная ссылка на "@iface"). Этот объект создаётся внутри STEAD3, а для графической версии интерпретатора INSTEAD, пересоздаётся специальным модулем ext/gui.lua. Выполнение команды -- это вызов iface:cmd(команда). Обратите внимание на ':'. Такая запись это синоним: iface.cmd(iface, команда). Команда разбивается на части, и записывается в специальный массив std.cmd. Так, в случае команды load, в std.cmd[1] будет записано "load", а в std.cmd[2] -- путь к файлу. Затем происходит вызов game:cmd(std.cmd). Это и есть то место, где команда обрабатывается игрой. После чего вывод (возвращаемое значение) пропускается через iface:fmt(). Который в свою очередь вызывает std.fmt. В std.fmt ссылки в выводе игры {} превращаются в ссылки для интерпретатора. ## Примеры модулей ### Пишем компас В качестве примера разберём модуль, реализующий простой компас. Наш компас будет представлен ссылками С/Ю/В/З в инвентаре. При нажатии на одну из ссылок, будет осуществляться переход по атрибуту комнаты: to_n, to_s, to_e, to_w соответственно. Начнём с того, что создадим файл compass.lua, в котором создадим объект @compass: ``` local std = stead obj { nam = '@compass'; } ``` Наш компас -- это фактически набор ссылок: C, Ю, В, З. При нажатии на ссылку, мы должны выполнить walk. Как отобразить ссылки в инвентаре? Мы можем поступить двумя способами: 1. создать для каждого направления свой объект; 2. воспользоваться подстановками. Первый способ плох тем, что не позволяет нам произвольно форматировать вывод (а мы хотим, чтобы компас был похож на компас), поэтому подстановки, в данном случае, будут удобнее. ``` obj { nam = '@compass'; disp = false; -- не показывать объект @compass }:with { obj { nam = '$compass'; act = function(s, w) std.p(fmt.c ("{@compass n| С}\n{@compass w|З} {@compass e|В}\n{@compass s|Ю}")) end; } } ``` В объект @compass (который стал невидимым, см disp = false), мы вложили объект $compass. Как вы помните, это подстановки. Движок, встретив ссылки вида {$compass} (а именно такая ссылка будет в инвентаре, если мы поместим туда объект компас), вызовет act у объекта $compass и его результат отобразит в выводе. Мы и воспользовались этим! Функция act у $compass формирует строку ссылок: С, З, В, Ю. Причём в качестве объекта реакции выступает @compass. Это значит, что, добавив обработчик inv в @compass, мы получим вызов этого метода как реакцию на нажатие ссылки: ``` obj { nam = '@compass'; disp = false; inv = function(s) p [[Вы нажали на ссылку.]] end; }:with { ... ``` Но как определить, в какую сторону мы хотим идти? Ссылки нашего компаса имеют вид: ``` {@compass n|С} ``` Это значит, что движок, при нажатии на такую ссылку, сформирует команду: ``` use @compass,n ``` Которая и приведёт к вызову метода inv у объекта @compass. Но как получить второй параметр, в данном случае n? К сожалению, у обработчика inv не предусмотрены дополнительные параметры, но если вы вспомните, что команда STEAD3 раскладывается на компоненты при её обработке, то поймёте следующий код: ``` obj { nam = '@compass'; disp = false; inv = function(s) local dir = std.cmd[3] p("Вы хотите идти по направлению: ", dir) end; }:with { ``` Теперь в переменной dir мы получим; n, s, w или e! Действительно, в std.cmd[1] будет записан 'use', в std.cmd[2] -- объект, а в std.cmd[3] -- параметр. Если бы мы вставляли подстановку в тело вывода сцены, команда была бы такой: ``` act @compass,n ``` И был бы вызван обработчик act. В обработчике act предусмотрены дополнительные аргументы, поэтому в таком случае мы могли бы просто взять параметр из списка параметров к обработчику act. Впрочем, способ с массивом std.cmd сработал бы тоже. Теперь нам осталось написать код, который делает переход по локации, заданной атрибутом to_направление: ``` obj { nam = '@compass'; disp = false; inv = function(s) local dir = std.cmd[3] local r = std.call(std.here(), 'to_'..dir) if not r then std.p ([[Нет прохода.]]) else std.walk(r) end end; }:with { ``` Теперь нам осталось только сделать так, чтобы компас попадал в инвентарь и предоставить объект compass для настроек (которые могут в нем появиться при дальнейшем развитии модуля): ``` local std = stead require "fmt" obj { nam = '@compass'; disp = false; inv = function(s) local dir = std.cmd[3] local r = std.call(std.here(), dir..'_to') if not r then std.p ([[Нет прохода]]) else std.walk(r) end end; }:with { obj { nam = '$compass'; act = function(s, w) std.p(fmt.c ("{@compass n| С}\n{@compass w|З} {@compass e|В}\n{@compass s|Ю}")) end; } } std.mod_start(function(load) take '@compass' end) compass = _'@compass' ``` Дальнейшие улучшения компаса могут включать в себя: - не показывать ссылками те направления, которые недоступны. Для этого надо изменить код $compass.act; - оформить вывод компаса в виде изображения. Для этого можно с помощью pixels сформировать изображение компаса, разрезать изображение на 9 квадратных изображений, преобразовать из в спрайты и выводить ссылки на них из act. Данные улучшения предлагается выполнить самостоятельно. ### Модуль клавиатурного ввода В качестве следующего примера рассмотрим код модуля keyboard. Этот модуль можно скачать с [репозитория модулей](https://github.com/instead-hub/stead3-modules/tree/master/keyboard). Модуль позволяет организовать ввод пользователя с клавиатуры. Идея модуля состоит в том, что клавиатурный ввод оформлен в виде специальной комнаты, в которой можно выполнить набор текста и вернуться к первоначальной комнате. Комната, содержащая в себе логику клавиатурного ввода, носит имя @keyboard. Это системный объект, который не уничтожается при рестарте мира. Для использования клавиатуры используется ссылка на системный объект (см. main3.lua): ``` p [[Как вас {@keyboard "Имя"|зовут}?]]; ``` Как видим, в качестве параметра передаётся информационная строка, которая будет отображена при вводе. Объект @keyboard, соответственно, должен реализовать act обработчик, который перенесёт игрока в комнату клавиатурного ввода: ``` act = function(s, w, ...) s.title = w or "?" s.args = { ... } walkin(s) end; ``` Кроме того, что здесь мы меняем название комнаты (title) и делаем переход (walkin), мы также запомнили все дополнительные аргументы, если они передавались в ссылке {@keyboard}. Зачем это нужно, будет ясно позднее. Итак, осталось реализовать клавиатурный ввод. Для этого мы воспользуемся ссылками кнопок (для того, чтобы вводить текст можно было на устройствах без клавиатуры). И одновременно с этим, будем отслеживать нажатия на клавиши с помощью модуля keys (для удобства игроков на компьютерах с клавиатурой). Формирование ссылок-клавиш осуществляется в decor. При этом, ссылки формируются в виде: ``` row = row.."{@kbdinput "..vv.."|"..input_esc(a).."}"..fmt.nb " "; ``` input_esc() -- функция, реализованная в модуле, которая экранирует некоторые символы, типа { и }. Как видим, это снова ссылки на системный объект, но теперь это уже @kbdinput. Этот объект специально создан для обработки событий от клавиш. Прежде чем мы перейдём к нему, рассмотрим вопрос использования модуля keys. Для использования keys мы должны: - определить onkey в комнате @keyboard; - задать keys:filter() Мы могли бы просто определить в модуле: ``` function keys:filter() -- логика функции end ``` Но мы хотим, чтобы наш модуль мог работать совместно с каким-то другим применением модуля keys, поэтому при старте игры мы перехватываем старый обработчик keys:filter, заменяя его на свой. А потом, при деинициализации мира возвращаем старый обработчик обратно (когда он уже не нужен). ``` local hooked local orig_filter std.mod_start(function(load) if not hooked then hooked = true orig_filter = std.rawget(keys, 'filter') std.rawset(keys, 'filter', std.hook(keys.filter, function(f, s, press, key) if std.here().keyboard_type then return hook_keys[key] end return f(s, press, key) end)) end end) std.mod_done(function(load) hooked = false std.rawset(keys, 'filter', orig_filter) end) ``` Здесь мы видим использование нескольких функций: - std.rawget(таблица, имя) - получить элемент таблицы без генерации сообщения о несуществующей переменой (работа с переменными на низком уровне); - std.rawset(таблица, имя, значение) - установить значение элемента таблицы без генерации сообщения о необъявленной переменной; - std.hook(старая функция, функция перехвата) - создать функцию перехвата. std.rawget/std.rawset -- это способ работы с переменными на самом низком уровне. Например, если бы в mod_start мы просто присвоили keys.filter = std.hook ..., то мы получили бы сообщение о том, что мы меняем объект, который не является переменной. Итак, если клавиши нажимаются в момент нахождения в комнате @keyboard, то мы используем наш фильтр клавиш, если нет -- используется перехваченный фильтр клавиш (keys:filter). Массив hook_keys содержит все те клавиши, которые мы перехватываем. Объект @kbdinput реализует act, который занимается обработкой вводимых символов. Когда текст набран и ввод подтверждён клавишей ввод или соответствующей ссылкой выполняется следующий код: ``` walkback(); return std.call(std.here(), 'onkbd', _'@keyboard'.text, std.unpack(_'@keyboard'.args)) ``` Как видим, происходит вызов обработчика onkbd в комнате из которой мы пришли. В качестве первого параметра передаётся введённый текст. Затем передаются все те параметры, которые пользователь задал в ссылке @keyboard. Эти параметры помогут идентифицировать поле ввода, если мы хотим использовать несколько полей ввода в одной комнате. Здесь используются следующие функции: - std.unpack(таблица) -- превратить таблицу в набор аргументов; - std.call(объект, метод, аргументы) -- вызвать обработчик объекта instead. Теперь вы можете самостоятельно разобраться в остальных деталях модуля @keyboard. instead-3.5.2+dfsg/doc/modules3-ru.pdf000066400000000000000000002622551467622671600175430ustar00rootroot00000000000000%PDF-1.5 % 6 0 obj <> stream xڅjC1D|^08wu!cT)MV@ +iwFoMv ]$'4_"! )lM;uB )C1h8_̥qNmVF -kzVCȥy&".f%I9tBը3qA=1`mj)ZmXfuro4~~d\~ endstream endobj 21 0 obj <> stream xV͎1 yOZHܐ8.'g4]:E VNlg'~:tt C}TyZMvXd*nzr}/)7 d]G] TuO[s<؜XR#:jҍU*:ƛQEGƫq7^"!nV`uɆVDL(:܄qJ%5g1u=oҸ#,tjDZfI*Y?$ss޴}.6.jO1{UDJP*􀛊ct32f\ 2-)S/7^L^l +y/t^ާ`$l7Vڵuwio71SlX+;M3oHYS_!꫌uƬv endstream endobj 26 0 obj <> stream xڝXF|ѳ"m ] R*E޿3<$ǰ}~A !?8s jm ʏMY3u\@+bzf(INcT6|"|ȬOO1=6=]"75$kl=[5f9;)1jrd=:sO"jx2 KsS}Br2R$O`|xsF5DhTHqBIjߍBl"Ok=*];odjL n3uv98iЅ'R8 $0#2`1!Ȏ.=jrh߶K ۓe 4Z lLQSa@Yr\0Xtw)tQ0g5ʕr^5RiwR5`r7J5еkP+v~j¢,smR]Wo:TW7'/,_e:_jB}qOJ 2ШTW`jv!%ajQnHBy0|Zȓս\֛~KNdxKzb乨:2z"\27 (UZXJի7ib+[=сkhZ(,](kĮ1>[iRO =FRl)>8<ڽ8E,s?Qdgq͈mKpk{6MWZ\y\E(Q nAz! kH"sXt +`gmΞKjcm^ZNb`JeҨTSB%^POBOy5İg: ىJ^X#ᐩF 4yTt7#}Zrmݕ:nsgc=˓Cfsp56߆iZ09iMS'o)RM D'͒b%CsDH= V %Km NW#u5, SQB܈-.5 NzΝ$˟{Je䝌Pl yJ X7붭KB,\ 'O,hNџH:޺:lI5 ؂;z-6`Tu#::B(Ȏ$eC@;Eĩjb9,OQ)~Hg "4k kh"B$6%/ÏKIw Di6-xŮlYWgEdK[ bxh&:CK豹Vr'/?Uct!e?zľoV"C*G~!M4`iwU[z.g\/_4Chse^Wqrax$; !LxF Iq5aq ?  endstream endobj 31 0 obj <> stream xe B!E}(vhQlբt}TxJOb !SLܿ e(hRz=ʩ!ڏwY3n%]XG&pY?J e0Zi]#0fM=Z E3 endstream endobj 34 0 obj <> stream xڕ6WfNOK[H` ż|U")c{6#ߤxӿ SrL|y5-]d?{zu1y3zLZ'?B9g a1T %DgSV`.S}s3A)BϢ<£:2YJFH= g+r3Ő7 p6_bAXi+7u GlF-Ğڛ* ;辳i H="R! k #E(sݠL䡹LJ}a6ٳG.Dy~/0tOw\qk5@^TU`RSHygU: sO엘>2;brh_ɡacGf[5' :7, |]03_1?]fŧ'K!X \< qĶk]$ *vu 5U#8 bu9عHC1ﰖܺ+M xH2i6C<%ȔHy(O,9.Qbr6{7SazBJ\k G᭓jzy>0Vu(]MFv߸3AjВG7f]yvIQUpQ$ܕt$4:8$;rjWU2jy]W) @:n>0Gq ;)$]TmEpF wcDhc3j!S1(.h?>xyiqFlLS >o,^fXbmG ?0iFPɥ{Ʀh7)ATzAf5ы6QҵhmՖW{lP0Nre} ލ%wGev|n䰺Ԑ{Lf:6-(xo_CNzfr:7*ySdOg1Jڽ, ů2$P7X2+Cg+e]]ɗq3tfeaޠ{i vqEG./E҂jzҨSb3u`\vvjwď/t}\,{hw>7*]8 t]>[5柿^ endstream endobj 37 0 obj <> stream xڅV0+  RȒU9)kmKԼz; }/71F]!XrNZL,jq)Ed RB; ҇S]:2B}2 =o+ؤ%BW6wAaR)> stream xڝW6i( x 830@H/rO샤8Y{릔#J4zT!/@g]25.(r'ySUd=U9iN3.ZQ00p g TA8%$X7lx X(8L1i"띁| cjrtjxM4:Mk-4p$KAf*+x#S|b}9GDurVRKRO`j'km 'Av3ZN bfRRT,E(G'lUI݂1aRYExUP281[U:Y;)!c^; &_wz.O%Zn= Yp[ ! T&H d (j`:ߋ%+}$ r{*aɓ6J½&dĴc9I6s\(/6APyWḡ tRWﷂ 朙vT'UPJQ`71R#4m"\y/ 狩kJ'TpWu'h;U-s(p -~_K.R vnR@c}k˃;Wo2 1eJO 8U/)Gu7N}JVcb!{S٘[jO)<*CçoJ [XBTeWa5>ݾ,#,(hdmS_gӂcc|PbҞDR-r}:F\H^+z>/7Cxe2ojg5O\1>edapt{ ɱʓ()Onﰪ"^5}p͕1K6EA {'H3k!U)yC 6X]?i3n/矿Z endstream endobj 43 0 obj <> stream xX6 ~qHaIt Rxvy&$E=Y!Nd)R?vKͻ_y柮ݏ`73u")ϹN|۟ߘ1mAd-ʄ pqςKY7afN"E;媴~!h4 ~j_zpf<:TK2n&MϴۉFPx9T #>xxɗ418䘖 h!TY_ DRݡMI4~3q6'Eeb7"FD/5 E 2є!%7M',j#t'_v'9pphq<js=5AɌAYegfڼ-9Fz 4[ rG3\K# 1 ZBowo&)7a:+\Ycif~}k 2MDCEs(xTt+j lxVlGkX'6ԇƗLwas!єZ,\SmZ\@^muZe(Y{?4|~ Z[jtc`ԩ M[[p oOp9;t;S0NE^3^XCG׾A^^+:Z/C(vG_Cӻ(XN X$n: I*^بC"XPzZ_8',$R]d\"+ڗ~pޟ^Rڳf-a|> stream xW6 ~(L  ]+P")3㹽+ v%G÷ @?fH0,_Oz<_O`&Lنa4N^.N`W@c!3J/ ^Y2y4Fu FcY+zbQPl3QhU*D}H8v3/3^OBԳsuҳ6Wؾhɵ2ꖕy&<6EXMC [SHa:R{-(_BXpjR) e f[ߊcʱ[$b1WfcgֶqeG+s}A!HġmDWV-]rp5kinYGi/~lr۷QީRLD3pQp(Rf@ֱx-}FP,w gW'y5 =Rm{];S# sn` FHsx|DX'%y討\1JIpޓ̫\taJhm'u+{_#Mvgmefр^*# ZxKVx6EB-,A=o?PrM:TTZ7svǪ9 ƮͺsƚEloj{rB? ^1eϒ0Z #RN4=#n#*IˣvMYS3£k{;A{`~ w8A5}39Jc$}S]i eW\S/Qnu~+:oP%fc&o?ޤlYwb c=E,*S endstream endobj 49 0 obj <> stream xڭX6 yԿn(Vජĝ:R)ӎkqgر)D~tdN,i__̩ ޣ|fH1 9|7NJNqG(E/I*[ums X=>$H'*\fP- 7.6h_۲留YȋMuܐ¤nM#;q n))4:{)b4JY㰶̿ >|YowWF|;.NWF <@w zuT)$AӡY`}{b$y[FPKM(Ie'-eQ/ͮaEui ,/c%1y./L1] 1G&IW(:3r#\K隧PDve *Tfxa.7{zl9&^>bM;)n!ͺڬuĔu;a|>of>ܩH(,25`S@%]bTy<.]'pSerj{7QWքce.K`{vxW:`]Zoe?UͽG]nձmN%j}ɼ7/z9pG;eכYiYc1EN*7zLiz+Ё?ف+BEOzħMzOzA `.~}FC|kXW&vPV4Og6/0z4.u:!M'F1nYk؃ #)b-3s_0?i6!o4e|6=@2xjI cGg=PņZJY)a\yJϓt& *^mjAFM0Stmh[ S7Dba zg{@y>;m,J^VD7z8VC, P)v-Bwhz^+}i#hx˭6n`g_0^|zw^)0$&IjxeѾW%.mq@jDۙ }FM endstream endobj 52 0 obj <> stream xX6 %60H` T)M(>dyƞvŗCjpȎaM_s8i\LpDŽ~q_\' ߈)/nIL'$.rU\&q61&mp#)ޟ+W,}W3$pZ+GFB#ҸV.Ec*33pdތ//::h*R=EBħd.@^MB΀G,";sL2꠪UՏ]աeÅN"Yq̢Yqln9﹧~CԀ鼓ó}ŤE[}#Al C0w0g;`{=i' xc;|'wdѕ>= D$DI3wf5QV)Q;{˷~ANsІ}B䌴3VW7bNgKB*?Z(`^ic)2i>Zq/Ks *Z-+פa{Q p S5LV㰓p  6ǡkiM TbVPaℸ`T0ռl6FBhQe.Q,pl 㪱Mr|(q"½)GEj.m9Z?A[oe! mu \f: \rKTL7D$]y?fW=GAg!zJ҉J)梻`mjyj^dܲ:>mmM3;nyX73J +G8AcFuT]Vƛ6"Q%scV%&kk~'> stream xXˮ4 })sk,^Y749HGB?M8٩;_ .nG?Q?ܻ]GEۧ8tgaoWcG ¢rj!>XѮ2vq.8`2 xkS5>Άv{.8`ݣDZPŪ;TCё[W8\ր:M=̊ڛ%b="5":F_ÌpvBEW+&2Yvg^dOמ-Hcm/:>Ah3Ԍ5%wn,UVÓw (ɮ݊] J}l~##lr M{ 0z>XV}ij716\NR<>)pK<*}~y}1`仏<םɉʏ>j'mU\wΫrԚJJO[vnֳc/Y endstream endobj 58 0 obj <> stream xڭW6+$p`&@ZR܍iK x%܍lmLg?4?;۽i{$\c\i/]ohkހ]=zhG?Mq=*ps (U*ֳ;E&E6tIA1+6zyF-a_kO 0m3%q h")*BlNɰW+oNa-?k^ [GZTe.}aʈtoY/1:}8( *FN(JBkZLܯV1A*,K6r[SNSh 1B=_Fs 7LBkC9|y)eSFU?i -C+E&\tq@$!ЧSCc:JCRW@qpffpUPdMuo ,i*²?ݻ/u\E^ o"/e> stream xڝUˮ0 $PHivEsˊN4sJyr15@$G`?w[?ǯLctLc ގ9'HS&#zTi$ ѲLb!'zTā/sC >QC ;.āLt8.3@Dqj|6Q+ޱ; b2jBG!5!ֱ];Xf8cz J6fpi.$q\HtbG+ɅL+|7.IfFZꃽKnvx$YoYQܲx߲B$d/ԇbN,Z?HS_>ς|)z^ymʆ)6b*Lpxlݾ J}*{4"E\€2p$0HjW^FBKtsZN7=ɺ' 麿*sf%ʤi+(,]N(R7Lv󸊭g.;V)SbbG|l}Ժ`35izE0#>naٺcRJ\v0IaamD\ɝ[7{w Ukj;wRsw+$'*{;Z.Iwbi=W g<7 endstream endobj 65 0 obj <> stream xX;6+T 0\pw@w*P"ײ,y<Ǡ?=xw9AGEpT4n8h2*D?_:~j1OC,`Aoaze vDT,(((O*U}ػdg{ k'lhI8_=]nh}:0Nyx/N\8yÎ0q|y~|_ң,E}n-䋜l=BhDnjݡ¥t.qa͟9 yLT=m)rB UXs)AgXDS]c#9PʪMdq,fAp!{ *s a1gU֋jLv9ұɅfF*~dEזzD G4ȁNRir/Vd̜Y BfKbxm}FM^SmJ7jϽ׏Jy=Jy>~t~=C*iHЈACFr* #MӀ 2s f>dr,~?~JQi{)CfMU<=N0Ҳʼ, Ͽ2Wvc {ÎѺɧaqR_dx$m#)Hxlx?= *~>ZE\cEFio(2~lg}Z> $K2.jf]~[[bɢEu`ieE=۬EyM0 ?`c>0:x;xu4,Gz/XךPٮ~>X1!* cw ˝d&*vͫLlV _vOg1-r㵃p9_pelXV C2' l*;c5'hHwAE|lλt9Ajp#.bP<юeSHO]ÓD OK8gfAx endstream endobj 68 0 obj <> stream xڭX4yc;TuH쐺C,9+I \] _ןnݏn:D+<;< $|럷ߐxh#s0fKϝρDLi>aDO4pU$ߖRJh' q}?ߎm;\l:Qj_.C# O\'|Nө ;1*U*^ezHHÌEHrCf I]MC=/{썻VK5FXhgPCe^) qM"vK cUWQ{GC.Q:99ƲyiKr2Yf'Qxg0cI7~J$%gB_ r?Uṗ؆4)u!vca˅oчF5Jqd+=D<*)ޢ+jD+#Wef9od9jO 将Ʉl8rLd >dz|(x&q,Ν)O(51j \Hq]ބ35K]=)S?+ \!GZ( 07g*_2Ї=1]`|Z87/qpwвɮRiz2LHwb뙋9Rr}nI"Umkd&2jg4E\qҺء^[ 9HͯC-ʃKZqS8KDžcj|^O%˺Z5#7 Ywzk_ETI)Gj4sˎ"Laن_Y)kX8/"*3>jڿZ&Si:ZIQoM)Yq 6X:PkGIZj):`6IT ^)n~P=)?'޳ }Mt6:ކ^0E#ߩ(e*o.z٦ Xd*µw&kfcW34zH`yk?/ffUma &{VZBq(7縑O(fmv",Bbi/o>ff%=;"b8>P~t0v-.E<0?g$[_# endstream endobj 71 0 obj <> stream xڕW͎6 )~, z+[у=Hv,f ?Q;?"?twyu~ލa m p)?.+N`cQX#+0_L(xw5qk Ȼ>X}q|#tgb5Tf;1lWd_ =8Ll')xH|MҤ^P$(QW`\םEbl3Kk>ol^O` \}}KP(hG)W_< ךt2V3b)V1^mL@MʞAS+yS循g m5!v7}3MhY =D8g3+ \ugJڰI\uuZ:.U39v4Fl%0h-}9Wy77[,~,_K@Xܨ+tԙDL=Lǣ/,vx2dv1] _r0a6KueMKdWQJve3)dF& pfمgPխ{YSJ. 8O*E` m)3GO0CL}HN̩:Ɇgr.b\7L5eHiDŽZ0햦(4X(øbQdڿ:I37D_VaF#hjAHYRH+ 6(fUyOR{}~ڋ/Kmү7*P)sS=+A:CXcPYRܤ Rx#]zHOfpզI-s ffy2~lA6/V7lmBzgwQpיAb.X=F\M յ>Nم~)>gU;yˆLmsihjkfw#;Nr1Зrԧ1)Vװ[|iHlSj9#D3qT}@@a3_Fjk帥$MZ,AA|N)U4d63Ҿ2NW[=pOӸs<ۇ7_ 'OR\+VyjLJcIc1* hqU5y>͇ES Mֶ*sͅy>4 C7>w$7Kޚ~ӝ $9&=']ORt;͠ endstream endobj 74 0 obj <> stream x6W0\H ]BT)MsPV>v2ɹOΞ9ٓ7~Wq{*ŖCΧ1] S . 1;D~3vq͸]Ĉ^8[.Yp7p%̈́_Z,'M62ȽF Q)1>hL=ept mBJsƝT N#-LHkPIa<[ C-F\MԠ+œ k&SIbpFQԬޞ=}A&}A^PӱsBQM͍Yv0ӓHS* Z'w)EMsy&UlKn錕qSV/_CD0߉L!a|Sg"a{6 9C*5q}6bq_Ku zbŕ/VNĆZ_ l[7ֵ|Mūa<;{ԎW2%2vP+=;|E \ؔ]^f;5"mH $I;ĞGēU#i 3xdAG`[sΠT:WN+xT>e &)e+#FA1p[DhAUnj18Y'}cчWqT(I)O+sAFW5NfJ.0A:Lj]arp: " N@OZƓ{0u.bN+\f)z;k|mUGjÿ϶ endstream endobj 77 0 obj <> stream xXF fAl Lf8Ԓ#wr'?w܌+z |}7 L`ԽW>lY0!{L0 P0Č`'zGR<#UjM;!>},8zH=v<)-|G*E*2#%iUڤqkDpSmWT+-F@ݔwP=s 9C3g051exxq=xP#I5<8kj'=Nc|&wxDZI%?@Y;f1v-ݢ.4@5H Q ]xtM|k5wRA*@*4igF( ,DK1nD+W+`J`56-x S8MDw;.'Cc[3\.;M支"&ANYpY pfAqۣ89%p$.4U2VhJ4%$zYEZQ8j+l4*̍YL e>?_u6,zJ촺?|MH~2ue%.5:ʅm/o{ /]SU5uAfOkO[9`1 \hC)U(Ȥ%c+:DZQ gji0Ȉ?{ <;x~@ 00XrivX;nDlR0VAݶۺdlmhc?ZmBWx5Y褐!I-Z!)9(;worXFݯt`Lh5+uc.$mqޖv8)ňTol{Qw/72|j܅||y2> ;J~\-(QFM g5h"HmSMb̈́#ɦPx#y]*FT|x`Cnԩ~-O\Ka/2"o왛Q3oWN@I*GI9S_VWpt͢3Yұb!Ɏ=xKbq;ǷR5D&<_3L8$dxVf7Pc@n|}4@|vE endstream endobj 80 0 obj <> stream xV0   d+:8թC)IQ8NP+(çiT7UO tW]}}sa?/P9TڄXQ-WPi>)qs^ 8P'f7Z!}}Jѣd9b7>_n#pTp'MMl '7:c-otVU#b{TRR)=AC:jO&znq]$uaTc %qĤ͠Uq4Mup"1^un]C8kZ)$:UÌ\\"bJ$tv( Rm=ۃD*oRn(9uQ0uߐM mFlJ6>'bE B}Lj@nL%Jy(b|b+}QTd,i_+8}95L O>m.1RRAr:%)TWNgs P')xp f k8tm!idSGA5%(WPJp'n~q0z0e3@I yH R;ÌnhsԫIG $ R5X2=n؇qis'X B5Q-1;! #`?ǝ`5% \MkĖrpq} 5A+n3! #pC^0]Ӷ-H#,"R'T(&6t=bݧE~O;E?: endstream endobj 86 0 obj <> stream xڝYM4 +CZ ^ N/ qN9gv2h7Jڎ؏d'vt @߽M:Dod\}NΥLo￾chZ1v В gh8^O>Z荽h EqE>'t/LM"Z^{Դ>9z\"m[K)9ȼ838 p[x6|9{fJW Ȕ.Bu4e}œEޢf~)LĿo=-LE "ΩT\C;!_Hsq>ZW;ڠ<_ ;6 Y4Egp:_̲0~71kKwd^{hNjPT>\8( v) hgL'7YѩK6._ȶk ɘ`"(/> :i.Az>6e3;on./n/|LC1lY\[6q4޺ n/m/Kl|iۗڴ:p_9e,r(7xڊ-F&.! 0 < 5*[{ 4G ,L1,]mr cgqQ~B #Z$ϑpwͧrwYb݃&!u]L 5Zࣦ$}N}';Y;'@[wLqJ%Y,nU.YEK<='BIABb*&z,Nb_O9gh7 ˩m: e.99Yb<@)h%;Sr9(wv5북SOb1ќTu˿ ]r6A]ayejލR,ބk!r YEr@1VE~t/Uz:bKXE u~FaF-RcL.cOm􇪅UH-x=B)%0."ب@bu+ְ`PhbEƸNcQ]`9V4"Yd$͆? Rn#STI2GǗVfБ}G)LA&_K{6,kTic^G;UO)a=]#j=X$^`z0%o}~n_Gg[CUTHuw'37e)M}f[C<3TuηrXɈzTZ[ݹzbdVyˡ)BfL[;nG/ yS1}g)M)"D4 )xlj[A\DlW}D>rt/+l7J_._YƫFף~d@l ڕp`3A(\6SUNsH?ɣKke;h5߷ ؜+/ wmڧ9$?kbQgn2ewk٭S`Bä6@Х1cUǷuqKqq`A96/=+9`w{ۡݻ7 Ư]-I4GkKŨӃ}waۏU skO7^  f!O'%AQ zgDGKD%ҠGE=n3}(*ťPA-'uwN& Z2qp9"ʃwx4ZoK` / 7?m~; ; g .Nw.#\7[UE͋7p̳H5_=\$ӓeL/tibQ_;"r.$;1x~2\ endstream endobj 89 0 obj <> stream xڝY6 iI`It R3T)MH(;{qDQG{1^r~oRcvJsy;|u5F|"v>Msc5v,~"-4 nGzw 37x W$Ư'HeO,挳 v _K5+p&&2b`p5\h\me`6 &31kD.r]ZY]`O 7~:C[a"罛D$Xg C-4@sUwVlbA?C`9,EyVipZ3\ez@-)l!k!ZCYڥk1Oe5ˬ uf>(J;&^«yrŠa,GݰTֱPEP> &l 6;Ϡc\BoChCU,0tZ~K)<+~:? 7w햒#7֘ĵ|D@QJJ 2,:Z1K\n.ZT-jC$ܪΉfIh%+%vvJtH&f~g\D qfg1#T3Q65[8Yq-)*W:7=U|sDi^aJ%x MF^!2)i%6wlŇU9u3DodOqd 鹎N`R:P39QT䌔4aZ]" DnnA)mU~y22uWSo[vtq'jC$9r)P$(ev*_]qu7Ю [q,Zzb]64gkɋ¡֣Qq?Hgz[Q[f7Me Awu{ qEϡnI7\񈱒 & ܶ9 A%"sy 3cK'B>/ bA,"m"2Nrd<$qͫT@(?gy }FT{ܜHxmʹ~o|*Mc3z,t;fT(5*qdx捌1=Odbwa`L֑Y{W3AfQIo6RS _RKujR_]tEq F+rl@zak!L1ȳO`.VdGb_sJ#b%{.Po(!t}ע?t ~K&Sco\KQ gTI%z>^P@UXy,Yоp^gqZ3ݤYNͳG 8e46mpu;Eڹ\8ʙ:=)@qmHt魊ֲ0>5K9nv+q3TխȣAQ:$惽?C6upUMt+~g B;Ҫ;_E [1#П&n*,\hԝe NEtĺ929_$nfP++ F8Ljsx+Wϟ:K endstream endobj 92 0 obj <> stream xڽX6+p . (UFd<əÙlϠUMW2/qȣs::نdp}qVJOe2<݀ZA!g'3K =wbؙwS3G;"7w:|Sv}[ 6z|ZffYRvL_p mErxL{ /~bUȆHQ"s%N%W0lo}EU22~G GE]Ɣ OqTqS; 5a?ߙpݹ]}AձTF[ĥs1ѽ2:+cr6j*+h:E:ʰR(gJ3C0aEզ9 ?9pq`ж<6cȮhhBfх1W7.YfCLjO\CƉ9te𴂷p͌昙gzcnTӗܭq=1~Yn',eb: %^nry$tC]6e^e0]0J{"hyf3 [eu3Y=l~f1ȍs6ɟ*&er endstream endobj 95 0 obj <> stream xڝW6+M$E$@lJo2?p/AKY8s8gh_|?u>= a2cpqfLi?#±.SrD:̷ @8q̊/WrOzu•gE-RރG.'2IJZ̷p>XCEҚgpfXq~nTZSql1*Q=08J[UWPgk!|0@8fpɉFɼ킱j:R$* U;A `tu#i >_[Gz\ S^VDD̞Y]6>tzΘYP EĩjfX*yR~ZA|0NUlՆRǿMlØTKxټs֫ŸfE> ^a5,'`_K/YH!j¡9cE1x{р>ۍ7?3Nf7ޞ>!q}c~cI87Gg[#P(}j^WҬ|:Pm%v|hAp_V% $c^bؓH7f3N;.g^U9E9s%+;Mm.A7|K化ߕvG: қ_hjS~(Kٶ{"HG9)׵)J'/+s?^&ctj#E9vca߯]]dK}jA6e)YȕZ5O@p6V a*,*U">*~;/Փ? endstream endobj 181 0 obj <> stream x]K0 /6L)CJ]pRC{~bñ[zQ.%)Pz5&QDRlž2Pd"!Pd |&IĴM@(&A Y ifg{nȘB|~Ȧdo!\+,"\[,.,Nej q]J O#{EwUƥ1UN-P94+SMIer*sbSz=IJ|Y$C?~SUP.HTpiFz?xkZ~  endstream endobj 182 0 obj <> stream x]]k0$_ Z2l7viͱ(迟9Ǖ'yWf1M7Vnpn/Cc:sEH)RB I "Z͐9, "Lac-[֨"bTӹw,q:%9ђHD(%eD h$QF4w$%UPK"Sߙ$k|cL.WcBlY+=3kёh,ʹ]۹(~c= endstream endobj 183 0 obj <> stream x]n0y _vZTRV]$Ejl䐋}anc { 3a1 "]A:z:oH@*v0SaoD럟ߟ=z:<=V2- }$:m2"5|Uӧiow(.}B'<$rk\Kn쑂e4\,q苏sY(R:HLq 2T2IghCDA)3i9-~Lj@L\q|А$JLLVss M 㒣iɞ2eh*@Ȁ h Z3ɤ$"(HT>TMV-^B/6K\Q|}9HL 2ǝpi.ޏm̳2rg}zOy endstream endobj 184 0 obj <> stream x]ۊ0}\ML "@=Pާqj^tKM3G?)=lK١6s{`US7Su_G~ہQWZOXn0q"-ZEczp>^UW6)1R^ ^t[S2G`b{`vWYN"8Q$$Ds"I "3iHDʩ n{_!i ydRMؔgXRTýxH'\> stream x]PMk0WqK)~zd,-ucLF7P0ƃ1zH23y$97F{H= (.$zaYJKtp,pbBH.OQ=mv7P8o:{3X( | we{|fRHڌp.NŹ_xHYYFl$ $̈H./ X2Mj;–U.DC\HL;smxWo endstream endobj 187 0 obj <> stream xcd`aa`ddtrv445gi2?d~1g{I "_ Hu PX9(3=DA#YS\GR17(391O7$#57QOL-Tа())///K-/JQ(,PJ-N-*KMQp+QKMU]B9)槤d`t,<3##K|?{6?TΝ;{"Ǵ r]]6llnni$0c'vNgF 4WΛ3{Tu;{:9['h1wğ鿛ʛH6Oj.3s"_قSM^wTv9.> stream xګOD endstream endobj 191 0 obj <> stream x xE7^U}wH$dfrNC䀄$0$# $\\U@TTD[(fVfDG,֥M:P#%#H>,>FaT$+P~]R~dԥՒD#XP$ 9!C|.$9CJTЍ)1ء_3ܼ/ś%:avVW-l a_Bw ]&NȺnp/u?7n sʜY? eDVؔBno ooJ;]- FRF& #,WVII)Pmc8Eypߺq纵>|1ÖW{dTƼb4h@r\bX¢1S$&eU?%F[aD6lzՉPH &Rvz^lCbtF"~]^n/ǤwDY}WSNygoZ3,X^oDllc  j!m_xC!ohxCE"\.;/ _|1?w#} 7\)cYI_˪Lc3 Ӡ@>*4l`_QȊŒ39^BzNo}ƅͤQ6šӸL'o"5SjV`>z!ɠ+ࢸԃ"φ;@P 20$>=υש)'RD\M0 6¹pA 2ڤr ~(nf}Xÿ%edn3z3n0ʅrPWhaLQ6J*)J$\mQX`\N,R$xb`қ rrPŒ^:sUBŔZ1s5FFx\%}:y5Uo)'|Mxwf<*(UjCPCZr MPEQ^fpNt66akC /$f062i٣ouވmʯu9CZe&h 1ʀ*; e&^hBt5j[-3mָV{vjg=Oo'F!fy5V˫9ԁ.yW:4tK3n9`'6nn8rhEx^3G6~:e'-y~/fSS-O6~pӸ_*҃gV[ZFo<ɛZT$*y4fyK>U\XUd/0C22R\6R+JTj8ەg4L{A Rl/ќiNkc5D/İ|D v}(//pfo.N*n8 )=3×emOezfJlѮҊZ^qGK ݧTwη;bv̭Z e%܅)Y>hVI}ٛh2ҠLPe%PVDJ8e%dJBQҠFdjC$ )l ͷu#V:^@+ D^+}ZK } S>f4Uq~ 'F x:2ViR'}yKZaYt-VY8>*RVt:ܑw#m'qcq[huǭ$+f^-E؁ѥd˪߻PC ֦b; S[zĦ= ['!46?sA]o>++u9X/SVۄ~ ŇnpRLWo|>2+`5jB+0kBtZPt(&ƈN2 9hYuo |z~:GtNw0Gf'7~_ql|Yr8bkqLo4fOMkRͲےV=ˋL2/MMР@-'CxeT0%9Qs{BT|oqb"ꆌ^AJT’$w? mfy/4 ]Xsսu7{n'Բ死 ϯ>Y-yw|>-@5 ϩ+Џ=ƔPmM^.:.J,2'&Nf6ѭ1!sJTkr* 6.*-"ݒnEv/H./"äkenGK6eAY\؏Bϸu/c [3|xHQ,Y-W`7cŃ|Ssg$?y_ 1-ŘJ ̤tH6"mdb4E'f <*qh Kn1ϓ12X4|`f_*XIet hdD71n 5VI*=$7bn Nf* ux  xQCb' Cw1I$;'񾈽& %tJ>%FD|Pjh|ޚU߾bscdm{?W^{g^ f'6ew_yNMMvdܦqd32NmSŪjބt,9b dG16Mw&{ޱƊ8$7W^u*[:3$uVP2F['Mfdթb-etA9uȜjqwA y j#1pN1>pxՃrĕ,JDظDI x:ؙh"iK1h,P;"jV顓??Z3y75 GmѼPvgSj>$]һf]_,ywu-ov_oU:t럄 xዿA˕u~gCE[ܾY? 9ddT/?K[# <K"im#r 8 op2j=v% îf{%gxYq2+H q(@ǜ' Ix\ft2 !@lqD({^tBS99I1!rQآ9|skx֓sYxΜ:}NIJ;%3cvJ53RtiI5]3=j7edu(--L`1S)oz0;q<ȴ "d+2~)|͍;_f-7*_V6.~jB|vj9-Fo s *>wf/ fFqS8%*u<%mKD @9c,G]Ј6<:IZFwMsν*l}C|#YC6ݍzY?=89ksפO:o0|e!հe!@,4bWVB3ʢP|bёawPo&;sj@7~uź2y G簔ʁR"T"3P jhx?-vO)2vG6n;zp pZDјv$j [ȒԒyH,u?fN$<3~^V͍28areݨfdgzdQ":>j)$8@kh?]FOh%r)'rZPժ(F/Y-vF{pA^BK\n-ƄM᠋0ky p 3[gXGh# 88$~IN.Y,,c"-c `{X,j ,B(źI`\-酲J\8$ H"Df̿%]{%Ӯ<}$a4VS0fW0TĵFuGmNUp\>|Fbج#.wQZ#f?RC쪅2f{E )DH;E$ʰ dɹMT7러sS{߳3sʝ{˃b¯2a:axms#/ՌiUrMQ\քl 9NOwKXssJ'%q˕)VzUk.+r9=9ʾȕzd׊3zh(),^AK) TQA jYp )NjRbPpCBrN  .;[M&V1^Y,iLC0N$D{J:Xxk9?? QhEftͪ:UU2$M)b:506tc2(U8m28918iQJZvT a|r#8ɹ y}]Q8KCweo,gWo޹l7L7eu}}źljwfd8qTs&9:!ٛu>}RG:>ߏBc sn_*VؘqZZ<+K 6DxqVMTo$ā$E&$Ȭ͖ iT}ˣTPEmo{PN~kuL^*_Q\`?Vq#W0*0̕FV157|ةZ {UzT.5Hqjp;ƭkb_׀0bd\ r3n]REe-$Y9˼F upLnҊw_=_4ռȚ;Yc[lb=N1UPjȴw[#nI׺&9't:2&s#Htn`ו=޴zpp w lV{j7}z#"yq(>7>,d(ёb"?L3\t_|[!%91*S)O/dJ$ыqrJB_7Ue2CIr1HXX%h:uuq!htU1C棏zÏܶQ) EPby|7{7z I| s8وUձ`c3[bvC`3]/}vt1smlrU]RgiAK''Xߊ'ûRR`0RxC)$Vn~DȊdYTa;j,&wNzmNOȸI翢CT3]1%.>pE͈,$.-!+JMLɄLS\ީ9BSۙcXk+R<Zv̩ZJD+VBqTYe.l@_޿ EEz0OuoG(]\Sz7꿌5߱)WnZ_0*^=w'mj5&q+tYZS8.>̙Uɷ^Q2˛>\vf U(lOW0VPrD)16[ 5qqH*5VTB`dC3Xi~Ήz/DȤF ~to VX-5&dvd2˨.8V8|@5$82{\N|$9kP1rM(gD1ȭ1#S^D ] D룧 >1ؠjk|zpuu6L,1YDt>;dT&:aX+qpiOGU RI;gvNq_NQz/hꏢǮ9X; B%X E}tzjEiV "%G4J%IL#B V3`L/Bi![ _DK>*WRnWI,N!l7)N"72xY lRiTAU5J EE\\'τ=.Uڏ6PwSd9x۠2Hl\2,)Oi?rŲQet[&&Z`4HZy7l3mnnܭF@DYKD=R)geb3E@YiK9^I/% qH q4-2%5^٪YDC ĹO6&9iD@ÊĚ!l>)BXP  %]~)v\ϏZaY0*+&0 8$!Xii(D3Ha(*3p- Er^{R#(ʜG"s4n}=}'_J_` :+oQEDžt38+TIsKlA\UDgdP uPnPkPa'+ agtV?)"nN|R1'Ep*E'֏ϦBH7oɮG}Gw}oے _wU_w~7^u?9Ϝ?(]׭TzLID.0 A0qB3YHG)@= Vm)JK鎴2to[$eOSV K^qIM?`6 >9H D,-k!#ldhp+7"'#fWqf^21dyCOW@E?e2ZBflq<_MDsiǹb4Xl[QJH +#~nZ'ȁ#SG=h\fUf\HEyfJ`2ډN{.I:˴^)FE*|m\Q |,/mq%d(\@!?6F# s#HUk(LŜJj+4NgUi)_F)?^& ԋq F^"w(;Y"Dd&p-ƶx : KA s/qqAy6"^*>s5scmS&^|}?o ~EOvON.|Pɓ;8tr,#_Jsb\Cv{q1R㲳k+:1^f ! QTG N5e=sUY\?7绱dftO|maVGWS=+ЫiWϙHQYYԌNpzh7hYZlj]WU;xHhd!%G=e4JD)!Z"AC:OBDSR YU.YU%CX,.L /NƜ:7*g) v+8耩0Ypss@Spʔy r@O@9u6dxixP*SHI(|'CѨw,3t-qx(&rEkb@D_CfFd$\* R!|}-))J5S';<1-p3s*u[}Ʈu{,q֦kWgQ}gF k$^GߓH~V5$ăritd ^xy!OEXpIb]5N|'pM`>q 4 c"ጜDI9KMۍ ǨќHK j4+-Qu [1DbGޅ $ \|FQEE##Gך/lBsMÙ/yZMsĺ?TO{/,5s{qM] Ɩ;?&DEW LIA͚\z]c:-zBxZ si_Q$&7nB>!-N.L9  ĐmPiPtYGO R4ُ% S-KI_ szShHO;T1VvX:hш`[,)\BӟуKF&ދcsYp(Q E8EjQ.!e^6o9 LrêW**ϿIU3&Lxru?NӆA5&|q1ᓹ] r?;iZu5aw~~ޤmub3ɛ̏o,~r(3eR_oXoBrj5AE[A+j`:u*zQM Y1l.q%0G?܊Oz - +k8`.TRx fl&a_t_>A>&#@ftu*ߩ[|]`zƂD q7XX3 lYb: (ۦXWUbP!rg̍玪<|Ux]G/>_!|mbњ %+VziT G_\wV_9^ޱ0XY+i)+/<:)D?t^4cD懧`7nn;QJ ܌;U6[R&X"5"oڀcZ%@{U!%o.yUu4%98pe`̪WδjBBR\aBqRYuWyӰsuULY/3_L(5`Ÿ5S3P->ΗRs¬uEn,TΏLo6++PdT2ZnEWJ>Ng$ϊ OfdxcŭIC*QM7CiA uqXL+{.C~YO45f / ^tVFx ˽0/uw1 h}:a{pwvV55Pz[g.M~偆jK (0ngǕҘA~!|ee՜g[>;|:J/Š$RݕEtD,>RڂcǢX6;% *##$vʲķ,eYn 8cNMqK7v~{Wo|SG_e]9]i9i}Y-N:_8=Rg['(7uь+a?$'gƏͥExwJmIXUb_ش6Nb.n5( 웠1*f()Y*w䈒X XcjjzΡӏBԄBDcOm2j4ZB1'2/IhJ#"A!!gE's9!ߥRr0{~x(/ܼkgX007+*φS ,V =j~d6f on۬~ܣU#+V눍FV<>^G`q Q 'RYȚ38Z)wlmRӜҜ`/.Y:uf,Tܰ@ය@ ?'*q1@ q)әDN,B|qfY72\tɠJi5O֎ɤv٧h y%8dnG#>?3L',@^NU=T?qbZŬQ4xŐbĀN:O|=\"(Dv* 1^OC( !d>~wY0+jI(*97Qz> [[kU:m iEKn DA,D$ cT??m{"o,2nk~O=H=s\ eGvqSIJbX _JZVF'dup+_?3Yz?T4+N#`n ev>ma?cx7iC0M˪əz_Ivథo Xg ǘ,=Y^{O"]W8=~,X^͒/:+V'eD捜2O&S*yY7+w+1C"TC!U7qn{~ J\rBouD˦KU4AY9Xf(k]R18}׬'X3,yn^;l:7"lb>IN-%m|i sFP+Ze2ʲg4aQA6㝭<3 ߑFSD}ץU|&K!VR3߅:)j?#_)vuK+&κB;"I4KPR\cۆl69ha&56dz[vn#IמPިdE^Fu\xtqۖ DOpo"՚ MI2/L<"Sہe797rY,B E1VnS)mߚNJ{i nӆQcHKĆ;-Eۡ}LͿ\[# yfp2mEl s>qh{i^lz]H9tk^C/zP!W).,ڥ+ʡHCnN3C"S4|f)qw vJXR[nkX>SX}%;q |o!<`t *:#Pq"O*k9KEyL~ n4e'old^V9t]wf)(Ě0;hs WEs$:4 իdZf:NSYe&E`ѹ%z[rf㮛n[<׃C}+~¿Po[ᄑS`~ B8wTyJy4ߒX(ycߗdUk( pCy/f1|1ViaaѾ`TJb"/-ywG<$x!F\WE~#aGpjФĘĮIOpdN+GP.&D)ĶD@S' k0߆TL?rUY*9]ۅfMRrGAd=HD9*҇{K~H)#*% DK%A7c"cd;. MOn׷s99: xg"`;W}1Nx=8SV 0+{e FM.a&yo10{f [Ge|GChbH+Gi c Hр(F s88H@yN,K| *{q;񹈤 }rn!1 % $p翟~g8 #6Qr8!Ph #a[:b Ѳ_2uڥ#ϊ[G]Mdg?2lN! ckKgbKǃ.@&CA&l`l*g@Ny7 La+EK^Env3lJʨuZFod21;^Iʤ orex);#OnM\ݶ(S/\|l*oIxL}P?A9Zvv'D<Fwhv÷4oMLoފmmËc~6皗0e~ⴤX>^e=n=nBVmMZ6+{{}S׎;i9MmG?N56ak%9$}+aLb ƐA@~R <=/z`?QM#)|]4M54`}4LNj)\JӬ]U b%h5F8@4Mp_4Mf䈦YMKLT.etzn1i~YLkH]1ioELI9Y'ibB"{2txOvJ1 3l4St+IZɿNLSL]9}vgG{_agv~~sK{9Kt/i}Es…s:;{;,h\~E{}ܥ ۗ>WwF ׽ g3eM#d:۝}K;:/Ysyd E,ĩY`TNߦ>|tAmP u;OS ЃN  w,&[.k Nm[wUUoRoVoq\ݴf oܲv-9Mzc s\"</# ̂`fiG0à ǐOtH; v,"&6km5?ͧ\JkcaliZ,T>_PvȎT;83`vti#]C]G?<|9UzɅ\e81&i  8BzG>菑Xz: -}- endstream endobj 194 0 obj <> stream xګOCD< endstream endobj 195 0 obj <> stream x{y|U;t'UWn IHBXb*aq}(8qy#l>gF8H[] aʽuRs!-@4Jgw#Ԝu}aF[!}ѽ| =*X:FB|u"!Pa51P^ eo皾.]-?RP !fMˍl"ՊP~7׶i_P!uqwO{4coB^8]).,0>CY*fbvIZQDp_XGE rV1"a<|1Ccwam Ok\WoP8}Y*y·xA܊ .<#,(1`c3Hs9? dvA9& Gg^Qt?G8'< }N: }-}Ux^𝔞I-~\wRs ʌO6EOWo_}t8A8H?Huz`A~^nNvVfFJZ/%9)1!sBl刴۬hX0J!Gi(t iJ9r7~!eW亢sE9v-5d2V̀rؙݓ6Yq!^W\ .Xꙡ'hYOikY k!:𱌤N1rSvu6Co]ե;g!3XSC>|C =!/֟qNm&DzŲ -(=Ut)K *G[xX˒,#mr!,@ra{?3zcLuj}Zu֨vim5~mH[lwkiM?2]act_nj׹1Vc7ttN Y\g?nv\tgGm_f -~ 3d>Yۍ~_j5f{YF4m1lF'ع{kq*'ۜ$tG:ӟ IBF=j 'F33A9G~\"G&nHK䁆xL(tM#28#+%faBNό~ ';|g˩,l9[iZ'jK̎ȗn: SsM3&l0$~ylG6Bk^ʧɢjJ\Mi"Q[n6GQ}}V+˥:b6"QUjUXj :.=:9^JeM^=p3JؓX5vV<-PzY`!~AziiuJvԉ!sCF!6+(2NRUj qFd"Z4 iam:#g*qXv`7 FgicR%ވo0S43h~R܅1M##x 7& elC11s[`rp?9NEЇ]R!:@w74?@2ɝ6i1.BY ЖMa}vnǠZS&ɭ7eM3M Ml}6:S>GcmtbW9#\q3jvun"N!9`vnh7e_,2As bIuw/tm:nZuLl4H7U]5W %}6iGm0znNMr`Ag:Lv1n'P[hȞ]\-,+jڶx/YR{YBzzAꨄ*a@ ;3bFGӑD V#Y 6E}ӵ)kʛhwMaæ ~f̉څuUm¿O1TT`ލ)S<+ny| sۛe5oꡞNnZ@i̞cfNi0X1[iyFnZ1.ug$g^rϜ| ؓR4Hzsyz??/7u|~#NUzZq2E:raD>i-osiQjK>⟴4.Ll.e7mg&ĀKN^=ĬwH3'SnzzuԜz"yt67'LK;tܜY|/Ijћ ʼnEhx Jj03{8FmŨUFuPݯdKJ[)1.T1UtSE{f -~8GNEE-P̧& N蠠Fۃq>U.*W-y/N UPKx?1&d<)V4A;KH DF)> *Wm~F>L>_״|`#N[ڋS|~p?eo&>Kp%1ة.gk:Ћ3t\VаOrgI;zs+ћ1U6JxgV]'؅ K߯_'pQP֘Gz l$ ݔ:9v~EM@&1?da 3aYIvB4M<|6ٮ EkUA3{FUzNg#ėF V'\ k5˂*e^{-bP" ,7ۅ>U_MُT|=^ÉOY|Ъ J'cw?4~| E׏L Fg >l.X@|)k;chuMRce/VTeuv)9LQWVnvk#wy%ٿ/*Rw@ D0cșoDQINQ4iLInzCl1ȂhqXcY#qFG txl z6o h6ym˄^݆?kgMnQ<[,=7RziN#}_i~1>L??0zYs={)Q- jAO ?~ڮXt [AlƚZIي??SN3}7%HrHo&"Gtt>:zZ>"p Ht<hdf1˜g4n֗ "OkTQcd.5vTwh;a[@0e]NmrRy9U7۩YgRHğ~֖|aڑ .r.j:qyAMi8/v9t0ưI mx%#Lb+۵Zb5G¼03Yab펥T {2|"KjB0 )!qK H )|L[#5K%gms2 )}[Mmiiqr}t}RJzsjQF5DKnQQ0@WaY,w0c;<4M)Q4&7VȉGdbAl0sYZޡiOb=|$+.l!ʽ..#?6H;;΀X"Ru:DOO(0k鮋{d +g0>/O-ெt:.p2fjzN g(n#D`6'0`60nFc~1^zPGv#"or *yi2{&| /!yO oJ|ᯏy /IOE}E V,id,[/yٴ;ݻwo\=k*gNL^3Gc 6kMz-< %2r`AF^. NyY5MQĸq3%A`A&0:OUrHj9+tTzU7nF iS!r 3v ȗ܁V J1A]+3(.Pb `?(Fh8Y`Y@}4ALLlU>L87.+iWjQ:WGiO׬ⶔmsp^ڷegTÖshڹeNkU*R~S_ϝ=/%%?>taG3RhA9|J2#X=V ".^r>KQ焬˗ ?Ux9. 'j֓=*jsa#;hV^8/P!O/v4h%t3`yD 31SFțg>?e]SfI"鮅{M%vz2ǟܛ2.$`4`oJp Ay:';<&0 wH[W' j f "4Hi`TL&$>[Kɨ0ߎ7 K<_<( utvO}b 2Y #'sٷjNJX3N+̏GK#98dWd%)fҍM*e^/}.ӯ_WQwb[kkF|"ΦFǰ4XU/.~fduؚ?VJRa觖aTZVeTP߅^Cٗ!գl5go49( | _lk: i7:H@pu~X\.9Uг d/h GΧب}!bėea{_r<Q&(?:@ }}b稞4$F&bI< |4|?τ'7őARffu:OcfWf0wOV~Au6Nܫի52kCZvZI :CTDa= q ?S&|$aaD *'"أQgbJ'v^MRf+0R<fmT` WyG? 314^S`YaV>fP4ez(0#<ԫp3ȁɰ uA2,- Q+0CFTØ:fM9T`-N˰E;袓eX fz3(#қ梷pC ~D8(0]c Ja 0a|lPoef*0L L鍒?s2$bW`3"1W`˰@l {ؙ bke8Mߥd>oÀ'{ )0uLW&ds 焺 -b6E|X((hKzzZVt"N[ZYWimY޶emm/*"%^x[&z$O1!sJVR}V-b_OK[UbWǵуP}-gjh-$>士]j逖õ8}W*iE9ȏ]粶:uC{S{Mƒ0 0^(hA]R`uAMVMih5"` -Rj'j5ho3^Ex^en1F7q@Aʹ/B-,C‡6h_ ߅{[):\ouWLyޫzח̿w>5zƑ/qkgf[a,uh½ Wq>l G Sㅻan ߹7Jط'^L&ZWk5NOg0:i$d_BDcOF,E& س4;$tvLvY­a¶AuPaw4tSbߏ0-aKla7Ì!U7wF[Rs Q݂Ŝ"R|IɆo!! BwDEmHb&NSk:Wh!L錆8*HДPG tA9 4T"`(T tJ@*: ̕nzȂY;=$1 Wo_oocj2{[c1[Byf#C{f`cN.[']5yw endstream endobj 197 0 obj <> stream xګ?b~ endstream endobj 198 0 obj <> stream x|yxU轵It5dk%!H i $1@Ё \P@QQA@t|?uAνU :~Gunܳ[FQ#bQ؂LTPs Ҳ I8*f^~Ɋ{!WZ4"zUE\+1gWA|/<'Tn;EȀmͪ- o3Bg3LN"4~/<0;U}x(,w6*gԜax. ]nYzQƠ!HD!-DHQBğϢ?N9(0JQZ|n4 ]kX)&a7G;ѝ{~#h=30O9h%կ1h.F@: Ns%#rttl4Ch-`RBhҼayuƪvu1FzprmE;*i z N+aF#C?4 MG+T[g#B:5`+HݭWR94 G%\rpoQ @7$+**P0~\1G1m[N}  XXiN~ox@& 4d@Non&y) L(C KOR`XPhZ. n.A+QEC]QѴWBNSP2W`\l}1<4tv )Ki**JwBCP"D( Gʄ&ݦ "7Ĝ yi@DPxt@ U'ji-"Emhw!bҏDH&xQ#jEcd05/CE6b>5VƍW=D7@N.zр`@f[ʉj* eC.` Ql DT.P18 &I@^E ؅ax#>?A%7MoB`T,-"p5 *fXPio[mo_kHZVo/b em1% Г6BjH5^F! Q|k- JB-cMj*]%XWmSEUTWU*Ri,L'dԻR -A}@7 `W@W{.Zև/.X3= K"]Y i5 }ҾAw'I(j$s "1p## ,q)>۵e \?NV F-bZB`qmqB`&0 ңSZ.yyf*[#BuzK)VzL38s lZ&E6 e#!{w*.tBrK\.*Ӡ2DBHkъ|m'mڨjUxʃiSpEBXHN  bH;@V'ɩLV>YA'<Ӓ,vyW/4Jswn[3^p5hy 0;\+M8j{xŴU/Y~p,4GޔLjA~h1xb߀];k4r #*uz=ǂ%Q:yLo:w UT1u'4e|zYBst,ǩ"7?d۬&9貱s>y;_?ړC4w0wWQT~f &1[둁r9eF8"Z=:uzUn=֐V"\ 6;U1_2' cnޭ>}x6lŚ^җGm2韽ް1c_0ӊ~~;ų&qO^8D-c0!E$vhU{7HEx)&=iz%+=) ham)c(u.ބAZf^ :#KƾJ`j0mȘ``?0ݢR_GJKYNW/Xg=EqC6l?7z6k;¯M^ѽ0v,nEFy\=>c_ dcbX iլ3bc:y"0olty$?ƶ'>rcE|s'ypöKS c OSd)HD\XF L&thPa6 Z լNe(֝⟁*.ЇPtX~mӰqIQRyjZZ@sA @]*wBWJdf6fm6ߥ լ6As@MHG%<IJ;M@ׄ>.pY`RpV0sR'rҊ/'`NJ+O\;~}6:uKO|׿|1 珜gKߪa3-5=qu?bdYX'YXRNJysXyŤde De5SI?ڔXcU 'nK#g.I]$-&|~Y@p7L(a5-?2sZn+cYN8|\0?!y=i)2WN.lƍڸni  #]~߯Gnk@/w^L\[ܑPfajLL&ѳ`JͰx/klɝCm]|p,ֿs_1OnacF=gB?x7$8= ?֊=^^:dS,%g#sRzۭubf%Z"=G6п^zMߋ7A/A(]DF|iS:`Spw{ t JmwYF$^LqxB,vZ=굌=cf ?;cXʺe)/i/T |4?=Bizg1/i;Oَ.YZ{mCi/[ҚܢIeOx|c3g/a}}FT 3,(O~0 g61gJB~` ~f:U dI3IKKb3kjy{X/|e!g3~yPZz;?ވ!m+ɛz vQP,AH F5-_jFޠ[_GvȑC@4Vwt;Զ<紜a=J`X'\y4jh466vhDɚgh\f$2@V Iv.};V>cm3-瑿+FRInI;kk"#JY"f!Q ֤me`l@6l Nخxx(VU8pwuHYqMl4d_{_ǣu?KJWg#WWyWZ0NAD?ϩ50*VDɫ%tSm)o="d^?&Ž↷L8SڣoSM/<!sB0?-q]$P ď2A\+MRYUT"9#C#s<!g:MKF.HZM< .8IT%~^oMԺpqZG2º@1GsTE#Ơ( zcbmdA5nB6!Ss>JLk 2.Εk .@*IҮO@&fqIJV<%O1:\#A|F+/V[6 stRohts ժ,ugلE&Yq}Rj8ՔGLJ8&lra̓N&E#&?duXHd}8, 䭣=jstЪ@v9ҥodFͼ:q?/sC+n^>*}!}y8ʐF r7?Og$%mXT%Z;WgnvL%?qOHWQY{HtWGqq&pаJ3?t9q6<>kq"&ލ?홳 VS\ OVuA&Ye$؝&Czv:n,1DP H&vRqʲNxrx2jjۼׯ^_.dO?uݾ+ܐg}֟s2u.+ dTcvyԣX!EΫF0z*&S;9t:Jeubv?o_='z^z˥KKoᙼ8΅Fw)NXE}EGdb "r1!by.?䂈؉В4oOzIm]0CHbի{GygM{yCjT۵Rύ JCeYZ՗5;Cnp29:?$pqĠeMm5oG}~5+pr}**hy6)?3/ơl/V=z߿龕 …s1#O͘Y /Ww7w^uPȯ27ޡw:ڜ(::[{A+j 9eVGz?+-m龖4Њky`VL-أOopxʛz]AH4@Jq,puɝ]5dG Y~Fzp5k5<)ACV-Y *ellͬyNԷ9MϢ*z᝱;zmIfF>wXKctYY!v:- Z9>d:310 lۧaHAh!qzi'sR-9͈z9|#+B(M䝉IIԱ.w;9c5wvy8ΰ_9rkKY K[v$2ɮdH}xFvXn1}Z XQt X{' 0p7Z+73A]TLת1EL¹;3 ͼ='wlg ^(rji{";w/9=(Mt[]zbbAa`U7cϸ5j7fXm"N{S-i { d? " y'ZX5č]Nwo++ylݺu[0^)7pk}H\>@8 ,Bk4OqW; d.uFktO'4`39Flu3G^֫/]Z0VȠKb%[l4t{V a_gYw7J̓ODZҗkZƎ2uFf瀎>NhcV2:5`*WU”i x7T 2~6&l;(nrAzJ2:Ơ2$ySJ1}o} = ށdxYeNQ8NsulbUY'FQ{cYIhf~~ ЭAr_luS L v3l@ھ;:?پ%[ExfU׀v۲NiR%c7٧ xITR"%{):sʶ:) [Z!^9J{oJ2=Tn={0؟k̾צ51&ŪNI-:3S`gv IcWۤ'Xgn &闫.Z^am߸ts%|wM3-WFY6!اQ_ 5iw4W4h,Z"ie} & :5=;wR#%ғvdXxɃO.gT./@~\rJ~A.]̪;g?x6̐Z0c&1G^ sA|w-g؟! 4'v⳯'YZ ,'$jq8X7ͻֻWee^;ۮ7o"ݲ !L^',%w;Mdkl̟.NHc4iUh&.ab6ɫY)mt?Sھ|'jmmv¦c4lNBBqdW牉1D&{t5MPĬ5507 SGqfvO\$!UI{!1E] eϚYyےu\GY\Di`?(_7l्fN[zce%!CTy{T7⟶w~2V'>1y}pgRaBebl|4A?n٪G*)ȋ <3YvCGGcо ԊCĴJevԥ!ᄁ1@Y\! c6[9 o;M44S"`&پ3v%qe+yvJB%}>Q`=CzVsD4^tƙ ٙ?u-d1ؼ޸!!/+"/~^R:D~l&@dC6ݴzh>{oj֗o6]9sgOgNzkGүXC^J ݷq%}oMr~C̐eɷS*K<˚tɡ3TXϸPll!۩p vYO7ܹx'JT7o3F+sV7^z 4,ZQOI'&0;&beTjLH p7\lS~k'p%Uqsx;)&pFl1Z:=oi4vl ZN0@AXsT 1/Fmv5^O(u/7&[IW|F|6O r}QAv\ARy]nw>B©9͘9dK3c٭*% 794b6so,ӯGhʛNlM> Z@TdU`VX0.V&&mASM4?b8:STZi6[ttfJ6z8IhDYP8H0X.!M&$w#hA3YتӳNgL B6@&\tr|ȡWƼq[sBꕓo6ܱr#KaLݭa9FW2*oM&ֱFjmf\ n X {Ԭ: jTV\8DX诧̮WC#n ]k buМ#Kb#֌Da:ё/7 yW+'\8 77HelNp( ZyHXUC.6h y3Hy鯿A6텹=mV`ET5ZɪZvov?5%iii.5[ɓ`)2ۭȍ1b83gpp`xy'x;>#?Ī\B%ߖ}'Cv<޶>a o5arkۋ]]{B~`;,}f9bi].|I ;񧓯bwB+%SZE=C![t2<:J2yB:~7 n,bSσjw0FZhE)Yjƪٍ6K [y/^c*sN8'o37@+~ DBe @meլmp`=j"+YmR;'iMAY}Ă9{!͐3KnXSa;=kl چ|X̰1 -1jZ['2&tzHtLsq]?[~ôNoN}+4o{Hߋ~z}μճ;v UU5YuSwYzW_[bZ.uwVRW`uEFeySׁ]uXpPh`-/͇ŭ,}ݫbcfǷp/^r3`{?썹6M:m*x-;D%EuykRLJo14e̟4Kǫ{x3L7K&"SMm9av3`b!J!7,x{Ssb#w˴q-{ǽݜ;;-6Zg% lJD~F *GWQcW1lNE2ZX^jQ&L/?jBZ Z4]zTF_ѳ8F1gѭqu:n=r-Tj+o:ߌHjtk <':CQ \2|fd4IbZ˹E[ǭqu:?ڶgK+s\FP|yul[ɾ6N9oJǕ2kB&ƥhU`O*e-2?(eQal@ZR6,mn&%sZxC"e k2L8K)79Ra-甲 ៕$*e nRZ~u̗64l@S4V&[ Z*P9 sJeաZupD(. ^> ha ykQ JE:g˄x<:'2 QP\(7ں3ne݅taXmYpCumMn20E^0 Mhzd (@s`aW̘3+ A(Vr:z}P^%)biH{LZ\YTQ!3S3R~ߙ?Q *& y6ȝPW*#3WAE/-J.W>Ih@^~XX ˨,sqgrzA9׶ĭa>\^1;\P[YՑz S RpCEM)&[YY]VA+*й X?sN}u@ Vrbs)F9")h[!74TDH!_f,5JQ Ur2NI4F=t[elX*osUQ `PS[¶ʛ(kTPd oςsbf-e5ZQ2}+δżR:[Ot(7z*(Vv:ExUQaSQPDb Ҳ td- e'M3J3(sPli]m;IY $yųKTBejzzWR4(Pk)Fp|%Ρ\_P.L[Ae΃POP!s"5=yUeU¼pD(TϨ!@k @MM\P0"RU]3Ck"BRBh 7s1,Z0{emVtNݦOFQ'UX\Ef f?A8$j / ցCOgfL.Us]xjR*% h j'au]C$5R=+~F\h W@>\wǢ N@wpvx&,{ JŽ.^Dy8Fpɵ0.jkӠHRHR8u?Fqw[Qn 5& `y <g|-nr{f~۽߲W^aN\ۮ`ߕ+WXtY.E/x >E,^uv!w;_` 1@ El;ZA6 i aYNU,`[}ş iS)~VڢIX8~qxq|wI;6X<?\w0OwCX8Px0z18+/QLٝk2Q6m̶3'y&m=feb..Va8K閺-#|&7M\vɚ}c߶AZ S8GV{3oܻFV%#WkސaEl/cQ`?{w~N_}1cZZa-K{\aMf%>վiYqŞk9 =Jm=BR-UK|+GX~oG.Öl}x,.r#Zb0&)TBpJ:zriArMM}2홶B\& 93Y>0rɟm&„+Z1⸬rqrGQ]|#s|WG?byp ko.>{%in,te: \h42i+[K̜ٜ̋fk557E`$6an߄խGFQ"X@~qQT8hkBx 22YP--H PtBCHÜJ1RRNh \(D"J 97%iHB>5D0 pQ( OHiZ$Mi0fȸ6-"ciHw:B endstream endobj 201 0 obj <> stream xګOCD< endstream endobj 202 0 obj <> stream x|y|EUWsg&dt&$$dpɅ%I@W$b! &"2( 7suU\5d{3 IDW|즻_WU;0BH6!+/Nj!P3is/! مTsq-[+v!E(  ~!x`1R/>qu+V8xe-|c*;myVn"SФlh\Ѹ|; !qg&ċ0Ge?E8I^BnGߩY±waۥ9# Cϫ4Pp[Djx)<P# \`]A㗼 bF/:AB)S`t+?ehE'=.(A;-h7[3B#y5}?-Gm ]n@SvAczToftZZ2ѵhFѧ، {8&)enq<=9e$|'vABk אJ>MEB_A~77'ۓNOKMINJt%HNG|\=&fDEMF^ըEs,a0X[VR{(Zp%I nj$?2hdPQCS(2P*)/>9# 6_ ~i9]O@pWwҨK\% ԙZ(hzO bJ0LR= @JMPc>_sd5ë<6HC%A]gs@n CǷ_sĈ5M F!DWS9ѣa3˕Je]Te*.XbImt0,L.Nٚvngk%zA%͓),%74~-qn߱@5JeA1eMƦKrrA3kAtupa:)$i%cR{HC% ((tL4Mӂ1h1Hu:TK2Ȓp d7dar|{#湜FC[Wj#ʯ B=iEv)njIaiv@ orRFյ5rt5С+5$01بOI$j;h6M ;<HA `MtZifCFߨ*yh1-. `OT/%ԅ(N(vHNuo%tW{>i@wbZg!+9vj\=<уy`P\r˃k< =JM gp&8|wQyI9dKRD0nW*;oJD^G`D&,&^L\ҞӖ+feefv\$rIflt ZP\ }Zm\q2[5c yFC '3 8>Hf/tԯ[0讏z~;a|Z7.'KR"y!J,D-M[eu[۵s\lLƦ-M-9-[pߍn;eIMh)Pwu~@NL`y=qk1eN{G %WvՄAw1Hш,Rq\/Dd)gj5 -L'2:Y~8/~ Z?e{Ng/E bQ@0<"oNFXI=eeDl2SfHf>"x5t3ws0ON?\ mxs_BH*YWETJ#*s}lʴNmi' |dz ˛:БD7}ƯPy}Nv=du9QDW \`Kv%DEZeUso[=EZ=#םjK[@q㸧V,qyAq%$&0CN$;uEbyfqZ>ۻqֻWE/d~JI.8yR>\ʻ$ieELleuԱBMd3t>;jWYv3{:˹ɨ4]fo,{e+Z^Q-b&I2Dk jV,B4洘--/WD6 WJ F$8D ɆkOWG=sݺJMZnՄ =qOxUgčcF x<ցMP˩@3-Վ%&G5BGQ['ⷈ_3uf iers?8xNySӧ\f/^UWP nP rHhv6(_Ful3aZ 1k-1%?2tE^Cnӟ[PWTozz]-= G!ǡ}dDŲ,%Fdƌ%El 1l%W"Z+cV˸SRi댉k5`A,0pz/ڬT4ddCb Q]iX,(15ʭpJ}/(8kCΓAb s;}BZ:r{sԢf㼦o#P g|,&ќuclEқ&qamqsli WR(LN f_1[7zX>IKJ cOE&?@S+NROLn 1*pc#YdCg{M{ͮ?vW9[.>>xޥoۼVϹy[CrK '-|i6cHze=oP0ѥ,>ݑ<"Ftꩊ3^*3; KV#L H9!-Do` !n?'={nbL9`uw[u<@\g3ycHc 6ܟw@.:b3&Orٍ$i\jBF8'0hiEZ6ͪ#'$XhEw:_tt2O9JkVk~}CF0!(hx=?m%A"%k?7''227 )esҦ%>̓3ccm1Z{ y߭{3w˳'>@9M5f.nɌ ތIB{0݌[֘xo"I$rtH<8`BzӶ:P{(0}\ HPxTEU"沷y6\FQuKmmFšg3Nˮ.Z&.&n;xHc ~^Θ܂] f 7npo-j29-CnA ;Jɉ B <trOlSL|p-fL=eJE0c>x`KlI2~ul9o(n6)=Yvq5Yt2r0]!\fJA`49__f*QUH[N`'DqTK>8}\,-r@,gW1'~8|!9V6R~j<)f0xh2#r_\g`-'8z0v_ǸYhylFNoi4HC~dMfDFEj FȌP{Dkz L[L>-r'u?+8%3{ Y^߿_y00 ލ'{wyݛEo}A>"D9iYV`EYŰ\2m[`\܂;15FPfHzԣu!{X4L+@fXWDGN|*fpW^g9\L_W}/N})(\CO;znp;jP;uU[fecF'r!U9pxjf?tXQ6!?.A0lwhe0>7VVi>z};FJQD%Wο;yFgץfj-چC:ZhH.h3m *vq,v9 o碔6 r#d+j5I R!wXr2ZUXeT^ t4f z0&(Io,BP/Yn9kN\]iW@]q3ڝq]]ty+ѵ0c4v s_\$ZqWLNg"% %QDmT K54Wj:%V?9~]ȁoch )D0Ittj{TtxfhEcqX2-,k-|zdoCժEkBXG'X54/h4?BYPGxtY1o:M!`: ^h،cxb˯~Lnc3CHڂlٹI+]0%?{MAy&2|D4cƜMQ$XRERY. ' T// @VؿP]Rp}0Fsu6j>C^衲 I7" " b1-xě/d9o{rv"%qYME)E(~e}xPO'V\fQlWYp)7S“eVd;?WiYIƍFFj'>Jn5dR3+Kοѝۚ0AS37k4ִ>^Q⏃\%ɖ;L9/󭁳:4~d~~dPՉZjpʡwnp|>뢙Ǣh'TK #*i -tXϣ%FQ+**,[Ye5w'=2N2EFhBh" X0:tG7lO+qVÉ7M(HK.IZeL?fr܋r3N4ݗ7F[?57krtl켋)D,`Oh."I|$h[h"鐋c d_š tk[xg-l2ǖمl M<@#貆 d!<vCh,.fH ;Ss?f8$=֟{S@=HFy)ҎO8t:cə;/v89$ma%9d&fd@fuA|:P0*s(0Br$D}/8ϒ J#j!^mg\h%2ReAYv^ F;xp18h534k4X,~>OB^OܠO3ZI?edWyܽ!f o N/F-Lhͅڦ x8~ɣ(~+緅<4 |[,3,Ð^ @%wȍG~: `ó^2`3MXcpw5E/7;qrW5f}~}\&U^24u3^iT%:.HҼxS)ΈWUna RT&͐!dJf=t,IJN6&{loB(Xvv8Rwgp{p {yc\W]Χf`x:VVT[ćS;=v0e+ݻ}#;!H@XMxOv@~Qϰ6Yk[ ,x1q>Oo4:#y@\Q2gtׁLBi϶Pi$Ȃh8T$1i`i;j!רDhw䆣 g,i(scD.(#(j,ǂikv[ުZYf)*Cls 졿+'V`_:M@.E:ϩ4iiZ >&U+P9&miTF[ٗQ 4eFuհ!^$w̧YMp$QG63ǐ[Cp:$Π}/޸u(guuuuuuogzW?c"!n@ܙ]8\ˇb9Bso jJL])( CU{bs·(& gsʪn?zF>ʋP /Z4?o|hz0þH1#rx 35$V9О]yA/lSU]mQ7?ϪIA0ݵ&=<=ޤ'wa?j8j̀7"i44i>0EGMzRjD٫-[ քZ뵶dӡIEs"%MDcE ʹdf\d(DIf.e0"=9EׄiiyX9Y>Ph+=aʱAy(0͢XWhA)iyB0M˯Vh-a#=Оif3eae1 <4JHIez@y$YHSh-ɃaENB\E>,+4D=H,D6+0M+t$勝vBG)iھG-J0MCF+y;L|vڞ#as'LC{nB;0M+t0M߳S3iJ9s4mB+44Z=Ӵ\ѵV?_A 6_l\ljlktpKjYݲYҲeUc[sˊ,e˜Ӛ-n[휶`Uk4XqEe+ ;Cv5Lj6`,o~&sFi׼l[ش`y㪥Ζ& v Fh jD3kjQKQێ]: UDauv8v8As c|.5nջq#pa惏\?r:P_v_Cz˯UgWˇr_qC2o-9N㝣&܃FƂWpqsr4qc?u8v^Sعq͎T%9qU[[۶69ZuM͛*]y҂MXh݈K Қ6U45545FD;^rD,fS##Ӑ֧SI)z{lXu&s`juzhyA%,E ol"J$'w"(CU9 *hQS.1\/+xGThZ ]f:( 0W:^ud#8VoU/9M[wQuu@Seָ@.%CmWvvH4Ч,J}>s@lqƲŁR}ʏѦnslwVDh endstream endobj 8 0 obj <> stream x[[s6~_Z1Lb7۸IzQ [-y$IDr4$spp!gB2K3i2Q8f- ϜGX@ J6R2!bҁeLt)LkŃF{'53c N1 V2 HW0B%ä61ifPZhI%ΙLzg 3 fA1dk(U0)JKoP`k*! nlT018nmbn )6N P(}2$pc&I M#9]Z7pR$~68a1d46nmN >@nؐ5hgx@8=%mc݀ڑ/ 8Fڑ6pq'X!1@y A ɃYN<)HhwAj`|F+߁4I57SCUx#hczPKo4sdUpdNY`ǜ%ˁg~$K#Jp' xSo?B`xM^;zKAPiH<łyn} ('u(XCȄӸ!BKp҆n`L , I:+Rx OݘXRߒCAU[5utBe"f).LNyD&* 8Z Sԡ=+_N'5Ho7yU7'/wէ<^Wǩx?@]U>Luy~Qӫt6f}|P~[}fnZ\~լ=H~[]}dYJl.пt!xbrKX XږxA9[Z(r*|S]Mbf[pSQ"]zr\xi@). 'Z]DYp/ ';tRf?2 I/= \ܖLaTBRV\,yv()R Qfe咑$-X,[?ÃqZA8|pgۋS>/m9j8:sttSzVUogop6Z c!{cmQ q~^M5Ƹ$3%x0X=UA ymu\:G|5j>8*xznQJ6մٳckVCDVh5V[Tt|cz-Ǧǣy?XMT\^cQ~WS1ףm~w:1|*W6YX%ɆBN>jlA$oAhmsFo  :[rq4ץ|&ߣ2t񑙍܌A=tqYDOM6j@߆ Mˇ&K|x.s Ng.[*.wqY0LCH#uKY +4.zk.izb.H"9^産}*M&X$槦~wi_EL I ZEbSkT[ VTj[a^.㔆wk "`")dsqQ`Xj1F~$|7ۯmnMǵ;Mv7BKvlnbZ>Ma'ɛ]yꤚ0N|f\TϮ+.V.͵V(/py%(\smpa*qюO ojR_Wǯi=D5 sx.*?UaCY{אK$d#<_4 0ޥ2=Lm:߰%e[z^ddюoBS0CgEG;K 3˒$s=&;maE`M9P*"* S[pJ:#D'̏v~P8Mw{J/ze\4zfR=hǗټ^-_ K{(w(;^fHfL\jOg՜q f+OL5OVKoy^өN+R ͸HP0mFu#tAn_=Hs!MN:rAo77=[?y e-޴ ֮zFO$̷toS+Oq*tȷÚ#|S)s|:o-Q\Uegh<|1?Y\X|^p& NDmʎ~@B. g)΂Ӂu_ (66P ]NAPmwc]Mrܣ9z C3:֟ch;A#$}ʇIǠaT]#pَ=lY;ޡ)xȍgJɗgOO*db8b7'?l4 #I5,a8ZjǙ}>x>^T5ONGsbn[8'?[Oqg戀~6+TH|~I5%w9t#}[?6q-)E=#v mr$!N1~rT #= 5 #|dڙte2!byZEi6?gq>7P}٩蒼 7RWˌt#ca=t5@Ht͔1`lZbZAyS50Yo5R endstream endobj 204 0 obj <<44ce64db85c9c0c23e3128a2036cd248>]/Root 1 0 R/Info 2 0 R/Size 205/W[1 3 2]/Filter/FlateDecode/Length 489>> stream x5YSqϷ,,,Q(K%$"K,rR‰(K"EN5;#0 ҅ =Ì v_]'I RHs|jR,OO+| Cp($mx kSboG`ǷoGSr(l46xM./)xޔe L?b)Xl5^a)KvzM^&`'~0~>/L+>/xTe20L2/؅8*stmdSG/cj2z+gJ\q5"9a+p#M,m8v܁Kq!]#Xq1a9%+q?¥Xa.ǃX0FQ:}~ΚL'/˷g߃>1j f??iA] endstream endobj startxref 90605 %%EOF instead-3.5.2+dfsg/doc/modules3-ru.tex000066400000000000000000000026611467622671600175630ustar00rootroot00000000000000\documentclass[12pt,]{book} \usepackage{cmap} \usepackage{tocloft} \usepackage[T2A]{fontenc} \usepackage[english,russian]{babel} \usepackage{indentfirst} % \usepackage[russian]{datetime} \usepackage{upquote} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex % \usepackage[utf8]{inputenc} \else % if luatex or xelatex \usepackage{fontspec} \ifxetex \usepackage{xltxtra,xunicode} \fi \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \newcommand{\euro}{€} \setmainfont{Verdana} \setsansfont{Verdana} \setmonofont{Liberation Mono} \fi \ifxetex \usepackage[setpagesize=false, % page size defined by xetex unicode=false, % unicode breaks when used with xetex xetex]{hyperref} \else \usepackage[unicode=true]{hyperref} \fi \hypersetup{breaklinks=true, bookmarks=true, pdfauthor={}, pdftitle={STEAD3}, colorlinks=true, urlcolor=blue, linkcolor=magenta, pdfborder={0 0 0}} \setcounter{tocdepth}{3} \setcounter{secnumdepth}{3} \title{STEAD3: Программирование модулей} \author{Петр Косых} \date{\today} \sloppy \begin{document} \maketitle { \hypersetup{linkcolor=black} \renewcommand{\contentsname}{Оглавление} \tableofcontents \clearpage } \input{modules3-manual-ru.tex} \end{document} instead-3.5.2+dfsg/doc/stead3-en.md000066400000000000000000005074131467622671600167740ustar00rootroot00000000000000## General Information The engine for INSTEAD is written in Lua language (5.1), therefore knowing this language is useful, though not necessary. The core engine also written in lua, so the Lua knowledge can be useful for in depth understanding principles of operation, of course, if you are interested this to do. During its development, INSTEAD got loads of new functions. Now you can make games of different genres (from arcade, to games text). And also, INSTEAD you can run games written in some other engines, but the Foundation INSTEAD remains of the original core, which is focused on creating text and graphic adventure games. This documentation describes the this basic skills is necessary, even if you want to write something else... so let's Start learning INSTEAD by writing a simple game! INSTEAD 3.0 was published in February of 2017 after 8 years of development. Version 3.0 supports a new runtime named STEAD3. The old runtime is now known as STEAD2. INSTEAD supports games written for either STEAD2 or STEAD3. This manual will teach you everything you need to know about writing games for STEAD3. Other resources may be helpful to you such as the INSTEAD website: https://instead-hub.github.io We also have a chat room on gitter: https://gitter.im/instead-hub/instead ### The story of creation When we say "text adventure" most of the people there one of the two familiar images. It's either text, action buttons, for example: You see a table in front of you. There is an apple on the table. What to do? 1) Take the apple 2) Step away from the table Or much less, this is a classic game with a text input where game control was necessary to introduce actions with the keyboard. You in the kitchen. There is a table. > inspect the table. There is an apple on the table. Both approaches have their advantages and disadvantages. If we talk about the first approach, it is close to the genre of books, games and more convenient for literary texts that describe events, what is happening with the main character, and not very easy to create classic quests, where the main character explores modeled in-game world, moving freely on it and interacting with objects this world. The second approach models the world, but requires considerable effort from the game author, and more importantly, more prepared player. Especially when we are dealing with the Russian language. INSTEAD the project was created for writing other types of games combine the advantages of both approaches while trying to avoid their disadvantages. The world of the game INSTEAD is modeled as the second approach, that is, in the game there are places (scenes or rooms) which can have access to the main the hero and the objects with which it interacts (including living characters). The player is freely exploring the world and manipulates objects. Moreover, actions with objects is not spelled out explicitly menu items, but rather reminiscent of the classic graphic quests in the style of the 90s. Actually, INSTEAD there are many invisible at first glance things that are aimed at the development of the approach chosen, and which makes the game as dynamic and different from the usual "text quests". This is confirmed by including the fact that the engine was released a lot of great games, the interest show not only the fans of word games as such, but people do not familiar with this genre. Before you read this guide, I recommend to play classic INSTEAD games to understand what was going on. On the other hand, since you're here, you probably did it. However, not worth while to examine the code of these games, because old games are very often behave inefficiently, with outdated designs. Current version INSTEAD allows you to implement code shorter, simpler and easier. About this and tells this document. If you are interested in the history of the engine, then you can read an article about how it all began: https://instead-hub.github.io/article/2010-05-09-history/ ### Look and feel of a typical INSTEAD game So, What does a typical INSTEAD game look like? _Main game window_ contain a narrative, information about the static and dynamic parts of the scene, active events and a picture the scene (in the graphic interpreter) with possible transitions to other scene. _Descriptive part of the scene_ appears only once, when showing scene, or with explicit inspection of the scene (in the graphic interpreter -- Staticheskaya part scene contains information about static objects scene (usually scenery) and is always displayed. This part written by the author of the game. _Dynamic part of the scene_ is composed of descriptions of objects in the scene, which are present in the moment on stage. This part is generated automatically and always displays. Usually, it presents objects that can change its location. The player is available the features available on any stage -- Inventory. The player can interact with objects of the inventory and to act the objects of the inventory on other objects in the scene or inventory. > It should be noted that the "inventory" is a conventionalism. For example, > equipment can be such objects as "open", "inspect", "use", etc. _Actions_ of the player can be: - inspection of the scene; - the effect on the object scene; - the effect on the inventory object; - the action object inventory on the inventory object; - the unfolding of the object scene; - switch to another scene. ### How to start a new game project INSTEAD will treat any directory on your computer as a game project if it contains a text file named "main3.lua". The presense of this file means that it is a STEAD3 project. Any other files you need for your game such as extra Lua scripts, images, and music should be stored within the game directory as well. Any time you reference an external resource in your code, it should be relative to the top-level game directory. The "main3.lua" file should start with a comment block containing a list of tags. Tags are pairs of names and character strings that provide information about your game to INSTEAD. Any sequence of characters starting with a double-dash on the same line is a Lua comment. INSTEAD tags are comment lines of the following form: -- $TagName: A string of UTF-8 characters$ The $Name tag contains the name of the game. Here is an example: -- $Name: the Most interesting game!$ It's good practice to follow the 'Name' tag with a few others. Here is how to specify the game's version number: -- $Version: 0.5$ People who play your game may be interested in who wrote it: -- $Author: Anonymous fan of text adventures$ It's oftentimes helpful to include a description about your game. Here we give an example of a multi-line tag. You specify line breaks using the "\n" escape sequence: -- $Info: This is a remake of a classic\nZX Spectrum game.$ If you are a Windows user, make sure that your text editor can save files encoded as UTF-8 _without a BOM (byte order marker)_. After the preamble containing your tags, you should list any external modules required by the game. Here is an example of what that might look like. We'll explain what these specific lines mean later: require "fmt" -- some formatting functions fmt.para = true -- enable the paragraphs (indents) After this, it's usually worthwhile to define default handlers. We haven't covered what handlers are yet, so it's fine if you don't know exactly what these lines do. Here is how you would define the default "act", "use", and "inv" handlers: game.act = 'Not running.'; game.use = 'It does not help.'; game.inv = 'Why?'; When the game starts, it will set the initial game state by calling the "init" function. You can use this function to initialize the player or to perform any special starting tasks. The function may not be needed depending on your game. function init() -- Put the knife and paper in the player's inventory take 'the knife' take 'paper' end The game engine only calls init() when a new game is started. It will not be called when you load a game that was previously saved. To perform a few actions whenever the game is loaded, use the start() function. ``` function start(is_loaded) -- to restore the original state? if is_loaded then dprint "Game loaded." else dprint "New game started." end -- we don't need to do anything end ``` If you include both an init() function _and_ a start() function, then them game engine will call init() first, and then call start(). The graphic interpreter looks for available games in the directory games. The Unix version of the interpreter in addition, the catalog scans also games in the directory ~/.instead/games. Windows version: %LOCALAPPDATA%\instead\games (below Vista: Documents and Settings\USER\Local Settings\Application Data\instead\games). In Windows and standalone-Unix version of the game are searched in the directory ./appdata/games, if it exists. In some assemblies, INSTEAD (in Windows, in Linux if the project is built with gtk etc.), you can open the game in any way from the menu "Choice of games".Or, press f4. If in the directory with the game there is only one the game, INSTEAD it will be launched automatically, which is handy if you want distribute your game with the engine. So you put the game in your directory and run INSTEAD. __Important!__ When writing games, it is strongly recommended to use indentation for coding games, as in the example from the leadership, thereby you will reduce the number of errors and will make your code graphically! Below is a minimal template for your first game: ``` -- $Name: My first game$ -- $Version: 0.1$ -- $Author: Anonymous$ require "fmt" fmt.para = true game.act = 'Hm...'; game.use = 'does Not work.'; game.inv = 'Why me?'; function init() -- initialization if it is needed end ``` ### The basics of debugging During debugging (check the health of your game) it is convenient to INSTEAD was started with-debug option, then in case of error shows more detailed information about the problem in the form of a stack calls. The-debug option can be set in the shortcut (if you are working in Windows) and for other systems, I think you already know how to pass command-line options. In addition, the mode is debug, the debugger automatically connects. You can activate it with ctrl-d or f7. You can to connect the debugger and explicitly: require "dbg" In the code of your game. When you debug a game, you usually need to frequently save the game and load the state of the game. You can use the standard mechanism of saving via menu (or via keys F2/F3), or use the quick saving/loading (press F8/F9). Mode '-debug' you can restart the game with [ALT]+R. In combination with F8/F9 this enables you to quickly see changes to the game after it changes. > Attention! INSTEAD's autosave feature is helpful when playing games, but may > get in the way when you are in the middle of development. When restarting > INSTEAD, the default behavior is to pick up where you left off by reloading > the previous game state. You can disable this feature through the menu > settings under "autosave". You can also explicitly reset the game whenever > you edit its source code. While in debug mode (by starting with the -debug > flag as described above), you can press [ALT]+R or select "start over" from > the menu. Mode '-debug' Windows version INSTEAD creates a console window (in Unix version, if you start INSTEAD from the console, the output will bedirected to it) which will be implemented by the error output. In addition using the function 'print ()', you can generate your messages with debug output. For example: ``` act = function(s) print ("Act is here! "); ... end; ``` Don't be alarmed when you read all the guidance and start writing your game, you will most likely take a look at this example with a large enthusiasm. You can also use the function dprint(), which sends the output in the debugger window, and you can see it when logged in mode debug. ``` act = function(s) dprint ("Act is here! "); ... end; ``` During debugging, it is useful to examine the save file, which contain the state variables of the game. Not to search every time files saves, create a saves directory in the directory of your game ( the directory that contains main3.lua) and the game will persist saves. This mechanism will also be useful for transferring games to other computers. It is possible (especially if you use Unix systems) you will like it the idea of checking the syntax of your script through the compiler "luac". In Windows it is also possible, you only need to install execute the lua file for Windows (http://luabinaries.sourceforge.net)/ and use luac52.exe. You can check the syntax and use INSTEAD, for this use the parameter -luac: sdl-instead-debug-luac ## Scene Scene (or room) -- is a unit game in which the player can examine all the objects in the scene and interact with them. For example, the scene can be a room in which the hero is. Or plot forest available for observation. In any game should be a scene called "main". It will start and your game! ``` room { nam = 'main'; disp = "Main room"; dsc = [[You are in a large room.]]; } ``` The record means creation of an object (as almost all entities. objects) main room type (room). The object attribute stores the name nam room 'main', which you can access room from your code. Each object has its unique name. If you try to create two object with the same name, you will receive an error message. To access the object by name, you can use the following entry: dprint("Object: ", _'main') Each object has _attributes_ and _event handlers_. In this example has two attributes: nam and dsc. The attributes are separated the delimiter (in this example -- a symbol, the semicolon ';'). Usually, the attributes can be text strings, functions-handlers and Boolean values. However, the attribute nam should always be a text string, if specified. In fact, you may not specify the name when creating the object: ``` room { disp = "Main room"; dsc = [[You are in a large room.]]; } ``` In this case, the engine itself will give the name of the object, and this name is a kind of number. Because you do not know this number, you can contact the object clearly. It is sometimes convenient to create unnamed objects, for example, for decoration. When the object is created, even if it is nameless, you unable to create variable object reference, for example: ``` myroom = room { disp = "Closet"; dsc = [[You in the closet.]]; } ``` Myroom variable in this case becomes a synonym of object (link on the object itself). dprint("Object: ", myroom) You can stick to any one method or to apply both. For example, you can specify the name and the variable link: ``` main_room = room { nam = 'main'; disp = "Main room"; dsc = [[You are in a large room.]]; } ``` It is important to understand that the engine is in any case working with object names, variables are just references-it's just a way to simplify access to frequently used objects. So, for our first game, we owe to specify the attribute nam = 'main' to create the main room and we begin our adventure! In our example, when displaying the scene, the title scene will be used the attribute 'disp'. In fact, if we hadn't asked it's in the title we would see 'nam'. But nam is not always convenient to do the title of the scene, especially if it is a string like 'main' or if it numeric ID that the engine assigned to the object automatically. There is a more intuitive attribute 'title'. If it is set, when the display room as the title will indicate it. title is used when the player is inside one of the room. In all other cases (when showing transitions in this room) use the 'disp' or 'nam'. ``` mroom = room { nam = 'main'; title = 'Start of adventure'; disp = "Main room"; dsc = [[You are in a large room.]]; } ``` Attribute 'dsc' is the description of the scene that is displayed once when entering the scene or when an explicit examination of the scene. There are no descriptions of objects present in the scene. You can use the symbol ',' instead of ';' to separate attributes. For example: ``` room { nam = 'main', disp = 'Main room', dsc = 'You are in a large room.', } ``` In this example, all attributes -- a string. The string can be written in single or double quotation marks: ``` room { nam = 'main'; disp = 'Main room'; dsc = "You are in a large room."; } ``` For long descriptions it is convenient to use the following: dsc = [[ Very long description... ]]; The newlines are ignored. If you want in the output the description of the scene was attended by paragraphs -- use the '^'symbol. ``` dsc = [[ First paragraph. ^^ The Second Paragraph.^^ Third paragraph.^ On a new line.]]; ``` I recommend to always use [[ and ]] to 'dsc'. Let me remind you again that the name 'nam' of object and display it (in this the case of how the scene will look like for the player in the form of lettering at the top) you can (and often should!) share. For this there are attributes 'disp' and 'title'. 'title' is only in the rooms and works as handle when the player is inside this room. In other cases, use the 'disp' (if any). If 'disp' and 'title' is not specified, it is considered that the display equals name. 'disp' and 'title' can be set to false in this case display will not. ## Objects _Objects_ -- this one scene interacting with the player. ``` obj { nam = 'table'; dsc = 'In the {table}.'; act = 'Hm... Just a table...'; }; ``` Object name "nam" is used when it gets to your inventory. Though in our case, the table hardly gets there. If the object is defined 'disp', when it enters the inventory to display it will make use of this attribute. For example: ``` obj { nam = 'table'; disp = 'table angle'; dsc = 'In the {table}.'; tak = 'I took the corner of the table'; inv = 'I hold the corner of the table.'; }; ``` Still, the table came to us in the inventory. You can hide items in the inventory, if 'disp' the attribute will be 'false'. 'dsc' -- description of the object. It will be displayed in the dynamic part the scene in the presence of the object in the scene. The braces displayed a fragment of the text to be a link in the window INSTEAD. If objects in the scene a lot, all descriptions are displayed one after the other, using the spacebar 'act' is an event handler that is called when the action user (action on object in the scene, usually -- click the mouse on the the link). Its main task-the output (return) line of text which will become part of scene events, and state change to playing world. ## Add objects to the scene There are several ways for you, the author, to populate a scene with objects. First, when a room is created, you can assign a list containing the names of objects to the room's 'obj' attribute: ``` obj { -- an object with a name but without a variable nam = 'box'; dsc = [[I see a {box} on the floor.]]; act = [[Hard!]]; } room { nam = 'main'; disp = 'Big room'; dsc = [[You are in a large room.]]; obj = { 'box' }; }; ``` Now, when rendering the scene, we will see the object "box" in a dynamic part. Rather than referring to the box by its name, we could have used a variable reference. This is possible as long as the object is declared earlier in your source code: ``` apple = obj { -- object variable, but without a name dsc = [[there is {Apple}.]]; act = [[Red!!]]; } room { nam = 'main'; disp = 'Big room'; dsc = [[You are in a large room.]]; obj = { apple }; }; ``` As a syntactic convenience, you can assign room objects at the end in a ":with" block. This allows you to remove one level of indentation, and group objects at the end of a room definition: ``` room { nam = 'main'; disp = 'Big room'; dsc = [[You are in a large room.]]; }:with { 'box', } ``` You can even declare your objects directly within a room definition. Here is an example of how you might do that: ``` room { nam = 'main'; disp = 'Big room'; dsc = [[You are in a large room.]]; }:with { obj { nam = 'box'; dsc = [[I see a {box} on the floor.]]; act = [[Hard!]]; } }; ``` This is useful for objects and scenery. But in this case, you are will be able to create objects with a variable link. Fortunately, for decorations don't have to. If the room is placed a few objects, separate the links with commas, for example: obj = { 'box', apple }; You can insert line breaks for clarity, when objects many, for example: ``` obj = { 'table', 'apple', 'knife', }; ``` Another way of placing objects is to call functions which the objects are placed in the required room. This will be discussed in further. ## Objects used as decoration Objects which end up being moved around within different scenes or into and out of the player's inventory during play are typically given a name or assigned to a variable. Naming an object allows us to refer to and work with objects in our code wherever the player (or our code editor) happens to be. On the other hand, many or most of our game world may consist of objects that serve no other purpose than decoration. These objects exist solely to enrich our environments with descriptive content for the player to experience. Such objects can be numerous, and moreover, it's common for them to be duplicates of each other. A forested area might be populated by many instances of the same tree, city streets may contain the same light pole on every block. We use a different approach for creating objects such as these than we would for unique objects that the player can manipulate. ### The same object in multiple rooms Using our example of a forrested area, you can create a single object and place it in multiple rooms as follows: ``` obj { nam = 'tree'; dsc = [[There is a {tree}.]]; act = [[All of these trees look alike.]]; } room { nam = 'Forest'; obj = { 'tree' }; } room { nam = 'Street'; obj = { 'tree' }; } ``` ### Use tags instead of names A decorative object may only appear in a single room. For objects like these, you can assign them a local name using the 'tag' attribute. By assigning a tag, you don't have to come up with a globally unique name. Strings assigned to the 'tag' attribute look like a name, but are preceeded by a '#' symbol. Even so, you refer to the object by its tag without a #: ``` obj { tag = '#flowers'; dsc = [[there is {flowers}.]] } ``` All objects have names whether you define one or not. In this example, the object tagged as "flowers" will be given an automatically generated name. Referring to an object by its tag is only possible within the current room. For example: ``` -- search the current room for the first object tagged as '#flowers' dprint(_'#flowers') ``` One way of thinking about tags is that they are local names. For convenience, you can tag an object by assigning a tag to the 'nam' attribute. Remember that tags always start with a '#' character whereas names do not. ``` obj { nam = '#flowers'; dsc = [[there is {flowers}.]] } ``` By assigning a tag to the 'nam' attribute, the object's actual name will be automatically generated behind the scenes. ### Attribute usage scene decor Since the scenery does not change its location, it makes sense to do them part of the description of the scene and not dynamic. This is done attribute scene 'decor'. decor is always shown and the main function-description of the scenery of the stage. ``` room { nam = 'House'; dsc = [[I am at home.]]; decor = [[I see a lot of interesting things. For example, {#wall|wall} hanging {#picture|picture}.]]; }: with { obj { nam = '#wall'; act = [[the Wall like a wall!]]; }; obj { nam = '#pattern'; act = [[van Gogh?]]; } } ``` Here we see several techniques: 1. To as a related text describes the scenery; 2. As references are used design with a clear mission objects to which they belong {the name of the object|text}; 3. As the names of objects are tags, not to think about them uniqueness; 4. The objects of the scenery in the scene has no attributes dsc, as their the role of decor. Of course, you can combine all of the techniques among themselves any proportions. ## Objects associated with other objects Objects can also contain the attribute 'obj' (or design 'with'). In this case, when outputting the objects, INSTEAD be deployed lists consistently. This technique can be used to create container objects or just to link a few descriptions together. For example, put on the table an Apple. ``` obj { nam = 'Apple'; dsc = [[On the table is {Apple}.]]; act = 'Take what?'; }; obj { nam = 'table'; dsc = [[the room is a {table}.]]; act = 'Hm... Just a table...'; obj = { 'Apple' }; }; room { nam = 'House'; obj = { 'table' }; } ``` Thus, in the scene description we'll see descriptions of objects 'table' and 'Apple', because 'Apple' is associated with a table object and the engine in the output of the object 'table' after 'dsc' will consistently "dsc" and all its nested objects. Also, it should be noted that in terms of object 'table' (for example, moving it from room to room) we will automatically move and invested in an object 'Apple'. Of course, this example could also be written differently, for example, so: ``` room { nam = 'House'; }: with { obj { nam = 'table'; dsc = [[the room is a {table}.]]; act = 'Hm... Just a table...'; }: with { obj { nam = 'Apple'; dsc = [[On the table is {Apple}.]]; act = 'Take what?'; }; } } ``` You can choose the way that's clearer for you. ## Defining attributes and event handlers with functions Up until now we've assigned strings to most of the attributes of our objects and rooms. You can also assign _functions_ to attributes. For example: ``` disp = function() p 'Apple'; end ``` That wasn't a very good example, but it does show what the syntax should look like. We may as well have written `disp = 'Apple'`. The main objective of such functions is to return a string or boolean value. Let's take a look how to return something. One way to return a string is by an explicit statement such as the following: return "Apple"; When a statement like this is encountered, the function will exit with the given return value. In this case, that would be the string, "Apple". The most common way to output strings is by using the following three built-in functions: - p ("text") -- output text and white space; - pn ("text") -- output text with line break; - pr ("text") -- output text as-is. These functions do not output text directly. The engine maintains a clipboard where text is stored. The contents of this clipboard is sent to the engine all at once when your function returns. This allows you to build up a block of text to return by calling p/pn/pr multiple times. In most cases, you shouldn't concern yourself with where line breaks will go or any other formatting issue. This is especially true of descriptions. The engine will wrap text and add spacing intelligently based on what you present to the player. As with all functions, you can leave out the parentheses if there is only a single value to supply: pn "No brackets!" It's likely that you will often times want to concatenate strings together. You can either use '..' or ',' for this purpose, and in that case parentheses will be required: pn ("String 1".." Line 2"); pn ("String 1" "String 2"); > The main difference between attributes and event handlers is that only event > handlers are able to change the state of the game world. When writing an > attribute such as 'dsc', remember that your goal is to return a value and > not to affect what happens in the game! Forgetting this rule will lead to > unpredictable behavior. __Important!__ > There is something to keep in mind when writing event handlers as well. They > should execute quickly. Event handlers are called in response to user > action, and the engine expects them to return immediately so that it can > refresh the user interface. If you want to insert delays to control the > output that users see, you will have to use the "timer" module. Functions almost always return dynamic results that are based on the contents of variables. For example: ``` obj { nam = 'Apple'; seen = false; dsc = function(s) if not s.seen then p '{Something} is on the table.'; else p 'An {Apple} lies on the table.'; end end; act = function(s) if s.seen then p 'It's an Apple!'; else s.seen = true; p 'Um... It's an Apple!'; end end; }; ``` When a function is assigned to an attribute, its first parameter always refers to the object itself. We typically name this variable 's' for "self". You could also write out the object by name (\_'Apple'), but when writing such functions, it's generally better to use the 's' parameter than to make an explicit call to the object name. This will save you from having to rewrite functions if you ever need to rename the object. In this example, we make text descriptions dynamic. The first time the player encounters this object, it will be referred to as "Something". Once they interract with it, the 'seen' variable becomes true. After that, they will see that the object is an "Apple". The syntax of 'if' statements is easy to read. Here are a few examples for clarity: if then end if have 'Apple' then p 'I have an apple!' end if then else end if have 'Apple' then p 'I have an apple!' else p 'I don't have any apples!' end if then elseif then else end -- etc. if have 'Apple' then p 'I have an apple!' elseif have 'fork' then p 'I don't have any apples, but there is this fork in my inventory!' else p 'I don't have an apple or a fork. end The _expression_ of an "if" statement is a boolean value made up of true/false terms separated by "and", "or", "not", and parenthesis to control evaluation priority. Expressions containing a single variable (ie: `if `) simply check that the variable does not equal to `false`. The equality operator is '==', and the inequality operator is '~='. ``` if not have 'Apple' and not have 'fork' then p 'I don't have an apple or a fork!' end ... if w ~= apple then p 'This is not an Apple.'; end ... if time() == 10 then p 'It's your 10th turn!' end ``` __Important!__ You need to define variables before using them. If you use a variable in a condition expression without first defining it, INSTEAD will raise an error. ### Object variables The entry's.seen' means that the variable 'seen' is placed in the object 's' (i.e. 'Apple'). Remember, we have called the first parameter of the function 's' (self) as the first parameter -- is the current object itself. Object variables must be defined in advance if you are to modify them. Something like we did with the seen. But variables can be many. ``` obj { nam = 'Apple'; seen = false; eaten = false; color = 'red'; weight = 10; ... }; ``` All variables of an object when it changes, enter the save file game. If you don't want the variable was in a save file, you you can declare such variables in a special block: ``` obj { nam = 'Apple'; { t = 1; -- this variable will not get to save x = false; -- and this too } }; ``` Normally you don't need to do that. However, there is a situation in which this technique will be useful. The fact that arrays and tables object are always saved. If you use arrays to store immutable values, you can write: ``` obj { nam = 'Apple'; { text = { "one", "two", "three" }; -- never go to a save file } ... }; ``` You can access the variables of an object via s-if it is himself object. or variable - reference, for example: ``` apple = obj { color = 'red'; } ... -- somewhere in another place apple.color = 'green' ``` Or by name: ``` obj { nam = 'Apple'; color = 'red'; } ... -- somewhere in another place _'Apple'.color = 'green' ``` In fact, you can create variables of the object on the fly (without pre-define them), although usually it makes no sense. For example: ``` apple 'xxx' (10) -- create a variable xxx, the object apple on the link (_'Apple') 'xxx' (10) -- same but in the name of the object ``` ### Local variables In addition to object variables you can use local and global variables. Local variables are created by using office word local: ``` act = function(s) local w = _'light bulb' w.light = true p [[I pressed the button and the bulb lit up.]] end ``` In this example, the variable 'w' exists only in the body the handler function act. We created a temporary reference variable 'w', which refers to the object 'light' to change feature-variable light this object. Of course, we could write: _'light bulb'.light = true But imagine if we need to execute multiple actions with a the object in such cases is easier to use a temporary variable. Local variables are never displayed in the file-save and play the role of temporary auxiliary variables. Local variables can be created outside of functions, then this the variable is visible only within a given lua file and misses a save file. Another example of using local variables: ``` obj { nam = 'kitten'; state = 1; act = function(s) s.state = s.state + 1 if s.state > 3 then s.state = 1 end p [[Purr!]] end; dsc = function(s) local dsc = { "The{kitten} purrs.", "The{kitten} is playing.", "The{kitten} is licked.", }; p(dsc[s.state]) end; end ``` As you can see, in dsc, we determined the array dsc. 'local' indicates that it operates within the dsc. Of course, this example you could write it as: ``` dsc = function(s) if s.state == 1 then p "the{Kitten} is purring." elseif s.state == 2 then p "the{Kitten} is playing." else p "the{Kitten} is licked.", end end ``` ### Global variables You can also create a global variable: ``` global { -- definition of global variables global_var = 1; -- number some_number = 1.2; -- number some_string = 'string'; know_truth = false; -- a Boolean value array = {1, 2, 3, 4}; -- array } ``` Another form, convenient for single definitions: global 'global_var' (1) Global variables always get to the file-save. In addition to global variables you can define constants. Syntax similar to global variables: ``` const { A = 1; B = 2; } const 'Aflag' (false) ``` The engine will control the consistency of constants. The constants are not enter the file-save. Sometimes you need to work with a variable that is not defined aslocal (and visible in all of your lua files), but should not get in the save file. For such variables you can use Declaration: ``` declare { A = 1; B = 2; } declare 'Z' (false) ``` The Declaration is not stored in the save file. One of the important properties declarations is that you can declare functions for example: ``` declare 'test' (function() p "Hello world!" end) global 'f' (test) ``` In such case, you can assign the value of the function 'test' others variables and the state of these variables may be stored in the filesave. That is, a declared function can be used as the value of the variable! You can declare a previously defined function, for example: declare 'dprint' (dprint) Thereby making such undeclared functions -- declared. The function Declaration, in fact, is the assignment of the function name, thanks what can we retain this feature as a link. ### Helper functions You can write your helper functions and use them from your game, for example: ``` function mprint(n, ...) local a = {...}; -- temporary array with the arguments to the function p(a[n]) -- get the n-th element of the array end ... dsc = function(s) mprint(s.state { "The{kitten} purrs.", "The{kitten} is playing.", "The{kitten} is licked." }); end; ``` Don't pay attention to this example, if it seems to you difficult. ### The return value handlers If you want to show that the action is not executed (handler did anything useful), return false. For example: ``` act = function(s) if broken_leg then return false end p [[I kicked the ball.]] end ``` This displays the default description is specified using a handler 'game.act'. Usually the default description contains description of the undoable action. Something like: game.act = 'Hm... does Not work...'; So, if you don't set the handler act or returned from it false -- it is believed that there is no reaction and the engine will perform the same handler from object 'game'. Usually, there is no sense to return false from the act, but there are other handlers, which will be discussed further, for which the described behaviour is exactly the same. Actually, besides 'game.act' and 'act' -- the object attribute exists handler 'onact' of the game object, which can interrupt execution handler 'act'. Before calling the handler 'act' of an object is called onact have game. If the handler returns false, the execution of the 'act' dropped. 'onact' convenient to use for control events in the game, for example: ``` -- called onact rooms, if they are -- for the actions on any object game.onact = function(s, ...) local r, v = std.call(here(), 'onact', ...) if v == false then -- if false, chop off the chain return r, v end return end room { nam = 'shop'; disp = 'Shop'; onact = function(s, w) p [[In the store, you can not steal!]] p ([[Even if it's only a ]], w, '.') return false end; obj = { 'ice cream', 'bread' }; } ``` In this example, when trying to "touch" any item, will be display a message prohibiting this action. All that is described above on the example of the 'act' applies for other handlers: tak, inv, use, and transitions, as will be is discussed later. > Sometimes you need to call the handler function manually. > It uses the syntax of a method call > object. 'Object:method(parameters)'. For example: apple:act() -- call handler 'act' of object 'apple' (if it defined as a function!). _'Apple':act() -- same, but name, not a variable reference This method works only if the called method designed as a feature. You can use 'std.call()' for a handler is invoked in the way that it makes itself INSTEAD. (To be described in the future). ## Inventory The easiest way to create an object that can be picked up is to assign a handler to the 'tak' attribute, which is short for "take". For example: ``` obj { nam = 'Apple'; dsc = 'On the table is {Apple}.'; inv = function(s) p 'I ate the Apple.' remove(s); -- remove an Apple from the inventory end; tak = 'You took the Apple.'; }; ``` In this case, the player object is "Apple" (click on link in the scene) -- the Apple is removed from the scene and added to inventory. When the player uses the inventory (double click on the name of the object) -- call the handler 'inv'. In our example, when the player uses the Apple in the inventory -- Apple be eaten. Of course, we could implement the code takes object to "act", for example: ``` obj { nam = 'Apple'; dsc = 'On the table is {Apple}.'; inv = function(s) p 'I ate the Apple.' remove(s); -- remove an Apple from the inventory end; act = function(s) take(s) p 'You took the Apple.'; end }; ``` If the object in the inventory is not declared a handler for the 'inv', will be called 'game.inv'. If the handler is 'tak' will return false, the item will not be taken, for example: ``` obj { nam = 'Apple'; dsc = 'On the table is {Apple}.'; tak = function(s) p "It is wormy!" return false end; }; ``` ## Transitions The traditional transitions into INSTEAD appear as links above the description scene. To determine the transitions between scenes is used attribute scene -- list 'way'. In the list are determined by the room in the form of of the room names or variable references, similar to the list 'obj'. For example: ``` room { nam = 'room2'; disp = 'Hall'; dsc = 'You are in a huge hall.'; way = { 'main' }; }; room { nam = 'main'; disp = 'Main room'; dsc = 'You are in a large room.'; way = { 'room2' }; }; ``` With this, you'll be able to go between scenes 'main' and 'room2'. As you remember, 'disp' can be a function, and you can generate names transitions on the fly. Or use title, to separate the name of the scene as the title and how the transition name: ``` room { nam = 'room2'; disp = 'hall'; title = 'hall'; dsc = 'You are in a huge hall.'; way = { 'main' }; }; room { nam = 'main'; title = 'the main room'; disp = 'the main room'; dsc = 'You are in a large room.'; way = { 'room2' }; }; ``` When passing between rooms the engine calls the handler for the 'onexit' of the current scene and 'the onenter' in that scene where is the player. For example: ``` room { the onenter = 'You enter the room.'; nam = 'Hall'; dsc = 'You are in a huge hall.'; way = { 'main' }; onexit = 'You exit the room.'; }; ``` Of course, like all handlers, 'onexit' and 'the onenter' can be functions. Then the first parameter is (as always) the object itself - room and the second room is where the player is going to go (for 'onexit') or from which is going to leave (for 'the onenter'). For example: ``` room { onenter = function(s, f) if f^'main' then p 'You go from room to main.'; end end; nam = 'Hall'; dsc = 'You are in a huge hall.'; way = { 'main' }; onexit = function(s, t) if t^a'main' then p 'I don't want to go back!' return false end end; }; ``` Writing: if f^'main' then This mapping of the object name. This alternative records: if f == _'main' then Or: if f.nam == 'main' then Or: if std.nameof(f) == 'main' then As you can see, for example, onexit, these handlers other than line can return a Boolean status value. Similarly, the processor onact, we can cancel the transition by returning false from onexit/the onenter. You can also return another way, if it seems you comfortable: return "I don't want to go back", false If you use the function 'p'/'pn'/'pr', then just return the status of a transaction with the final 'return', as shown in the example above. __Important!__ > It should be noted that when calling the handler 'the onenter' pointer to > current scene (here()) **not yet changed**!!! In there INSTEAD > handlers 'exit' (leaving the room) and 'enter' (entering the room), > which are called already _posle_ how the transition happened. These > handlers are recommended when there is no > need to forbid the transition. Sometimes there is a need to name the transformation differed from the name of the room in which this transition leads. There are sever always to do this. For example, using 'path'. ``` room { nam = 'room2'; title = 'Hall'; dsc = 'You are in a huge hall.'; way = { path { 'main room', 'main'} }; }; room { nam = 'main'; title = 'Main room'; dsc = 'You are in a large room.'; way = { path {'room', 'room2'} }; }; ``` Actually, 'path' creates a room with the attribute 'disp', which equal to the first parameter, and special feature 'the onenter', which redirects the player to the room specified by the second argument of 'path'. If you specify three parameters: way = { path {'#hall', 'room', 'room2'} }; The first parameter will be the name (or tag, as in the example) for such a room. Alternative form of entry with the explicit task attribute nam: way = { path { nam = '#hall', 'room', 'room2'} }; You can change the name of the transition, after the transition occurred at least once, and you know, what is this room: way = { path {'#udvari', 'door', after = 'living room', 'room2'} }; All parameters except the transition name, can be functions. Thus, the 'path' allows you to call a transitions convenient way. Sometimes you may need to turn on and off transitions. Reallyit is not often required. The idea of transitions is that the transition visible even when it's impossible. For example, imagine the scene in front of the house by the front door. To enter the house because the door closed. It makes little sense to hide the transition. Just in the function of 'the onenter' the scene inside the house, we check whether a character key? And if the key no, talking about the fact that the door is closed, and prohibit the transition. It increases interactivity and simplifies the code. If you want to do the door object in the scene, place it in the room, but in the 'act' handlerd o the inspection doors, or allow the player to open it with a key (how to do it - we will look at later), but the transition itself give make the player in the usual way through the line transitions. However, there are times when the transition is not obvious and it appears as a result of some events. For example, a clock and saw a secret tunnel behind it. ``` obj { nam = 'clock'; dsc = [[you see an old {clock}.]]; act = function(s) enable '#clock' p [[You see that the watch is a secret passage!]]; end; } room { nam = 'Hall'; dsc = 'You are in a huge hall.'; obj = { 'clock' }; way = { path { '#watch', 'watch', 'inclock' }:disable() }; }; ``` In this example, we created _disabled_ transition, by calling method 'disable' of the room created using the 'path'. Method 'disable' have all items (not only rooms), it translates the object in disabled state, which means that the object ceases to be available to the player. A remarkable property disabled facility is that it can _enabled_ with 'enable()'; Further, when the player clicks on the link that describes the watch, called handler, 'act', using the function 'enable()' makes the transition visible. The alternative is not in shutdown and 'close' object: ``` obj { nam = 'clock'; dsc = [[you see an old {clock}.]]; act = function(s) open '#clock' p [[You see that the watch is a secret passage!]]; end; } room { nam = 'Hall'; dsc = 'You are in a huge hall.'; obj = { 'clock' }; way = { path { '#watch', 'watch', 'inclock' }:close() }; }; ``` What's the difference? Disabling an object means that the object ceases to be available to the player. If the object is nested other objects, and these objects become inaccessible. The closure of the facility makes unavailable the contents of this object, but not the object itself. However, in the case of rooms and closing rooms, and disabled room lead to the same result -- the transition to them is not available. Another option: ``` room { nam = 'inclock'; dsc = [[I in hours.]]; }:close() obj { nam = 'clock'; dsc = [[you see an old {clock}.]]; act = function(s) open 'inclock' p [[You see that the watch is a secret passage!]]; end; } room { nam = 'Hall'; dsc = 'You are in a huge hall.'; obj = { 'clock' }; way = { path { 'watch', 'inclock' } }; }; ``` Here we close and open did not move, and the room, which is transition. path shows himself if the room in which he leads disabled or closed. ## The effect of objects on each other The player may use an inventory object on other objects. For he clicks the mouse on the item and then for scene. When this handler is invoked 'used' object which function, and handler 'use' of the object which apply. For example: ``` obj { nam = 'knife'; dsc = 'On the table is a {knife}'; inv = 'Sharp!'; tak = 'I took the knife!'; use = 'You try to use the knife.'; }; obj { nam = 'table'; dsc = 'In the {table}.'; act = 'Hm... Just a table...'; obj = { 'knife' }; used = function(s) p 'You are trying to do something with a table...'; return false end; }; ``` In this example, used handler returns false. Why? If you remember, returning false means that the handler instructs the engine about what event he is not treated. If we would have returned false, the queue to handler 'use' of object 'knife' simply would not come. In fact, the reality is usually you will use or use or used, it is unlikely it makes sense to do both the handler during the action of the subject on the subject of. Another example, when it is convenient to return false: ``` use = function(s, w) if w^'Apple' then p [[I cleaned up the Apple.]] w.cut = true return end return false; end ``` In this case, use for knife only handles one situation -- effect on using knife on Apple. In other cases, the handler returns false and the engine will call the default: game.use. But it is better if you will add default message in use handler: ``` use = function(s, w) if w^'Apple' then p [[I cleaned up the Apple.]] w.cut = true return end p [[it is Not necessary to brandish a knife!]] end ``` This example also demonstrates the fact that the second argument u use is the subject on which we act. The method 'used' accordingly, the second -- argument is the entity that acts on us: ``` obj { nam = 'trash'; dsc = [[In the corner is a {trash bin}.]]; used = function(s, w) if w^'Apple' then p [[I threw the Apple in the trash.]] remove(w) return end return false; end } ``` As you remember, before calling use onuse handler is invoked from of the game object, then the object 'player', and then my current room. Youcan block 'use', returning from any of the following methods 'onuse' -- false. Use 'use' or 'used' (or both) is a matter of personal preference, however, the method used is called earlier and therefore has a higher priority. ## The "Player" Object Player in the world INSTEAD represented by an object of type 'player'. You can to create multiple players, but one player is present by default. The name of this object is 'player'. There is a variable-reference pl which points to this object. Usually, you do not need to work with this object directly. But sometimes it may be necessary. By default, the attribute 'obj', the player represents the inventory. Usually, it makes no sense to override an object of type player, however, you can do it: ``` game.player = player { nam = "Basil"; room = 'kitchen'; -- the starting room of the player power = 100; obj = { 'Apple' }; -- let's give him an Apple }; ``` To INSTEAD have the ability to create multiple players and to switch between them. This is the 'change_pl()'. In as parameter pass function required an object of type 'player' (or his name). Function will switch the current player, andnecessary, will move into the room where the new player. The 'me()' always returns the current player. Therefore, in most games and me() == pl. ## The "World" Object The game world is represented by an object of type world. The name of this object the 'game'. There is a reference variable, also called game. Usually you don't work with this object directly, but sometimes you can call its methods, or change variable values in this object. For example, the variable game.codepage contains the encoding of the source code games, and by default to "UTF-8". I do not recommend using other encodings, but sometimes, the choice of encoding can be necessity. The variable game.player -- contains the current player. In addition, as you already know, the object of the 'game' may contain default handlers: 'act', 'inv', 'use', 'tak', which will called if the actions of the user are not found no other handlers (or all of them returned false). For example, you you can write in the beginning of the game: game.act = 'does Not work.'; game.inv = 'hmm ... Odd thing...'; game.use = 'does Not work...'; game.tak = 'I don't need this...'; Of course, they can all be functions. Also, the game object may contain handlers: onact, ontak, onuse, oninv, onwalk -- which can interrupt the action, in case of return false. Still, the game object you can set handlers: afteract, afterinv, afteruse, afterwalk -- that are invoked in case of successful to perform the appropriate action. ## List Attributes List attributes (such as 'way' or 'obj') allow you to work with its content with a set of methods. Attributes-a list designed keep a list of objects. In fact, you can create lists for their own needs, and place them in objects, for example: ``` room { nam = 'fridge'; frost = std.list { 'ice cream' }; } ``` Although usually it is not needed. Listed below are methods for objects of type 'list'. You can call them for any lists, although these will usually be way and obj, for example: ways():disable() -- disable all transitions - disable() - disables all objects in the list; - enable() - enables all objects of the list. - close() - close all objects of the list. - open() - open the list objects; - add(object|name [position]) - add an object; - for_each(function, args) - to call for each object feature arguments; - lookup(name/tag or object) is object search in the list. Returns the object and the index; - srch(name/tag or the object) - the search for a visible object in the list; - empty() - returns true if the list is empty; - zap() - clear the list; - replace(what, what) - replace the object in the list; - cat(list, [position]) - add the contents of the list into the current list position; - del(name/object) - delete object from the list. There are functions that return the objects lists: - inv([player]) - return the player's inventory; - objs([where]) - return objects of the room; - ways([room]) - return transitions of the room. Of course, you can refer to the lists directly: pl.obj:add 'knife' The objects in the lists are stored in the order in which they add. However, if the object is present numeric attribute pri he plays the role of priority in the list. If pri is not specified, the value priority 0 is considered. Thus, if you want some the object was first on the list, give priority pri < 0. If the end of the list -- > 0. ``` obj { pri = -100; nam = 'thing'; disp = 'Very important item'; inv = [[Careful with this subject.]]; } ``` ## Functions that return objects To INSTEAD define some functions that return different objects. In the description of the function uses the following parameters agreement. - the characters [ ] describe the optional parameters; - 'what' or 'where' - means an object (including the room) is specified by the tag name or a variable reference; Thus, the main function: - '_(what) ' - get the object; - 'me()' returns the current object to the player; - 'here()' returns the current scene. - 'where ()' returns a room or an object which is the specified object if the object is in multiple places, you can pass in a second parameter -- a Lua table that will be added these objects; - 'inroom ()' similar to where(), but returns the room in which the facility is located (this is important for objects in the objects); - 'from([where])' returns the last room the player goes into given room. Optional parameter -- to the last room not for the current room, and for a given; - 'seen(what [, where])' returns an object or transition, if itis present and can see, there is a second optional parameter -- select the scene or object/list in which to search; - 'lookup(what, [where])' returns an object or transition, if it there is in the scene or object/list; - 'inspect ()' returns the object if it is visible/available on stage. The search is performed for transitions and objects, including, in the object of the player; - 'have ()' returns the object if it is in the inventory and not disabled; - 'live ()' returns the object if it is present among the living objects ( described below); These functions are mostly used in the conditions, or to search object from further modification. For example, you can use 'seen' for writing terms: ``` onexit = function(s) if seen 'monster' then -- if a function has 1 parameter --- I'm not hungry ... p 'the Monster's in the way!' return false end end ``` And also, for finding the object in the scene: ``` use = function(s, w) if w^'window' then local ww = lookup 'dog' if not ww then p [[where's my dog?]] return end place(ww, 'street') p 'I broke the window! My dog jumped on the street.' return end return false end ``` Example with 'have': ``` ... act = function(s) if have a 'knife' then p 'But I have a knife!'; return end take 'the knife' end ... ``` > The question may arise, what is the difference between lookup function and _ > ()? The fact that lookup() looks up the object and if the object is not > found -- just did not return. And the record is _ () assumes that you just > you know that the item you get. In other words, _ () is unconditional > receipt of the object by name. This function does not, in general, makes > the search. Only if the specified tag> will be searched from the available > objects. If you use _ () on a non-existent object or unavailable -- you will > get an error! ## Other standard library functions In the stdlib module INSTEAD, which always connects automatically defined the functions offered by the author as the main work tool for working with the game world. Let us consider them in this Chapter. In the description of the functions most of the functions under the parameter 'w' refers to an object or room, specified by name, tag or variable link. [ wh ] - indicates an optional parameter. - include(file) - file to include in the game; include "lib" -- will include the lib file.lua from the current directory with the game; - loadmod(module) to connect the module of the game; loadmod "module" -- will include the module module.lua from the current directory; - rnd(m) - a random integer value from '1' to 'm'; - rnd(a, b) - a random integer value from 'a' to 'b' where 'a' and 'b' are integers >= 0; - rnd\_seed () - set seed of random number generator; - p (...) output a string to the buffer handler/attribute (with a space at the end); - pr (...) output a string to the buffer handler/attribute "as is";- pn (...) output a string to the buffer handler/attribute (with a newline at the end); - pf(fmt, ...) - output formatted string to the buffer handler/attribute; local text = 'hello'; pf("String: %q: %d\n", text, 10); - pfn(...)(...)... "line" - creating a simple handler; This feature simplifies the creation of simple handlers: act = pfn(walk, 'bathroom') "I decided to go to the bathroom."; act = pfn(enable, '#transition') "I noticed a hole in the wall!"; - obj {} - create object; - stat {} - create status; - room {} - create a room; - menu {} - create a menu;- dlg {} - create a dialogue; - me() - returns the current player; - here() - returns the current scene. - from([w]) - returns the room from which the transition to your current scene. - new(constructor, arguments) - creates a new dinamicheskogo object (to be described later); - delete(w) - deletes the dynamic object; - gamefile(file, [reset?]) - load dynamically the file with the game; gamefile("part2.lua", true) -- reset the game state (remove objects and variables), load part2.lua and start with the main room. - player {} - create a player;- dprint(...) - debug output; - visits([w]) - the number of visits to the bathroom (or 0 if visits); - visited([w]) - the number of visits to the room, or false if not visits was; if not visited() then p [[it's my first time.]] end - walk(w, [Boolean exit], [enter Boolean], [Boolean to change from]) - transition in the scene; -- unconditional jump (to ignore onexit/the onenter/exit/enter); walk('end', false, false) - walkin(w) is a transition in the scene (without calling exit/onexit current); - walkout([w], [dofrom]) - return from sub-scene (without calling enter/the onenter); - walkback([w]) - a synonym walkout([w], false); - \_(w) - receiving object; - for_all(fn, ...) - to perform the function for all arguments; for_all(enable, 'window', 'door'); - seen(w, [where]) - search for the visible object; - lookup(w, [where]) is a search object; - ways([where]) - get list of transitions; - objs([where]) - get the list of objects; - search(w) - search for the player object; - have(w) - search for items in the inventory; - inroom(w) - the return of the room/rooms, in which the object resides; - where(w, [table]) - return the object/objects in which the object resides; local list = {} local w = where('Apple', list) -- if the Apple is in more than one place, then list will contain an -- array of these places. If you only need one location, then: where 'Apple' -- will be enough - closed(w) - true if the object is closed; - disabled(w) - true if the object is off; - enable(w) is to include an object; - disable(w) - off object; - open(w) - open; - close(w) - close the object; - actions(w, string, [value]) - returns (or sets) the number of actions of type t to an object w. if actions(w, 'tak') > 0 then -- object w was taken at least 1 time; if actions(w) == 1 then -- act it w was called 1 times; - pop(tag) - return to the last branch of the dialog; - push(tag) - the transition to the next branch of dialogue - empty([w]) - empty right branch of the dialogue? (or object) - lifeon(w) - add an object to the list of the living; - lifeoff(w) - to remove an object from the list of the living; - live(w) - object is alive?; - change\_pl(w) - change a player; - player\_moved([pl]) is the current player moved in this manner?; - inv([pl]) - get a list of the inventory; - remove(w, [wh]) - delete the object from object or room; Removes object obj from list and way (leaving all the rest, for example, game.lifes); - purge(w) - destroy the object (from all lists); Removes the object from all lists in which it is present; - replace(w, ww, [wh]) is to replace one object to another; - place(w, [wh]) is to put the object in the object/room (removing it from the old object/rooms); - put(w, [wh]) - put object without removing it from the old location; - take(w) - pick up object; - drop(w, [wh]) - to throw object; - path {} - create a transition; - time () is the number of moves from the beginning of the game. __Important!__ In fact, many of these functions also are able to work not only with rooms and facilities, but also with lists. That is, 'remove(apple inv())' works like 'remove(apple, me())"; However, remove(apple) also work and remove the object from the places where he present. Consider a few examples. ``` act = function() pn "I'm going to next room..." walk (nextroom); end obj { nam = 'my car'; dsc = 'in Front of the cabin is my old {pickup} Toyota.'; act = function(s) walk 'inmycar'; end }; ``` __Important!__ > After a call to 'walk' the execution of the handler continues until it > completed. Therefore, usually, after the 'walk' is always followed > 'return', unless it is the last line of the function, although in > this case, it is safe to put 'return'. ``` act = function() pn "I'm going to next room..." walk (nextroom); return end ``` Don't forget also that when you call 'walk' will be called handlers 'onexit/the onenter/exit/enter" and if they forbid the transition, it is not will happen. ## Dialogue Dialogues-the scene of a special type 'dlg' containing objects --phrase. When entering the dialogue the player sees a list of phrases that can to choose, getting some kind of reaction game. The default is already selected phrase hidden. The exhaustion of all options, the conversation ends exit to the previous room (of course, if in the dialogue there is constantly visible phrases, which usually occurs something like 'Finish the conversation' or 'Ask again'). When re-entering the dialog, all the hidden phrase again become visible and the dialogue is reset to the initial state (unless, of course, the author of the game specifically make an effort to change the form of a dialogue). The transition in the dialogue of the game is how the transition to the stage: ``` obj { nam = 'cook'; dsc = 'I see a {cook}.'; act = function() walk 'povardlg' end }; ``` Although I recommend to use 'walkin', as in the case of 'walkin' not called 'onexit/exit' the current room, and the character with which we can talk, usually to be in the same room, where the main hero. That is: ``` obj { nam = 'cook'; dsc = 'I see a {cook}.'; act = function() walkin 'povardlg' end }; ``` If you don't like the prefix of phrases in the form of a hyphen you can specify a string variable: std.phrase_prefix = '+'; And get prefixed with a '+' before each phrase. You can also to make a prefix function. The function in this case will be to enter a parameter the number of the phrase. The purpose of the function -- to return a string prefix. Please note that 'std.phrase_prefix' is not saved if you you need to override it on the fly, you will have to restore it state in 'start()' function manually! __Important!__ > I recommend to use module 'noinv' and set the 'noinv' in the dialogs. The > dialogs will look more beautiful and you will protect your game from > mistakes and unexpected reactions when using equipment inside the dialog (as > usual, the author does not imply such things). For example: ``` require "noinv" ... dlg { nam = 'Guard'; -- in the dialogues typically do not require inventory noinv = true; ... } ``` ### Phrase The Central concept in dialogue is the phrase. The phrase is not just the question- answer as you might think. The phrase is a tree, and in this the sense of the whole dialogue can be implemented only phrase. For example: ``` dlg { nam = 'conversation'; title = [[the Conversation with the seller]]; enter = [[I asked the seller.]]; phr = { { 'You have beans?', '-- No.'}, { 'You have chocolate?', '-- No.'}, { 'You have a brew?', '-- Yes', { 'How much is it worth?', '-- 50 rubles.' }, { 'He is cold?', '-- Fridge was broken.', { 'Take two!', 'Left one.', { 'Give me one!', function() p [[OK!]]; take 'brew'; end }; } } } } } ``` As you can see, the phrase is specified by the attribute phr and can contain branched dialogue. The phrase contains elections, each of which can also contain choices and so on... The phrase is in the format of pairs: descriptor -- reaction. In the simplest case, this a-line. But they can also be functions. Usually, the function is reaction, which can contain code to change the game world. Steam can be as simple as: {'Question', 'Response } And can contain an array of pairs: {'Question', 'Answer', {'Sub-question1', 'Under-answer1' }, {'Under-question2', 'Under-answer2' }, } In fact, if you look carefully at the attribute phr, you notice that the array of choices is also embedded in the main sentence phr, but only the original pair is missing: ``` dlg { nam = 'conversation'; title = [[the Conversation with the seller]]; enter = [[I asked the seller.]]; phr = { -- there could be question answer 1 level! -- 'The main issue', 'Main', { 'You have beans?', '-- No.'}, { 'You have chocolate?', '-- No.'}, { 'You have a brew?', '-- Yes', { 'How much is it worth?', '-- 50 rubles.' }, { 'He is cold?', '-- Fridge was broken.', { 'Take two!', 'Left one.', { 'Give me one!', function() p [[OK!]]; take 'brew'; end }; } } } } } ``` Actually, it is. And you can add the 'Main question' and'The answer', but you will not see this question. The thing that when entering into dialogue phrase phr automatically opens, so as usual there is no point in the dialogues of a single phrase. And it is much easier to understand the dialogue as a set of election than as the only tree phrase. So there is never a phr of the initial pair question-answer, but we immediately find ourselves in the array of options that more clear. When we talk about what the dialogue actually implemented one phrase, we are not quite right. The fact that we are dealing with the phrase,which is located inside the other phrase... It reminds us of the situation objects. Indeed, expressions are objects! Which can to be inside each other. So, take a look at the dialogue from a fresh perspective: ``` dlg { nam = 'conversation'; title = [[the Conversation with the seller]]; enter = [[I asked the seller.]]; phr = { -- is a phrase without dsc and act -- is the 1st phrase inside the phrase with dsc and act { 'You have beans?', '-- No.'}, --is the 2nd phrase within a phrase with dsc and act { 'You have chocolate?', '-- No.'}, -- it's a 3rd phrase within a phrase with dsc and act { 'You have a brew?', '-- Yes', -- is the 1st phrase inside the 3rd phrase with dsc and act { 'How much is it worth?', '-- 50 rubles.' }, { 'He is cold?', '-- Fridge was broken.', { 'Take two!', 'Left one.', -- act here as a function { 'Give me one!', function() p [[OK!]]; take 'brew'; end }; } } } } } ``` As you can see, the dialogue -- it is a room, the phrase-special objects! Now you will understand the subsequent presentation. > Attention! By default, when the player clicks on one of the questions in the > list, the engine repeats it in the conclusion and then displays response. > This is done to ensure that the dialogue seemed related. If you want to > disable this behavior, use the option std.phrase_show: ``` std.phrase_show = false -- don't display the passphrase question when choosing ``` This setting affects all dialogs, set it in init() or the start() function. ### The attributes of the phrases Consider the phrase: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', {'Red', 'Hold!' }, {'Blue', 'Here!' }, } } ``` If you run this dialog, after you select, say, red pills, we will have another choice of the blue pill. But our the idea, obviously not this! There are several ways to make the dialogue correct. First, you can use pop() -- return to the previous the level of dialogue: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', {'Red', function() p 'Hold!'; pop() end; }, {'Blue', function() p 'Here!'; pop() end; }, } } ``` Or, in another entry: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', {'Red', pfn(pop) 'Hold up!' }, {'Blue', pfn(pop) 'Here!' }, } } ``` But it is not too convenient, besides, what if these phrases contain a new phrase? In cases where the option offers a choice, and this the choice should be the only thing you can ask from the phrase attribute only: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!' }, {'Blue', 'Here!' }, } } ``` In this case, after the choice of the phrase, all phrase of the current context will be closed. Another common situation, you want the phrase was not hiding after her activation. This is done by setting flag to true: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!' }, {'Blue', 'Here!' }, { true, 'And which is better?', 'You choose.' }, -- phrase -- which will never be hidden } } ``` An alternative notation, with the explicit task attribute always: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!' }, {'Blue', 'Here!' }, { always = true, 'And which is better?', 'You choose.' }, -- phrase -- which will never be hidden } } ``` Another example. What if we want the phrase was presented(or hidden) on any condition? This is the handler function cond. ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!' }, {'Blue', 'Here!' }, { true, 'And which is better?', 'You choose.' }, -- phrase -- which will never be hidden }, { cond = function() return have 'Apple' end 'Do you want an Apple?', 'Thank you, no.' }; } ``` In this example, only when the player has an Apple, seem branch dialog 'do you want an Apple?'. It is sometimes convenient to perform an action at the moment when the options current level(context) of the dialogue is exhausted. For this purpose the handler function onempty. ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!' }, {'Blue', 'Here!' }, onempty = function() p [[You made your choices.]] pop() end; }, { cond = function() return have 'Apple' end 'Do you want an Apple?', 'Thank you, no.' }; } ``` Please note that when there is a method onempty, automatic return to the previous branch is not performed, it is assumed that the method onempty will do everything you need. All the above attributes can be set with any phrase. In fact on the 1st level: ``` phr = { onempty = function() p [[end of conversation.]] walkout() end; { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!' }, {'Blue', 'Here!' }, onempty = function() p [[You made your choices.]] pop() end; }, { cond = function() return have 'Apple' end 'Do you want an Apple?', 'Thank you, no.' }; } ``` ### Tags We have considered mechanisms dialogues, which already allow to create quite complex dialogs. However, these funds may not be enough. Sometimes we need to be able refer to phrases from other places dialogue. For example, to selectively enable them, or analyze them state. And make transitions from one of the branches of dialogue in others. All this is possible for phrases that have the tag. Create a sentence with tag very simple: ``` phr = { {'#?', 'What have you got?', 'Pills. The red and blue. You what?', {'#red', 'Red', 'Hold!' }, {'#blue', 'Blue', 'Here!' }, }, } ``` As you can see, the presence at the beginning of the phrase string, starting with symbol '#' - indicates the presence of the tag. For such phrases employs standard methods, such as seen or enable/disable. For example, we could do without the attribute only as follows: ``` phr = { {'#?', 'What have you got?', 'Pills. The red and blue. You what?', {'#red', 'Red', 'Hold!' cond = function(s) return not closed('#blue') end }, {'#blue', 'Blue', 'Here!', cond = function(s) return not closed('#red') end }, }, } ``` Tags, except that allow you to learn and to change the status of a particular phrases, making possible the transitions between phrases. For this purpose the functions push and pop. push(to) -- makes the transition to the phrase about remembering the position in the stack. pop([where]) -- invoked without a parameter, goes up by 1 position in the stack history. You can specify a specific tag phrase that must be in history, in this case, the refund will be credited to her. It should be noted that when you click on a push, we move not one the phrase, and the phrase list the phrase. That is, disclose it, as well as this is done for the main phrase phr. For example: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!', next = '#aboutpill' }, { 'Blue', 'Here!', next = '#aboutpill' }, }, { false, '#aboutpill', {'I made the right choice?', 'Time will tell.'} }, } ``` Here we see several techniques: - next attribute, instead of explicit descriptions of reaction as a function with push. next is a simple way to record push. - false at the beginning of the phrase makes the phrase off. She is locked off until you do an explicit enable. However, inside the phrase we can go and show the contents of the elections. Alternative entry possible with the use of the hidden attribute: { hidden = true, '#aboutpill', {'I made the right choice?', 'Time will tell.'} }, Thus it is possible to record conversations is not a tree, and linear. More one feature of the transitions is that if the phrase is not described the reaction, when the transition is triggered by the title phrase: ``` phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!', next = '#aboutpill' }, { 'Blue', 'Here!', next = '#aboutpill' }, }, { false, '#aboutpill', [[I took the pill and the wizard smiled slyly.]], {'I made the right choice?', 'Time will tell.'}, {'What next?', 'You're free.'}, }, } ``` When choosing a tablet, will be called the method header phrase '#aboutpill', and then will be presented choice. If you like linear, you might prefer the following option: ``` dlg { nam = 'dialog'; phr = { { 'What have you got?', 'Pills. The red and blue. You what?', only = true, {'Red', 'Hold!', next = '#aboutpill' }, { 'Blue', 'Here!', next = '#aboutpill' }, } } }: with { { '#aboutpill', [[I took the pill and the wizard smiled slyly.]], {'I made the right choice?', 'Time will tell.'}, {'What next?', 'You're free.'}, }, } ``` The fact that the attribute phr defines the first object of the room. But you can fill the room objects in the usual way: by setting the obj or with. Since entering the dialogue reveals the 1st phrase, then the rest phrase you will not see (pay attention to the phrase '#aboutpill' not worth itfalse), but you will be able to do transitions on these phrases. ### Methods As you already know, objects in an INSTEAD may be able open/closed off/turned on. This corresponds to the phrase dialogue? For common phrases, after activation of the choice phrase _closes_. When re-entering the dialogue, the phrases get _opened_. For phrases with always = true (or true at the beginning of the definition) -- this the closing does not occur. For phrases with hidden = true (or false at the beginning of the definition) -- the phrase will be created as disabled. It will not be visible until until is explicitly enabled. For phrases with cond(), every time you browse phrases is called this method, and depending on the return value (true/not true) phrase turns on or off. Knowing this behavior, you can hide/show and analyze phrase standard functions: disable / enable / empty / open / close / closed / disabled and so on... However, to do this you can only in the dialogue, as all the phrases get identified by tags. If you want to modify condition/parse phrases from other rooms you can: - to give the phrase name is { nam = 'name' }... - search for the phrase on the tag in the other room: local ph = lookup('#tag', 'dialogue') and then work with it; With regard to functions push/pop then you can call it explicitly as methods of dialogue, for example: _'dialog':push '#new' But better to do it in the dialogue, for example, in enter. In addition, there is a method :reset, which resets the stack and sets the starting phrase, for example: enter = function(s) s:reset '#start' end > It should be noted that when you make a enable/disable/open/close phrase, > then you perform the action exactly over this phrase, not over phrases > included inside. But since the showing phrases engine stop on/off / closed > facility-phrase and will not be included inside, that's enough. ## Special objects In STEAD3 there are special objects that perform specific functions. All such objects can be divided into two class: 1. System objects @; 2. Substitution. System objects are objects whose name begins with the character '@' or '$'. Such objects are usually modular. They are not destroyed at the death of the game world (for example, when uploading game file, when loading the game from save, and so on). Examples of objects: @timer, @prefs, @snd. Such objects, in addition to their special functions, can be used the link, without explicitly putting the object on the stage or the stock, but the mechanism of action of these objects are special. ### The object '@' Usually, you do not need to work with such objects, but as example, consider the implementation of 'links'. Suppose we want to make a link, clicking on which we will move in the other room. Of course, we could add the object to the scene, but it's worth we do it in such a simple case? How we can help the system object? ``` obj { nam = '@walk'; act = function(s, w) walk(w, false, false) end; } room { nam = 'main'; title = 'Home'; decor = [[Start {@start walk|adventure}]]; } ``` When you click on the link "adventure" method will be called act-object '@walk' with the parameter "start". In fact, in the standard library stdlib is already the object filename with '@' which allows you to do your handlers the following links follows: ``` xact.walk = walk room { nam = 'main'; title = 'Home'; decor = [[Start {@ start walk|adventure}]]; } ``` Note the space after @. This entry does the following: - takes an object with '@' (this object is created by the library stdlib); - takes his act; - causes act with the parameters of the walk and start; - act object the '@' looks at the array xact; - walk detects a method that will be called from the array xact; - start is a parameter of this method. Another example: ``` xact.myprint = function(w) p (w) end room { nam = 'main'; title = 'Home'; decor = [[Push {@ myprint "hello world"|the button}]]; } ``` ### Lookup Objects whose name begins with the character '$' are also considered system objects, but they work differently. If the output text is found on the link: {$my a b c|text} The following happens: 1. Does the object $my; 2. Taken act the object $my; 3. Act is called: _'$my'(a, b, c, text); 4. The returned string replaces the entire structure {...}. Thus, the objects play the role of a wildcard. Why is it necessary? Imagine that you developed a module, which turns write from a text view in the graphics. You write object $math which in its act method converts text to a graphic image (sprite) and returns it in the text stream. Then to use this module extremely simple example: {$math|(2+3*x)/y^2} ## Dynamic events You can define handlers that run every time when the game time increments by one. Usually, it makes sense for the living characters, or any background processes of the game. The algorithm of step games looks like this: - The player clicks on the link; - Reaction, 'act', 'use", 'inv', 'tak', the inspection of the scene (click on the name scene) or transition into another scene; - Dynamic events; - Output a new state of the scene. For example, make a snow leopard alive: ``` obj { nam = 'Barsik'; {- do not save the array lf lf = { [1] = 'Barsik is moving in my bosom.', [2] = 'Barsik looks out from his bosom.', [3] = 'Barsik purring in my bosom.', [4] = 'Barsik shivers in my bosom.', [5] = 'I feel Barsik heat in his bosom.', [6] = 'Barsik sticks his head out of his pocket and looks around.', }; }; life = function(s) local r = rnd(5); if r > 2 then -- doing this is not always return; end r = rnd(#s.lf); -- the # symbol is the number of elements in the array p(s.lf[ r]); -- derive one of the 6 States of the snow leopard end; ... ``` And here is the point in the game, when snow leopard gets to us in thy bosom. take 'snow leopard' -- add it to your inventory lifeon 'Barsik' -- to revive the cat! Any object (including the stage) can have its own handler, 'life', called each tick of the game if the object was added to the list live objects using the 'lifeon'. Don't forget to remove live objects from the list using the 'lifeoff' when they are no longer needed. It is possible to do this, for example, in the handler of 'exit' or by any other method. > If your game is a lot of "live" objects, you can ask them > a clear position in the list, adding. For this, use > second numerical parameter (non-negative integer) 'lifeon', > the lower the number the higher the priority. 1 -- the highest. Or you > you can use the attribute of the pri object. However, this attribute > will affect the priority of the object in any list. If you need a background process in some room, send it in 'enter' and remove the 'exit', for example: ``` room { nam = 'In the basement'; dsc = [[it's dark in Here!]]; enter = function(s) lifeon(s); end; exit = function(s) lifeoff(s); end; life = function(s) if rnd(10) > 8 then p [[I heard something rustling!]]; -- occasionally to scare the player rustles end end; way = { 'Home' }; } ``` If you need to determine whether the transfer of the player from one scene to another, use 'player\_moved()'. ``` obj { nam = 'flashlight'; on = false; life = function(s) if player_moved() then -- put out the torch transitions s.on = false p "I turned off the flashlight." return end; end; ... } ``` For tracking moving events, use 'time()' or an auxiliary counter variable. To determine the location player -- 'here()'. For determining that the object is "alive" -- the 'live()'. ``` obj { nam = 'dynamite'; timer = 0; used = function(s, w) if w^'match' then -- match? if live(s) then return "it's Already lit!" end p "I have lit the dynamite." lifeon(s) return end return false-if not match end; life = function(s) s.timer = s.timer + 1 if s.timer == 5 then lifeoff(s) if here() == where(s) then p [[the Dynamite exploded right next to me!]] else p [[I heard an explosion somewhere.]]; end end end; ... } ``` If 'life' handler returns the event text, it is printed after the description of the scene. You can return from a handler for 'life' second return code ('true' or 'false'). If you return true-it is a sign of important the event, which will be displayed to describe the objects in the scene, for example: p 'In walked the guard.' return true Or: return 'you entered the room the security guard.', true If you return false, the chain of life methods will fail on you. It easy to do when performing a walk from the life, for example: life = function() walk 'theend' return false -- this is the last life end If you want to block 'life' handlers in some of the rooms, use the module 'nolife'. For example: ``` require "noinv" require "nolife" dlg { nam = 'Guard'; noinv = true; nolife = true; ... } ``` We should also consider the transition of the player from 'life' handler. If you are going to use the function 'walk' inside'life', then you should consider the following behavior. If 'life' takes the player to a new location, it is usually assumed you: 1. Clear withdrawal reactions: game:reaction(false); 2. Cleanse withdrawal live methods at the moment: game:events(false, false) 3. Do the walk. 4. Stop the chain of life of the call using return false; Some points required clarification. game:reaction() -- allows you to take/modify the output of the reaction user, if set to false this means to reset the reaction. game:events () -- allows you to take/change / withdrawal of life methods. Inas choices are made a priority and not a priority criteria false we cancelled the whole output of the previous life methods. The standard library has a function life_walk(), which makes the described actions. You just have to return false. ## Graphics Graphic interpreter INSTEAD analyzes the attribute of the scene 'pic', sees it as the path to the picture, for example: room { pic = 'gfx/home.png'; nam = 'Home'; dsc = 'I am home'; }; __Important!__ Use in ways only direct '/'. Also, it is strongly recommended to use the names of directories and files only Latin lowercase characters. This way you will protect your game from compatibility problems and it will work on all architectural platforms where ported INSTEAD. Of course, 'pic' can be function, expanding the possibilities of the developer. If the current scene does not defined the attribute 'pic' attribute is taken 'game.pic'. If the picture is not displayed. Supports all common image formats, but I I recommend you to use 'png' and where () 'jpg'. You can use as images animated GIF files. Be sure that they are GIF files, and not WEBP format or PNG format, which are unsupported. You can embed the graphic images right in the text in the inventory, transitions, titles rooms and 'dsc' using the function 'fmt.img' (this will switch on the module fmt). For example: ``` require "fmt" obj { nam = 'Apple' disp = 'Apple'..fmt.img('img/apple.png'); } ``` That, at least, the scene picture always should be made in the form of 'pic' attribute, not insertion 'fmt.img' to 'dsc'. The fact that the picture of the scene scales on other algorithm. Pictures 'fmt.img' get scaled in accordance with the settings INSTEAD (the scale theme), and 'pic' -- also takes into account the size of the image. In addition, the images 'pic' have other properties, for example, the ability to track coordinates of mouse clicks. If you put 'fmt.img' inside { and }, you get a graphical link. `` obj { nam = 'Apple'; disp = 'Apple' ..img('img/apple.png'); dsc = function(s) p ("the floor is {Apple",fmt.img 'img/apple.png', "}"); -- other options: -- return "On the floor lies {Apple"..fmt.img('img/apple.png').."}"; -- p "On the floor lies {Apple"..fmt.img('img/apple.png').."}"; -- or dsc = "the floor is {Apple"..fmt.img('img/apple.png').."}"; end; } `` INSTEAD supports wrapping images with text. If the picture is inserted using the function 'fmt.imgl'/'fmt.imgr', it will located at the left/right edge. __Important!__ > Images inserted into text using 'fmt.imgl/fmt.imgr' can't be > links!!! Use them only for decorative purposes. To set spacing around an image, use the 'pad' example: -- indentation 16 from each edge fmt.imgl 'pad:16,picture.png' -- margins: top 0, right 16, bottom 16, left 4 fmt.imgl 'pad:0 16 16 4,picture.png' -- margins: top 0, right 16, bottom 0, left 16 fmt.imgl 'pad:0 16,picture.png' You can use pseudo-files for images and rectangles empty areas: ``` dsc = fmt.img 'blank:32x32'..[[Line with blank image.]]; dsc = fmt.img 'box:32x32,red,128'..[[Line with red semi-transparent square.]]; ``` INSTEAD can process compound images, for example: pic = 'gfx/mycat.png;gfx/milk.png@120,25;gfx/fish.png@32,32'; Thus, the composite image is a set of paths to images, separated by ';'. The second and subsequent components can contain Postfix in the form @x\coordinate,y\coordinate%, where the coordinate 0,0 corresponds to the left the top corner of the image. The total size of the image is considered equal to the total amount of the first component of the composite image, that is, the first component (in our example-gfx/mycat.png) plays the role of canvas, and subsequent components are superimposed on this canvas. The overlay is for the upper left corner of the overlaypictures. If you need to overlay was the center of the overlay images, use before the coordinate prefix "c", for example: pic = 'gfx/galaxy.png;gfx/star.png@c128,132'; Having as a function the formation of the path of the composite pictures, you can generate an image based on the game state. If you are in the game tied to any coordinates images or their sizes, do it in relation to the original of image sizes. Scaling topic under specified playerthe resolution INSTEAD he will convert the coordinates (with the coordinates for the game look like the game is running without scaling). However, there may be a small error of computation. If you do not have enough of the features described in this Chapter, I examine the module "sprite", which provides more opportunities for graphic design. But I highly recommend not to do it in his the first game. ## Music To work with music and sounds you will need the snd module. require "snd" The interpreter plays in the cycle of the current music that is set using the function: 'snd.music(music file)'. __Important!__ Use in ways only direct '/'. Also, it is strongly it is recommended to use the names of directories and files only Latin lowercase characters. This way you will protect your game from compatibility problems and it will work on all architectural platforms where ported INSTEAD. Supports most music formats, but we strongly it is recommended to use the format 'ogg' as it supported in the best way in all versions INSTEAD (for different platforms). __Important!__ Caution should be exercised when using tracker music as some Linux distributions can be a problem when playing certain files (error in bundle libraries SDL_mixer and libmikmod). Also, if you use the 'mid' files, be prepared for the fact that the player will hear them only in the Windows version INSTEAD (as in most cases Unix version of SDL_mixer compiled without support "timidity"). As the frequency of the music files, use a frequency multiple of 11025. ``` room { pic = 'gfx/street.png'; enter = function() snd.music 'mus/rain.ogg' end; nam = 'on the street'; dsc = 'it is raining outside.'; }; ``` 'snd.music()' without a parameter returns the current track name. In function 'snd.music()' you can pass second parameter-the number playout (cycles). To get the current counter you can use 'snd.music()' no parameters -- the second return value. 0 -- it is eternal cycle. 1..n-the number of playbacks. -1 -- the playback of the current track is finished. In order to cancel the music, you can use 'snd.stop\_music()' In order to know if the music is: snd.music_playing() You can set the rise time and attenuation of music, by calling: snd.music_fading(o [i]) Here o is the time in milliseconds. for attenuation and i is the time in milliseconds. to rise music. If you specify only one parameter -- both times are considered as same. After the call, the settings will affect playback of all music files. For playback of sounds using snd.play()'. Highly it is recommended to use the format 'ogg', although most common sound formats will also work. The distinction between music and sound file is that the engine monitoring the process of playing music and saves/restores the currently played track. Exiting the game and downloading it again, the player hear the same music that you heard when you exit. Sounds generally indicate short-term effects, and the engine does not store or restores sound events. So, if a player did not have time to listen the sound of the shot and left the game, after downloading the file, save it not hear the sound (or end) again. However, if you consider the fact that 'snd.play()' allows you to run looped sounds, the difference between music and sound becomes not so unambiguous. So, the definition of the function: 'snd.play(file [channel], [loop])', where: - file -- path and / or name of the sound file; - channel -- channel number [0..7]; If not specified, get first free. - cycle -- the number of playbacks 1..n, 0 -- looping. To stop playback you can use 'snd.stop()'. For stop sound in a certain channel 'snd.stop(channel)'. __Important!__ > If you're using looped sounds, you will have to reset their state (run again > with 'snd.sound()') in function 'start()' For example: ``` global 'wind_blow' (false) ... function start() if wind_blow then snd.play('snd/wind.ogg', 0) end end ``` If you are not fairly described here functions for working with sound use the full description of the module "snd". ## The formatting of the output Usually INSTEAD deals with formatting and design output. For example, the stage separates static from dynamic. Highlights italicize the actions of the player. Moves focus to the change in the text and etc Modules like "fmt" improve the output quality of the game without additional effort on the part of the author. For example: require 'fmt' fmt.para = true -- enable indentation of paragraphs And your game will look much better. If you need some automatic processing of the displayed text, you can enable the module "fmt" and define the function 'fmt.filter'. For example: ``` require "fmt" fmt.filter = function(s, state) -- s -- output -- state -- true if this is the beat game (output stage) if state then return 'This string will be added to the beginning of output\n'..s; end return s end ``` A good game for INSTEAD not do your design in addition to splitting the text 'dsc' paragraphs using the characters '^^',so think, and whether you want to design your games manually? However, sometimes it's still necessary. > Attention! By default, all trailing and starting newlines, > spaces and tabs are cut from the output handlers. So > as usual, they are meaningless and even harmful. In rare cases, > the author may want more control over the output, then it > maybe ask std.strip\_call as false in init() or start(), > for example: ``` std.strip_call = false obj { dsc = [[There is {Apple}.^^^^]] --- now the line -- will not be clipped, even though it's weird } ``` > But usually such manual formatting indicates a bad > the style. For the design stage it is better to use decor and/or > substitution. ### Formatting You can do simple text formatting using the functions: - fmt.c(string) - place in the center. - fmt.r(string) - place right; - fmt.l(line) - place left; - fmt.top(row) - top row; - fmt.bottom(string) - the bottom line; - fmt.middle(line) - middle line (default). For example: ``` room { nam = 'main'; title = 'Welcome'; dsc = fmt.c 'Welcome!'; -- if a function has only 1 parameter, -- you can omit the parentheses; } ``` These features affect not only text but also images, inserted using "fmt.img()'. It should be noted that if you use several functions formatting, it is assumed that they belong to different rows (paragraphs). Otherwise, the result is undefined. Or abuse the text into paragraphs with '^' or 'pn()'. INSTEAD in the derivation removes the extra spaces. This means that no matter how many spaces you insert between words, are all the same at the conclusion they will not be counted for calculating the distance between words. Sometimes it could be a problem. You can create _non-breaking line_ using: fmt.nb(row). For example, the module "fmt" uses a continuous line to create indentation at the beginning of paragraphs. Also, 'fmt.nb' can to be useful to output special characters. We can say that the whole string parameter 'fmt.nb' is perceived by the engine as one big word. Another example. If you use the underline text, the spaces between words are not underlined. When using 'fmt.nb' the gaps will also be highlighted. INSTEAD not support the display of tables, but the conclusion is simple tabular data you can use 'fmt.tab()'. This function used for absolute positioning in the line (tab delimited). fmt.tab(position, [center]) _Position_, is a text or numeric parameter. If you specify a numeric parameter, it is treated as position in pixels. If it is set in a string parameter 'number%', it is perceived as position, expressed in percentage of the width of the output window scene. The optional parameter center specifies the position in the following'fmt.tab' word that will be placed at the specified offset in the line. Positions can be as follows: - left; - right; - center. By default, it is considered that the option "left". So, for example: ``` room { nam = 'main'; disp = 'Start'; -- the location of the 'Start!' in the middle of the line dsc = fmt.tab('50%', 'center')..'Start!'; } ``` Of course, not a very good example, as the same could make using 'fmt.c()'. A more successful example. dsc = function(s) p(fmt.tab '0%') p "Left"; p(fmt.tab '100%', 'right') p Right; end In fact, the only situation where the use of 'fmt.tab()' justified -- is the output of table data. It should be noted that in a situation when we write something like: -- the location of the 'Times' on the center line dsc = fmt.tab('50%', 'center')..'one two three!'; Only the word 'Time' is placed in the centre of the line, the rest of the words will be appended to the right of this word. If you want to center the 'Times two, three!' as one unit, use 'fmt.nb()'. -- place 'one two three!' on the center line dsc = fmt.tab('50%', 'center')..fmt.nb ('one two three!'); To INSTEAD it is also possible to perform a simple vertical formatting. To do this, use the vertical tab: fmt.y(position, [center]) As in the case of fmt.tab position is text or numeric parameter. Here it is perceived as a position of the line expressed in pixels or percentage of the height region of the scene. For example, 100% -- corresponds to the lower boundary region of the scene. 200% corresponds -- the lower boundary of the second page of output (two the height of the output pane scene). The optional parameter center specifies the position withinline on which you position: - top (upper edge); - middle (center); - bottom (for bottom-the default). It should be noted that 'fmt.y' works entirely for the line. If the line will meet a few of fmt.y, act will be the last one tab. -- the location of the 'CHAPTER I' - center stage dsc = fmt.y('100%').."CHAPTER I"; _Esli position specified by the tab, is already occupied by another row, the tab is ignored._ By default, the static part of the scene is separated from the dynamic double newline. If you do not fit, you can override 'std.scene_delim', for example: std.scene_delim = '^' -- single line You cannot change this variable in the handlers, as it is not remains, but you can set it for the entire game, or fix it manually in the function 'start()'. If you absolutely do not like how INSTEAD forms conclusion (sequence of paragraphs), you can override the function 'game.display()', which by default looks like the following: ``` game.display = function(s, state) local r, l, av, pv local reaction = s:reaction() or nil -- reaction r = std.here() if state then -- the beat of the game? reaction = iface:em(reaction) -- italic font av, pv = s:events() av = iface:em(av) - the output of "important" life pv = iface:em(pv) - output background life l = s.player:look() -- objects [and scene] -- the objects and scene end l = std.par(std.scene_delim, reaction or false, av or false, l or false pv or false) or " return l end; ``` The fact that I have brought here this code does not mean that I recommend to override this feature. On the contrary, I categorically against such strong binding to the text formatting. However, sometimes there is a situation where full control over the sequence output needed. If you write your first game, just skip this text. ### Making You can change the font style of text using combinations of features: - fmt.b(string) - bold text; - fmt.em(string) - italic; - fmt.u(string) - text that is underlined; - fmt.st(string) - text crossed out. For example: ``` room { nam = 'Intro'; title = false; dsc = function(s) p ('You are in a room: ') p (fmt.b(s)) end; } ``` > Using the function 'fmt.u' and 'fmt.st' on strings containing spaces > you will get broken lines in these places. What to avoid it, > to turn the text into _non-breaking string_: fmt.u(fmt.nb "now the unabridged" ) Strictly speaking, INSTEAD does not support simultaneous display of different fonts in the window scene (except for the different font styles), so if you require a more flexible output control, you can do the following: - Use the graphic insert 'fmt.img()'; - Use the module 'fonts', which implements the rendering different fonts at the expense module 'sprite'; - Use another engine, because most likely you use INSTEAD for other purposes. ## Constructors and inheritance __Caution!__ If you write your first game, it would be better if she was simple. For a simple game, the information in this Chapter do not need. Moreover, 90% say it's not a good described in this Chapter! If you're writing a game, where many similar objects mayyou will want to simplify their creation. You can do one of the following ways: - Create your designer; - Create a new feature class. ### Designers Constructor-a function that creates the object for you and fills his attributes as you need it. Let's consider an example. For example, in your game will be a lot of Windows. You need to create a window, any window can be break. We can write constructor 'window'. ``` window = function(v) v.window = true v.broken = false if v.dsc == nil then v.dsc = 'there is a {window}.' end v.act = function(s) if s.broken then p [[broken Window.]] else p [[it's dark outside.]] end end if v.used == nil then v.used = function(s, w) if w^'hammer' then if s.broken then p [[the Window is already broken.]] else p [[I broke the window.]] s.broken = true; end return end return false end end return obj(v) end ``` As you can see, the idea of the designers is simple. You just create the function which receives the input of the table with the attributes {} which is the constructor can fill out the desired attributes. Then this table is passed constructor obj/room/dlg and returns the resulting object. Now, create a window was easy: window { dsc = [[there is a {window}.]]; } Or, because the window is usually a static object, you can create it directly in 'obj'. obj = { window { dsc = 'In the Eastern wall there is a {window}.'; } }; Our window will be ready used method and act method. You can to check the fact that the object is a window-just checking the attribute window: use = function(s, w) if w.window then p [[the Action.]] return end return false end The condition "weakness" of the window, this attribute is broken. How to implement inheritance in the constructors? In fact, in the example above is already used inheritance. Indeed, the designer 'window" causes the other constructor 'obj', thus obtaining all the properties of conventional object. Also, the 'window' defines a variable attribute 'window', to the game, we could understand that we are dealing with a window. For example: To illustrate the inheritance mechanism, create a class of objects 'treasure', those. treasures. ``` global { score = 0 } treasure = function() local v = {} v.disp = 'treasure' v.treasure = true v.points = 100 v.dsc = function(s) p ('there is {', std.dispof(s), '}.') end; v.inv = function(s) p ('This is ', std.dispof(s), '.'); end; v.tak = function(s) score = score + s.points; -- increase the score p [[Trembling hand I took the treasure.]]; end return obj(v) end ``` Now, let's create gold, diamond and treasure chest. ``` gold = function(dsc) local v = treasure(); v.disp = 'gold'; v.gold = true; v.points = 50; v.dsc = dsc; return v end diamond = function(dsc) local v = treasure(); v.disp = 'diamond'; v.diamond = true; v.points = 200; v.dsc = dsc; return v end chest = function(dsc) local v = treasure(); v.disp = 'chest'; v.chest = true v.points = 1000; v.dsc = dsc; return v end ``` Now, in the game you can create a treasure using constructors: ``` diamond1 = diamond("In the mud, I noticed {the diamond}.") diamond2 = diamond(); -- here is the standard description of the diamond gold1 = gold("In the corner I noticed the glitter {gold}."); room { nam = 'cave'; obj = { diamond1, gold1, chest("I can see {chest}!") }; } ``` In fact, how to write constructor functions and implement the inheritance principle, depends only on you. Choose the most simple and intuitive way. When writing constructors, it is sometimes useful to make a call handler the way it does INSTEAD. To do this, use 'std.call(object, method, options)', this function will return the reaction of the attribute as a string. For example, consider a modification 'window', which is that you can define your own the reaction to the inspection window, which will be executed after the standard posts about what is the broken window (if it is broken). ``` window = function(nam, dsc, what) local v = {} -- creates an empty table -- fill it v.window = true v.what = what v.broken = false if dsc == nil then v.dsc = 'there is a {window}' end v.act = function(s) if s.broken then p [[broken Window.]] end local r, v = stead.call(s, 'what') if v then -- the handler is executed? p(r) else p [[it's dark outside.]] end end return obj(v) end ``` Thus, we can create a window to specify the third parameter, where to define a function or a string that will be occurring at the same time the inspection window. The message that the window was broken (if it really broken), you will see before this response. ### Feature class The constructors of objects are widely used in STEAD2. IN STEAD3 obj/dlg/room are implemented as object classes. Class of objects is to create for those occasions when the behavior of the created object is not fits into standard objects obj/room/dlg and you want to change methods of the class. Changing a class method, for example, you can generally to change how the object looks in the scene. As an example, consider creating a class "container". The container can store other objects to be closed and open. ``` -- create own class container cont = std.class({ -- create the class cont __cont_type = true; -- to determine the type of the object display = function(s) -- overridable method of displaying the subject local d = std.obj.display(s) if s:closed() or #s.obj == 0 then return d end local c = s.cont or 'Inside:' -- descriptor content local empty = true for i = 1, #s.obj do local o = s.obj[i] if o:visible() then empty = false if i > 1 then c = c .. ', ' end c = c..'{'..std.nameof(o)..'|'..std.dispof(o)..'}' end end if empty then return d end c = c .. '.' return std.par(std.space_delim, d, c) end; } std.obj) -- we inherit from the default object ``` After that, you can create containers like this: ``` cont { nam = 'box'; dsc = [[there is {box}.]]; cont = 'box: '; }: with { 'Apple', 'pear'; } ``` When the container is opened, you will see a description box, and the contents of the box in the row of links: In the box: Apple, pear. dsc objects Apple and pear are also shown if they are set. If you want to hide dsc objects when opening the container, leaving only the names of the objects, you can perform the following modification: ``` -- replace the function of display of any object -- if the object is inside the container, don't call it dsc std.obj.display = function(self) local w = self:where () - where is the object? if not std.is_obj(w, 'cont') then -- if not in a container local d = std.call(self, 'dsc') return d end end ``` Unfortunately, a detailed description of classes is beyond the scope of this manual, these things will be discussed in another guide module developers. In the meantime, for your first game, you don't need to write your own object classes. ## Useful tips ### Split files When your game gets large, the location of its code entirely in 'main3.lua' -- bad idea. To break the text of the game files you can use 'include'. You must use 'include' in a global context so that while loading 'main3.lua' is loaded and all the remaining fragments of the game, for example. ``` -- main3.lua include "episode1" -- .lua can be omitted include "npc" include "start" room { nam = 'main'; ... ``` How to split a source text file depends on you. I use the files in accordance with the episodes of the game (which is usually mild linked), but you can create files to store separately rooms, objects, dialogues, etc. Is a matter of personal convenience. There is also the possibility to dynamically load parts of the game (with the ability to redefine objects). To do this, you you can use the 'gamefile': ``` ... act = function() gamefile ("episode2") end -- .lua can be omitted ... ``` > Attention! If your game defines a function init(), > loadable parts of it must be present! Otherwise > case, after uploading the file, will be called the current function init () > that is not usually desirable. 'gamefile()' also allows you to upload a new file and forget stackprevious downloads by launching this new file as an independent game. To do this, set the second parameter as 'true'. Keep in mind that existing modules remain and survive the operation gamefile in both cases. 'gamefile()' can only be used in handlers. act = function() gamefile ("episode3.lua", true); end; In the second option 'gamefile()' can be used to design multilingual games, or game collections, where the actual shell running a standalone game. ### Menu The default behavior of the item of inventory is that the playerneed to make two mouse clicks. This is necessary because each any inventory item can be used on another object or scene inventory. After the second click happens games the beat games. Sometimes this behavior may be undesirable. You might want to make a game in which game mechanics differs from the classical INSTEAD games. Then you may need menu. Menu is an element of inventory, which is triggered on the first click. When this menu can inform the engine that the action is not a game tact. Thus, using the menus you can create in the area inventory management a game of any complexity. For example, there is module "proxymenu" that implements control of the game style quests on the ZX-spectrum. In the game "Mansion" his control, which introduces a few action modifiers, etc. So, you can do the menu in the inventory area, identifying objects with type 'menu'. In this case, the menu handler ('act') will be called after one click of the mouse. If the handler returns false, the game state does not change. For example, the implementation of the pocket: ``` menu { state = false; nam = 'pocket'; disp = function(s) if s.state then return fmt.u('pocket'); -- emphasize active pocket end return 'pocket'; end; gen = function(s) if s.state then s:open(); -- show all the items in the pocket else s:close(); -- hide all the items in the pocket end return s end; act = function(s) s.state = not s.state -- change state s:gen (); - to open or close the pocket end; }: with { obj { nam = 'knife'; inv = 'This is knife'; }; } function init() take 'pocket':gen() end ``` ### The status of the player Sometimes there is a desire displays some status. For example,the number of points the state of the hero or finally time days. INSTEAD does not provide any other areas of withdrawal, except scenes and inventory, therefore, the simplest way to output the status is output to the zone equipment. Below is an implementation of player status as a text that appears in the inventory, but cannot be selected, that is, looks just as text. ``` global { life = 10; power = 10; } stat { -- stat-object status nam = 'status'; disp = function(s) pn ('Life: ', life) pn ('Power: ', power) end }; function init() take the 'status' end ``` ### walk from handlers to the onenter and onexit You can do the 'walk' of the handlers 'the onenter' and 'onexit'. For example, 'path' implemented with a handler 'the onenter', which puts the player in the other room. It is recommended to return from onexit/false in the onenter event, if you do the walk of these handlers. ### Encoding of the source code of the game If you do not want to show the source code of their games, you can to encode source code using the command-line option the '-encode': sdl-instead-encode [output path] And use the encoded file using the normal include/gamefile. However, for this you have to write at the beginning of main3.lua: std.dofile = std.doencfile The main file 'main3.lua' must be left open. This by the way, the diagram looks as follows ('game.lua' -- encoded file): -- $Name: My closed game!$ std.dofile = std.doencfile include "game"; -- no one knows how to pass it! __Important!__ > Do not use the following with 'luac', as 'luac' creates > platform-dependent code! However, the following can be > used to find errors in your code. ### Boxing resources You can package the game resources (graphics, music, themes) in the file resources '.idf' placing all the resources in the directory 'data' and start INSTEAD: sdl-instead-idf Thus, in the current directory will be created file 'data.idf'. Place it in the directory with the game. Now resources game separate files can be removed (of course leaving himself the original files). You can pack in format.idf' the whole game: sdl-instead-idf Game 'idf' can be run as a normal game 'instead' (as if it were a directory) and also from the command line: sdl-instead game.idf ### Switching between players You can create a game with multiple characters and from time to time to switch between them (see 'change_pl()'). But you can also to use this trick in order to be able to switch between different types of inventory. ### Use settings handler The code example. obj { nam = 'stone'; dsc = 'On the edge of lies {rock}.'; act = function() remove 'stone'; p 'I pushed the stone, it fell and flew down...'; end Act handler could look simpler: act = function(s) remove(s); p 'I pushed the stone, it fell and flew down...'; end ### Special status handlers Handler usually returns the text in the form return "text messages." Or with the functions p()/pr()/pn()/pf(). In addition, there are special statuses that can be useful when developing game. The return status is false: return false This status means that the handler has not fulfilled its function and needsto be ignored. Typically, the engine in this case, it will call the handler by default. You can also return a special status: return true, false In this mode only equipment (but not stage) will be redrawn. This status is useful for implementing menu the field inventory. There is another special status: std.nop(). It can be used just like a function call at the end of the handler or together with the return. return std.nop() -- ... or ... std.nop() -- then the end of the function or return In this case, the contents of the scene will remain the same as lastthe beat game (even string a reaction will be old). This status conveniently be used in conjunction with the module theme, when you need to change the design of the game on the fly and redraw the frame with the new parameters theme. ### Timer For asynchronous events bound to real time. it is possible to use the timer. In fact, you should have a good think about whether in the adventure game to use timer. Usually, it is not perceived too favorably. With the other hand, the timer can be used to control music or design purposes. To use the timer, you should connect the module "timer". require "timer" The timer is programmed using the object "timer". - timer:set(MS) -- set timer interval in milliseconds; - timer:stop() -- stop the timer. When the timer fires, calls a handler game.timer. If game.timer returns false, the scene is not redrawn. In otherwise, the return value is output as the response. You can do local for room handlers 'timer'. If the room declared the handler "timer", it is invoked instead'game.timer'. If it returns false -- the game is called.timer. For example: ``` game.timer = function(s) if time() > 10 then return false end snd.play 'gfx/beep.ogg'; p ("Timer:", time()) end function init() timer:set(1000) -- time in second end ``` ``` room { enter = function(s) timer:set(1000); end; timer = function(s) timer:stop(); walk 'комната2'; end; nam = 'timer Test'; dsc = [[Wait.]]; } ``` As the timer gets to the save file, so you don't you need to take care to restore it. You can return from timer special status: return true, false In this mode only the area of inventory will be redrawn. It is possible use of statuses like hours. In addition, INSTEAD there is the ability to track intervals the time in milliseconds. To do this, use the function instead.ticks(). The function returns the number of milliseconds elapsed since the start of the game. ### Music player You can write your game music player, created on the basis of a living object, for example: ``` -- playing tracks in random order require "snd" obj { { tracks = {"mus/astro2.mod", "mus/aws_chas.xm", "mus/dmageofd.xm", "mus/doomsday.s3m"}; }; nam = 'player'; life = function(s) if not snd.music_playing() then local n = s.tracks[rnd(#s.tracks)] snd.music(n, 1); end end; }:lifeon(); ``` Below is an example of a more complex player. Change the track if it ended or it has been more than 2 minutes and the player goes from room to room. In each track you can specify the number of playbacks (0 - a looped track): ``` require "timer" global { track_time = 0 }; obj { nam = 'player'; pos = 0; { playlist = { '01 Frozen sun.ogg', 0, '02 Thinking.ogg', 0, '03 Melancholy.ogg', 0, '04 Everyday happiness.ogg', 0, '10 Good morning again.ogg', 1, '15 [Bonus track] The end (demo cover).ogg', 1 }; }; tick = function(s) if snd.music_playing() and ( track_time < 120 or not player_moved() ) then return end track_time = 0 if s.pos == 0 then s.pos = 1 else s.pos = s.pos + 2 end if s.pos > #s.playlist then s.pos = 1 end snd.music('mus/'..s.playlist[s.pos], s.playlist[s.pos + 1]); end; } game.timer = function(s) track_time = track_time + 1 music_player:tick(); end function init() timer:set(1000) end ``` ### Live objects If your hero needs a friend, one of the ways can be a method 'life' of this character, which always moves the object to the location player: ``` obj { nam = 'horse'; dsc = 'I am standing Next to {the horse}.'; act = [[My horse.]]; life = function(s) if player_moved() then place(s); end end; } function init() lifeon 'horse'; -- immediately revive the horse end ``` ### Menu You can call from the game menu INSTEAD of using the function'istead.menu()'. If the option ask: 'save', 'load' or 'quit', it will be caused by the relevant section on the menu. ### Dynamic object creation Ordinary objects and rooms cannot be created "on the fly". Usually you create them in the global namespace lua file. However, there are games in which the number of objects is unknown in advance, or the number objects large and they are added as the game progresses. In INSTEAD, there is a way to create any object on the fly. For this you will need to write constructor your object and to use the function 'new'. The constructor must be declared. So, you can use the functions 'new' and 'delete' for creating and removal of dynamic objects. Examples: ``` declare 'box' (function() return obj { dsc = [[There is {box}.]]; tak = [[I picked up a box.]]; } end) local o = new (box); take(o); ``` ``` declare 'box' (function(dsc) return obj { dsc = dsc; tak = [[I picked up a box.]]; } end) take(new(box 'In the corner {box}')) ``` 'new' takes first argument is declared as a constructor function, and all other parameters-as arguments constructor. The result of the constructor should be object. ``` function myconstructor() local v = {} v.disp = 'test object' v.act = 'Test response' return obj(v) end ``` > Attention! When the object is created the constructor should only rely > on information derived from parameters! The fact that the creation of > object when loading occurs in the beginning, when the environment of the world > still not fully loaded! As parameters are supported > simple types: strings, tables, numbers, Booleans > values. Undeclared functions and lists will not work. If you want to destroy the object by its name or the link-variable use: purge(o) -- remove from all lists delete(o) - release the object In this case, delete this is the delete the object from INSTEAD, rather than analogue remove() or purge(). Usually, it makes little sense to do the delete. Only if the subject will never be needed in a game, or are you going to recreate an object with the same name, it makes sense to release it with using delete(). A more practically useful example: ``` -- declare the constructor path declare 'make_path' (function(v) return path(v) end) -- dynamic transition -- create a new object -- and put it in a ways() put( new (make_path, { 'transition', 'комната2'}, ways()) ``` ### The ban on saving a game Sometimes you may want to forbid the player to do conservation in game. For example, if we are talking about scenes where an important element is case, or for short games where the loser needs to be fatal and require restarting the game. To control the save function uses the attribute 'instead.nosave'. For example: instead.nosave = true -- disable the preservation of If you want to prevent save not everywhere, but in some scenes, make 'instead.nosave' to the view function or change the condition attribute on the fly -- it gets to a file saves. ``` -- prohibit -- save the rooms that contain the nosave attribute. instead.nosave = function() return here().nosave end ``` It should be noted that the ban on conservation does not mean prohibition AutoSave. To control the AutoSave, use the same attribute 'instead.noautosave'. > You can explicitly save a game with a call to: > 'instead.autosave([slot number])'; If the slot number is not specified, then > the game will be saved under slot 'AutoSave'. Keep in mind that > saves the state of __after__ the completion of the current step of game. ### Definition of an object type In INSTEAD, there are two ways to determine the type of the object. First - using the function std.is_obj(variable, [type]). For example: ``` a = room { nam = 'object'; }; dprint(std.is_obj(a)) -- will print true dprint(std.is_obj('object')) -- will print false dprint(std.is_obj(a, 'room')) -- will print true dprint(std.is_obj(a.obj, 'list')) -- will print true ``` std.is_obj() is useful for determining the type of variable or argument function. The second method is to use the type method: ``` a = room { nam = 'object'; }; dprint(a:type 'room') -- will print true ``` ## Topics for sdl-instead Graphic interpreter supports the theme engine. Tema is a directory, the file 'theme.ini' inside. The theme, which is the minimum required -- is the theme 'default'. This topic is always loaded first. All other topics inherit from it and can partially or completely replace it settings. Themes are chosen by the user via menu settings, but the game may contain its own subject and thus the influence on your appearance. In this case, the directory the game should be a file 'theme.ini'. However, the user is free to disable this mechanism, while the interpreter will warn about violation of the creative concept the author of the game. The syntax of 'theme.ini' is very simple. = or ; comment Values can be of the following types: string, color, number. The color is specified in the form #rgb where r g and b color components in hexadecimal. Additionally, some basic colorsrecognized by their names. Example: yellowgreen, or violet. Parameters can take values: - scr.w = width of the playing space, in pixels (number) - scr.h = height of the playing space, in pixels (number) - scr.col.bg = background color - scr.gfx.scalable = [0/1/2] (0 - don't scale topic 1 - scalable 2 scalable without smoothing), since version 2.2.0 available optional [4/5/6]: 4 - fully scalable (non-scalable fonts), 5 - scalable, with non-scalable fonts, 6 - scaled without smoothing, with not a scalable font - scr.scale_aware = [0|1|2] (adaptive themes support: 0 - virtual resolution, 1 - real proportions, 2 - real resolution) - scr.dpi = [dpi|dpi1-dpi2] (theme dpi, 96 by default) - scr.gfx.scale = scale (image scaling, 1.0 by default) - scr.gfx.bg = path to the background image (string) - scr.gfx.cursor.x = the x coordinate of the cursor center (number) - scr.gfx.cursor.y = the y coordinate of the cursor center (number) - scr.gfx.cursor.normal = path to the cursor picture file (string) - scr.gfx.cursor.use = path to the cursor picture file usage (string) - scr.gfx.use = path to the image-indicator of use (string) - scr.gfx.pad = padding for scrollbars and menu edges (number) - scr.gfx.x, scr.gfx.y, scr.gfx.w, scr.gfx.h = coordinates, width and the height of the window images. Region in which is located the picture scene. Interpretation depends on the mode of visit (number) - win.gfx.h - synonymous with scr.gfx.h (for compatibility) - scr.gfx.icon = path to the file-the icon of the game (OS dependent option, may to work correctly in some cases) - scr.gfx.mode = mode location (line fixed, embedded or float). Sets the mode of the image. embedded-the picture is part of the content of the main window, the parameters of the scr.gfx.x, scr.gfx.y, scr.gfx.w are ignored. float-the picture located at the specified coordinates (scr.gfx.x, scr.gfx.y) and scales to the size scr.gfx.w x scr.gfx.if h exceeds it. fixed-the picture is part of a scene in embedded mode, but does not scroll along with text and located directly above it. Available modifications mode modifiers float 'left/right/center/middle/bottom/top', specifies how to place an image in the field scr.gfx. For example: float-top-left; - win.scroll.mode = [0/1/2/3] mode scrolling region of the scene. 0 - no auto-scroll 1 - scroll to change the text, 2 scroll to change only if the change is not visible, 3 - always in the end; - win.x, win.y, win.w, win.h = coordinates, width and height of the main window. Region which is a description of the scene (number) - win.fnt.name = path to the font file (string). Hereinafter, font may contain a description of all styles, for example: {sans,sans-b and sans-i,sans-bi}.ttf (the font style set to regular, bold, italic and bold-italic). You can omit some of the faces, and the engine itself will generate them based on the normal style, for example: {sans, sans-i}.ttf ( set only regular and italic);- win.align = center/left/right/justify (text alignment in the window scene); - win.fnt.size = the font size of the main window (size) - win.fnt.height = line spacing as the floating the decimal point (1.0 is default) - win.gfx.up, win.gfx.down = paths to the image files skallerup up/down for the main window (string) - win.up.x, win.up.y, win.down.x, win.down.y = coordinates. (coordinate or -1) - win.col.fg = text color of the main window (color) - win.col.link = link color for the main window (color) - win.col.alink = active link color for the main window (color)- win.ways.mode = top/bottom (to specify the location of the jump list, default top -- on top of the scene) - inv.x, inv.y, inv.w, inv.h = coordinates, width and height of region inventory. (number) - inv.mode = string mode inventory (horizontal or vertical). In horizontal inventory mode in one line can be several items. In vertical mode, each line of the inventory contains only one thing. There are modifications to (-left/ right/center). You can set the mode to disabled if your the game doesn't need an inventory; - inv.col.fg = text color tools (color)- inv.col.link = link color tools (color) - inv.col.alink = active link color for the inventory (the color) - inv.fnt.name = path to font file the inventory (row) - inv.fnt.size = the font size of the inventory (size) - inv.fnt.height = line spacing as the floating the decimal point (1.0 is default) - inv.gfx.up, inv.gfx.down = paths to the image files skallerup up/down of equipment (line) - inv.up.x, inv.up.y, inv.down.x, inv.down.y = coordinates. (coordinate or -1) - menu.col.bg = background (color) - menu.col.fg = text color menu (color)- menu.col.link = menu link color (color) - menu.col.alink = active link color menu (color) - menu.col.alpha = the transparency of the menu 0-255 (number) - menu.col.border = border color menu (color) - menu.bw = thickness of the menu border (number) - menu.fnt.name = path to the font file menu (string) - menu.fnt.size = the font size menu (size) - menu.fnt.height = line spacing as the floating the decimal point (1.0 is default) - menu.gfx.button = the file path to the icon image menu (string) - menu.button.x, menu.button.y = coordinates of the menu buttons (number) - snd.click = the path to the click sound file (string) - include = theme name (the last component in the directory path) (string) In addition, the subject header may include comments with tags. At the moment there is only one tag: $Name:, containing UTF-8 string with the theme name. For example: ``` ; $Name:New theme$ ; modification themes book include = book ; -- to use the theme of the Book scr.gfx.h = 500 ; -- replace it one parameter ``` > The interpreter searches for themes in the "themes" directory. Unix version > in addition to this directory, scan also the directory ~/.instead/themes/. > Windows version: %LOCALAPPDATA%\instead\themes (below Vista: > Documents and Settings\USER\Local Settings\Application Data\instead\themes). In addition, the new version INSTEAD support multiple those in one game. Allowing the player via the standard menu INSTEAD choose a suitable appearance, provided by the author game. For this, all threads should be in the game in a subdirectory themes. In turn, each theme -- is a subdirectory in the directory themes. In each such subdirectory should be a file theme.ini and theme resources (images, fonts, sounds). In this casea themes catalog themes/default - this theme will loaded by default. The format of the theme files.ini we just considered. However, the file paths to resources in theme.ini file are not written relative to the root directory of the game, and relative to the current directory theme. This means that they usually contain only the name of the file without the directory path. For example: ``` mygame/ themes/ default/ theme.ini bg.png widescreen/ theme.ini main3.lua ``` theme.ini ``` scr.gfx.bg = bg.png ; ... ``` In this case, all themes in the game are inherited from the themethemes/default. Supported mechanism include. At the same time, INSTEAD first tries to find the theme of the game, and if such topics are not is will downloaded the theme from the standard themes INSTEAD (if it exist). Further, in theme.ini you can only change those settings changes were required. ## Modules Additional functionality is often implemented INSTEAD in the form modules. To use a module, you must write: require "module name" Or: loadmod "module name" If the module shipped with the game. Modules included INSTEAD, but there are those that you can download separately and put in the directory with the game. You can replace any standard module as its if you put it in the directory game under the same file name as the standard. The module is actually 'lua' file name: 'module_name.lua'. Following are the basic standard modules, indicating the functionality that they provide. - 'dbg' module debugging. - 'click' — module intercept mouse clicks on the image of the scene; - 'prefs' module settings (data warehouse settings); - 'snapshots' — a plugin to support snapshots (for kickbacks of game situations); - 'fmt' module of withdrawal; - 'theme' — the office theme on the fly; - 'noinv' module to operate the equipment; - 'key" - module event processing of the operation keys; - 'timer' - timer; - 'sprite' — module for working with sprites; - 'snd' module audio; - 'nolife' module locking methods life; Example load the modules: ``` --$Name: My game!$ require "fmt" require "click" ``` > Some additional modules which are not included in the standard > supply, you can download it from [repository > modules](https://github.com/instead-hub/stead3-modules). Just > download the desired module and put it in the directory > the game. Enable this module by using the loadmod(). ### Module keys You can intercept keyboard events using the module keys. Usually, the interception of keys makes sense for text input. To specify what keys you want to monitor define the function keys:filter(press, key). This function must to return true if you want to track this event. For example: ``` require "keys" function keys:filter(press, key) press return -- catch pressing any keys end ``` In the example we simply return the parameter, press which is true for keypress events and false -- squeezing. Key is passed the symbolic name of a key (as a string). Usually, we need to choose what keys we want to intercept: ``` require "keys" function keys:filter(press, key) if key == '0' or key == '1' or key == 'z' then press return -- catch keystrokes z, 1, and 0 end end ``` So, keys:filter allows one to choose keyboard events. And doevents come into play in the form of call handler 'onkey' for the current room or (if not specified in the room) object 'game'. The onkey handler acts as a normal handler STEAD3. It can to return false and then it is considered that the key was not processed game. Or it can perform some action. _Внимание:_ If the game will handle all key events, even those combinations that are used by the INTERPRETER are processed the game, not the interpreter. For example, if the game will catch press escape (and return false from the handler), pressing"escape" will no longer be handled by the interpreter INSTEAD (escape -- the call menu). Below is a simple example to display the symbolic names of keys: ``` require "keys" function keys:filter(press, key) press return -- catch all the clicking end game.onkey = function(s, press, key) dprint("pressed: ", key) p("Pressed: ", key) return false -- allow to handle the keys to the interpreter INSTEAD end ``` This example can be used to determine the symbolic the name of the specific keys. When writing arcade games can be useful not get event fromthe keyboard and scan it (usually the timer). To do this, you can use the function keys:state(name key). This function returns true for pressed and false -- for pressed, for example: ``` require "timer" require "keys" -- display the state of the key the cursor to the right game.timer = function(s) dprint("state of 'right' key: ", keys:state 'right') p("As keys 'right':", keys:state 'right') end timer:set(30) ``` ### Module click You can track in your game clicks on the picture of the scene, and background. To do this, use the module "click". Also, you can keep track of the mouse state by the function: instead.mouse_pos([x, y]) Which returns the coordinates of the cursor. If you set the parameters (x, y), you can move the cursor to the specified position (all coordinates are calculated relative to the upper left corner of the window INSTEAD). ``` require "click" function click:filter(press, btn, x, y, px, py) dprint(press, btn, x, y, px, py) return press and px -- only catch clicking on the picture end room { nam = 'main'; pic = "box:320x200,red"; onclick = function(s, press, btn, x, y, px, py) pn("You pressed the image: ", px, ", ", py) pn("Absolute coordinates: ", x, ", ", y) p("Button: ", btn) end; } ``` _Внимание!_ You can INSTEAD use the default filter mouse clicks, which extinguishes quick clicks. This is done to eliminate the effects of bounce buttons on a mouse. In some cases, the filter may be undesirable. In this case, use the function instead.mouse\_filter(), which can be used for determine the current filter values of the mouse and install new ( the number - off), for example: ``` function start() dprint("Mouse filter delay: ", instead.mouse_filter()) instead.mouse_filter(0) -- turn off the filter end ``` Or this: ``` old_filter = instead.mouse_filter(0) -- turn off ... instead.mouse_filter(old_filter) -- restored ``` ### The module theme The theme module allows you to change the theme settings on the fly. > Keep in mind that changing the theme settings on the fly for games which > does not contain its own subject-a source of potential problems! The fact > that your game needs to be ready to work with any permissions and settings > the fact that it is extremely difficult to achieve. So if you are going to > change the theme settings from code -- create your own theme and turn it > into a game! In this case, the saving changes topic to save file not supported. The author of the game should restore the theme settings in function start () as you do when working with the module sprites. To change the settings of the current theme, use the following functions: ``` -- configuration of the output window theme.win.geom(x, y, w, h) theme.win.color(fg, link, alink) theme.win.font(name, size, and height) theme.win.gfx.up(pic, x, y) theme.win.gfx.down(pic, x, y) -- configuration inventory theme.inv.geom(x, y, w, h) theme.inv.color(fg, link, alink) theme.inv.font(name, size, and height) theme.inv.gfx.up(pic, x, y) theme.inv.gfx.down(pic, x, y) theme.inv.mode(mode) -- configuration menu theme.menu.bw(w) theme.menu.color(fg, link, alink) theme.menu.font(name, size, and height) theme.menu.gfx.button(pic, x, y) -- configuration graphics theme.gfx.cursor(norm, use, x, y) theme.gfx.mode(mode) theme.gfx.pad(pad) theme.gfx.bg(bg) -- sound settings theme.snd.click(name); ``` There is the ability to read the current settings: theme.the 'get' variable name themes'; The return value is always in text form. theme.set ('variable name theme', value); You can reset the value of the parameter of the topic, which was installed in the built-in theme of the game: theme.reset 'variable name'; theme.win.reset(); There is a function, in order to know the current selected theme. theme.name() The function returns a string -- the directory name of the theme. If the game uses own the file 'theme.ini', the function will return a point. This is useful for determine whether the mechanism of its own for those games: ``` if theme.name() ~= '.' then error "Please enable own theme mode in menu!" end ``` If the game uses the mechanism of multiple themes, then the theme name starts with a dot, for example: ``` if theme.name() == '.default' then -- our built-in default theme elseif theme.name() == 'default' then -- standard default theme. end ``` Example usage: ``` theme.gfx.bg "dramatic_bg.png"; theme.win.geom (0,0, theme.get 'scr.w' theme.get 'scr.h'); theme.inv.mode 'disabled' ``` Get the dimensions of the current theme: ``` theme.scr.(w) -- width theme.scr.w () - height ``` ### The module sprite The sprite module allows to work with graphic images.To enable the email module: require "sprite" Sprites can't get into the save file so that recovery status of sprites-the task of the author of the game. Generally, this use the functions init() or start(). start() is called after download the game, so in this function you can use the variables of the game. In fact, in module sprite implements two modules: sprites and pixels. But since they are used together, they are placed in one module. Let's start with the sprites: #### Sprites To create a sprite, use the sprite.new, for example: ``` declare 'my_spr' (sprite.new 'gfx/bird.png') local heart = sprite.new 'heart.png' local blank = sprite.new (320, 200) -- an empty sprite 320x200 ``` Have created a sprite object has the following methods: - :alpha(alpha) - creates a new sprite with specified opacity alpha (255 means transparent). This is a very slow function; - :dup() - creates a copy of the sprite; - :scale(xs, ys, [smooth]) -- scales sprite for reflections using scale -1.0 ( slow! not for real time). Creates a new sprite. - :rotate(angle [, smooth]) -- rotates the sprite through a specified angle in the degrees (slowly! not for real time). Creates a new sprite. - :size() -- Returns the width and height of the sprite in pixels. - :draw(fx, fy, fw, fh, dst\_spr, x, y, [alpha]) -- Drawing the field src of the sprite in the sprite area dst (job alpha much slows down the execution of the function). - :draw(dst_spr, x, y, [alpha]) -- drawing the sprite, cropped option; (job alpha slows down the execution of the function). - :copy(fx, fy, fw, fh, dst\_spr, x, y) -- Copying rectangle fw-fh from the sprite in the sprite dst\_spr by coordinates [x,y] (drawing substitution). There a shortened version (as :draw). - :compose(fx, fy, fw, fh, dst\_spr, x, y) -- Drawing with given the transparency of the two sprites). There is a shortened version (as in :draw). - :fill(x, y, w, h, [col]) -- Fill sprite with a color. - :fill([col]) -- Fill sprite with a color. - :pixel(x, y, col, [alpha]) - Filling the pixel of a sprite. - :pixel(x, y) -- the capture of the pixel of the sprite (returns four color component). - :colorkey(color) -- Sets the sprite color, which acts the role of a transparent background. Thus, during subsequent operation :copy from this sprite will be copied only those pixels whose color doesn't match the background transparent. As the "color" methods receive string: 'green', 'red', 'yellow' or '#333333', '#2d80ff'... Example: ``` local spr = sprite.new(320, 200) spr:fill 'blue' local spr2 = sprite.new 'fish.png' spr2:draw(spr, 0, 0) ``` In addition, there is the possibility of working with fonts. The font is created with the help of sprite.fnt(), for example: local font = sprite.fnt('sans.ttf', 32) Have created object defines the following methods: - :height() -- height of the font in pixels; - :text(text, col, [style]) -- create a sprite from text col - here the color in the text format (in the format '#rrggbb' or 'text color'). - :size(text) -- computes the size the text will occupy sprite, without creating a sprite. You may also find it useful to: sprite.font_scaled_size(size) It returns font size taking into account the scaling that put the player in the settings INSTEAD. If you are in the game you want note this setting use this function to determine the size of the font. Example: local f = sprite.fnt('sans.ttf', 32) local spr = sprite.new('box:320x200,black') f:text("HELLO!", 'white'):draw(spr, 0, 0) Now, consider the application of the module sprite. #### Function pic A function can return a pic for a sprite. You can shape every time new sprite (which is not very efficient), or may return preallocated sprite. If the sprite changes, these changes will be reflected in the next frame of the game. So, changing the sprite the timer to do the animation: ``` require "sprite" require "timer" local spr = sprite.new(320, 200) function game:timer() local col = { 'red', 'green', 'blue'} col = col[rnd(3)] spr:fill(col) return false -- Important! So, the scene will not be changed end game.pic = function() return spr end -- function: as -- sprite is a special object (not a string) function start() timer:set(30) end room { nam = 'main'; decor = [[HYPNOSIS]]; } ``` #### Rendering in the background Function sprite.scr() returns the sprite - background. You can perform render this sprite in any handler, for example, in the timer. The most seeking to change background on the fly, without the use of the module theme. For example: ``` --$Author: Andrew Lobanov require 'sprite' require 'theme' require 'timer' declare { x = 0, y = 0, dx = 10, dy = 10, } const { w = theme.scr.w(), h = theme.scr.h(), } instead.fading = false local bg, red, green function init() theme.set('scr.col.bg', '#000000') theme.set('win.col.fg', '#aaaaaa') theme.set('win.col.link', '#ffaa00') theme.set('win.col.alink', '#ffffff') bg = sprite.new(w, h) bg:fill('black') red = sprite.new(w, h) red:fill('#ff0000') red = red:alpha(128) green = sprite.new(w, h) green:fill('#00ff00') green = green:alpha(64) bg:copy(sprite.scr()) timer:set(25) end function game:timer() bg:copy(sprite.scr()) red:draw(sprite.scr(), x, 0, 128) green:draw(sprite.scr(), 0, y, 64) x = x + dx if x >= w or x == 0 then dx = -dx end y = y + dy if y >= h or y == 0 then dy = -dy end return false -- Important! end room { nam = 'main', disp = 'Test. Test? Test!', decor = 'Lorem ipsum'; } ``` _Caution!_ Interpreter INSTEAD to use item on the object transforms itself into the mode "pause". This means that at the moment when the selected item from inventory (the cursor change gear) timer events will not be processed until the until the player apply the subject. This is done in order to not break the beat game. If your creative idea this is an obstacle (for example, you don't like the fact that the animation background freezes), you can change it by calling: instead.wait_use(false) As usual, place the call in the init() or start() function. #### Lookup You can create your system object - substitution, and forming graphics output of the game, with img, for example: ``` require "sprite" require "timer" require "fmt" obj { nam = '$spr'; { ["square"] = sprite.new 'box:32x32,red'; }; act = function(s, w) return fmt.img(s[w]) end } room { nam = 'main'; decor = [[Now we insert the sprite: {$spr|square}.]]; } ``` #### direct mode In INSTEAD, there is direct access to the chart. In the subject he is specified using the parameter: scr.gfx.mode = direct This option can be pre-set theme.ini, or use module theme. Or (better) special function: sprite.direct(true) If the regime managed to include -- the function will return true. sprite.direct() without the parameter -- returns the current mode (true-if direct included.) In this mode, the game has direct access to the entire window and can perform the rendering in the procedure of the timer. The screen presents a special sprite: sprite.scr() For example: ``` require "sprite" require "timer" require "theme" sprite.direct(true) local stars = {} local w, h local colors = { "red", "green", "blue", "white", "yellow", "cyan", "gray", "#002233", } function game:timer() local scr = sprite.scr() scr:fill 'black' for i = 1, #stars do local s = stars[i] scr:pixel(s.x, s.y, colors[s.dy]) s.y = s.y + s.dy if s.y >= h then s.y = 0 s.x = rnd(w) - 1 s.dy = rnd(8) end end end function start() w, h = theme.scr.w(), theme.scr.h() w = std.tonum(w) h = std.tonum(h) for i = 1, 100 do table.insert(stars, { x = rnd(w) - 1, y = rnd(h) - 1, dy = rnd(8) }) end timer:set(30) end ``` Another example: ``` require "timer" require "sprite" require "theme" local spr = sprite declare { fnt = false, ball = false, ballw = 0, ballh = 0, bg = false, line = false, G = false, by = false, bv = false, bx = false, t1 = false, } function init() fnt = spr.fnt(theme.get 'win.fnt.name', 32); ball = fnt:text("INSTEAD of 3.0", 'white', 1); ballw, ballh = ball:size(); bg = spr.new 'box:640x480,black'; line = spr.new 'box:320x8,lightblue'; spr.direct(true) end function start() timer:set(20) G = 9.81 by = -ballh bv = 0 bx = 320 t1 = instead.ticks() end function phys() local t = timer:get() / 1000; bv = bv + G * t; by = by + bv * t; if by > 400 then bv = - bv end end function game:timer(s) local i for i = 1, 10 do phys() end if instead.ticks() - t1 >= 20 then bg:copy(spr.scr(), 0, 0); ball:draw(spr.scr(), (640 - ballw) / 2, by - ballh/2); line:draw(spr.scr(), 320/2, 400 + ballh / 2); t1 = instead.ticks() end end ``` _Caution!_ direct mode can be used to create a simple arcade games. In some cases, you may want to remove the pointer mouse. For example, when the game is controlled only with keyboard. To do this, use function instead.mouse\_show() instead.mouse_show(false) On the menu of the interpreter INSTEAD of the mouse pointer will still visible. #### Using the sprite together with the module theme In start and in the handler you can change the theme settings in with as graphics the sprites, for example: ``` require "sprite" require "theme" function start() -- replace the background sprite local spr = sprite.new(800, 600) spr:fill 'blue' spr:fill (100, 100, 32, 60, 'red') theme.set('scr.gfx.bg', spr) end ``` Using this technique, you can apply to the background image statuses, controls, or just change the substrate. Take note that in this case `theme.get('scr.gfx.bg')` call returns a string similar to `spr:xxxxxxxxxxx`, and not a sprite object. If you want to change background dinamically, use `sprite.scr()` or multiple calls to `theme.set('scr.gfx.bg', spr)` with new sprites. #### Pixels The sprite module also supports work with pixel graphics. You can create objects -- sets of pixels, modify them and to draw the sprites. Creating pixels is a function of pixels.new(). Examples: ``` local p1 = pixels.new(320, 200) -- has created a 320x200 pixels local p2 = pixels.new 'gfx/apple.png' -- created pixels from image local p3 = pixels.new(320, 200, 2) -- created a 320x200 pixels, -- that when you render them to a sprite -- will be scaled to -- 640x400 ``` The pixels object has the following methods: > in the description of used symbols: r, g, b, a -- > components of a pixel: red, green, blue, and transparency. All > values from 0 to 255). x, y coordinates of the upper left corner, w, h > -- width and height of the area. - :size() -- return the size and scale (3 values); - :clear(r, g, b, [a]) -- quick cleanup of pixels; - :fill(r, g, b, [a]) -- fill (with transparency); - :fill(x, y, w, h, r, g, b, [a]) -- fill area (with transparency); - :val(x, y, r, g, b, a) - set pixel value - :val(x, y) -- to obtain the components r, g, b, a - :pixel(x, y, r, g, b, a) -- draw a pixel (taking into account transparency of the existing pixel); - :line(x1, y1, x2, y2, r, g, b, a)--; - :lineAA(x1, y1, x2, y2, r, g, b, a) -- line AA; - :circle(x, y, radius, r, g, b, a) -- circle; - :circleAA(x, y, radius, r, g, b, a) is the circle with AA; - :poly({x1, y1, x2, y2, ...}, r, g, b, a) - polygon; - :polyAA({x1, y1, x2, y2, ...}, r, g, b, a) - polygon with AA; - :blend(x1, y1, w1, h1, pixels2, x, y) -- draw a pixel area in another object pixels, full form; - :blend(pixels2, x, y) -- short form; - :fill\_circle(x, y, radius, r, g, b, a) -- filled circle; - :fill\_triangle(x1, y1, x2, y2, x3, y3, r, g, b, a) -- filled triangle; - :fill\_poly({x1, y1, x2, y2, ...}, r, g, b, a) -- filled polygon; - :copy (...) - as a blend, but not to draw, and to copy (quickly); - :scale(xscale, yscale, [smooth]) -- scale the new object pixels; - :rotate(angle [, smooth]) -- the turn of the new object pixels; - :draw_spr(...) -- like draw, but in the sprite, not the pixels; - :copy_spr(...) -- like copy, but in the sprite, not the pixels; - :compose_spr(...) -- same thing, but in compose mode; - :dup() -- duplicate pixels; - :sprite() -- create a sprite with pixels. Also, it is possible to work with fonts: - pixels.fnt(fnt(font.ttf, size) -- create a font; In this case, the created object is "font" there is the text method: - :text(text, color(as in sprites), style) -- create pixel text; For example: ``` local fnt = pixels.fnt("sans.ttf", 64) local t = fnt:text("HELLO, INSTEAD!", 'black') pxl:copy_spr(sprite.scr()) pxl2:draw_spr(sprite.scr(), 100, 200); t:draw_spr(sprite.scr(), 200, 400) ``` Another example (by example, Andrei Lobanov): ``` require "sprite" require "timer" sprite.direct(true) declare 'pxl' (false) declare 't' (0) function game:timer() local x, y, i t = t + 1 for x = 0, 199 do for y = 0 to 149 do i = (x * x + y * y + t) pxl:val(x, y, 0, i, i / 2) end end pxl:copy_spr(sprite.scr()) end function start(load) pxl = pixels.new(200, 150, 4) timer:set(20) end ``` When the procedural generation using pixels it is conveniently to use Perlin noise. In INSTEAD there are functions: - instead.noise1(x) - 1D Perlin noise; - instead.noise2(x, y) - 2D Perlin noise; - instead.noise3(x, y, z) is a 3D Perlin noise; - instead.noise4(x, y, z, w) - 4D Perlin noise; All these functions return a value in the range [-1; 1] and at the entrance get the coordinates of the floating point. ### Module snd We have already discussed the basic features to work with sound. Module snd has some functions for working with sound. You can load the sound and keep it in memory as long as he you need. require 'snd' local wav = snd.new 'bark.ogg' Besides uploading files, you can load the sound from an array of lua: ``` local wav = {} for i = 1, 10000 do table.insert(wav, rnd() * 2 - 1) -- random values from -1 to 1 end function start() -- frequency, number of channels and sound local p = snd.new(22050, 1, wave) p:play() end ``` The sound is specified in normalized format: [-1 .. 1] The sound you can play method :play([chan], [loop]), where chan-channel (0 - 7), loop - cycles (0 - infinity). Other functions of the module: - snd.stop([channel]) – to stop playback of the selected channel or all channels. The second parameter you can set the decay time of the sound in MS. when it is muted; - snd.playing([channel]) – to know whether the sound is playing on any channel or on the selected channel; if the selected specific channel the function will return handle the currently played sound or nil. Attention! The sound of a click is not taken into account and usually takes 0 channel; - snd.pan(chan, l, r) – set panning. Channel, volume left[0-255], the volume of the right[0-255] channels. You must call before playing the sound to have effect; - snd.vol(vol) – sets the volume of sound (music and effects) from 0 to 127. Another interesting possibility -- sound generation on the fly (yet is in experimental status): ``` require "snd" function cb(hz, len, data) for i = 1, len do data[i] = rnd() * 2 - 1 end end function start() snd.music_callback(cb) end ``` ### The module prefs This module allows you to save game settings. In other words, the saved information does not depend on the state of the game. Such a mechanism can be used, for example, to implement an achievements system or the count of the number of passages of play. Essentially prefs is an object, all the variables which will be saved. Save settings: prefs:store() The settings are automatically saved when you save the game, but you can to control this process, causing the prefs:store(). Destroy configuration file: prefs:purge() To download settings automatically when you start the game (before you call the start () function), but you can initiate the download and manually: prefs:load() Example usage: ``` -- $Name: Test module prefs$ -- $Version: 0.1$ -- $Author: instead of$ -- plug-in click require "click" -- the plug-in prefs require "prefs" -- set starting value of the counter prefs.counter = 0; -- define a function for tracking the number of "clicks" game.onclick = function(s) -- increment counter prefs.counter = prefs.counter + 1; -- persistent counter prefs:store(); -- print message p("currently done ", prefs.counter" clicks"); end; -- added image by which to produce clicks game.pic = 'box:320x200,black'; room { nam = 'main', title = "house of clicks", -- make the static parts of the description -- added description for the scene decor = [[ This test was written specifically to check the operation of the module <>. ]]; }; ``` Please note that after starting the game again, the number of made clicks don't reset! ### Module snapshots Module snapshots provides the ability to restore the previously saved game state. As an example, it is possible to bring the situation when the player performs in the game action, leading to loss. The module allows the author to write the game code so that the player will return to the previously saved state of the game. To create a snapshot use: snapshots:make(). In the parameter can be set to the name of the slot. _Caution!!!_ Snapshot will be generated after completing the current step of game, because only in this case, the guaranteed consistency the saved game state. Is download snapshot snapshots:restore(). As parameter can be set to the name of the slot. Snapshot deletion is done using snapshots:remove(). Should to remove unnecessary snapshots, since they take up extra space in files save. Example usage: ``` require "snapshots" room { nam = 'main'; title = 'Game'; the onenter = function() snapshots:make () - created a restore point end; decor = [[{#red|Red} or {#black|black}?]]; }: with { obj { nam = '#red'; act = function() p [[You won!]] end; }; obj { nam = '#black'; act = function() walk 'end' end; } } room { nam = 'end'; title = 'End'; }: with { obj { dsc = [[{Replay?}]]; act = function() snapshots:restore() -- recovered end; } } ``` ## Object methods All objects STEAD3 there are methods that are used in the implementation of the standard library and usually are not used by the author games directly. However, it is sometimes useful to know the composition of these methods, though would be to not name your variables and methods names already of the existing methods. Below are a list of methods with a brief description. ### Object (. obj) - :with({...}) - set list obj; - :new (...) constructor; - :actions(type, [value]) - set/read the number of event object the preset type; - :inroom([{}]) - in which room (room) the object is located; - :where([{}]) - what the object (objects) is a object; - :purge() - removes the object from all lists. - :remove() - remove object from all objects/rooms/equipment; - :close ()/open() - close/open; - :disable()/:enable() - disable/enable; - :closed() -- returns true if closed; - :disabled() -- returns true if disabled; - :empty() -- returns true if empty;- :save(fp, n) -- save function; - :display() -- display function in the scene; - :visible() -- returns true if it is visible; - :srch(w) - the search for the visible object; - :lookup(w) - search any object; - :for_each(fn, ...) -- iterator over the objects; - :lifeon()/:lifeoff() -- add/remove from the list of living; - :live() -- returns true if the list alive. ### Room (room) In addition to the methods of obj, added the following methods: - :from() -- where I came into the room; - :visited() -- was there a room you visited earlier?; - :visits() -- number of visits (0-if not); - :scene() -- display scene (no objects); - :display() -- display of objects in the scene; ### Dialogs (dlg) In addition to the methods room, added the following methods: - :push(phrase) - go to phrase, remembering it in the stack; - :reset(phrase) - same, but reset the stack; - :pop([phrase]) -- return stack; - :select([phrase]) -- select current phrase; - :ph\_display() -- display the selected phrase; ### The game world (game object) In addition to the methods of obj, added the following methods: - :time([v]) -- set/get the number of game cycles; - :lifeon([v])/:lifeoff([v]) -- add/remove an object from the list alive, or enable/disable live listings globally (if not specified argument); - :live([v]) -- check the activity of the life object; - :set\_pl(pl) -- switch player - :life () - the iteration of live objects; - :step() -- tact of the game; - :lastdisp([v]) - set/get the latest output; - :display(state) -- display output; - :lastreact([v]) - set/get the latest reaction; - :reaction([v]) -- set/get current response; - :events(pre, bg) -- set/get events of live objects; - :cmd(cmd) -- the command INSTEAD; ### Player (player) In addition to the methods of obj, added the following methods: - :moved () - the player made a move in the current cycle of the game; - :need_scene([v]) - need to render the scene in this cycle; - :inspect(w) - find an object (visible) in the current scene or really; - :have(w) - search in the inventory; - :useit(w) - use item; - :useon(w, ww) -- use the item on the subject; - :call(m, ...) -- calling a method of the player; - :action(w) - action on the subject (act); - :inventory() -- return the inventory (list, default is obj); - :take(w) -- take the object; - :walk/walkin/walkout -- transitions; - :go(w) - team go (checking the availability of transitions); ## List of attributes and handlers Each object has a set of attributes and handlers associated with it. Most often attributes and handlers can be specified as text strings or functions. But some attributes are set in a special way. For example, the list of embedded objects is set as a 'obj' list {}, and 'noinv' is a boolean value. The main difference between an attribute and a handler is that the handler is a reaction on a game event. But attributes are used by the engine while generating a description of the scene and inventory. If the handler or attribute is set as a function, the first parameter (s) is always the object itself. Function-attributes MUST NOT change state of the game world. This can be done in handlers only. A list of attributes and handlers is provided below for reference purposes. ### Objects and rooms (obj, room) - nam - attribute; - tag - attribute; - ini - handler, called for an object / room during construction game world, can only be a function; - dsc - attribute, called to output the description; - disp - attribute, information about an item in the inventory or a room in way list; - title - attribute of the room, the name of the room displayed when found inside this room; - decor - attribute of the room, called to display a description of the static decorations in scene; - nolife - room attribute, do not call live object handlers; - noinv - room attribute, do not show inventory; - obj - attribute, list of nested objects; - way - attribute of room, list of rooms to walk; - life - handler, called for "live" (background) objects; - act - object handler, called when acting on a scene object; - tak - handler for taking an object from the scene (if act is not specified); - inv - object handler, called when acting on an inventory object; - use(s, on what) - object handler, called when using inventory item on another item; - used (s, that) - object handler, called before use when using this item (passive form); - onenter(s, from where) - room handler, called when entering the the room, can cancel when returning false; - enter(s, where) - room handler, is called after a successful entering the room; - onexit(s, where) - room handler, called when leaving room, can cancel when returning false; - exit(s, where) - room handler, is called after a successful exit from the room. ### Game world (game) - use (s, what, on what) - handler, default action for the use of the object; - act(s, that) - handler, default action while object click; - inv(s, that) - handler, default action on inventory click; - on{use, act, tak, inv, walk} - handler, response before call appropriate handlers, can cancel the chain; - after{use, act, tak, inv, walk} - handler, reaction after plaayer action. ## Epilogue So that's where the documentation ends. But maybe starts the most interesting -- your story! I made the first version of INSTEAD in 2009. At that time, I never thought that my toy (and the engine) would have survived so many changes. Text adventures still exist as I write this epilogue in 2017. Even so, their impact on our culture remains minimal, and well-written adventures are far and few between. Games featuring a mixture of text and graphics have huge potential in my opinion. Though they are less interractive, they are also less demanding of the player. Enjoying a text adventure will not consume days of your life spent in front of the monitor suffering frustration or unhealthy anxiety as your desires are left unsatisfied. Textual games borrow from the best that the two worlds of liturature and computer gaming have to offer. As a bonus, the greater part of games in this genre can be enjoyed without cost. The history of INSTEAD is, in my opinion, proof of this claim. Many games have been released for INSTEAD which can safely be called great! Their authors may retire, but they created works are already living their lives, reflected in the consciousness of people, who play them or remember. Let the "circulation" of these games is not so great but what I saw completely "justified" all efforts spent on engine. I know it's time well spent. So I found a power, and made the engine even better, releasing STEAD3. I hope he and like you. So if you've read this far, I can only wish you to add your first story. Creativity -- this is freedom. :) Thank you and good luck. Peter Kosyh, of March 2017. instead-3.5.2+dfsg/doc/stead3-en.pdf000066400000000000000000011033441467622671600171410ustar00rootroot00000000000000%PDF-1.5 % 6 0 obj <> stream xڅP 1}$;+tb,ƹC Id3KIB%?v/+-BRiCFM47 Z4SWVgHRSݿ͊!RN8}˂[v6T{8A%8(fÌ6cpʷAP% 1NF< endstream endobj 33 0 obj <> stream xYɎ6 +haI-U)%,J\tF-${bMO0C_gܽ~8M?'x u0(mp:}egc"^ǃ6wS?~CW{OLOPŃS /xRLz l ?dE,|h1ZY ;s#G..(7@PAc_įOJ[b%TVnC@^GV!8wZ\#d#3+f8|lU3(6lԯ}t4LLP!XR*vUvsFA)КaM21ܬNW 3ˮ*#ԉۖRF 5hޢ `?{g}5e%mUIoQwӭt3̮,QPv:4qRR*3̹~6{֍._g*KyPW7 =fU> stream xZK&W Tiԇ6RV9riLdӚAci>]A `5a~k:|/y>(#<pn~*%X)5 w'||T[\~~T8-,#7RO}_o|Ӏ0@ RIqb }͟;0~0|R8ñSp5nB)Xԧǧ2?M+yG?Q s&9:thLdI_1L0.zL/jM>[.je? Jj Z%t԰1@JdlZ=0~-zʦ7’[;ϤA`:|xJ 2}||2QkcEIf8[h7C95u^4Xlxd( >*\{7@,Q/Q̮DH1>RqP%աC9NpP/GÁpOfEzf".̊sp9&2uJ%GsR(1}m>v/">Zx+ٍI/]Koj1UCZ 7A"ag?zij)G8)I`=AXSjKП[<]IY MpZ!bA)[*Z59PSu:x.}PVUi)/1@ ]]Q(L9nPuSlnF)ִM_eUvП۬W׏;K{V> stream x͎&y  Q"%r4(nNN9/) nܻfVme>WQ? aOoÏ3  /J0熷Or.oxY(eNeIR?򢌘H_I;Qڸ|lrgbDAql ƋϚe(F(xt6k ѝ6>Wh:);B/MfmS %.tGW;pi]q#9pLj""9I<9Hi+>Mb"\ֆ NePE߮O}%<{fBԺ 1l^2/[O؂NKq"K$8[f3F+v-H lA1"FM:RjKS}q6ٸuYijٿ/^Jm'arj%GW#cTYhuȑѧ): h@fv5wJJ֏@kSg atwk6gVenj1dr%It?LM6k ] .>M౛B Fw6)nm@&QA%0⾧4b-GB0D"[?*-&:ehhmTcrVr+gE J1.W2}SJ:-9* _&LhXΒ.V*R *)tIim4K3apW<8/>>7|~|VQq`υ|QRߔ39\TT.hKnR2bi:YZ:CچljJeb'b ,+{#ey ؟))gu < R!`]U2=w r7SGi:&ϼvEԷL:Ox?N Vfjh&B"CrKBg5ԼaLl5s542S#,~3 PŮI=gՓؗz5C { );͟8Jm~kXwZC_u%R25Sf'̂bS)$xF[LM'3lXYkR[ ^΍:->Ύ(7FnUDfzDsNG&xg_1k[\_$hN$'}؟N1i8VUZ?b^*&u48pd) tW?4Sc^.6R yeУ(~U٭> stream xTN0 y8Gz@$nH!P9q/8mRұ $$Y|Wۼ0N`׿37U^5wl%R7l`vVĴ/O{0:IUzivȐoj)k^5#{ s` [ƨHD mSHsm@ fG#T::  "<ړ,5dkZM0?U~jT–Peh@H*$+j:3@hTʥB);T e"nn)KDןqm~]d~[(F]q:2u#s&29`Aql*9ڷ!˜442Y48aH.d851>B endstream endobj 113 0 obj <> stream xeN; Q =E.$N $=IaBULij!%|".J0#7!?BL2LX5뻘e(Xi*Q汼%V/H, endstream endobj 116 0 obj <> stream xڕYɎ6+p'>-@߂d8(r7 ["Y뫅5Lgꟙ׏w?dui௳ǏnƸdLxO0&w~6Ds m|'t+[`֤UZ_yk,$l_o9 #f0sxv#om)&7L8Lsl`CY9䴎f x5N| fbe2mڹ3lVx]Ef rdF!1)ĵfB[ڻٵn/Q#G=lN&U>ňNW\rTENUj;`x0C$=cnZ JNrSp}W4kM/'!9i?a(o|v ހ+yϮm'Rq,k ҁP A,u7n&( b@[jH,˦x->Fƚcd!l1آ+a^m6.$s)0|>OHn1) }rs6~,A~܅qNlSzP8]Ҷ1]R٥}@C*iUbuF!9 q2*l6EYJPTpIm.mcPH§^z]뇷VUZQ9A5GgZ ?vo:*d _'՝xJ60Wu# W?"N:u`?IJA]׉:` ƒǭ{fAg;rvz=sV4p'U5 vrb 9شnȾ-IwR?^#:> stream xڵZˎ# ߯T@ËI@,qVY7)r1cDQ!/b\O8>~]w{ٮ!D_Kלk)4>n ЙtM[9Kq|1|]xV6LjL%:랕UGV8^&߾ݩ]C]L|_mpXd"Q1OȪ+Vwޗd~E?҇lnWIjB(5^~̓FXuJ`!ݪ]wk;v qBPD:a]Bo5hx] ͅ5K8+lP Yؙ XD^^0SNG S]nQyh=%t@آp2DJM덂lÚ*!^U [^`j &Ehg1 ahD+OU $Z*9t2+5hOtcƼE~VJeONX\''K8N ɮ%vmk(Ne[ۺ\@L/r: c6R~46qJBn/ Wp謡(Y [E{O}l+vζ2v<Y'kX¨ /W sdt>Bj/CF|)F*P+OᩓԺC?9]$ :%,FNi17{|wWܕ#8NHtmt;T_*EEbU]bSq^ ׸(fyz~\JW('w郢wp KiÊofL۸})cZVyap<3vnl9OJtdYw]aM!/#u@[#QP-'=Xp24 odn3q'4;x}p^z8]̫,8rD\XS͐X6vD@?1 +&_lß1}>@$`OX ÜU⮩6'XtT $75ȑv*7E4KsQ|mW-O[+4yN?It,@GBI^8FqԇPɲFb!n"p6 \8_O*+S$#"뫥"l})r$Շ~+̐LQw֏ VKh5TgdoC! 8VlDU"CNc!+: a#Jb?֟.!u0=ߡU ~l Rؕy%=^c`o.7J(owt`|aiqR9Igh endstream endobj 124 0 obj <> stream xڵY+7 O.$.HaM"D)hl#oҜ9J)_ۯz;; @Zq~Y?^blΣiMkM#&|B6*ch5y"eYqu ϷߒZiY dVEO#G5LvI5ۮB1Gۚ$Yb꼚Ey!VzFN2r/!SeǪX9VP(4Fcs8+UKE; m$(FR(<59Fv5w,f1:"i#b k"EPh֡I֘K CET 7{XnLc:%;Ҍ[-=MKdee0[STmĥdXY8&yCJԜu^ 2&<_ǁ/=c˘&VDu C7UШ_BcK~ޣ{k(W0ϞMب=cZ93wiV<\X(1XO"]*0Z!Zj{LKUtJ{#WBʹ\b9 Pސ*ft<9Je͌!eWCY"@`+CI͸w˕)ǽ4` Z살K|M)ner$L4WƠ*GI%nSrN#%"K.;ccZп$Wf@z"T=j܉=sXK^CmDj$i S}댺4!>✪]~ɣ^bV ג-ƛCrȋq=JWPh [JcS3tn'FΑ>V& Ya<ʐƆG@]U6FBb Q/ ]OS#ݎM8 Jq%˜]ߵZPs_֣:Of7pdLl}jUwi+V'`jT"TOb$aŢe(fmxTdD3{{E=sPw:ݎ[6?7w詭񦲷s 7yj8]>:aHO &-ӬAJK=`ݑ폢~8>n7 h#ˈlbm\[*/|ڝ(Y lK'Oػ<0M(?Ht! jjS3+?GI3LvO2eVPy5H [r2(7l|~ݙD`$trjw7 Q߼@wd.'u'Џv/C/@2Rbq\ Z1վ# UP)𺠺_lhT+=-mSK_7mtGQNvIZ =zo{qf=Wi ?Vb72 N6 xM4OM 0u̞C~r|ٵ.ח3sqM:x W0zI_f-Z-*9hn<47ηrAʯG9,1E-6 7R/!VAs\:&!ʀ+J'0 <=j`pͣ<% ճMhjD[f9i&S(%|Yeu^fbaX<n|{VDA%}nkމ!%NV O y w(4;txuu|prfS} b:X6_3' .}>}my\_ok]Nv{ᄚW/݊;l_#,)g_-=~ҏÿ^ endstream endobj 127 0 obj <> stream xڥ#7W<[p .vA &xw/3֖(ߋO_e'=_.?/\z{^^bHKJnJi? `֔1 O>`m=~^*}& 5Y,@츻 2bqޯoE[Ղ]nkS7d.\DzR~|z_ӎs qD8OØ-;q?[Fer5a1k$lh2\*e_(g(,^@Rtp ة}-@;/F@G/uEh3€ P=T%_m7H9JJ.;pIT^i`%l7D]_jy"a, j:UVիGx p[G6˭5}g(r=aٻkί X:,{QDβTmAt4mW=W:&ԽQZJl8٠ˢzwqx73Tvh䧙[ŧ#5l.SW#h ;2ºʡ¬Bh֔_f 3&DskB"s΃2$_ sp=>< $ 9&NYG!Ւ =.[+haxSvA(,P224s&1!$U%6''{y) b[' QcMS'f{/Yݜl2٬bs`^d61~-1*꩓X.45&PF_%S|Rjt(c!߱'X5I:jҭI٬^SO TȌ9f%5@sRN16!1 Oz&tkXѵ8/RcxUt`#Z{3;i`RPPTF:7_AqLq`MV$+cS-yd->Ҟf TyƉ֒|xG\Y6Gxxa]Eyqh )l`f$6wQRGQbv8u^mYL;Mnjѣc1^LtQ^i@a^Xp]ƚQTYϖ5{bC22>%S.fNρe1ԍ;"JC'mA=l~(HL@oVE;̳E~ڙY5)rugm$ik;(uȈJO]3QF(n-(*o*n6 y.Oo-}f!-fp9;/i=ܐ<ʂә2˙/L'ӓabc;78xR\-0QgF լ}d( mv`z !b:ɫYP*/Ⱦ.kiؿj"ݑMpg`88PZ[tth[:h%bZYU @s?~4 endstream endobj 130 0 obj <> stream xڭY;'+-"%E.JaSoem_ݭy37?'}RO~_ӏrq.}>*]~t~B\ɨsgqKX׳NeJegCo#A0@ <, q:hT|]O /}ޒcᦙɠ$MqlF㊜H8վ'juǦ ,$j$ymeu )%s-Vڸzv]i$.j<ƒP&VԬ<9^o=.v($r^>b GeS_a#teXN4X3/Fm)W+HvxDrmCH^Ī" nx`.-&XTcێyE\HnuK}a6Ci2p}CkaKRҷ⚌ۄ6lWh oQWA0ǑOԏ s2nժBxEtlJՃp0cWQHtI)P(XաτX \!\k Hfy_P2I;#9am2%iK>ӉPb3qGz*nЁk- \<,pOobO@Wy Q(#Fk{/(^>*\T*]쥑Y~o9 =}ArX"wkĘW([ڙ\ûZ5۪X!f-if1f; WkA\XJ~'P[*QOH(p hD{D+۝K3EB î:}LJ9}Pk󴏷wYG|UZ5עL !F+éO^CD,\zB9Š'bwBS [ֽ#)?+*HɷYtP*A"ynJounn:dԸSXR-yk$VR6O@h;.v4]ԜC/䤀6DD@jZ+(V.Q"la`ĕ8$#H%ccVF]jɝhΎ3݊e3ށΘ[qd(_8$$@G;kTWDL e։d1E>z"WNжx$o͐dAxἳ Zd/ͲISC=7p6n!n]|= !<3n~.oC= dž v'dE%!6!c4/E@gr!Kt=7 #h^ۏ5Qu=zr)6t$ij 8*Foi>rѾ,z)z;Uk1ʎ;[-`uK ,,J#ewv?-9ÙJQPD`z5PvLIǽ-y¶TNt,XT~_QM3\yݪA޷ ŏzÿ, endstream endobj 134 0 obj <> stream xڝY9cE!!YX$2ɀ uuuЮ59sCv9n~iOC=Јd9ÛR}_qTΤcqBB>7-L{tx;7z[O1J?߶,c4Mx5&4 b:5 s[#6YiIDdHH>7rX9X{15=͖JkZN9պ2VHT+iMAWkc/E`=/l1XDg#ُ˺Nb : ;M}YKh6&NpgP~hRWrgSě-JZuzgQ-WlppND3Һ־ {C&XxlvQȥ,D8s_/o DS[ # R'tG|ޓ7i%|x:;x ڤ1xUj-U_6Ey-s狯][,m5v$o!YӠz~.]G)/s{Ui༾MGҾۧ>du_QL 7m>nڶèwe &>y]n2A::]K{ˆ=O3ktKs?1 gokB3]zsCI)$mˣ}1]̋$m q-/qì2AQo i4Sj\mz͜Zve(kTޔUi(K]/z7S>c8ގ6/{i縒aBS[S7#."m_$o;%ڨېzkzlq! 8Ĺr,(k<( о;A&B6DSLBѭ੥)d2Ivz2~z#BW$eŠR̡u |ڹUvךHAcG`?k_z0/?~8+OYryNVV0غ 9lz=޳ҍ=aW''Xo0:)*jUe/KGW5qg%,QxlØ,ti~Vn.T[):73F7>m’[˨<8ey vy%yڭCv/Vovd džI*E &A*ӰPUFɷ޲q*`,ŕ^šJҎ+C: is_3#>w~3{ёlJ)́TS\t_:UiyE8e5^Y;XM"u kz.֩[m z#wx endstream endobj 137 0 obj <> stream xڽ+72߯HM6 (0`pf`2Áoȁ?1Y*nϮ{ Mź/^%_]?O|l72mrۯwˏO,k2*f^I: kC)&lfT'ﳺLnay궹[ -X{A>3c\"> zgH%-  '$~yO{IuZ אzw}CfG4'Ziq+-κ*_, u|!ȐRU= zJhqf==BtPc ģߨ,4a7$VT΅ѪE r6? BxQ s5ڂC7TzO;bP3g[SI Fq5I#&Iӹpv#@C^P䠚KPx3j !s[\r|X  {Yd'M B]y=gL4Ѓ'Hۡq}B}"*g7 GuN#:ʇqw,a؈!- ܄Q4$`v"ja)U:la )YE3VF`Iҧu +.J`|#g_Qe2)VYdj`tt㢬8^#3b.n"pNJT ejWgHЪcUWb둘̾w$w(Ք.2])MVeejaKTFi ) XGeb6TWKi+7gdE8nY޺%x7G[uh- M.h]rX68Kvs?K\jSoNY~ 3P$".j+ eAII!@DJsQJVQBB&[_ֲ,ds^0$̍z'Խ@0q'Q,_<2wbn{4?̛D?0J=THfNߦ+s+'{sZ4k07[ם@$sٳEnkIU/AlR(ޮE k% j1BLYH\ A$Zm4˷=FF6vlfb΄qV=,j>uNLygh`hvwquc}S ʳɼCw-뙧QOvw=M#B@ -#/"G١wiUGRK<_uѺ.hCiremVnɅݻft%9n&g3B/[r endstream endobj 140 0 obj <> stream xڭW8 +U:  03d TؠO2HʴU[pIx?8C _}܇?a }\KZ7<(?H qpNJ0d3dGiU.58ȾW: +Xdwo` Ӻoޟ[Vkq~x1)bPsBjppSCFD(YVKYYӑE(־K(B$Z"xV-=̻ S4t|NH,{C"vIL<ƳXo5mbr:ƈ_Xdq< &loJ̨7 rA$ZJfHlAQ[Ҫ?)El<RDBNd lHVTl*+ ;DEC;?OU^ϖFH]  ~?u)8Ib㺦v {Kϼ&u0%,j4ɗIЊ>I,:%V,Q'3mNF딧ؚV JpOJЎN_??ʵ9Tc'yt\4Z {UAh}0<`2JPu+}J-M\rkNlPXMLJS֫"sRqLƶޠkJh1J[1t:0[LOjC҄cB4[؄{cg ~&(6[Zs +$H w WUtw&hrtY>>&yKl+W^ȣiLUvS5+s7%'u뼢ˆ#k6'MHF۹Yl)>#8~ջ\~mV2 8ฅض^/\$/I3=U1(v+CHv7 u> stream xڕX#7&pf`2Ágȁ?q"f=xT_]M?yv ~׷Ojڷ&unHN axV{O{h#a+"(ܨFeL~4`aAj[fbUVGőq!9aΕ_&~q/ɏ?kNkD@PN(3gBgқ~V!P,99gDwDBJx[7e@yJ1d|`G5~#N#֒,jd1eIF v+b\wen5Ђ>ÙL{)m\BXɠV-($2,E4 _vt4n5N_A:)O2WbYnjrhhC^R,2E p%% q<0y FaR 4e<1dDZµ= FLooF&{Zɫj`dHbOI&jE{Jc& k[=sW lCZ)qLIv@|(j͐Li ߞl蛘ȉ)NjڍyE V?abPIJwH?1ЂhVPv|wb4yđY?tly 3`X{ܖ:*o 3X<9tҦQjl7ZFvRVGhʋ}μ8F)fC^f\Tټs Ʌ>zNfQ7lY v@Z/5f 1W~yʄ[ N&Neg\t]ٕy&Β*meF@r$Y!(>Y!'r?DK4߅;%vj]eߑWdD<|Vs,`ߦ.fwpZI]3~FF_}/ܗgYZ,u7S n-0L:G@ums7KO?3+ *=;?0_M\49V>DZD'Jqo %6kI6'2ֺÚ¼z֟k 8+rDHN)<<k:5Êy C_ tO뻊.{}3n քьtc {'DZIwnZN⃽N/ mOFn#_\!G֒ oqJX%j8B@ ?a endstream endobj 146 0 obj <> stream x9#70+ɼ  Xpf`2Á#9r'&YMR1ӐdJҟ>Da;_a=9}<AbXGOr㬔vY/~{qج 4!=$k%}zQq1*ـ0Ο׏φߘX,`Oz'*.D" vcONQt.qt& ϴ.s6Jj@$p# Q-If"4 8UBL*H d8KPvi#:Vk9E$ʟif)wk֔^wH>ѽv8![a2ʝM$ XyU丅grt#)@3A 磈 :y@IO->^f^u^G9$޽ߨWb$EiX@G(EyVl֭AgV)z5vFlrR^ce4ғHNc@KVۭU+>d!.Phqy=Z ndnL[5-I>;r17PwmGBT.$IOAmV ~?#_2|&2]X9g <|Z`c!H*'obؙEpi[w[l˻ߙy765v!՗y!(lA]XJguCEx{Q6~+&jbUa?"e绚V:yqDғatP )Pq5$LI1sոsv*gJ\TU56?՞aА΋7gUܑծgg}2yv endstream endobj 149 0 obj <> stream xڽWɎ6 +H"h`&@nrw)%ZH嚪1DA*Ӄ7Vv~iDBp=0\zSJc|×AGG]ޚti7Nс%]V'5_RqԿ##0EcXV Ϳb5e.^'W d 4Ɖ߲(g@Ml(#8p9@{x׏bH2xAJxPW^HEKƝʛ-{x*y{͏-8Fш.8S7>vX2%>əFĬ);Vb]aK٧kHҋ^V\aaT9#.c"|*i.*- r{HY&BL޻ WҽRIH!Pb|otm?hGu$N^NIIA?ԭa5ν+ yժXup KKrKXgo[)zl,UDRc[m%S;˧WYR]f6Xq~H ";|׳vom+hKBaـҳw͆~~ oO7iM:utW|l+%ȟ4n{=oYsZ3gæ`k9^Wf]GD-w3L IroR-%A׼ԔA~`4OMpcǦkSg>=r7qsyfl-YA7:xzl^ o6aZ@FV_O=~ =Y Mhڲ6 5R贲1tG A mۈ^x`IA^M#+< Y菱;~<~0WxUmgS'n=wۥ}27iIoi_tLc+;_,3-Yn쵈h F7)ʺd'>{8axޤ c$y/zu-OCqG endstream endobj 152 0 obj <> stream xڅV0 C@يw_JJ$Eq{u:"5`?o?݇_0]6D{M1^s~܌2᠄!Rt#3a"TaKvHgP\|ۗk2vzWjp0L@O(P2``1OsN(ˆ(Ĉuxl6ш{ ZgkpƒA0zp;yx`Ȗ4*,o刈a~!a)$ә%$%U.bnS#P\ܯr2ذYFTʓKDgl|8޴ǎbk'c'z7.|yK| \HfYv(NvA;DCaJACY; FIF̥9ABLWWl69wh~^EKqa`54ax-QVw5' eeKPМ&@Uh qizwxE蒐S!Gӷy_փ|BT4gIi{+nxQؤƶF1TZus endstream endobj 155 0 obj <> stream xXˮ6+VK - $+]хkgEpvJ<MOOzROO𿚶;>?z|3] NǤNښ㏳R7|R}n=Bo(dhÌ.&miPNût#YEYoѹ&1*Ut[|V@g+;8uwr"IhȻ*BS'G&n[tޯZ!8XZB0s`kbʝDhG8#y[ 5[X %>+A'1X @uR.ZsCo$B! rZ;@UJ442X2  +&fM)`I%$UUpuK_Pl9Qu9mNSഐx" ĭX6Zb>H<ۈm&eH#>"xY&6vD')/l|-+1VecSߙ&7z_J(dE^r|qvaâ))}a"Ai"}wPK`?ea8VXZh= q#ڬSb[r;0G4wE֚,gF~UK· ss`=7.3)-_LBlem&\#st,~,ͶRmRr/ HW^w |oέɭE:[Z_V;l ֥:Cι䒠KGBlK~-4\6$dLo+){=A]YqVAUJXdm7n^3V+ƣgL3i2TF4JRG6 `jUԗ|OǥyLo츓}&)> stream x}Tn0 +EQ ;]pڻN"߄(N]A3m3 -i[Ũ4zOAˮ1D583ƨ뤵n`mTmZ;Giiyp`"h5휥n%9DžL|ӈڨ!18|ٍ;ײ͞#:݌:_>Ϸ 梄Bˆ&zөPPVrZ;Z>> stream xڭWK0 +Z~Hiw'1˲MkЃ֟0 :d'LA)0E)r 0"'xyN`:<%m p8700 ; Yx%SU]wv8;M&G2:EjBtakuBbw6X4\Ԩ9Eb(&VE[=epZ @7#uIc[5IĮgFh^qfhb\ٕLڨb/xH :Q.a#sHٽ7k*7Vj rAGyOUBFoCV):s0qLo84"թkxwā71}6OBoyfQtVY zdօ8zO *r6ϧwE6>aVV 0N!نJ׃ ~0ΨÃsUᡚCL[-ޜșW}mRn7z^L D}wprzN):'|TۊwoKau%nGUKXZUWAwivk1m]z:y]}*j%:t8GvNCdջfS[M8G|/M endstream endobj 167 0 obj <> stream xڕTn0 $.p[[oEƉ;u\R"eIK"CkI'Zl12WCLf0l냵6?V".3ıhQY/!ZK')sbk<].:mVpLD\\}I/S #0zOb,{b6lvlhݧHTM-1i26N;U Yq˥lԮAp/E肈IRWnTkNLuL/6i GcOL/b~rm>CdB>m o_˰[EznFrpf 91/w1Q endstream endobj 170 0 obj <> stream xeO 1 MGe ބċ<'"H;I&3))0Ut{!;%nLHAC-Fr0v?1rpiGM()FUmy4KMhYɬ7:-}y9VOb= endstream endobj 173 0 obj <> stream xڍXˮ6 +AËȮ"M$ENn0cX!IO*S0㧝t!4]s~h?_-JJ9׭ :qGVz4GmQК oΓ+j<> e,x M9w t㧞5m/քl.f'|9ܭ={yb4Z#ҺR[z#*nO/?Ӛag2ˆ6N^}z\G":!6DIWt0 XC: QW J\ZV_농]Ti7wZXoU^HO;fV{#@b@aH6<)vi MƓdH깭,0[SMa 86$CJa]v[ Nxj9OKe%bvCj+8'2o<ޣS9)QXӒ`dpQJ[Yꏅbw.Ǚ%kB^S6`Ey򅓌?҅5Q'\1r#oDnO#b^&fJR#٪"מגR2͞MhhC383 -VzLẂPc{g;߆<\걛iv荁\0WU>ze g&3Mwo 8]~ R.OxѬl!n\Ky wYSr2Ȱ1*)?0<2m\l]*rBD1TBt{Jurm$Zo<Þ{s:@6wb L|_6v09ðGZ^s߮j'BPRqzi r^L:uI)&(P.8VheJ01a`W̏;a,N}C@FO 9 vZ»QkoQ[-MS"_s~QƟ~) 9s3Qzw,kGUi Z*nCW<4ف*ex[7h/|yIr3 B@,;adhAA&n z;q9 WdsL7$."jH1F>B_ى endstream endobj 176 0 obj <> stream xX+7 )$.Ha{שRHQcŽH_"E?Dr~m79z/A1dY)o:5 \qJY O >v^*xz;%z\cաF-4Q6hIoc$ &UǼ]-"r˫}h3`)(6rRH%;PTX1<0Frԟ];#Am֔5]#CUTѫ珔vvV{YFNbNZ:0k:pQ,Gwyj_EH%oS*[u\dXM`tĄ6Nt87|nE=b1:Q㶈_orINPlGe 3:s6+Ly3q> K|>kXTZMdo'8` \㈧h)2VU_C%Ŧuw G>H⽆(zVS/f܊Xˠy$OpxLХG* όP/ᑡ؏ hʱJS7**SKPSYv2Ѽ8+MiW`DBXb7fxxFX{91tm]` }w1)횫i5\4+$AB<µ,oWT֤] B}a$@Y{EA|FA$;#G\5I.jx% p usdd20oޝ^=y@E-qmF^ފ;|e|y3 ʁI ]5>o95&P0AZI]yV@Im.rP7;ԋ4場寜@ӂ.kM+ |pSWcNlCpv1r5ğ?X;NW4tTAprcBǣ~A״|[[J; j2AYrbK[ypr).'/v08J3P(u5_!/Z]z,YrIýq?8QhX^h?&Y/ #o*{_ru&o#7zA,L~NF}3Imu:Qg_t&dTr[=3s|I߼VÍ#nm 3[ $5<[{G[ϟ*ui endstream endobj 179 0 obj <> stream xڭX6 ~;(ـ"@ ]RHIK]cNw*.{|~ߠ"i?Lw8v_J1>:>>~4* @vcf\z zWgLI1!Yk?P?MVQ^ׯFih4[X&B'vD01uD­< $ ]θG,$aQUf j-|F7Vj"?[#/4ioGRėpA6ޗt.*q/\e2t :,=3E=! tuLVLU`Gؓ5JV[.vԠ,FЮu4k/%Ҳ-L2px`Kr:AfJD49:v֘R}IQ 5[j*ވJ7r4[r"0(I29pJ"iMrAK7R [UW36\PCZzi}VL i`ߍR!p\+;cD#Pvc6縗/V9 sܾV^r +"5E V:2,貾, T :G`)sJsܳϙى61 ,ukU |ޫGf"_-ފq nQ x&cbYhPF#zoG &-|)Cg Nn?q,X3Ƽ H#|LNݛ[Ys T}WMK\x({DSbk\b׃S]#(}kmI,! /ƭ+ I8 6c`4ޖ$4n.` :HqJj!t鴳BoXcώ#~8fb>Z֜*+_|4DVqoxxK!)P q=%8v(JU\?9wGpS(*o֨ɳItCvhUMxlhk8Hqx=n Rt%raZҽhLCy"ꨋvP0;#ԋmy^&A1p& h8L+ZM[rqbȱጚKGay} UԍSvt zho"恇}Y03s[vrw,֏%#E~0ssy'QM.Ul/{ݬx1/6tH\(zO>G endstream endobj 182 0 obj <> stream xeM 1 "ڤӴ҅;;q33ʅ2?2 #M嵔>䱘`{.gε-$e4SLuQfUbz>(ciBdB\,Ya.ټ5^i]iNzJLݶVO?տXm? endstream endobj 185 0 obj <> stream xڵWɎ0 +hd |()[܊LSK)dGt`[(=.kЃ?=p_qy~<Ovq`pOa`'/ǗoW V8f|thAT:Bt8^hxl*=Cpy>$mPڝh5eL11hLloLz[bF 0:Lq'u \2:ͦ;VUZM4ÄO*\ˊZ\W "kڀ(6ym"I;oÖ3'xqBV*rXo8ocZ*>7y;ۮi2 -bo#f_疼-"QnJ™8աIS갪!'d]RYS#͔z.8'RHHo22cM ms\mdNhq_/kbח>zN FkkfvъG0UR4 }ϭqwjZwffo0a Qnk:p7CI_YX2+nREJ׍aݒVqC^MmeR}my;|Cr=Xr ]4ÝHuuIԡ]:anO/NE?hQZRG-'F(3#0+O~T] endstream endobj 188 0 obj <> stream xڭW0+`"@ ]wA K^Jo2ɡLkHKX"~sӟIN>r Ŵ~O9 :&'gtra:_!,<bˈPQ$eBjev9i+K.i5%ģ]W/$Ra}|֗|'kљFO~>'g-ogsV@x`S@I 1gP]L @IΖRp)Ѿ'hO'k5̉޸m(;^7 &;MKH\HSl)~3%4+8$Sc?tW; x[x[DPXWe%=ݪbeE[{?P$mn2P Esb.ҔbpZQГNDY9҆ˮh3X֬G99J9(?-IsPcxK% -x)aQ%\vꮢ! m]J7gÊ$F֗JN3~\sejFN=_dG%PQ-~_xy>N6ҕ/*BoP&{jcͧ"-`ТbyY?/7"A~w#HV> surWlOY+ԪdɾaKfӛiތ*-#zdi3W6$73l`T2@~gٳS+ZFէB9J>@3^;.<ꠔ;D?;(CYKogHauge溫nw~+?ުqI=-p 6HjXݵ|> stream xXnF z` . VJoBΐgW\$HN);oox?N߾9Wd\}.6Ï׷?^qɘp+=\~ .F/zV$P@l+vXR K~7ݢ;R)u(<:Wr%D%wP7WrdjK~n'Hfc23$OfW3yъ_.!& 7bo"{W\.E[`_JΖ)2,}~udȉ'o&Dk~!"jDMMr+ iي 1]]\УA9.˞ ƾ5~y=& z- 1YZ 8fsnf~+Yk@&KB>)lYgE1X+eu]F].T^KyQDf7m2%S z.fs* Q@ajo0M_W]|V7;16,8ۯK(LM3Fl5EQ$,m+VZJO2&q;W ~`Y,$.m ;=LC\uvP>&:Nv/}&D3sc<qZb; aǓ#E4?$Vp\c Bj02ϑ5 haxwLr$$r`,P&b}vÂ{nеd}&<I`I"O% 04(ʌN=I-ZxD2[oAED%UI(,gqIV>%vwM endstream endobj 194 0 obj <> stream xڝ9#70+*׀3$F$`ݭ1v{ZMu.=ٓ)ߜԯS޿}r=O/ޞs>b߯T`P֝u¹ x_T70c/)OQzxMǖp!6m}6_mk3oDUBX6(G.^E9{z= P 7;\gBh 4Ⱥ#8(Wk0IFajplz4nBA<]PągoيԄ0f:f=x +r9k:kŦsC|$1MיXw_h_@wA@ 0D4 ̍"_e/[Ǯzf,ˎhy0aw`몦LMqLڄrJtZh-pl%, aL nvDI7RHd}-9F>Xkb_~cfp֑߰7!ߕr<1סbt݃ [ioS0ؼڏQlUd^5l˅wȆ8RtqI-Erj$, ߭OɾIknơh.tHxuP8! 2nri6B E|&o sُTMPgPև|wd"cn$ɒn#-٪Y]=:u}vµ5LڋǸG H碏Wԫ %ƕ0A9⧮b=4'[Apn \4>'îIEJX!YNz]`[4G,": 'EV:׵&~6|ʯ<'bsL$ dAkXX6Pw8%(l-( JTfj,%k:#]x&ǚOIyIyu?CLG}CA5J8 I{S1 A^`DD%! 6NjK2ױwV0 )KRv@7oS y -7?z%Hn;{ܠFƔ6-l6jUˠYql/T2.[$]tlr%>$ >e4{4Z/T]/1SzA59ZY"nݵOx+Y.Ѡց|[&XΞeSW M5MU"uT't_* (c:L"fxj}d;PHEBMoZFa D<\Rq$=4mAT_hܬJ^U̦0kgLX#Z QIXƎkjس:iJ0l\(LI/akKȓ fcSq:ERʏWWK,տX{.T|OBGkyK Nw 8w4KTDoFJ2v' }Ox Fw~*VwjWi8;JeäYH;7`,lZYpZ}5kE[}Ϣt2ۚ_I> stream xڽXn6+R(C--Cd3؂-XUQӿL򯙶V2N <&+yx{MizyfY~c5g]sp8]FXWp@zj;jvycklLi%!5"-2G~[i"J mWT*Y$Մ硐ea#˘Z5YRCdy\GJJG὎`wc| MjLlrنn8v֔|F3}̃Þ70:ya ~(?unÕv7JSZD!PTOȡ':Oez{>YP}s&yWktR0k7H9.҃)ڈp}By &uk>yN"jd%,m>N#G`nYv pNY|] K*::oѾ{&ٳΒ.I@@SBWwY8s|CqbĴnysDcܪՑi*̲$є|uT+w=VFS2ɽ X-W9 ]@jh L5@NHsgp2Vx FBJ(#vcI೐ɼ '֮JD_*,Rh`]/{cԠe*L*L{Ў>m[U%]HFÒW)'DհkD&IEI,'cI{ᓛGYۻi,V`5w:Gۼb#6k ي -ف[]L¸Jr[ mN]M^!2/Q|W-CIr 95sDx v2۠S$@R Ed4ْ' 2lD6-.u* p>.A{KecYN\22̨k $%P][ҟvE;Իelum0La~`ɨԞ'} w,8[n *c:NMBz4daR3Vz}t+@]褱)s&ZϢST#*{hNe-Tll0BmUfz M/ awo(':ZX պ:rBvWӅ^$ї/mk?s endstream endobj 201 0 obj <> stream xX;#7 +3%Qp .$=*Ez{{N;'#0yMմM~W}x~XKB]fKRh_I;aЋM&9}a2ρxBt;y]G+A$iB+Ҭ ֩+^K[,sͨXVucFi߲R:{q.c=Eϣ}}XTCK6lٗ!ӯB,mbfn0$O!%Qcp2KY,4%.cf7mD@lo0_3 +@~8q1x~ٝ{KUl(úO bѹooƜ &W/UY3ؾTgzfh,V&jfԱ}+ï1y8퇩ܡ:/҄Ź5L$5z9;.޶KqXo7I˄-KXϐҨPMfYgjA(3L=3 JXR,ۗ0°9';=2Z7P~= }׳UږԺP yp7Vfi)MLk3(}JvyvM]Z $kVƻk/K6Chw ۀ o ّ!>@|BUTW<~}/FJ endstream endobj 204 0 obj <> stream xڵX6 q \H ]bfvV)M(,^$1L%d'v ~6K9 z{N6͋O۹1+RUqw \ zַ G'Qp}՚K[^gw#BA.P5CP$Z7a.6ΦdfkWfRK(,B+x%էp|Gi.WV(EI;cyʼĜ6Rn|gn/evPXc-G# A:*N!_l@}`{!_hϝ7/(^w1>+?9|bgSUz[#H͂ N16c+d[B#_YMqlr8$zp 6wi8$Ɖwk\SoyAbW$b êfqgfr5zYsS~!^%Z/'eUU6Er!"0~4pNA#ɘ[M65!h>)c Uko~e/r9JLlylvbPqX6Ҡ*W~zUU85GQHS=])"9pe:$a+褘4ɰc^bݠʇXcKE8 (cy{-[ZݺHCтTeծ՟-4t1~!.Þ9CQѕ8Sw$Y:?kB.!0`Cu<gVZIÎIe,@!52Td5n壆8S[Qe qգ~֠A&;ǭmz$5Y;꭯Q|R3a~0den z=uk`ү5aTuri)S9h™E9^[hHөC,|Ʈ.ba̩| QZ{Rd\mmNU j9TJ} k,-: T<ʟ.>s"oHP !g0hHɃIޕkX!VZ%t|ڐs\q#QZ"Ikj-Ơ҂62my5-[ү0Uʧ0MiZ$*}ue4iM8,ǗB Rn5]ZXIYD6 KIu)u)9H1.`XڏVv4PE; r4ǻ~=ȇ]̡BG}cȆ`C4Uϗ endstream endobj 207 0 obj <> stream xWˮ8 +z ( H|Y͢)Ez$vvEX")萔L 4W/}O}~ fp:{3{S,cߖngemf 0qxƝ-FHkb֙2,FkcbSݚ붺] %-ʾk|]]U$j.Xl>7{oߚ>&~:Y[~њ$V:y)N]d\d jzf]a8SG!ϘcyYx<=6myHGlU&6Xg kd]g|9KMUv؇RyLJї#OIhKh[IOh ofrE_ nqѐfiF&T"Tu&lU K*^:J&o;1$LBwq&Z+堜^Z$x 0*lTZ!̞F8نx[(Ff 5t_~CzLV?ARsj[yε:&jw]TgT*DO+n!Z֦P%0{;5-B꒡k1{t=h@҃@ {,T: Dl v-p& oHM]'y/66锞rd) :29CQn_PzwM!"hWv }$m _ {vIZ]3( O?[ojpҵl*p %;37υԾq涂47*v ܕC ޡ˾XVgbQEKoAUCc.Qmv?ehNʇu5õvA`7 }$SX4]3ڣrׇu endstream endobj 210 0 obj <> stream xڽX6;|S  RX~JoB΋#}7`W5EΜ9;ٕf]~Ze8Lʦs84=pq2^e|)iwG[ W|n4 7t[Qlb16|^ELn?&IV(BPnB hyOᚙ˽`q6?q=,=^;OUM7] vĺtHqԔV"ynr07UY+ʋ:Gi   dn3xrxXK0- m.=4щ <̺e3e-!2l'vG84ϳ9b%kDL` MΈ-\^ξY#}X v2B;fts'0'C(q(Iutj84"mRsAH(ED@G*|TVVD)Q ~ Ir-L,ܟcT S #TE+*ǽ #A}=OHH]f&mDޒt\~@>yh{m939InI_TCAr!:G;~Y '$$ PXq8#;{L!RqvNctv?P4aBҜDދ% $9 tf=4-tg^UO6_LSqHѻE "T3;p{Vbtj<;"+PodC&\z(esA\Eњ41CjJ CuB$Tm +Pa=׫BڊT\iW._\E&EX5ͼ7F|1EtG8T1~.UG m=VVU0"DeT/J;iyi/ 8CNJ[bPC0ɫůeGǣ5Rɘ'`fѸ"Ҙ迠rד +@|> stream xWM4 +lUH inôÉخig}h7ʴuytu9xw'>vLjB{/y.a�9<~;Q(gѹp=KpvR#yG ʁoVx&qѐI:4/</q#7FE4W%Wx=wu⠻ć'2 4i"$ &z3֏$XXX.Lu$C{$;HjUG5iRE9،K⽙)ucPouW5lO ~ 爑 V @<Eej|?09fr IU&KyehS,؂վK 읺*^T̓86M`\s; _qdCWm[*kMQvu)-RZixAy_v>pճX'&sxYi0)),J:ZF![osDQ`.9":?\ O}q zFqD`=pЧɞ8c?9qSQ.t(7ÿIz6^m,uWjlmB>C,:,S6]9[EB$2Z~jkT̚FsjCל;Ф" _x{?Z7ހR=[% n.V9v?]~ R=c('3gnA{yd7Dtd0EIzZڃs5j&fm}ԩz=DbRue7O Im $rwviX46-W/oJnJQy[k,,&?Bd5_QV`,$AB͌Zfgk˭&N5F& ~Jts08#o&9>$?="{Ts9^AT{: ˾YLfPNTP&B4 ޗƻJTYp\|69!tRt}>358xZdĤOiW Ƭ)i~73L endstream endobj 216 0 obj <> stream xڵXK4 +崑F= 7!3-' Nb;kvNcvƧ_K?}t?]C@O>v7oq>>cxY|n3xx-x_{nlMWE#ꚏӟr!դ\Xۼb Sw7+ hb[٤Nwu |j@ UZ@QJώ'HlC~EF _P6z CJ;? e(XJovtxHe'!9u EERaEZdA ӐҔH"UFc]2qsv *7gI5U>9p /Zxgui\`CJtYҼ2E)FQ Byɂ)̳xuZGXlOj‰LO4Y4!1K]q$Q4&|6()5,]K䑕;:yMF9!} \*qyS#b[E7^f-͜S5Ud#Eb?Bx7aQ8*&R6pBd L (~"p@B~;͡};*ՖZql>hx\#  ʼn '9)l2t=]1S6{gqmQm\޵Kr2Hᛥ&UKk{gaա#BVrTsĹYf>6*:w)EjAr.P)V2x55pkXj'~^Lo~LICkp&"߀ GEl:h1R(~gdHe$ f zw5V3TONvy֭OۙTO؆mey(v9-Z=6Pai{X0m8uDj4LSݎg‹y~Rk-%M\DWx٬ Oլ2dm:O3wί*ݠºxZ{^oɫ.5LݷS~w5s-t^ s+[wJ#ie74hyoZ͟BtGBאԗ[ g#%c;W/*ÿ$Kutyޅar,~*?e7N`م_W R=pR஺jz!cAFhH2+e[u#|qx7I2 endstream endobj 219 0 obj <> stream xڽX6 q$)$.H1ΦJoBI$E?+xmQ$uDR33?;$ͰoK? ?bi >hpvyx{nM8ϷPu59q81u.7ohzⰏ[Ӽp,(gkDçB,ґ$_DO[̬q|OH̲v"lw-RĊo;W'D30 h΀v|{JqMoacvـGQlPYC3b֌_}eّߡ=a z J`D UB_4Tg6[CfG"<BMlb͆J5Bp&e8yFgעԣfFto1nJ|(dž>>ӽ*+ϴ)4B=T&ϱB:-'Y]a86\K)rb!iП&+QdUtN=±}-ukp>S:|%tu]`KqPNXjx46e޵Vڤ`>߂| I *-jC % jivbJnGu$~ b8E/ttTIeA&1S2rZR@I“Su:}u-P}*T91_TO}PK ,OQ!v?9n YW+{_#01Ndà=vW(&ҫ}r_\9 ԇ-]*VhDIH]cT־-sTL qSHtJ0u 6ISș=A6bnkPX,{kgUIE5$$C#3ꕿSт:ElTIxWb:$#2(ayU:6'cU,;isQD*rU'gxu˰xL_T9qV ׌3*rT#Z$z ];geXx&`5TvG;0)~3_UrF endstream endobj 222 0 obj <> stream xڵX;o6 +2pP-Э@C:u_*Q @ĸ;>>ErgғJzZLWwkzϟަ:;^jzqz㩔~ONO̟#E)'nu~/X~[WM^]ӪK Va_^)\\M P?~K i0{CivVfcXGs]P'>< PTg7 DwgDgwլ?ٖt-Dykk氮t-{I؁Ցplib+Ҳ2I44R:J׫8 -!]$gWM>4̯eZAȕ`X1vvZIE*?Q]z-*S|đ<;{UqplΣ3[--vސ!؀+҆嶑|8E.G8;Չ_ #D?ܣRMm;9䋨E혝#_8W2pCO+o#G`bOV)fG򟞱x.ڎ=giz6'%H7w:YoAhLF`i(-+:% 8tT?j!YCbLfɨeEHEt1vbk#qvKŪ9reʐnLRX T,5^m+L49rĖn=9) !z1"mRVeԎoo> stream x}Sn0 D\xV[vs3e/!%Ro"!t-{w<ˁ;;8V:#2hsNMR{l^0N`:.$ Bᓖ)zL,SN^`bZFT! :Z$fx3n|-ԏ>b2w *hz^-usI5<ȼss@|˄> stream xW8 )vD 8 pWΤJoHYN\qEk MQɏ?;}`RS7^iQ/ik_.Jicr#ul,٦%wT|r|; &`qfg[2!u1^=پEý)+ڕݳ<\AF}R,jq۬} Sf Y7Xk͎z8ԷWW*X߄䭻V${y|t̒!\e,(9~+Q14ǎ1S7,1U;:1)+IrfZlxͮ YӪ<G8g4x}+ ӱ.+Rjѧ,yIm SxG8ZjtHrxHvr)~lB!dXvپlKCh b!&XR͍#"S➺o} w^pȣi3D! %gP=1.^-c5 |ŭ1$]IS fq2[r`B CIkMBͬ6[̼#n &(:G8ĝ_Ao8g8oߕJ hnP |’fFjhodcY2d!hZ.t4N>P;KT"o zinGt`dKNVmb*&Kmϫ4bhj~ p 'ivKmnHOdoOܢqQ8Wkz?TϪ endstream endobj 231 0 obj <> stream xڵU0 y8TB= 78q/؉Y ڢnߚk}=?^`1RKAѸ2l9Ud[Tw$֨X=Zuβ0ʷ~܋L#jѷk+侭iErli&> stream xWn8 )0m-0EI=_HYd(ɏ)3;ddLp W7A}e>&sqq:wÏgcl4/xc'ww럨˜KIRt:⟿„X<"', lK42C:W]4kTnc 0P߂[D"TM/Z=hclY; дca뾞DfOr '> stream xW0 ;0\H 0]bƳ*E %d $zGW';?s E7OQO 1(ttVr;BHO0T  RT>F^P3>rc@x~sx=)xhy;@H ]z1 zY ϝAKzҚ|IDKZs$22쌽:UV(ew}l[r6I!(०2pX2|`$%J+?X?Sk Xa,-?x?01K%sr n󲭒 A딪>r8FHHYK)E,a82o0Vf;~lS> stream xXˎ6 +qE^h tW ؙUM%+tP\f_:<"?Xr~o/U(t{.*U[\/W!}^gO{X[Z2܅:~ W_~W"K#r7/ eN v^M=$C_Ľ&y碄8Ш9pڬC+ aGF%{l4t(_v߻+C^K\FOw $L ˕.Fb ?}zRqe {m)+(.>\SmaE9}E:n-YfYF7lI |CaZ%,[ BЎc Re}>IRVX@5MRgC͌`.(a_Mfs#p`>ps5WH A" m@'uKUmf[4<铉Af߷=rdFd]nytܑJH9-jѦ<_}ԤwfRO&OLZAI~bG~T&sn3:zYPDm@IkcWS ȸĿó$/t%z xm %~> >YxB`K Qwf!ޕWrisqekR*UZv&}sfH߭$]}cdǔx źD&zFKϡ([Zw3N)Ǣsv 6SXXDKlcwp$c 2DcIh;$^J^A/4ⴅ Zrhn Ӓ,=dJgpYz2M^+WH p-p!=;NyifTq%ߩ|͋|< |>)xdԂ%7^;icWY|Etu@T1 _!?&|H;:`\<x19=[ ef:6_^>{$9ᑔ8ic endstream endobj 243 0 obj <> stream xڽX6 ~q0\H ]b۹*E޿ E%k~6w5fF(H~ 4O԰ւmj ~.F<}k&ٷa'c4%Ad [/ }"mn펾0.{rpTdXB(̫،7D94_e+Cy& Aޥ묣㜀R7rM)?jFp(l(Kl]%AyEu>4Q/+c15@S6gʹbqFh-~SSK0@gY?V`f48;fJdi—&4޻얾Z8H%#*8[I<eo{VҵqgҖzV4M6 JF[|OK.BΦq^#:~#nk6r?b7!]ZflAN'S‚fIb;Š=׉G]b]ªf;{эYG"e<:(Qp]$:*% Y̬!b,Z_UvdrTisY mhbWs\r@3GCb:D 8OZ*.*2H}=/hVUt}&GEStDtثK]WRP3Da!2Z4 `NedQ JEYPqU79Gl>̡+]4ae7.Y'ϋ0 (B3/VDMX˝vog.W!2 |> u^??=k*7$g8' X5/~,(wd+:}*1Jx,{(+HH{UuԴ^`䮝g)1^N|qslވګ} zydݞlz_:iJrުY87ᙊ!Ek;/fO]# .|?6~{缋[o/$"䷝SΡJĘȕnϗ%u"ף->j1On8[k9zْ}r%.29^'N t}WmF\?tS`PSmӭ]̅Z2a8 'F|e2_~ ";_Ȓ/ڏ{ ]>yCʛAkM),m?C endstream endobj 246 0 obj <> stream xڭ6WM \H ]کRCA+sߣ=s'S4:_/K>'ڳ ayYN_lJ阮o?G`=ڠ7RJ%L.î1e1wPlb~Zcn2~3|9UqnW_t}@HS=%c72A\~'hc\g Hmy6t.( ,`ynM"2"LO<ߡB[ PV8 ebOk-ƣ⫌Y7kq5%^<=%dJ7ph+WQoG9>Ҭ-OE G>&]^ЋU O27oV!2id  7)2()Y)(JƋ.R $/Rֵ?HPd( 0Hڦ9aY̾,`({ /&.w-%%i+pngXD,!*n8U<7 1r4r [uZ~ɩ 6pSPCwKЅM坰4-=:Dfd p8&9L\WQYSQ%&rx))Jp]k:a"#iTU9p&^$Jo).(iďfKI2L7_[#.ӫ0M,doMf{@4_4kuޣ%It׋ U&J xk0hϯD8l)$L܃PSls ^PqW %Ж1.78drhMB~EFkʤ[L k,PB`alX8"&nG" [ ^EhߚM+bFzuGt^!̀JQ ( #qu,Nޞ# Q-izqEuCXT.5o(_A.{^"mN{HKex&MzO]'بKq׎0„WV|p qaݢ%eS⽲1`~}tu*7LAgYZ%t.&X!j9/0{]x mKr)PT9|iB> stream xW1 p#@$:]* I4;!Nt?M?Q?\t7htyt^ducw;+#>v~N`"CJYOwlxN' =Q:Kdz:R Do{os ]llZw' 6Slm-qU VuT 8EdWpʾMJ0HHwSH@hKڤC<{4LqaMD"m)㘺jjQ%xg˚*rؔ &Og//3Qj]نj ߒh̓%\gjLJIpg 21|,"I|pq~4iQ9#Ai(_9PR,$2?9A[ D8d D柳\e NOʠ9 -N ^,SjJp:o5]]lMx+Й2DJH[h:SEꚐo:bYm!IL亗$ eѮOs4ˌmftp+Ԥ>2,*k/Μ=EXA-9*!<ʠYa- EmNvW^6:ѺgC'7Raru촖'IJYnMf(elJ@  >oMioX"}ﶷ{zۮy/t_g-W0u䄳q};8^ Az?~rF:G#?#o4~ endstream endobj 252 0 obj <> stream xڅTN0 8Vz@$nH!.ā`;NtEi^q~(?P_gؾK4P}U޶.DXhNM׏Ak谹szSSm6zӑ-A5z&hM_fj-@khGJ̜ʍ H.SEuyd2Kiɹ#wT![3G.rDžVPb8PHӺ^+?O7Ե ͢UlmkژnqyGc2 '\Lp X|jZ %WtWGfQҡ6:~}t"*ֱqޖNNw]]AnIرai)x=!M38ǧCx> , p* \~ .'!ȮߡcQg8榀&HL0 endstream endobj 255 0 obj <> stream xe 1 >E^`k4mAoBoŊ<|LfҋK(yS{tn+BLNQ\3yd \f1{.yC# AMz 8~=\W=\1 endstream endobj 258 0 obj <> stream xڭWˎ0 +z‡ȭ!qz_JJD٪E]ы<`PC'>cx^h'=~N`hU)핲W|Ro8f~Ov'0y yēiC=QNHr\|[qM=9GNP_`-2E 'gG=z-$>.kR㼐xi* Yss5 9` =GjhTҒ} #}1>mN %&RHqIԟm]P2˩%5{"y,KE_)92z5H'`.[+A^>đ)}AL}.\*ٿzYG H[/z)L !ԧ4SoNkBkD65 w@yu72~L.B9:*1Tnڧs 'e o9!~Gڌ`0llͿmʥ~w`@ߜŘ܈xzn\Ck ?K)Rd~ԫ2*B{6zq=!n\\ | S#?E$zJ: t':w]xص[R5mh&?eޭfTjtm۝9n'״^U%(q)pNq-^b۲ٺ<[+q ߴ|`+_q\\GV5(t;kg"o4Bn[[kkd7kgYo%ޮ BtPA\4ӎ#kūe ˰-mi^Tc}"\#3Gk25KU,^M^+7j4*sR$䷫~ bK endstream endobj 261 0 obj <> stream xX=o37 +շtqC@ފyKE$ot)oE?DղWt]~E/ٹLt}]>ǐ甖tO ڝY3JhB~qJYo'5;:hQ3 h̥0+>rvWV>?/6?A[MƑ Qc`zg>k2|hq,:M%gn@+pNҎ-Ѻ:Ux"?յ$9U+CUu/2.H@5C.Zݣ^(!_Z-/{Y%j9ds.{CfdB-Ѹq5L2 . LGE\(EIBJwfzcQ.d1) Ԑ? #ãY'ViOTtJ7ZՎE>F^xRҢ+O!0 ȓL|@y{QK7Pc8= X@yiz}Nw9,Ujx^E]'P~i ST(5%wgs>V$Z֪$NAQ8(U洙2I/G`#f؈$ ų3z?@!S,8di}HӨV!3eyh}lLhQBBB!Ir9U̙?+0oHeBnĹi}HO3?pϰQ!#VFM8gF li&KT$k,UcH93Rrjs|l84rYNB}C22Ⱥ=$C"0&˼֝cp UJ韠 @C^sfn7P=* YƁwr656cUqfrFI:7J<4)#[95 MX3 qe'(nTA4 / nZBWa-!ƺcj6|="ydzwrmro [x ٤tpf џPVnH5ԛ4ʫ\sӷ|oAzڗ0T?#M4 pk:M+Oo>kww[ L;VzCy]CƝrbǟO wNӋ,&sV #42i Os'?Iz 4otwL#s}cN*MU:4/k!pدK2Gc 2뱭LYA)xiJ__yig་͓N8LYYi endstream endobj 264 0 obj <> stream xڍV0 ;p&@)ޝT)M(qI#x_( VO8}/7Qen力}LjrfY޾-Z\Eގ tS4]`Vq/Y-tE' .sR@a{BxqνvcIoF0"qaY[K-_fjV-j]N}*b{؝wI*5ol8\%҇|xw$yjkYb80h,=yJdSWKKkt{tsÎNƸso* r.?v&]W@@Hde{ l,C1j%*gUs`ӠvZ 抾f^$+,W}z;{ԻXe9i&?VZ< T0DM[D28O2^zɕAR\&ÁҖVeQ63mF-.#Adg]űG"wy᩷J \ÿ0ȭ endstream endobj 267 0 obj <> stream xe 1{b_bv7p\!`',|8d؄v؄>d`[q;B mL8<)!QlRrp-'~3;4U"hV?tFa8C3S{Re:$JST7=,ּrGƵIeq}Vϛ/Ha endstream endobj 270 0 obj <> stream xڝX͎6 )(Y@z+[уCRJ"%/Fl>33` 3<_k6|Hln˜\.wz1>/(g14N|x;p'|;sVi]o?a ̞$̘#avhS[9^s*&/zAP4S^YWI*%$EͩU H_;V\wSVD!kyj&5.L1+]1/,__0].b d,*Z:GD!hdX؛̾,;x3t.l\2Ǣ+l" 0$4fmr bκ O,էƂY b؊w+ĢJ3$qytK'0q +mk(twMWqIތ޼Usߘ= 9.Ϫ3{G.eʰWVswN 4:}"^z'L{_cǵZDL9 \a ?n8*W9RJEQJc>*yeT?7׸m8MGiGSsTnPyPy_eBI+1w^nS_NڮVǎ%?xw?k4kªZF"Tfd*z!߹'PJj0IRsGMEb"rb3RNt> stream xe 1 w"/$APM&.wNNiҤ_"Ŕ;Dv߸o=2|ڝ:+})Ԧkhv~`al J P A8YSuج"Hz1ʠsqu]\TPEE,7k< &;P endstream endobj 276 0 obj <> stream xڭXn$73ˣx x 83pn6rOLYdnI;ɺG./r\Ų5~~ ?,߾E;xE{vIwBY!`qfi;Ҭ ܽԅXBYH?J4q[6 E߾% ѺfஂI >kQ^U3vB:U[ϙbfm5jE$fnKVjCEXP9AX')#N-0IbL fAkv"m&Nk4AvSk-`*=d7"xOE9VSrm!f v%NKsĔQ6'xZLA)(4<'i2ޭgXٳn ߭#Fl_l2ďnz7XIY. u;MaC)u؊.@?5BY" 'wٟo/f,?ƪ6:TXpdo-{X*;G+?o:W~2T@ޡ|SxRv[ [rO9Q5ɂztrY Gd{-$O>wTi^n8c[56U{ZY@hz˾qЈ56_O&a{^kÞ0Q}*?G9M\ߤu=I*3 91~|0b:S֠fZC"&e{n*6>hz9Ts1m5fU E6fGoXSoA#*)OVfP['m8P_^.ɝQ!wt)@V+__ͷA|F3\WkFz'LV8Qe#C*b4b辬d+_Z>*%pw:TwT{rwރ\}2+]Cmت&8(GCW?G*J~^;SCE@sS1TFDss(`R9T'Yk|Hv Rb z>tdlnCاs'qn4ӎjh Y *+3t4н<'δٞ{Lyށ?!Ҹ=2$9aeYQƳާ5fxvr tw*gz#W6]TVXyGsRV*A8|(aJf JldHOHZc endstream endobj 279 0 obj <> stream xe 0 >E^`5I5APЛxpy_~m-=I1b2{MH RPZ&J0:;fـ_rU$H6tEms`mobod }csGq2xW"3XCZ Ϩgƹ%V/n9 endstream endobj 282 0 obj <> stream xX8 +qE%`; V 3驇e)%;d(P|"'e_ 0Yo'}? mN˜\n ˷'cl0/13Ho<8p~BoFQdu.1\(Ʈb5 ʲ7J7m*nn[sJ'Lm'%:xxY2rA[/ji%b wZUΣ`XLI,a7aVr&#T13M4/L翧R9M>+ۢL#$%vX+Z7"IjˀV?M/Q0ΥPy^+pҧ+Z xʼԩodKͅ7s4lee,dxF[aբY-Au;;oa沫TՄQiŽJ[]kW+Zgwt~(|!ZDF:Y| z،N/ml'XIY7BV>] @Eo.+ke'$U=)ݝ' ]zucPZ&+3gpSJƮ_hDdHo™^ s8?hNӛh7P 1vǧŰba9pw]gוWE!9-avD#~zGrhcrCBs<{v۫^cɎ9w\I˝퍲*~0i+Э_=<89.$}/;Q] [ʏhig9npS/{u9UזA9xcsw.5Iр wOo endstream endobj 285 0 obj <> stream xڽX6 ! Cs t+8:u/Յ)N-1G&%]?L2ɫ_Nׯ9O?) c>9ޅA0o{["Xi%̧TBsMRwHo{:h y<̉eLV :]]VA tpZ8mQGّ$J$MʤdOJ!f.Iȝ0I$slQqÐno/u}ѓ[Dm.i\R1JڞC|(Qe`4f ;V92-ZxKbjW'ΌC endstream endobj 288 0 obj <> stream xڽX;6+Mpt)U)>$ʶ\-r^AMN0_L?g|~PY{};eh5YiзB?.\NJC(A1s"%%~˼f, VҪL9c_ٍRtT!JM|S. Kh)s,Q%Vtäy5'x5I/8WG4-dQ7trv]cit\Z"@B Nb!`0ǎq4FV;Ape`#M?( G(  $[@D?B@7'}bU=7M)ƁGۤlLL*E `~?qM~ѧ_/T ?gBM!42IMzfDp)Q.WI+4NfӖkXכ()*9x*fb)V,l悧-V,1a@ǶZhYASxw ֎zY0G3"zCu}ƨӢmiV{B{wX#o(S4|}wZ:KL;YP Jo<\bS{{!7Uib-b-mhIq9ٞW%ΕwIJkq_u9YÃk-W)͹f%(6ņYwc[ND 3:Ha"A;}Y j4Pݲ؄Դm)>,YRӸ9c ko\RxF oupek6WB+[ W`t֢+Ԟ4toydP 3K!~1?2.p endstream endobj 291 0 obj <> stream xڝXˎ6 +q ^\@w+pIW]7DR+38<37A5l·\_<:B4i:+gBX;;ƃ%4+\N)ky_Nd%Sp4tM2wk6$]s˪gD?/Y1IRyyIބHЛ^ R~yȖ kpw?}99R$_b7ixR+x;IߓL,1ɺoُs#!kS_dcC :nϸfbSrc~uPI;|4gh xCx,@k_/KPʎZ*fl5 $@V3†+@5}rv-'f-k͜U,Obw\ċAu'7Yv% >C"dzu!̸K?{+$M3g{LRsY[Bc]룴$3R.;e> O2Qdw2+3ۥV:B\.r=aيY0Z~-[wյX§@>2#u1^ddNZ參2seD!BX=7t1< L=̤?";ї3l] H`M'}BLqίa!;rqd>5vͤɮ3+c7iǶ{' n! P)΍{gj̾N%nzAh/ y䳬(]JQnݰNos~pwJ+{NC3VۺO endstream endobj 294 0 obj <> stream xڕV;o0 +<]QoMnn+:NJ|ȲON$>E~H0C_ ˟-_e CJu0Lևa408\?8|^lll+8-S2~qb B{jf͗Wʅy̷,Jlb@t}wM2u,W 9ةoe6Vp {\E.Ҭ=u5'CveǩP UcC7E%$!xm!osN߇TCE[?Em;'2 Tt ;ࡺd!p" mŜe5k H=s85|6WzdvP4g%RUњ lPohF 6T)R:KrY;>I++VpZZɚ{; wqi)4-9;3MSV`zbIl@ Ν¹~6hKG;vV02'bSMB?A\v* V41'#O4t]՞d$Hթ#e'1>ȴQ+זqkw$⍊ F+njI}Q3|ugSx_"OJ/ZֶAUfllv-Q""l)XԦj*b/7ّDW'gejZt ZXv{ +9 Srgn!e2YONgSdV.s:Iy="*XD hXSi$iPRXa%:>:@(T,Zp֓JۥPAYۙ鏷ۤv"e\u\zmieh ,6V!©^!?fu]:g?>c endstream endobj 297 0 obj <> stream xeP 0ͳPzT&&^lSYAaݙYzbJmiZp;'xQyRdbαə|^1#fL/IU(xZ瀄ss5 FyX ܩRk.WV 댴y"M@>X~uB endstream endobj 300 0 obj <> stream xڭX;6+T&u  .vA K*E>f^s5,|$Tm Gt17\b޾5)RvN9o^Di?EJe6-:Zb!}3Lϒ>H+DKW ,3qЕ} C&\> fhŢڪ:jOhYI1II:QdWmҺgJHR3ȶgx|Rl$[sFR'jEKڊƥq3e sNKٽH@APErAGv޼R`*q3:㣘T夕w]mߛs ,oU;Ji{#sT5nDȆCNF* 6Ö$lC|x\_RaV"msx]}6$ft÷{ %ITjh|?IPIgHy7 ?k9QLI32ՒkAdʫ0DiZ8kT\*%V!vjU(6NkG*yxx8N=_EVׄޤqW q^/բ@7׵lb)Qsqo\p@鷔GtHmCFƠwxG(1ft*d*!T4驧&ćz6eYpi垒=~ڙ-KW7aŽՙix@ DkQwFXZ5J)p|fdbkL#Omc ^rbけAC_9WaOxABb5:!^%ߖS`Q]m}' 7'p=Z'$ǑΏ$} o=3ЇZ.Bk>S3Em4#dUFl>p8feT#T5P%'3i< T::ieag͹659疊{8k|?__&::ohA -EHt(VҰ[cny-1OOg˟,,]ꗢ)+L-ZE ֎(%|5׍0oʞvs^yDu7B@V*8l obMɠ~B?KDzؾ]‘%t(rݥe@>ה0хiXܕOk3ҪZCV?µUl+ҼԽF_@9=<̡)0mpz S?(v ק>_~pJèdHXmO a endstream endobj 303 0 obj <> stream xXɎ6 +h,: 0 [9]9H-޺]='"N? n{/{}폫Rzgy "8Dh<>>N)k=/.4_]QjZC+WH_yz*gx),: o3k֤'1:A`|w0,W|=,rh/mSO+jOCH$% ]Ed:ǔ8tCy"{b2-q!끤ŇȻi$ާP'JDT̀`B0$$O"ע\j oAe˓RE;amND" e>Q;F+1,ha0noB9mn7RODПѪOtePBD2'r\Wl3*K; l)I: bH=3̚*hqh]W7Lq>9O~gL Mvl:VIE|ޫN)hQ "sPٗk}v.v^뇖ၖYx7yW n&fa|D(m{ 4"sf˟t 5P}P{|j[Σwr}nfa>rDq#zG /zByWelk^Q22e?Ujc7 H%DVqY_8^0>eTuxUߩ^t erҺ[> stream xX8 )dQIbƻ*ŽsDǖ=cgC") nWqL_ݟdzq n赱e8vބ<}tT,겠FK~T7.=rW q)\6qq;_q5=>ShEjtЉ0^$}vv@ϖ`åiD4һqCؤ ] mr4Q?p}DxL:BGC1J"K#"6t0ʑ𶧽-P2C|`7/gxkt̲R&i߲&#+*):joH"zRYy63<>l3ʙ*/TVmظGk$- !iqNy E:_eJHU]'J9mQ֓ѩ^ 62<31_"-Nt$ޛOتNXg6S>[J+u$r5Kջ^% $S2d=I.JF i僛ܶZ !VhF}{%;6@A2S۩!G'!uւ6WM2Q},i|[(Ux{f<^-ղ 2s1ȵJE%B8p;S%2[KvgU^ObT/πj]þrHXzUY o9NLBϣ N1Ub<5'[A*xnq,y3c%'8ijANCp5tTˢHSLv=~QEīC9{X}d? c{' L*ԝr17+̍x7ʩq՞:J6B؆ɼJl R Z9 Q82`On^gy &938Q%GL6dBDM.\sDqmK LJcUܟ֚+:E6޶8[PsQlXdrM]#qc/3y_ *Nylsُ׋Zk/ endstream endobj 309 0 obj <> stream xX96 +}x .tAnMh;v#"?|0 _<=E7$Or,b.hNi00^0cR°੧<p>ݜ`yݫ]+Œ3'3yqOes;OTCdAq {>m:k@ <TngS[U0|ӟ`Í+2FpR T^~iD\m 3HB, Pm)!_aID]a'p/+jr"ce"s@k䦖g ߀O%%}nZ6lX0ќw_dxa+%j_x~qfcƸwM0 /#B'Gѝ=$A #xHmQ VY.Eg4Iu cGȻd{O'3 X BewFC8%WM6dž/q1R\͙gd"ƴ]|/p6vڏ ܚ3{A'B=Nֳ=ң]{FZF.D/J'$ח ~(~̙H&Gg. J vII{JxPk!׳]!~=W oXE9G&9Š)JBc|}ω?e+ 'w1Y_Ta Mv=n*v! ڨ7z`?jܤz:6K)?s]*,Q*4VkfCe_Evq$˲U-Zղ H:g3q!<| 67@;-jVIJD\Bas!oq}]Pla&nf_FڎKIx*!e3J6&}h"A$r(cC_-su6]˩P<1!@SMk˜qU%BĂ3T{fjy y+G.t ;bv}nSYkF2/#i 5֙h>!]aZ r=ot>Gpl'@u} W %Lւ4U(R✞(2hpAQ{ZV\+N6Vwrg#LA 'ۡNI)MS'ưFʚHn)wFcM=+gB%̷ޱG@7F71@?  endstream endobj 312 0 obj <> stream xڭXɎ6+p_Cf YmC.U%m%6lb-rg |"a;~ }~R*_rRsc| 5ymq=H Qf@<}jOvl#Oу 6Ze*TUqήgA}Z^ E&l$na|zTtaX֨M<Tm$I0ɥ g%Ͳ &ѻ;(dGN>[7I.غ%'v)\iMKms-)\C%z[-E[Gүئ7,m:,b/,C-/uم87n;~q%(~т&;{VX)o9(_ !*o1dM>`;PEx)˝{=崛LWڨl(WgvD^>7twr_нژ<ڭ$ƶd陛"ήY2? y!IV-<3.뉶uC؟eK>)Qs~ũ'S~)7>o|ZGLm'ޠz1w+V")#x(YeaKW9/3O {ނ:¨l{R_/}8DSN g1AeÒ@C}`otK {#mfsJЯ:(b8!h̔g2JO*k+C4PU1J\dyy(9aXE?(aH^f/.8HI|e . ܀{wDĕU./CM/6\v@wr:*|˽VQJלJxr)`ʶ#WQl `@hGڐ.cnf Q"c`{lk`D 4 8oCA挟ُ5 TY WBNp^jl)䉌RXg^ܑƮ E mS#<1G&hnUU^AFV°VxK-NRm쬔(Ehjܮơ$C 0y` +{\hXdX> endstream endobj 315 0 obj <> stream xڅV@~;[:DJi(wN"0{v7`d _|Oy~ 0Oޣm"L)at0<^w\a}¡4ψtڈkqW}gXF 2fk"NS*ew\ '"6ig|˂Xá}8 q@<%]h  ۣOa!#>5X~L6ѧ]> stream xX6 AI6`L  ]3RHIѲ=f`wH>tH&Cr_<lg?|sc1Ec`?0&K~pxy_|[V|ygQᕅ\u*JPw;d  )c%%-!ZCV|_nsyrKѬ%E%e_YxyBV*o,R  U1B}h0T}WM ŇLz %et}l!jEt7>§rO봨Ċfiˎ w/ˆn:ZqʎX7кה\;hQ:. y5%O%eDLz *h2¯'^R"L2XT JN$ad#kovLvZ)RCY|shvsйOC[ tX2!NiRŒ>{sid5Lr=mq v Zn֍8 5(Dm9TkÖvD6[0(cʱ1f/ ,̍;aZXU#NI#:QQWL OkjE]B&v m W({)1[ )+ ҷ0ORc='7&Q]""]]bw]SOؔ ЅKF?~CL]ۖҝD 3&V$)M{'@Pǐ' "uԮΊYz }y@fC`#I;mvz##A>|t MGm; }JufgG­ØW|Τ9n_Fuɵ_ndzfc^ nң&7N6F6OT)g9]L簅wyJuT> stream xڥX6 ~QC@يSR"%ʷeȏ7 zPIհ5=O_0%{z >7Ry- 6>Bh|zqJY~fAgV鋞ң[4*4kcމ֤whcދBB F-.rI-ſ\7hI$LYSI\cGvXÃ'U݋jb2cK̦B ށv<2 2qwX4[$JCNq6JKٶnJ6.q&"/fO/v]^˄:VfTO^q39:JoXͻi 'ҞNew"T$9Wk_L ̩}A ˑRj:өw0LԒC13rfG-6)NbO%l 垂_n9q:q$ȉ+_%W} } %O]rs-#|M-XĩG{7..AZϋрr0g2Ư*Nu乷Z"%qN);y)Hm$ߥ'QJM%N~%en5AhI)5,OzsoFM^fHUdX[AjazQ™6i.4XYoÎNbob( Pfy&"CYeZUZhAd8\5~uNUnBR* Y|M2c{+N '*V4reܲ#5HлIBY3E+__t}!GnB]5,ņkZɔP,'x kT*_ C+mvEV%j8Pv2$F|sH#ilJ3v|^TTGe ۨr ێ_:SH9)Hôk.:VΰMBԟOfgH3'҄]JCn)ןo6eV_A-, endstream endobj 324 0 obj <> stream xX6 ~ꏒ  VtH|NK)(N|PkDOIO )o+>ϟӏ4Cs4[?}X}q~qVJ;|f|4/(|cR掟z?Z-O`Ryç|]TDۓ@\qY'$ xPAgw'"xhkO=S)eqeRGy̽zy+YK$\ϦgHYL¼eHf 7|u`)vq"-ʶ@ɔҊ(s ӑGRꛢC=F7_Sj̟o %svkauҗ@L |B|ϐs в*t} ̲h9|N+j "=;t453e&{ ƅ=1yf$C4nA.Jd`c؀oȇnbEM4ق&[v2F|V rEC?A°+}Ԣy':젣$뫊'bDAu֏Mx%^zs XO$i()%[r6FWF3$kE9"bkz)KGPcWƹo燫Gubff dZD 0xC'03;[H퓚Í^,dLUOGG"9~'K<'v&)֛s< K=o7ºr'X l4!AP{6vg""CކpZin<8g7e' bU X4036Ү\+*!k7LЇxLaNg5,.Dl?L/KGRAF-;= l` DHPkC= ni/˜W?0 ga,]la)-iRRSt;mpIozؓ7qx +66gd̰z2EM{Nݵn^6Υ~2,1A‮YҶN';J% w3e᤽nqS5Y ^#H?6mŹ2Woi9tzm-\OܗH>8ӆ:옙xfr#9ȕ^Z<@\b78O0-{?qy/ɣ :;| YQ- *7`ϡvɫty?Fg7Mtq2Vr~>-> stream xY;6 +A2d(VජK:u_*Q7wF"?)LsÏ|DC)SJ?%_Ϗ2qP.N'$t1_|1kS *_rLΔ={#ӺTV?lpw i .iџ ȼa3ļ'puDlhajߦό .d] H=..cJ)4׎KEd^;$%Gˢ`úe_%w } .xd6-.p3[4d A%DMBMND-iAXPN~kZ+F@@ͣ ɬ+f@畬0wVs#8߼EUg`"˵P΁ (h[g$r7~aG t}u&]*2ԶxHnPL50|UL#az-7UK ˵{+98Q;S{.ls+jLʋh&5oSI C4d LfMuc;Q]Ep j9;֭CDn>,h}ޑNa6eNc*ܖ23LP稺>i2tnuA+Tjj@kX(}ڑΨ @\ wўlݼmY wۿOJyޝͬu$+<2%YaTh)BZo9Z}t5JY^ݎkIDZZHF=zV ).09>U"zd0IE`s++$5~:x&Rp8XͽC2? Sn&OQ oQU?/fv;ux׵&]mگ$J!J>wqcteU*h?ҿWϲ/*,QG؍v=qTG eS%;P|'HRm`RFN̷'7U%5yUXݹkAJǐ OK}qYK(:1>#7N," mGH;`GȯZVfCnTpմ <1 `j~}-=;F/)K ~=4\=v\yݑ8QE~3oح,{m7_0CcP~_c- endstream endobj 330 0 obj <> stream xXˎ6 +qdA-].2.)Q~%@1#8I`vHp~G}~?L<&jmIBd[dlTor$U@)Ob>A}d{Je[>آV"Tݾ l8- C1Uj">j U̳vY$wŲl|S KʽNp4/RGnF!g`İyVx;S/%'͒@4NRɎ4rh [ 1@qo .-3)9Ln٦x}!$*?gz;,*3iajeU>w-%Ԃk++ 8yT85@n|;Woi7mkQ9mjv+b]"u9{7T"e$:r #.mf6CZR`ML\DY "} Ev0l I +iqǿkю%]b]^-^b5];(![,F9/L+Ze:iZ^_zNJƷw U01)\ ۷~7cu'R{![5TehQ ?,%7V#t]'7c7o /'FR.v@m1;8}UwO%GG7')gظ(l FBxHnioitt_{%s龶UrP;5@;vVUr;VZzUe/.J{qAbvĻ~;K`/ endstream endobj 333 0 obj <> stream x6W^"@ ]wA Yk*E 9Co)vY79;I៞5|_Ͽ)t}L^dt}묔^]6>h<>7|@)k ;]Ni";:/hZpa z=79(=u"҃t9ALKv.:D8Px@dBY xq99μ(qg1|#b j!_(${MrgP,%+Voa*.i4+!*ZkN:Z|ijI'ZIZeDe+A$F\z]qeeƢ$*L Bͳ\k2hvVvcvE=Z|B޳*3_ˠ[^xrF2)&tTy(r9 gEu$Y̮(-Ҍy &Pd,|+TGskX,f 4{{ f.V$ѳ,ŠKr|Ѯo9ʀ28®m33GP3qcgzKw oT)"% ~]IE{6o2ʋ1"@GI/0$2֭ Uf7HlV)vbѫ(Jψ,} !݂UAGe]> =<)VGbF}:&~:=2!xm}Ǜ!*vYS2-ŽՑ-T X\q\ɑoHml!HS;>w=N6'{?7ΙW㗗au%20ޗ ؒv@]T!*jz)-+ۧ&0&}Sc`gMڽ wa|1¾u#Ÿt6.yRPI 0rIo\o]@ۧدA'A4_6p>]߃E]#[x6w]\BbW< cG:[>&!aC6+n.硒z?fi-Q+W#'q+/NVW>t^ڗỔZZD-t G endstream endobj 336 0 obj <> stream xWK0 +T ! qvgā7cvv8~|v>Nw ~t noa<ݹ{wCo`CwO;?|9*y:$`F#k1fY3M,πmZɚPs _ϟu]ncŘ ) ?"o&zj˃#t0PUliBwen_HP|,e vIp2.<0Ҩn~ (YͶf`̾+l/%@ iHnJpf$-|`+] c:P}ĪRB 2$c/ &͝ZZ_3`xR!8 CCNHְ Ǽ~yEJ^f570[7Q15jmg%%M,= ͒BrD.*'9>E9)sڄ A>OdXWd@3IUXODV-V^7UNDHTZ{\~dCzأ]6Щ_y<OϥH6l{6|^8lM%U,Ԩq;Zκ P*k@CEi,:S&a ALUƓv>$BȔ`Jyy3 9;fNM ŔC*UcZ1`# 5f%oz5y踉 4{x zji^yIM9|%}ˆմ<9kr;:MTs2I 5$/]pd\ז*}](zQ/|,NөnW|^ RiNӝ"d..Ȍ+Z4TY:ǏmpʅRVGOPB &¢F}#-;p 7? endstream endobj 339 0 obj <> stream xW#7j>g-64F'fU"`l`"XX?DS,7~vZ~C/yuKk i9X޾җB q54BSS;k`U\Qph팹ZSNp \ߘרrv ֓ 3U/:"ë%RкRf8GzUit;C, ,.#7XISRI'3m2JrdD/y\*izkU}q֖+>Q4#9 Mf E\fq7o ["="~+ U@7Hnj5*BICBxBfLތ#_y֋48/!<&_JM#qQԢMs쎭g*juX-mX.zdFNS iEU~[enls>ݐ*A8 #ܜ\Nީ6 4> wLЂ[P(S x7he)-C(xGF0ԃlўעSIT{3:#"vx)뢵Vs6s ojC F;%bC$n)Oqv$H2hvM&Ƭb. cuu_ ȧF'Da"¡>zrvUx > stream xXˮ6 +q"ef tW.bߛYuTIrvS&)> v0KͰ~L׷W1$v,8M/WclHל..̟er&=[˯o?%uVGVfuE[EL")oC>S2 [.ɋ |$GBreV.; pOWHTᅵi J~YM(1_ņ"䤠D46."%}H9!eʑż-aYJ;īļҼ3s{H@!f 2ZsGZ]Im؈0?"s:Y>`_B(Kl4i#\k}4tmZmw/P37p1Vf3mcI1.LaTG;7_|0K@{>wi0Wݱ{uʽq8yM, 2q~ vm[_.l2S_5Dgɸi2 Eb4}V#CiJxfm_^apO U(0Ok'\t:?=?!'\׎`&կJ'"9\/Z,_z6r\n$[c_j[=ZTڃUٖ {i:oI8ʴ%J=iQB:| yAnEUja?щ R=τHYФ +;ڛ/oS/%µ&艶E[5۫SCgC{;Dj O9aJk 1Th>(2#^xe endstream endobj 345 0 obj <> stream x96++IIt RuspHv v>83s%.ׯ?}\~E_ɹy z!]VO)]>>)˟^l6!N*ф|)emb~No/\QY<^|O8OQ5)X|ظhH]F3c\e5e.fn}tZ=K/o .,&~Kp]]3qIo݀1g"Cbj?XmI"E~ mH0=O! QCӚ=>#qPrD\(c扯׆3p/F_!O41! ٩yd^8|-Z];Xp>z͚H#ZdovEH\} C!Ι 20lLpfON-bj X*QI&.6#|=)]΋C̝ot9C43TKS _wJHa{ٴ,-¾˳M,tn( K.K `y6+n-SU[/8_5|3Weм=F9h;Es>&E*ƴ -8u2rɎ~rL#'eC&[SGsR KRb[%cæxk*Ujv 3q7έ}F83,-߄Ŝ&9"^J״ܴDolӓr,<(zp;9Qx>ԿpW,ֽGk _woX|@2^[A"zp{W#C-sp gFOt~F|ZNя }Yفa$Ei{ !D uώŌk6خW {g~Hwt4"raJEja5-}_6LHdĴj Mz}{h=s40γ=ПF͸5Q}'%5y. 7Ӭf?ŗb7߱eqxԣ7[0Hg:6XqHᴶZ_^T]i3Lء !:iC|0bGv4hFfo(jU_w}ChM&o8d͏7sȸiZI݅Ka$ntZO]EF;lePV c73APM4΄m*5IXnN0o{PeP5X;x{, B3JWeUl9덵PQ'G_\`w;zZV_?<-?9s !d"LK =fF/z9m dL*!v̗f9EM28CLfch|٠8v^UAa$n E&i9Cqej%mȆwIh̟-1>yclbx8 endstream endobj 348 0 obj <> stream xX6 qlLV)M(aɖf﭂M3)ȣ`&p ~E? ?2B`8y<8cz7~2[wq:?|nIEr@SPn.QE?F 1'D37xfΏd"RcFW dΠaVw΄+Ϥ@8h^ׅ lk dž% d }BUU(5B96LgUgzԊTlN R8$aGYY vDž \8 YppJWixTzJ+P`өP^~LE/ '{MS) U~3%x{:fbM+$u03y+Jd6c::32MP_KSUANR<6:?ZXXRKన vGH'I*o9a+ӁL ]cW`Zظۛ5*/^mI,F9lQ'|[\InʮHm+[чfƊd:RĒns;SBTE \[}[e/V\ +_`ϜmZAvo.ಛ BMv,K5a.`=%kބq Ĝt/2hڂ-ʴe`xڹ\S~gA?aw.C!铝&XXv`,{7sMf77k|3~o:ߛ춚˶ܼM솼v*DXRv,po7k=]z meg*> stream xڽZ# O$91E$@ Rؾ{S7(Cɚ7EװG#Q?{1埽$(wykKu_e]/~..)%?nG_+ 1-.m")\;]]Tyc5kg[?e.{u-n篞_wn ptKt9mk{/tC>C˗!$lZV.W Oqկ^xnȄ̃L !9d6mOkO(.G&a oF,FGm1I sx.Vu>PWEґĊMf4iFm3+<%D_L3 RwY/'egG6Y֑gRB^|oC;԰nCԧ0/qԾyY+* %n63-](RxPr"Q9ԓ3DLqYWMR~j*qbpwf,yXӬҹ~T[.Bvd1lJ:Z{`1;#D6%\"t~I^E&n84Wu'1YXc֧^ FϳCuI̤pR>?Ȧ Jg'x7@ | jAZ|ZdJt3d3ӦYu#噔;[ 37vv>⢞+!Dc0mL(ߵ mT+Ht?<=>a4fPVRT;uD{W94\7祳ȁ;\ݞ}B4?;ڇoĿډG8VRU5 ŃսDip8 U0O F׵/'cϺ<ܔQm>v/bro>C=l @vPKu)`#hn{tО|=ef"u:ǻBpalro! ]3H12S v|drN,S%" Ue.3ig*7&߸WBs*uyAGLVᓓhH~*b4xI-3 XisTT6EYvgG%jiX;1lj>Y  FUSfh4ڛ*M*McnѦF 6ȚwHc8{$>.IZE'q*K ljvnU gKœT0H+F^p{5{in^Ir\,O;Vts ^:CĘut՘ ֎_ rznK 㺽!#US9<~֩a JϮ%d6aVƄFm|$6 n`$r?<(hC+U9`I!qBpqbbfY ]i@Sq+s54KkuNϹ#G -EVw;FF/J!\`_ƥΫLKg- >y,39O u-Ի.1#R"Q.#5^˥'5jqO;%"G3$"Hf]"z0;2 E?bg& %do+y] ؗ*R:/Ǝז1U&T'5[F7Hm[Լ3mG(Pʓu;Z'466cnw> stream xڕXˮ6 +zY, ].ߛYuߔHrb3e<0a~o÷nqR'{2h*](7MeUǪYMiΫ, )>{š%J\Vg;{=jGr #3a=%k#ҩZ R2 ga,&쁻W•;g_QztgԵ5QZۣ̕kjC,zNN~u4<^$Xx7v3({ld!H N *RcܴԔb ~SImۤruoOgj={G24 Vj=8[*#a%K=jvDQ_кM[ΩOղ {|{÷.;}C[VjB\¸ŋʐ\p\; y劣Y(dh>B(.rdu-_9)XmL5o1K.;ґ]֢_qvE}.Dw$Sll'4H (Nc&|kfeT6tmɃTX5D/AgxQKc]gsIwWI_ 5v#^Mk>T endstream endobj 357 0 obj <> stream xW6)b @!@R9XS}KP$%A [,A `%a|~ gZ#1qèsn8 ?PK*hIAb9W ?a W>B LɐN]Vi 8: ?#(kT$ӢSJ(h^ԍG4DGTEtP``"SmI ~l|X`tuχfβs.H ~K .0^W[2rx&t&TBQZ𭳛 \)9%^{! %tC\1kQѳ^4A,Jjmk>zh"*w\82nUvXBOmXFr)}꠵RE4 ;QT^p)OrwzQئEU2*]):*/ % FhgCW֠Dn1(;Q|d ^eٚHLySdZ8KUR52p[JיTUXddjΌJlH"S@YLF_c,~-@PK=.np f#= ,m 7}~sB:{W~"k>fñB]Sā'}؃ R٭S~Wn0^WQ g 09JJsg_2z )X>~EqIlji a΍<"HHSOFZKnxÔ70>WS9u`d\76`rEk[~%AYˇ-?Zfk[ygKt%YO'/b֗sbJ70FWj"*ft~GIMo:ct7jwm)Q07BwhdëJ7O_xS千)s5 <@^>hJosiF9_}:K endstream endobj 360 0 obj <> stream xڥXˮ6 +v~Ȯ"qo*R$%9vfnLQ<|Qwgғ*M2O_5d%㢔veexxs2|1/<3a?SkcX{HT7bQIu.z.WLtjfR [F:10]e>MSE/Ն8Y. CqERE,-)kiwb~_W4i}Tsɛ><_`Jsg'.V]Xߣ`4,EL{^dߌn|lv}፬5E=lɢH"p8AqcBI[(gyV:CRq^'YuTn:h ɑBx:[/OC~ 4ݺYs.IKeg,62{}Am-3=#@9[Q9{1BC-@ fؐ}љ^ ok``/gA=Cx$moȧJ ;i\ѭƢD׏J/ k%.o'5|Rfq4uo!q G>@)\Ds K2o Z>g{|/- JRKvA۸jhMu0y/N~ /N@×եau-+a. UFN"8PX\)G0#g.磻ŝ1kg$Ti+r/A%w[g@[q$ !Z/{bU;+e#$><^to7*>_I%V^@I:.;xe砘%wܥ ;ѥk\HGtǭz̷IX6:$rUo[iSƆ]Ӂ$gMv[=18+w 5Ȥ\|wDG'?^_d~nw%kM/mQ2w !yvs* ՑA#/57{gkAJwhԳ+Q Tt'v endstream endobj 363 0 obj <> stream xe 0E~@< AwBvB[ڕ  fs' =I1b2TGh iCTGJT1iK:\rwuz`,&f3(c]k,‰ 隢K ܜQ'U/-O׿_z6 endstream endobj 366 0 obj <> stream xڵXˮ6 +(I.b;UM)ܢ7 3#)vw9]u_wzƩHh]|ֽ$ = {LFyCEXBG"Re">^2*L)== fmP~IǪ<^u OۭYYfP],Y6 8@o¡q7nlfʁ*S-IN2\BPRuB{2i=IGʨ8>RӨ*tMJhx[ Kڻ\FHIF;QMA@8R*AQڧATr 橠\K4ES}uv&TBѠSSif2jӞP[uTxЊd^G!ɲe-ebJM=si)&I(&N(@ tb5E@'v/keˇ3;mMz|.km yjT(y-TZN_t {%|i&޺SjO^izX'& # 0 ]IʀRL?Lb~-tܲF{ޛQ#Gh= ͬ+|n0d6n.Ew.6|j٤OybLlLdyl绗Y1 =^prz3okJ|fpp]E:x7ͺ;k&ȱror?rqZ]h^xD{Q2-E'Mb;k5ʋbs&+eii7P{6v=es7pa^> stream xڵY#7 ~;4`H` =*E޿ % f,I}ɞ sZ_y;= },1^R:u5Ʈo qPbH(]=> ~'|[DE koLA x|kUxܕ%d~[cU׷ђ[KE9k%|:G>UA-X#_!TpEI7O |?A\+2eL'}s#cik-{E@E[.f#?$EhDeF7Q%6h=nhϖ5IgˬDH͂^[ayf붨6Ry # G߈8Wr , >Ua-[Һ{ohz#jrQqa`iWO2؝23jk0q=kPmClǹ/c)iMx$_Vf_X{}څ^`,>.UousKky|e*bJb'>G:2%87ZUN^kBX&9HRvڝ%7'ae0g?(:?Sc s6k؀"]utFbGSc'so1ƃC #%WP'I fF䉉Du|vTg&2np'q{ps=%t{X7ܙzs :ThVbuCS;~k:]l~~kc!V #-c\?xx1FkwMZuy}VګUm$\W_`R-]qkr]? endstream endobj 372 0 obj <> stream xڭWn@ m>It RX7U94:u[4|#9 r#W ox ׯrt>~CBQKUeozު{h[8my BX w:^HFic ܗitBɾEj ŰoV?* eg F+%j ;GŒ К8Z+9l5ࢾ2U&n%/HgjN-Oߥr@uxװ ΁& ow27^{ط;$kP~rW) &HwelW8|$nB!eCKhq 1ha2%'ʤv@YqpKA#٣"dm Tr:Řb;NRyQFbY! e/>ewˢ@.6+MLyv%lCa '\-V.~$k@.Pqݹk.6q\ 77حqZ־TT!b߇if$6v%y~* R\#)3o=.:zU'gCz};<폜ίb1+ߒR;=cM endstream endobj 375 0 obj <> stream xڭX6+-( 6[3Afڑb$uzӂ$Xw*`vHfX? ni@svL1oǜ۟1v+\}E;!#'&t^`x%|x׋/)^3ex3x_ ae>:֖$T.r96M%1 /  Fz@9.A;?.%QDv[M9y' $lı53tWVЎPfּ3<\iWF,܏ViȃWbWTEJX$ n[Rg7!U-vVz *. <"kt@} B1rCu\4= PǫiLxF^IR4zZWI\S^<`kiMKeޯ Xw*s룔N$C4Gu\ $ڣ2j 2 +Z)3؍*TȽp8)H۪i:#_.Gb+=R$kAt]/vnͺ_ Og:B)mez˜]s$]MXJ=9F,ϻQKKOWaiۍ )]{!4}Nq"d>p4Iox"+Ūl9Bc.4 Z l\Umʱ|F"rd"nH:6mh{EtgU]>F~`Hew1'W0 O<'9vSW90E=#g{;@gi\{@"D#B7Q-3r |(N'N}R<)j( ++zAL#V0RV]{;C^kL|> stream xڝX6YS`g&3tk9'QU"EI3m*>` 0_?m7ј(Gp005+k?oF#qn9=:m ZL&~Yym9f <n`{"a0 xY{H)tbiTrxT 駱!|Yc:;Xe}ʰ/@5f wkePT^ny>rAG@?ɓ/&E#FụuIzvJ(D  [Yؼ'z^WK.5ilj%zdi,|)XQS=X4fT0#܌NOEuaXXJ94Mͽ`Jm- @N {vKY&qsu{_8m\.w;PŧC39|[n0X_I8G)e"rMp<(3C[ Ȋ |l /Ug~rFu ɻ#$?g6t3˾\wITHq 6}߷}hIe.9m` fƀft[—Uz&*{(,ތFs ZU;ɫUz+n Fo)͝*\8]7job4m0I2q'VP׭"cIpSޔ=KF|#n 15Q*WYp(jhĊ)l֎[* RE6kG2'ReX͞l x('k*(oUFw=]Lo?5Mxl(s"M6Pn9o<РRH5?Xx%lD3 thz>P^2timW8֜ߧƫBBq+%|íp<T&B^t Q+JC8ȅ]]Q)]jOZ7nY,O9{l=Y˔9 5uLU/"l#0WA.W)JaZI-Cm%pVz>YP%.4N~xͦ.Q]ia #Wl&IZ ,.'+F>VfrV.a7QJ5ƒַ9TW%"ZEV^)r'K8l^۶{]}%Z#d|/ǃ] endstream endobj 381 0 obj <> stream xe B!=y.. MFZƮE:7ғC(9Lnݿ M{@FQl͙43KR9;P1d4-̪P:C1WD@ *#ֻzͣa.KsG?^65 endstream endobj 384 0 obj <> stream xڕXɎ6+0t [9r_BB%=nYkyU$[Ͳ[~N߿-߾g[Z\\.5ڴ}u3Fc{xcT֋P)G| 3 Y}͆TmpU&)+#ICSm Y!6UWqu][$ cEuQx3)O?m&uS2TIR0z睏(.}+[7̽8͍⫄(v9Z_]M.4ˎ L\pmE_'a$ ˹:|1~{{&W 6֤bXRmk?PuWΉF|!` $ML@ZR@*S?VegѯD$D.B\{*4)WWbmk;GL)9~ΗuY}XL7By ۚp۞DWcUC"_. 7qIdFn F7jӆ`F 9|"40Mi 3^W ݏX᪽+@xk< ^9tVW߻J`.nBٖnb_Y{"ʃtHA懅H6;ʆ{3.AYI9F06%v{Pީ`)gM[ZW6R[qKw[:ifb8w2hj٬ s̫23En}Ϡn@s{cU֑֨`O:GnǸe ԿW(,l8僞i< z$(Kgm&MW%.G)s׊%R˜&s '^խ(>EC3-BO}H@hG~Cz>M ۔nZyWZlWA>) uK{n4/M<:.JoS~`MZcKj.h#5 endstream endobj 387 0 obj <> stream xYn6 +ףl@@w+MćD;N`H,SIRJO;._uU~}w. uA1 ~RzM8[B؄7$M(hBz8MOL駟oʑ:={^u򲳻?&7?>XOv%;|ZçnT|7QaeaE&+;v)8uK*6,84 *E:doQcW|wiԂrL2 saLSyO1XE`ӱgI2-t]77dHz~hf72|qKȹy" Zz> ?m-v@ui<#i)4[L1<&y @Pb1b0NATll1ͼX7/iD_­`vJQ Q m7Zf_$hN5`oUDgLU96x"K9̹eS`smF` {])`yT> z!@?uz1/0"[~ -;*%ZĶ-6j4t鼛>yhd1Y^64uiBA#[ij֗zp&nw-GWn#Ѣ9Kb=Jn ! C9X¼43쑴\FN?,$o;ۢR6h+Ha1W_ _G`{G3wZ`1AVēgEZBwI=Mb s>]M(\AI 'o endstream endobj 390 0 obj <> stream xڭY;6 +fd"@ ]cU)HC-nwEQ9ӿTh5m6s1^]kJ_RzӯoyEoRua{ #/! KG779Luݑ"#?.LL_Nr.k8v+Kt؋gH6W+PfREC s|lރPe#Ub.xJ+47r_fSO5Plo:fSī#d9l9aj,&s2YIWFy԰3\SڀUọQ3ZkbW+x?sS\S$ë̶YQbFtMY<3wkh4{+UE0_6הKD 7ahcB:GoF(!Xwj>&(0"wȼWwFx!./P ~$Q刑7\dbe2r3=z')J 큞'{{ E[uȲ_ ;n(oP>SJA8WE$A^o,Za5y'$Gx! *Aܝrހ.Y˦Xg,x]xEm$2/ρHn5zH `ZAZd؁*|3 . !#NBOrU!M=_ZmhQiy) ` R-y &}$e)Ktv^{?J_9x_%,!S wzȲ<OsbwqAhK|tUq"6hYd΃dXk#d N4V;`vouɂ+/8אDkck~ -]E "ohOg~2kYݽ$9XM,Js{Q1̇,2Z,cN}ꪗE$T?pb 8U\{o;S>o0GKWW0 <̓v1(my*tC1 [ïDs w!s4:f[]0Ksdt^ # |'v n_g4C6RtgjscUN^#s?TedH7>q=$0 ZJYmK@Q5ւ{ UXFd\:h~ezp=\{0 S'0߬^P7Gv]aEa6.?!ѪP$="lU^TzgKQNƤ\S|Ű7JUS`IZv'o`ks.lN{V17#hoj5=hXAhnLL +ڡz@q|B*;?ƊoL- 2IUw1B?F=}y紴ór+๯%BPon,[KJE0u"p2uXX-$y_ZT^:PfЅ*o'%Z3Anw1jξs/= jHtٰ桫1nYCI>?Ŕ endstream endobj 393 0 obj <> stream xe 1{b_ q7?BPNH'^ī,|ɝ l$ !JqڃJ˝ʆSMx9SPs1;MVCFlt  sb|^^uRLv3~L6wyֿx0 endstream endobj 396 0 obj <> stream xڽ6WcH"@.@)ln&v` ۟/z&.&Td/OD/_RBѲME_..'L5| UN_Ura5PWGvndHPF 4F\Oj ;p*W[>ErT[u\r5Xv#xv)ZLkwB u owssFPS8- \5ԣSK|NXtPwaC7|'v(67~z~]EmD@ JD;gfo]\ # !-YtfL<cy- )Te}ɉY;HΒAm߫U+NrLhYC&?Z&!R2FуŪB! Ful%/WvB 4Ւ2'DVA+ؿ0ބ:)ߛ$hz)3dʾQK7)Gi)aӚulbZI[%D4[Xၾj0p'KE{ZꬖK@ >A4xUuz^OVK5jj<٣R> stream xڭZ+S$0H` N"DIh9mY('O괤uoOSIϓSl%Ǐ?ˢ L~}^+d^I$!z6VeuԩFҗ9Yu~iYou˪%\l3g,-n|V>'68$sx]tzO83k)8+\@  AY-Ô3eɈE/9ſ٤Yqq8Z Gٝ%5end٩ʷ:sF}煇=|' C8\I'(TIR n pH^[co} 3t:ԹdWm|/XNb58 :64k0ʫ~jJy4~ YME%Z}B"zi.PG8ю odG&ZŌ\w"M@Fbm/#sqvC7_$=I jWTg͕p# h#WEphG.<.%7^R!$P&.vb$9Qgr&#ޫ&tI )e*V)fIJ.V[\;$Rمb V%ԉd}Kr\[21,#V=YPђ1s  ӴjzJD4/2!5ڏc4 9紱c͸[;rX߮SZ-hcu杨vL `nރ&0yhwj`Wgo$.`B @b5$+v?UrM4A$%>/I'NFׂRWzu{}lw闻b4#$ot;xn4ixIU BӂAFOb<h#o^IPk\>x>\ F,AhkNNC; , y'(΍@rt:Q ).ng7 3IHF+qojQ*7%J=*]C#s6'0e$PKAX݉-)P7[O;"`׊Q>4Aj#q1[Е@t \u=pDPkkqFhi\[c*^ 'PBn VgLS e偅sg^¹]QFJ~8h wCg/<*3l~p nn ]beԎ_Q\^^d5 +i<@nC)߁/|E߰~ݘ(VP/CгڴJpBWL2`H޺'\E"|5s]nch& [dgnaom*VVdNU75<'j9'CbH_0Iјyܦ,g8R>=2 p%s%ʊą'1r4m!FsU: .r _׳Iĩ =㢬BP9 hkv] h *ձ<ۼ*> ;T̸nhǑ d)Zv*iyWn-;QGWmƇ9pLDVH  ^BQvav&d-qw6p?j4rpݬJkѓ+`qYɀtGIܞ*獕넶,IvA޶˾äNrhG*!| D'rA\dKqvxtKGX.VzsNS()ٍvZRw%WGz[ᢌ:}(lzC &zL6t}79v;Nw+!R>}nk!<0 endstream endobj 402 0 obj <> stream xڍVɎ0 +h6`CN Vxz_Jqd;`Hwÿ?|^TfT:& N'o眧Wc,<X`:E?GNNu %n8rj,$_#0( Cw()͋eXR}]e /EXԌ f+ *T s a:4$pkfe[Uq-4BRSRIkw7`0ݦdA•yiR'N:kofQVX(apxO@*FI1?6~GE{yHy_b Vfm"UJ?]ZV^ TԨN3*Q KG,Ɔ2*ﰒ. E1BY$BN-x%Gw5 &l\4']}M (fgĺˎ}܇$ֶ^\OŔaGCUC>nFa,av*ЉPnKЄMe*E'!:s3j{2+TF^b-jSzoC~c郜3|Qgv$)LaMs HN>:=N玎Z't5Fn {@iմsni*븳PHGN Y>mmkd@j~4uSoTzGBkFwU2"Wǣ47Е0{w#:ikw x~>?![ endstream endobj 405 0 obj <> stream xeN 1 IӴY W4$ef bfL;uVh )AԮ%4wjYS`?F^☁3¤j'u5;MÇ@.O endstream endobj 408 0 obj <> stream xڵX6 ~_2x([[lENK))vO#DRG2ߓ)W Ϗ2dtvv])r/xR{Oެ@=輑d*k/ɵc5qP<Jh!JpϣO5#|̢XHe nz).._s79՞Ӄn>F(!ћ$ˣ5qNpz:ú GI/ [/”Q Sӡ|Fx z2RƝG\0IFC*E~0t3ˆO`Zf1W7I0Lqf;6ͥuQIlP-iFꝺlEo%ҜB]ˊ㨇^*S>RQgGJ0 zo_BNg^j7wr+5Vx8LMM ]j9B$T7A8`j[jۗPݮ] _%Ksbn]RNH#Ba'{uN8q5@˙IE7$Zש@!U#ՃDDҲC/&+Y}xG-b~oCk5!5Vr+[suN$lHWqMEOtWx@O64jݍF,kvG*I LM$#V+]6l]޴1W i&τbIV> stream xڭXɎ6 )qE z+[CCRJ"%vfnjE$E~\ &0jZŷL?SE}09Y)xdpJu 2n9Y#Vg<1,%WR$-w%fJw/H$s1$ɛ%ͅzY퀞QQ뻲)$.'k#YhE#]~W~uG`u%w+D5Sj'6Bdu#9V ]"ϐ)} N`RO"U&ҹfчx38./+Z$gYIIH}R6GQ@7>KF=>rVKltuYP3|IYBȏHo"JAmw)kW)c Hgd67+WK*Vp% ]h 5{+gK,\J kk2{ZdrC"ͬPgg# CؽR*V8-u곶oDmo%k>r1n.,TR)A784EJw)Kvp:v6̾.dVt49g!['l $74tɨp!^ާpr$r۪Wk"r4zan^E Mh[y§ZzJsBz *|+_ N@УB[?w)cR.iU!.UJxy W%WQCoDiۓ=CHyX,?\-}mde1j|XC@E+uZDY*o"f*LNH\[Vb$G=+vb}XB#OH;AN1jp`3pxll|ly/4?L cœNY߼A  7 9w4JXW"Hn\i·~}wiQNcΣ92>1|ǵb+: ^MSL2migMgCq F6ǁܵ_.Oh̠6;߫Cڋvi7kx#GƝ%!YsbM=OM7s[+HnlzqYEy3Q|?Dr@ǖիKsiS7)3"LoKPl> stream xڥZ3~Otn9@)lT)M$(&H P"GΞ:S0u?h. 4_Ѩ$ɟLaUP?枿sKfL9 ĢO9J8l-t:{yhaJ9_/ EDHu2\pL٨(j~5VL]G@$-8n*3m5+,֧~()4߰ރyBu@p'7eR6r/Zt1:5l-io NbJ,Qi&H؂g[1~~4y=Փjc+^(Fd!B]gE)UQ֓QT? 6#JRE AA5k̔\*y1z ^].mb܈!9cYpa .+18LbY9fRCyW6iF hsά ڪ"@mtsf\;g:{p8 =Z덋P4&;-}ePݤZX>j-} '´y'3qxE_NJxLHz,`4a \MՂm-fJ8A`'%F1ВV#@#泋VҴ ^g|KLT]{ >Bk vk{8|IY]Ћ&䤎 ae`Թ\RKN$\"O/{s%~}Əsi.-qmY,l( Fͅ&uqK#vtX㹌h) /,.Bx*#DY(7˃7 QqL/Mؙ(ҾJF?:Kt}N#<7<3L>@vpV淏fo J&j=3{zk 쨑!ry`Y_z'86| /7ߢmdR1m b}C |_qA>Y-971pcx5$7pe^>]ٽb:z̡Y'\NBvEԳ׷!zƉNxW ]!c7z10( \$,(qz endstream endobj 417 0 obj <> stream xY+7  lgwS7(eo. lkH#wkғ*MSgsyަS+DoSs iX=4vUJo/׳ӱHk&Qd {*v^WqE%uEʓ*RrY5< E\ʧ.wX)M&ޭ4P`̏o/b1-zi:G\R> *tEk;SMWՇDcQ%Zqe$ʚW)#ʏZ]j4toOthIVQVߺm@*S:\riRYɋ%ʄNda8gk U$J)_rӄծy}VI1/ܑnV"ZW}j)rCxx P\ ]B_LVj>PYRl"; J!dpӪVy yzq 4'9(gJJ:e2d9r0! yQZ.9(>\Qt$+fed{QŠ@|lkEM:n2)3Y18#% b |ZRlUUK9Ne cW(LEIwX`Dݽ iI ['ߍQa: (鸖^4̀&ݮ.0T'e;NC|fj i6`!ZJ|gx/.|Lsb?q*mm-·'Is!A Qoڹ6srҡi:hΥ8ֹۘuU{Oy[ak+1VߓQ//|Oe$N0~pEv#YC-dx/QWKCsbtʁ!_GYP^VIkr]iVP/KfV(ٽv{/nW7M#ZRh%:^&]zbK])f>:E.7•0Kpq&hуq>4CD '\ăi){/i塂s6HnO܊K ~=Hk0_pH&*9ߜ;$$XKA H¬qf?3N=G_a_6bOSezvt趓QuȽ+82Zb:dAչQ'p|wVNV0̫<ږ ws8nw~o"/ endstream endobj 420 0 obj <> stream xڝY~uHHp lT)7w8?䐢E>+3g8'{2=/o_N=,zl<%{NpY%g,.XJv?@Uj`96"$XZND8Ooq9%w|<'7 `pGr}['w<˗Cy.ta_z6q>QGE#mCB>ocxO[{zݵϞ},rEs斳O+x +!pTbؑ!j lc{SKncPT`ߜ*Ps-O&FF<z*G,ׄ֟b}9*cJZLzJY;o@JO}ŽG}wr9 AO ԑ8$?i)VhCXM7q!mDeV!8=8<6<`jxe(:`!JqI. E1Zs0]x͆ngaMRr:uWNNeOUi" ;؏ *FI+)MSp`FɽL5hu^w@vAj%K*:>{E.'G.~F:!6ܟED$EjO[ho 4'HN_楲U{S"S:ei}ٍFѝD5c?GX>(ЍIf^Z5t:oN`S} z-K5ǮWwPu/(Rꇉ5tC<#F endstream endobj 423 0 obj <> stream xڭX6 y  .C)E4e+ˡ3Eӿ'{2gO9!_N?fOON9۩_clu[~DF;[#v \"=.gme]ř 5ҸeL+-ܯ̱R!B~GMY@tOD[SJ:/C}c@k4 U[ $q Y_hhiMhPU\ޕ s{,6Opp|ٔ M)U Ra4*ㄼ!\b`ȵJ.^Wd$Hy=W5ҪNF&22 U7Dpzf(PA%mo+$=m؎ kqŕxvU$lVyLE I4oF"2By x0#+ ]im:* +gjF {W1%gV} [6 _ɛ ݺJ~(ͽQoh-kTUmvoU< MQi-v.9L.o-*ą( n};+IPe8{ўsY1bT˯[mV ћ2.0wi* I`Zڬ䬕'FbJ4?ț.]v)zJOP5TP h[.z|y$]J ?5Қ:shWJ3\pۙGpͮ[ame.>c4o_d$uPݼrpNˑK])nd*]ZIT`,c $Բls!9Y-jP5~Jyoh?1H8ZW _ _zSËObU ck ' M*_k?9HYjQpΝ2 =޿X@u -9f]zi"I-oU@lvBIg06d"Ocf}gv*b#.&qA 4q7X1 oklE:jCԽ{6{dN#mu22{މRc2Yo_o ^'1٧*A=@=*9dtwmP 6lO)C endstream endobj 426 0 obj <> stream xڕT=O0 -v'Tu@$6n=L ;ur}]~~o&Z9|g}>LzϠq18lS2[B}ǡIyx; EhTJhɞǹ@dBwőe {~zgvnE8A04F!t.$bi\_YI9"rN+fӕ+(84Yzn{%$o%%l㟝/h}?2PU"JsMSG:i`US)+ =& R+ֱo)ؤW:u jUZ-SE^O_׻* endstream endobj 429 0 obj <> stream xe 1{b_b68R* BOoG2&|Л4S4ؚNGhs'V1 eԚ]rBسrAM B} yǖS) h%'8oX&lO7NB endstream endobj 432 0 obj <> stream xڝW6+rHBE$@)l:U<(R}^(̙&xw_z?_ާ /c4 `ѧ7|roйh-=g\/N@k`N8zZ@+pО%H]wnv-hf5ae%] K9,MiPQPKBq9@XH)Mrtior8Xx4L ܣ)FN;Ǘ*.>D .}*oui1p]y*5*$TzX/B%>xB.: 7.FyᔕRCm23ATs*?@M]ݗ!( ߩ+Nm2_"-Tf8 =*h)~kf/ikXIsrs[vqt7S+|ډ$$b2ԩ ߂ V^ta,=` YL#:ygl=M54.A<%ptт-!5-hk }@K.8pI0˄ky:FqB]f$9bP6MALsAfI9]3ϯفC׆pMk^*vɷZ˫SԦ@b? a3eԩOWI@aM`=/q[|33 } G-R1k' u!,Be*mZ\6ʹ.q>Q5 \s:xt]Wt3k"s3<`֕5tkz!+sd;M5:_;k-39ztӅKU>0B_| k_"WC{XaeklϪb-_N22 ^8hΖ8G Lϊf,uq ¾ }aDf-'З:nux;+w.>9p7KOMM87}z6sU!i{Cޔ6=Cg#48-MD'ꭄYx7qkT?BЫ;?C)%LCNmY endstream endobj 435 0 obj <> stream xڵW0+8AE$@lJo2CGio"xsrjtG7_Ռ?3ùyI7@q.4'[^v~ bր2qp]q!1<Njgy:<åqc>|N{t=k@;ע|EMB2yfyۅd 99:c8@a/A5B;.TmPr.)L Z7' FDz)ױ\sx,!^t6(xd ԘL7)p.]4Ll_EaJEŬ9r_N..xʥӞ(E!Eŏ6S̯&_5ka,eΡJ)@*d7?JfyqYn9TZJG t,-vc*5sHQ?b?ѧdr 51jgٗܦ>ky'a'1+E+ J(&q1E_ jOZ&k8ݣw2$~Vi0;]$ۈS"m|YhA_%i#;Az6N%,X(ϟΩv!ds:H|`Z+M7EZ]楌9 &}0y~TUk}5pӹn7˖<8-N( 1"J$@V}[Bv_#U.c+gw9 n}G⑽!kҸ?;)O ݀2N)y|ĉQD_3JɃe2%ӺK;ٛl j}-;^|/b]~W;uVK-m->"uc<Ë׆ ^Kݸ|꺔}56.пxVOWk¼~ o endstream endobj 438 0 obj <> stream xڽXˎ6 +q$A]EIDJ-;0c$$>Cӟ)W3^?ᦏX?c>>;+.KS4 WL+*e=~wM ݿ B j;?z뺣n~NF)@wph)MVXutX_x9p+IP5rpe5IR-i.yxs&op.RjajE^7}TW2'0? \㻦  hs%&؉dKU%vsI@{eKu1zۅaG=f߲LrLYJɰf)ZLO:%uT8֞KNfUΠҁ6PˀzbnuGrUJIH&WfXVg+ȁoh@lɞס3v`n Y@cڜr';ARw8 6df-JK~;"ٰtm9(P D)xZv*+p3SV9.8nϒ/AJz/SX z &(if!F(:bQMЮKl'K"(ս"sWii(`(BɭBXUyWMEdRC:232#RqHaeˇ&![OD|*_gmwGb_r] :APs=ucD\&3pcB`F6`lrDLRS`2DREVrpgY8Ԃ=ExQQNmQQH^Nt]}R<ґ~Y3l0pW /MFs~`<:R{[ѣ1qljǾ A݈epϡb5-qo+&|FI(VSَF*<@M82H,+ēE]<\SN8ƏðOSY4 QcW]-{}Y1V0N[ȴ[?$,L}P7EgkWMq2>Ų=p endstream endobj 8 0 obj <> stream xˎy^&+`NdaX ^ 1h e $oƓa {`[ȪtVl 6y yKnl9-ԭT^l[\}"w>r [#jآhub t"Ԋq-\!jbR;yHH!Ѹ&>\W3ޯn;+KO>\Oy/Yf#lV8A>e)+մe H-j\!x("(Qϧ,@*!`X܆sElv} V4#+MRyBuk@8mE5~o-*Be)I^ě^yC$-VxSSO dXEuh&;b2=s`~d 5œ.nZy4‚+t Jf2I@7wzep4A>J~[=ydL:J6PE8`N;Id$ Į%ɔ%TlDI2U J_H/$I $IHdF\@Q&z$ە;2I^Hw$@N$sj$ QwIEt9Fǝ\0]$g7]i (%T4md7atvio6>I[- =z =تx'/l3Z UZs>ri\{Ts0 ld(ep‹g'Ԯ꼘m9%]u1%>/Gջ#>ۍSMs:&R\q%n'56'JϜq6fxB"G8E5Jչ Wڈl:쌍2*NEV8b$C2Y\t=@I(I|)8G;:ۇaܬk.;út}6ɔIQ;ƙV٘x)WoShaW,o&r5Hj{Gqٗy^]I}#ut @ V8`<TKtv;E2qDxƤ^gMTHZZzgrnʋuҼѽ&wF}88mAy_[{8TVq&$t⒈I u=禮(pjeVӀ$wSɚ,s%oE$VB>+#!4CpwEpĂLsg:bOu9A͇+>P⣨]_4AWKycAV3y/>mzOxŇOMڿCDRC_%.[6}m=?XmV<6[_H(?H,"ߩd_x"X$Rϋ?]_Lu?? endstream endobj 441 0 obj <> stream xW0 $J2x(V [!qn:u/%%JE)CJi~5(@5}U34~'hZZt6:BBhoRJ,YKqA  9Ci t 0A̳̱}}"9g"j/č|waACΣ=.WR8*Sȑߵ8%9YthS˘LDɆ~(>2s}9Tlٽ7zO:Вwȭ'$0榀 u=o۫I<_g-#34eL8{iSPZcƑS=S6덆oNI endstream endobj 445 0 obj <> stream xڝn+7WTH .H!W7pwc isqߓ=gOsZo|vx**dӥt:{{Y_Wcl'8SO\bOsϽ~Ga%X@Ґ}˕4Gik>gC]|'#/hlCS{}+*h@|ιՏ @fmJ:#LLgsb2cAUT>+ vwG'o`괰 \֋A̸t9<2/N1_"@*=t@bfwThrOt "Xh3z?Z3pl3 ]YFwڸ2Bg- \0BKʇRh[ #/,47߫fi"ysފ+Iw,MPd!BY\9r7f`.*PRbћ2WP&SvlZy8jWw*.Pѡ{.@9-|&_(Jt]K1=vn6j@ W誇+bpTv5 Jx uJEٜ !nYL)*A`c@hTڏ Ld \"Eift3Ԙ1ɷ` q&\f_k-oet 4goMf%&2\b#ukN ;74u`f\6 ʽ^[ rjwFC 8:te_vת 3V_l}k9R13&V-V}wUHSD@ ΋#s K6oO~xa'%jVgrŔkFX<*O ^OViX49m pCl׏r1јU.vn?>yMJekX3\90܁/y[idޮqJ܌orQSwm3RZ]·4҉g߬,WzPw uM{. ,b*o`T2(Tq]䅤R;dv'sJڢМ:fl9?a d endstream endobj 448 0 obj <> stream xX6;[  l .HqkJo29Hn`W5Ñ&3Lyz wWv~L{h).əL?.l<_o! 1p ~_zZ{i Zz-ʃWbג- ;ty? yuѫU._iy>m$'|C QȮN:*+h!v/C|Šf~5t=CzjdE΋+k{T Ʋ_/2c1'I)E(kun+-1vP0$\]Hw$$*ZsBLh--/{l["+;Kmi9X@7 z?lKѪB4' o^їU)Gs*;CE݈gP=zZa0y.^%-'4.gK\+I?JWт~1P^ p:tV%Eu™zȒ@.LXoZgt9"k'vv>¼뗔tW6BN"(>*o!}VuER<iVxDjUQ\Ԝ[ i01YP߽ɴ#TkrCbvmlrmlנ9F ;m5 (zb@:1Bp(zx0ͅ-UkXFCۺ, &좧8;#S\?8#oR;ªJqMzh2[,CzyOC*hXugo6"6!vlnAT0,)Ro#9{< ,ވ<6|<;N#:1HHyv=iG20i Oi#=13{q*6}4ȣHYLt7QE;Xfn^"؋2}Rq)bBW{zk2>zǐex>Tߙ q+CmKCe<(װCyR}u'WgJXj& j(kePx$>xGm=V0_׌TLsѰt^bׄ('IBSb4g)G3s~r{R;} sL>bQqqEǠ,'C'w0p゜xXe|_x]=Eߔq,ь2t$wလiL| M_;-/[q endstream endobj 451 0 obj <> stream xڝX6z)<E$@Z{W)MH 9(v p㣧'=`ҿo~r~MnIe~^bn.JiGKuFlH+=[]gti=uGttq%H ^(,ѯ⭣Y$\R Jα:WZwL޹_c0i}T3Y~e&ANVQ<+O܅za6hb{?t(EYCպk]Ӭ!9Ӊp6O1Ȧ;5R;66~F,SMNJoKF&-:Sah5bC' U4.|" J>D|Qv9 \UmPf:ܰDXm7* }jWJ q2M}<fɳ2Ġ)R!^T靼H#1rQ#w,#.4{MU~iاz|.X6[p)V}׮2˧MUhJD~.9A}'QVeЎ^9@9ԓ:<]@S`N٤Ǚ>9$ g;(D*Vnzh#P м"UH]h2d*H+h):^Z/<׽$4%cq7:8q/Q> -RdJLUD8 Lso~#Dny::>]4@6S:љSbH%b:$9a<=RO];R#wC(M#8T@&.m\|ɤ/HKـQ~a\. 2~0IC3k}U.ޏ|Ypa/ԨAACǼsRW';GuҰL\CoZp>αkʎŝ ODAü4dWCsyC!sFKX.ZQ@xܻ +Ž*H1%H?tWXC[n=Kw.^d-fsxyo Vy#{İ"pQ x9"X _"({xj(2YեSq˨m=|cS+ŒbB> stream xe0 Ew?yHlHK`bn[!ȉ}71y 0=M/N}ib>(+YvT{8csDY2 "`i$qk : <<{ Q\n}Bo'ʚ,3.gZC%^69A endstream endobj 457 0 obj <> stream xڥWɎ6+  r з fSKZl{W{`S! _sv yx0Z8!0T Z8K%U}Z!͎ Qߤo]+e /_:GO&:mM mbrZ\^]\l{FzoKte?IWO$hM.R;؛T`)Bl!NFj1o"#Iͼ7 3Kw~$>Ra3Q2p0b\4.Nt, M&'VĥNTq .cLR{57{߼mN%ĺoֱSeFODOuIPɇF#}~ GJEf|W.Oy @aW kOP=higk%۲Ŝϓ2ʄK+'5P[ 8'[\i;{4k> stream x+7W"@ ]:U$Eidn= E񾴧N?} &Wk?~EŹ 8y} >V_bv_NE\> &5Q;C̄r.Q * {|B[r07QT5Su;PH Z+ i_YYNOEhx$st,ě.\].IJo"Q_By(*ʱH 8C[ɖׯ - #STA l{3Vg쵱Z ꄚS9]d#g2! Qn*l;gș*0 d`H7dёyD_}_06cGSmRt3A<^ OwhxG`g A~J:$YK8MPpw,u7grwNP pei<U`kc<輦 *vl2Ggcr$l su,%Y;+ M t&*Zx - jleD8J*.%HR~xҼ "iM"c}Ӫf8ȧLtW6|6SңpcgEG0˝:ZkcևBج$vL;j4U\F[x|k #H LZIAx0 V%-U,.Ch_(D(Bfk?D@M0ɐq6"c#.IK SJ[&seZ+aCښYR RJf:V|oU9 9S^B(wT=$"`*&N(4[H*M|jh[\ZVxױsTUxt7#,aXh`u EԈ\מ0vRn 蜠W̪D&<_ #(WI[)QRr*lvI"*Z]F2Rv9Tʕxc*:QW,7ݓKR_NoxbD/ԝ\E9RE|ϋpP^z&O=Ukh9OfEUl7YaQf;0Y۠x(ꨮ:w}B,ZFC6Qɡ5=+O'cNSDi7kͩ[,m?z?v"wԄ$KVN> stream xX͎6 )vGK>H `nA;z_JR,iEC]+J$?a W L!}yR.o/Xg{31OZG(PC~D4upg)GnpooX_D8@bFd3qAM (:HqW!@`>DyϾN36 YD. 0X'Q=|ef^x`{Q ! Z]r"ɻ/1ا~2JvwF^l;V@;ClؘxSO|43gk *{HMRt6󈣜d9U;Ũ9?sCܤ#_P8 _ZPvu$EǏRjyVI9tC8J: US M:DJ=qQ쭨yZo'I(?oGO&l9Њ9qzչCΝx]i9eCN:ST:gŇo&%c坫gB`B=u9wבtTq5؃dGѰRV Nܛ=vmDhl$ 7Zv {hZy^!:\`6$Fq>8-U`_ xN퓦RM7s02~(V9<>6K5dc6.X)/; qѡ~s\9TeVFr9(qvw _좓==C"O#-o/kv[OU-lx+nMs}"/JׁUs2HC>z28Qؒc7vXՎܲcG)yZ%lrB3JcJ+v:}F8B9zx3W#| +'55R/EҀ>(hZűB_uI߱`2椃jo`B_V9) 5sΫHi} [*X9wZYꬬyKﯿ, endstream endobj 466 0 obj <> stream xڝX͎4 })MTHܐ8L;8v6]n5mj;tg0Äfa~/1!14ܜSܧ^>_˟ߐ+g* xx!sxEO뗛Nʘ+.پ2Ϗ-n ΓV~^ /-^ߖ B^͔QVP95YLi}~CݯG'Օ$*eIeG37iIM{#wPF2z4)Ix6ᐟj7,­f"ja'+a>6Ut`Px=Kab6i,DX/YQ׷ɇG. YCw _lJ5{^2,>vzC[2I6;FCKzfq ,/{d(JX&2JJ^IX3Jpqw:DRs'՞$k+%r_Wܹ3V(vuQ%=<+5&s^̦m ] Af;|אr`tj+`3Njm~Jd\yTF×.e"f.u-[\} ܢkў+O .?-ʫex 5S`. 2.hUt<]hKypT RnmvuqA$K ˢUa/s*N"n :eeD;웚ӊ9Cnp=yu-RimѓugnIEV5yNmG{ An<"te³+H|ǟtp~8T/B=NV}4Q7¦ПR*AIFKu,DzWqog_=HqH8:zLÃn-:J ?LЯKѤAn e G>`3lF{}e^|zQܸF\l+T].`Lz]]MF <-a4ؚEQDS/fwD`@4%&g\vn%4uw5<7O0ڗN2K+un$xK9ƙ㧇H#K{qSyq? GB endstream endobj 469 0 obj <> stream xڽX6+| l[7΃Q׻EpypgftdOSvߜwx~_N?OzlfNgoRNo]g˹8;v 'u9haî+T$oV)೙ m4L%ͧsS遟 ^(Ui`fp pfZ w9[pnz2ڻ%ͽF8s5WA2&vPBw%.e'ÒC(if3 _D\l{4:wVJUm)=I*'̍^œXɑ͉ .$Y~}ckcb,GWt~Xr2azC>h3C`*wT Vx2[`kb욲%G%9}uw\֊[t1v; ޹j^^rC9<(خL.zsEםO֢}4~1-kx;o/\_!kQ1…KCև42LFϼX'V%I?NUh+iQ-AIVR"20Y餱o+@ S}y+n\/2}W%TADՅU] o t:7Q 4+eWFwXVQfXl40gi\r7IJx()răB*mҘ-GhI0`i`PuA;BLCh`n~w)ECTKZ;x#c^\c%ʃ:jkN$v /z <,Ͼ `uAaU/7fEV5yt):! T62}h'ޭtDS( T\80Xs VJݘ 8 $n{KkZnBj0*'|^HGc/i!7M 6-ԮhS}swxP n1W54}{pyB /{?V[^ J֫OMr+bPnP+C+ҕ g=,9ֺ#XTԲqF2I+u-^!F` uqW M}a`E,ՕH|;v/75;Uӱ5Z8,w!>I>Zp3m&TA?:W endstream endobj 472 0 obj <> stream xX6 q,d7.H1I"߄H޹tLq3Lg`ֿWo_0Dt{ ތp{c&t!]7ڀjEqFV.]~G,̊^hťٹW%9ɧXH#;ky-IkH`)sVIde.#4>tVG'ѭ(uq *C%j{8K3ءهb^fƥ\X76 hp* lM[łuR`˄1~eT)E ݸq|ԲA]eqkf6jɬ홨Cqvq?cE)MU<%鑪W~OŮF]8MI:R~͚"DqUC]^JgO۶]MmU|0IwzR UeCez:zA|8~t^:O$ endstream endobj 475 0 obj <> stream xڭY6+|S .HaS7!A)}EpgϢ%_-_Wcչ<&-\>?!?:?.?|]6J=O lzv?$$*zI ]3˛,oERр#.<&?EG~vB-ȁTa^[ d|RU/IY]z"*u'O4>1:fbgdJdg F줞y$A6ѭ}D܇k(Sl#w=S %u+|GN;2]iW6r>>l Nڢ 뮞)0eԃ fChų8}P;qKڈ[x\1Ɍ(LKZ*^|LVuB9yt8Qd&Rq%RA;@`YMڲ^ k \tǹw#|WO;D,jH 8^݌sbp0CtP$u6̚yzN{& [w9؂i-+ H *۱Y=zVtQg!kh}h)1pH%CgC"H(V4ЂMxp8 64U '`EQfn=C Kq/:ϪIkv*kAtYwJcnx1) y'*\v ; ,%nVsO.I.iڦVɶnn'Gw7DYMYYO :|ρؙQB=C#%I%7UUw8 u>ZQERglimN̷Rw&uhe[hQS}z$7;|J6`ZaB2|yMK'R"@&^fWg*i#ٶmrW) D:\?`.m;f2uqzMu(E7;x,>ԟ ]s!Cz?]^/{2Խj7I@"ΐ?hV^,еڈ{ Wiݚcş/,; endstream endobj 478 0 obj <> stream xڽWF}g$Jȁ?qu} iP$>^(K4ηzU/yu.%5^SZ.Jiߗ?w g҈878d-\v^YPiQĖL{,vЄ/уEoR1(UǼ]l /uSTW0F9UwzB'*VPhiV4\#) KkF^^HBÔghFьc|20AcG* F/"ӥe: 5S)j,Y5.SgW|04хnJo\SU{Xޡ(Z啵W` 'IiZ*@4)oSC_J1jNY䴇y@ʑ(pb38;cq:ZQN &X${7j+qVo+.-ygyg.Lz"Z:\J9:9`-&:o\pXP1yBkhlj'Հȝ孑~ '(Hn؆,ZĪ2? 65A#m*A ;S䝪* TTnPZ`Ot.W"SiTI=%)=R`Ĩm:-g"l__``Ns߲ .Џ.~leDT*֤7 O80i֋, YM۩lPMw@o$3`Iye@{BJ>,pW,)}hP>X:7tQ}%@_[kN%VLW@Erg>4(gP?V$mWCZZn\xCt%˒pcM1hjUX"[LΙ%1cpp~iaym]e#0~pE[y_U[?Cy|._򧺚iN𰺿~1pjr|5ӃgzЂѾæTKn2ģ9FGhS` _W`6ƺΈUxr]q1&\%%rP+؈69؄F-ZjTO-4>5$Q7}Oϕ48 )N_OM,=\8ޫ6[1A endstream endobj 481 0 obj <> stream xڭWK1 +9I$@N[Nlx^eYA~?ߕ]7~O)~}~_kw8:3xӮ" .f'p> R7` X> 1L/D<ՒCwKp?N; w>y|޽PQ@ Pt^@]@rE>{[pP0R3-Ҕv="&6}]GJ,] ,ReQ/z`śO盓v0w!pszv 1#R5 H"u O*t>ғʰME7,. |N[rL,ޥ"b!ѲDcr%/$Wu! Ӑ<- A%uCIb6iz#E8',[1#ׯr% *-ۺa<p"G>cwIj^ʑBi)G5F1{Xr[;"] (aT|\_LVdi}$)Y\-i1,|p} 802,mY]**E~rrn X uu=ɷLsGA; "2^#5k;bx7:@%Y|e6N4bx;٧=`$/VT4Jr*rORO'Ï̀Y4MM{ l`ą3LmcjmVփl̪%% y_`}stXo;ZgR*뷱~!ziXVEF>^^mRG7M-uLr>ZCΑ"{UiF7 lX\8i&E *<xD\,hC\mV"E3#`ՕߔUZd@H+C_^>TVǗ2Ōw}u믎wcD2'D/jcֶNUqsS뛄t&ҋi~MI endstream endobj 484 0 obj <> stream xڭV0 }8Fz@$nH![q_'iƇmbN4oJWy~:6@;xkt}A7 ` xZH<<~#1X#Z"֙19G8PD05<$:ӷ1=(¤hAT|\ZГB=ځg6.8TzD!}#Pk]3%{I&##B,U9s1;Ipĵ4ZT}UfAzSK:ÌOg,<ݳ XM~92,=7YOxݲhܶ|:FBx@p}Krքdoڡ'$,kQ#z M{Ll/}P $pPjGKųwzmuiqSHw.jA1dM%JSJԡXo}g}63j>NzjUY[̪JZOcLBD)KyAyf%/RLwڟ|L"jNm2Ƀzq.Zbn 0#ýG\vEcrܐa_L|%cgX2)fRÛ^)wra J_}T!ٟZC͞J gүBLpJG;e*E]Fݛ7n7[~k OlYFB#{l^(3V 87'fRzX( endstream endobj 487 0 obj <> stream xڽXˮ6 +v~L tW $7骋DR8(f\KuHR&=)h࿚ۯſ߮Ͽ)/΁5d%E) hx(J)fmZ*PiZsQ_G4FoRYb]``=w\Ϫc6vqZOvm@꤂鴤lh}L=הu h u!6cT&[WR[wQ݇*Ug@S4:bNmWEs;ꊅgcGNNaᲓK藬[s1Cyt bk.-7d1RcьՊVK )9G8j#&&:SvzXvc=S1IOpz\֭ZKvvh!t8RP}꿂 |F7Ƣ" V1*5+M7 ުbl[vv4zn\H數L \eb[Fݱ|ږN%MpZRy߰ !6R#~&E99M,V#?)_+K&ۿUe֠[3ng@-1cLL|$(5&]D0Xl(<,2}Vĸl:3|w=gP_I>r@jLrBM}(t`U xL%}Ra" i"{v'PwKtAVzR=7@;$'<$Ә: Jֺg̳Q'6Ot<soȽ.߰𖊕e`.TI=UqUvD0nR9n82VN&gC5 ^B7iy&| Z•Q>i6 MF :nj!4yUyT m u-亷f*y!ejMC?)z3)pL?SVwlԩUZHS4]-M^ogcn R 6Q ar1v %#Qc,Xڂ,gasp6nvw&󩗯\E2]Mo{S %LUwl3݊C}N\2(u%[o%,iSx/t.Oy]ȏI<캎|o!J` ]j~9r ~1CETcz&P"pkGbX#l.!흆ӿ0r endstream endobj 490 0 obj <> stream xڝX6 q~l*E$>Dɞ^cEyxE/K4Zy[~M/yuݗrzMiy몔v o ^L0ޯ> M4)-O,S뷋NodTbx9ܫf¯oI S^.z4%,v)~bg[@-튏"G8~cv⋥nTT%xqǿJ\){MyWIcW'c`]kO_wRۅƏ;5TTF򟣿kӪv6uKlmq4Pb%w tV͌<ૻ6E!66n]MgS4قvn tzO;"ԢjDkيfox:-(cXroӑERhieɯ$7"AGS u?YvmG1s]k֜ᏞTU}qn½Gn]s`,x5\e;"dQn?^-!6qLGYEF,oT~2Dɜc*n "G^j˒RAB vlR %zAl4Yk{D x2{ְ^Q0E|ۜvvzNO&Jt^g6uo (mY*jm]Z>Pj a4fX&âe=HKKe9̺\us G}N֛Ԝ.u&Y%q mIO ҝJ(:0*.9u>:^/ǜ;g-KiGCҔCǾ1ΓWsn8.zZ,>R5\;`kY >eG(<߫H=7NW[cۂq?f_?±]ܺ3S2֑#CH .ۮ_˜_󌫝??٭?_xy@ endstream endobj 493 0 obj <> stream xڥY͎6 )q_ˀC@oVxz_JQ$Er&]#c")Hʗ.2?s,/ۿ;ՙ!_8OInG{'W X@L6og dg:{#(k z6NHQOz$K`gtCt׏Y?,o8;9Ll/E"|r{|zMyw/:8889(oc;ĈCx:rYy3/|k, 8gɬLSR̖f.Q3͡gGm@&QS{>X(xnv &7+y"KR=(pZ,PU#vlaˑU3r1,Y(44YQ7.4SzCyɾ;7ßK{)#TpYYV}.7O/yk$ky ;F/Idc{6e+@pZW ENTԖQB)Մ}ٌ9:C4~c ^b; Ncc:!h}s*ud4nkz{v/#1ʵjG,j^hP҈ (.5͋e&Pq})\X2d2s K귬Uq؀FU4FuPx]ی>[iwR =_R2)/ʌ|k>[ Xct˗c!Y`̥Fs1'U?Jݸ{nA⒰kY{S\B[WEթ>e jk@ty'ޥKgI=Eaܖoc{ΈP:UjoL p*pK^-Ş嚠I4Y MC( M O0zhY"+*ڶcT~ 0 I7W4cun xpTѳT[mPKUIFt=Ll[|8nsCQ)W3MPriuUcer-:rh|;Fwv:˝e7jKfsIϳsBK}ǤNJ[7qōAAnؖKep*bt4RidjA6>]صs\BY]Mwy{L< o@l ?.8]`[& uʐ?Nl endstream endobj 496 0 obj <> stream xUˎ +hȇ6r[ìCnh;Mٕ U [2-Zgj?{@e=]1$59)ev2<@  CEԘ*>Q EzN<9CyJЈPq6w3ޞaP$<./ " hQp:8%d=!B+2dN{5'AXlqKߨѻ)u*tp `tДS5U~9VyvXmVnM;pҋs;>"sRA՝Z{򹖊EϛZ{hؕ7~V1fkg}Qg蓋>Jmc͝jƺ* Ͳ𜋱z,=30V[kI,:I&e+[C\h3"UJ.Fl [ڞs7 `%ѓK\[l[ .qY8gthn%Wۭ{d9qZ`8;+ ( endstream endobj 499 0 obj <> stream xX6 AJ` .3sשRAR;7U;,>EN&St_oӗ~iťml͂}1.cO̿̓;,O|-+A$ftMa`AHrkyW=4Mm[gh|Sr aNܿW6=NfA+v$8 Y ).sm'RV~Sܻ֕?e7kªa@̶+; (sKEY"ecjIsm!?Px_@EЮVQb.fUMf rx'^~vь~zFvp}@{3:}Eu٩"ݬYkb--:[b}y|HW޷JB}Ǻ7U{:|pjQ=ciX;k k%r6xRpP\^?x.V-\KeIEw[OM;z!{> stream xˮ4lWTuH2XN>δ !toiqO߂Im+=??[9>7.Ji.0KBc߁ht%$k0|XЙdRG40 d=}~c3L(ı3ߠ?~;}xy K\zyXAå `ЮER=9=JFrCxGɄbqCT U ڜWV5`g*j=;:ł6|Eeʖu}!qSWD&غ)C1vWBၼ,nGߨۇv2 33Z!A^Pz`сY[/"Sf Wet熀T4>7TERl"4 dK{ ݿ )2%-|v ԣ ׼4׮dlY82 bV0?%F *X_Ӗm0=Y t7Wf&X43TaU<0\ Lp*6FL7ljhA+Zsy] r))NSxb>-wʧC0DIM L&3H$,W%*ֻ;ɛ0{bHesB@DՋ4e+ƴ=H-L2.x - Ud:}jA\ vA\J;|.\-q:x$I)JG\%d6'ljtu;oZ׶ކ x"9^m[%U}>׮.m/.XU^]ɭGjD̋6Q?X6lǍ衋!\0cx̐aYpYoa\[8 7^i ^.Ν v[;<0g= h77l37BA-9銭Q&6u em nͺ7m_\UwyśN XS-ExUVdcL}vFZŻ}g`-o\ #_2'y u@[4Op$x=;ӪW-1:pe]O=^BK*zy/V'=r" ͂vf@2[jGJZLz "l`,c1 i( wsxF]ܫЎyk.fZP4ݴ3 mG9o4s_5rzoTX`XL(L2qqJ؎%fMğAр 6Id:oE endstream endobj 505 0 obj <> stream xZ6 yZ~C@g+:>':J([Nt) K$ER$>.2u?^ֿӯyu1~SI !\>2'~v߸!hsp&&[a#4ӷYQL"iC̹2U56˚]zqy4:+p)589RI rIZ2Rhu9|(/_SeLC.25. RNju3"-|Azq}Ɛmv0E;;٬c,fA74rW#GY͌&t}+,˦BJP9G+-X 9ΗM+ڽޣ,+~ []|?.|Uahue7/: -çmCl&R7iF)&̍)d&lTeTٿ}NU}F u7]/eFUJ41iŀEjL$wNu(Z2CϮr6H6v}W+*tpYQrKyA>os/ 6{.UGjH0ePd^ 7ra6O7Αk{yR%dq3˞E& whW,1 `hL*XDKx>h86cW&ÑC 0Mv`s_v\0V1X+5Ѿ-.bE@%,U=+X(Q`# `(N-Buk\12gR=I!KMC zCd DO(Y-PeUqltRd7Hz2Y7jgT/5үd|^N#z^MO+O/œ7pȆ K4)&]j<}3Sbe-n%2d22Ύ5ɷ3Fu3+Ul6 RTBIS;NcmrG68ɸGk{g丕)pR+ wW+{rsDPqVoJDQ*yG:((d㠕yOQ^0ld{wƫPފRgCvi| %`=g>B+>PRb>}K`Xn?'WtP*Н)Eqʏ#QoqM_ k4W[ϸj=BiV]Atq̼0G#AE0UT=;7Baܵev)'9RK^[uv4_hlk Js(/lҩ;z m87gNkoyak^t&E;^lzQe{o珽)aͣ!#6O=j^ӑDdp+p z$vnڶԫ8zv=v;9qw ÛH;×DMWҬz ۾t_@'QH){Ue[!ڻXmn{~mRY3 Ѿne0BۼbP8bg)ai+m){uAm;F;Mx ћJEKz M60 .qhtjf5YqpR6yignYAq^gYƲWvO v!7fܣqTtgqynљ pgFUQr(}@%a=o-E6= endstream endobj 508 0 obj <> stream xYˎ6 +, [+H|gHb,Ǐ P%uHQ<;A?9x0~Or1i]޴CuBqlC C,ViO":}|ҷi+3;>iT[Pkj*s8kiDgg"FK'yYEoF9:7G-`_xӄ$54j&֧$y<˗ #6Yn(0fj]+ѰЇiD-\@Gj0lMC9t -u T{9/WVj˧j '^O] %R+h5%-._􅳣g||g< -vn; zl?[t3cЦJ&32½:\X*LV˜ lpU+Ga0VlƜp'T"1 S1"ƵU3iq}{YĸtЪR*K#iV.K]9ND9Sъ3dkμCarhQ'֘T9唐$#~DX &|#?76Ra?s.kL@7l=ޭ31w &gE1U'/U$8] %̙SJWisi VUsJS7]BV8T- rBpaTK^&~;4nk͌pذX[3uZRz&o5+=}JwՊ G:3zy䄻2k~Et{@u; ղL WެYYyl[ ^]"u^bI3ZfKd_nčԣ>Ss½yxy]_?D~g*MN(z{y|PiTqWŖSgpc]6 UdW+˃.ԳBG n pv^l>P7;k}7x&N^;OX_9o4H=o~Is4f{8W/z~kҘ?Q!s®{v}s% 4oصC׿u Y ΠWڼNT)G Lx & :e3QΊ^36Q3aVUȮyǵ|D_u[cN endstream endobj 511 0 obj <> stream xڭY;6 +\&~r.I1{*EQ")ږ.x,II3;I?=ESOy|oӗzʳs5gtzNiz㮔v9~M``=Iq˿saNfޕ<U哖PLa s廒4U@haJ`ha}ooƵj+4qW%1μ5A}9yGOߴ̈́%4\8TT'^2̨uyPUUfV%d>%*0ɣy4uq ո%Iw3WB9[[p@5Zn7Y7ԫd3\ܜveԮf&ﴐAUl᷅neF?ya䱵 ;+6ي3[+tu88rq.&ыqZb)FћHVTV?񶥚 ʽ=htAԳ ,dj߆ _v(G P?yoEQ+3!966.Zk,ca-|>5K;ǞC-AA8B߯C:zS[5VN[5Hn} lu~6P_ɂسdճ9I5S<푐2纠]67}8Jc(%B+.. ,eDX/ ƜoX(s4Q.U"릭Uzaq7ޡ]A][}GjDM^F#6&F[`0+)BCFr%Cm̰!*i@VN5]RļjLYۆi}{Z>&VS{un6y4k3ET`^w)@'l,*ӷ1x;.I?m0D1g339.ŋܛ-Tu)Ź#yI'%- |_V0\#Q'/rG^H!hx 1\q+'Ⱦ!4q%GGm/O򽷾̪G1STkSF9ż$NB/: Ŗ H^'s'bji#WQ 5t_4> ו ϳpp`z(lD,ɟNV L' $6\課z=sbyO$]q 2֠hE#vTQ KggOԴ> stream xڕU0 ( VtHNK)Ĺ@q/ᘏC_㌥?gk???]/Δ9rMtsL׏ZH"myF8\fLhH($LO\'@WᐄέSva7ƀX}E,bE@Qqb95_S+CI9JOHk'\I*;V:K/ֳRob[ML.Q9AՙE\ %)[^'K*,T-HI.?iw`6ܫoG ?ꀟ;yWd ML(!uVw>I = #h E Lbq& RRU!鈸)(0%cޫ32=hq ߶T XX=BؤŨAPuz+{> 3SzhQ7S^P^GrxJ߱d|$0*+}>0\`Kwnͭ{n6~x:up9U(oGEC-Z?nu򾯒E7޶B1Z endstream endobj 517 0 obj <> stream xڽXɎF+{_-AX>h ڗWOp_ϯ˛t\2y8l0jg'p~뤔 J+\N)o=G4PhW>S2^y ݈9 7=~anʳzWZHRz]ry4U Y/Bs.o,ө qH1UpeƂIޚT3B2$:39.^Hs.$Y.aGv{'z+Q7(& Fb!,Rݐl~G˾4BDoR_&{ܑ ?G~R}QHP.A89o)3pmWHP1 on2uY2z¶6h_q \JŶѶN%(&6 t)U^SA o3v'LM O̱jB 2-"\U @FF,h4>pn^ӄqqԶ{L{L'Ի ؂sn ?/Ye &y4.L7 bXԇ󬑰tBt?]mKԱ {} j "Sƴ"ªUEbb ÁչP:zZк><gH0o+]!~[$xvKB Uy(6m*MCL lg8NVEve!Q4iw)+JIq$՚?4T ob[d-[n:ˣRϙ:$j@v{~ z22Jm5x$EX·8{fDoBK~{u5-AG;%V}`I`Zvħ, 2̓.tjº)&\l7vr E'n[eu$:9p[vz , ϓ!\1bCmGl!uiCW iS*].Pth!,Lw4A<3![̉o4{eJxma3ii3(bDTXÙ F> stream xڭXɎ6+fX :HHN-ȡ-sH0S$hFMȒ<֢?9-_?`$zMwa:i!LoRqv KaBiX9\\Ȥ5.dTv>i IŅOSP Vu#7Pn:9-Kk _ZŠ|8/uEKLrvg=cYzƢLxh{$D~#_mK3&%#;%1 PuV jr%  IJ7$)28D"Vw~ERtz6Q _9>c˛ggy+|CbQ?֝(2,WYM~D%tʳҩ 9PR2*ѝZkzz{t*]NDj -n:pjw}&gEdJ*MG30%f+}.J%,[FFik(p'QƐc(8丳~'6h0Uhzda+QW:H5eyڑEݽBA4ݰknKt̼́#k|{'!C;i:+&T}剭[ق_?яv®F&`&E B:e; _NNNZ[N:< SƢ[['JRωN l\Ǻw0{> qofAQۆqdHk x>vmETlV3V:p؍n!|V)-!0e l_- `LئʌS*\0{G#ҕ'evKdU(fAkW栚)!ljǺW+-ҲͰC$mthH^·A]8jC|k8vA擗z}]gtocUB>V0Qbd?C0}-ڱW}l1⿉%8v_On#8RK7#JK'vHf+Q9 U S%啩ŢWKw5$xzh0ߋM]X;j>3uBg2gU3X0…T&{H}Ǯ'GY4YRpLKu7}ӡhW gX-ޠkٌ_'cӿ->L .=6} :<:qFzσڋ܄",Iz=-",3|I!|aD8nxRBK 3w endstream endobj 526 0 obj <> stream xY6 ~q/H` 3*E޿ %4%˳w\^KIGOWxOoӏiIyaY=4=+=<  1Jo0fY_0?~aZQxe1 oR7L``=7 ȃr9m$!i=r9>*ݟn%U(os&, F٭貪*JJQ.5X`4\>r bM_5џł[-GH7/Wx]HWp N"4JEDGxPrڄ%hX_(Nh_8me#+cm ݨ莫2P~+gV QCofE &g{ԑdL~:6x֝puʵ j¤]@'OW!gJwȦ5w:]O>]yAL.0.J=v7:Iu e5(}3̏vkATՖõh4H?h?yZ)Gm]2.2=r\#3\i=ej^w`v_Jdt1][e8QN;q_qxuBI6[~^ҵKyx\q*|evnK5xѬwOnhc^y/~c @9r4ynÄ:@KjaXU!N/S9+!Ezg{;9X51MuQv]g烴Y endstream endobj 529 0 obj <> stream xڽɎ6ޯF z+03驇DJdfKwzgvHa~/v1D;8 oic> X| @!dFR+.s݄\}_Nvev nS99 }Vi( TFI(~iOL^Tۨ*%R EAnEy|b %8!jcmd%78n,cEei3/֠bfخWwZaFN@l? +u|Bq?1-yk[;25e;V+K}gFkd_  7YTNJ$,ym9Ꝓ>gU B>C8pulVUgUS!=;UTx}lg,V֏\n@[bY:Zu$ θݔS <}0"NR5د(rY۲mW4xՠ|IS`gT%cmW4w%TݽK]z܉WESSf-o)R)Jq9w>^'ïQ+Vn,[U+%ow?ʍ@YD3ۃ'( endstream endobj 532 0 obj <> stream xYˎ+5i~HQHivEbo(r; H{[3ˮwgkыz'~WfkJog/ 唌27d.3 >3bayV~DB Z wº1Jak&N ?(eMG3a^=x=<%\W3޾6nBs:V6'Z9=b(l:p"^cY2ZŋKqVWTeiTC5WMtEґC'qjAZKmC#(J!#d~ *nT9gTcY`>xq%s>2yz@)A @E! #d=2@ƑGKFl3C7%׊6J0ŭI0?^8E7.*UE7T82]҅+G\G dj\lIS ԒL_UhX:7z/år3wl3uh9 i9Šù(g[h^\J Y?HQ%R&/VWg*֞\uQ թm>$r0G&Uc%gl*N%SqShT8oxFi3_1dIbJi6QM{|~7:1_tfH(9*fiah+GRG;_."A.W^-K>c2B6ή)ϠAMڡ.;@ol(W΢V!*V:P߂)TЕVv&ñ=n,ޕE'K )|$];gq=)(Ԃ]kmWoޅ+eUN[˩𒘰T]Ewh\]?O7&GޡY[g'Cy^!\ %ɾ`hWu`O (5 ׎G=׫M?Meijd8/wdkuvГM4M@hMxLG+/Zb hxzeS\gk=< l['ړS^}yKwL endstream endobj 535 0 obj <> stream xX0 ~$ d+:8ιSRJ"eɱ{q[E~GRR?l){_Ot1(t+[g}sв9< ! 6Z '@1A9тW- + 'i '*OdP+_PLhr(qDM4F+8Pouk5Dhaga G "'9z˽ +5Zp4сtBAZ 24-Ԁ"D^)"pMlX* !dn|;ҡ&iq?#%eIژU[F@/T'l{ Pƻb77 ņjNY{6n[ k&*>$IV:pCKOqӀ1WEjnײ3 endstream endobj 538 0 obj <> stream xڵXK0+;+z@$nH!Ir0gq.+~|wЃza?_`xCy~|~8X=Npz|&|4>>(ܱA)3t\Q\<̻ϔ M$G>!?h (*7ގFg]5Op< /:ZHM 4QeSJv:1gQԶYH|j-N[LN[ 9cI 9Wa%OFZԹ$k/G 1]$Yd;tOv! amגe{%-%茾Ķ(a{7=2MM)I"$yfEƖ$uCnN<Ş& E+D;͍?S LWJ+BE^Hp ˡߋ?jb꫸o2mfɮY EnU%CW;JM+**q B%7Al!KEģjqW3J_^.NJA"Bk#i75@wn1FCG=@g> ".Fy)5äӚX4sPH&ZieWu0wReGQ"C#m8=؍R#LI_D΍4~h-eE FS6T@T+4٣FmhNiMHIN&ũ/VշF·˻]) ׇ𖰕@ 7.(^nѕC;+Ԫ ٸЯJOTZkLS:^4+$ endstream endobj 541 0 obj <> stream xڵɎ6ޯվ[C⼼SK)(d3S9}' |_)OC:R:}(<< x`|2@ @@4 ~>[ 9h=Q`X ;A81kONj/v ֳčE|> }" )x@p5eA8`nwݪ5lldr$!$7o>=T\hQk4>W)|5zUW`#(BTPB'8kUл ܯxg|fjm=, ^^ћ$F[5'I^xm>@93МV墏@`UgTlku aN*y$<.2+AI8WaCٰ뗁^d Uhܸ* 6ǔCKIBIs(Sé)&Ž؆ ȧ)y_l":R eԣKBʪ|I92i2O$*&4ɅX 訥/%<>B8iù(BۮŦFމ"?/ZQoe2TK2*=ƥOp @\D1ȴYK4{Y0: \7Ȑn\O\@ѨRntT3.%ZQHȇq\Z>yu0l 6kM}1P fS= Q4l<|+'%0dcq%?U0éaUVbѵye*$񛙧_5A$Fwͨ8CTO&+ #v9M꾳fѷS4dATiףv]dN^79cJ9i+|jN&1o=(۳Ѕgao]5{K|If8+bz:m(QsI>5"^ &*şꖸqt VеwW]thVUyS ~x#bw=umj,6-ׇ~Hj&N#5)bSO޻6=`yJg/pI)XvWjikyAt,j @jM.խ2m͂;1nSà Iޞ,ߺG\;S#:7pa+zeζ.u/fsah9DnZBLzG-bQ PN.U^+L z7: uyUU̷y5?Q&!x6Vs NӪJޣdstM2I+A!?5ech1>`t)Y;;z|\^8 ꁺ&G,nl;rI\ҰηxӘuN+{jd7ܔX`_(7w~^sN*&]k> stream xڵn6lW Vt/IEʔ-;CĸDR|?t?)WoxOӏ)ÜmnV)M(=<  O,-; OZn벢1;p' ͝olGG!ϯcI:~M``=IqsaNfߕrpÿ+ml>ﶂ"\n&"ڽݗBJ­@P>Ԫ7d̕z{+Xb"_ 3S \.6H^wgh5ݴS{aLv4W5;R}GҞH/eDi'cx|cZfs蝁 w|\΢x<ϾE=F |C"tU9.z @zH^H&{j|v1r).H6Z F Ban,DI*^;-{]!InDW&E.J #(7*JXr*̪c,{75t!%p5jcI-.߯Toj:i?fȡOB &*VRw7 U\t+JtgKr9{3)5s]! 4DzzP=գT3s tE=>{N腊P>'DEoOJwE'Yjur\mF͇8|mǮ3:΅ Њ~Kup٨}qRTޕfSZ aѳ[0`ҷ*e?%ّ'o6>ХT\хm 5Ɩ3xiywciI뮧'ߌ ޒ뜱>jF%<'(/=OQJQ&MZ9ZWW d0gyr"_܊mL^OܫpakU%uCe%62Zmh;")!;qН (jYLJ<zs/jh}l8+m}z+FUkj&]?p6£8/ 8ĭ~ӕaЊ 9Ƚ Oٺ)&qU}I~W9[cBW- ŤV$Q83>5Yn#ԞM*ǘ9<ݜ5UxBQ(pbψPT 'jo *Q`?0|4(W\rު4Էqӻx.&oYݩlJMO@X1=X@34?N8ްuk>p>w#@>Y'ܺuǫ1Ih<|IGgA}q endstream endobj 547 0 obj <> stream xڽX6 ;.$]b칳U"%j[H$7<;?Nհ~o/Ͽ0O&a >)M) Y?H N0&uVOϚdLz[F sI+J+LI;I<1i0z3yH^w|3L޽C)tIw=M'vՐLy',6t[!"w2I;+ rDcȺk $]>e'TNDyTZKgu'8s`0M/h&%[K=;\B_ ʳzSM#es\.yLwI JO6ړKV&}95tAX݅g9YtO]"kYŷtQfEкGrl9rX%Oȏ00$-p* v @u+ aza`dW[:nhHOfw(q~CJtcBzQO jh]J="k (Y ٘/kra4噢׶Sިy҅m7Z"9DvgUI2-OeYn4`;^W΁X&K|ɾWhG2@_hXGiKvο|9RBa geGa] WpX*u(݋lmNڮ0EkI\4L\ Ta n`lquІ 0ꗇIiZp|j_S<[-cz˛VAED񅮆|.4 gq6Vզ\[$lSMR`h}YOwxltƽۻ(".'Fm5s1\oArބ^O%Mk۱D,M\<_0̐tWH zd1*9yݩFcg|=A&x;, E{]03vm+em祾:iCE_:hq,%Q~񚭪AϿT+3NU ֠*[UEg>gq[#=œҮ}f0+-SF]cn\g }p">R#」w$oą384;V"am5 '>!sfgS}W@\:v2+@͈H֙׶^+qD;3_NQ\xg-0X"CQ:H|3rfcuDEņͼ:Fɏlw<q#*eoqvM*_jj }ڢ7i?VyqfjCj\ mDNbNg-$㌋SI);} endstream endobj 550 0 obj <> stream xڝWˎ: ߯Ջ ^h tW ĉ))Q2e;3#$#vS`Ou}~~>wB7!yF!|yRJK 9(Xܙ+84(\ObQ,jq!ED3|~Z ZP4oobʱ)8TG˨͍HG>Dϐy3FpdTJR@\] rBrM>Duv@_\@J0A 3' "I.-Ury[En"~Z*5LhJe |;Nj@쬒-cƽoExH:^k{ `sfjEU3}? DL5=/l;s\Tr1*/?WbSNoe:vC~zJSp՚v>uy58m mQo30ErZ!7$ϒ6:l0fCZBΐ(ͩpNjIjEtƒo97v5TVB1OMFAe# A:Ru)B$ x]K2ܨvZ4ZOWF!pSnZi7Q/S \㽒@M}ٜKb4Y""y1ZrRԍHH9.=|7`1dIS{vyR};MCtevEn'pd%6 "ކ\zt- |}oa6ϧu?Za9v!ףܡHÆgM~}B{^k'c_ʄ|lc38\x/!];ۃ & endstream endobj 553 0 obj <> stream xڽW0 z~mP-Э@C7u/$Jlٗ\HȏHJa0o}CyɟW`c*gff`~PyutAXA, ʄD7K}oN98u8j\ C]+b=&8rZtoJFFj pF{ (ǧ..h?-gN^Ap։F3FqK2HE p +ցBB Y V&r'~mh.ڰׁL q 8mJ\w)Ne n<Nn+-pn GxS@ֲZgwȝł $t(Ks]vYI W(ya#)I\CK(3ijvMc ɦb,^qpN)q:G4.=ZkUrS QtDgqYU¥pt|y 1DrQv%>@WTΏZS9ZRYZ;sMF-' }*R yLJk(^Xm ö^{7uSkvHr$i$?Ir$IZtQ4hġ!dB!bPڡzB2enh=N\z5 uPms^SLzE*o_7 endstream endobj 556 0 obj <> stream xڥXˎ6 +qd(po dWt8]uߔHi#DQQS7ۯ_pP|1y?.όg*ig";>rɗO&d6ٌDV^?/^C10 oނ N)e)14rsLp#Ki9W M[|Y7!T4L]ោ'hDmc:'8ѳ`@y A$(?"΂Њ:g^=܀ǡT,.kRyBVP2OjJ硠z{O1'(*6|^ET{Jz&H=VbYJ-ʕZ©3B[s20EoVo"^9B#= oXg &>Tu9p{!FzӐ*}nڛpʌk)kf;ofIKz6dH^Rp1dNn|ٵӁ9=DzCB6$!b-; 1MV I^xI,&Zlx9d7)*g)R}TG`䌆pT뀋+CPEa[%Up5`A /7`M*q\Ǘ8[UMAUVoz/Tj~OCkRE tS+ՇJ؞P(SZ8bR#|UfKw+ӕ\kt% [1UBd.ި%ElMcۣ<&N=GBJ @_:6 ~xӲlIu]k~7t<$T}3IHKk}ՇGފcr5۾|.s^L/jO` "K6cFs,G2*_kjԒQIə*YN7x})m2K%n6MZtھ }iKSר΁*9 *S b\^&PJM"@:AŹkJwMNaW :G09XRʝ3ջՒB ɺUwm6SiHVJj;S3a7 'EݽLהͶo؂$`sozHhozvNMVətN:OU'RQ ~"oͷ C϶8~&w mZ]#A:0 endstream endobj 559 0 obj <> stream xڵWɎ0 +vPAȭ!=Hv$2)h61%M٣WQuohGRd'nI(+NSkS}^(xz|.JjC թ4Q6'nL>ȟ':Hձc}Ѷ^#Bn=$AzBaxF͖aЍ׏eߕyt=5O-02.ϣ=Øhv3{[~Ny> stream xڥV͎0 )xhbjJU[0˞z_j'$L`YFIm\tGW௪=z>oE\ۮ[x_]o(ǥq9{QxΌnAӉeoZ1s5tB-I' hbV t,GPՁi7kѷR!X"0tv\ )Kn!ZW 2y"{vNJ])=e{f 48Tvhrz-.~ߘѩ3;FI"XM#=v,D RNc`҂$׊!yR]1\"tF7y;eD!KSreqRdA;1!Bʒf>W"Z nV|9yبY΋3Z;LJj/ȳI,Z-} N@N%-'dTqw:g+dm; =7 t6D.LY"Gx^ oD|,sMcDL?<sVBMJ5״=k`.F{E=u8< s^{JCJ?}' endstream endobj 565 0 obj <> stream xڵWK0 Wq UsXi[Jsz`Sډ0j/gi4IzKחk+4C5 ]Blߴ o/Br_` DgzւF\.̥UȜaspi{)pń( ȅuwz]uٓtD K0N;=BLmh_,-b2SZZtѴ1xzYQVN9n4ƽ~ 56^%%oKLAB` Vy@{  J`#ÉP_܍M7-ZgZ'K^'Gl @ p?L[ ^HgOt$7yK1=W UL!a~=TO+\ӽ|k[43#ǏA>O?u_P2D@G,M@}@2ȑ7͉IeT1* bi}6 6t n>a͞h!97h#mmX0qiy4%@TWFS!v8)=}˅劔"ùYB4 v^Nn6=JU&O1X-Tb$żO{Iq{)2 n͐S(Lۖߚh5y^Kcs7N,Su9y\r6r4kfnx|b`u~$)-YH\e9ZS)~OJB endstream endobj 568 0 obj <> stream xX6 ~D]  VtO}HJ/Izp%# 3CۯUt~D`80S.?i2'S8|7|+>Wp]w>H␣ta1zQFX"kh68op^=+ʍx;Zw'zzOЊ(NV$ַ[_^sͧ=7ȷ[>rbi8@CQ=Gu }/MpJye:V *6 EHꖫ"&_DGkN֍`KlhR*bJ9L);Vr~jbyK\&Q rƳEe̳&ViJ_"K`~W[Ou' POo*N 0\bbn! bBK.G]~Cc|K sr@d+Fq\ϳh`D-v"l#d"%Zq7 db+Ild@WlElљ*Ұ}iu#c.?k:d-=OQ(VJP "]ZbfRNjUPr: f*U֨ߪw/$e5=9dI]%~P;˿owPKÚ(U"h7}'aB8֡aOJ1B# *0׷[U8HgO) >OڬҾmPANQWU0rB8%818J0o1Dw|ifzkl`Yv#pư{_϶̪eBk?$d@sh'0dطɪBQh\K7},gjTV+UٿxB+*p1 今4 ', TԚmRWX^Wau؏0({1*p_3nP~(:1ݸV3iL *j_NLpRgʉIqVJ-d\=|n9mG*'(y&SN7jzzpT~M ҋOӷ3$aWհMޏh4S 1bO#6Sw_fk{l4jj]Uh- *Iv][W"5^شj>,ľ5%t#A+~+_A.]ŜKU*,z}?;ԲV)QSbX(]_ $}R]j~;41$FMlpbdm 9H@{ZVRٲIgӋf;7e~sDZ]0E:Βg^`jZP*vrS* BܾOn?.RI#fuCuGQ endstream endobj 571 0 obj <> stream xYnF +V/ +]хwESC8jo+؞!9s{00~[/PzHvʩN^x1x x2OG0Ad΋hYB[,()lb8BjGY~>%gwxm-nwF\t! b'e<BqNi~5Σ\Ei:#FNGbެF.(7~nfm"Ϸ"=ԝ`mbYsW.BA˯ͨv:vzt1+IViAk3w 'y26{[Wjd]E4E#^n dLDA~9o ɶe6q]-YչJ W6 Stmr"RػV >HABZDʺiF;} ㅿru-yunH)uw{< w%e Q^ IzV5y? x]'N Zo)6;!jjQilZl [ys%O>~ zŽ?ণQ9wNf(Nxm{S lOu37*jJP̑nvM4,m5q&C3惀_hq2 G\B[dSwI>#O{1Xgq/3%mK~\y".O-JuڧgĚ ’,lhoƇ.j˕!F1Q@^!~q^nAπ '*y_]6^jF5*b0 ] wļCpvEʃi4sZ`-Obn*5>xe1hWN,;a cIyrpHv?syY57}5MYk.n`|8mjYՖP5bo3,Βp?J9-j+C<#[xC0T }[hn,|_]1r뫁;:>|4ʋ™?b]k>32R*=<1/YoZax=Ha  xKрue_~w3gaThe5}du~ǿl4 x?n/ endstream endobj 574 0 obj <> stream xXˮ6 +Q~L tW I)%Q/[E!2IPᯁ pOOxm'58"%^ =\#oWJaa0)'v agԷ_ V/ |D$poHh'D vY&/؃R+MBH z˜@oˌ<Ȩe 2j34ZEzk"szb4;8?J4委%. OG e8^O.׃ ~)Hw9lOcy쥊.Kq0ldig䴒4+~.ћfi5Y3{1'Pl29T gN/ H H*Y l{+d׈ U97C'`)ؑ,Qp&NI'oKvIO`QgvKPp1 i(QJHe1l`ykнyV1هw@9uisVq leлPOAFdt#j.5a/?B3@hZM{;$|wO4Ob@b5E`BQ*<D g|ǵx\ q #%B#xhXUHPwhCKMwMoK3J]`;źަ43N'YkG_0EoBE/2.lJQsɶ kt;ZJ@Q mUpUDHjS^cP2Z͔v[v ݂ ЖpNP(vφOѰnP.f'bC-C}.rNzϥ}O[[^+4L8{#ym DV1u ߊU/nowcԗ; /d;%L@,лE7^AmSukݐV|(VԐ37FoV mJ﹊XLh't{I(G8~C.fG 6R gmxޘzuήJzn pK\Mizg,v=|H jC9b5x+Yν}HU^NrW,|ԚW=]\]u>/׍\^STO'p>el endstream endobj 577 0 obj <> stream xWˮ0HUH;Ģu[V, 3pBZM̙3;ݯNvd.0~'ٍ1 t~tNޅr;߾FqlP^ 6(Жq6k;JTgÌ @VÊz ~l~lej9S7Be~ȇUjJE\Ϫ2gDŽ,<#oܫy/6PJ8j";}iN|dO=gA{8$ mCHyZFr;ҮKk=e|ȱ)bnY>报.rs͢2p0‹֓2t%9LL> stream xڭX6z+ lvy&\!%=`W%ͅZYʟ^)j_W_չB\tX7kJRڗ+K}$ʊU2JXe<˕r麺[ /ZG3q¯as%5XO|R&3sY)_Ei_qEWtr 5Ctu\.d}7sS'P*sr+b+%:VS_Z^K||kþk |گyy\48bSUqJ~`QW|7 8vIF&RxRD>mNWriQ Ӑե:n&wG{Էѩ ÛZ#Y~[rȡ;Q9 c5$  kxk@XJ! ]]^R=-ܸs <C±Ln* q\Eմc p"El)av/ր<\`Zp|NLhbH?h* [>GщNei)R0 76w0j%!`Gfo{#2Žyz{|<HrfY*.;;AHofT?J7`{b?VbIM2Z`wK!ޓb}L ւF7ߤ@-*^Z/fIXhG͠oE;s"aH_`ٜbCc>c; ӕ ڗoC(ai@!GuPO^UzpAtşlvƍ !^APe[-V~dIiQs(|0g6NOU2ܳ' rض X-UVREV(ROulsD.fPgVE=Ylg,_dsK(UL\_,Er8=^ݿ/f endstream endobj 583 0 obj <> stream xڝX6 Xp .vA v*E޿ɐsሦ?VΙo\]b]f_}Wlk@~_]s*۵7clg_zbp٬8.0yO⣭"<8_xt@a݉'5.-#R5ő/r6puyםHn`;G%õ^~R@‡o[*_8!&47[^#_'®jyg*HLFmA<}, ؉#+!lȞe/+[>rKBZPm*"=T%P 6H[ԂH(RdX.1F$ں5i#jj£u,OJ KDyǜ 1-}8|h$OiYSp"ʃ))(PQwǿ4cgm읷Vp]qΐN:z324KwO*<@JоjN E h78hhiPsڋ2Feo񍋿w0##(uh/"CYiœ gҝٍFo2W4Knl*3r]yns=K<_S$_8u59(E;s{K;u$c-,l,)2:0>1_j%+ig@1N (I ]K4< x5-i"4GtoO5k/D2 y@PT[]9j&7yI 濷Z4xr9,rmlbz@ؔS(pM۽@l3PZ&2Zpc 0$mF-#@ӣG}dra[X5a޻w4o& es @p0}bc{| HFmMdĽ3VkbUk -#.CՎdTC,Tc>1*1_{9tDCuH3~@x xrRQ}=ZhmmRn(1:|(;z ظ]ZݖDMz-8N/E&$:>ZH'ʆ;QF͔<m3!MZ *28ͽ*iF5iMʾ-BD%pcziWbXqy {5&ONm2ҌFt$9_:^Ј=޼Pcdd-Of"u=JLf\݉G Y8t!r[Gγ'9f'x j6JOxup:T u;酃l\ypF4` TP}'%LWGp^ zؕ*{?I'ӧC3L%{")ʞǹ\8ً j+\\r"]BWG`n %Kù:J 3 X0\ڤpPfImDvgez:xDϾC!ro˳X* endstream endobj 586 0 obj <> stream xWˎ0 +qȭa=H=l9](v8LGC r'_ oǯ:|y47]Apr~\8s:y%pE;! Nd8w«*Ⲇ0-i;~CFGPȽ!&n|DDДhAEw'HвNʏȲv.P7d\ gݘv%Aaf޲++4GoKv33ȇ^_Ȕ[-4 ( ɀ^hggW1<ƱGO̲4HqDu1GѾZ9bwC gD;^ӛs*0 dj {/qvFj5dL ܊P)5Ls70  uJ2.hU;df#XE hZ%\-HɰL"Y`IMlL]ӪAw,6/ڣT8D[|\dlE@Ź=ca9u"E=CQLڨgJX_&y׹˷LTQ @zC>5Ch8qQ 7-R5x1v&*˱:І=!$h\2: KF5,Wz4R>ML2@pQ?6D&/v#EwyU]=]|3u|q^#̧hs9, ՒYM {O1ְtjuG>&QDC#@HnﭩIjJӜuFDh~uX Jm]Q=!*KSRN'G/L[>~zK?\7_erz+n^w.ק"\)c4NO#{9ΥۙNؿ % endstream endobj 589 0 obj <> stream xڥX#7 EI.HvA :UJ")j7w4!N)9o+>﷏_! cvN1O'o眧?؀ς\ 7!;ֈ]ngɃ-\r i=~q?Fyr|٦e:E?G,)儢[@IB'_B+@Q H7Vv,Rn/E 3l@ERĉkND_7>H WtW`RRʢpdG{^ qή4ܝ,'s]*k8rDy Nh,䖯ўh ٖfgۃY4hUaCV4P7i}<<&c+g"Ok EUWSI./T L|fjU.,d[Z+(q@m$XP63ƶnR$O}" $=r9cҮ.[#a~/\[aeEz7o۬jߺlC9ӡԴ勗 kՃpi>V{PTӠ Sx#*GP 2?Is\@nlRֵy,EM-8Zv4HXZ*U9*2S³wrv#eTGg X+"}9Db>}>zaz~%ze~zs$å7ukfv%\/.6J#!k5!ɩ7\^oJV M` lDp\V"n~j+EEI!8Z%_9*.tJ(CGⲨ D7g]׳t7AY |G)*DUԈ)}q򜱚*Y2jӤiSǀ1}fլk42{ҍU%ޡs=݅.a&f?j!1 jnaD'K>g,ͬ60@ژ~x\Qd{I}fpWz^E5{r40怼=q#!>~,E2ӿ5el endstream endobj 592 0 obj <> stream xTMO0 +$NR HܐzCuāq !jN}*R?R1j}}dkw]P#;c! BUC5Fh 1ekzhWv]<\ AepR!6e5tp,y3Zx%7 k@|u<( S{TAxCj7Gϣ~ZXA¥ Toqi+8b5^(ǓEz@oFafsJy)p%3mKο+AXI*Cjlv %}3.v2Jwp|Ke0X_۰c S3Κ+n ^^v44CuRZDʦeH.wC头%ܲO/q}o6~Q1 endstream endobj 595 0 obj <> stream xe 1{b_ q@;!ب8z*$lBwb,Ln[pibJ0ZIt~9%v;O@+iY 8@١*"-2*)|::3/ endstream endobj 598 0 obj <> stream xڝWˎ6 +dQ@w+Hl޿^?Ydt}LTa:*8]?:km[|"Nu'/_@'8avUȅ@q _NoHُ0!:tYT0 r\N.3H:D*pIUoMT[䈀a6WD犖s3B!)-B0K8~+ܞNpp`:ɀs^]jbS fLSen(ؙgѾhڙvͱU5Ufm,/_5Ywo|B a׏3Hz |J^ \1M6n3f dfvKvg?#v7'x9[ybŒ=\Y] أƁeS{}>Vgr\@5&x3ǸR74(]n/K6 F PDzseo,YCw|ZqPjZ(@z,AfY@+mCfo]wnR.Tr-kk]R,sI| TߙVVMP`}k^G HKAT2AX[y&7|ճ 9$緭squ Y&H}Ŷjk",9CJL];bFraTYķE׻j?ǒF80ٽ^vqp/u9jdw9_& 2ዋj%OCT މAU",]xY=A9ޘU$࠿ς-#䡦r--p;#\gRz'VOd]oQPF.]F=~Bfg3: V&]Y-VN.u?ȇ^ojͷYC0D`m$vwRqa 6LFW Y'tQƫ8FFʆnd =cm,ݠ| cmGlI;c(H%_, ?m^nLm> stream xX͎6 )Q%XP-[܊2IO=/({wbƈcHfg0?3D=L_k:r!C.֨?hm^\Pw Yeq* 7PZ"'zSm93^h|be)|e <$69?__{K*X,Mq ~gJmshFĞ*QƧݛ˲׷.,y #&G@ZGvY;_mxDs:T$L?趷ŋg PMmԼyb]jE \.LYRiX'aȘ\15Z=gGFKItv>,57hzіϴR:TeJ(R.&Wo߱N)* "Ylǧy\*ŏ[V]DfhO/qt 6p\JEAZŪ'n(Q8ʩ,{8mr:pZ(A=,AC2ip{{%AZ!B cy;0+ ;GNT`Ьoţm"ck#/MxfNZ=D3Ud8 ߎ!<BGp|Nr4:GpdhΒv0VyG?@P^F/%L>#ub#񆰨CO*[[bSC&Q@SWt6) A%B)ꐟG_}}f[Λp8[wpL;^s\ dQ\n~Ei2 R٭V A=`5Q{)U(yaC\468'd [xM,MJݲRbOfٲ;z`TЍ8@;ٜ@F(γj,+t$bu"i#o9 IL*#TSq씙tz,d_k\ky5̽5K~}]gh*-|Jg'P*Rlku8Ĺ4.XwtZu N[+Z~wϐ\~e2CdsRƞWHxWa3{ՈmߊÿAi endstream endobj 606 0 obj <> stream xX͎6 )QCJ20ȡ@{*[Caeʒ-';^,JGA 4aF~< ?(h>(+FcQכ 5גodPQR"Wqk45Iߩ9"o=0SKͦt;*@dSV8ӥoy3 ;pFXy+9륜"Aijr4HG$,ojw땕.NSR'^0e5/S j9EOoV+O畑u|& >?Հ]ha-V/x7y),e6E_=Q~]U tjK[ANsPl@y(Vbu|սh;AFa QH|>у (ѕ׼ި5Gf l`EY9 'm.+:# U 7> '›ݏȄ.V+˜gfU@[ٗD+)'I+1Κo"a$TdkxEeH&}-ژt>rnE^M/ftktQ)?jkL[2}C2K+.1)lr-C/.ܙ+btveL)y<J6sC{Ty=Ejrcߺ32ӒQ0k+P̧BѾ`l`36- Wu_qv-1QZTgځ'P#l ef^5E)3ی[vW ;re+5 8B"m Qo{r˥8Vm\TJsɄSN C1-,(bV5hx jmlK(@e뢠.7R-7ʺnZϤf~߁H% V0blR٤xcPb+؋h}EIG~J?@`d'Z}Ly+̼3?8VVPefRDzr5N7@ޭ`#`{kj7!G, .C=&_Ƌ]¯] h1:]T>UO#^ʰ_e P> FfLg`W}zVWBvx}7kTiyȾːOJOKC~w C endstream endobj 609 0 obj <> stream xڝV0 ~nmnl'ԡᅯ:-9vHI_;S_no9&%N#3vvu@I߷Ġ*sHZ$HeSЋSIˁv'He?$DɁޅ|S\w-*ij͚!j͇Bi"]$Hk^>^`*(@IUШJI益-OdZ9B9λSMMr <t灎FH 騸W ۠J.JON{-7Y@Јmg6:v2uy3q״7Ju +І^8sHChf5a EVNcto37*7 ڎ*f;z!}fGںO}WqR>=1Ĭb5!t-ƺbź5gYCzYTB$/T35nH;-X}1&˛h۩?օ}g)Ljؙ3鸴3o\~ endstream endobj 612 0 obj <> stream xڵXˮ6 +zY, ].dV]7(Rl_ǹ@1c8QHC0IjXI߾} Gt.`8㯫R+eJ9)}nc!QK|G{qj33/gFfp:M_ID+6]{'y'+|Y/`Hfl4IS;Ȋ"ĢYĘzb+'%vhdnG3k>zNR ]aoM8k[oNO|*_+74Тށ>4a6K}i^">]β2ީ(lٽfLD;CRn\Y)[,,SbvB6лU:޴NtuSt[eFq@Rsҁjh9q7 t~[*ШUw0@dqhRH [C"WMBBf8Suq.YT(`gQoE(ʩD9VVLa-t -wl^8DHDICt܃K:2NK>Ǡ|hT1/ ~7}B᎑.+Չ#-?4_$D%@ Iڊ YSJu:j3E!NK°^_{.|0TPX콅yH'2DYs]vI8J*&jGۏ<'PgųARi?5ŰV[DMj_W  ެV{xʪVɛ"o7H'uɩkGqxF Ͱi|'" endstream endobj 615 0 obj <> stream xYˮ6 +q@E@w+H27]uߔH=mLѹc8I:<(gg?98_}9+Ggpr~*4x=ҷ?£4 RQH@kYXYxx9W"zQNV8[,}39{V|J4϶P/.g|Abh5К-L0/?.؈O,o/X/={v!ˤK7>qbYV̢ eJ.hZ%[>JEy`&]OepQiHTQEq9Ԙ#>i y+f/&`a/d Sֆ),!k?ΓBnS,*lAӉ{ K%E|2,j؎t^5OμK;acL1jy(^O֯ݑ+K.Ƞ̅lPi43sAA%s'ք{{EK ǀvaTB@S,Pg2_!fH=iQ:Ǹ&m,x<%(‰z+`ϹO]4Tnria 0ƂO"/Pȝu~N0X d1-޹ vz5IE~x48~yJa$2G~W@`R~N}di jyZhkn04GZ+[g;pr1_ȼjoS0rg@CC]vH.b\֚9&zL$yX@'ڄ^S{ee8!gvsw,^؉ΣW>b̼9oilR_P7c#=`۵yJfg<YMڼet2ϳ8.tٸ [CQ7 X+QOYpMĵVZnޟl) T4;uAŭiۥtC.XgY`'O)P:RyG)Ot."lsdGN܌"MQJDIOe]g]#܍2maa]mϺ62?/,P6+{o7ncN|KM\ N<zO L)Ӕ)ytSDzjخiP:br0kxgbfeb8kbWvuAȍݝa!yt!<4<˙ B%ڵYg;-Crg^[X@%g%]`RbgëtpؤgC;,v@k],7y+ÿٗ g endstream endobj 618 0 obj <> stream xV! 3,HH"myJo2a>&]33sejg}Ҟ 9ixW:<87wXh3 p^gqݸM)b9b5?o :n2,1Fsed8M.rD^b0JF`iCGTHaY^#͂'TlUT#[W֚8$%DfraaPij܋LN+7hdGV(alœςNӻ@~ㆺhـ{6+YanZaߴiޖA>] 3cjKm{k?QR]O&Z9@SIE%ܛ- TmYY\Jl* HB ԓ&t]M;H[Eщm ؍f2 b#쏒 ;X}#3]+ > stream xeP 0l[ 'I۔$$$%&W>fڟZ=Dy&EFبR~ֲ@ CX f IHX+8t.qaQggzhbCUmMyiA,kI5mT]z_y)OٞE endstream endobj 624 0 obj <> stream xڍY#7iy  x 830@9rOL".vdWU'{2=eWo{g?r +ɦKt_| }v6ֿ?s(z^ᢰ׿g~nM,ݞjtU:pq%|%X|;[S}{dڝ,F:2P:YsyJj[߼"<1*V+c0P%-@ADIԽnj8jԼ^L2EjX8֔0#QوsM_n3A>+pȃEh#BS+Zs۳rgPLta'#.[֓4چcoֈY_@ p̊CfqdN` ڱe٥C%/{[M`jbΘZԿxţ(E.ٞJ@rV(xUai;q%Ç52$Q%Lp_o1=*">C[_N8A[/V P^?>ɆWĥ  3^D%(aP)Z}* :t.jF:THu T. H X}Yɕh`|.BŸcl|Xij' S'9#my\_@huP-: No"UMU&uơsv%B7q/XtM}w^E+m:C-0jG.N9~NiXE5f,Z h>gT]R*³MX+x:?2C&mI\{_#/ g/*OTmt%p1Yk /~tZ 6>Ffղy+Cgپ+?'_w_VpE㥐.hEUjLc&@ry&,Imo|x\[A|'k]G;/K*AXU6!tЭg|-aӛ*Zun==Hi8I*ϼ:SsJ;}|Ш\t̃ |Ⱦs/^ВB.M^7a9\{١}}-jǭ#d* ucT Gc=`5=he+ͅX{;E ;2^uFq$F/ ~_0wθ-tNn[E"!f{ endstream endobj 443 0 obj <> stream x\[Ƒ~_G̓gؗ'7 v zXXKǐͿW9CGe"]3ZswrkW)w3*a-YW9u\kG&Jǖ*}'JN;}}걩jR])WlUR)؋l%J z5IzB;H PJDQ+bؓa/S0P|tY{ 6+% @P eIHdW csU(6SRTBv8g.]QlC {Ls@HZ397➁qq_8 R@Bf1u܃c_4ع'½ۯqZ tI86ˀ@qvjA9D@A:L Wg :W3LfKP0ci?5.Krada'E< bN A  LCD @{HFjVA.?US"JMV@ Qu@VuP!7,-9cY׾™/ٛǻg^?~?ū;wwǧg8O_=}ߜN}o_^zpO|jw哗߽}uIItcG[{iע0(ܟ>?1͒gIR)3_t'/,|qle2`RhI~EW<_[އ{H9^)`L{q8̔I uL95ɧ*\lG ;S>29rw_pJ/_3wr(VR)8` _lHã?5X ჿȁk0Dg~3;q)6+J߽yokqm:>Wi>VlEsեr-*%KiOr dʒ'A+4r hӮz+Z fK-8 .μ49 K=ߔ5$Õg=B*\ "YVXIK]b JّBJYLd k&WlVϏ(Zy q!qB8KnRem:FA8GA8EjW5?t[MlpuSȯSƩ!ї-y\6n^ hБ5N[hZB"Mkhch=ŀqbB380.k@%Z(%YQ SkE0*7>vg < R_4_8Yxݼ9(*]3ڮRG0ш sZƱWT=M,r4SZiR9")Mg5ˇC Sʺq~`-!J`0P,J2%](''qprrG\~S:@8(UnBmi hz(šGa^z[D7gs CiK:&$Oc #'l6W[(j! U(0P z-^+(+#<5s7ce~;y\oP-N=fxl:JXZ5;! `-6B5?Cw6Ea* R%J&6/u2,_pOO9ŷL=VI3֋0hfL--TiX^"s]׋·K5x|eY/;X*XKK]財 o0t- - -k@DPjqP /ɊYWbQIC? [ (9Ղ' endstream endobj 987 0 obj <> stream xڕ[$' E\Az ށ޿z<]UY911E'"cXȱ<3cѥ'F/c`f~Șǒv㐠9rLG1Cǡsk2f}73a:X>rϜѲߎGx3w? >8[GzP&,a͝~p !|X#XLp$uFH O0w85>8:qlT@MXF\h Q'5cFzbdqhA|V 7`gH:Xhhg?@рWCØǀ?_ώ&4f!a36$ b5JPIRpl fiCc|eCN`ј4XA\HlB :z O C:!IS{j \>'xv!IA(R2S~/ueP_A ̳%mYdG qdd4BL 9R~|Bxd# i4 0*H'9s$D4 b6 GII lJk,BnE a\ۜli< b*oŅQj \Q9e*p@3C0tKJ5t3H4I&Fb#3c$Q԰dj6 J6Rc_{)д pLqd.<ԑd2")P%%ɴld.$Ӳ1:՞N}RRdɯd|҆Qd@u\df+LA jd*!A9Y,IXI&F%[cA&EHv[GMA^ ³&cA~!4FL,pP~~˙z?( =?}788e@U<@!rB'\5'\G?$;~ߗ?}̯ qBw7{_TU݋\{ Vm ^ ZS+%zĨ{%CP^VB([ Vӵ{ҭB0\d8X/ӵÕ7Vqt)8 )Oy;x:_9݅qB"Flc(R,aHt fׁz;)^צ_t~ʦ_VA"ZY [d+lUWAQSߞvL|I~}vOv·}m}o,ϷׯgU! Xeu8km|y)ي߻AdKvL;k=yrzw_Rno/r(ţ*Pn8Hj"-*> _p8H"ūTORTd)m٥^W!X endstream endobj 988 0 obj <> stream xڝZm_1͙ F8v&c ʀV4@oj'*zʈ:Af+zB)p56SgA{CCjI.般Ł+ [+  C+`IzV+"h*JhHO81}\wt`*qcc,T2W+#h?)ZDk`N8QVd?[у.HTŬoV6 T:~`\GMќQ{rI0HGywD = {̲,0\ԏRGL@9(蹨 = QAq-axY_:|ŶEEBxM Ia@FBH#rYcڒ|ڳ0qGHvBXzVDCzҲ'8N4VEWDd䏸Qr4ƓOR}zFa 0YӐzڒZnXi 2E?-}1韢\WJT&قKIzTFUz: oMJi놾N(a ^D O~$h"QjbKIY)%)Q# tEhzd]!0YSkڧ EBb%w((0)}ܣˀg/W">d)F) !b<:r% y+"Ky\Ey(&lKT!}ra>׿CNJ\ᓻvO ﯨ@[QݯcxXw>z_~^B\pE(ϛ2( \.\p"fUKe#+Ɉ%# F .ьY )b΋q ֿŝ<{Fnm]V6 oj߶O_<94+{%Ϟ=}]][IKG;OmnfK5t_7z ?_maeYͧ c?kqWCs T@u.>lV溹>nv lUkdM8]}5䛗;YpRw}$W绚Dƛfd復w\p``kaz m&w5/ǝ Bfnsm`߶(sƒxǡ= k5r>(΅ɉn>v mo8Ugũ85ԇ]d'c('lNJS>զPϛZGnܩz^*|ze2`fQ/9g&1WzUb3!ޣo %!.2;w;PfK3%iMhn6;~:|a)ܸ40Y409D` QqGZag\RLr6\d%&$Ɓ4bFV"mt䈂rbdALI#*Hc`L/z\wCڕU肼Ĵmn]װ\kk/0gI#*Y]՜xc( sB dEIN Yer?7].DzNswݓwTV9l]ָz, ;$y496iBogr,+, d 9[<_[ݬRc(٦ ɾ](.2Ki9I韏x=!t/υRc']5IE49kf@>?rG@RYԽH2 $%as3)G6SYqU yXXmA` 5|ťWJnoJBb23L.3 ߮K56^V`Rc9fY)??B ܮ>4_`7k7\m7<}1IÇܑ4nJMK _m |' Xgyi'1k[c7|]>1(,=Xv0 6v͞]\bJRlg2.81Ѻm&@ 7Ė4XNRUH;>w9׳}fXV-iT>haJe-)0-HOX?ܵ]A+Il8l"tgTL}yۓ+}k<29)9x {,9X9fv@)mI*qّ~|I(-kI.̸M7QVjKbLIdqvzlbie라wp}͉r3eS?Z4({n!7zg@ ۬$jNIHcHs HHHtH'jH^H'SHHH;H.HG!H'HRB/ZfHuR@!p,H>R0d*|T0cK.E?$JܐA"(H ) P\BIOH^$JJT0~gBI?v{!H?HР_ JQ饶$,*{'>ê>Ū>+%-P[B23CVmj)-gKZ 4'=#@!\ 3C_=Q Y4Ϊq8x'?4M0aCQr*M`X7b͘AjiA=sh6k+b!߰/ Z acWtqa0l} cz6 ELYŠǘ =b*r8$ 6 dAә`{c(n!W߁ D p 8s!(sG D `\C^- y<}+<;"0Lrs A=CC#>$p6_e%BJ,} Q !3Ǒ)FədՏSsQɱ"p!]j9Dx933RxF*2 ]a?S?m*X9O'_'M9H}Yhhm0TR< T0!3o~Z'D7V-C0#rǣz:G9Is+pCǸ?Hp$0]p !c\ڏb&n\d\bpÅ.gkøaoI|X4qJ% endstream endobj 1170 0 obj <> stream x]k0+1IDڂJmf >޹\.or~^iG\_W05\ xB2B;e=?S]u8'8z="f9-0pYTa4Mϒc?N%VxcNk͕= #o{i{ U58e%|)KH=0ߺhۥpJ\)#ZD$)X$ǵ@Z&\JmF#eID($ rjfib ZGn(I9Q\d i B i-";!]QLc(3;[͹饰oj > stream x]]k0EG?@j'86j;EF7眼ɉB7sl'KXhenVhL5r g Asxx{˴SPSn3X;DZn?;[TWˤ}Z8g%*͘+9I89 V 878?bt8F{hCmRFJ|gD!ў("*h~s,9Iuy@" <2YBJ"7G1GGQ͵?{%w5Nv^ެ> stream x]_k0y$Y":em4vBC^ױ4nNYu}{qNdL֍> stream x]RQk0~Wc n: ݘu.0Cv wyEVH1(^H:![: H+8#|֞k}{ ~u}UǝhԣPrz[&-tNzh #csrFs!Mxܻiy"*-)Z@r$Kc6Ztͧ N'!v:]|Ѥ4`3]8u :I(+td䲬rɜ})m4 ih}^7S+ Ŧϙm+ JS_i6~6fn NEH-VF $ endstream endobj 1174 0 obj <> stream x]PN0 !ԦH!9Ut8pliH4tl~.xoP|F'7`,hVFIҿ8׷=? -Χ>J9-v/)cZ'N1,{Ѯû}vg.2"fqD$uMiT5MMMGʬGT͞CX'dGixw>rmo endstream endobj 1176 0 obj <> stream xcd`aa`dd rv 44 l2 ?d1g!"Ћ?,OAD~j@1VyRqfnfNbs~AeQfzFFcnjQfrbobIFjnb ZRaQRR`_^^[_nPYZZTWr-(-I-ROI-:QH30129|e֩rm-]ڞ!>ۢE 17Ai}3]~T= bǞx;3y?.b>sWfܛg1" endstream endobj 1177 0 obj <> stream x]Pn {LUU~Tɲ:qmT;Aa|C23٤Gl5o 8rGH] Io6!$\5 KWgo p jvNT $^qvvû=>ُhp8ic8rrka-S#"MK($Ŀ|c1K#?>m)vDPYQb#RcgFYo endstream endobj 1179 0 obj <> stream xcd`aa`dds pv445gi2?d~1g{I "_ Hu PX9(3=DA#YS\GR17(391O7$#57QOL-Tа())///K-/JQ(,PJ-N-*KMQp+QKMU]B9)槤d`t,<3##K|?{6?TΝ;{"Ǵ r]]6llnni$0c'vNgF 4WΛ3{Tu;{:9['h1wğ鿛ʛH6Oj.3s"_قSM^wTv9.> stream xګ i endstream endobj 1183 0 obj <> stream xͼy|833{fwl>ؐM$ KH +*x!(OXbÒW2#DO!Tz;^GHcTq4BS8gp,=_zq_ZP}+;d*U+tc?z>|̇P]a΂E<= EDtGy#ގ.̜v#!UiC:;gT˟6sa!2#4OAKi7 (ڋFq(_c >2tzGߜ݁A?w:zz=#ہѣ[Vtz ^ 6+''Z 9Q>@ Zt)p3`` =0zjAaԋV'asX.A]0 cykFt%=6dס}eCQΒH9JIIx'NOǥ^O4NlFMzщ(ц}~z|n?Hx nzS[У6?U p@yl.@y ]v2ld\%|[}ʎ||?kv2@[B6MD#5?/u%wo,y AC,=7P똑>-o8=?/\vw,-"K ,i)iUI Y%DP*N嵖*-/\eh;!AI )5DR }|a?Ю(DO.|~iFFig)-/ MXq8+Op0P\b[z.bv2,1/fsܢq+RoWݚ:y㽑YAк+/Ûo}=NًƠMbnx͂I~ʋ$۾ķ/PZMTGq3Qßh&K) k9b6'!9Pm-VS1nk}Ɔ㹌FRWDL(5D81N[DoY6sr (r͂>\> EaP4F[oZ&P_^c7Mb/Ӂ_?xW>B~'[נ!Cc۷+ V lU%48QMz\MzM;n׬ƫ5Cx CcF w0,C*Lb1[Kv#n2ϟ|'?o>TVW3lLU1.ǯjkmR~w#ʩ-^D*l+] ,8Nq8feګL*{mqzGV!l qt.'Ch&op2.)$Ktf:irMmyF)o)W/mڂgo:Z}Uq𽉒#\dTG17G|Tk`l@#-\ " {[ {@*by#|D< .c'QH ʙNHJTMQk B[ ∓JC| e {HHb8%fmx`bQ=ߎyp(Z43RZG?ͮ*<YOZ |8 ৼ?7:]XΠ؁3T*p ^/۰[ L(cZtx1@cBwO7/ŸTONJV]ZPHSC&#Ô It04fq[dx ȁ:r*+  7%:=n&_)+f_7)Cn`Ϛ9kV}׻n{sYcpDO=5j,,. ˄M&MBt52K ) }wK@Asbеܭf-q3m5Ent"<,j[& Ac(%Z W; sa~biO\NnOiO]Be}uj 9R3l*}Ʌ&$L8B\XtpH3҈Ln # a@0Qt_m]wμvrUWܬeuO-j;7?eS',U >9uv_.ӗSV Ƨ|J۴iƷ}%޲Az@pS30b"4 , %'&@ KzJR9qIfzϗ.y84}$ 9 R] m,nt:mOz'epQGuo& Ȁz)fH7 >7T F/h$C yT iDk2LDZ `MKE@!,:0 tE2+`p,-~s><)!'},*a|\?+x,z+YZ)bR+,99FQaFLS6CH%& `k;]SlNН|W>n͋rq#qyf2:n댩/]YƦ?Vm };nLɛppFC+}ϯL.t%JBLJP\! xIMJqotҜj"A0|AV Vj*uGyj'Y̥db$3XMC1 55*~S-p+vԐM^3QdsfZW޼g&!SJ-]3哊i5CZQSAo5n[v#u3'>AT/IXKq5#d&F N<%M"B85ԬpgRT}Kix4U3 pѻ=1q:^+ɦIv̻\ɶ4[+䚒A|ޗKNOsgB)UrEuKujVI݆eOw֒В)MI}YLV"Z6ٞTb㸙łFX>>q|91A[Y l֐LFcӕCTS!j48ܢ?RT\_up<ƓjbAp$+3ݛŒH4&_k8HlGXT'hzoʝ͛ڪ.+{c-E[ Ok"C]4m*2Y96z<}vwt,XHf7K 즡x qhݺm_+2Rz'GӉ|"e BHV$AmpF*x^,(>-JZvÏd?ͤ>(X-TMJ@[M&M r4+EX:ט[*V# T`e7IϛS5[#STbM+ҳ}*/kEX KNO&dm_{czpŵI).5=o^oF)nRzV؄BL) 6Nl {}mتm57>gs8+ ZZA$fq/?:w=y-)ʢeYhjc~K%m[QcEϢvlo=M߹ʙӦ?۳J㊄8C8sĚ,]X3ZU[h*FiVƺ84Xa L.K4RR;EE&뗜}]فǸqCG~mjWCPIO|[YuҪ/q0$+` `>H6EXDk &$^[YlL֨ \}ߨ53yol!XKB9V FD^Ǣ.I DFN5}QVK=l^ll8N=ʂ3t^5M1E3zAc bl4v ݺ@)-({׫fs|@ORT^i4Ye2LK=1~$dYc :pZUCw (.Q=?q>|7^1[O>| qZYCf0{_$rrGTI*&^DY$k!E K64HmyEP,TcȢI#Ǐ?'d'#H5s%;:D+aѰR+im'JwE/DH@YN^ 3^xfo>ѿ?PNś1TgKMXv,hy:$)d4&»u9+I&_|ۢ?lLA:o׃D/g eKZG)NM+DR\*u5F-ݺ~A4Cۈs$hdpBȸXv#pQ4TR(ǎm$@ݼ1N`NeMY؏uh ,%7ݡhJx-riLpxdhy:*-u?t|ɟ<јl ף r[O bjAW!G>Yj.:@J3sritQ@N@$&`|f!S1UG~M K븲h}5x 鹛3@Z>ծ,g5.M@Sitjh4lDpa*r! >Aǜ@f!bN0ġA0C8!($2MXu*@D~?#c?081kG?EȋZ`U5 D\VRgKi01u41kF#%TMXQECZ1yBI+1C>=fç\T _P8gymGÿ).)ܴB|™?4yخ҇Ow%E7(q .qiJV2l2ҡ],LȬqdHPu&{`0|'*bٝ(DQF qX6|l~2㻷?U8] _Xx<Oz ^rKⴔo<+mchTхI͕#f'}byB\U[+Vk*]Y9\Wؓ'_G W{|{>f?~܏E~9^7K3 钸Kd͒lh=D.ɦ_z㔲U@"`/(!S87W^FUcqOVMdy{0czmuӗM6mt)SK_IwQZ^RA9^# T`/@n.* зo&:)%b%`A51B hh1h fM7QviX _ĉmD~5E>U|6~ nS>^7=+QE pyQlj4Ou94GM" e_;QWG* q4M[kH37iݸts|<V,k7m& 6_Bd$P-dl79a5Z1K%0?5>R^R~U\`bq Ú{l>x\ݳܧ**b~NoZ7jNήi&7UJ۹V~Ԡ+~ԡ]ĭ>M@BX-`N "BO$*Kb#"ODcҀ(*^b%!QJj]%لXWLQĪc( &^" +JFO>BwGn%_"J 6|ek˜ip}CHlEh^Qւ d rHC9N@nZ^;@5QURtʠ2}xD֒AYBE3QMbu1NbD\PR`qYh8"Uӡe1#BX> at8a1Yaxv=u\ӹ%tl=*($F` !XE|3đG' jn{LWޠgl'\<6܃XVD}0uYUYy'3ZۃpOn &j^ؘ #eu&F[_ʦ|- -[,n>''')"b"NCMAW0t[Kra4M [GC 3'\)(b(RMlml͕Kp}};%otBM}嫊ƮKw:qn1Eo8jJ۳BIfl\ |Cn(H4^ :k]j7%덒?q,hu- ]J cUYU#a} D][?%*#W+oEuښ۞$%W< 3 "oO|qU"[ғ_y[6'As)&o4c#=a"': 5^[awLIhe۸5ƙͶx!*5$ikDžZy~3f‡7R]Ӏ qx噹w~jvzAQUuV<8x vhh?-F:_,LwNMv =BYbb9,Nݞ(ݓĭXjTTƈ9eTȼi`02-~zau68_++lQ722c{[7}`ˮ?ΚѐO%9KRw ی n'˙\d(KRAT#.sLvNӄL^D=,`y 'YjmA%|ƞjZQV{LWs/O.nxmʟ8O ~M$i- 翞] ?U7ܳ1?NB*Q'R:f錓E o{#$#uNexe_yEE,B~>|00J4jw٩ NDЁ\  ĬsvďYZK caG fbHE6ܞ3cҹ_yףv r9_+3*@˞Aw AFC`TkԧA?e]>3JMD58-̓7wLNu:1!-uhq$J>V@8խ+|?H .9;;{M#"V{h^~&7f$*aSP}B[F6bv+V:} nHњh?KU~sF+nPm^7WU휓"0? KԘ(|6"h/oM]22iAP\MiN\z\N"\ JIfq)<6'rv }ϥdXC#۱yj4U5@kjFF}wnBۇIَOf6ff+օ*}tH]h9D3hszr

WKqx}/N׶ߵٗT:qc˻^Vf]y ]^U$[Z%H ƬVUn,U: ԚZ?JBrwy<ՙ5 :-s}P 1SD٩5,xj-'Z↔_*< 9{/>n Bfy|KrhɧyW:~.nd%J] g7Ikuz)T"Ohl W).70awA)nF#N(V>|\D1_4|q'd-K CWK$l6ME4ehIRv*4uLQZVES s9Lx( FnC>:ӪLV 5={Z68pZSy@}G8||y-w=~Ji8'?(51e6) G\U_`rAWS8y[! D5|"ڊ T"GQM㉞@D(TdbrYJ&S.亹u@SQT|XPck\T<#/L{  ~:"-cCL?%"OiP:Ghhd2"NFK҅tպ!OPku.V PH\NFɝWΩqc a02QSi. SjSHJ4; 8l&}?)2BҨ>"eC#}/i8}zœ]o1 sm{|#~#|t`oMrߦK#7>t8K~_$'4[ Vc$dX됫^}7Y$Ya1CKU5H[e"[78+ʨ RRc26!HPwc;юabEtpİ^S|T_ߝ*%Ԙy {Rp=I]4z}@X&!}Pl18m3D#ysyIB{{*x??țK*~FLx+N?[%%Jg)RvWLe5K~\,O6Sg jz$ŇF< K@k%f(h-<=)İ*c?.uԏZ!fͱM۷߰ 2͏Gc7FVKXFbC$T[{#ǫ3kF*v}l M]E71+b ٛ8޶Sw !U^z/p'`Í(LT:3ivRY&B$Q?|iE_#6"%7Q:Q4!wmcw99(dfJ_^V6ts];& ]Ƿ>B_;wC{LhF>hypS}JFwV r ~/Z+ބNpB):A+( `9@k; } ~vOWh UpE/6#1oPw2د^D &E zjNl<ګ^fpI[k 6a#E~'_hb SB~%;do5|o&6.yi1CWЛ\o! _jvfH\;;$QZۢ}S7]w7:E߯@jbp8ݸddsyk*˷jǭ[j-`~Xc9$hZ'g$~,r;_K*JUrr_%2|oKٟԢ-)y-:ȇ&_XBv6qL;o h@6c}Ʒ<c}c+qG/($}A\k}V'7cۣmcd7-b}|%W/xIA I2Ƚj_%O}:~Tj%8[I~:jCwqٵ4 O:@sվKרtu~/PY_Tak~?c}}tJOo{Inw.wW@!beW]d=mu΁eWsOYݴliZwS]-]:[qw;^ pwg4vh?ÐzN@gWK.V~u[6`VW~87 ~m?(9h+Űwf+صnŬl~Xc-%0 VSe[) 7R֪Gݰa:wkwgupכ\1v~m e_N9?O+(xY?LʼnTJ0Vߡڅώ]'?־*{9.x8 V.nӵ+\\}lݲcunv;L%sO5شO`K8tk-hy;$fm\˵q96;粥r4m+^vVrΤ*.Y9mǣ\k99 >mS.[ /Թ׹\4~E׹ȑ:>XBԹ^x>uhrˈuA^4=a䗿>3-#D>01 ?8t3Aw5tуV*sHѭ\2uxKJ!ixW۰X7;EjZv`ڼ|iP9,x+ֲ#;0z+3lb}"*{m䭍.nк`mg endstream endobj 1186 0 obj <> stream xګ i endstream endobj 1187 0 obj <> stream x|y|T9ޙLIrg2u&ɐ2$H$ @B2@L(Zvʢ֥?uֶVlk+j=w&aѶ}ygn{sFbPn}A)HsswY6H -]~!FD/]C !$#4WoP* Cn(gxvn;".]~e@=h.#K*m+: oENdyM BSNC2G/|ކp#^Wx%=Mp<6a=؂t$YOyZ~O@_4vW,:TlB^ a jBM8<}'B{tڼ}CDc/.|1idÕx'I.^$Ċ2vEϠWѻLx{&Eס <G,F!g#K rr}Yi^Oۥ$'%:bv["MF^'ϱ (* >nΉ'\fR忻zE#UzO=y}VS=SG?QLˆ΂cfLNU=eʎ61#S?GQ>Uz*;u9N h:N@VM8Bh[}aZESO8  jb.՜*F|eXu- hHЮOhqh88ALjUw#cMmݮ0 kJ\Uݮ]ʎ6=SwCTٴ= [YӠŴg̮e.kvWM׺i0XUOɎe@G[YڵSf iU7ߵڵSQ2lqAF nJs(jXmJ;چJ}3"h TV(0@صF MhZLbkI ֌uo,?BtŴ?숩ƎQT61N+,8÷ ',\Ӑ%[P^5(T@=ݻK 6Txna;.K_Ӳ\mI Co8t>"VJ C ykW'?/Ō0"Y1N}f>.wpg.~"09 p-V*^ I@))_C%,-؝F,m7a'v562GC'O VO*^;I'7W'׽0 }(>SH L31miiH ńl&+b0бX+. I8^vX'J'Uז7 $eGiC7cOV'}zǣJzNy^kfL~Rq9ѓ_ߒ~BP$$!=:J3˘4/1(㷉@:䧝Af2ډ-thx8k^G^܏9L'21:GΈ΄F>_Q,`U*R18HniCt`>XW񄏏ID;`dK_rr[&IIKO#Ep rr'Ȏ@~!2χbJMͧ? uKϦM=7lXN>>ھcb9cdΎ飏կ?1ܛȌ x?yC`p1Ĕ3 [JdM)Xg@dz0|aח]ks3n V6"bYTxx4 kbc 0b!`T-5M✬eQNNN8rO:n>ޕ[ -EmK~@\$Lw&M8"ZW6"K 1.ɘ˚?皿}YY ]ϗI٬gxԅ]}?6IiJr|mۮ_ƟU4ۀ9&`mJz\oG5>Sƹ:qM5r9 ]U(='8LW6 qh)#4_a<#jDh_oBjV7Θmޯ[ضk1.yɄ4 Co9f>d9j]<>-e&v k^U]; mq{FƕddOzsJK}uKbf֍l?KIJl!> 2݄0A`xTKEIi%d =>Y㠦-->$a78"f/g}8O0@ļq3ql^XX#,wZ:Ko67 rs[ g/ ,:cv9EVE*0QIV]%$(1(豥 VviƺS Ї1`pfpDp&t$L껏|:sFn݈cpC%k۽JRZqz\o6~ŋSJ[duG=ߟD2f,Z,E (7|\s[ս);aU[mʒ2oYfMJ:sjoMX\4 }dż1cU|(6P,`mik<gƩQͧ(]OiEerG1m9j[ܣx93{f/,agosشY Qog&JVҳR=9=I SzzV\Y9[ 2}/+΁%~}>W>553)8/Um.2s >ws2ٮ`OzWϸ}}Yqq5/^@6}eJVṬ)!LL3LcVM#fj ?uP2`cvhQ@38N#T"F ` \n5F}p>{ddqXlZEt/ח\񽗧Yѕ^Ϣ9seq`8|UHG2fu[2~GB~|Yi9xv)yI_;9ys:~3%v}km|1djkB|2vӛ$I'|J:q|_,S|_,\ϯt3Ln ±̾BH'1FpN8# Zur 樭jUBqv[CCCZ.ex Y:Ru I9ܙ+c_nȋhADH=dW{k(YN&m?L&B>'8fBt 9_xzp>ڲ~~9[VEݤȎr_"\ʝ?鍇ב=0wOT֖U޲]*rטͥe9凋+3q=-'&Zc%zfz -mY k'DYOD#?Ε EIIqI&?i&|]sUX&Uĩetzbh,l$=udwؽym'E *  J n|%+v̐Ixz S_cX\pu͵}6l1ܙŋw4~xw#$2]"#*뫴 (y܇걇A?a|'jc(poM!0xN}5lR _8>"KMA'W mbH"/N`0gH?:fDF0"EB3T(|/Ձ៫xA}8ĝqÜP$"xFâA]?"3ѠsAXG`|BkS,4Ẋ?t?E,X>_<ma`P8X`֚%r2S><_Oqg.E߆1 铈aZ8 :^u>f:TWu.]z[YO9VG5)d- rGtg66IJ,mŬ 1^L6~d8!UxZ(Nw7r}AUS3V_CڏO:< f>@_tt/u/8r pxwp5[r0DLXgxn!L ) czXeCǀgHI2ҥ @|@AKX MA J$^>η}Oq jY:k@Ƌ;+DmzF3.s1z>e  :)Aʒu;0LTǫ8/?eY.tE wwnKqGe 'n^}Ca~m55ȟCj Fî)'l;5p|YOliiqI䜏 )`],W4-P D4SiSVA7]f*ύ>(*7b}^U]3%lukT7sM TPZ8"jÙo>m69[(ϔ',eEJFaRg0Mgg̶Cf$*6d~k DkI$-WJ <˽)+NڽYdS{[9KceAڋ$eܙ{*m>_ѓ(ed h %Srbqx 8g:uژbX7R૱TXt6Y|dIIL9}IKB#zi\- -MPuHMOe2- &jmD;rsˌFjtI^قrtա96zũ,szaGnkvz- w{WQMǝ] oZxX(Oo7ZK,pZLL0(h!/(KA_b"{!DFw}VKa\chg~iAT0UZbc؏ۄ&=rifzK '>n{Mx+q=}փ>ÑA3|lP2HF0l^CScJA|QZcAII|C~i>]Xb N)JVzlw 7q'd\ɶbw9&Yb_g!$eZ͙Ͻš` q;֋G-fNP9AI&Z V+ϒr'a.OA􈊁ꌛSW{y[9`B:q{^/RDf3XiM rʙhq9z[č-tDIrznt>;Afv:ADLK%)Zs̞k?]qc[I|_#hִ:9ш[ﭷnX_}}LTh WT{$rk_F>4Bð[a 8Jy=^f Y,;cd2b +.7-AhI(QތQSsVubYY vdHΔ.@s,إ7jF_}D"/9 A^eLp& @G^XL:uof<-#/v TNfp&]ɠq$BlqJ|cy4le,]sЩoS$txLTooZ$Ltͷ2(>7>zRZ2H9/bR.µR nVR?"m?N?OҿL,*"k$,Zb$W1&̉wN^' әR?GF ~^Di>A!6C!8}XqчP~\ڢt1[yVX5Y' ڸGEK+ M-7-XhQp2y%f=SL3A*5Iwdٔ<Ńb4FD&peeܬP0Y>BP҈b_VɞWVkuEAGųù_]|9u`Tc/%y k^/Yv%m }m8Y %}߽;k)m)ҽ}. VIvb?% [Wntǹ497p?p *r-?~v;=j.k&y5˱I .ٖc53ӽ8vpOt.))sCL#\D)vE6z PO19AIwX,(VM?ݶm*eYX%,oCuvUfs#kzU;z$>)lOqlst"NYoDl~6ɘѰ0,E{;خPևkbrAmq2䑮JB>|u4ZA#(ԑsCĹ +mJȀp}Ah,PTc `zq3nLNW|,D e/E#_zKfD/. {Kb^vkioU֘;]Jk/(޺wP@[32s(.!bȬ,q.!3lPkyx.ׅOȻ b0uA?uP^vCpt  Shx )/((p3ݲO:($g* ;F1AipQ#^GC.VD" VsٗwR?X>Ԋ?GzD2PWb\Xn|ltxUSLی^wryJx\0$!5Bz6H -=|!ie!G-~foG;EH{B|!ZL=N$kB04j51ȧGar =-ztskk<?ZGQ @[([EzHcGkw &9O+2a^d;+a_Iҫ[~~ ^5~۷i9"o1YY޲ݺp9lݶ'mGS:b4Sr-ݍ8BQ ؉`im ֨*ǬQ $fEa|Qx[GљX1ע0 k= X,JP("h".,Ó5Xrn,JĝLO0F&"Daأ0HR1(|K~$ hyNu..&SPneEa0 t^fS52s0 -=6+QP0#Qܣ:0FCYO}#k퟈´b? /'Q|8! >QڞDahhʋA^ Fa~Eܾ( xrj?|嚎"ic|lJPgWNWWG{_qW^IIk%{v*{WzW-]95yrWò}k\ k:W׹}e{EN.ZJ_@oW+cE-F DsZek\+W_n`yvh5}̓jJHjZlRMt|>R:Ufyȏ\抺F jӥg%qHy`JP!@32h5 V/ZJ4j&pP-S['<)V뾃 ޾=ӄo;vfMtn e|tG 9W42 ):~wW){Ӊ٫ ͧSSYN'FOc?A]_fyy3ӺO7CoOe(O(G¡pWGgʇgG ЉF~/)g Rߢ AzmGNsx9|%C,?zޙWvqvH-ʍAÇ??5k0_[kx^3nTgd[qسw+qY ˸kc22i&o9crɊədO0Fkh-dtz/ l0 ? 33*Guf[Q0^GF,QaJDJ}"9"՞QC8W6f(  0r¦8Vߤ7rs jn%;j4CI| ܞԌٚ5kuDw4T7D{cϔ#|?O> stream xګO)RB; endstream endobj 1191 0 obj <> stream x| xEp}L}fL$L8B@M$I |^cEe]cJ:=SQ*>O!K! \->j[Khki/*=FW_XWjvutPP ҃t#>^Ů},Q }ҮOnC]Gv!#նyZgZMZPXŮ>*WnHqU-pm0rT-htH*:3y&@ ?wmU.mVW߭Su{SSS(EwmjTGkѨ l% @T6Ğ\W聢ح}6w<& _՞O7z\p)!WjOu˶mWm6񸌞m'OjVkCowU_glYK69ܦW,Q*. &ЩuGqGh>j<1fܹK߆)wx>/G 9:cr6 }VFLTCcjAi>KE#u(DAj/1}v/Ym0<}Fox1e4`73yʌFWն!.0e|i]-6{` j\,OOPg}G-?mrᆡOxt= [y/~E{h|;q ЂO !j)%D|Gp,o>/azJH>J+/r%?_i?η"9-P@g A!#3|q5>_3*+ؓA %M @lV䝘5izX#mqcGp뽷H["Oa5J?Jt\NtZVY$:jX4f&oxOuS4Co If?L/ihX׶-9MymתwEgx.rp2=%DzF2w:A|oEHx7ej6v':d#~hp ade_?T.qSuxg G5񯕶1=-V? 27 |}LȃY(8c1 hdjҝ:Ucۿڀ bn mQYDJwl!IW"@Io?*kAJ'5 8/ 3<2qb/5K?wbKϿԾ嚱7ͼ1P+}>U!awnHͽW5[`tǗHUZA9+@Kn%sRLuz]/[Tck) doI0c2 6fhlٻuwYx4?-3₯#/%ȋpΟe*ؼGQ2^h-3Fr>>͔8qe_%p5|XiI\-[ln>h Ň0$]ƒ$6$! Z AlHJ6P" 7$.Ή}lʫ` x^%Otll>p1v5Ux"> {g߃MI,i^>M6]˺&)o/PPZgXLΏ2o`˲x!zgN_bqB$=/(X0v 2s=@l™%@ /.pD[ `Ɠ{W}vPuSΜ};/v[>{iK6_4}l‹޾c-7l-G4j@;:*RA_6KJ a~@ h+,e|h.H6[z%< `nsUHw?懑 |g3Km 8ղ4 "ZU$.@Бo+֥T$!!C`lKݺ =:@qd *GޟmHFtp`雍_߼ Yqo,{k*2Ud_Y5I{w;THJOԒwG w|'_{_G]-17D {SxL ]BeVoLۑ$#dV?{V0e~sMZ>57+a"QQZd2` .vY]Gmv҆;F\xZOϚ_rNlܽk]z&>F_CNR~-eed}0js%@2p:@1WBH-9qT C] 2LT BaO|^eWGQ4'?Lg3}POAOh,Qn7d,ɟC 顼P~`uɊ<}i?_RdMRMqu`G@E:qDB-Q'XzR6_Ϙ/s'︱sEe[וO{-yjD ގ{ͻfäo cW/^l8Ln޻<0;RhtǙ;}+Ve{eEpoq}<7Jv1##cSǎ^4:s<:l :lWY5cUHjBB&\UŨcR(I2foLNsT1Y35aݫ"(O;q^xS eeuϳLh_ODoyF l?(*7ٛؿp1ykV4ي&6OT< L3DHEn$fr<` K*׋ # U*# tE#r tie-݌wKI`ZR# gͭffx3QpѣnuSm r`ars4tnhdh G,R䗪U]҈܍o8>}]4|:ASEr. \1W5p=`r #9I iaF9䚗SQ Ήq̘|L97v9s Ƌ[{'n}n)/)ٽqe(4&)1g}a~C޸u77cӖL]9?!o|X帶+}3ĜdT'8ҶJI0_INPt薁(uxU%…diivŦ!SȾ.]2RT$qVGt:nKKKލ,iiLjjԌىYƿGeiU%5Baj$2Lu 0"'#Gvo<*ந(7ʯZ~i}8^m]_V;1/ɧ39x;=XKiam2/5' jr,goUVQT֡CNىS XS)#)qUԾ[T8NAXc~ ȷDFeC;?mn/ /ϝ4=()N? 36?mAeDōjU QETA9P5LMyX]nPyV-U?v)m. w8Fٹg^_yO-M {"zz%OrbdgeVS4֨j~1 !-x8bG:#H>/ll'[3ëz7C|V0Y c+y%i|#Ba2&.1,1CuE)SdG;+Z^ eeg:e3NiZ8l9%o߯3W߁tXR7F=~=~]JuZΩqw@ڨ.` 6Ý|.q?2=\~&3v:=E|CVt^\Jp&ټц6 mѶq͎N0_k즖b.G:oedwe5]h8x"EBYJKJ+!I%$4DӗrKE6-\BӦѰAD(|1_7=<3hE(A3c^ffG>@[*040, ؏yH+@(0]t#V\2($G

z[ stD^a._^ј/88LyR6QehSMUFUi#uZKsR$A,!G(ɖ-dJ"D 6p݂Iz:4m|eR.`۠6ݝ#G_9rR\4ȖW]}jZm>td;n9{o||rp+o.|7ELa-'q`M.$A!%C.z=<:O޻.݊TTy663Ss2c.لYF pajv< ܅oS}7&÷ \u?b?:bNKB3888A;%)!eNlEefZm&FӀp3`"o+ϰ[ +oe[q9mkLLVqLEI`>O))&9M3riUKk?Ɯ'~Ude/sF_]41~:-`ȴ0B쮆#_D_!]`\+VVmNk2LnYetgꕀ3$pK`1jI[B\px!u88ùp9+X@uuVDc+&& ڂ`GrCרd G3:, Ev|(Q,Li}7ٔ?4pNq`V~B]y6W]R?oelgsլ8c_rג{UU|a̒0yb "r myU@/bDC1*RBRHRHQ͊e`W(L1ݱ/pG>w{ؚ$o&m,RSZd6:G`بYZ]V(q489z<yuXWvu#-ܩ6TL2Y>1+ =P E"O>:R*F%Tx"Xj R;^,%ɤQkBFI^r*q=HZ 4Z{ 7Yߓ%W+EH/z*(+{l ;~˔y`&L3dO5#\trDc_"⎟NNvq(1A E@(%-Cp3\(Ij@NԷZ}j4!LJE'I%`#vaDj1Ux؎E̳Qj P^8 >Zu57+LٺY*8FϪƜ 3?Ɇ`=|g.G|debFf1ohBȗjT^Յ**# ATśKf֨j=s:Bp)i=#@t~ćP7E7y)3PL@4\ PDZQwCj8)4G(!3 fƖcE#*0TG%{_yH+?g+JKn9)7[ [aKZ }my9=9$Z %ťqdsBIڗOHIIl7X(]gS&ZdȘ1  \yRV2>oz]oFRJ^׫h MJSRciZxɨqb:ǻ<`A,`3g3J0P7-M7Moh~pɁ#/`/F^U?șw:e^ _pҍS S3;7 |Rd3,)rG0k%F}֘ť5`0ddeY؇6:|4x"Ǝh9gkcl:&鄂›;nm/lqɑCؗf^ (O8ngLL lxJXX RDH=&AǼ@9l= ɸ5V!eU0`%jic#LS'dYCy/Rewl^6߮6ݔLnOhU0vHGY-YMoT_, m kz{=i~9\H-03ofK#F3Ff2o04 fsW"w% Ofq!8JKRM2%J@u?3li;a2|gq6g7#`W=H-ޜ"}fOՖ֪9]|_M8#G~L{"ad~NNg՜ʊ= _;“;f==>JA+J@{-T[-4{ mͶuVWڂWz1f g08b4V̙q181`.0LnoJt$K^g7ob~UB*gfeC+>|V7m6o)f+kr!p|/DAl5^ &IBBHz3a!ylr+}C ?hrO#Ø?Ld\~?#M{t\Jxyn\B/%F&mVhWkoԮV "Ns1q a FDW f_!7yܷ#U֦LurMa <.>OdޫKzsU{>*{io 424PdCQy4ՅP 2S_d].Q"19@yI]+Y?OW?y@K{״HvK?{a6.ot_yJ͉ۮ6.+?ʓ YhXFHerF-kRz111!u:WZkeO bmyAsF= &G9kNh )OhTEoVE> s+ΎxOw͟^{->[;^rbwF3wF>ױ*;3 n{KՓV[༧_0rbXSᴢȫ4`DIm$a ؘ֠[ Hn,VK:Ac8TapcΚbg=Ϊʿ8#r^4}̙/;/4pӀ@ɒ/H ٶڂcw@;[ @ ^.Y.CqͨX*B;u 509ltht,8Gω[Q׉49_8fhݞq^_зjǭS/\2;XY!?weYjqnE]&9?^^0Kq_((H?a$u,hmճ.8 6 |M7tY rt<נrrTDz1 YzR1HVGA+nf Wt&"Iꘇl%N5&$*uZ&}nH 6s`ׯWbV>BclJ =k-;`%/zl%] rk>}T̮r6y+|Yf[r}}(Z?πl' f*(%.RJ&d.-5"\AfNT*ZP˶!b0`'<.vBHEGx*C]JF"D5VPs Rz>^H|nz5Y {46F͒K)UAIP!/9 }4H*:M`Èԃ\eێޠI_+0P\ 6v2Tv[E 9%  ]}4pŐJ[sجgqM9(] lQQ*\%Vj-J,xV'| Ƴ~YS5`p68_+q\%IyS//"_Ɋ__ (6~з",  JkQXSDvd-C2@3IEQ2H "*jh.Uv(3ƙb:z驛Iܫ6!t)Zmoѓtbs1$!̡q,..}S1pPthe{좫6]md'I '>'z;V,{q AH~Oz3ƛHZe!ηvIb'ww$ gܪ =kn``p'CWԃqgxTc1)x@ѵ0S/a$t<+H*^xXo: ؈ N`ִh0^2B8Utcj OB.-o7)q}w}e~=u3#$p1/Ӣ.LE.4ΦhrdRluQ.R/QK.iZǍ?Wz [*e=x7CbX(Vyb7Ke@2&!NMx5sZQ#8# /l8yo3a$f暞x!|۞c19y3W5&rf AVq"{$5b5H)\5J"X `{QWy:?eՠLը'UDբ4/m;Z|g ,f=h^px槟}# I#t#8ن1E?<"">9(=&2!mF?Oi=HjA35}C_5'_7ơ-pW*\p5^5w^|ZTA[zT-;E%H䷣\gy!aRԱVBӃ>~ܷlk(;Fq^ܳC܏(RJSDe _DX:>j if {=(\<r@݇~7%}tv>Yġ~9uN?w>AIsκa>rFp" n9CH1?9f?A#Ur%].Pi.h11[ͽ?[vZIևm#l3q޶?)لʄW%t9.Y?q^2tSWgԤ x`ݣEh4 gaNL!gb#bǩ hR h$ң1,@ N*ıeF=x QC)3fc!Xt-΍J1*JI_Y ,7Cy"U1%`œ`ߊ"I>3=ڬH51CijB>9(U̡xY@( s&(*͌ 7_mJ1ߥqJ1GMPy?zP`+ hYyF_nX^Z?rӥj'+ߥ{\(g1@AsNhRrg_u b8]h*G oO֫ÉJv~Z>`XX](_K`GE} ߜCA] ]  <È^+W8\.{n*se(ͯSgӣ >{ƍ?O΂!xh6?r}DGƏ>?( 4ŬOhDZ|H2G-!8??r~ZOԞhs~p;ny{ﻝ|83C7F77!pyw~$y'Mvy$p^ud퓝Wnrn^ Λ$:/2ҹuKwK-p[ƌ-޺ܴaschS0xC(˹^B뫜X^?8mt䶦6hp;l9NQp;su;-\CWmԧR=zې;u :[]gXuI鵒ZDra56,lL7Pb@e!J. 'hUNCI*'rqy2\WgVN>BS ڙ1 R0.?Da1N`[ !aˎ!ɛ6yZc_0;[-\ѵb 9J~mSy믔T[_owb(\]JЊ.o]XMO endstream endobj 1193 0 obj <> stream xګ?b~ endstream endobj 1194 0 obj <> stream xyxU(|N}_j$@6&AHI {Xi"$! BEeAl:.363ی |ꄀ\RUNݗSՀ0BHA=FIMG5/-pj#cb2}~TGLS˵`FzSUQZIfT_)_.U񾈐hGtbZmY)j|oDzg*^텚= 9{Ukz !n."EqPNʕJƪaa+H*[aT/J0f ٿK1SJ>}}:;2r as|Av4֫jkRKZA'~%G|:s[znCQ8qg\ڄx/E=0be4 7aJPZa|4 }W=f!?pڋ18oh0O0,aA0I Rmcœ!hzJ3;>Rǜ`-h+UI6s:_Dsf8ҷ~ CQ. U37u".p-"dn `uDmL{;̽b~![웲Ľ+-?x & Ǝ=*Æw_nNĬۧ=23z$'uMhi5jϱ(I㒜0,i^rNN疄R! 6ޟ'WKBKi꒰-+h)*-,E}~!|1/4 :ro pA* ΝUՔS0C: mr:AQpW!ܵ? Lל>6iӜpœlLN6Gh9Q@4=i^Sfs+KÍARa<>"N mjpyHЫcڥ,\qr9%YUn@B%*00,fCA,p,PTQZ ΖNׅܥ`T)D]#©9^ 9M% t,(zPOB y06v)i*, {KꐈPx 򱅇 *<iȵ F7tp{5OYB/kHSaT(ufexy"1UmYS+urBdբF3sӪPo^c^fxH#zBT \^pk /t0@Vrr*(UM%Al ?&ׇa ϢYJ=OU ؉{#>?@%s&7SA0*M/2BBG*Zaԋ-Vܻ%` X|f]o[tN(0lyT5Å{Y+NcZO$#`mrYĹsrh2!] y!qSk,zj2XfwzcU,b1byD[|jVo v†d2Pl`FZHK嚅XDo<`\6Pj +` f9q⌉3D G2M\pIcu\5sFF-@zYšqңckƞ۠*XS()|ESҫӤ*zL)%j*C[C|5%+Vt݀\UVYc<dE`!us11nSՕt:t=Ƭ5 G/;5au 8qw@ u$@jb"x;U="COVj.w;r3^eIHa2zf9;U NlO1;FiBc>>?7t>yg[ON0{"fO6yOjv2`Un'=j"}TҸyaRzx\EKznft?Q@]#Fq( $?CǬ>S'^Ht{1(x pҸ_ cE*G@DgEA@i Dʏyx;@z&'{6܉=Vް { 8p}oj)=O Ϟ>unC]AƓ 70΢Iӱ4Ye4i$UVZg,fk0gNyfϫg7RիeB|UiMp>?m|VKXVʟiJf>uk{v݌]tI0z|09I=2&3b _gԼFϪթUTDzE>O2 D%y"(D66KD\*N׋#fV'K_y?N3a (`YPjDzPq>Yz  ?]H8P\8Ioٹ+ rAߑ lX1%:JozģN&76nMQ(AFc 5*Ik'M8 lxۜhLؗn%m@5l;~[7V~zƝ;6I_3OJKp' ғӸ3&HPL{f*,#GdXQTJE# My.[@6YFz^T ⤯nªOeDæEe7ih2cTvS`hCA G[92gܫ?ΐ*?;`XsK{UM oϾ\cޝ95 N}:}m7p5\,q@B`_RX҅11)jZBAJ|:|OE4juNei-{S<'c-{. !8#;a/RlZh{iqkG/Y<{g[.=auSzm]uskϝ}r| x++&9Ϩ5 6gCA5g{Z=cc"ds2]P }GZꙇtBZ'8Kzg"so._C E QnaU' Pnx̡:P %j5+Ӹ(NMNS(iezBAM&Д:m^x{^9x~V8ZtwBtyyObg4~4p灼8m%6t..qvb;Fvni}],d՟Q:,X`SCEÈU 12^xlЙ{lG` >ϓ= }uKv=6l xPr x#Ԩ9v[gjs D_˾dI+%x=hc^rdp BЉ|F 7mЦM{6yRYj!%I31м^A1~1\kJ.R&MO9|(G}>Ml,r-P;5OlX=l˦vu۹@TgzgQf@:i4Luݱ|>cs4ֽuח2WnF )5}?ʍ)4sfP^}`Vym4r)$C@ (cNܿUDgt4uXM:XW[t Kj%޽{T TD%&r[Ɏ-w{eJ}++@@SA3sqh,Knd@Xi3W<'<ѐ֦ 3uvȈ1><Dpg{zxT:,"}{S>tm*<aIX,EݑP,h7 d o,͌D2!ӭltQTZ{xЙ%&,IG?`L/:dSƋFVBKuq˥r NY\1;]T^A &HSD;sU yɖrksKJ-> p84h9W3<<&<cPY`\`-cNB`8]`[SOG'8؁2{Z?MbI'Z>Q F-PGz]2XܮͨN2 -fl.R9` dhI):;*]jB濽o.ސ"}//y \IGM-tp˼"U#cuz lD Ti䣹e#z*a ]<ӧie=rea.,[*EFo`* O:KF9<%ɸV[&x!b:^-bM jzes'?|;C5J7exFIQzX :KY@M@MeM#A*D*ڒ'}&f>)H[jy`~yE#-]L@uj7\΍ۡBKs47t"VlfhItәlͭgDђgS&bl\Yr #teaH>BDO[G;9HN:7Rl`i~1'ݛ2OXEPbYtzNo4Va<jxXgq%85DUYS`ATd[~61[S (f"RBggP%s6,˒ӥYҰV$ߵgsJ?"ٖc9= Ai(ß3Aʻ,_6S#3ϫa`MA5;8Gdl>bK?/|_ңϒCV"q9Z /=ΐ]ш< !:ۣv d0t|IXuHɒmTq):Ǐ*W/hocݖV;`Y~[j}"J_oXwމ˰;dShX$(3z=1j3Vr#dͲZO[Y9=ZYdmnnS[i+@bM;Ii÷񺟥ؽ1&.#^ny\,uo2> 蜄]yS'&tG($ةSKE_0<ذFʨ D6ft݉IҨBpcW,VI?"r<&qS.޵bt>{J /2䬜[/ʸ3tXP3乗7}u&X}GP|Eb>* dbXJ[Hj߾`xJa{ngm} 'Z4 4j3RmGe+ ,h9?~xz]Nᯤ~c2svy9 zaebg4ZFkRlGJdrԖQ1v2{suIuތI9.q<,Us** I4ӥh\(6<\l&f!vC6!"}@) O?#<Ұ,@5ǪԬڠG³XZˢzw𫑤 :4`*pEIZy$ H2%* H{8SyHFቈQ "YX*%gbM-2F0b.Y"1--3e0`k7fѬpZ*" TwF)ۨ w*.:Ioq7/ҵl7>?mƓGCHOA)<ɦh:!AMG먠ժ1EF]HTTL3?cN s%tVbqmn-`նbQ\z܏8Nvx/"ph;W6̪ҞHs8׽僒MO͚UՙL=O{ZpI)Lѣ)/o}b8o:n6 x9BѢ8ܶYI7Siaf<F<a٢ZG,t>lQ~#F˅+>ؓE=hT%mvd0m%:[팍9ǃXPdK6 #vrhM.6Nm&ѴY!v;i&t(]0![3ȤsΟ<0G,K7Z.Nf2MނaۗijH>y/%S^Zہ#$( *fS'ƍnZ_Fpv)Go_#p/EYZVMDO^~兩9&/K؊u+}*]vw>l4Gb3aVn""Arۈ;a*@ͿgK&n%D]<`P)Ukdޮ Xv(hP*%&ttvi4^Gdfcdt U~P`{ Rc! tȽ:|PЖ_Z2(+އF13efˌfҞc]L2Q6/^170`aTش0j(|)S1`]uiZ}y땏O_r0ǁT~#Xfkuvi:T 2#$J6qT'q ͽ颴%9ZVSQP_ѫ1)vLP@J L.6hMd ×@'w;~Zzk֬!k9sFә߲aN3`)XvZdLDyr9o*kJ,d_yk56I7ވyh˪Ώ&Tfj_'vZĢ(k,tI@&pc`!j&KBeݵbi#GߕKR-wf)cR[ /O-q#2i;]NW+! QҚ=DnG)6rkX{nRdMS͚E^`r# (GLH@HƚjMk7?kE;M6F;;,%3!rW."*[q>Q\5pZ[0roڀÙ>tfO.2d=*'Op rPw/sۍREEn;*N!S dʠrY! m"NzٖT=FQ/ͥk?=m֭۱r7{;xv 3iKQwusx pjMg[0NK5Pz_{?}OGhvG3DO': >hu<(qJBofS;~XnMcTA(d<1)囖ΙxJvH8v>*pv0-WӅ_ CuFWNfcFmfw_u]vT@uԕz'ٮj.J˜v:â3 ;]ţbwEG!lBWI ft$:iaBζU[vM}S# }3߾&ű 埗.շl\!f{D=81~rh•q#GF R;fKlv1STu 7h)z8MNE2B_+R-mOYS- dB7Sl@CH `ջa^aL ;"yu0o/<l?ӊ3g1gy0O1#HxNg%:rGUQ*O41u(Zefsgoiay$#1@zamo;<ї`["IEʖ]wfiE12t[G~,$:B-Y5g"n S =iYC 'ރOHLcS-?Cg ޢǪ12F٢j-QZ0wV!t.CSFa"U7yJ'xZ[ZƦ̿[C7^L@$E^{Pf@0:&&rǵ@҃c#e2yk_+a8 hn;cպXGH8ꧠI^~K}MYZm-?!|J@dAlׂؔC6?4;H̢=.Zy(qJVpspɊW> ==(ƽq ؤqy ? !~Ů c{.ԎBO b! Op\8'H{R=k==oyyx xlf)hsv)6wN9#F9Q5KvQY$_*7ͥxBOvV:̙*Z0Ɩ=`S9]\PDWL5<m:%6_LLLo6ݥ+k8Td. r^X8a@-IH {|RtrԵcoz[R<ʖ3AV(W:bc:H% t= c9T}ҝA.tjO~98jyؖKFWfL 4zxƛq-qߩ#r7-Џx3׹w }ǟ|od$/3ȃq8 z4mBP#h1m8'$ۍfQߠp#0@]`6%72E Fn<83U2=NIFcivwnw۶ߩQ#ۢdnw m"Y4G~71dʙfWb'IdKI?lwO7oUDNzffSmvY~vKz~~!0Qoo3^0MM L殰6hgoemmUݶK*_K_9;9w:o]aݽ}~wwv}jQOG w~wޯ*{t }wFyAfG'D}8| E RHh8RfͩHCU##㌔Uh.Djd'g"e 2"e-m}u(FHYR4Hـ24mQ6Bj -cd2A=H6ODr)RQ 9RVHY͑Ő#e-%D:tzRGF4U30R6Q6FShc.@HKTjQVUP+P JC@AZx> h=֢>Z:FGȓ{'Ai0/PvByiCPV[7zJUе#p_mi ҆ښ; a҆$apM; vX@k-<\ & 4.>htŔJ0 U.&d87UԔW o& 8me:P- xTQ SR2~Q  4O(e<u2SvI|W.J.cVrOJyߙq$X d1lkY&MYULp Qa@P*4ԗWL/@])աz RƤ 5 BiM0 6TάWB)'HU#,>tP1B^PBP c\3e)zʴ@2J*\*3\jrMdmN.DFFYfEfP)C50R5 -e[P2kKeAQs:-%Nr)dC&ĚGdBX]J UOK:2 c\Ȏ^D<>p ^ p H=F>RItPjӠ_5áԦB-\8HR;ipa q~j laA0@g}qJj?w~]nw ow|{[R{m55^+V{UFun{cq>>⧹N߮zO_y+D̽v[a^G .~V i|8pƀ ci-T |QGXGmG[j ^%Wupǩ3HݩSz"D퉃'.?{47576s1ͶncX8Xx4|1µH36ua&>~;LRfdv>~910;g`&XE^n;yls[- fgL.Ehݵw ~}A\sqصktpMD)-WIo5mLݘqk9KXj^ Ǵz/=auLּVXK`;&WXc 3ruդ*lZ]̶\i,t v iA7sW.׻|Y?GziX͏xX,">7᪁# UxV +Xu+D-&w҄'Bmi[( !N ! \z$w mJiR(M ɷ R`imRH46 endstream endobj 1112 0 obj <> stream x\ے}W[r)ĥKU֊HdJKˬZ-U\ʱ>1.9^C, pq8@k\]p8κܹ:Cy/ԑAd; Q2PǞp`mOdXKqw7x|-S E]*8f$<,b6Xf)k'K xw5w6yYr1>H5#n6H<){$xB<|*P*8`).La@$P,I]x2 3IW[RuCqTmK$ze2WHA?b@ BU $ )P,VF.Vy4魊YyȉQ#o G*)&#1Q+F(F J%d9͔$Bdžc6d%Y4 v'$^B bFm 9($ƒAB!9{aGJCʠj] HGKˣ6  r؂ 2 A83CY-IJbhh'1R5II.: /—$R V(R rT a¥XQLL@gd |̸fA]cNE$QFC&/4!@Z"PhD}w]$)u)piWȅRAq) (Hb(O*lJMAa.fb \lb q.YHB1D @$(!`r͒3NY n,Fc!F|VZ%eIz)WEF'I@!pjfJЄBZ(œt,Y:.νAET"T㋇{C5--/ _-`+)\HW|9G!gH*zǂI$%tA[DQIe(]C .^ TZ^y!2 =}œЍ 2HAJ PzE hC=g>\Ξ//g֟fDMb 夌8JX^?m-q=;=RW[\8 m3D4 CW* ?Bv !46$LC$ )t{RLV1$V r;DȮ"SHTi1P1tckgDX[׍oؾ=zL{7C1 Cx"CV/9&tz @ a!:$p*4TCTpflȴ XipVv:?5$D t @%nnc›F 離BEx cBQ22KhU;<ף +BQ2:jQ=*ɺf`nPS;D<iٝkgI7~n8@nS] ([v*Kq:]SƣhP4%vEo QczT4ǣhT4%vtJƪ%QђjIo P"Bђ!)M%v-1{0@Ki!~PГՎǣhV:~v֎ߏ=ggЧEdL;DV |+֎@C! iCcCXӳ"~-]R R;ĴΜBG}Au'[#i!~N(3qrqݼ!BI,i9.yl"7Cx@v4T臃=lUȌ Q\3)JE'vpߴ!:vlBA(aa1BU:jlCOԐay xn1Dh}/BUZY= @Cz s C9!T)H311"z s N#V) ) gJ,Cz,s (CS許 XR8MCh0aB"nx]w.~#=<񀬄GG}{AJxzxt   5< DnGã#hR R;NSι~}>4±o\bjW)Rl03OT֣ q]1Qmx5TY5mG +QQ1Cu?P\dӣ>Q>25fvRjQ\Gm&=YOy3+Nw$ af, @J7Cת!yCtP<>ƃcP v!b}@C @Q!%K"SU;bxwT~l")C(JM;D>T#74$ ӏ0L?(o!80D(A%6XYiY O @0"μCƠ4泽P9=KB , RcWt.ԥpA j.!K uA_ w AQp#f*a%o54*ZW}0q(avjDwlyZ<\v. _*r]o<]ZjK ,;{^.|̓3w|nů?3NǟV뫳vy쯸E&棋_gc|WIC=^m祆+TI ]Saԣvq~/Rcoi:<4O_[[>'7$7RTsw9+E=s ?h EIDeIJ|O!23`dsCDɕ9`lcĄ*Cr]K:-T &%Ē-?ܓ=48έgF[Qh @~y!~%lon\Vb;TʠX6E=\1$[ ̰8l)%{Ivj]<"Z)%9P#0NB1N>J:#rEY :%m &r#H4e@3*{Kc"d_<~}fue CQ{p6)%{;3==zuG|)W&!3o &k_tECQ3AYs)-eK[/xu,/Jz;}[)$^__{){mǏ^<Ó=\_^Lq.1axo]3G¾X¬#s0J[eo [[\~58>󇏿=nk@XMXddU{w5P&qy{3Ӵ&/i/}߼鏯~tv)gs pqHȓnE>ߓr7';-0<' FF~2M㍟c?/i&}wA{k ^>\otfO7?oѳf«xŽvk/0;0N1T}rwOKCi|"bJ̮WVݛV>/3 endstream endobj 1197 0 obj <> stream xU_K0yTޤ` [C.mkJAIDԷsnNN/1 NXr PBfzdy.=Q`__Kml5M8Gc(PY,ܣ鴜[ ļAEkdx1gV[Onԣ ih.KqF8s@cN򌾆Zx"y5h E}Og8 endstream endobj 1198 0 obj <<79724f203d0ff3bcc2ef75c4ed9a84ab>]/Root 1 0 R/Info 2 0 R/Size 1199/W[1 3 2]/Filter/FlateDecode/Length 2770>> stream x5eϜubffub,fffff&e\);vl8U8.N%w_u==^mCBҀp oF!2b(\!D!dAQsc03+0$̀1f,av́91<1WPxoyW/ Xb1,%$Xb9,"VXb55& _ȸ.`= !6b3l-%b;l#vb7쎩{b/}B;3p RȓGȥ  ,K+zJY~/\a̮T(=*j UH9eeF|#t2Q:/)Re eB߿yK٪0tqm #~2Ca/(;&2Kar[/({o2OaNq/S( 2rPa~LRXtՇ̠U{I9Ve֍^fSN*e¾#^R*…Z^P.(\KE )nrY=/)WLrUe,\W^Qn(|\rM rW;SC/(iO?NP󼬡9JEi}E/) *Ҟ3"tg/(5c+\ԒNrRG:8W)u =\HkxN/Nr@zyIi$=m~4rDz;/w(ͥyKi!}{Vgܧ>O?(mN&ܶZo {yL }wJ's~}u~z"%sJwER](P//)=N+J/EyxHWQyK駨*O-=L{VCzE5ye^" Ez)%2LQC^2PSn/2RQKf(E:yBh3/Y)cdS4 2Q ^rR&)K.4EKZxMh/y(3mK^,E[{IV|^2O+@/) ]}e0e "X)׏)1=eZJчǼV /)k}6K:EO e)}r IMZKfE ^*R(wn/([2e>RKqKUnITQu}sexI9HQ/(Kma.yC9e/u)NB9n/(^SN+nKY f|1 vg4\P%q6\R㚗ˊ{҂rEqݕ~H_YƭoM0~< xlxKx f3.gKK ;Sb̀O >_銯!X 2vTW^xW{&]vzCsWky(ḋǸBXcEXKai(e,Vf\+beʬ]Xb}f2nͱ =cw0|`W+;qw쁽mqq̎d<'DS8fLhߚEk.%Ӂc2O=Ѯ8v+eb.s ڞW ?h{)qܓ0#f,*>+f옃W1f)='hO[ḋTu7S%0k׺ x홹 N”F̮a YVvd, s0kRN̅rO|Yz <4A`f- 1FaMmhw݇ V֡PqI bvىp7~t;}3߇EvJbQ,űX+`Y,"VJX`U5&hu1ac !6fbsl- b;#vBb7쎩{b/}/ڎҁ8mvbmm{mumמ-7k/jjj jG:_7A۩=LDôI{nv܍gp?xo9v9y1>C[ۺ5(ibe_ZVʶεUmibhVR/hF--vĮ8{`Cp 8'-C^R\cFMۯI]Aٳ)۝4sݰW-I)ڻ9xSG/woc5x{J1y}{?X?ȻW.{ڹүu^޲.%-*/j endstream endobj startxref 293687 %%EOF instead-3.5.2+dfsg/doc/stead3-en.tex000066400000000000000000000025651467622671600171720ustar00rootroot00000000000000\documentclass[12pt,]{book} \usepackage{cmap} \usepackage{tocloft} \usepackage[T2A]{fontenc} % \usepackage[english,russian]{babel} \usepackage{indentfirst} % \usepackage[russian]{datetime} \usepackage{upquote} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex % \usepackage[utf8]{inputenc} \else % if luatex or xelatex \usepackage{fontspec} \ifxetex \usepackage{xltxtra,xunicode} \fi \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \newcommand{\euro}{€} \setmainfont{Verdana} \setsansfont{Verdana} \setmonofont{Liberation Mono} \fi \ifxetex \usepackage[setpagesize=false, % page size defined by xetex unicode=false, % unicode breaks when used with xetex xetex]{hyperref} \else \usepackage[unicode=true]{hyperref} \fi \hypersetup{breaklinks=true, bookmarks=true, pdfauthor={}, pdftitle={STEAD3}, colorlinks=true, urlcolor=blue, linkcolor=magenta, pdfborder={0 0 0}} \setcounter{tocdepth}{3} \setcounter{secnumdepth}{3} \title{STEAD3} \author{Peter Kosyh} \date{\today} \sloppy \begin{document} \maketitle { \hypersetup{linkcolor=black} \renewcommand{\contentsname}{Table of contents} \tableofcontents \clearpage } \input{stead3-manual-en.tex} \end{document} instead-3.5.2+dfsg/doc/stead3-ru.md000066400000000000000000010162331467622671600170140ustar00rootroot00000000000000## Общие сведения Код игр под INSTEAD пишется на языке Lua (5.1), поэтому, знание этого языка полезно, хотя и не необходимо. Ядро движка также написано на lua, поэтому знание Lua может быть полезным для углублённого понимания принципов его работы, конечно, при условии, если вам интересно этим заниматься. За время своего развития, INSTEAD получил множество новых функций. Теперь с его помощью можно делать игры разных жанров (от аркад, до игр с текстовым вводом). А также, в INSTEAD можно запускать игры, написанные на некоторых других движках, но основой INSTEAD остаётся первоначальное ядро, которое ориентировано на создание тексто-графических приключенческих игр. В данной документации описана именно эта базовая часть, изучение которой необходимо даже в том случае, если вы хотите написать что-то другое... Начните своё изучение INSTEAD с написания простой игры! В феврале 2017 года, после 8 лет разработки, INSTEAD (версия 3.0) вышел с поддержкой нового ядра STEAD3. Старое ядро получило название STEAD2. INSTEAD поддерживает работу игр, написанных как на STEAD2, так и на STEAD3. Это руководство описывает STEAD3. Если у вас возникают вопросы, вы можете посетить сайт INSTEAD: https://instead-hub.github.io Или подключиться к чату на gitter: https://gitter.im/instead-hub/instead ### История создания Когда мы говорим "текстовое приключение" у большинства людей возникает один из двух привычных образов. Это либо текст с кнопками действий, например: Вы видите перед собой стол. На столе лежит яблоко. Что делать? 1) Взять яблоко 2) Отойти от стола Или, гораздо реже, это классические игры с текстовым вводом, где для управления игрой необходимо было вводить действия с клавиатуры. Вы на кухне. Тут есть стол. > осмотреть стол. На столе есть яблоко. У обоих подходов есть свои преимущества и недостатки. Если говорить про первый подход, то он близок к жанру книг-игр и удобен больше для литературных текстов, которые описывают _события_, происходящие с главным героем, и не очень удобен для создания классических квестов, где главный герой исследует _смоделированный_ в игре _мир_, свободно перемещаясь по нему и взаимодействуя с объектами этого мира. Второй подход моделирует мир, но требует значительных усилий от автора игры, и, что более важно, более подготовленного игрока. Особенно, когда мы имеем дело с русским языком. Проект INSTEAD был создан для написания другого типа игр, которые совмещают преимущества обоих подходов, одновременно пытаясь избежать их недостатков. Мир игры на INSTEAD моделируется как при втором подходе, то есть в игре есть места (сцены или комнаты) которые может посещать главный герой и объекты, с которыми он взаимодействует (включая живых персонажей). Игрок свободно изучает мир и манипулирует объектами. Причём, действия с объектами не прописаны в виде явных пунктов меню, а скорее напоминают классические графические квесты в стиле 90-х. На самом деле, в INSTEAD есть множество незаметных на первый взгляд вещей, которые направлены на развитие выбранного подхода, и который делает процесс игры максимально динамичным и непохожим на привычные "текстовые квесты". Это подтверждается в том числе и тем, что на движке было выпущено множество замечательных игр, интерес к которым проявляют не только любители текстовых игр как таковых, но и люди не знакомые с данным жанром. Перед изучением данного руководства, я рекомендую поиграть в классические игры INSTEAD, чтобы понять, о чём идёт речь. С другой стороны, раз вы здесь, то, наверное, вы уже сделали это. Правда, не стоит пока изучать код этих игр, так как старые игры очень часто написаны неоптимально, с использованием устаревших конструкций. Текущая версия INSTEAD позволяет реализовывать код лаконичнее, проще и понятнее. Об этом и рассказывается в данном документе. Если вас интересует история создания движка, то вы можете прочитать статью о том, как всё начиналось: https://instead-hub.github.io/article/2010-05-09-history/ ### Как выглядит классическая INSTEAD игра Итак, как выглядит классическая INSTEAD игра? _Главное окно_ игры содержит описательную часть, информацию о статической и динамической части сцены, активные события и картинку сцены (в графическом интерпретаторе) с возможными переходами в другие сцены. _Описательная часть сцены_ отображается только один раз, при показе сцены, или при явном осмотре сцены (в графическом интерпретаторе -- _Статическая часть сцены_ содержит информацию о статических объектах сцены (обычно, это декорации) и отображается всегда. Эта часть написана автором игры. _Динамическая часть сцены_ составлена из описаний объектов сцены, которые присутствуют в данный момент на сцене. Эта часть генерируется автоматически и отображается всегда. Обычно, в ней представлены объекты, которые могут менять своё местоположение. Игроку доступны объекты, доступные на любой сцене -- _инвентарь_. Игрок может взаимодействовать с объектами инвентаря и действовать объектами инвентаря на другие объекты сцены или инвентаря. > Следует отметить, что понятие инвентаря является условным. Например, > в "инвентаре" могут находиться такие объекты как "открыть", > "осмотреть", "использовать" и т.д. _Действиями_ игрока могут быть: - осмотр сцены; - действие на объект сцены; - действие на объект инвентаря; - действие объектом инвентаря на объект инвентаря; - действие объектом инвентаря на объект сцены; - переход в другую сцену. ### Как создавать игру Игра представляет из себя каталог, в котором должен находиться скрипт (текстовый файл) main3.lua. (Обратите внимание, наличие файла main3.lua означает, что вы пишите игру на STEAD3!) Другие ресурсы игры (скрипты на lua, графика и музыка) должны находиться в рамках этого каталога. Все ссылки на ресурсы делаются относительно текущего каталога -- каталога игры. В начале файла main3.lua может быть определён заголовок, состоящий из тегов (строк специального вида). Теги должны начинаться с символов: два минуса. -- Два минуса -- это комментарий с точки зрения Lua. На данный момент существуют следующие теги. Тег $Name: содержит название игры в кодировке UTF-8. Пример использования тега: -- $Name: Самая интересная игра!$ Затем следует (желательно) задать версию игры: -- $Version: 0.5$ И указать авторство: -- $Author: Анонимный любитель текстовых приключений$ Дополнительную информацию об игре, можно задать тегом Info: -- $Info: Это ремейк старой игры\nС ZX specturm$ Обратите внимание на \n в Info, это станет переводом строки, когда вы выберете пункт "Информация" в INSTEAD. Если вы разрабатываете игру в Windows, то убедитесь, что ваш редактор поддерживает кодировку UTF-8 _без BOM_. Именно эту кодировку следует использовать при написании игры! Далее, обычно следует указать модули, которые требуются игре. О модулях будет рассказано отдельно. require "fmt" -- некоторые функции форматирования fmt.para = true -- включить режим параграфов (отступы) Кроме того, обычно стоит определить обработчики по умолчанию: game.act, game.use, game.inv, о которых также будет рассказано ниже. game.act = 'Не работает.'; game.use = 'Это не поможет.'; game.inv = 'Зачем мне это?'; _Инициализацию_ игры следует описывать в функции init, которая вызывается движком в самом начале. В этой функции удобно инициализировать состояние игрока на начало игры, или какие-то другие действия, нужные для первоначальной настройки мира игры. Впрочем, функция ''init'' может быть и не нужна. function init() -- добавим в инвентарь нож и бумагу take 'нож' take 'бумага' end После того как игра проинициализирована, выполняется запуск игры. Вы можете определить функцию start(), которая запускается непосредственно перед запуском игры. Это значит, например, что в случае загрузки сохранённой игры, start() вызовется после того, как сохранение будет прочитано, function start(load) -- восстановить состояние? if load then dprint "Это загрузка состояния." else dprint "Это старт игры." end -- нам сейчас не нужно ничего делать end Графический интерпретатор ищет доступные игры в каталоге games. Unix-версия интерпретатора, кроме этого каталога, просматривает также игры в каталоге ~/.instead/games. Windows-версия: %LOCALAPPDATA%\instead\games (ниже Vista: Documents and Settings\USER\Local Settings\Application Data\instead\games). В Windows- и standalone-Unix-версии игры ищутся в каталоге ./appdata/games, если он существует. В некоторых сборках INSTEAD (в Windows, в Linux если проект собран с gtk и др.) можно открывать игру по любому пути из меню "Выбор игры". Либо, нажать f4. Если в каталоге с играми присутствует только одна игра, INSTEAD запустит её автоматически, это удобно, если вы хотите распространять свою игру вместе с движком. Таким образом, вы кладёте игру в свой каталог и запускаете INSTEAD. __Важно!__ При написании игры, настоятельно рекомендуется использовать отступы для оформления кода игры, как это сделано в примере из данного руководства, этим самым вы сократите количество ошибок и сделаете свой код наглядней! Ниже приводится минимальный шаблон для вашей первой игры: ``` -- $Name: Моя первая игра$ -- $Version: 0.1$ -- $Author: Анонимный автор$ require "fmt" fmt.para = true game.act = 'Гм...'; game.use = 'Не сработает.'; game.inv = 'Зачем это мне?'; function init() -- инициализация, если она нужна end ``` ### Основы отладки Во время отладки (проверки работоспособности вашей игры) удобно, чтобы INSTEAD был запущен с параметром -debug, тогда в случае ошибок будет показана более подробная информация о проблеме в виде стека вызовов. Параметр -debug можно задать в ярлыке (если вы работаете в Windows), а для других систем, я думаю вы и так знаете как передавать параметры командной строки. Кроме того, в режиме -debug автоматически подключается отладчик. Вы можете активировать его с помощью клавиш ctrl-d или f7. Вы можете подключить отладчик и явно указав: require "dbg" В коде вашей игры. При отладке игры обычно нужно часто сохранять игру и загружать состояние игры. Вы можете использовать стандартный механизм сохранений через меню (или по клавишам f2/f3), или воспользоваться быстрым сохранением/загрузкой (клавиши f8/f9). В режиме '-debug' вы можете перезапускать игру клавишами 'alt-r'. В комбинации с f8/f9 это даёт возможность быстро посмотреть изменения в игре после её правки. > Внимание! Если вы просто перезапустите INSTEAD, то скорее всего > увидите старое состояние игры, так как по умолчанию работает режим > автозагрузки автосохранения! Либо отключите эту настройку в меню > (автосохранение), либо явно перезапускайте игру после правок. > Перезапуск возможен через меню (начать заново) или 'alt-r' в режиме > '-debug' как это описано выше. В режиме '-debug' Windows-версия INSTEAD создаёт консольное окно (в Unix версии, если вы запускаете INSTEAD из консоли, вывод будет направлен в неё) в которое будет осуществляться вывод ошибок. Кроме того, используя функцию 'print()', вы сможете порождать свои сообщения с отладочным выводом. Например: ``` act = function(s) print ("Act is here! "); ... end; ``` Не пугайтесь, когда вы прочитаете всё руководство и начнёте писать свою игру, вы, скорее всего, взглянете на этот пример с большим воодушевлением. Вы также можете использовать функцию dprint(), которая посылает вывод в окно отладчика, и вы сможете посмотреть его при входе в режим отладки. ``` act = function(s) dprint ("Act is here! "); ... end; ``` Во время отладки бывает удобно изучать файлы сохранений, которые содержат состояние переменных игры. Чтобы не искать каждый раз файлы сохранений, создайте каталог saves в директории с вашей игрой (в том каталоге, где содержится main3.lua) и игра будет сохраняться в saves. Этот механизм также будет удобен для переноса игры на другие компьютеры. Возможно (особенно, если вы пользуетесь Unix системами) вам понравится идея проверки синтаксиса ваших скриптов через запуск компилятора ''luac''. В Windows это тоже возможно, нужно только установить выполняемые файлы lua для Windows (http://luabinaries.sourceforge.net)/ и воспользоваться luac52.exe. Вы можете проверить синтаксис и с помощью INSTEAD, для этого воспользуйтесь параметром -luac: sdl-instead -debug -luac <пусть к скрипту.lua> ## Сцена _Сцена_ (или комната) -- это единица игры, в рамках которой игрок может изучать все объекты сцены и взаимодействовать с ними. Например, сценой может быть комната, в которой находится герой. Или участок леса, доступный для наблюдения. В любой игре должна быть сцена с именем ''main''. Именно с неё начнётся и ваша игра! ``` room { nam = 'main'; disp = "Главная комната"; dsc = [[Вы в большой комнате.]]; } ``` Запись означает создание объекта (так как почти все сущности в INSTEAD это объекты) main типа room (комната). Атрибут объекта nam хранит имя комнаты 'main', по которому можно обращаться к комнате из кода. Каждый объект имеет своё уникальное имя. Если вы попробуете создать два объекта с одинаковыми именами, вы получите сообщение об ошибке. Для обращения к объекту по имени, вы можете использовать следующую запись: ``` dprint("Объект: ", _'main') ``` У каждого объекта игры есть _атрибуты_ и _обработчики событий_. В данном примере есть два атрибута: nam и dsc. Атрибуты разделяются разделителем (в данном примере -- символом точка с запятой ';'). Обычно, атрибуты могут быть текстовыми строками, функциями-обработчиками и булевыми значениями. Однако, атрибут nam всегда должен быть текстовой строкой, если он задан. На самом деле, вы можете не указывать имя при создании объекта: ``` room { disp = "Главная комната"; dsc = [[Вы в большой комнате.]]; } ``` В таком случае, движок сам даст имя объекту, и это имя будет неким числом. Так как вы не знаете это число, вы не можете обратиться к объекту явно. Иногда удобно создавать безымянные объекты, например, для декораций. При создании объекта, даже если он "безымянный", вы можете создать переменную - ссылку на объект, например: ``` myroom = room { disp = "Чулан"; dsc = [[Вы в чулане.]]; } ``` Переменная myroom в таком случае становится синонимом объекта (ссылкой на сам объект). ``` dprint("Объект: ", myroom) ``` Вы можете придерживаться какого-то одного способа, или применять оба. Например, вы можете задать и имя, и переменную-ссылку: ``` main_room = room { nam = 'main'; disp = "Главная комната"; dsc = [[Вы в большой комнате.]]; } ``` Важно понять, что движок в любом случае работает с именами объектов, а переменные-ссылки -- это просто способ упростить доступ к часто используемым объектам. Поэтому, для нашей первой игры мы обязаны указать атрибут nam = 'main', чтобы создать комнату main с которой и начнётся наше приключение! В нашем примере, при показе сцены, в качестве заголовка сцены будет использован атрибут 'disp'. На самом деле, если бы мы его не задали, то в заголовке мы бы увидели 'nam'. Но nam не всегда удобно делать заголовком сцены, особенно если это строка вроде 'main', или если это числовой идентификатор, который движок присвоил объекту автоматически. Есть ещё более понятный атрибут 'title'. Если он задан, то при отображении комнаты в качестве заголовка будет указан именно он. title используется тогда, когда игрок находится _внутри_ комнаты. Во всех остальных случаях (при показе переходов в эту комнату) используется 'disp' или 'nam'. ``` mroom = room { nam = 'main'; title = 'Начало приключения'; disp = "Главная комната"; dsc = [[Вы в большой комнате.]]; } ``` Атрибут 'dsc' -- это описание сцены, которое выводится один раз при входе в сцену или при явном осмотре сцены. В нем нет описаний объектов, присутствующих в сцене. Вы можете использовать символ ',' вместо ';' для разделения атрибутов. Например: ``` room { nam = 'main', disp = 'Главная комната', dsc = 'Вы в большой комнате.', } ``` В данном примере все атрибуты -- строковые. Строка может быть записана в одинарных или двойных кавычках: ``` room { nam = 'main'; disp = 'Главная комната'; dsc = "Вы в большой комнате."; } ``` Для длинных описаний удобно использовать запись вида: ``` dsc = [[ Очень длинное описание... ]]; ``` При этом переводы строк игнорируются. Если вы хотите, чтобы в выводе описания сцены присутствовали абзацы -- используйте символ '^'. ``` dsc = [[ Первый абзац. ^^ Второй Абзац.^^ Третий абзац.^ На новой строке.]]; ``` Я рекомендую всегда использовать [[ и ]] для 'dsc'. Напомню ещё раз, что имя 'nam' объекта и его отображение (в данном случае то, как сцена будет выглядеть для игрока в виде надписи сверху) можно (и, часто, нужно!) разделять. Для этого существуют атрибуты 'disp' и 'title'. 'title' бывает только у комнат и работает как описатель, когда игрок находится внутри данной комнаты. В остальных случаях используется 'disp' (если он есть). Если 'disp' и 'title' не заданы, то считается, что отображение равняется имени. 'disp' и 'title' могут принимать значение false, в таком случае, отображения не будет. ## Объекты _Объекты_ -- это единицы сцены, с которыми взаимодействует игрок. ``` obj { nam = 'стол'; dsc = 'В комнате стоит {стол}.'; act = 'Гм... Просто стол...'; }; ``` Имя объекта ''nam'' используется при попадании его в инвентарь. Хотя, в нашем случае, стол вряд ли туда попадёт. Если у объекта определён 'disp', то при попадании в инвентарь для его отображения будет использоваться именно этот атрибут. Например: ``` obj { nam = 'стол'; disp = 'угол стола'; dsc = 'В комнате стоит {стол}.'; tak = 'Я взялся за угол стола'; inv = 'Я держусь за угол стола.'; }; ``` Всё-таки стол попал к нам в инвентарь. Вы можете скрывать отображение предмета в инвентаре, если 'disp' атрибут будет равен 'false'. 'dsc' -- описание объекта. Оно будет выведено в динамической части сцены, при наличии объекта в сцене. Фигурными скобками отображается фрагмент текста, который будет являться ссылкой в окне INSTEAD. Если объектов в сцене много, то все описания выводятся одно за другим, через пробел, 'act' -- это обработчик события, который вызывается при действии пользователя (действие на объект сцены, обычно -- клик мышкой по ссылке). Его основная задача -- вывод (возвращение) строки текста, которая станет частью событий сцены, и изменение состояния игрового мира. ## Добавляем объекты в сцену Для того, чтобы поместить в сцену объекты, существует несколько путей. Во-первых, при создании комнаты можно определить список 'obj', состоящий из имён объектов: ``` obj { -- объект с именем, но без переменной nam = 'ящик'; dsc = [[На полу я вижу {ящик}.]]; act = [[Тяжёлый!]]; } room { nam = 'main'; disp = 'Большая комната'; dsc = [[Вы в большой комнате.]]; obj = { 'ящик' }; }; ``` Теперь, при отображении сцены мы увидим объект "ящик" в динамической части. Вместо имени объекта, вы можете использовать переменную-ссылку, если только она была определена заранее: ``` apple = obj { -- объект с переменной, но без имени dsc = [[Тут есть {яблоко}.]]; act = [[Красное!!]]; } room { nam = 'main'; disp = 'Большая комната'; dsc = [[Вы в большой комнате.]]; obj = { apple }; }; ``` Альтернативной формой записи является конструкция with: ``` room { nam = 'main'; disp = 'Большая комната'; dsc = [[Вы в большой комнате.]]; }:with { 'ящик', } ``` Конструкция with позволяет избавиться от лишнего уровня вложенности в коде игры. Во-вторых, вы можете объявлять объекты прямо внутри obj или with, описывая их определение: ``` room { nam = 'main'; disp = 'Большая комната'; dsc = [[Вы в большой комнате.]]; }:with { obj { nam = 'ящик'; dsc = [[На полу я вижу {ящик}.]]; act = [[Тяжёлый!]]; } }; ``` Это удобно делать для объектов - декораций. Но в таком случае, вы не сможете создавать объекты с переменной-ссылкой. К счастью, для декораций это и не нужно. Если в комнату помещаются несколько объектов, разделяйте их ссылки запятыми, например: obj = { 'ящик', apple }; Вы можете вставлять переводы строк для наглядности, когда объектов много, например, так: ``` obj = { 'table', 'apple', 'knife', }; ``` Ещё один способ размещения предметов заключается в вызове функций, которые поместят объекты в требуемые комнаты. Он будет рассмотрен в дальнейшем. ## Декорации Объекты, которые могут быть перенесены из одной сцены в другую (или попадать в инвентарь), обычно имеют имя и/или переменную-ссылку. Так как таким образом вы всегда можете найти объект где угодно и работать с ним. Но немалую часть игрового мира составляют объекты, которые занимают конкретную локацию и служат в качестве декораций. Таких объектов может быть очень много, и более того, обычно это однотипные объекты вроде деревьев и тому подобных объектов. Для создания декораций можно использовать различные подходы. ### Один и тот же объект в нескольких комнатах Вы можете создать один объект, например, 'дерево' и помещать их в разные комнаты. ``` obj { nam = 'дерево'; dsc = [[Тут стоит {дерево}.]]; act = [[Все деревья выглядят похожими.]]; } room { nam = 'Лес'; obj = { 'дерево' }; } room { nam = 'Улица'; obj = { 'дерево' }; } ``` ### Использование тегов вместо имён Если вам не нравится придумывать уникальные имена для однотипных декоративных объектов, вы можете использовать для таких объектов теги. Теги задаются атрибутом tag и всегда начинаются с символа '#': ``` obj { tag = '#цветы'; dsc = [[Тут есть {цветы}.]] } ``` В данном примере, имя у объекта будет сформировано автоматически, но обращаться к объекту вы сможете по тегу. При этом объект будет искаться в текущей комнате. Например: ``` dprint(_'#цветы') -- ищем в текущей комнате первый объект с тегом '#цветы' ``` Теги, это в каком-то смысле, синоним локальных имён, поэтому существует альтернативная запись создания предмета с тегом: ``` obj { nam = '#цветы'; dsc = [[Тут есть {цветы}.]] } ``` Если имя у объекта начинается с символа '#', то такой объект получает тег и автоматически сгенерированное числовое имя. ### Использование атрибута сцены decor Так как декорации не меняют своё местоположение, есть смысл сделать их частью описания сцены, а не динамической области. Это делается с помощью атрибута сцены 'decor'. decor показывается всегда и его основная функция -- описание декораций сцены. ``` room { nam = 'Дом'; dsc = [[Я у себя дома.]]; decor = [[Тут я вижу много интересных вещей. Например, на {#стена|стене} висит {#картина|картина}.]]; }: with { obj { nam = '#стена'; act = [[Стена как стена!]]; }; obj { nam = '#картина'; act = [[Ван-Гог?]]; } } ``` Здесь мы видим сразу несколько приёмов: 1. В decor в виде связанного текста описаны декорации; 2. В качестве ссылок используются конструкции с явным заданием объектов, к которым они относятся {имя объекта|текст}; 3. В качестве имён объектов используются теги, чтобы не думать над их уникальностью; 4. У объектов-декораций в сцене отсутствуют атрибуты dsc, так как их роль играет decor. Конечно, вы можете комбинировать все описанные приёмы между собой в любых пропорциях. ## Объекты, связанные с другими объектами Объекты тоже могут содержать в себе атрибут 'obj' (или конструкцию 'with'). При этом, при выводе объектов, INSTEAD будет разворачивать списки последовательно. Такая техника может использоваться для создания объектов-контейнеров или просто для связывания нескольких описаний вместе. Например, поместим на стол яблоко. ``` obj { nam = 'яблоко'; dsc = [[На столе лежит {яблоко}.]]; act = 'Взять что ли?'; }; obj { nam = 'стол'; dsc = [[В комнате стоит {стол}.]]; act = 'Гм... Просто стол...'; obj = { 'яблоко' }; }; room { nam = 'Дом'; obj = { 'стол' }; } ``` При этом, в описании сцены мы увидим описание объектов 'стол' и 'яблоко', так как 'яблоко' -- связанный со столом объект и движок при выводе объекта 'стол' вслед за его 'dsc' выведет последовательно ''dsc'' всех вложенных в него объектов. Также, следует отметить, что, оперируя объектом 'стол' (например, перемещая его из комнаты в комнату), мы автоматически будем перемещать и вложенный в него объект 'яблоко'. Конечно, данный пример мог бы быть написан и по-другому, например, так: ``` room { nam = 'Дом'; }:with { obj { nam = 'стол'; dsc = [[В комнате стоит {стол}.]]; act = 'Гм... Просто стол...'; }: with { obj { nam = 'яблоко'; dsc = [[На столе лежит {яблоко}.]]; act = 'Взять что ли?'; }; } } ``` Выбирайте тот способ, который для вас понятней. ## Атрибуты и обработчики как функции Большинство атрибутов и обработчиков могут быть _функциями_. Так, например: ``` disp = function() p 'яблоко'; end ``` Пример не очень удачен, так как проще было бы написать disp = 'яблоко', но показывает синтаксис записи функции. Основная задача такой функции -- это возврат строки или булевого значения. Сейчас мы рассматриваем возврат строки. Для возврата строки вы можете использовать явную запись в виде: ``` return "яблоко"; ``` При этом ход выполнения кода функции прекращается, и она возвращает движку строку. В данном случае "яблоко". Более привычным способом вывода являются функции: - p ("текст") -- вывод текста и пробела; - pn ("текст") -- вывод текста с переводом строки; - pr ("текст") -- вывод текста "как есть". > Если ''p''/''pn''/''pr'' вызывается с одним текстовым параметром, то скобки можно опускать. pn "Нет скобкам!" Все эти функции дописывают текст в буфер и при возврате из функции возвращают его движку. Таким образом, вы можете постепенно формировать вывод за счёт последовательного выполнения p/pn/pr. Имейте в виду, что автору крайне редко необходимо явно форматировать текст, особенно, если это описание объектов, движок сам расставляет необходимые переводы строк и пробелы для разделения информации разного рода и делает это унифицированным способом. Вы можете использовать '..' или ',' для склейки строк. Тогда '(' и ')' обязательны. Например: ``` pn ("Строка 1".." Строка 2"); pn ("Строка 1", "Строка 2"); ``` > Основное отличие атрибутов от обработчиков событий состоит в том, > что обработчики событий могут менять состояние игрового мира, а > атрибуты нет. Поэтому, если вы оформляете атрибут (например, 'dsc') > в виде функции, помните, что задача атрибута -- это возврат значения, а > не изменение состояния игры! Дело в том, что движок обращается к > атрибутам в те моменты времени, которые обычно чётко не определены, > и не связаны явно с какими-то игровыми процессами! __Важно!__ > Ещё одной особенностью обработчиков является тот факт, что вы не > должны ждать каких-то событий внутри обработчика. То есть, не должно > быть каких-то циклов ожидания, или организации задержек (пауз). Дело > в том, что задача обработчика -- изменить игровое состояние и отдать > управление INSTEAD, который визуализирует эти изменения и снова > перейдёт в ожидание действий пользователя. Если вам требуется > организовать задержки вывода, вам придётся воспользоваться модулем > "timer". Функции практически всегда содержат условия и работу с переменными. Например: ``` obj { nam = 'яблоко'; seen = false; dsc = function(s) if not s.seen then p 'На столе {что-то} лежит.'; else p 'На столе лежит {яблоко}.'; end end; act = function(s) if s.seen then p 'Это яблоко!'; else s.seen = true; p 'Гм... Это же яблоко!'; end end; }; ``` Если атрибут или обработчик оформлен как функция, то всегда _первый аргумент_ функции (s) -- сам объект. То-есть, в данном примере, 's' это синоним _'яблоко'. Когда вы работаете с самим объектом в функции, удобнее использовать параметр, а не явное обращение к объекту по имени, так как при переименовании объекта вам не придётся переписывать вашу игру. Да и запись будет короче. В данном примере при показе сцены в динамической части сцены будет выведен текст: 'На столе что-то лежит'. При взаимодействии с 'что-то', переменная 'seen' объекта 'яблоко' будет установлена в true -- истина, и мы увидим, что это было яблоко. Как видим, синтаксис оператора 'if' довольно очевиден. Для наглядности, несколько примеров. if <выражение> then <действия> end if have 'яблоко' then p 'У меня есть яблоко!' end if <выражение> then <действия> else <действия иначе> end if have 'яблоко' then p 'У меня есть яблоко!' else p 'У меня нет яблока!' end if <выражение> then <действия> elseif <выражение 2> then <действия 2> else <иначе> end -- и т.д. if have 'яблоко' then p 'У меня есть яблоко!' elseif have 'вилка' then p 'У меня нет яблока, но есть вилка!' else p 'У меня нет ни яблока, ни вилки!' end Выражение в операторе if может содержать логическое "и" (and), "или" (or), "отрицание" (not) и скобки ( ) для задания приоритетов. Запись вида if <переменная> then означает, что переменная не равна false. Равенство описывается как '==', неравенство '~='. ``` if not have 'яблоко' and not have 'вилка' then p 'У меня нет ни яблока, ни вилки!' end ... if w ~= apple then p 'Это не яблоко.'; end ... if time() == 10 then p '10 й ход настал!' end ``` __Важно!__ В ситуации, когда переменная не была определена, но используется в условии, INSTEAD даст ошибку. Вам придётся заранее определять переменные, которые вы используете. ### Переменные объекта Запись 's.seen' означает, что переменная 'seen' размещена в объекте 's' (то есть 'яблоко'). Помните, мы назвали первый параметр функции 's' (от self), а первый параметр -- это сам текущий объект. Переменные объекта должны быть определены заранее, если вы собираетесь их модифицировать. Примерно так, как мы поступили с seen. Но переменных может быть много. ``` obj { nam = 'яблоко'; seen = false; eaten = false; color = 'красный'; weight = 10; ... }; ``` Все переменные объекта, при их изменении, попадают в файл сохранения игры. Если вы не хотите, чтобы переменная попала в файл сохранения, вы можете объявить такие переменные в специальном блоке: ``` obj { nam = 'яблоко'; { t = 1; -- эта переменная не попадёт в сохранения x = false; -- и эта тоже } }; ``` Обычно, вам не стоит так делать. Однако есть ситуация, при которой этот приём будет полезным. Дело в том, что массивы и таблицы объекта всегда сохраняются. Если вы используете массивы для хранения неизменяемых значений, вы можете написать так: ``` obj { nam = 'яблоко'; { text = { "раз", "два", "три" }; -- никогда не попадёт в файл сохранения } ... }; ``` Вы можете обращаться к переменным объекта через s (если это сам объект) или по переменной - ссылке, например: ``` apple = obj { color = 'красный'; } ... -- где-то в другом месте apple.color = 'зелёный' ``` Или по имени: ``` obj { nam = 'яблоко'; color = 'красный'; } ... -- где-то в другом месте _'яблоко'.color = 'зелёный' ``` На самом деле, вы можете создавать переменные-объекта на лету (без предварительного их определения), хотя обычно в этом нет смысла. Например: ``` apple 'xxx' (10) -- создали переменную xxx у объекта apple по ссылке (_'яблоко') 'xxx' (10) -- то же самое, но по имени объекта ``` ### Локальные переменные Кроме переменных объекта, вы можете использовать локальные и глобальные переменные. Локальные переменные создаются с помощью служебного слова local: ``` act = function(s) local w = _'лампочка' w.light = true p [[Я нажал на кнопку, и лампочка загорелась.]] end ``` В данном примере, переменная w существует только в теле функции-обработчика act. Мы создали временную ссылку-переменную w, которая ссылается на объект 'лампочка', чтобы изменить свойство-переменную light у этого объекта. Конечно, мы могли написать и: _'лампочка'.light = true Но представьте себе, если нам нужно произвести несколько действий с объектом, в таких случаях проще воспользоваться временной переменной. Локальные переменные никогда не попадают в файл-сохранение и играют роль временных вспомогательных переменных. Локальные переменные можно создавать и вне функций, тогда данная переменная видима только в пределах данного lua файла и не попадает в файл сохранения. Ещё один пример использования локальных переменных: ``` obj { nam = 'котёнок'; state = 1; act = function(s) s.state = s.state + 1 if s.state > 3 then s.state = 1 end p [[Муррр!]] end; dsc = function(s) local dsc = { "{Котёнок} мурлычет.", "{Котёнок} играет.", "{Котёнок} облизывается.", }; p(dsc[s.state]) end; end ``` Как видим, в функции dsc мы определили массив dsc. 'local' указывает на то, что он действует в пределах функции dsc. Конечно, данный пример можно было написать и так: ``` dsc = function(s) if s.state == 1 then p "{Котёнок} мурлычет." elseif s.state == 2 then p "{Котёнок} играет." else p "{Котёнок} облизывается.", end end ``` ### Глобальные переменные Вы также можете создать глобальную переменную: ``` global { -- определение глобальных переменных global_var = 1; -- число some_number = 1.2; -- число some_string = 'строка'; know_truth = false; -- булево значение array = {1, 2, 3, 4}; -- массив } ``` Ещё одна форма записи, удобная для одиночных определений: ``` global 'global_var' (1) ``` Глобальные переменные всегда попадают в файл-сохранение. Кроме глобальных переменных, вы можете задавать константы. Синтаксис аналогичен глобальным переменным: ``` const { A = 1; B = 2; } const 'Aflag' (false) ``` Движок будет контролировать неизменность констант. Константы не попадают в файл-сохранение. Иногда вам нужно работать с переменной, которая не определена как local (и видима во всех ваших lua файлах игры), но не должна попадать в файл сохранения. Для таких переменных вы можете использовать декларации: ``` declare { A = 1; B = 2; } declare 'Z' (false) ``` Декларации не попадают в файл сохранения. Одно из важных свойств деклараций состоит в том, что вы можете декларировать функции, например: ``` declare 'test' (function() p "Hello world!" end) global 'f' (test) ``` В таком случае, вы можете присваивать значение функции 'test' другим переменным и состояние этих переменных может быть сохранено в файле сохранения. То-есть, декларированную функцию можно использовать как значение переменной! Вы можете декларировать ранее определённые функции, например: ``` declare 'dprint' (dprint) ``` Тем самым делая такие недекларированные функции -- декларированными. Декларация функции, по сути, это присвоение функции имени, благодаря чему мы можем сохранить эту функцию как ссылку. ### Вспомогательные функции Вы можете писать свои вспомогательные функции и использовать их из своей игры, например: ``` function mprint(n, ...) local a = {...}; -- временный массив с аргументами к функции p(a[n]) -- выведем n-й элемент массива end ... dsc = function(s) mprint(s.state, { "{Котёнок} мурлычет.", "{Котёнок} играет.", "{Котёнок} облизывается." }); end; ``` Пока не обращайте внимания на данный пример, если он кажется вам сложным. ### Возвращаемые значения обработчиков Если необходимо показать, что действие не выполнено (обработчик не сделал ничего полезного), возвращайте значение false. Например: ``` act = function(s) if broken_leg then return false end p [[Я ударил ногой по мячу.]] end ``` При этом будет отображено описание по умолчанию, заданное с помощью обработчика 'game.act'. Обычно описание по умолчанию содержит описание невыполнимых действий. Что-то вроде: game.act = 'Гм... Не получается...'; Итак, если вы не задали обработчик act или вернули из него false -- считается, что реакции нет и движок выполнит аналогичный обработчик у объекта 'game'. Обычно, нет никакого смысла возвращать false из act, но существуют другие обработчики, о которых будет рассказано дальше, для которых описанное поведение точно такое же. На самом деле, кроме 'game.act' и 'act' атрибутов объекта, существует обработчик 'onact' у объекта game, который может прервать выполнение обработчика 'act'. Перед тем как вызвать обработчик 'act' у объекта, вызывается onact у game. Если обработчик вернёт false, выполнение 'act' обрывается. 'onact' удобно использовать, для контроля событий в комнате или игре, например: ``` -- вызываем onact комнат, если они есть -- для действий на любой объект game.onact = function(s, ...) local r, v = std.call(here(), 'onact', ...) if v == false then -- если false, обрубаем цепочку return r, v end return end room { nam = 'shop'; disp = 'Магазин'; onact = function(s, w) p [[В магазине нельзя воровать!]] p ([[Даже, если это всего лишь ]], w, '.') return false end; obj = { 'мороженное', 'хлеб' }; } ``` В данном примере, при попытке "потрогать" любой предмет, будет выведено сообщение о запрете данного действия. Всё, что описано выше на примере 'act' действует и для других обработчиков: tak, inv, use, а также при переходах, о чём будет рассказано далее. > Иногда возникает необходимость вызвать функцию - обработчик вручную. > Для этого используется синтаксис вызова метода > объекта. 'Объект:метод(параметры)'. Например: apple:act() -- вызовем обработчик 'act' у объекта 'apple' (если он определён как функция!). _'яблоко':act() -- то же самое, но по имени, а не по переменной-ссылке Такой метод работает только в том случае, если вызываемый метод оформлен как функция. Вы можете воспользоваться 'std.call()' для вызова обработчика тем способом, каким это делает сам INSTEAD. (Будет описано в дальнейшем). ## Инвентарь Простейший вариант сделать объект, который можно брать -- определить обработчик 'tak'. Например: ``` obj { nam = 'яблоко'; dsc = 'На столе лежит {яблоко}.'; inv = function(s) p 'Я съел яблоко.' remove(s); -- удалить яблоко из инвентаря end; tak = 'Вы взяли яблоко.'; }; ``` При этом, при действии игрока на объект "яблоко" (щелчок мыши на ссылку в сцене) -- яблоко будет убрано из сцены и добавлено в инвентарь. При действии игрока на инвентарь (двойной щелчок мыши на названии объекта) -- вызывается обработчик 'inv'. В нашем примере, при действии игроком на яблоко в инвентаре -- яблоко будет съедено. Конечно, мы могли бы реализовать код взятия объекта в ''act'', например, так: ``` obj { nam = 'яблоко'; dsc = 'На столе лежит {яблоко}.'; inv = function(s) p 'Я съел яблоко.' remove(s); -- удалить яблоко из инвентаря end; act = function(s) take(s) p 'Вы взяли яблоко.'; end }; ``` Если у объекта в инвентаре не объявлен обработчик 'inv', будет вызван 'game.inv'. Если обработчик 'tak' вернёт false, то предмет не будет взят, например: ``` obj { nam = 'яблоко'; dsc = 'На столе лежит {яблоко}.'; tak = function(s) p "Оно же червивое!" return false end; }; ``` ## Переходы между сценами Традиционные переходы в INSTEAD выглядят как ссылки над описанием сцены. Для определения таких переходов между сценами используется атрибут сцены -- список 'way'. В списке определяются комнаты, в виде имён комнат или переменных-ссылок, аналогично списку 'obj'. Например: ``` room { nam = 'room2'; disp = 'Зал'; dsc = 'Вы в огромном зале.'; way = { 'main' }; }; room { nam = 'main'; disp = 'Главная комната'; dsc = 'Вы в большой комнате.'; way = { 'room2' }; }; ``` При этом, вы сможете переходить между сценами 'main' и 'room2'. Как вы помните, 'disp' может быть функцией, и вы можете генерировать имена переходов на лету. Или использовать title, для разделения имени сцены как заголовка и как имени перехода: ``` room { nam = 'room2'; disp = 'В зал'; title = 'В зале'; dsc = 'Вы в огромном зале.'; way = { 'main' }; }; room { nam = 'main'; title = 'В главной комнате'; disp = 'В главную комнату'; dsc = 'Вы в большой комнате.'; way = { 'room2' }; }; ``` При переходе между сценами движок вызывает обработчик 'onexit' из текущей сцены и 'onenter' в той сцене, куда идёт игрок. Например: ``` room { onenter = 'Вы заходите в зал.'; nam = 'Зал'; dsc = 'Вы в огромном зале.'; way = { 'main' }; onexit = 'Вы выходите из зала.'; }; ``` Конечно, как и все обработчики, 'onexit' и 'onenter' могут быть функциями. Тогда первый параметр это (как всегда) сам объект - комната, а второй -- это комната куда игрок собирается идти (для 'onexit') или из которой собирается уйти (для 'onenter'). Например: ``` room { onenter = function(s, f) if f^'main' then p 'Вы идёте из комнаты main.'; end end; nam = 'Зал'; dsc = 'Вы в огромном зале.'; way = { 'main' }; onexit = function(s, t) if t^'main' then p 'Я не хочу назад!' return false end end; }; ``` Запись вида: if f^'main' then Это сопоставление объекта с именем. Это альтернатива записям: if f == _'main' then Или: if f.nam == 'main' then Или: if std.nameof(f) == 'main' then Как видим на примере onexit, эти обработчики, кроме строки, могут возвращать булевое значение статуса. Аналогично обработчику onact, мы может отменить переход, вернув false из onexit/onenter. Вы можете сделать возврат статуса и другим способом, если это кажется вам удобным: ``` return "Я не хочу назад", false ``` Если же вы используете функции 'p'/'pn'/'pr', то просто возвращайте статус операции с помощью завершающего 'return', как показано в примере выше. __Важно!__ > Следует отметить, что при вызове обработчика 'onenter' указатель на > текущую сцену (here()) **ещё не изменён**!!! В INSTEAD есть > обработчики 'exit' (уход из комнаты) и 'enter' (заход в комнату), > которые вызываются уже _после_ того, как переход произошёл. Эти > обработчики рекомендованы к использованию всегда, когда нет > необходимости запрещать переход. Иногда есть необходимость, чтобы название перехода отличалось от названия комнаты, в которую ведёт этот переход. Существует несколько способов сделать это. Например, с помощью 'path'. ``` room { nam = 'room2'; title = 'Зал'; dsc = 'Вы в огромном зале.'; way = { path { 'В главную комнату', 'main'} }; }; room { nam = 'main'; title = 'Главная комната'; dsc = 'Вы в большой комнате.'; way = { path {'В зал', 'room2'} }; }; ``` На самом деле, 'path' создаёт комнату с атрибутом 'disp', который равен первому параметру, и специальной функцией 'onenter', которая перенаправляет игрока в комнату, заданную вторым параметром 'path'. Если вы укажете три параметра: way = { path {'#взал', 'В зал', 'room2'} }; То первый параметр станет именем (или тегом, как в приведённом примере) такой комнаты. Альтернативная форма записи с явным заданием атрибута nam: way = { path { nam = '#взал', 'В зал', 'room2'} }; Вы можете менять название перехода после того, как переход происходил хотя бы раз, и вы узнали, что же это за комната: way = { path {'#вдверь', 'В дверь', after = 'В гостиную', 'room2'} }; Все параметры, кроме имени перехода, могут быть функциями. Таким образом, 'path' позволяет именовать переходы удобным способом. Иногда вам может потребоваться включать и выключать переходы. На самом деле это требуется не часто. Идея переходов состоит в том, что переход виден даже тогда, когда он невозможен. Например, представим себе сцену перед домом у входной двери. Войти в дом нельзя, так как дверь закрыта. Нет особого смысла прятать переход "дверь". Просто в функции 'onenter' сцены внутри дома мы проверяем, а есть ли у героя ключ? И если ключа нет, говорим о том, что дверь закрыта и запрещаем переход. Это повышает интерактивность и упрощает код. Если же вы хотите сделать дверь объектом сцены, поместите её в комнату, но в 'act' обработчике сделайте осмотр двери, или дайте возможность игроку открыть её ключом (как это сделать - мы рассмотрим позже), но сам переход дайте сделать игроку привычным способом через строку переходов. Тем не менее, бывают ситуации, когда переход не очевиден и он появляется в результате каких-то событий. Например, мы осмотрели часы и увидели там секретный лаз. ``` obj { nam = 'часы'; dsc = [[Тут есть старинные {часы}.]]; act = function(s) enable '#часы' p [[Вы видите, что в часах есть потайной ход!]]; end; } room { nam = 'Зал'; dsc = 'Вы в огромном зале.'; obj = { 'часы' }; way = { path { '#часы', 'В часы', 'inclock' }:disable() }; }; ``` В данном примере, мы создали _отключённый_ переход, за счёт вызова метода 'disable' у комнаты, созданной с помощью 'path'. Метод 'disable' есть у всех объектов (не только комнат), он переводит объект в отключённое состояние, которое означает, что объект перестаёт быть доступным игроку. Замечательным свойством отключённого объекта является то, что его можно _включить_ с помощью 'enable()'; Далее, когда игрок нажимает на ссылку, описывающую часы, вызывается обработчик 'act', который с помощью функции 'enable()' делает переход видимым. Альтернативный вариант заключается не в выключении, а 'закрытии' объекта: ``` obj { nam = 'часы'; dsc = [[Тут есть старинные {часы}.]]; act = function(s) open '#часы' p [[Вы видите, что в часах есть потайной ход!]]; end; } room { nam = 'Зал'; dsc = 'Вы в огромном зале.'; obj = { 'часы' }; way = { path { '#часы', 'В часы', 'inclock' }:close() }; }; ``` В чём разница? Выключение объекта означает то, что объект перестаёт быть доступным для игрока. Если в объекте вложены другие объекты, то и эти объекты становятся недоступными. Закрытие объекта делает недоступным содержимое данного объекта, но не сам объект. Однако, в случае комнат, и закрытие комнаты и отключённые комнаты приводят к одному результату -- переход на них становится недоступным. Ещё один вариант: ``` room { nam = 'inclock'; dsc = [[Я в часах.]]; }:close() obj { nam = 'часы'; dsc = [[Тут есть старинные {часы}.]]; act = function(s) open 'inclock' p [[Вы видите, что в часах есть потайной ход!]]; end; } room { nam = 'Зал'; dsc = 'Вы в огромном зале.'; obj = { 'часы' }; way = { path { 'В часы', 'inclock' } }; }; ``` Здесь мы закрываем и открываем не переход, а комнату, в которую ведёт переход. path не показывает себя, если комната, в которую он ведёт, отключена или закрыта. ## Действие объектов друг на друга Игрок может действовать объектом инвентаря на другие объекты. Для этого он щелкает мышью на предмет инвентаря, а затем, на предмет сцены. При этом вызывается обработчик 'used' у объекта, на который действуют, и обработчик 'use' объекта, которым действуют. Например: ``` obj { nam = 'нож'; dsc = 'На столе лежит {нож}'; inv = 'Острый!'; tak = 'Я взял нож!'; use = 'Вы пытаетесь использовать нож.'; }; obj { nam = 'стол'; dsc = 'В комнате стоит {стол}.'; act = 'Гм... Просто стол...'; obj = { 'нож' }; used = function(s) p 'Вы пытаетесь сделать что-то со столом...'; return false end; }; ``` В данном примере, обработчик used возвращает false. Зачем? Если вы помните, возврат false означает, что обработчик сообщает движку о том, что событие он не обработал. Если бы мы не вернули бы false, очередь до обработчика 'use' объекта 'нож' просто бы не дошла. На самом деле, в реальности обычно вы будете пользоваться или use или used, вряд ли имеет смысл выполнять оба обработчика во время действия предмета на предмет. Ещё один пример, когда удобно вернуть false: ``` use = function(s, w) if w^'яблоко' then p [[Я почистил яблоко.]] w.cut = true return end return false; end ``` В данном случае use у яблока обрабатывает только одну ситуацию -- действие на яблоко. В остальных случаях, обработчик возвращает false и движок вызовет метод по умолчанию: game.use. Но лучше, если вы пропишете действие по умолчанию для ножа: ``` use = function(s, w) if w^'яблоко' then p [[Я почистил яблоко.]] w.cut = true return end p [[Не стоит размахивать ножом!]] end ``` Этот пример также демонстрирует тот факт, что вторым параметром у use является предмет, на который мы действуем. У метода 'used', соответственно, второй параметр -- это объект, который действует на нас: ``` obj { nam = 'мусорка'; dsc = [[В углу стоит {мусорка}.]]; used = function(s, w) if w^'яблоко' then p [[Я выбросил яблоко в мусорку.]] remove(w) return end return false; end } ``` Как вы помните, перед вызовом use вызывается обработчик onuse у объекта game, потом у объекта 'игрок', а потом у текущей комнаты. Вы можете блокировать 'use', вернув из любого из перечисленных методов 'onuse' -- false. Использовать 'use' или 'used' (или оба) это вопрос личных предпочтений, однако, метод used вызывается раньше и, следовательно, имеет больший приоритет. ## Объект "Игрок" Игрок в мире INSTEAD представлен объектом типа 'player'. Вы можете создавать несколько игроков, но один игрок присутствует по умолчанию. Имя этого объекта -- 'player'. Существует переменная-ссылка pl, которая указывает на этот объект. Обычно, вам не нужно работать с этим объектом напрямую. Но иногда это может быть необходимым. По умолчанию, атрибут 'obj' у игрока представляет собой инвентарь. Обычно, нет смысла переопределять объект типа player, однако, вы можете это сделать: ``` game.player = player { nam = "Василий"; room = 'кухня'; -- стартовая комната игрока power = 100; obj = { 'яблоко' }; -- заодно добавим яблоко в инвентарь }; ``` В INSTEAD есть возможность создавать нескольких игроков и переключаться между ними. Для этого служит функция 'change_pl()'. В качестве параметра передайте функции требуемый объект типа 'player' (или его имя). Функция переключит текущего игрока, и при необходимости, осуществит переход в комнату, где находится новый игрок. Функция 'me()' всегда возвращает текущего игрока. Следовательно, в большинстве игр me() == pl. ## Объект "Мир" Игровой мир представлен объектом типа world. Имя такого объекта 'game'. Существует ссылка-переменная, которая также называется game. Обычно вы не работаете с этим объектом напрямую, однако иногда вы можете вызывать его методы, или менять значения переменных этого объекта. Например, переменная game.codepage содержит кодировку исходного кода игры, и по умолчанию равна "UTF-8". Я не рекомендую использовать другие кодировки, но иногда, выбор кодировки может стать необходимостью. Переменная game.player -- содержит текущего игрока. Кроме того, как вы уже знаете, объект 'game' может содержать обработчики по умолчанию: 'act', 'inv', 'use', 'tak', которые будут вызваны, если в результате действий пользователя не будут найдены никакие другие обработчики (или все они вернули false). Например, вы можете написать в начале игры: ``` game.act = 'Не получается.'; game.inv = 'Гм... Странная штука...'; game.use = 'Не сработает...'; game.tak = 'Не нужно мне это...'; ``` Конечно, все они могут быть функциями. Также, объект game может содержать обработчики: onact, ontak, onuse, oninv, onwalk -- которые могут прерывать действия, в случае возврата false. Ещё у объекта game можно задать обработчики: afteract, afterinv, afteruse, afterwalk -- которые вызываются в случае успешного выполнения соответствующего действия. ## Атрибуты-списки Атрибуты-списки (такие как 'way' или 'obj') позволяют работать со своим содержимым с помощью набора методов. Атрибуты-списки призваны сохранять в себе списки объектов. На самом деле, вы можете создавать списки для собственных нужд, и размещать их в объектах, например: ``` room { nam = 'холодильник'; frost = std.list { 'мороженное' }; } ``` Хотя, обычно, это не требуется. Ниже перечислены методы объектов типа 'список'. Вы можете вызывать их для любых списков, хотя обычно это будут way и obj, например: ways():disable() -- отключить все переходы - disable() - отключает все объекты списка; - enable() - включает все объекты списка; - close() - закрыть все объекты списка; - open() - открыть все объекты списка; - add(объект|имя, [позиция]) - добавить объект; - for_each(функция, аргументы) - вызвать для каждого объекта функцию с аргументами; - lookup(имя/тег или объект) - поиск объекта в списке. Возвращает объект и индекс; - srch(имя/тег или объект) - поиск видимого объекта в списке; - empty() - вернёт true, если список пуст; - zap() - очистить список; - replace(что, на что) - заменить объект в списке; - cat(список, [позиция]) - добавить содержимое списка в текущий список по позиции; - del(имя/объект) - удалить объект из списка. Существуют функции, возвращающие объекты-списки: - inv([игрок]) - вернуть инвентарь игрока; - objs([комната]) - вернуть объекты комнаты; - ways([комната]) - вернуть переходы комнаты. Конечно, вы можете обращаться к спискам и напрямую: ``` pl.obj:add 'нож' ``` Объекты в списках хранятся в том порядке, в котором вы их добавите. Однако, если у объекта присутствует числовой атрибут pri, то он играет роль _приоритета_ в списке. Если pri не задан, значением приоритета считается 0. Таким образом, если вы хотите, чтобы какой-то объект был первым в списке, давайте ему приоритет pri < 0. Если в конце списка -- > 0. ``` obj { pri = -100; nam = 'штука'; disp = 'Очень важный предмет инвентаря'; inv = [[Осторожней с этим предметом.]]; } ``` ## Функции, которые возвращают объекты В INSTEAD определены некоторые функции, которые возвращают различные объекты. При описании функции используются следующие соглашения о параметрах. - в символах [ ] описаны необязательные параметры; - 'что' или 'где' - означает объект (в том числе комнату), заданный тегом, именем или переменной-ссылкой; Итак, основные функции: - '_(что)' - получить объект; - 'me()' возвращает текущего объекта-игрока; - 'here()' возвращает текущую сцену; - 'where(что)' возвращает комнату или объект, в котором находится заданный объект. Если объект находится в нескольких местах, то можно передать второй параметр -- таблицу Lua, в которую будут добавлены эти объекты; - 'inroom(что)' аналогично where(), но вернёт комнату, в которой расположен объект (это важно для объектов в объектах); - 'from([где])' возвращает прошлую комнату, из которой игрок перешёл в заданную комнату. Необязательный параметр -- получить прошлую комнату не для текущей комнаты, а для заданной; - 'seen(что, [где])' возвращает объект или переход, если он присутствует и видим, есть второй необязательный параметр -- выбрать сцену или объект/список в котором искать; - 'lookup(что, [где])' возвращает объект или переход, если он существует в сцене или объекте/списке; - 'inspect(что)' возвращает объект, если он виден/доступен на сцене. Поиск производится по переходам и объектам, в том числе, в объектах игрока; - 'have(что)' возвращает объект, если он есть в инвентаре и не отключён; - 'live(что)' возвращает объект, если он присутствует среди живых объектов (описано далее); Эти функции в основном используются в условиях, либо для поиска объекта с последующей модификацией. Например, вы можете использовать 'seen' для написания условия: ``` onexit = function(s) if seen 'монстр' then -- если у функции 1 параметр, --- скобки писать не обязательно p 'Монстр загораживает проход!' return false end end ``` А также, для нахождения объекта в сцене: ``` use = function(s, w) if w^'окно' then local ww = lookup 'собака' if not ww then p [[А где моя собака?]] return end place(ww, 'улица') p 'Я разбил окно! Моя собака выпрыгнула на улицу.' return end return false end ``` Пример с функцией 'have': ``` ... act = function(s) if have 'нож' then p 'Но у меня же есть нож!'; return end take 'нож' end ... ``` > Может возникнуть вопрос, в чём разница между функциями lookup и _ ()? > Дело в том, что lookup() ищет объект, и в случае, если объект не найден > -- просто ничего не вернёт. А запись _ () предполагает, что вы точно > знаете, что за предмет вы получаете. Другими словами, _ () это > безусловное получение объекта по имени. Эта функция в общем случае не > занимается _поиском_. Только если в качестве параметра задан тег, > будет осуществлён поиск среди доступных объектов. Если вы используете > _ () на несуществующий объект или недоступный тег -- вы получите ошибку! ## Другие функции стандартной библиотеки В INSTEAD в модуле stdlib, который всегда подключается автоматически, определены функции, которые предлагаются автору как основной рабочий инструмент по работе с миром игры. Рассмотрим их в этой главе. При описании функции в большинстве функций под параметром 'w' понимается объект или комната, заданная именем, тегом или по переменной-ссылке. [ wh ] - означает необязательный параметр. - include(файл) - включить файл в игру; include "lib" -- включит файл lib.lua из текущего каталога с игрой; - loadmod(модуль) - подключить модуль игры; loadmod "module" -- включит модуль module.lua из текущего каталога; - rnd(m) - случайное целочисленное значение от '1' до 'm'; - rnd(a, b) - случайное целочисленное значение от 'a' до 'b', где 'a' и 'b' целые >= 0; - rnd\_seed(что) - задать зерно генератора случайных чисел; - p(...) - вывод строки в буфер обработчика/атрибута (с пробелом в конце); - pr(...) - вывод строки в буфер обработчика/атрибута "как есть"; - pn(...) - вывод строки в буфер обработчика/атрибута (с переводом строки в конце); - pf(fmt, ...) - вывод форматной строки в буфер обработчика/атрибута; local text = 'hello'; pf("Строка: %q Число: %d\n", text, 10); - pfn(...)(...)... "строка" - формирование простого обработчика; Данная функция упрощает создание простых обработчиков: act = pfn(walk, 'ванная') "Я решил зайти в ванную."; act = pfn(enable, '#переход') "Я заметил отверстие в стене!"; - obj {} - создание объекта; - stat {} - создание статуса; - room {} - создание комнаты; - menu {} - создание меню; - dlg {} - создание диалога; - me() - возвращает текущего игрока; - here() - возвращает текущую сцену; - from([w]) - возвращает комнату из которой осуществлён переход в текущую сцену; - new(конструктор, аргументы) - создание нового _динамического_ объекта (будет описано далее); - delete(w) - удаление динамического объекта; - gamefile(файл, [сбросить состояние?]) - подгрузить динамически файл с игрой; gamefile("part2.lua", true) -- сбросить состояние игры (удалить объекты и переменные), подгрузить part2.lua и начать с main комнаты. - player {} - создать игрока; - dprint(...) - отладочный вывод; - visits([w]) - число визитов в данную комнату (или 0, если визитов не было); - visited([w]) - число визитов в комнату или false, если визитов не было; if not visited() then p [[Я тут первый раз.]] end - walk(w, [булевое exit], [булевое enter], [булевое менять from]) - переход в сцену; walk('конец', false, false) -- безусловный переход (игнорировать onexit/onenter/exit/enter); - walkin(w) - переход в под-сцену (без вызова exit/onexit текущей комнаты); - walkout([w], [dofrom]) - возврат из подсцены (без вызова enter/onenter); - walkback([w]) - синоним walkout([w], false); - \_(w) - получение объекта; - for_all(fn, ...) - выполнить функцию для всех аргументов; for_all(enable, 'окно', 'дверь'); - seen(w, [где]) - поиск видимого объекта; - lookup(w, [где]) - поиск объекта; - ways([где]) - получить список переходов; - objs([где]) - получить список объектов; - search(w) - поиск доступного игроку объекта; - have(w) - поиск предмета в инвентаре; - inroom(w) - возврат комнаты/комнат, в которой находится объект; - where(w, [таблица]) - возврат объекта/объектов, в котором находится объект; local list = {} local w = where('яблоко', list) -- если яблоко находится в более, чем одном месте, то -- list будет содержать массив этих мест. -- Если вам достаточно одного местоположения, то: where 'яблоко' -- будет достаточно - closed(w) - true если объект закрыт; - disabled(w) - true если объект выключен; - enable(w) - включить объект; - disable(w) - выключить объект; - open(w) - открыть объект; - close(w) - закрыть объект; - actions(w, строка, [значение]) - возвращает (или устанавливает) число действий типа t для объекта w. if actions(w, 'tak') > 0 then -- предмет w был взят хотя бы 1 раз; if actions(w) == 1 then -- act у предмета w был вызван 1 раз; - pop(тег) - возврат в прошлую ветвь диалога; - push(тег) - переход в следующую ветвь диалога - empty([w]) - пуста ли ветвь диалога? (или объект) - lifeon(w) - добавить объект в список живых; - lifeoff(w) - убрать объект из списка живых; - live(w) - объект жив?; - change\_pl(w) - смена игрока; - player\_moved([pl]) - текущий игрок перемещался в этом такте?; - inv([pl]) - получить список-инвентарь; - remove(w, [wh]) - удалить объект из объекта или комнаты; Удаляет объект из списков obj и way (оставляя во всех остальных, например, game.lifes); - purge(w) - уничтожить объект (из всех списков); удаляет объект из _всех_ списков, в которых он присутствует; - replace(w, ww, [wh]) - заменить один объект на другой; - place(w, [wh]) - поместить объект в объект/комнату (удалив его из старого объекта/комнаты); - put(w, [wh]) - поместить объект без удаления из старого местоположения; - take(w) - забрать объект; - drop(w, [wh]) - выбросить объект; - path {} - создать переход; - time() - число ходов от начала игры. __Важно!__ На самом деле, многие из этих функций также умеют работать не только с комнатами и объектами, но и со списками. То есть 'remove(apple, inv())' сработает также как и 'remove(apple, me())''; Впрочем, remove(apple) тоже сработает и удалит объект из тех мест, где он присутствует. Рассмотрим несколько примеров. ``` act = function() pn "Я иду в следующую комнату..." walk (nextroom); end obj { nam = 'моя машина'; dsc = 'Перед хижиной стоит мой старенький {пикап} Toyota.'; act = function(s) walk 'inmycar'; end }; ``` __Важно!__ > После вызова 'walk' выполнение обработчика продолжится до его > завершения. Поэтому обычно, после 'walk' всегда следует > 'return', если только это не последняя строка функции, хотя и в > этом случае безопасно поставить 'return'. ``` act = function() pn "Я иду в следующую комнату..." walk (nextroom); return end ``` Не забывайте также, что при вызове 'walk' вызовутся обработчики 'onexit/onenter/exit/enter'' и если они запрещают переход, то он не произойдёт. ## Диалоги Диалоги -- это сцены специального типа 'dlg', содержащие объекты -- фразы. При входе в диалог игрок видит перечень фраз, которые может выбирать, получая какую-то реакцию игры. По умолчанию, уже выбранные фразы скрываются. При исчерпании всех вариантов, диалог завершается выходом в предыдущую комнату (конечно, если в диалоге нет постоянно видимых фраз, среди которых обычно встречается что-то типа 'Завершить разговор' или 'Спросить ещё раз'). При повторном входе в диалог, все скрытые фразы снова становятся видимыми и диалог сбрасывается в начальное состояние (если, конечно, автор игры специально не прикладывал усилия по изменению вида диалога). Переход в диалог в игре осуществляется как переход на сцену: ``` obj { nam = 'повар'; dsc = 'Я вижу {повара}.'; act = function() walk 'povardlg' end, }; ``` Хотя я рекомендую использовать 'walkin', так как в случае 'walkin' не вызываются 'onexit/exit' текущей комнаты, а персонаж, с которым мы можем поговорить, обычно находиться в этой же комнате, где и главный герой. То есть: ``` obj { nam = 'повар'; dsc = 'Я вижу {повара}.'; act = function() walkin 'povardlg' end, }; ``` Если вам не нравится префикс у фраз в виде дефиса, вы можете определить строковую переменную: ``` std.phrase_prefix = '+'; ``` И получить префикс в виде '+' перед каждой фразой. Вы также можете сделать префикс функцией. На вход функции в таком случае будет поступать в виде параметра номер фразы. Задача функции -- вернуть строковый префикс. Обратите внимание, что 'std.phrase_prefix' не сохраняется, если вам нужно переопределять её на лету, вам придётся восстанавливать её состояние в 'start()' функции вручную! __Важно!__ > Я рекомендую использовать модуль 'noinv' и задавать свойство 'noinv' > в диалогах. Диалоги будут выглядеть красивей, и вы обезопасите свою > игру от ошибок и непредсказуемых реакций, при использовании инвентаря > внутри диалога (так как обычно автор не подразумевает такие > вещи). Например: ``` require "noinv" ... dlg { nam = 'Охранник'; -- в диалогах обычно не нужен инвентарь noinv = true; ... } ``` ### Фразы Центральным понятием в диалогах является _фраза_. Фразы это не просто вопрос-ответ, как можно подумать. Фраза является деревом, и в этом смысле, весь диалог может быть реализован единственной фразой. Например: ``` dlg { nam = 'разговор'; title = [[Разговор с продавцом]]; enter = [[Я обратился к продавцу.]]; phr = { { 'У вас есть бобы?', '-- Нет.'}, { 'У вас есть шоколад?', '-- Нет.'}, { 'У вас есть квас?', '-- Да', { 'А сколько он стоит?', '-- 50 рублей.' }, { 'А он холодный?', '-- Холодильник сломался.', { 'Беру два!', 'Остался один.', { 'Дайте один!', function() p [[Ок!]]; take 'квас'; end }; } } } } } ``` Как видно из примера, фраза задаётся атрибутом phr и может содержать разветвлённый диалог. Фраза содержит в себе выборы, каждый из которых тоже может содержать в себе выборы и так далее... Фраза имеет формат пары: описатель -- реакция. В простейшем случае, это строки. Но они могут быть и функциями. Обычно, функцией бывает реакция, которая может содержать код по изменению игрового мира. Пара может быть простой: {'Вопрос', 'Ответ } А может содержать в себе массив пар: {'Вопрос', 'Ответ', {'Под-вопрос1', 'Под-ответ1' }, {'Под-вопрос2', 'Под-ответ2' }, } На самом деле, если вы посмотрите внимательно на атрибут phr, то вы заметите, что массив выборов тоже является вложенным в главную фразу phr, но только первоначальная пара отсутствует: ``` dlg { nam = 'разговор'; title = [[Разговор с продавцом]]; enter = [[Я обратился к продавцу.]]; phr = { -- тут мог бы быть вопрос ответ 1-го уровня! -- 'Главный вопрос', 'Главный ответ', { 'У вас есть бобы?', '-- Нет.'}, { 'У вас есть шоколад?', '-- Нет.'}, { 'У вас есть квас?', '-- Да', { 'А сколько он стоит?', '-- 50 рублей.' }, { 'А он холодный?', '-- Холодильник сломался.', { 'Беру два!', 'Остался один.', { 'Дайте один!', function() p [[Ок!]]; take 'квас'; end }; } } } } } ``` На самом деле, так и есть. И вы можете добавить 'Главный вопрос' и 'Главный ответ', но только вы не увидите этот главный вопрос. Дело в том, что при входе в диалог фраза phr автоматически раскрывается, так как обычно нет никакого смысла в диалогах из одной единственной фразы. И гораздо проще понять диалог как набор выборов, чем как единственную древовидную фразу. Так что у phr никогда нет первоначальной пары вопрос-ответ, но мы сразу попадаем в массив вариантов, что более понятно. Когда мы говорим о том, что диалог на самом деле реализован одной фразой, мы не совсем правы. Дело в том, что мы имеем дело с фразой, внутри которой находятся другие фразы... Это напоминает нам ситуацию с объектами. Действительно, фразы -- это объекты, которые могут находиться внутри друг друга. Итак, посмотрим на диалог свежим взглядом: ``` dlg { nam = 'разговор'; title = [[Разговор с продавцом]]; enter = [[Я обратился к продавцу.]]; phr = { -- это объект типа фраза, без dsc и act -- это 1-я фраза, внутри фразы с dsc и act { 'У вас есть бобы?', '-- Нет.'}, -- это 2-я фраза, внутри фразы с dsc и act { 'У вас есть шоколад?', '-- Нет.'}, -- это 3-я фраза, внутри фразы с dsc и act { 'У вас есть квас?', '-- Да', -- это 1-я фраза внутри 3й фразы с dsc и act { 'А сколько он стоит?', '-- 50 рублей.' }, { 'А он холодный?', '-- Холодильник сломался.', { 'Беру два!', 'Остался один.', -- здесь act в виде функции { 'Дайте один!', function() p [[Ок!]]; take 'квас'; end }; } } } } } ``` Как видим, диалог -- это комната, а фразы -- специальные объекты! Теперь вам станет понятным дальнейшее изложение. > Внимание! По умолчанию, когда игрок нажимает на один из вопросов в > списке, движок повторяет его в выводе и только потом выводит > ответ. Это сделано для того, чтобы диалог выглядел связанным. Если > вы хотите отключить такое поведение, используйте настройку > std.phrase_show: ``` std.phrase_show = false -- не выводить фразу-вопрос при выборе ``` Эта настройка действует на все диалоги, устанавливайте её в init() или start() функции. ### Атрибуты фраз Рассмотрим вариант фразы: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', {'Красную', 'Держите!' }, {'Синюю', 'Вот!' }, } } ``` Если запустить этот диалог, то после выбора, скажем, красной таблетки, у нас останется ещё один выбор синей таблетки. Но наш замысел, явно не в этом! Существует несколько способов сделать диалог правильным. Во первых, вы можете воспользоваться pop() -- возвратом на предыдущий уровень диалога: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', {'Красную', function() p 'Держите!'; pop() end; }, {'Синюю', function() p 'Вот!'; pop() end; }, } } ``` Или, в другой записи: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', {'Красную', pfn(pop) 'Держите!' }, {'Синюю', pfn(pop) 'Вот!' }, } } ``` Но это не слишком удобно, кроме того, что если эти фразы содержат в себе новые фразы? В случаях, когда вариант предлагает выбор, и этот выбор должен быть единственным, вы можете задать у фразы атрибут only: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!' }, {'Синюю', 'Вот!' }, } } ``` В таком случае, после выбора фразы, все фразы текущего контекста будут закрыты. Ещё одна частая ситуация, вы хотите, чтобы фраза не пряталась после её активации. Это делается заданием флага true: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!' }, {'Синюю', 'Вот!' }, { true, 'А какая лучше?', 'Тебе выбирать.' }, -- фраза -- которая никогда не будет скрыта } } ``` Альтернативная запись, с явным заданием атрибута always: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!' }, {'Синюю', 'Вот!' }, { always = true, 'А какая лучше?', 'Тебе выбирать.' }, -- фраза -- которая никогда не будет скрыта } } ``` Ещё один пример. Что-если мы хотим, чтобы фраза была показана (или спрятана) по какому-либо условию? Для этого есть функция-обработчик cond. ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!' }, {'Синюю', 'Вот!' }, { true, 'А какая лучше?', 'Тебе выбирать.' }, -- фраза -- которая никогда не будет скрыта }, { cond = function() return have 'яблоко' end, 'А хотите яблоко?', 'Спасибо, нет.' }; } ``` В данном примере, только при наличии у игрока яблока, покажется ветка диалога 'А хотите яблоко?'. Иногда бывает удобно выполнить действие в тот момент, когда варианты текущего уровня(контекста) диалога исчерпаны. Для этого служит функция-обработчик onempty. ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!' }, {'Синюю', 'Вот!' }, onempty = function() p [[Ты сделал свой выбор.]] pop() end; }, { cond = function() return have 'яблоко' end, 'А хотите яблоко?', 'Спасибо, нет.' }; } ``` Обратите внимание, что когда есть метод onempty, автоматический возврат в предыдущую ветку не производится, предполагается, что метод onempty сделает всё, что нужно. Все описанные атрибуты могут быть установлены у любой фразы. В том числе и на 1-м уровне: ``` phr = { onempty = function() p [[Вот и поговорили.]] walkout() end; { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!' }, {'Синюю', 'Вот!' }, onempty = function() p [[Ты сделал свой выбор.]] pop() end; }, { cond = function() return have 'яблоко' end, 'А хотите яблоко?', 'Спасибо, нет.' }; } ``` ### Теги Только что мы рассмотрели механизмы диалогов, которые уже позволяют создавать довольно сложные диалоги. Однако, и этих средств может не хватить. Иногда нам нужно уметь обращаться к фразам из других мест диалога. Например, выборочно включать их, или анализировать их состояние. А также делать переходы из одних ветвей диалога в другие. Всё это возможно для фраз, у которых есть тег. Создать фразу с тегом очень просто: ``` phr = { { '#что?', 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', {'#красная', 'Красную', 'Держите!' }, {'#синяя', 'Синюю', 'Вот!' }, }, } ``` Как видим, наличие в начале фразы строки, которая начинается на символ '#' - означает наличие тега. Для таких фраз работают стандартные методы, такие как seen или enable/disable. Например, мы могли бы обойтись без атрибута only следующим образом: ``` phr = { { '#что?', 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', {'#красная', 'Красную', 'Держите!' cond = function(s) return not closed('#синяя') end }, {'#синяя', 'Синюю', 'Вот!', cond = function(s) return not closed('#красная') end }, }, } ``` Теги, кроме того, что позволяют узнавать и менять состояние конкретных фраз, делают возможным переходы между фразами. Для этого используются функции push и pop. push(куда) -- делает переход на фразу с запоминанием позиции в стеке. pop([куда]) -- вызванная без параметра, поднимается на 1 позицию в стеке истории. Можно указать конкретный тег фразы, которая должна быть в истории, в таком случае возврат будет осуществлён на неё. Нужно отметить, что при переходе по push, мы переходим не на одну фразу, а на список фраз этой фразы. То-есть раскрываем ее, также как это сделано для главной фразы phr. Например: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!', next = '#отаблетке' }, { 'Синюю', 'Вот!', next = '#отаблетке' }, }, { false, '#отаблетке', {'Я сделал верный выбор?', 'Время покажет.'} }, } ``` Тут мы видим сразу несколько приёмов: - атрибут next, вместо явного описания реакции в виде функции с push. next -- это простой способ записать push. - false в начале фразы, делает фразу выключенной. Она находится в состоянии выключена, пока не сделать явный enable. Однако внутрь фразы мы можем перейти, и показать содержимое выборов. Альтернативная запись возможна с использованием атрибута hidden: ``` { hidden = true, '#отаблетке', {'Я сделал верный выбор?', 'Время покажет.'} }, ``` Таким образом можно записывать диалоги не древовидно, а линейно. Ещё одна особенность переходов состоит в том, что если у фразы не описана реакция, то при переходе будет вызван заголовок фразы: ``` phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!', next = '#отаблетке' }, { 'Синюю', 'Вот!', next = '#отаблетке' }, }, { false, '#отаблетке', [[Я взял таблетку и мастер хитро улыбнулся.]], {'Я сделал верный выбор?', 'Время покажет.'}, {'Что делать дальше?', 'Ты свободен.'}, }, } ``` При выборе таблетки, будет вызван заголовочный метод фразы '#отаблетке', а уже потом будет представлен выбор. Если вам нравится линейная запись, вы можете предпочесть следующий вариант: ``` dlg { nam = 'диалог'; phr = { { 'Что это у вас?', 'Таблетки. Красная и синяя. Вам какую?', only = true, {'Красную', 'Держите!', next = '#отаблетке' }, { 'Синюю', 'Вот!', next = '#отаблетке' }, } } }:with { { '#отаблетке', [[Я взял таблетку и мастер хитро улыбнулся.]], {'Я сделал верный выбор?', 'Время покажет.'}, {'Что делать дальше?', 'Ты свободен.'}, }, } ``` Дело в том, что атрибут phr диалога задаёт первый объект комнаты. Но вы можете заполнить объекты комнаты обычным образом: задав obj или with. Так как при входе в диалог раскрывается 1-я фраза, то остальные фразы вы не увидите (обратите внимания, у фразы '#отаблетке' не стоит false), но вы сможете делать переходы на эти фразы. ### Методы Как вы уже знаете, объекты в INSTEAD могут находиться в состоянии открыт/закрыт и выключен/включён. Как это соответствует фразам диалога? Для обычных фраз, после активации выбора фраза _закрывается_. При повторном входе в диалог все фразы _открываются_. Для фраз с always = true (или true в начале определения) -- такого закрытия не происходит. Для фраз с hidden = true (или false в начале определения) -- фраза будет создана как выключенная. Она не будет видима до тех пор, пока не будет явно включена. Для фраз с cond(), каждый раз при просмотре фраз вызывается этот метод, и в зависимости от возвращаемого значения (true/не true) фраза включается или выключается. Зная это поведение, вы можете прятать/показывать и анализировать фразы обычными функциями вида: disable / enable / empty / open / close / closed / disabled и так далее... Однако, делать вы это можете только в самом диалоге, так как все фразы идентифицируются по тегам. Если вы хотите модифицировать состояние/анализировать фразы из других комнат вы можете: - дать фразе имя { nam = 'имя' }... - искать фразу по тегу в другой комнате: local ph = lookup('#тег', 'диалог') и потом работать с ней; Что касается функций push/pop, то вы можете вызывать их явно как методы диалога, например: ``` _'диалог':push '#новая' ``` Но лучше это делать в самом диалоге, например, в enter. Кроме того, есть метод :reset, который сбрасывает стек переходов и устанавливает стартовую фразу, например: ``` enter = function(s) s:reset '#начало' end ``` > Следует отметить, что когда вы делаете enable/disable/open/close > фразы, то вы выполняете действие именно над этой фразой, а не над > фразами включёнными внутрь. Но так как при показе фраз движок > остановится на выключенном/закрытом объекте-фразе и не войдёт > внутрь, этого достаточно. ## Специальные объекты В STEAD3 существуют специальные объекты, которые выполняют специфические функции. Все такие объекты можно разделить на два класса: 1. Системные объекты @; 2. Подстановки $. Системные объекты, это объекты, чьё имя начинается с символа '@' или '$'. Такие объекты обычно создаются в _модулях_. Они не уничтожаются при смерти игрового мира (например, при подгрузке gamefile, при загрузке игры из сохранения, и так далее). Примеры объектов: @timer, @prefs, @snd. Такие объекты, кроме своих специальных функций, могут быть использованы по ссылке, без явного помещения объекта в сцену или инвентарь, но механизм действия таких объектов -- особенный. ### Объект '@' Обычно, вам не нужно работать с такими объектами, но в качестве примера рассмотрим реализацию 'ссылок'. Пусть мы хотим сделать ссылку, при нажатии на которую мы перейдём в другую комнату. Конечно, мы могли бы добавить объект в сцену, но стоит ли это делать в таком простом случае? Как нам может помочь системный объект? ``` obj { nam = '@walk'; act = function(s, w) walk(w, false, false) end; } room { nam = 'main'; title = 'Начало'; decor = [[Начать {@walk старт|приключение}]]; } ``` При нажатии на ссылку "приключение" будет вызван метод act объекта '@walk' с параметром "старт". На самом деле, в стандартной библиотеке stdlib уже есть объект, с именем '@', который позволяет делать свои обработчики ссылок следующим образом: ``` xact.walk = walk room { nam = 'main'; title = 'Начало'; decor = [[Начать {@ walk старт|приключение}]]; } ``` Обратите внимание, на пробел после @. Данная запись делает следующее: - берет объект '@' (такой объект создан библиотекой stdlib); - берет его act; - вызывает act с параметрами walk и старт; - act объекта '@' смотрит в массив xact; - walk определяет метод, который будет вызван из массива xact; - старт -- параметр этого метода. Другой пример: ``` xact.myprint = function(w) p (w) end room { nam = 'main'; title = 'Начало'; decor = [[Нажми {@ myprint "hello world"|на кнопку}]]; } ``` ### Подстановки Объекты, чьё имя начинается на символ '$' тоже считаются системными объектами, но работают они по-другому. Если в выводе текста встречается "ссылка" вида: ``` {$my a b c|текст} ``` То происходит следующее: 1. Берётся объект $my; 2. Берётся act объекта $my; 3. Вызывается act: _'$my':(a, b, c, текст); 4. Возвращаемая строка заменяет собой всю конструкцию {...}. Таким образом, объекты играют роль подстановки. Зачем это нужно? Представьте себе, что вы разработали модуль, который превращает записи формул из текстового вида в графические. Вы пишете объект $math который в своём act методе превращает текст в графическое изображение (спрайт) и возвращает его в текстовый поток. Тогда пользоваться таким модулем крайне просто, например: ``` {$math|(2+3*x)/y^2} ``` ## Динамические события Вы можете определять обработчики, которые выполняются каждый раз, когда время игры увеличивается на 1. Обычно, это имеет смысл для живых персонажей, или каких-то фоновых процессов игры. Алгоритм шага игры выглядит примерно так: - Игрок нажимает на ссылку; - Реакция 'act', 'use'', 'inv', 'tak', осмотр сцены (клик по названию сцены) или переход в другую сцену; - Динамические события; - Вывод нового состояния сцены. Например, сделаем Барсика живым: ``` obj { nam = 'Барсик'; { -- не сохранять массив lf lf = { [1] = 'Барсик шевелится у меня за пазухой.', [2] = 'Барсик выглядывает из-за пазухи.', [3] = 'Барсик мурлычит у меня за пазухой.', [4] = 'Барсик дрожит у меня за пазухой.', [5] = 'Я чувствую тепло Барсика у себя за пазухой.', [6] = 'Барсик высовывает голову из-за пазухи и осматривает местность.', }; }; life = function(s) local r = rnd(5); if r > 2 then -- делать это не всегда return; end r = rnd(#s.lf); -- символ # -- число элементов в массиве p(s.lf[r]); -- выводим одно из 6 состояний Барсика end; ... ``` И вот момент в игре, когда Барсик попадает к нам за пазуху! ``` take 'Барсик' -- добавить в инвентарь lifeon 'Барсик' -- оживить Барсика! ``` Любой объект (в том числе и сцена) могут иметь свой обработчик 'life', который вызывается каждый такт игры, если объект был добавлен в список живых объектов с помощью 'lifeon'. Не забывайте удалять живые объекты из списка с помощью 'lifeoff', когда они больше не нужны. Это можно сделать, например, в обработчике 'exit', или любым другим способом. > Если в вашей игре много "живых" объектов, вы можете задавать им > явную позицию в списке, при добавлении. Для этого, воспользуйтесь > вторым числовым параметром (целое неотрицательное число) 'lifeon', > чем меньше число, тем выше приоритет. 1 -- самый высокий. Или вы > можете использовать атрибут pri у объекта. Правда, этот атрибут > будет влиять на приоритет объекта в любом списке. Если вам нужен фоновый процесс в какой-то комнате, запускайте его в 'enter' и удаляйте в 'exit', например: ``` room { nam = 'В подвале'; dsc = [[Тут темно!]]; enter = function(s) lifeon(s); end; exit = function(s) lifeoff(s); end; life = function(s) if rnd(10) > 8 then p [[Я слышу какие-то шорохи!]]; -- изредка пугать игрока шорохами end end; way = { 'Дом' }; } ``` Если вам нужно определить, был ли переход игрока из одной сцены в другую, воспользуйтесь 'player\_moved()'. ``` obj { nam = 'фонарик'; on = false; life = function(s) if player_moved() then -- гасить фонарик при переходах s.on = false p "Я выключил фонарик." return end; end; ... } ``` Для отслеживания протекающих во времени событий, используйте 'time()' или вспомогательную переменную-счётчик. Для определения местоположения игрока -- 'here()'. Для определения факта, что объект "живой" -- 'live()'. ``` obj { nam = 'динамит'; timer = 0; used = function(s, w) if w^'спичка' then -- спичка? if live(s) then return "Уже горит!" end p "Я поджёг динамит." lifeon(s) return end return false -- если не спичка end; life = function(s) s.timer = s.timer + 1 if s.timer == 5 then lifeoff(s) if here() == where(s) then p [[Динамит взорвался рядом со мной!]] else p [[Я услышал, как взорвался динамит.]]; end end end; ... } ``` Если 'life' обработчик возвращает текст события, он печатается после описания сцены. Вы можете вернуть из обработчика 'life' второй код возврата, ('true' или 'false'). Если вы вернёте true, то это будет признаком важного события, которое выведется до описания объектов сцены, например: ``` p 'В комнату вошёл охранник.' return true ``` Или: ``` return 'В комнату вошёл охранник.', true ``` Если вы вернёте false, то цепочка life методов прервётся на вас. Это удобно делать при выполнении walk из метода life, например: ``` life = function() walk 'theend' return false -- это последний life end ``` Если вы хотите блокировать 'life' обработчики в какой-то из комнат, воспользуйтесь модулем 'nolife'. Например: ``` require "noinv" require "nolife" dlg { nam = 'Охранник'; noinv = true; nolife = true; ... } ``` Отдельно стоит рассмотреть вопрос перехода игрока из 'life' обработчика. Если вы собираетесь использовать функции 'walk' внутри 'life', то вам следует учитывать следующее поведение. Если 'life' переносит игрока в новую локацию, то обычно предполагается что вы: 1. Очищаете вывод реакций: game:reaction(false); 2. Очищаете вывод живых методов на данный момент: game:events(false, false) 3. Делаете walk. 4. Останавливаете цепочку life вызовов с помощью return false; Некоторые моменты требуют пояснений. game:reaction() -- позволяет взять/изменить вывод реакции пользователя, если задать его в false это означает сбросить реакцию. game:events() -- позволяет взять/изменить вывод life методов. В качестве параметров принимаются приоритетные и не приоритетные сообщения, задав false, false мы отменили весь вывод предыдущих life методов. В стандартной библиотеке уже есть функция life_walk(), которая делает описанные действия. Вам остаётся только вернуть false. ## Графика Графический интерпретатор INSTEAD анализирует атрибут сцены 'pic', и воспринимает его как путь к картинке, например: ``` room { pic = 'gfx/home.png'; nam = 'Дома'; dsc = 'Я у себя дома'; }; ``` __Важно!__ Используйте в путях только прямые '/'. Также, настоятельно рекомендуется использовать в именах каталогов и файлов только латинские строчные символы. Этим самым вы обезопасите свою игру от проблем с совместимостью и она будет работать на всех архитектурных платформах, куда портирован INSTEAD. Конечно, 'pic' может быть функцией, расширяя возможности разработчика. Если в текущей сцене не определён атрибут 'pic', то берётся атрибут 'game.pic'. Если не определён и он, то картинка не отображается. Поддерживаются все наиболее распространённые форматы изображений, но я рекомендую вам использовать 'png' и (когда важен размер) 'jpg'. Вы можете использовать в качестве картинок анимированные gif файлы. Вы можете встраивать графические изображения прямо в текст, в том числе в инвентарь, переходы, заглавия комнат и 'dsc' с помощью функции 'fmt.img' (Для этого включите модуль fmt). Например: ``` require "fmt" obj { nam = 'яблоко' disp = 'Яблоко'..fmt.img('img/apple.png'); } ``` Тем-не менее, картинку сцены всегда следует оформлять в виде 'pic' атрибута, а не вставки 'fmt.img' в 'dsc' комнаты. Дело в том, что картинка сцены масштабируется по другому алгоритму. Картинки 'fmt.img' масштабируются в соответствии с настройками INSTEAD (масштаб темы), а 'pic' -- учитывает также размер картинки. Кроме того, картинки 'pic' обладают и другими свойствами, например, возможностью отслеживания координат кликов мышью. Если вы поместите 'fmt.img' внутрь { и }, то получите графическую ссылку. ``` obj { nam = 'яблоко'; disp = 'яблоко ' ..img('img/apple.png'); dsc = function(s) p ("На полу лежит {яблоко",fmt.img 'img/apple.png', "}"); -- другие варианты: -- return "На полу лежит {яблоко"..fmt.img('img/apple.png').."}"; -- p "На полу лежит {яблоко"..fmt.img('img/apple.png').."}"; -- или dsc = "На полу лежит {яблоко"..fmt.img('img/apple.png').."}"; end; } ``` INSTEAD поддерживает обтекание картинок текстом. Если картинка вставляется с помощью функции 'fmt.imgl'/'fmt.imgr', она будет расположена у левого/правого края. __Важно!__ > Картинки, вставленные в текст с помощью 'fmt.imgl/fmt.imgr' не могут быть > ссылками!!! Используйте их только в декоративных целях. Для задания отступов вокруг изображения используйте 'pad', например: ``` fmt.imgl 'pad:16,picture.png' -- отступы по 16 от каждого края fmt.imgl 'pad:0 16 16 4,picture.png' -- отступы: вверху 0, справа 16, внизу 16, слева 4 fmt.imgl 'pad:0 16,picture.png' -- отступы: вверху 0, справа 16, внизу 0, слева 16 ``` Вы можете использовать псевдо-файлы для изображений прямоугольников и пустых областей: ``` dsc = fmt.img 'blank:32x32'..[[Строка с пустым изображением.]]; dsc = fmt.img 'box:32x32,red,128'..[[Строка красным полупрозрачным квадратом.]]; ``` INSTEAD может обрабатывать составные картинки, например: ``` pic = 'gfx/mycat.png;gfx/milk.png@120,25;gfx/fish.png@32,32'; ``` Таким образом, составная картинка представляет собой набор путей к изображениям, разделённых символом ';'. Вторая и последующие компоненты могут содержать постфикс в виде @x\_координата,y\_координата%, где координате 0,0 соответствует левый верхний угол всего изображения. Общий размер картинки считается равным общему размеру первой компоненте составной картинки, то есть, первый компонент (в нашем примере -- gfx/mycat.png) играет роль холста, а последующие компоненты накладываются на этот холст. Наложение происходит для левого верхнего угла накладываемой картинки. Если вам нужно, чтобы наложение происходило относительно центра накладываемой картинки, используйте перед координатами префикс ''c'', например: ``` pic = 'gfx/galaxy.png;gfx/star.png@c128,132'; ``` Оформив в виде функции формирование пути составной картинки, вы можете генерировать изображение на основе игрового состояния. Если вы в своей игре привязываетесь к каким-то координатам изображений, или к их размерам, делайте это относительно оригинальных размеров изображений. При масштабировании темы под заданное игроком разрешение, INSTEAD сам будет осуществлять пересчёт координат (при этом координаты для игры выглядят так, как будто игра запущена без масштабирования). Однако, возможны небольшие погрешности вычислений. Если вам не хватает функций, описанных в этой главе, изучите модуль "sprite", который предоставляет более широкие возможности по графическому оформлению. Но я крайне не рекомендую делать это в своей первой игре. ## Музыка Для работы с музыкой и звуками вам понадобится модуль snd. ``` require "snd" ``` Интерпретатор проигрывает в цикле текущую музыку, которая задаётся с помощью функции: 'snd.music(путь к музыкальному файлу)'. __Важно!__ Используйте в путях только прямые '/'. Также, настоятельно рекомендуется использовать в именах каталогов и файлов только латинские строчные символы. Этим самым вы обезопасите свою игру от проблем с совместимостью и она будет работать на всех архитектурных платформах, куда портирован INSTEAD. Поддерживается большинство музыкальных форматов, но настоятельно рекомендуется использовать формат 'ogg', так как именно он поддерживается наилучшим образом во всех версиях INSTEAD (для различных платформ). __Важно!__ Следует проявлять осторожность при использовании трекерной музыки, так как в некоторых дистрибутивах Linux могут быть проблемы при проигрывании определённых файлов (ошибки в связке библиотек SDL_mixer и libmikmod). Также, если вы используете 'mid' файлы, будьте готовы к тому, что игрок услышит их только в Windows версии INSTEAD (так как в большинстве случаев, Unix версии SDL_mixer собраны без поддержки ''timidity''). В качестве частоты музыкальных файлов используйте частоты кратные 11025. ``` room { pic = 'gfx/street.png'; enter = function() snd.music 'mus/rain.ogg' end; nam = 'на улице'; dsc = 'На улице идёт дождь.'; }; ``` 'snd.music()' без параметра возвращает текущее имя трека. В функцию 'snd.music()' можно передавать второй параметр -- количество проигрываний (циклов). Получить текущий счётчик можно с помощью 'snd.music()' без параметров -- второе возвращаемое значение. 0 -- означает вечный цикл. 1..n -- количество проигрываний. -1 -- проигрывание текущего трека закончено. Для того, чтобы отменить проигрывание музыки, вы можете использовать 'snd.stop\_music()' Для того, чтобы узнать, играет ли музыка: ``` snd.music_playing() ``` Вы можете задавать время нарастания и затухания музыки, с помощью вызова: ``` snd.music_fading(o, [i]) ``` Здесь o - время в мс. для затухания и i - время в мс. для нарастания музыки. Если задан только один параметр -- оба времени считаются одинаковыми. После вызова, установленные параметры будут влиять на проигрывание всех музыкальных файлов. Для проигрывания звуков используйте 'snd.play()'. Настоятельно рекомендуется использовать формат 'ogg', хотя большинство распространённых звуковых форматов также будет работать. Различие между музыкой и звуковым файлом заключается в том, что движок следит за процессом проигрывания музыки и сохраняет/восстанавливает текущий проигрываемый трек. Выйдя из игры и загрузив её снова, игрок услышит то же музыкальное оформление, что слышал при выходе. Звуки обычно означают кратковременные эффекты, и движок не сохраняет и не восстанавливает звуковые события. Так, если игрок не успел дослушать звук выстрела и вышел из игры, после загрузки файла сохранения он не услышит звук (или его окончание) снова. Тем не менее, если учесть то, что 'snd.play()' позволяет запускать зацикленные звуки, то различие между музыкой и звуками становится уже не таким однозначным. Итак, определение функции: 'snd.play(файл, [канал], [цикл])', где: - файл -- путь и\или имя звукового файла; - канал -- номер канала [0..7]; Если не указан, то выберется первый свободный. - цикл -- количество проигрываний 1..n, 0 -- зацикливание. Для остановки проигрывания звука можно использовать 'snd.stop()'. Для остановки звука в определённом канале 'snd.stop(канал)'. __Важно!__ > Если вы используете зацикленные звуки, вам придётся самим > восстанавливать их состояние (запускать снова с помощью > 'snd.sound()') в функции 'start()' Например: ``` global 'wind_blow' (false) ... function start() if wind_blow then snd.play('snd/wind.ogg', 0) end end ``` Если вам недостаточно описанных здесь функций по работе со звуком, используйте полное описание модуля "snd". ## Форматирование и оформление вывода Обычно INSTEAD сам занимается форматированием и оформлением вывода. Например, отделяет статическую сцену от динамической. Выделяет курсивом действия игрока. Переводит фокус на изменение в тексте и т.д. Модули вроде "fmt" улучшают качество вывода игры без дополнительных усилий со стороны автора. Например: ``` require 'fmt' fmt.para = true -- включить отступы параграфов ``` И ваша игра будет выглядеть гораздо лучше. Если вам нужна какая-то автоматическая обработка выводимого текста, вы можете включить модуль "fmt" и определить функцию 'fmt.filter'. Например: ``` require "fmt" fmt.filter = function(s, state) -- s -- вывод -- state -- true, если это такт игры (вывод сцены) if state then return 'Эта строка будет добавлена к началу вывода\n'..s; end return s end ``` Многие хорошие игры на INSTEAD никак не занимаются своим оформлением, кроме разбиения текста 'dsc' на параграфы с помощью символов '^^', поэтому подумайте, а так ли вам хочется заниматься оформлением своей игры вручную? Тем не менее, иногда это всё-таки необходимо. > Внимание! По умолчанию, все конечные и начальные переводы строк, > пробелы и символы табуляции вырезаются из вывода обработчиков. Так > как обычно они не имеют смысла и даже вредны. В редких случаях, > автору может понадобиться более полный контроль над выводом, тогда он > может задать std.strip\_call как false в init() или start(), > например: ``` std.strip_call = false obj { dsc = [[Тут лежит {яблоко}.^^^^]] -- теперь переводы строк -- не будут вырезаны, хотя это странное желание } ``` > Но обычно такое ручное форматирование свидетельствует о плохом > стиле. Для оформления сцены лучше использовать decor и/или > подстановки $. ### Форматирование Вы можете делать простое форматирование текста с помощью функций: - fmt.c(строка) - разместить по центру; - fmt.r(строка) - разместить справа; - fmt.l(строка) - разместить слева; - fmt.top(строка) - сверху строки; - fmt.bottom(строка) - снизу строки; - fmt.middle(строка) - середина строки (по умолчанию). Например: ``` room { nam = 'main'; title = 'Добро пожаловать'; dsc = fmt.c 'Добро пожаловать!'; -- если у функции только 1 параметр, -- скобки можно опускать; } ``` Вышеописанные функции влияют не только на текст, но и на изображения, вставленные с помощью ''fmt.img()'. Следует отметить, что если вы используете несколько функций форматирования, то предполагается, что они относятся к разным строкам (параграфам). В противном случае, результат не определён. Разбивайте текст на абзацы символами '^' или 'pn()'. INSTEAD при выводе удаляет лишние пробелы. Это значит, что неважно сколько пробелов вы вставляете между словами, всё равно при выводе они не будут учитываться для расчёта расстояния между словами. Иногда это может стать проблемой. Вы можете создавать _неразрывные строки_ с помощью: fmt.nb(строка). Например, модуль "fmt" использует неразрывные строки для создания отступов в начале параграфов. Также, 'fmt.nb' может оказаться удобной для вывода служебных символов. Можно сказать, что вся строка-параметр 'fmt.nb' воспринимается движком как одно большое слово. Ещё один пример. Если вы используете подчёркивание текста, то промежутки между словами не будут подчёркнуты. При использовании 'fmt.nb' промежутки также будут подчёркнуты. INSTEAD не поддерживает отображение таблиц, однако для вывода простых табличных данных можно воспользоваться 'fmt.tab()'. Эта функция используется для абсолютного позиционирования в строке (табулятор). fmt.tab(позиция, [центр]) _Позиция_, это текстовый или числовой параметр. Если задан числовой параметр, он воспринимается как позиция в пикселях. Если он задан в виде строкового параметра 'число%', то он воспринимается как позиция, выраженная в процентах от ширины окна вывода сцены. Необязательный строковой параметр _центр_ задаёт позицию в следующем за 'fmt.tab' слове, которая будет размещена по указанному смещению в строке. Позиции могут быть следующими: - left; - right; - center. По умолчанию считается что задан параметр "left". Так, например: ``` room { nam = 'main'; disp = 'Начало'; -- размещение 'Начало!' по центру строки dsc = fmt.tab('50%', 'center')..'Начало!'; } ``` Конечно, не очень удачный пример, так как то же самое можно было сделать с помощью 'fmt.c()'. Более удачный пример. dsc = function(s) p(fmt.tab '0%') p "Слева"; p(fmt.tab '100%', 'right') p "Справа"; end На самом деле, единственная ситуация, когда применение 'fmt.tab()' оправдано -- это вывод табличных данных. Следует отметить, что в ситуации, когда мы пишем что-то вроде: ``` -- размещение 'Раз' по центру строки dsc = fmt.tab('50%', 'center')..'Раз два три!'; ``` Только слово 'Раз' будет помещено в центр строки, остальные слова будут дописаны справа от этого слова. Если вы хотите центрировать 'Раз два три!' как одно целое, воспользуйтесь 'fmt.nb()'. ``` -- размещение 'Раз два три!' по центру строки dsc = fmt.tab('50%', 'center')..fmt.nb ('Раз два три!'); ``` В INSTEAD также существует возможность выполнять простое вертикальное форматирование. Для этого используйте вертикальный табулятор: fmt.y(позиция, [центр]) Как и в случае с fmt.tab _позиция_, это текстовый или числовой параметр. Здесь он воспринимается как позиция строки, выраженная в пикселях или процентах от высоты области сцены. Например, 100% -- соответствует нижней границе области сцены. 200% -- соответствует нижней границе второй страницы вывода (две высоты области вывода сцены). Необязательный строковой параметр _центр_ задаёт позицию внутри строки, относительно которой выполняется позиционирование: - top (по верхнему краю); - middle (по центру); - bottom (по нижнему краю -- значение по умолчанию). Следует отметить, что 'fmt.y' работает целиком для строки. Если в строке встретится несколько fmt.y, действовать будет последний из табуляторов. ``` -- размещение 'ГЛАВА I' - в центре сцены dsc = fmt.y('100%').."ГЛАВА I"; ``` _Если позиция, указанная табулятором, уже занята другой строкой, табулятор игнорируется._ По умолчанию, статическая часть сцены отделяется от динамической двойным переводом строки. Если вам это не подходит, вы можете переопределить 'std.scene_delim', например: std.scene_delim = '^' -- одинарный перевод строки Вы не можете менять эту переменную в обработчиках, так как она не сохраняется, но вы можете задать её для игры целиком, или восстанавливать её вручную в функции 'start()'. Если вас категорически не устраивает то, как INSTEAD формирует вывод (последовательность абзацев текста), вы можете переопределить функцию 'game.display()', которая по умолчанию выглядит следующим образом: ``` game.display = function(s, state) local r, l, av, pv local reaction = s:reaction() or nil -- реакция r = std.here() if state then -- такт игры? reaction = iface:em(reaction) -- курсив av, pv = s:events() av = iface:em(av) -- вывод "важных" life pv = iface:em(pv) -- вывод фоновых life l = s.player:look() -- objects [and scene] -- объекты и сцена end l = std.par(std.scene_delim, reaction or false, av or false, l or false, pv or false) or '' return l end; ``` Тот факт, что я привёл здесь этот код, не означает, что я рекомендую переопределять эту функцию. Напротив, я категорически против такой сильной привязки к форматированию текста. Тем не менее, иногда возникает ситуация, когда полный контроль за последовательностью вывода необходим. Если вы пишите свою первую игру, просто пропустите этот текст. ### Оформление Вы можете менять начертание текста с помощью комбинаций функций: - fmt.b(строка) - жирный текст; - fmt.em(строка) - курсив; - fmt.u(строка) - подчёркнутый текст; - fmt.st(строка) - перечёркнутый текст. Например: ``` room { nam = 'Intro'; title = false; dsc = function(s) p ('Вы находитесь в комнате: ') p (fmt.b(s)) end; } ``` > Используя функции 'fmt.u' и 'fmt.st' на строках, содержащих пробелы, > вы получите разрывы линий в этих местах. Что избежать этого, можно > превратить текст в _неразрывную строку_: fmt.u(fmt.nb "теперь текст без пропусков" ) Строго говоря, INSTEAD не поддерживает одновременный вывод разными шрифтами в окно сцены (если не считать разное начертание), поэтому если вам всё-таки требуется более гибкий контроль вывода, вы можете сделать следующее: - Использовать графические вставки 'fmt.img()'; - Использовать модуль 'fonts', в котором реализована отрисовка разными шрифтами за счёт модуля 'sprite'; - Использовать другой движок, так как скорее всего вы используете INSTEAD не по назначению. ## Конструкторы и наследование __Внимание!__ Если вы пишите свою первую игру, было бы лучше, если бы она была простая. Для простой игры информация из этой главы не понадобится. Более того, 90% игр на INSTEAD не использует вещей, описанных в этой главе! Если вы пишите игру, в которой много однотипных объектов, возможно, вам захочется упростить их создание. Это можно сделать одним из следующих способов: - Создать свой конструктор; - Создать новый класс объектов. ### Конструкторы Конструктор -- это функция, которая создаёт за вас объект и заполняет его атрибуты так, как вам это нужно. Рассмотрим пример. Допустим, в вашей игре будет много окон. Нужно создавать окна, любое окно можно разбить. Мы можем написать конструктор 'window'. ``` window = function(v) v.window = true v.broken = false if v.dsc == nil then v.dsc = 'Здесь есть {окно}.' end v.act = function(s) if s.broken then p [[Окно разбито.]] else p [[За окном темно.]] end end if v.used == nil then v.used = function(s, w) if w^'молоток' then if s.broken then p [[Окно уже разбито.]] else p [[Я разбил окно.]] s.broken = true; end return end return false end end return obj(v) end ``` Как видим, идея конструкторов проста. Вы просто создаёте функцию, которая получает на вход таблицу с атрибутами {}, которую конструктор может дозаполнить нужными атрибутами. Затем эта таблица передаётся конструктору obj/room/dlg и возвращается полученный объект. Теперь, создавать окна стало легко: ``` window { dsc = [[Тут есть {окно}.]]; } ``` Или, так как окно -- это обычно статический объект, можно создавать его прямо в 'obj'. ``` obj = { window { dsc = 'В восточной стене есть {окно}.'; } }; ``` У нашего окна будет готовый used метод и act метод. Вы можете проверить тот факт, что объект окно -- просто проверив признак window: ``` use = function(s, w) if w.window then p [[Действие на окно.]] return end return false end ``` Состояние "разбитости" окна, это атрибут broken. Как реализовать наследование в конструкторах? На самом деле, в примере выше уже используется наследование. Действительно, ведь конструктор 'window'' вызывает другой конструктор 'obj', тем самым получая все свойства обычного объекта. Также, 'window' определяет переменную признак 'window', чтобы в игре мы могли понять, что мы имеем дело с окном. Например: Для иллюстрации механизма наследования создадим класс объектов 'treasure', то есть сокровищ. ``` global { score = 0 } treasure = function() local v = {} v.disp = 'сокровище' v.treasure = true v.points = 100 v.dsc = function(s) p ('Здесь есть {', std.dispof(s), '}.') end; v.inv = function(s) p ('Это же ', std.dispof(s), '.'); end; v.tak = function(s) score = score + s.points; -- увеличим счёт p [[Дрожащими руками я забрал сокровища.]]; end return obj(v) end ``` А теперь, на его основе создадим золото, алмаз и сундук. ``` gold = function(dsc) local v = treasure(); v.disp = 'золото'; v.gold = true; v.points = 50; v.dsc = dsc; return v end diamond = function(dsc) local v = treasure(); v.disp = 'алмаз'; v.diamond = true; v.points = 200; v.dsc = dsc; return v end chest = function(dsc) local v = treasure(); v.disp = 'сундук'; v.chest = true v.points = 1000; v.dsc = dsc; return v end ``` Теперь, в игре можно создавать сокровища через конструкторы: ``` diamond1 = diamond("В грязи я заметил {алмаз}.") diamond2 = diamond(); -- тут будет стандартное описание алмаза gold1 = gold("В углу я заметил блеск {золота}."); room { nam = 'пещера'; obj = { diamond1, gold1, chest("А ещё я вижу {сундук}!") }; } ``` На самом деле, как именно писать функции-конструкторы и реализовывать принцип наследования, зависит только от вас. Выберете наиболее простой и понятный способ. При написании конструкторов иногда бывает полезным сделать вызов обработчика так, как это делает INSTEAD. Для этого используется 'std.call(объект, метод, параметры)', при этом эта функция вернёт реакцию атрибута в виде строки. Например, рассмотрим модификацию 'window', которая заключается в том, что можно определять свою реакцию на осмотр окна, которая будет выполнена после стандартного сообщения о том, что это разбитое окно (если оно разбито). ``` window = function(nam, dsc, what) local v = {} -- создаём пустую таблицу -- заполняем её v.window = true v.what = what v.broken = false if dsc == nil then v.dsc = 'Здесь есть {окно}' end v.act = function(s) if s.broken then p [[Окно разбито.]] end local r, v = stead.call(s, 'what') if v then -- обработчик выполнился? p(r) else p [[За окном темно.]] end end return obj(v) end ``` Таким образом, мы можем при создании окна задать третий параметр, в котором определить функцию или строку, которая будет реакцией во время осмотра окна. При этом сообщение о том, что окно разбито (если оно действительно разбито), будет выведено перед этой реакцией. ### Класс объектов Конструкторы объектов широко использовались в STEAD2. В STEAD3 obj/dlg/room реализованы как классы объектов. Класс объектов удобно создавать для тех случаев, когда поведение создаваемого объекта не укладывается в стандартные объекты obj/room/dlg и вы хотите поменять методы класса. Изменив метод класса, например, вы можете вообще изменить то, как выглядит предмет в сцене. В качестве примера, рассмотрим создание класса "контейнер". Контейнер может хранить в себе другие объекты, быть закрытым и открытым. ``` -- создаём собственный класс контейнера cont = std.class({ -- создаём класс cont __cont_type = true; -- для определения типа объекта display = function(s) -- переопределяем метод показа предмета local d = std.obj.display(s) if s:closed() or #s.obj == 0 then return d end local c = s.cont or 'Внутри: ' -- описатель содержимого local empty = true for i = 1, #s.obj do local o = s.obj[i] if o:visible() then empty = false if i > 1 then c = c .. ', ' end c = c..'{'..std.nameof(o)..'|'..std.dispof(o)..'}' end end if empty then return d end c = c .. '.' return std.par(std.space_delim, d, c) end; }, std.obj) -- мы наследуемся от стандартного объекта ``` После этого, вы можете создавать контейнеры так: ``` cont { nam = 'ящик'; dsc = [[Тут есть {ящик}.]]; cont = 'В ящике: '; }: with { 'яблоко', 'груша'; } ``` Когда контейнер будет открыт, вы увидите описание ящика, а также содержимое ящика в виде строки ссылок: 'В ящике: яблоко, груша.' dsc объектов яблоко и груша будут тоже показаны, если они заданы. Если необходимо прятать dsc объектов при открытии контейнера, оставляя лишь имена объектов, то можно выполнить следующую модификацию: ``` -- заменим функцию показа любого объекта -- если объект внутри контейнера, не вызывать его dsc std.obj.display = function(self) local w = self:where() -- где объект? if not std.is_obj(w, 'cont') then -- если не в контейнере local d = std.call(self, 'dsc') return d end end ``` К сожалению, подробное описание классов выходит за рамки данного руководства, эти вещи будут описаны в другом руководстве для разработчиков модулей. А пока, для вашей первой игры, вам не стоит писать свои классы объектов. ## Полезные советы ### Разбиение на файлы Когда ваша игра становится большой, размещение её кода целиком в 'main3.lua' -- плохая идея. Для разбиения текста игры на файлы вы можете использовать 'include'. Вы должны использовать 'include' в глобальном контексте таким образом, чтобы во время загрузки 'main3.lua' загрузились и все остальные фрагменты игры, например. ``` -- main3.lua include "episode1" -- .lua можно опускать include "npc" include "start" room { nam = 'main'; ... ``` Как именно разбивать исходный текст на файлы зависит только от вас. Я использую файлы в соответствии с эпизодами игры (которые обычно слабо связаны между собой), но можно создавать файлы, хранящие отдельно комнаты, объекты, диалоги и т.д. Это вопрос личного удобства. Также есть возможность динамически подгружать части игры (с возможностью доопределять объекты). Для этого вы можете воспользоваться функцией 'gamefile': ``` ... act = function() gamefile ("episode2") end -- .lua можно опускать ... ``` > Внимание! Если в вашей игре определена функция init(), то в > подгружаемых частях она также должна присутствовать! В противном > случае, после подгрузки файла, будет вызвана текущая функция init(), > что обычно не является желательным. 'gamefile()' также позволяет загрузить новый файл и забыть стек предыдущих загрузок, запустив этот новый файл как самостоятельную игру. Для этого, задайте второй параметр функции как 'true'. Имейте в виду, что существующие модули остаются и переживают операцию gamefile в обоих случаях. 'gamefile()' можно использовать только в обработчиках. ``` act = function() gamefile ("episode3.lua", true); end; ``` Во втором варианте 'gamefile()' можно использовать для оформления мультиязычных игр или игр-сборников, где фактически из оболочки выполняется запуск самостоятельной игры. ### Меню Стандартное поведение предмета инвентаря состоит в том, что игрок должен сделать два щелчка мышью. Это необходимо потому, что каждый предмет инвентаря может быть использован на другой предмет сцены или инвентаря. После второго щелчка происходит игровой такт игры. Иногда такое поведение может быть нежелательным. Возможно, вы захотите сделать игру, в которой игровая механика отличается от классических INSTEAD игр. Тогда вам может понадобится меню. Меню -- это элемент инвентаря, который срабатывает на первый клик. При этом меню может сообщить движку, что действие не является игровым тактом. Таким образом, используя меню вы можете создать в зоне инвентаря управление игрой любой сложности. Например, существует модуль "proxymenu", который реализует управление игрой в стиле квестов на ZX-"Спектрум". В игре "Особняк" своё управление, которое вводит несколько модификаторов действий, и т.д. Итак, вы можете делать меню в области инвентаря, определяя объекты с типом 'menu'. При этом, обработчик меню ('act') будет вызван после одного клика мыши. Если обработчик возвращает false, то состояние игры не изменяется. Например, реализация кармана: ``` menu { state = false; nam = 'карман'; disp = function(s) if s.state then return fmt.u('карман'); -- подчёркиваем активный карман end return 'карман'; end; gen = function(s) if s.state then s:open(); -- показать все предметы в кармане else s:close(); -- спрятать все предметы в кармане end return s end; act = function(s) s.state = not s.state -- изменить состояние s:gen(); -- открыть или закрыть карман end; }: with { obj { nam = 'нож'; inv = 'Это нож'; }; } function init() take 'карман':gen() end ``` ### Статус игрока Иногда возникает желание вывести какой-нибудь статус. Например, количество игровых очков, состояние героя или, наконец, время суток. INSTEAD не предоставляет каких-то других областей вывода, кроме сцены и инвентаря, поэтому, самым простым способом вывода статуса является вывод его в зону инвентаря. Ниже представлена реализация статуса игрока в виде текста, который появляется в инвентаре, но не может быть выбран, то есть, выглядит просто как текст. ``` global { life = 10; power = 10; } stat { -- stat -- объект "статус" nam = 'статус'; disp = function(s) pn ('Жизнь: ', life) pn ('Сила: ', power) end }; function init() take 'статус' end ``` ### walk из обработчиков onexit и onenter Вы можете делать 'walk' из обработчиков 'onenter' и 'onexit'. Например, 'path' реализован как комната с обработчиком 'onenter', который переносит игрока в другую комнату. Рекомендуется возвращать из onexit/onenter false в случае, если вы делаете walk из этих обработчиков. ### Кодирование исходного кода игры Если вы не хотите показывать исходный код своих игр, вы можете закодировать исходный код с помощью параметра командной строки '-encode': sdl-instead -encode <путь к файлу> [выходной путь] И использовать закодированный файл с помощью обычных include/gamefile. Однако, для этого вы должны написать в начале main3.lua: ``` std.dofile = std.doencfile ``` При этом главный файл 'main3.lua' необходимо оставлять открытым. Таким образом, схема выглядит следующим образом ('game.lua' -- закодированный файл): ``` -- $Name: Моя закрытая игра!$ std.dofile = std.doencfile include "game"; -- никто не узнает, как её пройти! ``` __Важно!__ > Не используйте компиляцию игр с помощью 'luac', так как 'luac' создаёт > платформозависимый код! Однако, компиляция игр может быть > использована для поиска ошибок в коде. ### Запаковка ресурсов Вы можете упаковать ресурсы игры (графику, музыку, темы) в файл ресурсов '.idf', для этого поместите все ресурсы в каталог 'data' и запустите INSTEAD: sdl-instead -idf <путь к data> При этом, в текущем каталоге должен будет создастся файл 'data.idf'. Поместите его в каталог с игрой. Теперь ресурсы игры в виде отдельных файлов можно удалить (конечно, оставив себе оригинальные файлы). Вы можете запаковать в формат '.idf' всю игру: sdl-instead -idf <путь к игре> Игры в формате 'idf' можно запускать как обычные игры 'instead' (как если бы это были каталоги) а также из командной строки: sdl-instead game.idf ### Переключение между игроками Вы можете создать игру с несколькими персонажами и время от времени переключаться между ними (см. 'change_pl()'). Но вы можете также использовать этот трюк для того, чтобы иметь возможность переключаться между разными типами инвентаря. ### Использование параметров обработчика Пример кода. ``` obj { nam = 'камень'; dsc = 'На краю лежит {камень}.'; act = function() remove 'камень'; p 'Я толкнул камень, он сорвался и улетел вниз...'; end ``` Обработчик act мог бы выглядеть проще: ``` act = function(s) remove(s); p 'Я толкнул камень, он сорвался и улетел вниз...'; end ``` ### Специальные статусы обработчиков Из обработчика обычно возвращается текст, в виде return "текст сообщения". Или с помощью функций p()/pr()/pn()/pf(). Кроме этого, есть специальные статусы, которые могут пригодиться при разработке игры. Возвращение статуса false: return false Такой статус означает что обработчик не выполнил свою функцию и должен быть проигнорирован. Обычно движок в таком случае вызовет обработчик по умолчанию. Вы можете также вернуть специальный статус: return true, false В этом режиме перерисуется только область инвентаря (но не сцена). Данный статус удобно использовать для реализации меню в области инвентаря. Существует ещё один специальный статус: std.nop(). Он может быть использован просто как вызов функции в конце обработчика или совместно с return. return std.nop() -- ... или ... std.nop() -- далее конец функции или return В этом случае, содержимое сцены останется таким же, как и в прошлый такт игры (даже строка реакции останется старой). Данный статус удобно использовать совместно с модулем theme, когда нужно изменить оформление игры на лету и перерисовать кадр с учётом новых параметров темы. ### Таймер Для асинхронных событий, привязанных к реальному времени, в INSTEAD есть возможность использовать таймер. На самом деле, вам следует хорошо подумать, стоит ли в приключенческой игре использовать таймер. Обычно, игроком это воспринимается не слишком благосклонно. С другой стороны, таймер вполне можно использовать для управления музыкой или в оформительских целях. Для использования таймера, вам следует подключить модуль "timer". require "timer" Таймер программируется с помощью объекта 'timer'. - timer:set(мс) -- задать интервал таймера в миллисекундах; - timer:stop() -- остановить таймер. При срабатывании таймера, вызывается обработчик game.timer. Если game.timer возвращает false, сцена не перерисовывается. В противном случае, возвращаемое значение выводится как реакция. Вы можете делать локальные для комнаты обработчики 'timer'. Если в комнате объявлен обработчик 'timer', он вызывается вместо 'game.timer'. Если он возвращает false -- вызывается game.timer. Например: ``` game.timer = function(s) if time() > 10 then return false end snd.play 'gfx/beep.ogg'; p ("Timer:", time()) end function init() timer:set(1000) -- раз в секунду end ``` ``` room { enter = function(s) timer:set(1000); end; timer = function(s) timer:stop(); walk 'комната2'; end; nam = 'Проверка таймера'; dsc = [[Ждите.]]; } ``` Состояние таймера попадает в файл сохранения, таким образом, вам не нужно заботиться о его восстановлении. Вы можете вернуть из таймера специальный статус: return true, false В этом режиме перерисуется только область инвентаря. Это можно использовать для статусов вроде часов. Кроме того, в INSTEAD существует возможность отслеживать интервалы времени в миллисекундах. Для этого используйте функцию instead.ticks(). Функция возвращает число миллисекунд, прошедшее с момента старта игры. ### Музыкальный плеер Вы можете написать для игры свой проигрыватель музыки, создав его на основе живого объекта, например: ``` -- играет треки в случайном порядке require "snd" obj { { tracks = {"mus/astro2.mod", "mus/aws_chas.xm", "mus/dmageofd.xm", "mus/doomsday.s3m"}; }; nam = 'плеер'; life = function(s) if not snd.music_playing() then local n = s.tracks[rnd(#s.tracks)] snd.music(n, 1); end end; }:lifeon(); ``` Ниже приводится пример более сложного плеера. Меняем трек только если он закончился или прошло более 2 минут и игрок перешёл из комнаты в комнату. В каждом треке можно указать число проигрываний (0 - зацикленный трек): ``` require "timer" global { track_time = 0 }; obj { nam = 'player'; pos = 0; { playlist = { '01 Frozen sun.ogg', 0, '02 Thinking.ogg', 0, '03 Melancholy.ogg', 0, '04 Everyday happiness.ogg', 0, '10 Good morning again.ogg', 1, '15 [Bonus track] The end (demo cover).ogg', 1 }; }; tick = function(s) if snd.music_playing() and ( track_time < 120 or not player_moved() ) then return end track_time = 0 if s.pos == 0 then s.pos = 1 else s.pos = s.pos + 2 end if s.pos > #s.playlist then s.pos = 1 end snd.music('mus/'..s.playlist[s.pos], s.playlist[s.pos + 1]); end; } game.timer = function(s) track_time = track_time + 1 music_player:tick(); end function init() timer:set(1000) end ``` ### Живые объекты Если вашему герою нужен друг, одним из способов может стать метод 'life' этого персонажа, который всегда переносит объект в локацию игрока: ``` obj { nam = 'лошадь'; dsc = 'Рядом со мной стоит {лошадь}.'; act = [[Моя лошадка.]]; life = function(s) if player_moved() then place(s); end end; } function init() lifeon 'лошадь'; -- сразу оживим лошадь end ``` ### Вызов меню Вы можете вызвать из игры меню INSTEAD с помощью функции 'istead.menu()'. Если в качестве параметра задать: 'save', 'load' или 'quit', то будет вызван соответствующий подраздел меню. ### Динамическое создание объектов Обычные объекты и комнаты нельзя создавать "на лету". Обычно вы создаёте их в глобальном пространстве lua файла. Однако, существуют игры, в которых количество объектов неизвестно заранее, или количество объектов велико, и они добавляются по ходу игры. В INSTEAD существует способ создания любого объекта на лету. Для этого вам понадобится написать _конструктор_ вашего объекта и воспользоваться функцией 'new'. Конструктор должен быть декларирован. Итак, вы можете использовать функции 'new' и 'delete' для создания и удаления динамических объектов. Примеры: ``` declare 'box' (function() return obj { dsc = [[Тут лежит {коробка}.]]; tak = [[Я взял коробку.]]; } end) local o = new (box); take(o); ``` ``` declare 'box' (function(dsc) return obj { dsc = dsc; tak = [[Я взял коробку.]]; } end) take(new(box, 'В углу стоит {коробка}')) ``` 'new' воспринимает первый аргумент -- как задекларированную функцию-конструктор, а все остальные параметры -- как аргументы конструктору. Результатом выполнения конструктора должен быть объект. ``` function myconstructor() local v = {} v.disp = 'тестовый объект' v.act = 'Тестовая реакция' return obj(v) end ``` > Внимание! При создании объекта конструктор должен опираться только > на информацию, полученную из параметров! Дело в том, что создание > объекта при загрузке происходит в самом начале, когда окружение мира > ещё не загружено полностью! В качестве параметров поддерживаются > простые типы: строки, таблицы, числа, булевые > значения. Недекларированные функции и списки не будут работать. Если вы хотите уничтожить объект по его имени или ссылке-переменной, воспользуйтесь: ``` purge(o) -- удалить из всех списков delete(o) -- освободить объект ``` При этом, delete это именно удаление объекта из INSTEAD, а не аналог remove() или purge(). Обычно, нет особого смысла делать delete. Только если предмет больше никогда не понадобится в игре, или вы собираетесь пересоздать объект с тем же именем, имеет смысл освободить его с помощью delete(). Более практически-полезный пример: ``` -- декларируем конструктор -- path declare 'make_path' (function(v) return path(v) end) -- динамический переход -- создали новый объект -- и положили его в ways() put( new (make_path, { 'переход', 'комната2'}, ways()) ``` ### Запрет на сохранение игры Иногда может понадобиться запретить игроку делать сохранения в игре. Например, если речь идёт о сценах, где важный элемент составляет случай, или для коротких игр, в которых проигрыш должен быть фатальным и требовать перезапуска игры. Для управлением функции сохранения используется атрибут 'instead.nosave'. Например: instead.nosave = true -- запретить сохранения Если вы хотите запрещать сохранения не везде, а в некоторых сценах, оформите 'instead.nosave' в виде функции, или же меняйте состояние атрибута на лету -- он попадает в файл сохранений. ``` -- запретить -- сохранения в комнатах, которые содержат атрибут nosave. instead.nosave = function() return here().nosave end ``` Следует отметить, что запрет на сохранения не означает запрета на автосохранение. Для управления автосохранением воспользуйтесь аналогичным атрибутом 'instead.noautosave'. > Вы можете явно сохранять игру с помощью вызова: > 'instead.autosave([номер слота])'; Если номер слота не задан, то > игра будет сохранена под слотом 'автосохранение'. Имейте в виду, что > сохраняется состояние __после__ завершение текущего такта игры. ### Определение типа объекта В INSTEAD существует два способа определить тип объекта. Первый - с помощью функции std.is_obj(переменная, [тип]). Например: ``` a = room { nam = 'объект'; }; dprint(std.is_obj(a)) -- выведет true dprint(std.is_obj('объект')) -- выведет false dprint(std.is_obj(a, 'room')) -- выведет true dprint(std.is_obj(a.obj, 'list')) -- выведет true ``` std.is_obj() удобная для определения типа переменной или аргумента функции. Второй способ связан с использованием метода type: ``` a = room { nam = 'объект'; }; dprint(a:type 'room') -- выведет true ``` ## Темы для sdl-instead Графический интерпретатор поддерживает механизм тем. _Тема_ представляет из себя каталог, с файлом 'theme.ini' внутри. Тема, которая является минимально необходимой -- это тема 'default'. Эта тема всегда загружается первой. Все остальные темы наследуются от неё и могут частично или полностью заменять её параметры. Выбор темы осуществляется пользователем через меню настроек, однако конкретная игра может содержать собственную тему и таким образом влиять на свой внешний вид. В этом случае в каталоге с игрой должен находиться свой файл 'theme.ini'. Тем не менее, пользователь свободен отключить данный механизм, при этом интерпретатор будет предупреждать о нарушении творческого замысла автора игры. Синтаксис 'theme.ini' очень прост. <параметр> = <значение> или ; комментарий Значения могут быть следующих типов: строка, цвет, число. Цвет задаётся в форме #rgb, где r g и b компоненты цвета в шестнадцатеричном виде. Кроме того, некоторые основные цвета распознаются по своим именам. Например: yellowgreen, или violet. Параметры могут принимать значения: - scr.w = ширина игрового пространства в пикселях (число) - scr.h = высота игрового пространства в пикселях (число) - scr.col.bg = цвет фона - scr.col.brd = цвет бордюра, если он есть (по умолчанию чёрный) - scr.gfx.scalable = [0|1|2] (0 - не масштабируемая тема, 1 - масштабируемая, 2 - масштабируемая без сглаживания), начиная с версии 2.2.0 доступны дополнительно [4|5|6]: 4 - полностью не масштабируемая (с не масштабируемыми шрифтами), 5 - масштабируемая, с не масштабируемыми шрифтами, 6 - масштабируемая без сглаживания, с не масштабируемыми шрифтами - scr.scale_aware = [0|1|2] (поддержка адаптивных тем: 0 - виртуальное разрешение, 1 - виртуальное разрешение с реальными пропорциями, 2 - реальное разрешение) - scr.dpi = [dpi|dpi1-dpi2] (задать DPI для которого создана тема, по умолчанию 96) - scr.gfx.scale = масштаб (задать масштабирование графики, 1.0 по умолчанию) - scr.gfx.bg = путь к картинке фонового изображения (строка) - scr.gfx.cursor.x = x координата центра курсора (число) - scr.gfx.cursor.y = y координата центра курсора (число) - scr.gfx.cursor.normal = путь к картинке-курсору (строка) - scr.gfx.cursor.use = путь к картинке-курсору режима использования (строка) - scr.gfx.use = путь к картинке-индикатору режима использования (строка) - scr.gfx.pad = размер отступов к скролл-барам и краям меню (число) - scr.gfx.x, scr.gfx.y, scr.gfx.w, scr.gfx.h = координаты, ширина и высота окна изображений. Области, в которой располагается картинка сцены. Интерпретация зависит от режима расположения (числа) - win.gfx.h - синоним scr.gfx.h (для совместимости) - scr.gfx.icon = пусть к файлу-иконке игры (ОС зависимая опция, может работать некорректно в некоторых случаях) - scr.gfx.mode = режим расположения (строка fixed, embedded или float). Задаёт режим изображения. embedded -- картинка является частью содержимого главного окна, параметры scr.gfx.x, scr.gfx.y, scr.gfx.w игнорируются. float -- картинка расположена по указанным координатам (scr.gfx.x, scr.gfx.y) и масштабируется к размеру scr.gfx.w x scr.gfx.h если превышает его. fixed -- картинка является частью сцены как в режиме embedded, но не скроллируется вместе с текстом, а расположена непосредственно над ним. Доступны модификации режима float с модификаторами 'left/right/center/middle/bottom/top', указывающими как именно размещать картинку в области scr.gfx. Например: float-top-left; - win.scroll.mode = [0|1|2|3] режим прокрутки области сцены. 0 - нет автоматической прокрутки, 1 - прокрутка на изменение в тексте, 2 прокрутка на изменение, только если изменение не видно, 3 - всегда в конец; - win.x, win.y, win.w, win.h = координаты, ширина и высота главного окна. Области, в которой располагается описание сцены (числа) - win.fnt.name = путь к файлу-шрифту (строка). Здесь и далее, шрифт может содержать описание всех начертаний, например: {sans,sans-b,sans-i,sans-bi}.ttf (заданы начертания для regular, bold, italic и bold-italic). Вы можете опускать какие-то начертания, и движок сам сгенерирует их на основе обычного начертания, например: {sans,,sans-i}.ttf (заданы только regular и italic); - win.align = center/left/right/justify (выравнивание текста в окне сцены); - win.fnt.size = размер шрифта главного окна (размер) - win.fnt.height = междустрочный интервал как число с плавающей запятой (1.0 по умолчанию) - win.gfx.up, win.gfx.down = пути к файлам-изображениям скроллеров вверх/вниз для главного окна (строка) - win.up.x, win.up.y, win.down.x, win.down.y = координаты скроллеров (координата или -1) - win.col.fg = цвет текста главного окна (цвет) - win.col.link = цвет ссылок главного окна (цвет) - win.col.alink = цвет активных ссылок главного окна (цвет) - win.ways.mode = top/bottom (задать расположение списка переходов, по умолчанию top -- сверху сцены) - inv.x, inv.y, inv.w, inv.h = координаты, высота и ширина области инвентаря. (числа) - inv.mode = строка режима инвентаря (horizontal или vertical). В горизонтальном режиме инвентаря в одной строке могут быть несколько предметов. В вертикальном режиме, в каждой строке инвентаря содержится только один предмет. Существуют модификации (-left/right/center). Вы можете задать режим disabled если в вашей игре не нужен инвентарь; - inv.col.fg = цвет текста инвентаря (цвет) - inv.col.link = цвет ссылок инвентаря (цвет) - inv.col.alink = цвет активных ссылок инвентаря (цвет) - inv.fnt.name = путь к файлу-шрифту инвентаря (строка) - inv.fnt.size = размер шрифта инвентаря (размер) - inv.fnt.height = междустрочный интервал как число с плавающей запятой (1.0 по умолчанию) - inv.gfx.up, inv.gfx.down = пути к файлам-изображениям скроллеров вверх/вниз для инвентаря (строка) - inv.up.x, inv.up.y, inv.down.x, inv.down.y = координаты скроллеров (координата или -1) - menu.col.bg = фон меню (цвет) - menu.col.fg = цвет текста меню (цвет) - menu.col.link = цвет ссылок меню (цвет) - menu.col.alink = цвет активных ссылок меню (цвет) - menu.col.alpha = прозрачность меню 0-255 (число) - menu.col.border = цвет бордюра меню (цвет) - menu.bw = толщина бордюра меню (число) - menu.fnt.name = путь к файлу-шрифту меню (строка) - menu.fnt.size = размер шрифта меню (размер) - menu.fnt.height = междустрочный интервал как число с плавающей запятой (1.0 по умолчанию) - menu.gfx.button = путь к файлу изображению значка меню (строка) - menu.button.x, menu.button.y = координаты кнопки меню (числа) - snd.click = путь к звуковому файлу щелчка (строка) - include = имя темы (последний компонент в пути каталога) (строка) Кроме того, заголовок темы может включать в себя комментарии с тегами. На данный момент существует только один тег: $Name:, содержащий UTF-8 строку с именем темы. Например: ``` ; $Name:Новая тема$ ; модификация темы book include = book ; -- использовать тему Книга scr.gfx.h = 500 ; -- заменить в ней один параметр ``` > Интерпретатор выполняет поиск тем в каталоге themes. Unix-версия, > кроме этого каталога, просматривает также каталог ~/.instead/themes/. > Windows-версия: %LOCALAPPDATA%\instead\themes (ниже Vista: > Documents and Settings\USER\Local Settings\Application Data\instead\themes). Кроме этого, новые версии INSTEAD поддерживают механизм множественных тем в одной игре. Давая возможность игроку через стандартное меню INSTEAD выбрать подходящее оформление, из предусмотренных автором игры. Для этого, все темы должны располагаться в игре в подкаталоге themes. В свою очередь, каждая тема -- это подкаталог в каталоге themes. В каждом таком подкаталоге должен находится свой файл theme.ini и ресурсы темы (картинки, шрифты, звуки). При этом обязательно наличие темы-каталога themes/default - эта тема будет загружена по умолчанию. Формат файлов theme.ini мы только что рассмотрели. Однако, пути к файлам с ресурсами в theme.ini пишутся не относительно корневого каталога игры, а относительно текущего каталога темы. Это означает, что обычно они содержат только имя самого файла, без пути к каталогу. Например: ``` mygame/ themes/ default/ theme.ini bg.png widescreen/ theme.ini main3.lua ``` theme.ini ``` scr.gfx.bg = bg.png ; ... ``` При этом, все игровые темы наследуются от темы themes/default. Поддерживается механизм include. При этом, INSTEAD сначала пытается найти одноименную тему игры, и если такой темы не находится, будет загружена тема из стандартных тем INSTEAD (если она существует). Далее, в theme.ini можно изменять только те параметры, которые требуют изменения. ## Модули Дополнительная функциональность часто реализована в INSTEAD в виде модулей. Для использования модуля необходимо написать: ``` require "имя модуля" ``` Или: ``` loadmod "имя модуля" ``` Если модуль поставляется вместе с игрой. Часть модулей входит в поставку INSTEAD, но есть и такие, которые вы можете скачать отдельно и положить в каталог с игрой. Вы можете заменить любой стандартный модуль своим, если положите его в каталог с игрой под тем-же именем файла, что и стандартный. Модуль, это фактически 'lua' файл с именем: 'имя_модуля.lua'. Ниже перечислены основные стандартные модули, с указанием функциональности, которые они предоставляют. - 'dbg' — модуль отладки; - 'click' — модуль перехвата кликов мыши по картинке сцены; - 'prefs' — модуль настроек (хранилище данных настроек); - 'snapshots' — модуль поддержки снапшотов (для откатов игровых ситуаций); - 'fmt' — модуль оформления вывода; - 'theme' — управление темой на лету; - 'noinv' - модуль работы с инвентарём; - 'key'' - модуль обработки событий срабатывания клавиш; - 'timer' - таймер; - 'sprite' — модуль для работы со спрайтами; - 'snd' — модуль работы со звуком; - 'nolife' – модуль блокировки методов life; Пример загрузки модулей: ``` --$Name: Моя игра!$ require "fmt" require "click" ``` > Некоторые дополнительные модули, которые не входят в стандартную > поставку, вы можете скачать из [репозитория > модулей](https://github.com/instead-hub/stead3-modules). Просто > скачайте нужный вам модуль и положите его в каталог с > игрой. Включайте такой модуль с помощью loadmod(). ### Модуль keys Вы можете перехватывать события клавиатуры с помощью модуля "keys". Обычно, перехват клавиш имеет смысл использовать для организации текстового ввода. Для задания того, какие именно клавиши необходимо отслеживать, определите функцию keys:filter(press, key). Эта функция должна возвращать true в том случае, если вы хотите отследить данное событие. Например: ``` require "keys" function keys:filter(press, key) return press -- ловим нажатия любых клавиш end ``` В примере мы просто возвращаем параметр press, который равен true для события нажатия клавиши и false -- отжатия. В key передаётся символическое название клавиши (в виде строки). Обычно, нам нужно выбрать какие именно клавиши мы хотим перехватывать: ``` require "keys" function keys:filter(press, key) if key == '0' or key == '1' or key == 'z' then return press -- ловим нажатия клавиш z, 1 и 0 end end ``` Итак, keys:filter позволяет выбрать нужные события клавиатуры. А сами события приходят в игру в виде вызова обработчика 'onkey' для текущей комнаты или (если он не задан в комнате) для объекта 'game'. Обработчик onkey действует как обычный обработчик STEAD3. Он может вернуть false и тогда считается, что клавиша не была обработана игрой. Либо он может выполнить какое-нибудь действие. _Внимание:_ Если игра будет обрабатывать _все_ события клавиш, то даже те комбинации, которые используются самим INSTEAD будут обрабатываться игрой, а не интерпретатором. Например, если игра будет перехватывать клавишу "escape" (и не возвращать false из обработчика), то клавиша "escape" перестанет обрабатываться интерпретатором INSTEAD (escape -- вызов меню). Ниже приводится простой пример вывода на экран символических имён клавиш: ``` require "keys" function keys:filter(press, key) return press -- ловим все нажатия end game.onkey = function(s, press, key) dprint("pressed: ", key) p("Нажата: ", key) return false -- давать обрабатывать клавиши интерпретатору INSTEAD end ``` Этот пример можно использовать для того, чтобы выяснить символическое имя конкретной клавиши. При написании аркадных игр бывает полезным не получать событие от клавиатуры, а опрашивать её (как правило, в таймере). Для этого вы можете использовать функцию keys:state(имя клавиши). Эта функция возвращает true для нажатой клавиши и false -- для отжатой, например: ``` require "timer" require "keys" game.timer = function(s) -- показываем состояние клавиши курсор вправо dprint("state of 'right' key: ", keys:state 'right') p("Состояние клавиши 'вправо':", keys:state 'right') end timer:set(30) ``` ### Модуль click Вы можете отслеживать в своей игре клики по картинке сцены, а также по фону. Для этого, воспользуйтесь модулем "click". Также, вы можете отслеживать состояние мыши с помощью функции: ``` instead.mouse_pos([x, y]) ``` Которая возвращает координаты курсора. Если задать параметры (x, y), то можно переместить курсор в указанную позицию (все координаты рассчитываются относительно левого верхнего угла окна INSTEAD). ``` require "click" function click:filter(press, btn, x, y, px, py) dprint(press, btn, x, y, px, py) return press and px -- ловим только нажатия на картинку end room { nam = 'main'; pic = "box:320x200,red"; onclick = function(s, press, btn, x, y, px, py) pn("Вы нажали на картинку: ", px, ", ", py) pn("Абсолютные координаты: ", x, ", ", y) p("Кнопка: ", btn) end; } ``` _Внимание!_ В INSTEAD по умолчанию включён фильтр кликов мыши, который гасит быстрые клики. Это сделано для исключения эффекта дребезга клавиш мыши. В некоторых случаях фильтр может оказаться нежелательным. В таком случае, используйте функцию instead.mouse\_filter(), которая может быть использована для определения текущего значения фильтра мыши и установки нового (в том числе - выключения), например: ``` function start() dprint("Mouse filter delay: ", instead.mouse_filter()) instead.mouse_filter(0) -- выключили фильтр end ``` Или так: ``` old_filter = instead.mouse_filter(0) -- выключили ... instead.mouse_filter(old_filter) -- восстановили ``` ### Модуль theme Модуль theme позволяет изменять параметры темы на лету. > Имейте в виду, что изменение параметров темы на лету для игр, > которые не содержат собственную тему -- источник потенциальных > проблем! Дело в том, что ваша игра в таком случае должна быть готова > работать с любыми разрешениями и параметрами тем, что крайне сложно > добиться. Поэтому, если вы собираетесь менять параметры темы из кода > -- создайте свою тему и включите её в игру! При этом, сохранение изменений темы в файле сохранения не поддерживается. Автор игры должен сам восстановить параметры темы в функции start(), как это делается при работе с модулем спрайтов. Для изменения параметров действующей темы, используются следующие функции: ``` -- настройка окна вывода theme.win.geom(x, y, w, h) theme.win.color(fg, link, alink) theme.win.font(name, size, height) theme.win.gfx.up(pic, x, y) theme.win.gfx.down(pic, x, y) -- настройка инвентаря theme.inv.geom(x, y, w, h) theme.inv.color(fg, link, alink) theme.inv.font(name, size, height) theme.inv.gfx.up(pic, x, y) theme.inv.gfx.down(pic, x, y) theme.inv.mode(mode) -- настройка меню theme.menu.bw(w) theme.menu.color(fg, link, alink) theme.menu.font(name, size, height) theme.menu.gfx.button(pic, x, y) -- настройка графики theme.gfx.cursor(norm, use, x, y) theme.gfx.mode(mode) theme.gfx.pad(pad) theme.gfx.bg(bg) -- настройка звука theme.snd.click(name); ``` Существует возможность чтения текущих параметров тем: theme.get 'имя переменной темы'; Возвращаемое значение всегда в текстовой форме. theme.set ('имя переменной темы', значение); Вы можете сбросить значение параметра темы на то, которое было установлено во встроенной теме игры: ``` theme.reset 'имя переменной'; theme.win.reset(); ``` Существует функция для того, чтобы узнать текущую выбранную тему. ``` theme.name() ``` Функция возвращает строку -- имя каталога темы. Если игра использует собственный файл 'theme.ini', функция вернёт точку. Это удобно, для определения того, включён ли механизм собственных тем игр: ``` if theme.name() ~= '.' then error "Please, enable own theme mode in menu!" end ``` Если в игре используется механизм множественных тем, то имя темы начинается с точки, например: ``` if theme.name() == '.default' then -- наша встроенная тема default elseif theme.name() == 'default' then -- стандартная тема default в INSTEAD end ``` Пример использования: ``` theme.gfx.bg "dramatic_bg.png"; theme.win.geom (0,0, theme.get 'scr.w', theme.get 'scr.h'); theme.inv.mode 'disabled' ``` Получить размеры текущей темы: ``` theme.scr.w() -- ширина theme.scr.w() -- высота ``` ### Модуль sprite Модуль sprite позволяет работать с графическими изображениями. Для включения модуля напишите: require "sprite" Спрайты не могут попасть в файл сохранения, поэтому восстановление состояния спрайтов -- задача автора игры. Обычно, для этого используются функции init() и/или start(). start() вызывается после загрузки игры, поэтому в этой функции вы можете использовать переменные игры. На самом деле в модуле спрайт реализованы два модуля: спрайты и пиксели. Но так как они используются совместно, они размещены в одном модуле. Начнём со спрайтов: #### Спрайты Для создания спрайта используйте метод sprite.new, например: ``` declare 'my_spr' (sprite.new 'gfx/bird.png') local heart = sprite.new 'heart.png' local blank = sprite.new (320, 200) -- пустой спрайт 320x200 ``` У созданного спрайтового объекта существуют следующие методы: - :alpha(alpha) - создаёт новый спрайт с заданной прозрачностью alpha (255 - не прозрачно). Это очень медленная функция; - :dup() - создаёт копию спрайта; - :scale(xs, ys, [smooth]) -- масштабирует спрайт, для отражений используйте масштаб -1.0 (медленно! не для реального времени). Создаёт новый спрайт. - :rotate(angle, [smooth]) -- поворот спрайта на заданный угол в градусах (медленно! не для реального времени). Создаёт новый спрайт. - :size() -- Возвращает ширину и высоту спрайта в пикселях. - :draw(fx, fy, fw, fh, dst\_spr, x, y, [alpha]) -- Рисование области src спрайта в область dst спрайта (задание alpha сильно замедляет выполнение функции). - :draw(dst_spr, x, y, [alpha]) -- Рисование спрайта, укороченный вариант; (задание alpha замедляет выполнение функции). - :copy(fx, fy, fw, fh, dst\_spr, x, y) -- Копирование прямоугольника fw-на-fh из спрайта в спрайт dst\_spr по координатам [x,y] (рисование - замещение). Существует укороченный вариант (как :draw). - :compose(fx, fy, fw, fh, dst\_spr, x, y) -- Рисование - с учётом прозрачности обоих спрайтов). Существует укороченный вариант (как :draw). - :fill(x, y, w, h, [col]) -- Заполнение спрайта цветом. - :fill([col]) -- Заполнение спрайта цветом. - :pixel(x, y, col, [alpha]) -- Заполнение пикселя спрайта. - :pixel(x, y) -- Взятие пикселя спрайта (возвращает четыре компонента цвета). - :colorkey(color) -- Задает в спрайте цвет, который выступает в роли прозрачного фона. При этом, при последующем выполнении операции :copy, из рассматриваемого спрайта будут скопированы только те пиксели, цвет которых не совпадает с цветом прозрачного фона. В качестве "цвета" методы получают строки вида: 'green', 'red', 'yellow' или '#333333', '#2d80ff'... Пример: ``` local spr = sprite.new(320, 200) spr:fill 'blue' local spr2 = sprite.new 'fish.png' spr2:draw(spr, 0, 0) ``` Кроме того, существует возможность работы с шрифтами. Шрифт создаётся с помощью sprite.fnt(), например: local font = sprite.fnt('sans.ttf', 32) У созданного объекта определены следующие методы: - :height() -- высота шрифта в пикселях; - :text(text, col, [style]) -- создание спрайта из текста, col - здесь и далее - цвет в текстовом формате (в формате '#rrggbb' или 'текстовое название цвета'). - :size(text) -- вычисляет размер, который будет занимать текстовый спрайт, без создания спрайта. Вам также может пригодиться функция: sprite.font_scaled_size(size) Она возвращает размер шрифта с учётом масштабирование, которое выставил игрок в настройках INSTEAD. Если вы в своей игре хотите учитывать такую настройку, используйте эту функцию для определения размера шрифта. Пример: ``` local f = sprite.fnt('sans.ttf', 32) local spr = sprite.new('box:320x200,black') f:text("HELLO!", 'white'):draw(spr, 0, 0) ``` Теперь, рассмотрим варианты применения модуля sprite. #### Функция pic Функция pic может вернуть спрайт. Вы можете формировать каждый раз новый спрайт (что будет не очень эффективно), или можете возвращать заранее выделенный спрайт. Если в такой спрайт вносятся изменения, то эти изменения будут отражены в следующем кадре игры. Так, меняя спрайт по таймеру, можно делать анимацию: ``` require "sprite" require "timer" local spr = sprite.new(320, 200) function game:timer() local col = { 'red', 'green', 'blue'} col = col[rnd(3)] spr:fill(col) return false -- Важно! Так, сцена не будет изменена end game.pic = function() return spr end -- функция: так как -- спрайт -- это особый объект (не строка) function start() timer:set(30) end room { nam = 'main'; decor = [[ГИПНОЗ!]]; } ``` #### Отрисовка в фон Функция sprite.scr() возвращает спрайт - фон. Вы можете выполнять отрисовку в этот спрайт в любом обработчике, например, в таймере. Тем самым добиваясь изменения фона на лету, без применения модуля theme. Например: ``` --$Author: Andrew Lobanov require 'sprite' require 'theme' require 'timer' declare { x = 0, y = 0, dx = 10, dy = 10, } const { w = theme.scr.w(), h = theme.scr.h(), } instead.fading = false local bg, red, green function init() theme.set('scr.col.bg', '#000000') theme.set('win.col.fg', '#aaaaaa') theme.set('win.col.link', '#ffaa00') theme.set('win.col.alink', '#ffffff') bg = sprite.new(w, h) bg:fill('black') red = sprite.new(w, h) red:fill('#ff0000') red = red:alpha(128) green = sprite.new(w, h) green:fill('#00ff00') green = green:alpha(64) bg:copy(sprite.scr()) timer:set(25) end function game:timer() bg:copy(sprite.scr()) red:draw(sprite.scr(), x, 0, 128) green:draw(sprite.scr(), 0, y, 64) x = x + dx if x >= w or x == 0 then dx = -dx end y = y + dy if y >= h or y == 0 then dy = -dy end return false -- Важно! end room { nam = 'main', disp = 'Test. Test? Test!', decor = 'Lorem ipsum'; } ``` _Внимание!_ Интерпретатор INSTEAD в режиме использования предмета на предмет переводит себя в режим "паузы". Это значит, что в тот момент когда выбран предмет из инвентаря (курсор изменил вид на шестерёнки) события таймера перестают обрабатываться до тех пор, пока игрок не применит предмет. Это сделано для того, чтобы не разрывать такт игры. Если для вашего творческого замысла такое поведение является помехой (например, вам не нравится тот факт, что анимация фона замирает), вы можете изменить его с помощью вызова: instead.wait_use(false) Как обычно, поместите вызов в init() или start() функцию. #### Подстановки Вы можете создать свой системный объект - подстановку, и формировать графику в выводе игры с помощью img, например: ``` require "sprite" require "timer" require "fmt" obj { nam = '$spr'; { ["квадрат"] = sprite.new 'box:32x32,red'; }; act = function(s, w) return fmt.img(s[w]) end } room { nam = 'main'; decor = [[Сейчас мы вставим спрайт: {$spr|квадрат}.]]; } ``` #### direct режим В INSTEAD существует режим прямого доступа к графике. В теме он задаётся с помощью параметра: scr.gfx.mode = direct Этот параметр можно заранее выставить в theme.ini, или воспользоваться модулем theme. Или (что лучше), специальной функцией: sprite.direct(true) Если режим удалось включить -- функция вернёт true. sprite.direct() без параметра -- возвращает текущий режим (true -- если direct включён.) В этом режиме игра имеет прямой доступ ко всему окну и может выполнять отрисовку в процедуре таймера. Экран представлен специальным спрайтом: sprite.scr() Например: ``` require "sprite" require "timer" require "theme" sprite.direct(true) local stars = {} local w, h local colors = { "red", "green", "blue", "white", "yellow", "cyan", "gray", "#002233", } function game:timer() local scr = sprite.scr() scr:fill 'black' for i = 1, #stars do local s = stars[i] scr:pixel(s.x, s.y, colors[s.dy]) s.y = s.y + s.dy if s.y >= h then s.y = 0 s.x = rnd(w) - 1 s.dy = rnd(8) end end end function start() w, h = theme.scr.w(), theme.scr.h() w = std.tonum(w) h = std.tonum(h) for i = 1, 100 do table.insert(stars, { x = rnd(w) - 1, y = rnd(h) - 1, dy = rnd(8) }) end timer:set(30) end ``` Ещё один пример: ``` require "timer" require "sprite" require "theme" local spr = sprite declare { fnt = false, ball = false, ballw = 0, ballh = 0, bg = false, line = false, G = false, by = false, bv = false, bx = false, t1 = false, } function init() fnt = spr.fnt(theme.get 'win.fnt.name', 32); ball = fnt:text("INSTEAD 3.0", 'white', 1); ballw, ballh = ball:size(); bg = spr.new 'box:640x480,black'; line = spr.new 'box:320x8,lightblue'; spr.direct(true) end function start() timer:set(20) G = 9.81 by = -ballh bv = 0 bx = 320 t1 = instead.ticks() end function phys() local t = timer:get() / 1000; bv = bv + G * t; by = by + bv * t; if by > 400 then bv = - bv end end function game:timer(s) local i for i = 1, 10 do phys() end if instead.ticks() - t1 >= 20 then bg:copy(spr.scr(), 0, 0); ball:draw(spr.scr(), (640 - ballw) / 2, by - ballh/2); line:draw(spr.scr(), 320/2, 400 + ballh / 2); t1 = instead.ticks() end end ``` _Внимание!_ direct режим может быть использован для создания простых аркадных игр. В некоторых случаях, вы можете захотеть убрать указатель мыши. Например, когда игра управляется только с клавиатуры. Для этого воспользуйтесь функцией instead.mouse\_show() ``` instead.mouse_show(false) ``` При этом в меню интерпретатора INSTEAD указатель мыши всё ещё будет виден. #### Использование sprite совместно с модулем theme В функции start и в обработчиках вы можете менять параметры темы, в том числе, используя в качестве графики спрайты, например: ``` require "sprite" require "theme" function start() -- заменим фон на спрайт local spr = sprite.new(800, 600) spr:fill 'blue' spr:fill (100, 100, 32, 60, 'red') theme.set('scr.gfx.bg', spr) end ``` Используя эту технику, вы можете наносить на фоновое изображение статусы, элементы управления или просто менять подложку. Обратите внимание, что при этом вызов `theme.get('scr.gfx.bg')` возвращает строку вида `spr:xxxxxxxxxxx`, а не объект спрайта. Если вы хотите изменять фон динамически, используйте `sprite.scr()` или многократные вызовы `theme.set('scr.gfx.bg', spr)` с новыми спрайтами. #### Пиксели Модуль спрайтов поддерживает также работу с пиксельной графикой. Вы можете создавать объекты -- наборы пикселей, модифицировать их и рисовать в спрайты. Создание пикселей осуществляется функцией pixels.new(). Примеры: local p1 = pixels.new(320, 200) -- создали пиксели 320x200 local p2 = pixels.new 'gfx/apple.png' -- создали пиксели из -- изображения local p3 = pixels.new(320, 200, 2) -- создали пиксели 320x200, -- которые при отрисовке их в спрайт -- будут смасштабированы до -- 640x400 Объект пиксели имеет следующие методы: > при описании использованы обозначения: r, g, b, a -- > компоненты пикселя: красный, зелёный, синий, и прозрачность. Все > значения от 0 до 255). x, y - координаты левого верхнего угла, w, h > -- ширина и высота области. - :size() -- вернуть размер и масштаб (как 3 значения); - :clear(r, g, b, [a]) -- быстрая очистка пикселей; - :fill(r, g, b, [a]) -- заливка (с учётом прозрачности); - :fill(x, y, w, h, r, g, b, [a]) -- заливка области (с учётом прозрачности); - :val(x, y, r, g, b, a) - задать значение пикселя - :val(x, y) -- получить компоненты r, g, b, a - :pixel(x, y, r, g, b, a) -- нарисовать пиксель (с учётом прозрачности существующего пикселя); - :line(x1, y1, x2, y2, r, g, b, a) -- линия; - :lineAA(x1, y1, x2, y2, r, g, b, a) -- линия с AA; - :circle(x, y, radius, r, g, b, a) -- окружность; - :circleAA(x, y, radius, r, g, b, a) -- окружность с AA; - :poly({x1, y1, x2, y2, ...}, r, g, b, a) -- полигон; - :polyAA({x1, y1, x2, y2, ...}, r, g, b, a) -- полигон с AA; - :blend(x1, y1, w1, h1, pixels2, x, y) -- рисовать область пикселей в другой объект пиксели, полная форма; - :blend(pixels2, x, y) -- короткая форма; - :fill\_circle(x, y, radius, r, g, b, a) -- залитый круг; - :fill\_triangle(x1, y1, x2, y2, x3, y3, r, g, b, a) -- залитый треугольник; - :fill\_poly({x1, y1, x2, y2, ...}, r, g, b, a) -- залитый полигон; - :copy(...) -- как blend, но не рисовать, а копировать (быстро); - :scale(xscale, yscale, [smooth]) -- масштабирование в новый объект pixels; - :rotate(angle, [smooth]) -- поворот в новый объект pixels; - :draw_spr(...) -- как draw, но в спрайт, а не пиксели; - :copy_spr(...) -- как copy, но в спрайт, а не пиксели; - :compose_spr(...) -- то же самое, но в режиме compose; - :dup() -- создать копию пикселей; - :sprite() -- создать спрайт из пикселей. Также, есть возможность работы со шрифтами: - pixels.fnt(fnt(шрифт.ttf, размер) -- создать шрифт; При этом, у созданного объекта "шрифт" существует метод text: - :text(текст, цвет(как в спрайтах), стиль) -- создать пиксели с текстом; Например: ``` local fnt = pixels.fnt("sans.ttf", 64) local t = fnt:text("HELLO, INSTEAD!", 'black') pxl:copy_spr(sprite.scr()) pxl2:draw_spr(sprite.scr(), 100, 200); t:draw_spr(sprite.scr(), 200, 400) ``` Ещё один пример (автор примера, Андрей Лобанов): ``` require "sprite" require "timer" sprite.direct(true) declare 'pxl' (false) declare 't' (0) function game:timer() local x, y, i t = t + 1 for x = 0, 199 do for y = 0, 149 do i = (x * x + y * y + t) pxl:val(x, y, 0, i, i / 2) end end pxl:copy_spr(sprite.scr()) end function start(load) pxl = pixels.new(200, 150, 4) timer:set(20) end ``` При процедурной генерации с помощью pixels удобно использовать шумы Перлина. В INSTEAD существуют функции: - instead.noise1(x) - 1D шум Перлина; - instead.noise2(x, y) - 2D шум Перлина; - instead.noise3(x, y, z) - 3D шум Перлина; - instead.noise4(x, y, z, w) - 4D шум Перлина; Все эти функции возвращают значение в диапазоне [-1; 1] а на вход получают координаты с плавающей точкой. ### Модуль snd Мы уже рассматривали базовые возможности по работе со звуком. Модуль snd имеет ещё некоторые функции по работе со звуком. Вы можете подгрузить звук и держать его в памяти до тех пор, пока он вам нужен. ``` require 'snd' local wav = snd.new 'bark.ogg' ``` Кроме подгрузки файлов, вы можете загрузить звук из массива lua: ``` local wav = {} for i = 1, 10000 do table.insert(wav, rnd() * 2 - 1) -- случайные значения от -1 до 1 end function start() local p = snd.new(22050, 1, wave) -- частота, число каналов и звук p:play() end ``` Звук задаётся в нормированном формате: [-1 .. 1] Звук можно проиграть методом :play([chan], [loop]), где chan -- канал (0 - 7), loop - циклы (0 - бесконечность). Остальные функции модуля: - snd.stop([channel]) – остановить проигрывание выбранного канала или всех каналов. Вторым параметром можно задавать время затухания звука в мс. при его приглушении; - snd.playing([channel]) – узнать проигрывается ли звук на любом канале или на выбранном канале; если выбран конкретный канал, функция вернёт хандл (дескриптер) проигрываемого в данный момент звука или nil. Внимание! Звук клика не учитывается и обычно занимает 0 канал; - snd.pan(chan, l, r) – задание паннинга. Канал, громкость левого[0-255], громкость правого[0-255] каналов. Необходимо вызывать перед проигрыванием звука, чтобы имело эффект; - snd.vol(vol) – задание громкости звука (и музыки и эффектов) от 0 до 127. Ещё одна интересная возможность -- генерирование звука на лету (пока находится в экспериментальном статусе): ``` require "snd" function cb(hz, len, data) for i = 1, len do data[i] = rnd() * 2 - 1 end end function start() snd.music_callback(cb) end ``` ### Модуль prefs Этот модуль позволяет сохранять настройки игры. Другими словами, сохранённая информация не зависит от состояния игры. Такой механизм можно использовать, например, для реализации системы достижений или счётчика количества прохождений игры. По своей сути prefs это объект, все переменные которого будут сохранены. Сохранить настройки: ``` prefs:store() ``` Настройки сохраняются автоматически при сохранении игры, но вы можете контролировать этот процесс, вызывая prefs:store(). Уничтожить файл с настройками: ``` prefs:purge() ``` Загрузка настроек выполняется автоматически при запуске игры (перед вызовом функции start()), но вы можете инициировать загрузку и вручную: ``` prefs:load() ``` Пример использования: ``` -- $Name: Тест модуля prefs$ -- $Version: 0.1$ -- $Author: instead$ -- подключаем модуль click require "click" -- подключаем модуль prefs require "prefs" -- устанавливаем начальное значение счётчика prefs.counter = 0; -- определяем функцию отслеживания количества "кликов" game.onclick = function(s) -- увеличиваем счётчик prefs.counter = prefs.counter + 1; -- сохраняем счётчик prefs:store(); -- выводим сообщение p("На данный момент сделано ", prefs.counter ," кликов"); end; -- добавляем изображение, по которому можно производить клики game.pic = 'box:320x200,black'; room { nam = 'main', title = "Комната кликов", -- делаем фиксацию статичной части описания -- добавляем описание для сцены decor = [[ Этот тест был написан специально для проверки работы модуля <>. ]]; }; ``` Обратите внимание, что после запуска игры заново, число выполненных кликов не обнулится! ### Модуль snapshots Модуль snapshots предоставляет возможность восстанавливать предварительно сохранённые состояния игры. В качестве примера, можно привести ситуацию, когда игрок выполняет в игре действие, ведущее к проигрышу. Модуль позволяет автору игры написать код так, что игрок вернётся к предварительно сохранённому состоянию игры. Для создания снапшота используйте функцию: snapshots:make(). В качестве параметра может быть задано имя слота. _Внимание!!!_ Снапшот будет создан после завершения текущего такта игры, так как только в этом случае гарантирована непротиворечивость сохранённого состояния игры. Загрузка снапшота осуществляется snapshots:restore(). В качестве параметра может быть задано имя слота. Удаление снапшота делается с помощью snapshots:remove(). Следует удалять ненужные снапшоты, так как они занимают лишнее место в файлах сохранения. Пример использования: ``` require "snapshots" room { nam = 'main'; title = 'Игра'; onenter = function() snapshots:make() -- создали точку восстановления end; decor = [[{#red|Красное} или {#black|чёрное}?]]; }: with { obj { nam = '#red'; act = function() p [[Вы выиграли!]] end; }; obj { nam = '#black'; act = function() walk 'end' end; } } room { nam = 'end'; title = 'Конец'; }: with { obj { dsc = [[{Переиграть?}]]; act = function() snapshots:restore() -- восстановились end; } } ``` ## Методы объектов У всех объектов STEAD3 существуют методы, которые используются при реализации стандартной библиотеке и, обычно, не используются автором игры напрямую. Однако, иногда полезно знать состав этих методов, хотя бы для того, чтобы не называть свои переменные и методы именами уже существующих методов. Ниже представлен список методов с кратким описанием. ### Объект (obj) - :with({...}) - задание списка obj; - :new(...) - конструктор; - :actions(тип, [значение]) - задать/прочитать число событий объекта заданного типа; - :inroom([{}]) - в какой комнате (комнатах) находится объект; - :where([{}]) - в каком объекте (объектах) находится объект; - :purge() - удалить объект из всех списков; - :remove() - удалить объект из всех объектов/комнат/инвентаря; - :close()/:open() - закрыть/открыть; - :disable()/:enable() - выключить/включить; - :closed() -- вернёт true, если закрыт; - :disabled() -- вернёт true, если выключен; - :empty() -- вернёт true, если пуст; - :save(fp, n) -- функция сохранения; - :display() -- функция отображения в сцене; - :visible() -- вернёт true если считается видимым; - :srch(w) -- поиск видимого объекта; - :lookup(w) -- поиск любого объекта; - :for_each(fn, ...) -- итератор по объектам; - :lifeon()/:lifeoff() -- добавить/удалить из списка живых; - :live() -- вернёт true, если в списке живых. ### Комната (room) Кроме методов obj, добавлены следующие методы: - :from() -- откуда пришли в комнату; - :visited() -- была ли комната посещена ранее?; - :visits() -- число визитов (0 -- если не было); - :scene() -- отображение сцены (не объектов); - :display() -- отображение объектов сцены; ### Диалоги (dlg) Кроме методов room, добавлены следующие методы: - :push(фраза) - перейти к фразе с запоминанием её в стеке; - :reset(фраза) -- то же самое, но со сбросом стека; - :pop([фраза]) -- возврат по стеку; - :select([фраза]) -- выбор текущей фразы; - :ph\_display() -- отображение выбранной фразы; ### Игровой мир (объект game) Кроме методов obj, добавлены следующие методы: - :time([v]) -- установить/взять число игровых тактов; - :lifeon([v])/:lifeoff([v]) -- добавить/удалить объект из списка живых, или включить/выключить живой список глобально (если не задан аргумент); - :live([v]) -- проверить активность живого объекта; - :set\_pl(pl) -- переключить игрока; - :life() -- итерация живых объектов; - :step() -- такт игры; - :lastdisp([v]) -- установить/взять последний вывод; - :display(state) -- отобразить вывод; - :lastreact([v]) -- установить/взять последнюю реакцию; - :reaction([v]) -- установить/взять текущую реакцию; - :events(pre, bg) -- установить/взять события живых объектов; - :cmd(cmd) -- выполнение команды INSTEAD; ### Игрок (player) Кроме методов obj, добавлены следующие методы: - :moved() -- игрок сделал перемещение в текущем такте игры; - :need_scene([v]) -- нужна отрисовка сцены в данном такте; - :inspect(w) -- найти объект (видимый) в текущей сцене или себе самом; - :have(w) -- поиск в инвентаре; - :useit(w) -- использовать предмет; - :useon(w, ww) -- использовать предмет на предмет; - :call(m, ...) -- вызов метода игрока; - :action(w) -- действие на предмет (act); - :inventory() -- вернуть инвентарь (список, по умолчанию это obj); - :take(w) -- взять объект; - :walk/walkin/walkout -- переходы; - :go(w) -- команда идти (проверяет доступность переходов); ## Список атрибутов и обработчиков С каждым объектом связан набор атрибутов и обработчиков. Чаще всего атрибуты и обработчики могут быть заданы в виде текстовых строк или функций. Но некоторые атрибуты задаются особым образом. Например, список объектов obj задаётся в виде списка {}, а noinv -- булево значение. Основное отличие атрибута от обработчика состоит в том, что обработчик -- это реакция на игровое событие. Атрибуты же используются движком в основном при генерации описания сцены и инвентаря. Если обработчик или атрибут задан в виде функции, то первый параметр функции (s) -- это сам объект. Атрибуты - функции не должны менять состояние мира. Это можно делать только в обработчиках. Ниже в справочных целях представлен список атрибутов и обработчиков. ### Объекты и комнаты (obj и room) - nam - атрибут, обязательное имя объекта; - tag - атрибут, тег объекта; - ini - обработчик, вызывается для объекта/комнаты при конструировании игрового мира, может быть только функцией; - dsc - атрибут, вызывается для вывода описания; - disp - атрибут, информация об объекте в инвентаре или комнаты в списке переходов; - title - атрибут комнаты, название комнаты выводимое при нахождении внутри этой комнаты; - decor - атрибут комнаты, вызывается для вывода описания декораций в сцене; - nolife - атрибут комнаты, не вызывать обработчики живых объектов; - noinv - атрибут комнаты, не показывать инвентарь; - obj - атрибут, список вложенных объектов; - way - атрибут комнаты, список с переходами в другие комнаты; - life - обработчик, вызывается для "живых" (фоновых) объектов; - act - обработчик объекта, вызывается при действии на предмет сцены; - tak - обработчик взятия предмета со сцены (если не задан act); - inv - обработчик объекта, вызывается при действии на предмет инвентаря; - use(s, на что) - обработчик объекта, вызывается при использовании предмета инвентаря на предмет сцены или инвентаря; - used(s, что) - обработчик объекта, вызывается перед use при использовании предмета (страдательная форма); - onenter(s, откуда) - обработчик комнаты, вызывается при заходе в комнату игрока, может запретить переход; - enter(s, откуда) - обработчик комнаты, вызывается после успешного входа в комнату; - onexit(s, куда) - обработчик комнаты, вызывается при выходе из комнаты, может запретить переход; - exit(s, куда) - обработчик комнаты, вызывается после успешного выхода из комнаты. ### Игровой мир (game) - use(s, что, на что) - обработчик, действие по умолчанию для использования предмета; - act(s, что) - обработчик, действие по умолчанию при применении предмета сцены; - inv(s, что) - обработчик, действие по умолчанию при применении предмета инвентаря; - on{use,act,tak,inv,walk} - обработчик, реакция перед вызовом соответствующих обработчиков, может запрещать цепочку; - after{use,act,tak,inv,walk} - обработчик, реакция после действий игрока. ## Послесловие Вот и всё, здесь документация заканчивается. Но, возможно, начинается самое интересное -- ваша история! Я сделал первую версию INSTEAD в 2009 году. В тот момент я никогда бы не подумал, что моя игрушка (и движок) переживут столько изменений. Сейчас, когда я пишу это послесловие, на дворе 2017 год и текстовые приключения всё ещё существуют. Правда, их влияние на культуру по-прежнему минимально. И хороших приключений -- по-прежнему очень мало. На мой взгляд, у тексто-графических игр огромный потенциал. Они не такие интерактивные, они не отбирают вашу жизнь взамен на вечно неудовлетворённое желание, не вынуждают вас сутками просиживать за монитором в раздражении или нездоровой нервозности... Они могут взять лучшее из мира литературы и компьютерных игр. И то, что жанр по большей части некоммерческий -- даже плюс. История INSTEAD, на мой взгляд, хорошее тому подтверждение. Было выпущено множество игр, которые можно с уверенностью назвать отличными! Их авторы могут отойти от дел, но созданные ими произведения уже живут своей жизнью, отражаясь в сознании людей, которые в них играют или помнят. Пусть "тираж" этих игр не так велик, но то, что я увидел, полностью "оправдало" все потраченные усилия на движок. Я знаю, что это время потрачено не зря. Так что я нашёл в себе силы, и сделал движок ещё лучше, выпустив STEAD3. Я надеюсь, он понравится и вам. Так что если вы дочитали до этого места, я могу только пожелать вам дописать вашу первую историю. Творчество -- это и есть свобода. :) Спасибо и удачи. Пётр Косых, март 2017. instead-3.5.2+dfsg/doc/stead3-ru.pdf000066400000000000000000011711361467622671600171710ustar00rootroot00000000000000%PDF-1.5 % 6 0 obj <> stream xڅ0 Dw?ӸP$@bCʆ &iĀ% ľ@&/ߺރJOA>)K1yìeһ{RsQ5[o (XxdA;S) qAD'D`%6'X7K;.վY]&HE endstream endobj 33 0 obj <> stream xY6 Q( ,Mt R˩RP^70G%ywZSI wb[ٸ^AC4U@&|(f˃DBB8bI=n/nBS3lQU@'SpRa;G?mB_@?&%PfxeYk̢I(qbVBS 4 ԱX&Rż] |WJu&|7mC`V˴n0QIZq̩nLo6HٜxWm˜bخi4K8f]/zbH" tY< O+2WjԮM/זMԆ9.vf6Z'^Z |POcL,ltEӪif2#\zrKTW2)KO>s?-P&oR<6Ed4I_S˲r-[ |IJ&0P#.S į)3*M[I"d$u>fΩ/:.ÅXJ`(rw<sK,4W@ӉsBմ T!bڄ 4Cd,eDٻgzyf{fdPqFlO){3ImAKψIؤH*]Q ڄhLXљT~!D.'EqI\ yoW 4Љ"RQE0#ۀCkm7 IBr4FF䮕,DX_揟Quf~"h) mkIߥ]Z$jeoIؗ)S#탲Z:\􄸬jIuT4sCgVYFo#z7C*תy}uX6!M@ڏFHӸ_ endstream endobj 65 0 obj <> stream xZKo6W!9>ma%{s!DR$E"-xm z,f$&Nb2|?Ο.Ӈ?prL)tMB3zz./⦹x tt\ El2!Zi Up840 'e5z]/\ AJt??N}*e-ki.azO.ҝmY?9HN2!l-mT3s [SϰRb]quU?bmvtaʁp\!_!+`]Y'knl0Y&F`&wA,>\߃_@$}/,P$[*2I^T-Lu8ܰ5e}!]|-cT[Rw?"cCd Kqxx@Ym({Xaw,sJ )^|zf eu?Fy)"\[α^M¿@/4BRdpTN¿,Iy0EOyLޅLaZ!s,uƁUs/CZS90UB;}]C5te J:,2Jxڔky7*iyա`F{urL?}Bl҇yaݑZ*pwJ1˱{b} pF1r ض)1[T) I~;Ae|YKM/,Q<ܩtw;&9[vKy/;v[vLƨ$뱧7uN2["kWi g[ɳj>7=ݖ-g~temBUp|:˨Po.5=<UEP"xF<ϕϿ}mtb endstream endobj 103 0 obj <> stream xn6@ @X@n tW UM")ʢҋ‰D,KG3}pWoaGޯ͈"~Rf| .TŅsbUSv9^6 6Ãoa1^ Z$MƂP𥃳jz;)aVE(J9\51clx5x6JZao|z}j誠EWGst[#b‘ġKf,RYƮiO86}wEyaŝ ~YϦ?\Ob/Qn;s`aDW"]ψq1^ΈLCVBP֌:F neH xuvRd^P-=Z; n60y3!qH0ARm{RhG 09SiI}Л eFhMW}N B Cz3   0|bۮՃJC ~c+\qO[Ԏ#ՊX'֐JD*x#u,O5yQfcN]c/@8YJ [C"K2f9QXAK/'[5齎;`$To,MLT Fv.GM%%? %TN%xjdO#*p=\_ހ4P,LRŽ2| ht^ʢWvBs0z40OjLSYf~aOp] endstream endobj 110 0 obj <> stream xT=O0  v> ؐ!rL 6 wp'j6D)VU4xI=xU.oJ98u{A'TcYn|b/Y1ۈ&"b<,Bm 0`u~@6NBN+Ȑd1~d4xZXs̾djO5XYY> stream xS(T0T0BCs# 2PH܁8N;(*XꙘ)ꙛY(YX(DZņx")462ҳ0Vdff`'B)@ @lA!с\>[( endstream endobj 116 0 obj <> stream xڝX6)RElU&'G/M+&3O ԿЍC>>}0]SStaN]BxqzP3ҧpoU%k,AMcP!IDϐ*$UR-E}wuԠ%V_R_n,2ʸ+a?gK}R}Zb3||Y )\$PPWB@j ,&WY*R>4L犗ϋBREU ܛ3 ڙWq$rL[nn'#Uc?DpÈr^AqT&y=ǤPf\2p%A`+*|$QV5*eVOda$d<29^  Bu I+F"i&WqUɬj*,*Ὀ( O٬6en~@Sg`xE56Q* ~ ~nDorZ@i콋M4<:XTSZR/RU؂"tQJWiI]5\Z̓+aOfzI{AF /t\=m<2SĦ q rmaSq92;(e|(7,vw8C_/ZQx F8.T%T.LB5vȣ¶#i1*R(־lD X~VUS <>SU\-:}lFPJ8*O L L*(yH3siP.8Hz` ȥh^j:Q DZ-g#H|`N;xD`K9vs%gK)GmeZw_(~ fQ~XuhO66Z1f_vvgG Ԩ6CNĈG<+\ q>Eu񨵤7q& m5H4`栒R }{W.?Rr {g9X45aHLPVnL+yL}9֠ ppT=5NߣR9[|dP@Yf7ևC_ !'/~}"'' [i()o}`Nǻ1EY_ȳqsM;s5~gyv P{-Pžd i`Qb|vW(f ]V7.s!<8yqIUd4I.Hq-ߩյ4 ۸`&au'|sjCzƜ?d/~EO<7ךxU]&9N ? = endstream endobj 121 0 obj <> stream xڝY37 ~;g[H ]bOy&ER,ws(G忋/I~O%ޜKD%<_>J?ƹ @҇M9|Zt~:)莐Ƣ2J43#g鷕ʨ D^y=[d.^$^/ߜ~静$.I\Fӈ:oKLᙪ(CjMOhjP4r*wOy<tFqg2zl9*|Gm,rf5sQFGґJ3ב: d42-aK g >%ؔ9$AH 5OFPWZVyE? w@Μs6 { yiMN)1;_Eڻ: L֌6Jy'HiPx')S}7Ҙn>qi?K8/68ʞQH?9s9э{ejp_ic_dzfHFHv>IZ،j>Ÿ *9ךj`CN>7W^Kd!Tz&­Eڞa2ڐvXk 2VXn@) D;XFlJFR|ÍNیL}h%pGʬQTT%7VØ E9mTZ"rR'8z+ḐD*fݢU݅Ձ4(kzWޑewa/d@V]@AW) >4xzF-)HC5 VsmM6ښVɅXsUg[&ȼKQ@,*'r$(ѤrAq (lB+Sbn90&J䏥n)^f!=j[y oKOa?]Rۍfܫ7F҈hNQ-u, ~#QrhQ!ǮĤuUOuVJM$r!:Ye{U+,(!: c3Z)z^ j N>J<>.B) ѩeUdug`gy(IGǒS>f58/bgA;Il85\dr 翅u$ԊEk)YxdU ]ТN'Yar.pwMrtƊ51H?a53M1W0(v5 w\׸Pj#@[E_f{7ü(z" ]XS@T8R$gr)#2QbNS$v8{ҲGrrZ%N{{\] ו&u !Wfw43sd$?-#*T]qvT WxbnT7i i=I endstream endobj 124 0 obj <> stream xڝZˎ6 +qe E@wfWt8qW]7ŽF(<|h.]2\|yx2v0rvHf :3vs>Shs1yϣ>5ӶP9y;S(<;s ƭ,3)?Y.7 _C+2?֬ښOn~m@g G씟,B>\k0Pd/S97j,+oeg<ìD* ǜ/cH~'*s24fUx? bEr!kr$1sÉfQ D s IMde@Gbpe \fE, #iisQ= 8g4[3K('I xۙ459v3O (R͢)͆Z6n̎7Dz:Q2j1 X cHռVH~^:5J]%Ɉ'«vhB)jpKU rf?ÚK )a5izXS }۽- @&Yp!SRtSHg fx˪aRwK/@SLCS-˥{g(DoGUߑ7R.6DD@>T!oglJ~xuvh~x.5H;Pg \펫u ްCݷ|hL?Cg>!6QJ`ByN'/=5&X-Mp 164%$v';7[O[2m՚FjnGD]]8XH5{s[/N-ʴsm,РzM Q4uZƥ9zMoV j+wZ4Eߩ+ȅSnN*hN?+qɍM Ӗ] s-wџ*S}@`%_﵁%|tBT2mp!ɾ+̞q{us?930frY'^AcM@+(X6mː`REe~fr/a+X}Ex&\@L HH0(хvzIj (uvZa_'i{}q^n)ne_l^kE'nOŒ endstream endobj 127 0 obj <> stream xXˮ4gljHә CNӀ|Wǧ 0Y|u}'3{z߆h)̘`<>¢p脭Ke4pLerqer[Ĺ  2EsHD~|ߣMy 肢 |pW3;>״-;psӑ<,8&|">Jr& u-v6-lYS::Ìx]0dsS|K E.BkgVpJ߮N,L_òQ-FCT[lR>cN)LF2RSD SW}Fu1DRN{pbč =Xt :ZUթ"U2fwqbHJYlD5WRpQ$ co23ZoQ::Ss֪U#(Sڄ T9AptF}e kH/wnnoLáuL]ss5Xi4y;ć!Ir-\ksңW7rU.. ԭ= S~QikkJڡ=yqŕǍVq ΢yuטo >Xk9yb60#{%Ͷ7nثDؙUC_b6uv+6aw̚m|GzU4W,FN]!;@:QӸ %.!./+Ѭ[  `tҸm:sKp ?v"0NO熭+r-lT۾8oDp{|Vpw= 3,Z,DVm+_ҷnnilDMw'~t_ 3m endstream endobj 130 0 obj <> stream xڝY+7 ;z0\H ]bRPCxݽ+GCQ!忋g/?sYa#_>.?/- /6F.Woo9_>ֿHߍݝ[.G[fF fw ~&3PB *1nt44ߒ˔i 83 fx:V1~[al0Be H S-UQfhǩҌ,'_n<8Ngzz(ÖZq43NtHUfK<7fk͌k`cv Dw,T$u$oZ/E0xp/,Xokyނ.n]Z ]Bϱ\|e30DufU0ei<(=fv5q0kHLאCI72cryw>CN6LB\$;;4g5Ih&LdfK3O5UiڙW^Y6fPZV#yǀVUh˳asxΤ}cp3=7<\Q0"v[I9%JVUCQ|U~_=0sj̳$^O`lE ͼ^rai^mcmztg\Ur|;|J9fE]Zw“]V vBi|KKڧp1rNmٙ YoNCp7\ȖVU>؍ww,qHnp~RT%(W;n\hFSS{'-2L$AvRX<b+R6t~~Sm Z?6'9"{w{'VsU(&#c/'DC/6Ty@\.Ҷ[\gQ%4@$A;EpH[Rr$YcZ= %>S6sJ>B*0$X@8=(x3ȚVpb_VP }0MhkP1HC> UqI$eGu'ЗԌxЂLQu.MɪvD^f2rr Kt1$h޸=#~N;phssTK蒀S5a"0T;CU dKpγbX,m||WU*ٵ+2(嗬 yqߊ=&C\qXi0VrUeXxNaL(Lp݂rmыtۛS}h m`H=]蹾5ˡr6* /qU=}HFp5[aڣ*šl{F&`'4 !..v.das+Sk]}9k}e$hcΜ8> -q+_[z zϻ"'8URQ%\ˤYK_XCZ]*L=Wn@(Bj%~Zem)(Cr=(U8luɲV>񍕢oFL|jJk$Qwu$皌]p)5|?in6f: z(*LO q9zei)y'|.J4=vZe . bo[ 0غB$]iV}D x2,uiR'֊'-9dFYfkh%Dw*nxNW~t-ͽ-ێSRU7 IUHC+PA(׹:t'SayXfy%6N׫mI- &UVxL=r>7n-9UZ$'ƣtU5P[ܩ:O`ւmK.nպ|ǰ!ޱ8oe}qT#9iSsk>Un, endstream endobj 134 0 obj <> stream xڥ$.WthOgI 830.GyJgkjJ")%8/%w_`ٟ?~\kJ^&-SEO0p6!k 5³¸WV\u 4\`\3AW>Rl)`ɡZixbqRs.W'xx 8w{)ʺ+C|¹Y1 eස=D0E,2_'G(G C!"wo::%UwgdʈөtD_G?^A-$2V*Ъ7jh"$q(훔EέB,\M,H`!Gj,KElCO =6޽ƽW1mS=׋ז3teNphZ`k #h#g +IS@ 07ʽ2 X[[Cb1$g<)[Wnq1}&`CNZ\:,'S$eҮAt@<ö Jp'.&{f7^.3\XǮ$H)DUԮ8Kǁ [T F;M_1m[ kE=1c\|mttwǫVyY]KR/hOjWΊ֑" C9eIN#xP(MHR&d( 0$mv( pDѳE@(LlP' cl+כplEtB2iQ(&*?1Tm~ A`E/I6{Jܚptg-ԾǰieC d*`݆)$QV4GsLt #>.J`Fcd݄2_UtKFI1gC/nLPv&mH?ˉ]PK/|^u0ApBGðC6&1L??+acN냇ɞHw>-|ݝQmpLęhNGqFluUF1cvs5!Ue;xJ<-:W8 ; 8ڃ]x/~j+t=k>(gpBSK'RFPaʸlOќ1/~^"BMT~zHI% 6I7o;<$ #)ÍsOȵwϷDT[ mkS|4ݏ?jlǬa?iQ endstream endobj 137 0 obj <> stream xڝ6lWm n(VජCĝ:R|H-ŝ`G(oҗ.b^&~ /o!z}\`XSy~\'Ʈ F0VV0<0`??C:O}VϞ M͚oG1qO :<ˑ#~ 〤?EGEGu[kz Lkw%|:NN]s1T0*{Ms8iX0Kdx@*PNWċOeտy % O,vz=Y#&,W+N5WLp_0#M66P fvRvlR֪O[{G/(#G=ѐEviV彨ޘQ7QBNLBaQ܇b2tO3 xTXc,PHVS.m;%Lmùn:F"e6_C7'T0+^u~}tGW0d]b8HW1/ vܦV-UOb(eHJ'Wˣ]3xdq[NR>b9 wN'K=agNo":p!k Ii+])tTf <8WqSg%[GuIF:}픮TTQ9᪭e ݞE0׹zX*d(5;B[=QY7$J@n467q-AtINZWthvI* 5{Έ629Տ#TL]:QM^jݛ L(h{& ; )R`@od¥GTo/`bƨsݞvgUԿObtM%)ٯ}&-tXf*w#GއuK⤙HZyθo3v:zoUibs[C)ētcԋ!dzvLN>8N|ͨr tYsiymKT6˩xUWF4Ssq gKt{2l~n}+vʔ4:nt?+9*/ ,MGMC}x>#h@Fr4ř0`GŻy|H)c=v&vdfUBbsʹ}UuBWaqW* 6;!'ZSI iڷaTe7Z%> ÿ$v endstream endobj 140 0 obj <> stream x6W IQE$@)dٺ*Ep^ަHyO/JpZ_fO 2 p)c=Sz1WgjBq%+sAI@BmĻ "Ƌǽv3  *Ǔ;m Xr^1]ƔEeF\gFZ +0G>x+etd9ʂ<.wZ|'7 SF \=3̎}G+t>x[  RVܵd RKjDzue(4A%;cCN;N٩9U2#cCӰ> stream xڕXɎ6 +!) P3r з )%EU dn?lzh_t|8| v1> |Mq >aaa'ߓ0do?Sú"[u+4[w8Clql>n1FH|u|Ew19wF}"J=vmNz_ E^,]M;LfPݱ$֬>tobY$%jc"{LcXĬ|ϢYKdq̢JWB HyB8˽{1~(Im,˼EZLW)h4D۳ [xٷ wL'D(z?ٝƍ*uUC򖃿91:R8Jk|>WGoΥI]*A O趘]*o|hȩdA|p.$Ε}8TNZJSsoIQ}#GcL>b2ZԜT DX2rF#S˰X9ӱ3IRDzD3!vL<;X mCU6j9+kډ1w ð_׳ճuݾp-ҍnrCJĻ1_>|X2vЗl$H-kn -hIp.w endstream endobj 146 0 obj <> stream xX6 yԿ  8[!v;u/HJ;9Cq`ǢH's3dN_W_ӏ4xD)!tvf 8!qP`GNDh3sqYzNnp-Id7! nDVU&Etȑs٤ar-,IJ z"ef|t/-\os-1:qZ aG]#+eZe˄DŽ~qc 3K.Gђ mM8o/)dďxMFRЬELVNޖ\exR|}BձZ+I ѦdD1٠-ق[q$0gT\0y-TN% s֓$+)Q;`@Z7xcp,HMataq}]atEZzfX) Jx`‘:WA(vV)H I:Cꌸ#C3/]BHR{7$ؔ.ͫUFٝB-L ֆ„{{9" UA԰686dR9Ge~9䲐J澫Q'U%Z osf[@^Ă5xڗi^Ǖ{Ŀ[oџ+p̵q*r о6߱3Y5>w7 >bi*MeRup.> 6!3"sP5cCisSR$8Qc'>nR>ۛ.c:_ se4DH/>[>((І-)%_v-+s7`gUѨ!euW>ȗA3|u#Dj D@5fO"h(!@M9>I|+{ke/]T]ݓq.|qL r_ . '-ۋ.?olrdv.*}(fUr ZSA SQ]:sj4s"L~SFk88N.na|Ic+W@iJ9f#o}k@WǨ/nͭzP+Ûj+)]*o}| lq5/@f^w#ΔDm8v0 ~ |"V}ɳ 7 nW*ڧbsס k||M{P> stream xڽXɎ7+$sot-܂$ڧk!7͌vC=X#;g3<~[m̓/8=|=ŋr Y ߶Hg^J:Pmcye:A"+ւV^Fj/1,Ujl0[ղqҭ|$9|Jf,ݨ68Z }uԧ˲A.:Vhr4&l 7%FъYNawV4hf6: dSGa=ԶTVwRιJ tr (C>'Wr(8tq\v~Z}g7h,}>BGL˔TD4B e}bj9b qko]جSff{[;"c2iG}y2ΰR%5OL6ϻsC`gUcհS χZu[%y*Cچr3ߛ",s˻Fa6{d"t2_Lao2Tc6Ѵ0*tU1/NPliy+{jlew=-v#Nuv mܠqԆ܆ X4)$mǩJ* 3vh_^<D(c<0<%B>mz`2 ^KKZ}Nz!9BQˢ DgZ\I~WeFaMF%涠ŐK8ȮŶ|qqxdZ/觌}h{V~0qH6ڨ4N]Fҭ:-//$#EqW.gȩ7GtͪػNGubk r1{^=kސ~+:NU1O-#aWȏAƝպ endstream endobj 152 0 obj <> stream xڕWn6UE XMt R*Eɼɕײ Vqfr׭¯acGoaэcnts~S#q$a.0fn1yH0-rc Dr^ym !9`$o(@0HL$i7hpFaCv̂;{퐷鼊 @Ml69lA6d3h )8W\wp̞`l>X`^I௃%/ г!h]cw ?^h7 lۖl?[Xg'hQjfA)3Deab3nls7A? Z:wGe$Ea9`ϑw5mH]̗h bbC )b7nvPxW^"C oNn6br~:J 0cM0%1>%AgGgA- J_&/[$s=?sfp9 _g,jKPxk'aE9KCVĩgj%!kȞ,V),.Lp+P oZ oXIBv$C% \Q;U g;U;{јPjؐ&4PY@Е0bG%╉x"3)btT7'С7ցVg[Q^4Z) $lCd%̧37!ܦP}\'*0[MbW M[u5jd. XMFn5I=4Y\SAj|RR0-9E9 g y9Osj-}C( BZIV|,Ӡ8{*kF8M Ք̍wI@ۯ3MΉa'[퓤RFpg.4RjS>Gq&H&?6W/,YRRJ|I)ۖzO-nyz2gs~Ezhօb!k$$b#=TY^+ch:r6uSosK1S+XICq$gTJ[3"Ci)Rs" Z͠㽩Xau6}1(1ՆAV^~_t  _6 W)?q endstream endobj 155 0 obj <> stream xWK@ +l+= HܐzC' =PB7~Nv%o.gu|wY>  tr\>2)@Yh"DV$W>mzfm&!Ql|(0! L(: ̼>ׂ:8NL*E5YBQM\WlyTWI"k$۱x8} mDi>i@!0S;kA${vn4i=?>e!/9cqðP37^p5LlAa^~n;$X=! ˨1>$:7tN/׃q{N~-M1#xgMB5!rqmə48KB*2b1Uz"POCf-+@0Rµjɖ┓hy Im˓ڸ́@5p'GhױvKU:**FC.-. q~ctj/(#Kqk=䠘L|u*TYϑNbt⇼)-6c/ {%m|jZtmX i6:nhM0-+>aoG=so;Yz6/&OmDuFYw}&[9f:M akdFjh~C-:XCVehimbӝ" KjD7?ͪ endstream endobj 158 0 obj <> stream xڅV0 `d(V [N;u/K8)dYxtHg;Cvh]!9q8yikR% X/dtzX~@ ̛K_ߠɔ)4 \ X^N#h{ =jT+x|}An^ri43,3dDfp{`J.ⰺ2SV'  XboMo 8n2᩻BhJ&;lg.dͽP$M\MO?.M endstream endobj 161 0 obj <> stream xڭV0 {I , .tA RP$%3ddKxX՟ +V?TozJZ= W׵¶m[lc:x\F0h@1R[]~^a뛀6)LВ`)LG3=;= K;4#I%sMOHr1GF:Vwۧ<3wZDt:YEzYt1';'4Yt3娎YQw3NA %grB L^a .LRHR lf7BQ rsonٍ,tG]=7fG!nP8kqTe9ls $'C2'y63pRSʒRI@@AjY.ИTfyD\]LWVYY!ko͊gǍm> s4'+}fBkH^*?}pVO;ty)Bp$#6gsިاx3ϒ> stream xWK6 W$%6P[܊wa2Rdqv=tDlQ)a.C7IOo݇_mcH96q}C1c.#biN4'!" "X.ܯt@Lk̥R@OVl%tƘEt67-u=]p=~{hƞbwBGZ8RsLߡE% 4FD݁E,)T(h!&G}ÜX0r"ladH(~ O4pDG8f2B#Blc㹷6B$5fșf~i@k N)]Kl`Q(\ΚV׳r`QT6]ǨGżq}8{f HH/}[5,4zb8Yd|tyuE'h0 =/aTh2%7lZ4 XPG?ɠ^9U2ߤ(x0Z5רj06Wb8BZPsװf*Â҄ *]dHDŤ&>8F)VNQ%k٩vl\TMYu#F|E.ɤWfEY, & &^%{Τ'@^tl9k/jϢyGj\VGUҨ@k]COyKe̾8'Pپ}hiqi_RӚ22FZZ:9Nn{|G0[L͟]䂗j(U\߬km{AKJ_r=HIOBQi-3bUڸ~s%/o}Tlj*v*4ܘ-ҽ7Q`ZbMIBˊKn.IKDV>JW H ۏ ovdiz@W+˸5+*ܴ1:RkWy hkdUAM|͘>} endstream endobj 167 0 obj <> stream xڕTˮ0 yVfHfXqW, v{3M>>[~McltݝRvDZw]y+G*i|rCcѰ" eH|Bvq]^ }5xlC`{+J_fXfǻ觬 #@!@x%Ni&O-| {B_Y-wia"5Sn-Y6,P,w},S29=r:410IiԴO @P8,i>W2{)/4M_N,qD+tYWMuՉ<\ew͙\ZY)j 'v!څ(]$*~[Lr9A%5|rITj)xoD17ˀZn fA%+0 MtieټwS%3Pm|L~%līOxMG>VJ I[kqHq9a- {S B$Id}  pC endstream endobj 170 0 obj <> stream xe0 Ew?`QHlHC_abnJ)Hȹrl'$!FaN}}Qhg2bT911R H[:?h4-3(Sϒ> stream xڭW8 +Pi3 l6@e \>&`?YJ"uT, ,|A @jH0ןD^֯w=y2~ Mvè4=ܷ7PPi@DK\?Fm @SPZVbHQj'HIw5mCF۞lafٳaDl4  [cg0:E9LށJEdvZMl/jyo>ŔIΚy79(՟5[^,8e(\@2n+ŬƙCHA.=LL!kN:K&y3YlSv7JX2;+!i?A=!`q" nUMl88݉o9?roA`ce[Pp(rQ<;U`ChOk_us!5;nf{F[S2g$p4KUް_!gJTs, W &P6NՖCIR ؏\<+\:,OtuMv1989mI r#|Dex_%":] |=47V4,oL,Vd&p=NHngVnr2t3|-郘GM@2AO]O 7`xf Ψ~vï%{[}s^.uzZRC]ݢy`lr[.*zu7 yS{* dZ)LvqD\$w:w ECۮL gs5XIaϛ.΀+0ԑ^Tl"C!C_ICCu0ޯ#sDwHҊى݊KgF(̓V h'Kŵ9rx.H6g]$ )(5e_OH'o#5D;D5jam˷v#HpF endstream endobj 176 0 obj <> stream xW;F m + 0\H .H!VCPeߛ6xW#y\uЭ_QןݏncDeyN]o\B.^Cd) }(3]/Q4@ 冺%f 9`!̡! Є@);{u'V z7F* H9eGoOq|( B=ʝTjKf:\qyGt#yhC/'`JwʀQxV~Ì2}B7 ;Z,I+\l\,~g]%/٫T-A7SSèy@_. HOs/|iaT hГPV.03Z,-#΋deC&ovXr ~hk}Zb_8Qݩ<١5ʭN &kOF'$AъH_%褦+= V]+SXVM<Ȕ$&~vұbr0Ѩ v.',,`pF)mw<͍mI #ilw{u?7ڃC}34y ߯Xt}Fϴh4=/ӤE&ݽ&ɳ&/n> stream xڭX6 ~ [7u/%EJ%7{ئDG"A 0WGk7?9:ɆbuUJGhZeR/{6A Ь2)"<{껭_AG;}"2WֽḬ(㕙M8#v ;͹_G-`` (rmƁ;Zg0;0TG;}SIH,Qw`={ ܰńѤ@ivspsp-r,֪9a/bp҉=BTPcf,%`/zhDg{cqCE׌`HѧauZt") z=u Jtfh7rRxr)?4^zRJYWlLuەҳup_+Q SVq{9Tf*OE%Y`|-JH3ka<<uk$-ϖ潸UϛaS`3rOIx79 =[Vk>~.6DVfNhRKʽ;^uL-ۛ UquErŁp )չe.ќk++cRS@-ּjdY$$u}ҙQ1,`28y؏y+1m$W'{9]bΜ{{QF S(OFٳ]HKd;FDRjSK_͍'zJ]MQuܨGtWLМ-{䕛[jLlo|6L8s~ s'>Slc?#5"ַY-pxi*w<~_HysevPO ´#G:AJ\*2 1a0Y@0&%8J2PW/NK:f72dyB-#__Q̷(/PZuzLsPĶ2|kay㤋*{}kh8lԎ!StƜoбĩ}RN\Fe.qh\(n^\Yb*Yn}}Wg|O= endstream endobj 182 0 obj <> stream xe 1E{b~ q&$ )tb>x29\'7CObPr8LX/= JQlJƋU2]wo 9.EۇUy`2U(l`@~SgC W1 endstream endobj 185 0 obj <> stream xڵV0 R  .tA =N"߄HYcw$%4x<>R_a3ɏixzɣK:0fqv  h, $u`rv0"1X)e@DZ2Ր!ZXM0ҺVWA&M3X ǫ<*4PӋG1 H#7Sz>Ǻ+.w=шd[ /Ԯ`E I a8%6Ty1HsRa:7Q\780aSS=]5lNt&YB r{`b@*(k5Avrv[3y5R'4FqPxq;gvNį'bW-i~8҇X3_[ endstream endobj 188 0 obj <> stream xڭW͎6 )q?{(@nEc)J']AEDݿwuR=k7>cwqz pD,a1n<^\00%:`-şYxƼheRIP,EkF] C,3XnR60z+팞%_CSJep>k$kF X>Z4Yg6[%kI̊>SŠYzϫ{;kӬ(+^XaZg7/*o*!sP-Q+\AL2!B`8fP9bAZd0 C{x )It&[;ISkfi*LRVf-9UIJp>M3NM "\W$L& a\( ~8bSފ<--Qm^^%6<[wwo52> #v֏+%Ih-*1-_V$`XrZ ZDwT1[O`=dAƚ[^ 'WB!'LQ;X|[˺ Anfy /e*Brr 6aԝ5Mrbդ6Orv|Cr+sڼ'OўՐu:;.C9.%j\6uh6uJ=)>ŏgJvىȋ;b'+fwJPKPqˁTS|xv"n;1رZzx7"ޘC }+m˯xܲ͞`YlP Ǒ (~ ܬgj0vwkOPЕfo%TCHL3@,Nj<$GN( Tμ eSSTW&[&]bĉLYw/)~& c8M9-L)f3Lo+xLP@LPx_]~gcR,_"ۍCSwt_ݱV\_CAvָ? ZiqēO)~[ endstream endobj 191 0 obj <> stream xW6 ~ԟ 8.@)8U"eygƹMsſGπ?ׯzx~}|wOm8f z7zG>׭<.oo.> AXs#QyzfR#@:HP=dPi.j0]3D%Ar\P4ZŧxUw^-d C~4ם,4rXkbGR"@QR3 a L ynؚAvAu]c2V͓CW,*W|M}:{>ZBǏkIl(e_y{2"NwWLnݑ&򍋪pPMs!(M#D-rܞ"V:$keV J)هE󶟐鉖նC; a:˭$]m~I՗4S!uPVi̵y`oU’ c@)V#CH#lz U=/K:8US0q]oR3.}yMh6(4n>Y~ܑgؾ~hijZjm7:@ ҟ%,fM6`5UZb0ѦALI{{_tjsM޳%nm -SV8P%7qVp3EgݳAGSshLS;Mt> stream xڥˎ6ޯ$̡@[s+z/Vl,F<IQ|wSsy[>_>/?f/B\/ަ/Woo9_>ݍ>?*pT[qRB@Z]}s}u2Nk_nJ]p8;m0iZC+X` S\3"þ~|͡.oG8[Sf^1>KGw;kj# Fw UXx_L8ӡn [-[04؎YziLtԹ1k@Z(RsPHBt]tq,'%RK@jn.kr`ձB>fz><E|pկyGM}?V\]6CagT]ddW~u#:lYa+P`on4d67z|rL 䤓ہ "6AksaOl ۘC&0*!E,vIn@bLAV9+({.!&9$}`rw '~Dך8,!3e2V5Ex?Y̾RÅFdHWBxp S,B*Y%'$!kpm]ްQYdH!tܮf%=LJtWRC{mĘ*qCc0ˉ_DC{mkt dnyVƀ$LSE (=?Nv 4< !0,tgbsǀw,Cb\4[b*%<{f mhEv\"6.xS$oD9ps6e)|)C]sc/SaGL,Lޭ^DaXH8W7AHMU$uԎr]̟) o=6{$mic}d1E% ҥJث XE>-T1\7b(PFQ$V\k~/;l؁H fH{7FnnBi㰳8'n!Zc=--צ+4>/K !q;-h4*58\eF[J%|85ơu8T_# T\TVgHUynS/>&*۱P`ޤY{3\DܷJg:O;Dp33s ސqh1چF!A]M*edM(a*9Sl+n:se}89!NJPgeqqu%{XTHtW"[IOݺB .I!@3wKN T0p«빘yMQ\R'O mtj:ݕRn!{@GJ k5w;w.]UGݮ P*uz18 *1l!fZR"j&zT^Z{+1^ ]8ݲ >CDّ'mqse(H]XSdMCbs/ix塔+M=k3Ù})FIz1c/i)iҞ[+#k^ti_0fQɭK;٧`"h ! @,-0KنWE((!U{qQX0{Y|Ǻ[D2d!^CtA 1jt{y WV8ńqPN0D8_l뢲amKbbdjFcJ3j5 H˸_| LMd RLjyW`r̪6Y7~!  )Tt0ÀF8…bOӞ`hdz s6m\q;qY.k' yfS|v;|m?IvtX 5SSUGl泤>@ϠϷU:̲BO>Z+hK }rٷQ\K 4;k1xZMn\NxH~^{]-lk^;*L~`O endstream endobj 197 0 obj <> stream xڵX6u&pot)dɺUy,y v pg;Cvo;mK t[?KHyxRp[coߞtlteЕ+˦%(3&Dh˷7P=Û LRi F?,;8f,5{0;n>5adam'Bt&"Ȇ>sfnыz Xa29L= k9ľt^@ ¯Z8Hܨ9BqC(/vMX5e0YvҞ;SZ9_Z]鸺ZZM@M &|eM aA8XilRyO?WR@R!m0\8;B'ѳ W,OXAbė6oO"kvY;('NBVF$>76i*NSZjmNK~6Ѽrb :_egܻ=.Un maN]IKuFy3;H:Tl{{HF'=nl _n skw ؜C7r'н>|Quy:l TuW C>q[}q j&{=Ag'7^"iWFw"ïo#/|w'_/sb]kolǮRs?ۡJ endstream endobj 201 0 obj <> stream xW;8 WLz L .WxvMHN6{w]I!~ 0(!hW;>???FkqqØf!(eFy4 Pq X0t-8O1d'2dfԫaEP 3S6 R0˂2'²,δn@7ι\foAu}qI2w  >P/Tw K4=1EGlfY}ѽ& zlʿ㧶Y/1Wr/:oJ;c25B(vI,(3v(ƇD##lo4'zد|ltjM=T!ʹA]6dm+'w kjd.u*8sϜn?[a>c)0^S˴X#ceZ2XjCK$Wt3ܳJh8f< iP3.,sնZlBM˕ڲ~YiJ̅V13Yrq V=ZSfn9f J9^2dZ"H3qEqy˯rhWP1\ 6^$=;_sJ|u 7RI>dsPQ'@$ C<6%_QWJXS1y?e6'Qve^6enS,}B2RcX,{ŷs~2KC|DGH/BLH|;K=w# NMN|7jR$ jmTWW/W3q\<&t*MU> stream xX6 ~6d(VߊNlw_ʫ$;vH("?R\glR7^cDs:]C5vp6-Rn2c?hO</!98q+넿_"IdlBVͲx]rd[%Gu{ [wDbIKA}F<}_if>lp8~RͅJg\].#PzU3SS q,ؕ5Ǯdp%{tpH `1=W>{ Ю)I䘛evj9wՈ-) Oj0TeSX ꆖUa0h#. 5^ޛ @S̶25[p*(lfuyFRGos䁷xp1>zkE75cO~hSONSdBFbe`,҇+:V!IL`~a]!,ۂm➾a*̈́a;l+ ’[*ro w[Ni&YL7Ʌ46=Máo1GvT׻ZE)Z{ /5LB3~dVQ4S-m* J6ȑ͛OLY76kX3]lA-Q9 1s>E]Fa% 6@I x-46ki}bG5Uhnڳq 8* Y1jY2XsSőzs5]C-{(˗pʫw%#S<2^!*0!lhpo5$94ծWq4,x4SlX,;- z*Z/&[Y@˓mIcb؆J%jc yXO+>e1 l}UVIwxs?پ@i&d@:*(>Շ9x9dU ˞d_! endstream endobj 207 0 obj <> stream xWɎ05Ԛ qCtbN Y:=0mjL4\3ҏ:~4?oGKni3mJev0~a%lk{ y i!y:u4"cqy͂#{&jU&^F ֵVWTvV=}f9.hiz:ahef˘#oLs2AI#i[~uSrAfG.MʲҞס;T #qI:#x#Y8bjE?Ѽǿ ͊o7O,]f>βe҃GsI"ʺj^ec&girOB{x )u塧9KEaEXnHmF7D\VNcIʒ&lWm٪ש1YGk{/֪8R肰.X~2/هm3zu/pƩ\X\1$ CƋi a hPzMSׅ Ns$z3݃c]lT##J|T,c8EE[J '\pkW o-sr+ \+*՟ZϤ&)iFmZߥ0n3n0=s`7x-Y4Hgn\\<P-逋}fDUGqp=wmfF]׎xۧbSݪu^W(cXRm]{9҄IrYi7vU<&*W;jxK C^j=}@OiCk[k}k]Rk`'᫷A++m޹0$zzp,0(T`>ޥuLF;TP!%L zmBן l΂E:o?/,$~Rܸ~T\ endstream endobj 210 0 obj <> stream xڭXˮ6 +II,])]+p{V]7HJ'q ?(Cݿv@?zCw?gw gs0s 4Oǩ{\,@Α 8=n}D٧;NgP 0go*HH0VۡMV"sNM *iАf7f$u T0ا;NgP߫=b g3"J2s⽝cWjZ=5J `Lf]36'̓U`ѕZ+ue[{du]ңZDyDG6 bA8~= b@ bPkxƲҪ3Y vxC3%srm5S:u9٘1ZHF;+7sPIHHp&سCl]#tǝ v #?'6yEiѽ+^tL,€e-< :_7n'jBJS UTV)ҵ_W/HcRC@{{ܛpsIޚ Ped(o(g`27gUQ2x>'˔VΪ?EKV.uEMM6J\ s]`]b#<0(-4VVջ&^fd5 va*mj`ݳ!akB(lIwaUZcuT-teՀvڊP#m@ YZ7뚯R[ot-yZk[ HHa+uUp:sɪE×nsח*$O` @ǾKn *Jvn<WHdH7J'%"M;Qc ¹TA0T9ZlRm$HFv`U%Tmѭn{YaLa6Z]7ud)@|ό3B[RM!Mkx7}v^ sC2B0ZVJ<^)f'k6q\<Hm8jg[|p\;9fQ>;=4< _|#ͣ 5хøxqӠE /!^Vcnouym҉F t(ȕ+erMʲa;btv,*;ne "U"4.3bLJkj?ܭ4$8Nzkd1/uԦh?)Nx'`bGG|M Ѿ6a34XL 鿠{N~x)dC~>9<ܨNuy endstream endobj 213 0 obj <> stream xڵW6 ;[S\&@)+U$3b^ %/GtKůqkoZhs;3]c}ÆX7֣$f48Ǎws7/_2"x͂3v)QyeeQl=gjMƬ:.zر}LfIcG7D4(>  X3?^ah)5,̬MU|v:=}7'ò |dn[b</ b9$^Hk2 U>Vx x؝RW'QP.,G!hrbx08IfEM۵2jnkܤatOCEN5a!5T1i|/FC5 5ѻ [g'NXc"eY뚄#@pDSIn#ϲX 7!Nᨤp}hI2N"jY *Y% ʹRj[!Cju6ʅ^Cso\gCUNQ%f &Y#rr*,*iTHfjvG51aO;/bվv OOMh@~qf\Q_s;|UO+j13a[Gކ\#i TAjKs:`dŽH}^o&="CkTss

> stream xڽX6 ~  Vt͝:)ˎ$_cȲ('ޔ5@IHޯUڟ͏fh'ظ]lk98 =鐠;{\=zz#xj4]p$=&Qk 3?Ͽ WRlC;Q0 &?3W"5)`_+vm1?6:GH~K!C`Yp%|n+qPtcۣD#hg=}A&ՈDGm6,B_,AnūFIL:10B 0GΆ|@sp4Q -HC A ^8fyY.3, +xX/PDHvdE7IԙBv0iX+:q۹E~JpwMs>bv@'sص޹ցR&p33ǰ"aukƺ Xbrl4>x)|'nϐTL ٜ134KnڋZf/Cv5i־+$ N3Gb].E{\ lmںI X^xevaCy{Ģi<+YZ]SN +B1nZi+kNLi5Ļyc@sRh4r@5Hřߛ8{$8IHPc1mC;i[r-eј9j#"O3~afv}i"SW0{l _Jc[L9!&o0^ݿC{y.t՗??|j1w㴪bz,콬 wT7i>YKdŅHsŝy^wب/ h#S4ŗzFapq:|Sח޵8|Ar%$GVQoS24>«"-qrQAGiӬ X* (8`7{^0YP {`b.tdКwh.HSe*aYvf;CelYqYzL)ƲM]koF +yooQFءAGho~:st[!;$MOu}G K8/d@EH§0La˨D-Y +SUyJ޻}z|P(ܹ`~_ͮG endstream endobj 219 0 obj <> stream xڵX6U&,`H` ]7'E^Î y3# v0gnоW;Lc tCcNe8y;2\׿ _±Ώ `[=ڌE34{9e<_abBcxqgm[=٨l: ]'^\qQd73/ׇba9(1(A P%h`8cbı &Z92fy)eMgq26.[Er5ΆɅp_1~Dֳ8Qg͠TY]>Z;["`.2V66,a 2@N6@Ye9 Ie\N{Dg۹(頩xCU|J">ZM0No}fO=o IQ" $vD3v-Đ6Zv/RmdF4T @'֏ul n3/' 癮;veSE1̅AC覬89a?7ppHQ{ uMzwЏ+GA aFDMvz xp$Χq*LpOe ϋ¿q,IP&% w *[JXgrߎ^[O*7(`oMeMMgAZnPA[gmrF,z*w4f%`Ig偂LU9Ki1כ]%x %n<1*ag =}O7N4ooxiQmK֏z#$xXIFEH_͜ĥEL̏9+[#8_Tܡrwx\t ]!;j/Tme[Us*@e{JLWKK#DdwW7=E$iίuDRԶfۓЏʙ7UH?Vk綟b0pHG=)GRTbDZkAGJ9'4Jf֢X;;y{5i>םjNm|՞UHnݙ:+%rd̒մκiløwNm I_y|>z$lեW;15Zf`RV)T27Ӣ#U¢vNRCۺ0ʈzU% rcO1qQDQ>Ư/$I92-o^+V9e,8|Az?: endstream endobj 222 0 obj <> stream xڵXˮ6 +I Y 0-]+c.g$SWplSIRs2Wp+_e9B_Ehj-Ǥah6+;5*4]3߯뉥w.Rp+PLw:7F w`t~dF|O%o#*RC3mDQROM.;KڀqT}=+T86TT4ޥ +fh1mf $9he{bcH,/))Ԥ4xk"F߬r.D~ kTaBAtb Ƣs oP~ ^!  m-$뉤(eqw)l M!46vw}63?Kn"(Ց- iM Z cPJP"g- `f?J~,S,+ aQ%(E߾ʳ9KI *CZt^d+L hCR铨0U*A և'ŶP%&($P1U$mP҉Dzc$CAg"+O.T.+_56; /U \X{@=?:xI΍eT]J5QmWL* گs^630Vvil{F!ꪱ!*ܤ /HnLwujkpX'^}hōNRǂn*y kGn?]L)n8K澡AR3)-dIR4!G'eu (unɋ<+-=[_$R)}&僚0T.QޯRj$\~k> {#WC X!yS$jHgQ7g"cJvB)V43b)iʑ%U3eѹd(&3}mc]|E2/OUQYTh_,`={D]Eˋ* C!{.3t_jܴ 铉` r5p=hce,r G4rt{7əpocQEE||-Fe3jL24fL Ioe.@=G>*Q2BEaX+SFK_U>Y2H @ž649?c@xdp!3\ntS!O 0~"_1"ɖN1EýĸT0'u/}O( L6Gv"|!/6_u@2QfO>8=d\'&p ֛ s?f ! ׼OpTdzqlzMt1p֔#-NC;[ǵ!=^^g|oKe} endstream endobj 225 0 obj <> stream xڕW6z+S`H` dREjw?69?aW\_01"G\[pc)MϏߐ8b8+p/XpmpvgW>F]JST,g,z⻌HJ+c?c2S,it9XZi5@A8Wၪbi_%dd4kڰO+O[k ɾ DE0:E ot(]RR X0 =M:9su=pL\YWNkm7AEBhmmI=5Ҕ]OqG)v,ŜJ8Muފ]QiS碿jd+Z <Ђ|CʥjW1E9hnTP~`n)S 2+D`57ndL1p墘ۘj}T&J@je^JI\T"vJxf(nN1T9I^\UuGW Y٥tdpmRwHʋWW5b_xgO8>{71fsj쳣i*o.40k9\oD kp9W\[QKz9A&_W((r{gOfj ~VP!6j׵/볓u0LhVN:O޽c:bCwS7<6E'9C&F[ltwS%ݤRGWOxU>:ZhSt%'٨ʒ5hᜐzo's]: 1> stream xV6p.H]BW7u-ޤlB8D79!8UYXm_6t G:QG. >%Xhl4fywd DB9s%'OYI+:`*n7=&>_zS`QK}mfR^ء6ǬxM:߹fݞT|O0p:3k`z)d/E&1I!1b|\Է'Dj{Sv]ďezb\ ^r+"[ VE{"Q@/Uywvj[7m0;U?MV endstream endobj 231 0 obj <> stream xڵU0 ~nAmn|Sҏ8C:L(~t~E?uoB~mk wC ǐ>8q~)8FX*NbLQz/HzUgL%jQXJ:z7&2kKLd,Z6&zrĐ5Tb)7 `/zVAs51vd( F_h8V;[yR-I5zNF[ +ka+n0_ >Jnˀxy$ɿ=R&RpRQ_oJDA^h}k?^A:P0j\s&%h˼SOٮܞ2ǚ<'ekهw;5f_ZsM2>?dg endstream endobj 234 0 obj <> stream xW͎0 )xXI H9TVܪ@`Q(@g SAbIoix?ދ7[r>Z[qpz@c!x֙W3ܾ߿X*憄FtQV7qqbz^A^iiLG,m@Խlv!ܐͶ(mj Q:@vk΋EOR` 4z4%5%:Blf-zQ}K},A+jE֋.8aLdGi|&` !_\^blGTerE(]y$ EƛGwvJbh"h>h#Ǔp F&jYңs@\Nw 12fX;]lLi9IID ܐtcbP{ðO z 8'eR 2$L˻gEDK2zL#tG1c3'U͒[TBt0 x y`B|WdgT$h+g6N\S3="w3 pT %'o!Ѐn a\}`^ e <"a'A:4':ix0 (),ha/c ~ Uhο U.STyƻ]mVMgw6KBN.i?(H6-Y@u7jT'#ڊ>eWP[5zLY#g^Tgj1T}A!\MZk9mv YC ]kh])T< Y0}Kbnv3~d/ԕ,3ՊYugɣ(}،f-R짆٧?|}_IfM_9EY UDoDS endstream endobj 237 0 obj <> stream xWˎ: ߯$`E@w+v쮺oJR,'N⹝ŠHC@4^L??| ME>4.|x+ JT4Ă0 s1|jpʠsFIie&)NO` c.#E1O}){Q7]oh@ ]ㄻZ_2OfF#fcTZUӂE2( `3Ę2/^U8 )YO8.y}cK$bqn(7Wb$A6%*ԯCifހ ծvx3,yXWEbz\xEX(4g4PjQT_0F7фPqh ϡKPCdL/uIh"0o(ZQAքCKNQ٥v1̩>scNK2^مQ dAHWZ31PIeS .cH5A,sydζ$2BV"iGnQ"_'uOUK.xnb>  Kmq;bmOOq7ӱ^uGOOߑʺߵ]&5VK9ɑ%TZ򓳊}KMEW\-tvxXABUBE+To$+bQ"?sb}\{_XUa)n^]2i+\Ӱ0c *R+V?LPz*bSvZ'*r9lR_ b7s!TmcN?PK{=I"WUћNINۃdDE&k7֦y5|]E.'[Sthe#8nH-گD"ga] )pˏн:cayMe_[_ ݕyav"?P$ endstream endobj 240 0 obj <> stream xWn8 +%-0nЅ]b3$Eɲc'đ%yD1Ϳ 6@?DCL=?dzukc{ۺŶ#=sI7zӱ:R ֫qzo~ѷ8w4$&zG^rp#oC6oDU9ީl`U} ]9I65 6feߊCFu7GV9dgBcdcwċr<^݉*$5㒑۩.+Krƪ#'(ƶVFJG݁D5d`Ƹzӗ!$R1/SGP@۟;0C !áaP·jii̚枤1*af2n$#ŅX@y:rWө~ҐL{EC뭻8v`~ b=9 a9zxᩓ&l-v9lj7g݁WR/)yݡT"q(0ܠ,:}*n&fGV:tHםH8u![$3BĚ֓:L /YG^+sX+NYONj^ƴ&.5?*3< _:G>'54¢V@mYC*> stream xڵY;6+- 0H` lIWo2O%{o[8$8? Lw~[y~vc]rwϹ{chff&.>Z;]n`n>K-n!Ued7Y<^ 1=O;>]rYЀ'{㱝.nW%- 4ý Ƙ)R2ʗZFz*#8՜ ^U(pmYOi+ ,k]l[S1B,*L["{Ɔm]qR MFѡE91['Q slvlݥ'I,n}@Y!HbQ>P=Ç CtpT VBum[cZjar$l]@{Lv*m#/~qe@0gd|6PU&Q6̠uQü]Xr<_ ŴPY4F]O'uR3\bC@Gݦ>jZ_:' l}%N!Z9ZHxQ%C? Lq;:0h\[o B!A<7 a6 ZYWZ@YLq +W Da$Zsb)sh-[<(2{aDj%kOͽ.g^J] sg-+b6+"M H ZЌkV :AW+{~r쒽V3Pa#/'}Hуt^kdI ld s҃BSC}M\&Gօul^pa-, z XZwL`>}ͳc"G|@cJ3{*B`>oި:kvoYmL+.DQL79;z=P|_)Vǯ;d{kPkbOgGJZh9Umƒ\QQ]7 :K_Bl˞!ӪսT+"Ƙٯ/Abj6bp!R[70ϾՋIUu氾8<ᠾhjFg'Toxt.iuZ]2Qo6 bև_ϟh endstream endobj 246 0 obj <> stream xڥY6- hL`k :9'&bzwmRbc],ut3v[ο~_rv3Lw~ϐs1o/'^}G7^6=GG#1!H7SU^9u`Io._kf_~qfi<IJ>_[eUxm]ȓyѕmIpHxwQ=L& vcpxery}{(>;Q&]v&>F͍@V$#Ȝ嚘Av,m(_>{Lv$0Tv,0N$bvQa_~4'5(,%~o7E$PU>xfJұl`p,LǗ,M#Ta׫(  ~*9= {$q8Y@{eBH@[Q(p#x" Y9(CQs%GH*QJ@qxnPzغ m174#5ޮB ԰9F^Y-Q-šQwkI7\]BCkZl~h(Cz.S RD=VPZ%"cuƘb b)/ 9*JE4UЃ>GS$\IVU>jƈ|[X[pb2M\ O5F!@k2A05nk^e%.e&YtεehQW,DX&P6 i-lt+62:4f1LcXLPQبs pz}p' HsAZ Bq?e/PduWGyW 1}@jXxl:?p9K/2*uy cM@eyHCPY~O(8{zꨬbWV:q.afh޶O3Gj'ia3X{K+\1)o3!x b*9ܸgmݹ[4\fo+$Gb;U =^: M/6`{9 2eCN7zK ѷP.Y`r]YV1l;ig+5ڇf;Ԃ7t-a7tst蝿6~ p.yXyy^*lkwœc7pb>|?|x@Qr+H;o2uUIʨ}?)fr Uk5jSսڝY4>8T^o(~Ax^o\73W> stream xڥX6(R`g&3IQIݻƌ@5Y_,q kh|+/Ͽfh>צwms\s92>?8Vn- %1[Fpk1-DG"&|[tkµǬ#==O!'NVW:4,EQF|}hnz;:@`ęH:Sh\@NuS(bԂ,#lc;IWXOor1(װ'Fм H_)eExfZ[x(0yxSf,Й$709,#Ȫt(2R&avv,-+r=۲o ppcR8l\9^hn2QP!towt#p\wjb|;Ίsؤ{Uԩ/n`Xh!]p⾷6F+cD߫8G-ǥv[4.2+tPe:#i+4K~҄gP7-I$`P0:a/ծ׽C@o*кX9ѳ[[ >=芈qꨔr"Eb@(TC(&- Q%;@)^ ݅_ ΝŞ]0 N(ep5\zMyủGU73{ ]bg}'*up"i4Ax0>vU%ǯH<]sݽ _;^w1N3Rq<5KE0jooi5 y*!XK("Jd,f# וDN+ &V4;~ 6H@+2p4pґip$%iR#D,+P`w6FNX N'#%~ʤS<{`r6,e"5pXݑ/6%X>bOQ/b*oPr|3݊Q}g5ymtućB6݈4eSPbwtn2|ܼbS@,ҊUQg|伯˥QbNmE_WI/-Sn:,gsieM})r*!a;\Ut#ܶ}a+xJ)c]B7"bVh$r*/|+HO򤭯>I7EXߪ7,U* FW[G,{g-r֫s}ꌦCw7/^t&:ӟ^NNB endstream endobj 252 0 obj <> stream xڥV0 $4d(V [!NKI+DR!1h?h"W_Y~-㧛;Ǡl`{,)]޾Ϸmd)-~tz ㉛<Ȝ}ƒe,~t4 y1Z4C4:9442 Mmv`3,\UDƲչM4h1PT`5 +sT9r\vS0> stream xe!{b_psؙ ,|@Y 1L>(R^uFTY[:v?D8$-䑥xՇ8$Cـ+W8O])Vs^*RƖ&%Bu^ /<~y(@P endstream endobj 258 0 obj <> stream xڕX6z^:H` R7]^/vf8t_: {g3ua1N҅:C}|aC "~I9Ozw)Sez '2|&|nU@ =p5FB7H(+fC1S4Bf:t/c0ȽKhi00sO&_bN !w8s\đp4ԭR=}qH:oAV1 ]$5$^,!c`Q)Z&b *: n$u@a§+K FfI2hu K(˞Z!gVYPKaQ&)!b(Dd(o>v+%pf+aDM{/eħ{uR*KEEM 8͟;^:lǃ`fgK.̩lr^q C@ *ױcŊj|I PFg Ɉ6׽hHÈIXjT92I+$͚Y=5+Qֆy>dor@%S!y|s AbgsQU4]" Ną+ W|9Pw!̜UޠoҞߓ.J THR;{`AvXBOb52Uz Or$T:3[0)ZXN3#yRN)rzWthXbS4sʿ K;g?3htcn}H<)M057as6$w4\'xR'WU"kZo(D===J•Ǭal,-̢6(x֢/#<`ӗx>*)AobŦ@,@po=],R &riX^! 4YlTKV‡gV&]j̲@Yg^̈́V1Z}y ռ i=s:2MYoaC4kn Qٮ9A.u7e*1(eCJ,luW.JSoF6Sp֪d[Uǻ/{r1_ ZX?rU2,FI76|!< C>chj4R{.FiXhҫß>UK]~ڃ%gѺFF_XoUV>گSnKz+0|y|;]wq]Zmٺ^?Q_WVoW3*LT5ߍlLXmv>qMס a|iS(_/7qdQL¦"> stream xڽXˮ4}-N@$vHgX$MÊanMR#αsxq.]]_??|]][H]wxwq߿~Ad]r=p[y1y ɑ#p h8Vw8&l@#6 < J~?tm!*o* ;?~G"O rmHZ3Jp1wIǀ#*Z{؄V兄M@+R|FM2h7:I9`.]>,Qd {TMwQ-y /,HxV$pѽ|B9bT TaC `W? ΜDL!KX8$,nC f1 j¦ʅdf5 $J<Tx 'Ԉ(L,67eTx5nڒ)%<r6!Fr5o{t6^Bmd˦A;?F<мljRmk*I+m"՟''?JBV>DhTW)|;Xb+ ,d Xp })UgK_W .x$X^kxW3|h٠]Ӣr})" 1,E{lZ0|&{ˡL0Wyil Y޴Y nꝍQ%ZoXV쎶AHcAp. `J\ P_@uUVХn T^췬="eD؆{3po]/7R}2 lr$_1eg50VI7\ҭ4>akA / \̸Vmulk#ǰԵZz A`a X?ѡeQi\0@0eM n2lwH I~sD[ DZNplo0]>l#5]KK.<Pt)Ǽ]_aĩ7of,^SU[~}q5lLaLYY1Bn,:4|TF墷U'тS4p"B$R!>_yXQAwDп\&ʁL -8O9_sMG عTvOl&i ȫv16S84DJӛMW9<5J̟#m@Z?Rޞ>fD`3_j=G+^Ni8h eOm"7lֶ5dW-VS4";$]J9}n1hy|Ц~ endstream endobj 264 0 obj <> stream xڝX6 %-`p.Ha{R)ϻvk$")>no ?l:G_q|Lл|. ?=M>zp_x|1|롥%9}q' fMl 3o߱!Ru$o1<]4N"ӌs޺ n[i"+:;CcybW )ڪdP *O jW-7agPi[\  8ó.ٹ=ƎX~X9E1iٺ<ĞBoN0A:/3g\ Y7ְW4ߛΨ;d'51FD/%PW lY~6+Z涯MKgucq"[8#7 آ*]4z*|a:}.|lTV3XDQ"IJS-OXf'qS~"nLy mPZs^2c']J*$+>Gd]..p.j0Cq2ƞ`ʋwga ! {}-d}kUE]t}]πu'm!kXc€e!zY$s.ín=pɁZ=QIـ6g@l=H7}YgJO18󙆭-Fɜegʜg.D 'vlE m^|ΦĞ5.Q6gW(]WN.AwPb1Oo/r0 ֙r|::U_pӗ~a/80E#]nن˔%lߔJUY͑]/K땢1)J}nA5V t'[ z=$RDI3sTpLaЄU*F뮰UQav|YnM6\D^;O;P2Z6'Uվh,՟&WwHړĿ(fFL j"J w1ۗ{şe8+U9T J~әp0oܮi_W9}.nXU8tCϱWoBH[OE1jMT=ym-TŇmOr%p%@(rFR7m.yoʓ AC/0jJGD"QjbN h럀IS<2$6X endstream endobj 267 0 obj <> stream xe 1E{b~ q&BPNH'wx"rr$$!Et`;!LۣP+1$RVtJY|d>ie*,Ղ {e Fz­L#v7 Z*mgO>l^7o endstream endobj 270 0 obj <> stream xڥX6 GjS .&H6$WǢH<\ +?GP_{U}+u]5WX;_W7 kpAK㙞`~F oe\a9zĀԅ'@_FKCf;VM ݓ6 i[ w5ʗVW9YD$.V/ '=E]eP\1ڋ^Iш I' ]c$MZvW_i !ٳ~ da6Mm̫Hmy]=K>lijŒ&7 ٢<nU[*]`JZ3kQu6bcfѿVO%9Χ_j1_Z:1ewk\4ZPu@A~g-fZP-Ί4]2%c8d:"P\e6Ɍ.KT.cs*U6B-@5Q̲1Sq53@#m2ƽF|? D]=kNX)Qo3Mmn@7fO$WIKNsCs\Cpϓy2K ]PP 5"rT> stream xe 1E{b~ q&T҉XY7 e  1J( <= e)!S:_w̒@+zdf1iei,"Fex EEp{}feF )> stream xX:+|-.p .H!KV&([: vfᙙCvl787 Z}|-}Ȯt/>u|r?8|9`_zr& !2yqNSy}Ϣ{>f'. Ejw76t Iϴ[ޔ6JIW LKA.FfL G2>f5tr30a{`"eزga ƈ -&["O%&5n2o*gw >v!ň[c#h*r6+?Mνl=͘DzcU qs!Kt8F'Jȝ"a8y*_*"gaH!&znҼBXIRCIX@uY{l^ce|ǞA*>dFnoqzIgAO(68NYUg;D^J3bLnHip w JU76Zߕ):{X;${c1]kt endstream endobj 279 0 obj <> stream xڵYW)˧HItv3Uy"mvpq6!Yg֬u;)`Ou__~]t]c쾖߯J}%lM :)YF#^o5p0v ^Yf bMpQ߆{dO_D{3tL %~#VF`[ xhLC ܣ v1e d yJ"*%bPcMh9 }DM]V_M90x60a&!Ӱpj 灌C(0V9 P=#% hp%0b`EqpsL HI =$9f*V[= Cd7{k?!$ΕJrLy|ոמS0}dV3J#VM,JmÐGȍ&T"' Ebr\/ɒyf"jzU%a׽̒X@#H҄ q|߳\zWFXVXc觚8ok>;f <;{$AĽGv] =iQχP=KibIh43hSmwvfO\A{F<= 6Z8 Ub,$h?1 {DqX+HZPmR!E)a 2O%J'i;яDnQ>(Bu+?p:(:'zQ!Mڠ fG*p_3-|>XmO)HzwPQHt&E|CHWΧ#i愖pֺD c1o9ה@4 :wOZP"^;A5#e|P !gU&暸w/z93sCm n`*ֆxtLs h̪VbD֯~'3ϻ{Jj/揄0 98 w.?TcG\Tߟ/.o$׻ s_QZ1ϐo MdBhǵ7[%ws. X:,ܱyX 頞3\$uUmִTZٮ:qfجZzև^m$hcZon-2m3潞~K1ؿ9|ֱs:Zi?<&6D寸L V@#q_5d^Ik0ֈo5JCiL@V t͌&Yڨ|G'f-WT޽00,#6s:X @`( y)0vщ33#lE*ɴl1y.&.֙,gnp9d~?Py endstream endobj 282 0 obj <> stream xڵWɎ8 WVK@ t50rҧ9_HIN9NR"s}| f,~`8~8|pɣO6`]ƻ13,` L x\??!h+]ODubfy K$aߊCzW?@Py`R*!" 3`'La~f>S3'k fo'L zxu o5݇@g< ړ$M+Ve<"9ihʐT&lhc0m.0Ry*!l+Tl%E.2\=ITdUrZB+8I,k&IP07^ tU2gܳ؅1f?4P1[E & ,6+ȃn)m%$,M"*܊bj瑋vBr+%ph?(q,KdeR I37M&Uǵk:;VcwQqqqW\KK66*Q|Nfù^3$%8ץi*eƌ9Y"8@rHTZ6+W>svgc7=UuzkEx[s*\ bt{$6F+豥\_oH|y=k.E*N@\4 i ؤ4)"~)؄aTnrsy)EzkEżf),|ڟja˝Ρ)1TٍsNuQ,ZG^H.;KD:Ls$CR,.;x`E\=Nzn-H̥źH.:7f@t[9oO6$Esyi>~ō+`%jaMҹl^ڱT]E7śP6;x4<_<ȅwc@0e@+ vaF'hIDxr4s#C vvm6>oH(ۍް )_^A@9՚NfK.}i^])Y#jhFW phoۗ% endstream endobj 285 0 obj <> stream xڭX6~UxK[H ]BW)M␔i{v 3p˿{1g/sY__>/?f/}d1M7oi|ncgX?8V $ݯo>Z`h<+,é|]$X\' jD27!>C:!Iph@k0[:[F`LWANW6<2/ \Eqy`?]d>ox1QeB3B{g ban0i|g%|GlFRoJ4VP^aE)s?C)R1JEJI4]Tvs v"te^xF9\AQ%א5 F`0G ˆ{_Ʋjɓ'N+a"i>Y.h:OVxc: -2'^ h4Vn|$)\'zT>Jfi,1Ss$h.l&2$RyNxK#OhU2dYv•_w^ڦRRjA{KXO/aNr+pԶ t%Ɨ?ߘ[F~00|1s߭{g^{~X^r[RMN&=#.՞Jy;s'e/gJCƾm1=K)5ij|75֩__κrsDw~]9yv?GzŴC,ه}cTPmRf\Kޭ(Q"!ӶY$DSmi>F˵d* Vh#3HK/J)9l?M<ޛ9UVts@y"ZaY (6D,< fk3,w5h=2~9./ֲ/p5ou+Y2<4UFF-bUPQ[46/p X4tXc 0OQ_QWU"~LQsR;CE>|A }头RpN1arbՋ|d+'DΟ;bX>Mҹ2VL~<ƪEi{gM<%1>B u{ ^ĀTρe\ qP?-#҈=M9/+[S <vhɭIAj`@͔6H'I">eRrhCrFڴR`W{qtCv-͉e#PWLqK> a@i*Pn%o\uTT>!qg:._mx@$NWyoɏ. U:6Zf endstream endobj 288 0 obj <> stream xڍV0kg(^-d .Hab&9(Z+o0ɹπ?0,֯20ޓҥ <>4p8L+|\m٦r0NL4)_hͯPO7Z G63LJ+ֳ釤6ᄞ0G ®f*&օVPXoۉi9ZK2C ,gE~:./c0-F01}cv4&H\tooU=CV= MvH]i.VE|sdQXoC# z[LbYfWC&)IT{͊&x{ožL Q #ϒl}L~P]a{慫h]L>bMEµw \YA"*g=)޵Hw*5Vdj{_M:rHC>$#ɺݧMx4ПZkzgn\CZc=A_ Ǥ?|`LVб\8o^j'c#rZyFAFB)uʡN-mC uI1q$󮽡_>jūJQZUM\a{+͠D[nE-d Lg(2Ɓǔ> hgp]he9|JQdY`N1^Ѫ\{,vع endstream endobj 291 0 obj <> stream xe 0>ž@n&) 6<gC,$Yzc4;禇DPoɋ >RHi ҃0, I(%;hظN4 cgX.0gC`ٲvXjr7kXjjF͟4<~M3 endstream endobj 294 0 obj <> stream xڽX;6 +<} VlE';u_J-')P#Ň#Eeg0ӯ8z1|S&m>ĩ8ƻ8qz7'qї)ה Dњ+1ű*aD1*W4#[t3Peṓ(&oHW3 $ c-3Go#Fl#sƁ(T%R<;D|B 1l)|+8k '̛ucjThJ琺9XvVYϛF Cm*u,&ziO;m;k[EHplPQCo}ݽ=^h 5?UO`͚5ϰbkzڻHp{aOE-G(>K'pQO2AIޣJ(x>AbOo]]_qdwI2!Tr׻v{NOj4{:ʂlvS̟Av'|tC5#ƃ?F)FZ#H5m>ջ#Zs]A:Y'> stream xڵX6 ~q8lq%@)챝*E޿ )R4쮝 X$%|NuT47_ Hv^fTc> @ 4| ]E<"10Z&Pg1f" Gġn ޑIpq^z8XA$u1^DE"NMKȿT#38L#ˁ_Z~*L?Z+J2݄3M72"u%i,ȇvJHk"&SYN1o'ݲc%{wڛW;فE‹gz3=BޕD,t7eіU0%""v8+=x{ޗ-#9Lz\?k)] B*"Lb+8yV`đ4jp:6FoZLNolZ[4$E$rU~0 cfYp8pYy;Yef)͊|XLIvHqN9^|T&mjg%D">bNni_ėؚ W݈"3mWs…? CB[=Ÿg]2^?.nܘcieă`2X) %a21*>#nD mW1^OR8Q=>Urp&(ޅOL[MS֝*md1\H@-cdp m_F?Qr\;=!F%[h8;C7x}AÆ a" nIZ) ] u_Oie >B+2U%e5>Ȫ ɨ/h0f]nij꾂' U.j.$S73t}Øń ̴l'ة eL5:g%`+ %b4%Y~RQ ~ EUUȈ wV\`;/{r=tu [ w-cdEv`XMF܋;7Q5 esqI !jI41ۺWV5GMZ(Bkw{3h^7ekAGr ʎ?8{?\- w5߹Q9ʅEJ}v[hz/TJ$L{z=tT" Eb`xY!oס,5[^f+N n_&q;q|,/`/z# endstream endobj 300 0 obj <> stream xڵX6 [  ܭgIVF{[I44SM7~դZ$Lk}hnF16_wpt?~k~ɨdYmԶyzDpX8Pp<ˆsg ]ӹHkDLEQ$ ep ̄iyħ1TTW}ԓ+43,o˞dqjlKhnʢ=uYӘ|Aϊ5As"2[֑'Zw OpNOZ=+F'yy~zPs4kc}mLw įY7_VH'`OEѱ[)D N_/r -QP `9)SҎQaҐġ83K F_p_x> ؅=püqq}gpzNʎΤV'mPl}(榦zkF_|㎵J/FTfX wL0ҹ 䎥;"$Hh||ZGu:+ vbgc(% 9W 㦢b hE~PO3CIB;BX;[hSA9.r\ #R^Kv c`Q @}Uެ% JĹ /ή -`-Pt:Pd;T0Ti)cBhuf<ӂ8_XWڎW((`Q %!w*Ip\EnP6FQrrNׂWBoYT|ʵ.qqżk'Ro*r9wTYc [pn6³בLR]JuImL႓*ƣ4s2k{ܣ=_@3ruB40q>g/o{UV?՟g+1Eg(Rɝ`d|wVۚrL ?ͬ/Oֻ^,}Vp+;9j9~b*^סklE Pq*>6SVh~ ^&0kVڿysAljkƒrEgA kfX\ z?Jl>`J\-F)\Ѯf\w7T?|zQ0JEJXcbv7 endstream endobj 303 0 obj <> stream xڽX6 ~R2d(V [NK)ı!ERGNtsƷ_U~u?"nww_Jw ݯ~CaS ( IN,wA62"Z<6qr섲(%)Mb[D(€mLcEh}N6G,ɞe+3Ϸc%Bۅa1l!-ߧvB~7AyHPBb8"4z)8k2vbtpS G_ eJR>2V1&eNcd dғ6 LNbr;" !Q{`vR~Pô{?s+Z|9kH\q-2jwwKIFq+n;|gߌioiM2âu*x] å*i:"T8T!Jq:Q|TLtD5TU) {\jX8&BU+vN^FkjUE trzs+ިB.T)2RPCa+=I2je>:@JE*&$^L0xZk$.y=~*Ī*˴Xmh,tƧBsW|Sq0ÿê endstream endobj 306 0 obj <> stream xڭYˮ6 +m Ȣ@@wqoJ!KNcKC zPO?5,ӯpU?߾!`]ctkt1$7\#N[9hr EK+np\/JeԢpOpEfxVp8_f;<<<'֐HN2A#;C[FyF;o|.FY&OiG}ZL?kń)Lqj־aL#\~h3lrysX2Em*-nQHPch1чuʏ5gKUuMeMd}T:Ԏʿ`5O!0o(HM,xf,lWJ1](цNW2IoI+[E#>sb,]i<1g%f-Q7Ā{GjqbPF(QҺCs;`2coa`^w$Pm Tw0j+ΔjCXn(Ԫ3}`EU퓡ר[@O9@vf$P}:2]j-dKNu1}CԱcYABPN ;p`Rp!\nr(淶U;4pB UEԦUkmUڒ Cs^m ~ i/X~Tu8 iZ8yMMVvR?$+WvvEAĊq=v`V0NٝBgjNG4qLjO<ΰ^9W|^,Tɼ]{:_ ŝϙ oS+L>}s bu)hW+ڠ^SOeWkS%.Q7:VZ*7{@0Jš)k%M;b^GsqfBL1A |1i4M'(wڎc"b(N> stream xVF k  HE YҤJorH#[` %$ϐ!A zjƯ!mW=9(C.V) U)=APrzz}(], 2v^$];Cz!v\7-s)b k(Juɐ"-T2@t\x5J Y~u ,M v c X1upus5zhʃ`{KzY٥/ -v[1hz@|Ӂ7 pj]v k7G0()Sꏚ6> z95blҘnկo5N^$A;JipfJ;Kl$tΨ*(ՅW=U/ Y:mІ_EVj*lT(ek+oɃATGZa ]یb&\|ң;oM L@>}6LB1[ FdUF{˔z >&@ yx;C+j(v@?N|r ԙ֨"+qFp$,V@ѥjk#pxr}0;J,bbQVN@& F7N֥I9 ؒdZJWIJiUvMf-/ʖ٪T/T𢕹r=Y4&(v$`ոZ?4ъج_=u,H OGe)/Zo򖋚ڱ}QK˭wV++J·L{?6NS~xhw1*I Ņ1yBy=Y14}1s[#/ԏ5CJ c|O-[U-> stream xX6 ~P7 z t+8v}$EJc?Rcؑxs? C7~篷Ϗй|c\͡..k 03~ \'|/1_GiF&(Lz&A߾F7t>_KPWOD#{e|xw}PZdgPW]} %sՂ|V|&g`%H,*ɋKQWUCP/#"m(^ԓ.s%VDȚˆ]J{YSN:SdF64~W%8^MbjsS7qO/T>X]; i3[.T1G!1JO1 ‰y IMP+UqyK g;0[%1/+uqٸd4Ux߱K!C?jxI#r>0+;٠d|lGl ReW~4XN A_\TO/)b5=NL;%` ~$,_n0ř)*&6E{ 0*42X*w8-խXZ"WB:.a=D@:TBPhyIc~[ ֪mSdwsxz[N2vhbg9u,57ը!{ !S;#P!c.Dj"%VLBZ+WnjP(+1o:F.&sD3!§DXZJ?aBw>ojCעLQ)R] hb:L/*WFķZWhDTEwZsatruMdRN=T᛽k J3SZ ;YkLIjx#Bf0# "cC7u+_Z^0]w7 8T x*d uJ+ ބ8{&Pj_k , >eֱOr$*@RУL=TIosP}RTM=Č룜i=yjI}l1gDHWnonHS.PGR4:t9~p!i ڸQ}U&VnOEojC.i}6ܴƛiT 4o%iG!o%6)һ~]4 j`tHɮGu\>Jq2{]z5&Hl̳ɞն+hi ~LG0fyyHWtvwx  ? ,m endstream endobj 315 0 obj <> stream xڥXˎ6 +q \̢@[+oJQ$E;Nh1c8ER}q?w)r ~绾SH]JkpS oH qέ -skkHIkhH l7֒|mZk\/ @W|Uc㯰z|pd iő )gހh9A#>\]D?dQjSCą'dMNh}Ƿcs'>LDGsʬά R`asL8n_ϤG1 a3tB(&'6b\+NABƭ|>%7|*Dhw GNh.n]/JU3oTJ读(ƯwkG2gVZTK'|ݪf }g=ꎼu$̳6 s<#5$Z!j1^f\a8.qЋ9<izЦٛH+iXEfBqRX+GG=FÒNXiݎ̲dK!Sf;LQ3k<ǔ Dˎ 4c;;:zeZW#>W|Gӆ>ȵ0]mlrmm=>#;EM:vY&cJd)K:ski֭;kvR8(`qv, #{vQ-V{7侄1/F ^6ۺg- C_u[Kg7唱0mpR_D?RB}SsdK(#h˂:q-&w! *4 /~ol)ii*;RHUѶRs?RH)rјyqa ;blR4%+znYc2Ħs,'V6$[(2*7r_.4`Ze?$(WpZFLk(\*֣(fWAsJdP$^%d[ SAg_#kXlC%|.3q@Ly!{%%E_2G\45w^ *cLp\B@Gs|څHqˢ"7q ߰aIJF VX骳+ٯ-5oLe)mvxi՞~ ݺBK. pqaJ%U)i^Zqmnt4xwlΓؼaEKwn1F aizS*:<_o PQẙ"k}\rt:z Nx?sɁ=qG=|Vվ<M7sAP}WPX}>SMU}Cav$Ma*7jn*]E(#uԉ)ȳ+ZN)GQ'Di݀7Jx )aS9;(G4| endstream endobj 318 0 obj <> stream xXˮ6 +I Yh tW.UMIdMgEq`Y7s3d._+/_¥yD[̭.wq8Bc o4,]pL lR],[tAxc1<W’9[w\#((@:KsJ8 O#3=k2ɓuOWopkڭFgYFt^"e E8;>ãyxo-sSH2<rx؉NQdk޽ ֖+ pMe4ֲam!H,l,S9ovq( Kf}"ҝԄV=}sKJoj VFW'>4>^gVug64vQ|ģk5QXr {\IՓZsCz+Z+-q P+| OҜ=Fh Ǧ(X^*0TwɱɑJz)/.δN)*EZ?{=TIf7 m`|'[r=S4(ߨHL 8"혻-x 3Qg;/y*T*7Q",:x35,s(;LKzV*VAY xX|Vϧ. A0nG;!r䧮F;.s0YS#sUg7+\ 7k\ gVrg%3غ$v9e6ԸS5WIkxsD4 h{#VEPendEL՝("%swL )g:AЉąlb7TfܞqE7T(e u/M>{,Ʃ)*&D uT-iuQĘKIrDL_ONr"<)pĆ铅HO"`(k02q?t9{z e90֏Zb,19 + <&v(?19<79O>O?׮Nz&ퟛo՜vpV!R{9,~KReL5WO7wT;]KKK_ݭH[?RjHv QME␮VٙeujJv:dHju]=~Yo8d`񂻊k<Ci(}QD}mOl|Z.V=8W.YԠҾp/ m},Q;Ƣ)2 endstream endobj 321 0 obj <> stream xYɎ4xi4$@47!KBvekBhJb\7so%Ϳӏ0~no#% Zoݣk9?(~>=\AD矓kkc=fvZǴȳvH_Pz .f P{'I񑼿}mtB=P:]YzAP| #֐|@f"BdT#qz\%z0&ρ^ x'X4pnwV-6pݍh>Йn{t#e1I`ճ#nT\BzK\@*^'υewڑL'ú5wFlR^apω+M0桵KhV]7HdzM*'o\"D64]PR-+7cUqW5U.׹?&C޾.W.+1?,>,t}Xo <-h4ԭΦ]8֊Y~/wҐw[W17vA[ endstream endobj 324 0 obj <> stream x,50+fm4 Ȑ6C} u]ehr\w`?0h?aH`}iy{/ex_{cq~en}3֜o7-` c 0=J+ '|eͰ-GWp[Ǻx%c+ ed17V6fctH3%,cD , p50Keb;wBoK[:Q:ԣ_ɖU98a$6ɕ_; QdEMmrSOE{¯x*_'/[XSk/^@Ȫ Ȝ#Cy|Q^m9PLp}QQFN+q^(b:VE:#۵~g%tMВ_6N\UZ4i%*QrˎRwvyŤ{J\QrGJ>+Va^`vf<5MX] 0R E|c}m_eGc." 77y6Cga4p-ęb 6=tX3Wq#,P3ۊ"R+16sВ0fOKGN3艝_azɜqm ],pHhV& -7VWLf1{@c!:k$jLӰ[6Jr^GKHCRKlA=Yի І!d},O"u b2\^E- Sf륫ʱTdžC8]u*($UCX"loJM磊˜Z8zLg^(PBLA"i_*N> stream xX6 q(ɲd"@ ]{|&nn2EGxuK[}?n^nt}sw Ϲ{~܂mzF硇]R/]0 %A(+ɖ1s'pe ̽ 2a;= ە%"AO?Ɉ>N):[B '0TVq\pDX@P?9Ul@B\yg$aolB7bgy:>$'2C] 1؝Yc&p-C-T,Y,i xE'4-~ӳ*_`=x.>I -n53k+,g)hL H_;Oz]!׏eY?0.'b!7=D5kP+,Jb/"gt9ٯ=n5l'd| ᓣE& /o&0 V*ć×;c ձ+^y |`ȉIplN<0d|fu>'6kNQSMu'*1OD o[A67i"w}A,s$-nQqTԻ)~PZ:XSڐ߭#a(NuGh.7l/J}'N4j~[7\`֛ *tjO#jILmH龺E㋈d. *h> t{FWN1H#jݤ񺬤y7a:=-5ʾMui OC*B9Bώhmfj !`cOJT6our}޺_ %? endstream endobj 330 0 obj <> stream xWɎ6+-s'4` 9h!s!Im3A lb|EzPO5_`~F^Ɇbp~* q]WsR0p<({Xܹ́~SjcEkEጃܟl~=Mmv ֋,or v JŨ30vtZPe[Rv +ՖbWF Ty'YX`x6Hb&MKӖvO)4zIUvBAFF{o}m6c`{TEh#q(e+/Ţ[D w Cj=[|RMj^S G/\!ˋD+1ߩ-/,PSmt_gܾ;G_:tw7Ƀpfp6;siH`L:˫Z#`HcaG! ̉f87;1 A;DIpEEI)]U*E"͋έrjMUХ:,6[JZg).h*P_~0E\o ;p?pf$(8!RdߨqNWM7l02C t6mB .۷53kUzc=% RXSxkس[KCZS 0Ȫ]q%q&s +;4k $WUpB6kUty.(I ZЧ.qEVQ.tHitڎ`Gx?4L&.θ[=R"Im&kՄ\}nT7-X]\ʮ.;0J9Kwsi c29C[xP\7A\ۣHs> stream xW6y,3tq j ƆjbSWg;?n }Q/o@^d!msw_c'7Pˡ7"=cp]|h! vGt ➒d!?_C~0$'7r6$ `+<9ㄳ +hNj Zѧک{'kְ^4#C>ѲywYw{$']x&HZƔǽQrY<'T/vGa fb8ULYM +Hd:IR` ڼ5!ޢj 7"2ï)A9H{bo"Eh`ӞY֔'NAt 0DH$KmWpa.g:mx$ICP72m8o`" Գ=, lkb=\\#tJ!i-ϥd}x!ފ-[:=: K+ŒY rKpG| 9l:}tIe&7pq瀅"zamSjU懾ܨPqURƶ,K?y^B!_NW|e57XL ?X7Jx^@! z79^[/mү7nN_wP4g- 7Z쎭=2PJQWv%{VZ 5N$v]zvr+t;aa_f]{p tg {jK`ip2gkhs ΂$Z&s&LƤfj2&+SR: .l‚JsRУ+Ϝ)wJNHpӗ4?c+1'c߱2*&c%CA)NYh!%̯v}VXJsGlLs^h,˧@iTvSblVzrP?[WO@ՃsQKTb,&o5ROH1rB'g쟜Oޡ7` endstream endobj 336 0 obj <> stream xX4yNVF!7!B:B3ص\?:gGGcl&a16`X>3vVx6_?~qV9 ;X cAVd`э-G۽`:S8~0/<`,B#D\PUY@q*T}7~0063ΰWylv1FQ.r#.cy/qsmל"{j9 ]Ԯ>-ey3L= 1 5:Ҟ9% "5(1<_9$ȕ'I W4ۣ7yjW\ZBVJ!Xvh'rszdJ\/؝~YnXSguQ-# h$gn3g7sbʊ%uY&EHՔ Qi.u][K u8 47>wrc%Ӊli_0w!;.4}-+ŭ#M]cJQ1+q]c"KOa,I+Qhk熴j0 - u8*> stream x96)|q0xE$@ R3T)r&$EJK&}&R? av ׯϟ>CCm8Oiy;4|>cWX8*`hf Dpyx&X >?n>Z`eX65q qst ZƘp8BNm|s~ vNWGPc01;znq k57?;r V@(ܙpg)_ gp6٭3Ža58+7y *Ms֙.Lbl16FJ#X;|ywiAelD#=BO 4pǮu5c cv๸wvhشri`]VѴ=4aEmUddZ,Ww?;|~;i||#jte/y K`0Ta)+)gnGfh\"UtgmU N )3gfs &3u4[0t.%6QxcKWY 32BfMpɰRfЙcRn!|fl|覦Uz0aRDմ !JPJ,E/}m)eKq+đ@/%d,{kb3 Wf &.=rh ;$j5k!pwu`鳼+py( irZG@3ň9[/XR{sP9حR jXWKVq|_+̡F4/jdwWgQOKʲ.rRUbʏ/a[NSY]T HIJ s,?j#8oVu.FFg+jt3F;u*|i:TC@KǡܺPP H|PmY™4E n+5\Mp֞gG2׏pxw[dEl)k;-IWv{H')GxqFiiu2{jg<ƴn)"WMwx/%zfT+o2ӱ6LHJ <X@ePI&zsgVvf1ڽ8ťd<9Nʉ?p^ w5jM~+ ?}r+Pk9j`VBuqK[vs,.Mf6jmlÍ}\7\IrCV%2!/[2|7 _'ЬWCY݆HL4՜RRt&9).2Wto/?mQ7T̋G <:-)oӾM;? W` endstream endobj 342 0 obj <> stream xX#7)h ƇL o!6Ԧjfl5RWJguw3v?BcwBϹzx{-{܍ d/cZ}tHsJ-\KuGEc㬃f{^| KX¡D ue 5 *8c|Z2KьQjdD P}1j("CU0Ĝ+ՋͰ8ulV̡)-##Q/Y$$;6J`TLѹΨ(x.ڽu 83(M g,״٤Spbe/N$eGoHCzT}ı>UTiT=gTiMSv邀\ {4GWړBeG #8uz:8`:8Ry,Əpy܍ڛp!r4x"1Yh=(h/hc 02󰽸?X&y"Ujdmxhػ٦AAj38R<:$c8f4anH*;WYQ&A9[UMPtENCrhBA !b%ڐY7vUʞz7͎=2 KI@)Z\݌?bkllkv)%4*y)j ´!N)Q\DR'PYWĠm5۠(jHѡ{̜Udx/A:ԸxuV>ެƵ7c%EnTt [U$rrݽ3 D ~А#mtF=5#:f8}zXbTzf +!6ZʦZ|e@āϯc8:Ŋ[+b˽Y&4PT8VލZJ`Y%i&J69K(T5& ȽK[o~hjJs&Jy ceSx}YТ9g)EN9S _"Lvyrӷxlp|!v!wF]Q uM_VR9|b=}c yk\8HQ^0+̆r _^ )9r+]q)/yyv셨poeK*% rҩ; !;+jb^biXOq!Etoa| endstream endobj 345 0 obj <> stream xڭY6 q ,H` xJoBQDٲEkcQ!)ONzRh_Mp}_>2;D)94]S>}(W? bܬ"0B:\~Y'n~X3^9@{릌Jhk.#?Do$oXGHcZm[Z؉;[CR9&MőXžRMtK/R'^I4ggȍ.o֣$C?X] q 1:9kiWŝزOURG1l֊yZ NdŚJEF9@*ǩy )ji ̫;_]Bۯj@ag,M.G\AsS5dt vMq#řNqv^R8T `Ҭx⇦$N`x=tbrWHs"0=h)'3~H紨zӒh"HIj\]v{lR\uʠCTcg;o`̿ 1AGAG2٤d8 "]`y4wՍg3pml9s׽bv L9U5;PuOk[ü$EC-ð%oVPN`]I9Ao_3ђqyf&5A"He}kG+bH{uG.Z$h&> stream x}T0 u%-$.HqgJo2([w! ?7d?8}m[1F8. וEs,)\ɭccgn?:ؐyLA+5 |q9$Ê(ZʶO "'l3V_|iVN>ѹ"*`#~a[e N Ix5 {_/𭌘?EU<qF:w/04Z޽.+v,'Xlգٴnyy=Vt*C:lٰIb{Eӵ!D_v }5F}:{'# e+˹/;MB'jt&{ڐ̶rRsqSMR6倹Kӥe:U:|YL N/{1*ΥRI9Vƫp7V1Y&yukz40Tj+Z$H 8KO@#-MAYdTN)~t!!Ú\\-G,*:^AoI[uCfǟ$}O endstream endobj 351 0 obj <> stream xe 1 E~E~5v H ą3ZW.A%p$xBڡ;}s]h|J$^ ͨ\+fSC΢gŢٓRev!Hvʡ\~m> stream xڕX͎6 )$K`z+0g2驇$EJl5.~! =OK7lAbktĴ_@; މ|E iE\!(qc*;Ni$Xӕ4]Ss~bKg%R2ߘy$֍"$q=Zj/Z?(yGx4.J[_o'sbn sAPJչ ]5_G 6uK6ިT_*7wޢ1:*S&R9Qh-n~-W".c#>)T4wD1%[ ËzH§#ˀC ^b4Sl駌xe_w;ݠDvi'ĹD~)3JLt,2gy(&a4IꮮTG]IuHr(J w%0ek~ :P,jV,S6*@ !TtOs0[UKZ͆nƌ>@.Q/!Uo[#g6F)/\e'Ep;chk]v0hn1/č7HJ'=׶nR),W> stream xX96+&"nt)tX[o2$g(Ҥv Z\W/z֏r~]!9 EcBwVymC IʄxM{5zCk׋MKfN X-I֜d)[\/Cʦ}md*$Cte,荒_~l(43Yt4cq?}`vU!l=,‘Ô))U R(h^u3}FB'SpegU<|X<2T=NEiMXjJ˼S:Mj_dSeZ88> Wx.gMMj*:,l IuC1{4\EaEZUTtzO,\aZT8)MN93y~h'uIHThhVjzZ.-my3+zbUȻ vkR }0 hfXC!a̦5h%# |R!T.жVBAr %c=Tcoo5ʶ8K:T3qz*v8=MK}ҨzP Zއm&H3n|qͪ(ؤ8 }p[Q_LsP}- i|!EPK0@^kD6F;錛[= [mC,l8- }By|'eP?Es0⹲ m9E#2>Zs/Q48 ~)MmO=5 endstream endobj 360 0 obj <> stream xڝ6Wp`p ]wA ˒Jo2Ù!) v ?3<~oaF `y/] pz.ɸ-'>'\| r2 +XHFa3;I^ Hˣ>{bQr.xzt bYo~J[>3H?I̳k x. N/^٥d,y;*gX?l]KKf{|OJէFtŸqQkOz2~j׈+7; |N Y8oEnc ya Jnߐk$Ͻ| l7}d[F4oFNE AqY*BBN9NQ[,bEEv)]d+ItI'AdV=B(P*prkfr5F+(wܕpa$jlËxTJ3?1[1@AfWu,fEwV(x ^x> /{$NnDXQ)eeðXdztqyzfv1F 3]љn`y>^ g`L[TF(f[-N\acwskćל>O1;MzԋY|I|JqO|"CD/mr S]Zt?W.C^&<ٔT_2d[yv $!rwݝDLhfxs#eVn= \Ia+[kIRhĮV.l z޳ܭ\2R3O'b 8?j=nT[0;_N 7z.vg֭M"E$"Ag=)dg$-[+@UzjHO6sڎ1{cjf3լ <4Z8m6үhY 5v[x62Nn)>;.ǣ9n*h;о1/KfHtUNre72,{vvAhct.XF:ۆwbT:¼eӕF][qe"YNF#PͼzbP+b:!V/:+2{> stream xe 1{b_nKr W* "g.V afЃG(Z\}ʹ {r &Dz0ˤ/sc썕(;׋Vx@2vm"<!~G-؃Uj"`j)u->> stream xڽXɎ6+p)a-r_Rh[tA7!,VW=3J_7,ׯ0zy~ OT4ܶ)ɧx.Sn삏. )&q'o9ݳ#> WxN0ϹU3 `Y"ljfӹdzǝWR/b5zgk +hCIWy&옑s Ȼ.QZD"AНIcVF8o'uOད]e,!i:]y5+ %1yh ̝]N'/_~acYK!c{|Iqhj%цsmI~'fu`#u\w8πX9g.Z ~H-v L%$Iu5u7ɇiŷ*u>jXN F t^lN-Ŕ@GYG7H ٨{R%.%G ځem+fLd\Of]Hڔ r9I +8Iŋu'"ڳ:i>JΘ:Cs-KqőC )<֫QPxM{;`aվ̆& =WCo,i2˲Xg}GA 堓^PIh'?ءHad=nf|0U]۾MK[V:^ztGt_nWCo:qJIdh" + 3TxN?5.T:[Y Up;Ap CzT`NTU]l+_3r4#Xl"|!Ӵ|#}{"O~e(ϙ%RL2>P-hǾ6qR8t 4GM$BȆ$"$sA@a=$?L`cN(ܓ)&:$=EyIilR1u4vҴZGzu긆H͝th AE$eA\w-ܱ_x:ݭv`K[k[yezʕ2# 7#w& ZٙΑ, +KGBogoٿ9SSwȸs[%R ֒$ Q#%4E,rk8ņ.4Cg 13Th_ endstream endobj 369 0 obj <> stream xڽ6W, X\a6u W7!=wpr<|؇?/O1t!HS~=Hr50HTᎀ ~P}7x'Sr،3q63:^Y.+:Lpl:ƀ`gr g8sP ӯ(؂r5*XBo1 oñ$n E8[XJb~ɷv sr<37m>`$MeP,V]1L&bOL߻Z[<З :UC{ Qa\!^5 (PR3MeZqV1kultE)9 D%yTKr9 1`{l#w}F|rV\VtN)v {!EQT;VHWC&1&ی \aȹTvH\cV. eTqr C&PM )G__:HPo2jtn .6J$4.~&2ZHS]фuP}mm r ASMK((;9/*PN7Tz ?4> ]ܥe6~yXjU&(Н>JϨ5Upq0W:% wj\S(:FRH]vMCwG d !@,`i^H'0~\3fI_בX< ZSbevu]ճuw<3W W_rߑ%^d:x=;P:ҙ8ѝHoƟ\xۍ'Co83A2+5e糌#Asx4DQ'MHcܭ^yd%F"6%_ K endstream endobj 372 0 obj <> stream xڵV0'H-"%E.J,Jor{=W* +Ưt>~kmLgCUjڶ\^޾Uo۽{-%R mU{xdmrg jVSUQ KSlr=$,JaFkM:I&ýUfLYY}C,x9tTn$I]i0 0.ph1cycƀI}%0 M4b@Fj.aO):6Y[ 鞬Hpʆ$kw:cTV8Il8ibe@SV]ʓ;K$h'I)X$.[LRhN( kDthX ڕU |R@ J =OGd7C,۽g,CF@'oF91a~zn兣IoK8_Χ8!"LxpksylI~}3 g.C_4bܯǞ=I}ߥծ궹Y$5IGc0V֗ǯscO:ՙzHP8f*zSͧWͮGSBL:ڸI[P;IS֩p 0u4]B^Ҿa~Acv 󜙙@kj+ =TULt6na(IMTIK5Sf& Ft= V^}'=[mۥ} Yݝ6?t޸m璄9[a>&bu 1hkiς}q )o~sD?5VW #9SVxwz{%1?KuOv_ogc endstream endobj 375 0 obj <> stream xڽ6Wc)`1g0+/1(L8caɗэ??n9oMǦ/??3 }\Pқ9qk$`L0 " yߜ7X/00 1ΠNHF}Ya7ahvJy s@6DC5vb@ omrL_=j{W37sPH^ê5}iwi>AP@gƔXKK e{8Y繨RL?^ */&Ұ)XdkfҮ+ Л55-A)]Cs>Ѹ)av~0HJrT jRij" #fEP;ևdd%s>T#9yCBG@ǥJ2f^uk`߹R\ѐдlMɟ#g|q"QaO06$h5 &߂`(;F*'ClpN&+٠^Uj"'4&|ZvTSZ<>6<#*DWaIt{W̭u(QeTu oECb>fQ(?:էg?Oa"%E܇/`8wu6c:l~aKE*&6{94VD]JahM}l/vwk&,QȅT~N`?9X?O7N[jRǿxξw_^!< V/ | \ۛq'}hC쌮3 KU:UկѩJؽ1UqDqe~ci9n29!2kGSwtԕ,*ãa8l&]pU6R!7ZgN[D a3v8Fb3bs%qpy]>?~HUT endstream endobj 378 0 obj <> stream xڝX6 qD=-`E$@)~JoBQ${ً{kmR`a?c7h- =D3Zq])Xp >uS?F㇛77um?n^)|6Zq0枥ŧi-N,2áXym&y}Yi\~y|B949}c=/gc{^룷 f0ނ+ 3Xqnw,IZyӗ &Hò}-_|YV}3ٴv砹ؿiiMl=˻&FP52H H"{+ |B+]?{ gc\TeؗGRELZdҹۜ:">!`{BnM·āc [_p>sIb 篪ʹz|Ŵ 9Q֘&&&Hj"tDNq2J kJVYLjvwZң-^{LS"ӌsГ%PJNt%N54$Pҹ NgyrVA}VK2X% c#PtR!)). ywyjPd,&#=GS*_b?t T)[;(.S]nTG#*grq!%gɷ5?h ;z+ip@}NݔX!x,{J+ʳ4fZH߇^Ν5LJMs!n$}UIjӁűӁ`z4j}Z{4,nP;L#<-JJv~A+u(y_S/Iܙ˹ѬCBSEi&2ڵ4{ 6!Pcrh.`eS*O|#*x76ݽ~7y~yS v]6%6yݸbmrbw/:rIk7fAm4|3}\*3wxbs*M+]{cHuoW]Zn8ilNpo=%<qwX_׸/x}IީK8!^kQ־iO&=n_k,B(&u{ |?7Bc AzI{.kST|ܖrGm(߻> stream xe 1{b_n vB:XYSIa݄^$8BA2O3!$r!/*H#2/,)y`)z'uH&Eq+_ O^ystMbTм>~ u= endstream endobj 384 0 obj <> stream xڭXˎ6 +ɥd Ȣ@o ̮"oJ!Q'Ō[!MnaZĻq{r/sr鼄4\ ?>.w.VS"/(sq2fr+.剹&ʪ70xK~'^FUEf\7Ylե9˂ {H2\*fOYUqzaNA^<e o> ]mqx(yع-m"zbq݅ZW!iwN+zZ='GimmOlj1[_2&D/ 'c} >scLȕ+_Фxõ Cw5ٱ-ǨDkؠ*koEEL9:lO ~9;볽Vz: )A؊9BԊDexޤrQ &Ӣ| TkH4i(i+kqT50}BW_jgO5Ef Yj̬ċA0/&ǎZaɈ[fR7%Y"ʿBUwwIEF0Y>`Vƴؚrf°TYC d fR l $%%òuZ@Os#Y( ᦾTfNX4:S 5V[-m67$k0 kBkc)]1fPh)ښ6Nɖ Ey9)`6V"z;uԓTB rҮA]Bn0aӛo= v%@Gf?Jh^H}m>U9cP\,OJ">%qO;09k,"m,kHtF}.sj+/9)'nB~zdAͩ̾ mD) DAJi>v!R%c%|0:|:n=Z0nMBꝉQpeߎRȗh .4MFC!L 3ж':KuڱHmPfpuӪb o#˿Ve2p<ԅ}@ }z&j<{pKPxjk9 pU%=Tzsnae'm!REi͚2‘ˇ&\>dSC0,ⷍ.ED>(/RmcIWV4)!J9+r2hf̾ 4wlpMpSO [DhykoAqqS6,͓ld%nm<ӳp3˚?{l>K1ົ|+$c&Rogy)gS狹EbFwu0*I耇3i:%_媳e[ endstream endobj 387 0 obj <> stream xX;#7 +`E\t RxƞT))ik;<EHៃ;s?Wl×0bDݩz8wq -ئ??~C4OĄ:[ۙcHXDeޏV]l8z^C򱕱%:X S! hʜ|8EGQl)QFWT خv`CrHa.KEZH$lEg3 8漪ED1*?sLHL*AxWNSl{9]󩢞.7o<*Izlk8R|l=QMخ6ge3m]87mѾǾfOнLOF<97zӭ:H`70G0BEN#j%q@W7JϢ=%UymN#cJM MSp(ֿ$1A~S/k؊G&CљÀۤh(JWd!^lTF?̍ ΃BP5=8E3|~4Q>*tpBfc+u9w/7quO@v1ãt{QY-o>xkfWh!!(+z5o晪:k1_ uOWSt?Fg5Z-ҋq5*ٟNjVf*u`VkȎ'A7rt Gx2PE&a"'&/ 0hPnfbl"ד}x *,>}q-NiŬxK1Ix2_|3ݼ^IXv [Ւڒ|[*,F"xCx-,[a޶E6J%la>8 zp˵qY؏dkjETHYDkj B`#W<RI>>^ w>V~>sx QHYU`ǽH-;QBy9[Z)jٱrsM$s͏S}tE+Mz $?OvjSvj'1VIL70V5ZZ~5S<,6aw鍓7q\,ٗ F1I]oײD/Y1_GprS0(e6DZ)|iIݗ Ly`SW]{1X=L GϚ)|8PO|/UzO8M̓cz`L}qt{fWQ6W#nl55q~owh7b|m\ZzZ=!{ЊuޮڬIy6~3ʈ%ܯ==`^%wRy'9!nPߩM(c'4E}.F7G{4ʝ˿/^4[- endstream endobj 390 0 obj <> stream xY6 ;^l .vA ?ƩRP|Hy&7@p0ERER_'wNpķqQ~8};]1"z p]z < +qrc'գ>!r[]H"+^Qc}/~ %Ȕ |v !gXR(&,5'GRQHCa8T(LUi8G#-nX֕l 7?7M8Tr*/#[u Y͒Hh=w^p 8FdOG6G49|X![q=bE8.=Øruc1lyp\pLyh}sXzb&j ip8ޮ^VZ [tMkV37!_8n볳T$&!3gըd5'm7 s5~w}e*X9(2n_tp.MIm a(A!zI%eV<$8)xFC~e?ݎ_1Mbc0D} >~5 7Zo2लzr B  }#3}BmqZWe-Hр {Xy b)s0WD/"B=ILB)AQ<j9&(̋JN(w 阏Y%7;戕Y<爘.p1T{c<}!4QtE _HUGH -ޣҥM߉J !T{u*b*^wL!w,Vkr>t5>)Weh6aSKz{h/5q+us=f~%uyvDe`K,ZCV}bIڙXdثɓDRժ0 r40,߳1 Au1@l::5`b nx^.?o`@)‹?%[;UL׶P,,EeO&;ѩ36mg8 !kݻԶ=|I­Zv?/uy W, Q;SS$:jʈWip,M2g%atG]G=ݘ RusBƘ?-gLi/L+tTG譗Tcz]Ȝ9Zoj][Hy6xnE7֬P*WrG4cW[_i-ǒJR i_!`(# s2߿ڒk/ ͍n1 WRz_It6U$=P٥-8B)1V&ni{K{V?:7HN[ԍ)Y's3 > stream xe 1 D~E~5imAPЛxp8]]IIB'>7; PiŦdXU*ӚY*4s9~`ъ&$MF ]g#$3oU榝~h[:q0 endstream endobj 396 0 obj <> stream xڵXFiopf`2Á8:rO\gHQ !]WW:?C"7>_? ߾!Lf!A^O) @(xoS3LQL Ĉ!2#~ԙBPgB|.wQ**Q u#iutz>tZ0Z ا`]z7W^O,l-Lp13f⅌;藷p5\+qъ ]P0&yߌw{w= F%> "MdAKP!>n$B.+E)03Ȝ,]PFὯQ܊d[b|.#Xqb3O渐ї524f5Tb(jmm wC\h{@{ v_voS7=3԰ͳP3Q\&ESB4NM{]teha0Wb 84XI6^N`َoT5^ ҋx"k9eWF2QX!{ oq ?X>*J_`7#w ūWnCKM:QVg$N\ r5)h}r+KP[dUv(-Ֆǎ,*98C%j8 XS*-k u s'PT[Wo9CX4>sKPgb聟NUdZ'ٸpfZv5ZJ% 4XҽuwNEM㊋vHTII1>s˼&$I„[{<ۥ3H_طᵽ/ךuvu3Gd1C޺/ؗ*l4}(_2 t6]sG?\fWwZ_0r=(.8Hb5j]cx>ݨn3VGk*ytM/;ZlϋJ|-]z*qڕ{r4YC- .B޷R7FB &H˺m';q4ˋw)TӴKiFÇ]pnLxݦm̀Yڂd]$kiW9Cvxtzq^W6 X Ωk"bt`]$`:lĦr0@݅Gne?Pq#rHsƒZmek?JFx$~Efo^ Y8n^j?&VvTm?ӻ,֧R,_oN4kdWgD^S&A)LЖMQp V%0oKmnmίӨphu?XcljAGLk$34J/#8M?!ߢlK"qJZ9UQYwO]Xn 4x!?gT7j&Fysӿu endstream endobj 399 0 obj <> stream xڝX6~;)lT)MsCZyĹ8#O=e~O}y7{/!rJt:{{16e|0DfsSiHl_wc ƭ"&q`k1␾(sckgsrt9K򑍎-:㜌)__(Kt֑l Io0fT4FydEB89)JB^$%!wK~|mf.nFx r]O݂ [r,Psv=2|fՠ wzw^-%\hg7ȁ.Yz'SKCV bHcV9RyզF[2?7!UH3rS^(rJ ٣ \v,Lśq$KsX$: -HzE.TD! Fa[0 ~c2ڑe~uE\i%+ Q܇E8k62"鳨ٹ,$ }4I37rSY)C eWUB FҲ4YO%#:mn=;,Ivoco6xdeuj#.Yvأ{|{.MoQvfqhA Cr A7}3n*z<0:Gu~)O*މ6dlsrΕv 8'V C10O胧xë́y'2D;͍뗛N~aJ_]\ zz\:fiG:Jb$S*.-&A(3qWg/t< +)3ڔmQQ>bgvƾsS Bkv斿?s[(S,`>±zfr>+̵iR(!,cp.L>{Ŕv^8g]6 :N̯@͝-zB +lIyľ0`+ *?bn J`;h7E58Bk9W`vE>(C}6یWF8|s2!Ct1{ɩOMz[/ͨ*ڥ*JbI}u$rnPYwy5ۓ7<@$N..5B;N1)ŕ~Ph֯Ocw>֍IW&[o5%RW̋ؒnd:_\=Eg#-ͻΚ*]=WyK M̪ hWQ\~_Q8Ӽ3|**?cҽ[u+tbz 4qL,ʜ{ aQg-[ZKu-[rBotzEi[:(×[XIA-%uV6Tkm^tEh{nvnZ֔q*An} V0\d>TYn[Lņ袖}[7| ?5PV,dbiXArWU;&‘& yG,T:L٭%;NsMz endstream endobj 402 0 obj <> stream xڝXɎ6 +!@f-@߂\ۜr_B[t^DR\p)W>}:;GD.qvyY_gttts~ jt v3Ax;czъM+iˣ{}ЬD]kNRtt-/ M^ Q"y7T^:Q[MΪZqt݄҈n5#a:#qeR&bE #:)@H~`mL7Wuqx5 幈߲vD_ \<'O,gJ˽E"O2nqi?HՍo0BKyQ%zO%m%S$'Cjd&i{)H 튖IҢ xW6)E e Qld~ =$@m?QLSo jZC (P fOQr;] v8vHغ/9aIz&=xP'ة8NAc+Pp^'lW!~NK}3,f ل VdžU9鮻b38*M'5FN07B8&ػ84}՞}&)m~v°]=퇥kXbԴHu8,T0S-q-oɥY?) p `E'xGTZxre:yT.ɷK@X>ǠκrZˬv|9Y>37rM-4ɼ/rL5ykmQ K}<j'ُ8Bk7>Z#s0u"7K{|SiyQ&gDqqJ)\Nt‘raݒ}7 CNpYR*ܻY#7NRZ$P ߉>ɟҙ"H6 0rp%D|<̍P}ZAAE)8EkLYUbk `BNiӳ/~)x^qdkoGYPH :/u\xqrn> stream xe 1{b_ q'?H A;!Xs' a|3r \U[hC T ib/ endstream endobj 408 0 obj <> stream xڵV$7 ]K*pP#$EJcAGO?̐,ð_q0tF4|p1ލѸc f_2ys0^0αNā:],*C9MpqG+{۲vs|ʦ跟f@=ƈNC:}T!E4+vpx83#58\] 2N?XD5Ģ]4TcBM1,Ʌ{C$I`l,4(Uj>H7;sqQwt/:i]Cr01a:,x1B SxU]` szkmlT;.I$ [ z5ĺvw6 ! d=]'-@tH.,R2"eTDz>̺3I~zH2?|9gDl׉#$R%Xׁ BzA/%EGO$[)V0|c}>_6OVnWeo"l ?Fk~C蛓`w-p[?w(xǧM{ 3揀R7lDW);?H }!z"K$3}#(d-gXkb&? Q֍ޘewĈگ X8Ԟٔ'q{(K<;^OL몝#WΦ=sGcyXJSNn>j-If6svi-iFzHho27+1;6kItwRl*7򛽄Hjq( rG L}F4 hf "X~_/v endstream endobj 411 0 obj <> stream xڽˎ4tW&b[fHfX4MÊlpt'}oɝSN?g\r:ň@ivS-E\W~DHA\Hm|\zLRR-C@kƅ[ q6нIo+ JYhh #w>I(9OxQ`ݓhWwՀ \nd@|sy!3g1Wg +#lH2b,|5Jȋxߋ‚| q-sKλFj|f7 d_4W$XcfԠsd|HF"і'u^` UpsV& ͎FJ$v<z< =$K ;P0'kOGdĢFڔyńs1bP%ƕF ,kí Q eu:Gx*/Zk8(UC{Z4_xs-ܖE<"g!2dc}v|MQu Jo|F=NVEu{9嵨F@UAKH**zR )q)fEZWd{RUh27\<GMZ3G1"6fhNRd!jwÎ=Q# F"I[”~ ph%4.=-W~Z~˜Z;YŹ_ M/XUMaK# #ع"Hէc3VD OBSIv%U((63zI{ލZ^fōVaD/dzIL]G8}"cTHQ8ndY&mu~_䋽Cx_ {|Ju"kCL7a ÍWXրy= x kU · wB;6Lz7Ơrڼr䉺0 cĽpBXGy`W($ߜ MA#BVρb$aϢU=W)$b C5䡷g0kmkS)Ø6k,`짌w[%,Nàul50<]D^UN+2.tG,NF`N~m|o=픧$91ӷen垱2"ejJJ8"wj" A !3\ %[eS?/-|A~b*@x6}؉c84a6TjZ'v=хȱ(opWՕSXWbSiuJGVPO2c^ss4ZzY|a nܦ14L,CZ kl-;}|AgL\ :|TlusuTu W :}n0>f޶[ݷ~~E9 endstream endobj 414 0 obj <> stream xڭɎX. ha[e[s!b-dQ~=U,־}^ s2@_Ŧirv160~^g?0 #,7柏|j[?)4e##_=0\OGZ_6s&gg0wc0)͡xk2> As4?rᎰ8gꙿ_KC,>aX n%(_V~w/(ho"<093_6D^I0a!F EI x"Y^/"OWjII4n*%&ddgp\fa7yM?KwXE"gWAax*#pv -16kX^d`JsўfPx5O+ݢ+ %&&*7+%8q<tS~aGd%5+s's(0;-ѷЫȝDQgXHiQ QX oF&7Q "JhbuVX۞h"*L$m86o0⨯]}ՇoZh*+M㌢HeQXg¢0VHWڷf%l,%x}19gsFi&[aa|@/DU1IT(CJa]-ڊ*!֥P5e= .K!*&܇ѐ1.54ީN+5pl CᤄBBi`Bqab̀L BZFf gD^Wɬ+bGʨPLO q)4cL&ja4-0mF@#΃ɫ|J"EFjlD;pćSTOKʲќ8Dս1.}i`G3䱃`BNVgBEMc^1tcK."xcqz$NjI58')n!(|h!ԪegaO1Q԰]?"ۮ-53twfjЩ.+ku;K{vXH8֊RA˂JJ Yu{%ҼR%yڢpש|K&k@[#5}Њ>xEo`_ojp>>2,"vjT%+!Uw@!a/R8ztnVo؅{tp]֧}cyѝC G]UHJcP춭 #`k4LskͪtaЬyWADxhU'$hs@#& %ܭO=abپAT~o̻ = A5m[7„vyީWS1 N*cjNqXP޺TOTlkX[\sw|&}C$çBf;m#S}/nޡ4>A2D c,4U^xa:T VH}D3}׽8C1@ l.k˽b7'djGv,\JQv59I';nM;a.zORHZDxOvtS[+Z;!K^M~@ƥ+o9UPUfjθ ӦLםD؇n )(7=x`];&UV j> stream xX6 ~q_b..HOy&DgopNW")u\7x/;7׍}(uC.%} ExTHFA]Zv YpL^Brd&)w Pvqd(Ŧ<6.dϓ6f`EY;K 3TO>w G9bQ1{XыsRwm2gH38 c,L8wc[Y75)X;Amn<6<,]Y;CV۰B[ssnYLŁP;Ssa^ XX zjV*FHf \xOlҺ]7]nqm-gR@\YN(1?49&oҘ M9YrnVL4*Dj 17tf (@ ~7Uf˖ʭVeZ*QJmfo 5JW;rĞŰ#krA27B5}*mnYrW3e2o|>7o;zKc]p#&&@͠pF@.N\ endstream endobj 420 0 obj <> stream xڝY6 ;`E$@)l8U")#]+#C|j/]?w_;e>s.o_y9a$^o#9|/<qt2,M_?[t6s{pM.B~7oE #XaW~sivlX̪4 $?`q/0v yT3]I[PXTY<*uc5^d0> FBsu ^(2ѠS>B}K_;&-30l4Ϝ[ϪChYD6dݝ2pʀexz&Dq-i☟K4  )CaьvHj8րa$|)Q1q<9K$TשWE >*r%jJJ#3P,O"4ќ{"}/?9+ՃJݍ-M+s[O,sΠ Vd[I&My k8! ʽYqk liF`{M! puT7cJs( hW LvBg;SrJV`CAB#9 ?=Dݠq@6-s67cle49k;w[Q2;#>iB Btamk5&m\7w!;] ssy)GhRW7E+ > _=( h?X{(b4(c2uP.s%ir5 4%ią{ ]Y;4c=HB^<1jpFe 'J3O U&tV&K#рiWr FoL $4 ro=]}̮_$omp P8HKtԗR1RU갤\jNM^\OYz[!; H67F1"!)~V:vXZMIh q9NI\fHBAxCĉaV`jӊz*U>$qJɷ'wkӭ/$T39ʝ+9R˂>mfיW@ .{ yP$6Z O. &LKD 3։ $k;DŽbK#4g&/khq}teoWoc^JYKVhK)}=PwjXGi*d΅kd#P+ɤl ])s7$ q1kL')%;Z;wƖۋ 2_i񟋰EuCaȚz^uCAm;šIy,jE(;pPw,+zFq HӜ_GK{5 +9rJx΍B]pss W4u.ॖckFFA8JeRoHNȗ<8\B&^v#;e/3pq>eA&{4*E98Rl_ >XR ӾwbZlVu,6׵J6~ͶD`+ B endstream endobj 423 0 obj <> stream xڭY6 ml .vA =N"߄OxaDR!E.e~ __eRR0zy~qu'x"\dɴBZi?1:]^JĴMR K~^Ca/KSG^D9wH&,* xfG07n~Wx./>ϊ36#<*Qpgp/= ln7~$EF{geJk:lFz3D>M#.'TרLGzVD ‹ńM to=3i0Rt\]@c  { I!޳D8(*~+GVsKCȬM}m:q-^H3M?_W MԨvw8/q}>!f9׊s+lN;-6Ԑ~u 31S l482HraMt8]at٤|!̝GGG)pFSX.VߴƼ]z+=άuY,D@j$QRµaaG0 $P̢MāVvMUلR7d=MLqr]}3S sa!R Ȭ㖩hkƣ'Ӹ9`6¤{#g֫}9_;A%u;Qc]40bxsFAu)aNT-9~6ylJ3=qkM&c1%1L&ʛf,'qdBAC8󮧊ep~`ý6а90ƠDO{KXy_ǃRu w*]3Vh2$`7-N'bXݐCOM~(!#FhR&{i rjGzeI&:gx gu;vNK~~ŢoXc/w0hI|8x)0,x X9jKwW%H{wo_^'bGbFX.A۷Q:zrpu ip2*㱊fOjKsv$鴢~}˽ʖ1t)_ A,+>9!1$G[Iyས̍$wuUrjqW3 QYU*ȤzһhwniP+oa*LTkkDHA1bVˉ1™L6wpE WxbB% .Q?e\YZfPrh9U}ICp^_og'`W:M%LX=w9Op@E8Ni koMWmvDӗlMImwo]7rI~b? L endstream endobj 426 0 obj <> stream xڝV0 %Q2d(V [!7u/DR9-"(7!!ð,MaC`68'Oɻ1:XvSˢ:eeYm\O0FnQ{3<14ȏmt7B0}9&XaM-yb,&#)iEed'ּԣjUPEгv `)+tV"[JɓKP:0$p!BU"Е x%uW@FPo=]MJߕW_Ѳİ8Q[r>4[waTҐV>[\DJ1^п)JCw݇fީś4Ik[ɢ+kdTx<%=rf+  -_(jKۉ>rZ,qV*C?HS<|ҡӻ~ƌw~ejI^K9H]oV([뙂]{*hbύ"fy b yz*g*QyL)y(n72NT*0#J:nˡn9vzYIIݙBioRg'gi-*SlNb> stream xm 1{b_W+tbwoJ2lflBOb !c2]7;2ȉ.PE@q:4؏pPb=h,+KҨ:tJ؆M# xLvfֶߦs2X_Ğu%e~6\M endstream endobj 432 0 obj <> stream xڝW6 ;LS7!EJ=np^I<|q7sCFoWZ:\ŒeKSi]S4\?>=L?/E^?T Њ$hEZ :p {=  ?DVYVzgvL$%/~c]mR.Q (#()lfU]#.Y@T٭wY4n7/#`3=k^Xڔۥk{UyZbn~8c2 e f.#fA~(f=VQdvaU4ǏzlosPQ߁CC]QҬd2Se+ dRꗎT&O[Q a^zH.yd δXU*ҭvu'i%VV =?Ц>qRxZ? ۪wkvF.qOmMZ4`Zecns9,yNwWϮ־glg@J,jJwY笏51+#o"[zit-jE[9Xa>JݙՓNP1S7>N>Na XR 4xtY[H%?x_jS ~ūy3.Cm'qNZRgjKz.cLݝ~m;N}Xw od gyM䆐MQӬt|߰ʩ_-ϕ}fjAeۭ6Q.])GwlU*ck-u%QЋ\hv<sM}K?gAZ{y'丹֗`uoGqN\/t߹{aeγ'IN4m՚bƝ77K0 t ێza w t$ 4DF"=]ԿݑwrRcHOR㹆˘!ɑ zbV9=*t ?tO8):YG7a.o!u Oa{X> stream xW6 ~qHSHltA R%ϱv-GQa;?t;_uv7k.t}} F!}O3.#i Dj.4YHD+ɭ r@f=@4&9dL4el[t%c*p(cwqwJ6`}ۅ:QP2cZ'ZUރVڇ)to$:1&̜R͊BT.63ݪ"Dz"iJ^9ka,HhO1xL;b ɒO6ظG4U;sRy|^Hp$->R^ߕX7FoHARE*5}9k.+'I:b62. Z҆O5}ۥڛf春cxHVk 7^-RGT4C@_\)q$VJWK'誶(W8Us3+-9.%W.&@Ԓ~1NQ>bl8*R?KkM(@\X5& 2㦃I ZcNAgMmFNivȘ+ $Z `XYV+i?N %pY7)-rd+@HZG\r3l-<&0's{ڮDϷ䁜SCrl܄ϐ?KHDXl$,+s:KI*Tzr5({fMkb22鏄D#10ȃ sAR:-/=N(P: b~fa}>;PEKLi+_ #ҢlCXI+-"6-FMmwb.gŘ{5~d*_n+/ݨ}þ65V'/e'/2r endstream endobj 438 0 obj <> stream xڽX6 )II @nEY9HYqd2-Hq?ѯ_i|k_N_0C <`ڏ> ;RFH#hD#3Bkg]/> stream xKo]gNx :bό WhV*@-V͛x^rk[6nl9-֭T^l[|}36[dLefYΘoV'ɴ捡Yg tZG(|j'SO Jey_{wא14 ī}KyRټxRݼ澱doͶם-睩XlL#qc)mM]wF4fj ʕ)o!{G`ll%3p+PsVCF)!ȩh#b3$1e T)l- DYn A8jΐVƟ2g /^+kcҦWY˼y4BP/ 8M8|D*rG,G}}C=rQ7y25a+r J+bg%'~DwG,qOBq׻ȔS ob%$a6" wc4XiiѬIOK"4sqO9vah6B `X/a;E+KR:V9hE+da?|vx'c܋uoO]՛;s_tzve<)Þx_oބzu 2x`HpRp wׯCcĩC9s]l2OXڄ,o,G0-N3pGA <d^L/<+%OAF*rŸ>BJ{yt b4zmaX 5Ϩy NpK7dOy/({r G-ȳ(n r =ȳ,B ,)#x+rN`\8Jᯉ)ΰt R1aU/0ND5eix3J)5]1ˑgrAJ~ˑgA4G FET/95I1[6*x\vM}ƍ=(B%I „SLU2ow@.ae򖒱7NS 3ж}a&]o$*C5<}LxN!HS57M(Ə)cPqB<*!FULTy"˷[އM4|:AyhE?qL@ᩝb@ QHI~И"^ܤ:^nUrj׉cq{Vj5eVo^frg2^}=1oMR=覥`8rޗ㠒!?O'!T<-߮MXȕ6bIm?V#+!xW3R[AZFQK!@ϤQ%qʖѧnʦ("U]/]EmL/O.I{GDpYڑ$e8G(^6^}UTB ZLkIU{:ɷG Z>z FRfHIQy?)Rῒwy}Gv3#CRǹA,\F[s.V%\m#rP !²bTCGC1ms2@^NDWjW&jWUBYxmDM~CZ ~\9:`]EPSWDdqIBܪ%|Wv]ȁqZ FB]Maߣzn")AnD^Ի'FHh./#Wrr_"X7HªShfb tI-zN}ǀ뾍ueF}ਔ 9(JaHA6c]i#Cl!-&e! 4hMꦎO' daZ.\|ˌ_C 1]չ|~{WLVu'T+Nek^+ZURo \S~+K ULя/XgLR炛J&Q1\1u?袛(q%;ѝ/Gqz.߇^缰s`h~i΢ywr-}{2;oWtا7 'Йܚ++}#)}lH ㊏%\l>-c$q*ֆ+ba#{<0x̜G>GZ?/Q>JKu^9PF=p7(Ļrx 8dU?~ endstream endobj 441 0 obj <> stream xWɎ0wKhH oCVN ;I/@bLM9vy4j~ koOԤZS|lZC]iF)"#6rK*[6yPY?q"e`h8H~e^֣ʰͻx8N1'ȸYcok9wJ NǵYjZo:oR4[ԃOhUFmԼ!6;Z$D 23dD̅Uck"Ǎj9?UGkGӻe兡:t9^neɇl{$i -9Eέ(y Ebt&Q<ǑqjVuIo[ Sgym9Rgn;~%vegWof7vfN/z&Х1QY[p' J78<(zc}9 fbK  b+x% ~ыx* 0:g %^P+e.$PK/d8{"GTdz! RVȗ8ָ;2}a_5{k,m#|p!!ܕ+7>ʯtcG >^\% endstream endobj 445 0 obj <> stream xڕXˎ6 +I Yh tW`vEcUMM; H$EO?;o4]Ret9ex su`x]֛ .fX% VIF#_?VP94i c6c >9 L=`_4,"0}f<$ٮ){u2s j-kX[5N g0f]Iع'th| iA O0=oEt:CU;ÂD.g9ؽ_DbQ\q?EڥMA p*CNVZ&1@W'y:r׌; Ap$=_RC^s7^H@gmr =ğ"v #$ryx| 2*0 BDDQpv\]W*{L'u. $e"te4%+>os!N7vlۭГOq4q0gʳdjRʾe aMHr WQE{УFtC^%K?$pв{~ǒ}O:&ձ(&0۫0۲D4TQ*셙*)N8> 5)nkxn=ʑL%8Y 8Ӻ]rVzw5X$m:Gsd앫ohj._TA3îr aΫܕYx&ΤcB{d%\4a~\T aܫT/9 q1YHB*!y'=X>H:42 s5Gw~o/&s?ƴLAcj!5$yK ɡX)S%Dj%h^F ZF5K#YۆSmeV߽S#UùU}bݕq"S5l#'.ߍbKok5]wZcVW CWBmw~zX-hom`9ȓy$w̻O 5`_YG~1#8^ߺe>7PpawΙX^\`'/$]k jxt́4'l&=7@+Z~YY W*ϟ? endstream endobj 448 0 obj <> stream xڕX6~u[H ]BT)MHY.!Yf8wq?w)~O}u7w1"kdw-y|w:Ͽ@T#`!9btϏǑq$#įH:7Dʑh587 W{AUJ򃨒]>rT`'J :xf \)ezg!."B/6& D_,WoDK,dL:^ꤐcə&,!jq3/F>FTHQbƁ8GDee9VF! +>TtwƸ"/b/,*ER)eK0Z:oO*]߉k%aՋdȡ &15,rYUND/(,,-T$:B㬛!(+~7efUARҾ⹑n&K(g(`/3}u^Dxғߥ[H TQ0V_H b%Sc[8m\Ĉ:L5t3 -"(EqseñV6GD3886E C*/ģ S+8 A .JRFwr2d ׄVj;OFo6Ez~~Ѥ3qx!RrDk:pRMՏŪo<&so\5_[[QemtŢV|ذ\|!`3sHl F%$ꚗt8P{A >FT'咘5xO"xr-Aޝ7xTVm="AcJ8J~fc[՝YQ'm(+C)55F knj?1_#AU;VjMzZH D.rjbؖo[W`orCG6uUKaff C26} Jfĸ 3'rCD~ G`yPi42s*jSNl܎cqo܌~X wJc+lB&K:6qu]\=J؁ofPYCMMs[E?7oSd,Tg=vAbY\t-VuAyQQl[4%DP V47[MA; iol\CMȝ@ugvC8y32c=pCiǨ|}{ZBRu.a?jSw^Go|-mM+{p'z(v17)".ġ` B!'y0RlQ˳rY;u\2Z5;N'JM*AUERƎfGjB0SYbV3|#m{elZBX_k aٟgM^MV!ڐ]뛻J-ݓ]]au)wLk + uNKob:&s?jASRդMdv+]}'(QdOUBSiŵ7oKЅ!#:'ao@[?| endstream endobj 451 0 obj <> stream xڭ,50+ni$@"C ID'iЮe]rtt3gt߰_e؍}w6O~o(3vw0œ_Gn@N}7`l>>R <ʜ5G7P=B ,0@d t嬮lU1`]C*8yLҮE3]a\;\>S$2g#P9:;lf^DoMg}_03|G5M1I=q<1Q@y}c&k>%!Z֋Cxq(F; Άz0֬.#4:z"RL.Xxة m1~naya{Y/|c9A3}e m- 1'2)lg3Y=Yvϐ țփ۬MeS0'Τ18q^a!i2܆)!,c`|҅Blj4QilyOA]ֲ9e?Oܸa\c|/A112 3gw.a؛Ϡo kvʱ31nupR]A3e{HH=IS}~M#n1eT1n(pH"5\ vG[. `Ha(>$(hOW\ G5L g I )f9%`JY$oQR@9ǴIjVjiFRn艙^bӧtA8~|&Ǫzj9EY$V*83'eڦ41iD]I]@?d[SE&igtʚ}k/4sDy~n_:U*H PJkƣ%m7kȉ"z4zuhOAM4MtL/Po ݱOŇMHJrű34ϳ(Eu춸Mk VqNhCjP |M] |96g% 0>Z/Rp.9jq:.1^y,3{8 vxMJ% ? $\> t[IK}Y4K|(j6dQe m]4MV +ŕK[v'I ULrXڡJkR> stream xڅTn0 +vHX@ =CҡDi AK+ ÑaC _2zF}3O?٤yYڲ<xlׯ/u(5̉ #b|Bj} +"!Ϩˇɒ+UNZy!ZS{+7^cz@l&fV'[tFC!_+ZODYAA'rhy:+j­jǨJ!h : 3Fe[:T4䱖JՉq C^যUR_uA"{khQ K]NX4Һ:^aH ۏh v;ՙz<6t5jޟʜYJh2>[MZBշ<{'3JԕzR㔝,e%><.ncow3&T Axpr;F}C-~$$ endstream endobj 457 0 obj <> stream xڥW64&03ZRk#unM ђX0w}˷8:9}|k,ŧ8폫]p3]bW|U| ^RrhP ޅA𕩈-PRïM8U0<YJoq,:hjU;R_U`Q 4ISU bne% x9@t@8tH,&O0|CxnG:Xr:fBP BWg ]JVx݇inl'2f(n`'cSV1bB"ګ}},h2hÛڮq-r@wo0rg /t":УJ“WS1bi&ܽG`<43z%L!}NOpӧ4M(z|5 T t"f$PvI`0158Ѭm`*!:0&_%O:UD'4ֶ hW*q6\ KS %\mqLέ2@9m)68O6 O|REt i[9sjC hTR u/ ~]#,7X̟4)ȀBFhPLφaǹaHAVӝ8?8'K\>?yw90Th&->"ѕd2Pxk62=X5*!NZ;݋κr32rRp nlҌp@XX#x U3ʦ~JBMiv*7|24yG_BOն rރؠ3(c`.Y1;eRFDHyĐܪ_SmszЀx~OG >ܴ*o1 o Y:ڵ' endstream endobj 460 0 obj <> stream xY; +DoKbH` [oBQ$E[)>>D_{eq\yBmIrclaDyw67$gGA, y]m c8uRF܀j[+NA]ZoGV@~rTK:D0 3 4|ӵ9sqJ7Shx̓Ff)DʺIu*m4_/ Ƴ7uv3o~0 oCCMv<8ҊE r;gr<&} -0|}[gYڵ®A^wxFfgah(j) BKU7Ԁ<ރ9(yjvŐYlЉ\qC#.s) eT)@Ȯ߫B amNG Ӊ;Ô$'qSU"-%zqw Xxxךҍ#]j-d.gin]Vb%W97K\Z$Y[uF'šPS.qirÌ=|*:wSqӌ54cj>Vxs:QUuԏB\)rRn>Jף޶C Nj-u|^`}-_k'֏Zξ]ƥy#cmǻR9;U{4H8E3}c>﬽>VtԎE6sXG_zp{yz%s—ڛ(Cn+N*t0*fI8 C)L<Sp` z>+> stream xV͎0 })*Hܐ8Ӗ8i"!vLR~uS]'>Q' (t];dTcwq). jw © vhK@XxNɛ Ո"*8 jC''e Yt"{[#Hkk]~Aioaڌ;TCBPP iø!qP{Nx*'$]{ XZ$=0'0w|D8)(,e”?؈;8'Q)6pKD\RLqo/ҫ83 }HYDX 7|x =UčىT r$~O3'U'` OG~B-S"$cIZB-D4AXr>%r%Bud@I$AֽYwǸ[tf%,F9uVa:2hsHqK D%W&6WUp:փSywή.'nզǮ'BEKCʦZZ|a0a`A$o,Oz 흓muv ;I.yN Lrqѱ|8J :{N JP3fYq-,`jr[DbՕԌ H5}J/fmh#vS3U5WEHbHɥB]0^:\/VDo#>mO9ay]]$uRh4{j8GPDǥ㷖]9ޕyҖ,1qev%D\k711JM/J Ҝ&Ts4sQ.#$?Jy8=5ٳTsK ,>G-WІB_I3<]_>,u㠲W[4YN_T=pl=o[ endstream endobj 466 0 obj <> stream xڕX6 ~;Կ 8 ]㱝*E޿ Iaa ޘ5qx>+Cõ9 $ SW<"B*8˨w4nYpp8.%}5O|8JbSPza F›i2)>ȰSVXȢZJ8BcQ DNqv+ V]"Fҧ*/)(S%IV[:{E%]&\<'UKdOx RD/I$9.qKU'@ƋU'U%CvL[U-*VjTˣ vᤋtӦڌQ@ U#OM(JΝMU26߭ 1'=Pi]}^Gz*ݘݾ;6ohH$c if/mHv1Hei֙G23g\o&\68j\ƹ@bA4N^Jk*bP :8.zQU>AĽֿ.vsRxWT6i_g䶮?gUFÖS=؅ث_^J endstream endobj 469 0 obj <> stream xڽ6WHp .vA ْ^"ds$r8/^ |>[.X./Wo._7clð0>;? KGG{c cvF~!.g?[1E;&>׏wƚw߯0Dig400=ҼANPT'B:p;b@\]߹< z>#T:#<6:,1>wy~u_&$1Y ,'7#[BiAA^E6d{^f_a3-/뚈IFVhn{N`S(EHD@u^<{WL[jkKwYv3…{a8~^3À0 ATi+ƶ㕌$3/8rb2r⫼$d5C0(WЊaDH:6=/ D mY+/}f`u }H .IJ=Y`UiKLߘWTkLַA 'nr)~4D63gjיC"Д(r&k+i>URs2G-b0g_%_ĠЕ&xf9-Ў XJJ >!hahu5Š ^rޢ;?G=z}^IcE*扥sReI{m.“. O9.!6: ,&Z-X%Y"Yz"Nj[Xڋjd, N{8 ҇ZN7?26"FjV$n.=Lg^*([*?QSsX8 x$FqV]N=ظ'F<ܸ2'DB+}O߉wz ⮷hX2׊+ĩ:KAXpD=͆CeO9s%ȍCS9ODbg7a/'{/l Obb6i :q ӬWJ.*+Dy%w]sQ\Giqfe} zcIE{dZ?ܳ[\*F^m3RW'ޢؒ֨[5||m]u@6m<4j:gnaYt۸%xRGcETtKkrkR}uY2+uЏe=MyYc`OPx%rꬷojl'D> endstream endobj 472 0 obj <> stream xX;6 +Ro2h t+p[NNR|trŝX"?R>sp?w(p~Wqwqrn( >\đp!A2>hϊcj1$w; ܻY_q,;zotyq]v*?l- PcJCImJG|k Uyz\d55hG p\}n+$f2č cσ-|^5^$3.ѓQVօ5NJד,>]5^SĥRJ 6i\g֓ /q./3;nqv$<'G*+mȡ#R`Q1W G=s!j@)0g~v.l@U uG_ѵlĕpI$fFSrW}=oN'G{%Gv3S+%tYlY]`Zc:,ѝ|3@1@Gk TB4׃h.-?d-+c<"`YUR#|`(gڝ1ɹ"pبłbau|!⿄rsamce?nʵB@x7qp\!,ZC +xKgy62C`!˭".@ůO%]yֶ<=:ӚKd@}|Lv_DŀMUIl>*0u GqlRzsgorBޱRW0q\(W(vHo;ObI!MX9_ '~_ endstream endobj 475 0 obj <> stream xڥˎn"?z@0m ̮y.R)Ѷ<ɜ!HQߢO Ϝ8p~8we4ȌQ!K[8)G:k8‘asDst08Ҵ$+ldk4a2S0"!;u6lewEl:Sp4K8{;_J bfNYvz'I?Ҩ_tߤqq/~;o8,OIg Ԏ 7'%Sݕ(>s; A$Q" TwMftfVMzY_U("qVPB͛Zq(+nrπMtKT&ŕ':*EQJr'. aa:}[ԻPe(6^\'% SE#u"W\Q;\_ٹhX+Te;kӦ* 0aV&g <PxY4@8ڑY7ֱQ\xP5>Yس6*]!-"{xME|Td(qb[_ϸM>24N[o\!\Xɳny^Y"5Ţ)iT*mM&wCK3-l),U$3b Y> stream xڵW6 360"@ ]?R7S={`W")PN ϝ8_qU?}~ŝK(<]qpG1~*Nq.5v 9q]D>nGVdž pózUjyF^d߳H PpCtS3>>E8ӕn8̊z|'Ϯ\,S8V iDR0UyBDlm-41>']SO`p4 &{O#6O{;}z n8.e 4j7t#;ZOps* ޛqR #%N)gٰ&˱wE^KC]!tS{#͡|̝op,af}D|qUڶ7ӺuX*%)vb.{Kɜ#決L+A2MYEPDq.AMNjV8 .yMqeM$FE|VY$4wT1x4[͆F 3HXi:W1{#|KA\r:2V4_}^ck3HaY9=?۠{NiGyRV'ϼv׮RcVZ!7Oby "vaޔorՇTkFD~1}~:eud?f(}j''j8v$]QF(_nV;[IY|6BTb_ͣ5$.+_d>x䯶ZЦoMJ}Ѣk=hZ#1^E)U:[:@[l t֪îcKJ1HR$.HVL:cg/V0RA{Fga8Ы#뾾f҇Mp!̐SC,G$ZdFԓ@nwا[F"YGe #*xyΩs726ggqw[\!Il=f_fS7͛[ė],ڄYn{hqiK;Jʧ{_Pub_?󰪇~I7ݞBI`{ endstream endobj 481 0 obj <> stream xڥV6+÷.H]BR̋)KYo{ $̙Ps;.YǷ5tc=nznbwsq0GapxqK`6cn`ZypEU.27$b*".Al@J+7y1θ>8 Q %)ʈcxMfqwC6x8] > stream xڭW0 ~,Amnb'ԡᅯ(Yv$+E~HQt?4ozJWy~:5`3tΑinv}Mk9]~47 ƚѓ68[zFg~[* <=X{A/4f>RCm$5YB|>= XMd`hMɸ[A ~4Rn#)+ ͝e-Jo jPL-I+P ]j<8Nͻe ,VJм`}'hbI;({{ehvF>fglPU`z89ĵ{@"L 3)ӛ,A+AAE73&Q_[&DP *u293$Δ-i*7#rINx㔭M嗌Њ5X}_|jxKr-;$rt/^gjIywyU6¢m [=?wI wٗr?R 鰖[ d~_kRP, IhϗKާ['u-~; tߒ2&vq_tx%}w}5F+*^WdOBp RZh3M0Ճ#uhP/yBM4Z[ꕫ>`s]Z|[NT8KO݄6h,EJǾ%}grc]A@ kCu4F :lLL+U%|3(@螠>yIɨ(EQI^~<)3y_\'f4F*R3u񕚑 $ i ]f8V;XI .šCzXdbee-"BY_ ! f縒C`p+Gc\H\J/A3 endstream endobj 487 0 obj <> stream xڭX6z+[ lX_7dv18Gj;xn~[>FZ:1\? +K82#R \=Cܒv %J_1 "QCQ,g%FC,%>#񉷫r <& ]3Cl0XPjX,"ՏY߆{8*32ק]8 (Ax ;dTS`. 9Ǚ#0=O| &5H}SaQ_(Ŝސr̟H AI`jZ!$B޸NʼQ~Y%fPg.{͝OIR`l2r d 5(*5s#0΅>Z%Ceg]hu>`J/Qq]D(Ꮏu\A[mޏELe,`EzئkD:mM;Ȃ8pHy I7V EPZ4m8&@:UE{CSeQ096<*]unޞ0-[AūXzՋp3DxJjp"}CD )6ItI_ԫ z00MuAQqCòl>. &}|[{U=NlA6}] |7PֲHls2ȇ=ώ%rrzÔP|]9sٹ:.,ǑvnIđJNBusϒu8>U'=DVXTԃTIOUueWhqpiǐ~wQ:^[irNF};fb_4ǹ鷤ß1i`{O?ZbK% N"<{j }ϫDӍCZ>ݷ&@nmZg{6O8է'0p ? endstream endobj 490 0 obj <> stream xڝX6 ;z[S\&@)R&|gŮ`DQuH?ۍM ~O}~~v}.aLr>n-A? [<<3Gj~4d-{4oPjb)ReF l2qG1%;?k0$`D <ɩHO#}Lt@Odqe.EhjeTLiPFU&RB1b |B O6LЫJvi+2;/҉ï#lg?t=`]y3Z8.OO.wj~;D\ <;Cb[݆@(qX_5߱-^{ĺμ]W>v&QY03(NFhl:?@}Y:$I=582sTfMUW  Yf>GiK*hyQ1I&sfYr1u\M7U7+`0^Ȓս8P08/:ɉ2qby VCk¡|`GR0Hf;hp*`ܳQٗ\XfWݪLT\a8H_MhLA9-W:HHb"M$4%7 xH{%':O*/Se~a24@P/\/XQɈ6J…sy yWT7朗S^z\-OvH1u}paHi9?3j CQUz<%MF[PVg.>0i)Dbǎ4bVWΘh c.w>ƨ*5^1Rz7Q-ldBFj(syW.ѶI7}#Ne|FksBzk)?K084ֲP)-Ԡ(QIT`C ZرKB#>LhxkkH!JlAs[tk]K:KaKP~H^QAߚӅ8HZOXQ ^d=̻귚rkKp+Ţw1e?&n{ endstream endobj 493 0 obj <> stream xڥ6W)p .vA ɒR7,zK"w_x?eBbacfFXV{m|htxo&X#U`@ .3 m ED "h _?z=;0q\G?>2>@9g|3Exad^!CޟhgVxFYNo .4@ 3u'—a-6[r:¥ 7 H*Iu6Axx(.Qԣ'ܚd05 7D5gsӎV*sxb3 dur͂ YvL :sVerQf "x⺱P_+OuVbAQKnU-e$vTq |j}3Tυ㲼ں\s:p}HC鋜3b87ٛ&>t)\t_tATi66@.:òB.T.l3bQd''SIgt}MDӖЭ BOy \I7sgh?(M'X(jguyt A)H8.+-fX ,H`G@ k g~4N{CO,''i8.h2"i'ahw$p&Iɖi;!L8&hU9-n'ljt$v ܁0S3aȅ*csݽ! Eh׋1ܶfqr,,JQF,Om_'-x QOwPJWT6 J b];0!_U sk5w!VK,)vvm2c|n)|4G]pcICͫ_c`,s}_s ̿:/- 52g<-:v8ҩr,0;{ܼ.1Sw`IPe16ÎlMIMᆰʼnk?@2> stream xڭXˎ6 +q~F-]]q|W]7%)R8[ f2IyHgwЃ?=DjOQ} ~Cmz! ǔI)`X;cͨiDқk5z^b- L+ RBEҀjTqnI#.zdmuO| ,UJ ; vT+=HFR}|ʴ)r3M񮽎xVX4Q=fN#0M'E>8fk8-គ qĸףQ^8*'GQw5@y|o)ŝf'θpAX898y6upEUR-󁢔:Y_T8pXpCٜOcyIuc+fTpkpKI䐼Y@ZkK'QH Y`PI\"C1Tz}+{;L֋+lCT A gݑ2L|ZTrσA*Oĸg),`U<{$?&CBn;)ǀ_t(a&=Bu-yysBm"th"kYHR-lm+X43J=i4UpoэUM2% .d>uPc4"/ECA wFemGoaf<",K;xAPԒ5i驛"+c /fdSҵ] _gjzw>y2#+<՛HŁhE{JJe0 1_ևMƻI[8uYe*(:+ճ)!ĩ [} "q{ǡٟ! զW,1y[-6G,PcyoS/2w*z2b[)>d>"Lћ}'@ND6x@]#9Hk>xߡ W w:.O{IcB0r5VouAH{J$ h+iu37?ȟI6u endstream endobj 499 0 obj <> stream xڝX6 ^[ .vAyJoBe3$!)LaZ#t_Oߧoڜklc 2BNs‡bHuSaP)$LNxC 1&apeQq+E x=PkK_xNC=LoF뺾+ꛦSslWz6 (k픡n:wUd=,}8W^v%pg ,ŸDnGgTue닳>Qgc׹U)0m7pSJ{ZE)iMIz3MI$N`_.MD"rd)wdˢ{P i%ɚTڃoY I!,9XnoGwv.K̕e}1"rn퉨ܤMӧ&m(Ra\[1,yO<ZJEBIs$!)+ GX]Mj()ݾ:MSR d_BmREaGh^Bcfenwu7C!PsH@ lEVh ¹͔F%f`I<+5Υ/v-WU<| c.2BeuS%Jn(>Lwb*_00rD)epTFqԴK!}nu5?1KmAј9\å.dfF#Y! bqrL8-SATs#w@59-Ii+-bS;ezs3e^lvl5Z9XʅGZkH˯S^r<ɛU\~{QˊQdӏ̈́q[>՚↻^2{2{ǧ6_FLzcyrX;)̹S{!817[p3@;bFn^UYu*p{6]Q aq:W ʪ/7+n&+@ H#NۺVn»2>e21u\՘pIrU&]T Kǘnj-L=`9fYCjD:ߜ]?o՚u"*8  b39H8StBà!E;QJ_>]:ZQNk<OO bm(خV !C }%-N7u aMil0QT8JT7kƺ zU1*qxcB.չ;[+2(׷!ft9sJRjV5ǍjQdUv/[_``b-0&8ʼ> stream x;6l8zY2pP-ЭmEǹ|S|I;,ŝ!Y&)M*OgN?w|~Ͽy@_SoاӇ3]J_B0t,Rc`}ss8&|F.">!썾_q`% S3-bbYw5 `Ge4=? =^sx|B8ϬfAY0ȚwH! I4֫0,@0Qށ¼ m|X+x&KW󦐃@ RDY)un[--XoGqo8IX@[1ui73)E ھX-q6g,UClVb;b@'(MjA=%b7t@ G|\{^c9:OIX!MB%Oi!D~3S,,L BZP]TA //t/|/$  УL{t3 @vh8cDKCE|k,N6,TEP&˾YzrO12Et 1jX2QJ!zb{Qm.8xP&1`^}rbvT?mhDmm b 6Cl^LXa}cbVTŚVvs8͂2ͳYgLtkb-^nkc1ThgRaφ}ځ,y{(ȪRU2(tRIE qܒJQPV%1 ݱқMޣ lk~G* p.@s@g{f>۸zcYq.w9\'uVn,! .u @E49GDnME(r,!sԭ*yW FnJ{o&wPPjDX˳`')0vt@-ڝ$]ֽ| ¿ҭ\YsyyjɳTOy;}nt_-& QRX aVYLsbvmª hUi]`~> stream xڝZ6 yn 2h t+pĝ:)Q?1|)#}QO_e7ϿK:} e5R##>|{ 8,\FRngeȇtYARW榌NPt{c}^ˇ'V=QSf`1C7MfF`Oz6t4}{ԴV_RdyutBB'd@/:2 ,,tǣ-8x*0uLV4V#*=L3 ԭ琏\+Vmj*)12 \-Q/ڮժ._eE5EhhDdˋDF6A5nҎ=;+3/F&m5xwޜzCU%ub^d{kJR/ᗃE3;K=E;(kpht`E:xr;\S$pi9Vz:,Kؐ] ZU6OkU1Nkv).T*bHQD1ߔYF#Z~DXxb+oJgA^s@Tϓ)vf䓻ѝ/G[tXЃĂ(*!L6ZGAtK5 Fc,md6!4AS SYP ehGs)LJǁVZo!uJb;v7#u&I7֒nj"oҿԫTiiA1Ǻu8 mZ"EN4'AŚi$xPւ,ٱ2j/FoSl;2iE; |E.DvmJuQ$Ѝc['„\QiqIwB"m,+$hxSѾ8Aо-,FSCĸ`sU_HV#3ѥsnJ PN ÐebT`rS1ўC@k^{QDK|S2A62Ӕ5Qķ\DQH\gR t7X' Ӭ e}8Gb:13A(T)6}鈵u~3b$k|1.{M%k5qj++syUNo`g(9-PCiWyӕK!{$]X\,"<*@E S@p\ݝZ`>HLeLT>$$R܏-(f^upCjM\Tk&>"UJ$;(T4ٻAO ފɷڏ#q$ur@%"3}270RNL-.żd6 @`d}H/0gУ_-{S_ŰjR x 1@'|3(EŁM+ KHu hi\U<¿ UFk"wIs?%kB'N^4rǀLXve+%eJsEő`<~X+ޯv4Ҷٕ0 m;(" [Z*_tP58zb5l  9g1Р0N9.s P-~ɨ":nA-fH_u7qS1 IuuAckVIe5kY[.gbSmz,E\{u]a\/ Ę f>S摓p-)}T=~ k)ɼ3S>)X>;ٱdO=Sglp0O'^FXqT$lqثNnB8E=.< yVTdՙVvYk8D(j 4hEO+]38;cmpO`h浄 50!Y| MtF؀m/Z_dKR^,c~d{ <~*PiP,;ѥA[?Dx^pn룽?V ~afC&`Ww7.y@l C0W€ڻ?,#H jFe=1%`j̷_ 'n?C endstream endobj 508 0 obj <> stream xYɮ4ʱ-]eHH;Xcg޳r;h f'>\sӲu|!l6 LP·F(-]Iaߴ4ffFى&9E#a%lBj\!RM5w؀d<ާQ]stiu+ eۙ% BH>q=FqSSC y }1` [aLjO@) Y31B&;15{uxM2E_N+J6*C%KZ0}]$& ɌUZO}&##%vct76_[k.Uٚ~xfǦ"kF8*!kp[*yU'0]~)~տƯ5-qh1Ú{dTs.9<Sid38aHuP, ZYeiZYs(;hWܯFFa|"="z gs{s:k΃;{FD#+#r,GgO)+ YA).(1{nL)oẃPˮH.UUi> }b}L*7rŘ-dT6fi. cL:)Ѡ}!Ok! oZfuMoȄ=ǡBGL.%sϖv<Nّ7^/\4Sq0"daV_uDmnh+wfY-1hY㰲rJ(doкBIw(BG#xe𘰘m\#mG0"1qCE Pn : gMW=˪ʊ5K2snR&Sl1xb?ۆ,+`%+W]/DESu|etu,ΡMi<_mw9n{ƶ*In #|hW2t:@ydE*rR5^2m AWTcyh!EE(*XvAHl :xOk%{zX+4|`A`w$0X19UE CeI1&lQ\q%h{*vŰt>mʅȧW*X\kk\lW/\vo4[X,}V\ڷXZs**`L8E|J'<mmEuZ^i> stream xڵX6 .b|  ]8URjzfo+hlxHQ?+KZ&z5cn͗~~y;Ǎ~ɛ'zb˿~z/F64{tޞjl#SNZ .3S\xC~e endstream endobj 514 0 obj <> stream xڭɎ6ޯ$vP-[=ɸR\$ڱ=^ADRE]ܥxo+_eň@%[m.?.8?Cd<-TkHI8 v-vO#xW (f=b9^u}+ 1|epkxnqT^xKwEsL3.Bx+#C|S~Z>ɻ_^^ 1j+ m^]!QUFEN L߻(zluQ@;$DtBqaDF]oN!jW- O"LF] )C N܍?bQQZ٠QZ茒zقs*ҙE5|R`ĐK=V'`o$cBPЌ,XG 4)wuTQ{1؍@M0 r;mw4._QDEt%\3i*S}pBwռ}5!k :6/0m8R|"je#x_꡾; Vdq85zIpMӵ2uO-kQxj8P B@$hnоsiAl"V|޷ zD^DZ ȁ 9s%:6I-Ei(MtS*yJT#Z OÂV 31cL, G~/ 0Ie3'j{ _Zx+IH( z5k$H1n\bFkZ_]oI eE]LNK81WXJ-\2ɅsojJ5V}mTA߱a APRd*AE, u[D g5V+P$Wת&gA'P4; S)۶YQ<Ϙgmqn1>Ma!l|'%mùuc^6-ƻ rKm7/_ Iw=I_j9,WOqk,65̛')[)[ShE~Ȅ'I|K8DnI_^/{@L,RMA@'y31Mq$|L-N@qz~fʪrCFzۘnCz تiߤk*ă~dk=Hǎi 6glƗbM"7ajd{U!7>}}^^c'I@9xm 7k]#]_GoWw UzsQ׬Pppӎ!6wQ:2Y:ky.Yi]&Yݫ$dGZ) ŰeuTunV ?</f~`fc38Z"Vk/Gl"}WlZ-aHOOOb7}RXzPꕃJjI"Ön-Z@Os̃G}5?6(}i]Q endstream endobj 517 0 obj <> stream xڵWˮ6+Vo @]ؒUMIR~@Rf3g w\?ߏ×oap'?8<\ cre8n-.g. ׉Cnp x8A2L̈ҙ !1z*ܮN܉$"6y磼'|8|cguQܨ{n~?dRI409$jI'J8OW !*{q=m\D^<`p9+f˻`3Dz+95P!EA0(!ZtON&=(HQqWY4@Lz|$?g7 4" %j>ʶBLp^-\pE|p?W~~s$ X4jEDiVD4@~ي˦Q")*bO+''ޢ)~5έʜٔgID>E\F7Y]eEU6tOytOsVW2z,yTjtKRl*Kvҝ*eX>|\ߘyUg.Q/eV*O}s7 vj-wsqn>lxM;-[,Ƙ H2JbHK#j#uOү\ 7 +erX!Nm1tr?OHO:{Ne֧sKZ'R-B|TE̱֒U5q.Ϧb)ݤn^do!~isy oO#w1=YRT~eml@o8="z(VN77Delr懮è5mwzz"S;FFLNJ=Kq{J*%¥B,Ѝ&DμHzWUCj?&;M+ :>4Tlt<2^ >wh뭄?* endstream endobj 523 0 obj <> stream xڥXF .} ړtIꖦǘG֣$)h~}zm'5%a-,z'Dq%b޶_TygpIA-VE91bB5zi`nf3^c[NƱ1%%[:tG5^iBC0R Fjmy=Q+#rCPV~|.:%FЇ;}A}w`s W};V58늆LJ|FA4+BS;%8ݦDWT$b8gYԡ3 Fp TW !"ا9Po!i"hrB*,ЌT|* hpšijr>Z8A&t<4„ 0h2iB ׊@5N>! X##Qy/J (;Cyax{vI? 8=#doDFwYan(:ieyEh"9 G >ΠrBYxՒݛtj{up: L[SDŽl8$ lk${f]^rhbW!%TؗPuB{,lkϑQ*W iZǒG1N\v ډgQY 4o$הxSPEߚVviJ]seP י]C5%DsSXlɮX*M-V?MY{i[W A[q@_si#-4tJ欹en G9ƻpv>A'__,/tdU6䄩sU^nScB[R5,KI/ idXieQj=iجM֫65uPX5:MK焦 &5n@+84ܼˋu?|Pb:iIitlu|g2|2k.\L;(;}k>:3}@PѴ[OM rӄYqϠdX  "A UDLc)80LpWo% `qƑ7\(T|^ KWN0 endstream endobj 526 0 obj <> stream xYˎ4Xj !tV, N23W,@wrǹ.t'ORo)|Vc\}0zF۵s`'<ޮ1{  O_`3l;w!& I?һQ]}wˠx2LO{a&MBhww Re!;w"0 s~dNLp5 7IsVlډu]_q`L0VFĩsynygl+sOg^Kjn'd|~$@.@))gC_J_`T|Wi+nwӓV*OBupDeH*L99HG}Hz6ɝ8g 4 !5j6~x*=؄t Em'9܊SQgD(. ި ;r"*v=jk\iF*=>i$ ]Ӄy4*cE ~]u(NY$%6pQBt C颊]eD :8H'a2]? 9. ;E˱ޗS49ңDss]5;h>hN طnK `<; ia$v ϋBjYFTQF\,HN\hCn;O:C]yfB o0Z=ݔ'7ڳN&+PHx9ͥuvˮlc!Muz'*> stream xڵX6! t`6dIQR̮]d],7o+{/}ko7۾oޗ?ޜG#| R>4&pq4o!yp8ֹ[đfY6J~~?ء.A_ۘCCR##JN]sm`R eU~!58+nq) g\wq#ՙMFlvYtn-ژnj͋$VUyq9šeހoo*wD'}Mw7;퐣IXa\vWWRjqLw{ Z Io:WYB(tJc<+H΃L]; GfzdR?]%T|"V=E?&`n`IX,Z/Չ7WJ9δ5Hٙ zVW@}`m@TOζV#!×O 1d|; |o61‘\ll^ᆯ&P!K (t1]P~}By\Y;ϐgu5X5] p)tji[,75J.&\=BCOu)~giyOFY$J)Vv%4KfS/un5Z,h˝0z5 @ޡjF YPAT]@+hрC ٙRʾHSA닶2Wză|@< 1Gv 0q ˅۟ SEM,`p=޽Of(TACuP8i{W mT!>\\6opDc{wRRgw32 ';}I*gjN])= %b0|G uy`yOrTt\Z|EeMkX^xCXb(^tڀTG%C Yv@)KuU%W7s2 Y_a ~8QݒO\ctlS\L> stream xX6 ~q$b..Ha{T)MH=wY`Nʢȏ"5_CO\:y~ h-Aq2~=8?~{SJ;i߂2oJ'+8/8e743A)XpYh ԍ@$8D#,@s= ؽq!xu8۵|P76]{@ 7mvʌΤ.Soҏ|%93vrPrtݿ[dVgBdHUx'Gx^tYbdedžpDkI ;HVgZss)u5 ]C=6Q j:WVp۵әmA a*K@7 7%OX%N7 0 o*ŸWbaO>0zjXV%̊!  HU]–F Q+-/T~5^\G?p/tA6|\;av<`M4XaR5BL3@TA~Ruyov+r5^J>+  Ւb&9#/ANT3%0e嵊DA w8UohO&1"v49HYųRVf.k>eOx1/4&uDeNT)J = tG'bE"$nMϽ[{oMCoj"J}xC}Ί#޺ oH- FO MR d"ynS9eN0K^"Vuٯ(=l|4״_w5\i=zyU1(R؁/=~s18V_<:/&1GÚ VzPC2n,!n^u$j<닖A qX/} M4AʮNvJ@n6ՋwV=ZRhEhwusTqHPkeףƾ`TNs;_.ͱ endstream endobj 535 0 obj <> stream xWn6+v/,.p[]ȒUMEjdMAB<83CsMׯ8j_\W1"8;w̹{8co(rژ]s1rɑ#p/.G<*ֻ6wSpCR;{qv8FZFZ9^! ya K r}!M̴qq:WQ\omۄˇKs FùY? | B"FxqN A}GWOj9uQQ8M¸M..]ê\P;߸՛vE5v.PL&rSX (}oE׳niꞑM&͆$"n F5|pJ 9ݢi֩TlNcMvLg" S 8*at'dP~.XrSqBSK6 4x}nϧSϯ++ZpљWZʜ,)sǒRw8@j]you.yR7n,FZKCJ 3aOʝ6I¶p,!\w/S>!?B$S&?>޽nQk k\}}\N(gѡV{nj` }Җ6F1q@q`L"(%Yq2r3h2 .")rZvW\6neo^N `վ\yG zف>!UzӿIy}} +H`ÚJLf=Y{ʺ/ |Cv՟u}@ \faq8<\_.8 h;fd23Gd"62c !l"ErGGuC!M~E IE3-dl(q:=ioVQsOXu\LTz),rϪoz>mERtjfI\c!ld:I& f>d C-˧/ɔycYy_vMbҞNZd4R;MAbWO17Y?үC#~0٭ӽ7? B% endstream endobj 538 0 obj <> stream xڵX͎8 SR2@ V`vO{,IQ8' G")c76SM_e|暮s|ߜjcl3r8"|90gPAM748|&7uڡ6r@&z]58k]iqEy&mõA~C|39NgW?FxY8ypt8z+h(L JqiM=؅p_M;Ver^@k~ܧu^ťi'tb]ʓ% 4p>M݂uGA8_0Ex4 t,4|gy0dHTG ğs\I]u"(i"ʵ]v,qNj'܄%֪Y˹ I-u $s)rݩ%k!>r\ \5 +5+mZԦ𾓡i.2QKc'.RFJ%.1uB> stream xڭ6WI"@ ]W7ْwaEŹÿwxַ}7?1%z_ɏe)9`X?!P//֌ϷSdX;vI&SGL~}?8?8N1 ߥԃw ›w,`EB-fX6qol$* QɡZ5?Dmh ,83Vg{;MΝ]] 03&LB X rŔ Ir7|Mg&$NsF2yꗗŽo(iGLuEr+푪e<5FB/cq82VߊG EuF[?_wDDpfx L4"!w/bȟ-Lja؄%oq.B?zor`w}㘣VTU0A5N*W1iS&L(*lbz.Ә|Tw9k:_{C'„aǘ;[(Mr]V^jČF.$fsMƂŃhF:3d{t)r"xnR=uԘX/oȾFZˋU1Iz÷br&"IZVثzȓlOa3dE(e)mv)hZÜ%DSbN)[_ Mdde#xz_G+ՀΊ*D*RP^CHvbdvPaVz^)Sb rwa!4^5ϒ 4DŋLj>pTG'1Yb.GnZ1*TOF$LJyUZd|΅nt)dY~F=$=$|`&:2Kt&Hܓ Ypki(r2IJg#Ѽ~&QQ)_s:.y^O&R]2{c}'&M拉Dt6ri{,f`HZ >#v;CĉOY8T!D/k4Kc(SEJmۥ3 )בj%oi^}nlMV=GwqK5EI,m<:Dꗵ mMCLj<՚C1/TR_OCMӥHө.hs vS+fcqIifqmdk]r׮Ŷݏɟ? endstream endobj 544 0 obj <> stream xڭZ6 yE6d(VlEw_J-9q,ȏ=wGsۿw/_CE_n p s>hx}<{NOH#9}+'hD7$ZAjS"DH7D‹Za4BBT>C wtHpWr,F#O4n4@䖵AViv:R.3COv?oCX';^eM$oȆ7dgA؉xܤZ^nMe+}> ұ<zI½иouY&W퐔ų^4Dml,N0mNW"3. &jd˞2?(R2.zxO[7ϔF[AP<)}-!AI'x|$#qJdHc$E}*8a+b 3)1ceDVrh%)㳲q<#ND&;|x gT-i}"9o |B%gao(p'*)-l^('0663iOL@x >!ml +*&HGVlvpTf e8̘.+UFUyU9vw>"[WrC1F9B9$"eOmJb__K[رQ;P(n% @ g&!ZI ~*Z86,ӭ|cth VQi $Q K\9#~g=z䳤eibrcnZɷ-=| <0gK ЕR澌 ;;µ?mj$n\ݯx;a'n)*ByZ\<ЍUoKظS(Z=|qD[oe2[u[BOVSZh*vLMsgSUmH-VR1jz=Dkx oS?گKCߥ2WC4_A[:MISaBx ]9,ql_lؐj{Ϸw#>̾Gh&4|z^/W:̶@ξ>$uN%ܫcbR ꈟ&q.Usg7u|`ދ[D4cCٲUe̳pn 8ԍ~[º`8^k|sɜhʲl.^ڸ2,mww[ѪQ$\LUrI NqޭțDpqx^3(;ʕ-O 4纡r ݆gZ8_?kHU5E=o_4-w_mMj!T*Σw.pcw`hfvGS NpY4r)j SZaZ0,?}6]{+N ˘GH]4"Tմce~#GP~v zu/XgQuАJKU>R[x\r;Ux|a Yh 1fn.|dHUSHH s>h{7ͯ]zem*U=?G endstream endobj 547 0 obj <> stream xX6 zK  ܭ`'q|Jr8]{;2IQC yffxWccy>>E4CJX1⪊`3NjSТh)׀i MlĤfTC*lUnμ/~=PU宺HPTUaW֬r^`h>)*|~2fP[)o2# <^[NFmy̩2e2սT;xNd8>9qրxaU5^޻pϾs0}YĖc}EFc_,fYdԬ$۪ #KTXֶqpUV=}or3MOsqbl0(rԋH(q\qruVEnR'r3jZE,Ɇ`-}v;en9ZI=oso 5կP_wj'HEuif}ףD+c}j+aTȏ"qpӮ 0H/PC^]^º˨YÛ\~(|fSq}>X!]G 2`"5\1s-JauY /hQcvdޙϴ$he&koDs}hiM}nEŽ|](WNY^>> 6A\ylYl77}{s~[{}WC>eyz4ml7*Ϋ|T/K P%*^(;X2dX2af|Q6ms+4EH)CkI`iOl^/ Iޭ"FףXZhn:QC<{HZ\h'kO7n<wL5upu[4;u(6fфۢ2%Dz/׳oRKVUyԛ#GR ߊA3!KTw'G|Ayݺ:ptO!Vx8QQFwY򀘏JѮk( [sү)f}]k-xt3 endstream endobj 550 0 obj <> stream xڝWˮ6 Wz(]؎UM%JV%{C)!JhP!h԰?@nFk!tdp248\o" /YnA^Ѷb\@Fie/'#xF1 "1hК>*8[ތ8]gn> stream xڽW0 yTB; 75[9q/8iid7 Ù yxf?s6RyfZ $1$``0cύ"k^&ೠѐ\xrg~4ҝ%"Kc\7wƨɥ8zŠXDFRtH -ε~,g#E-:FKWuYE,)lʶ8.u XgHg]-Weyݬ%+ r Y^}/"ԫ|/h>|`EVwyQFOJ a endstream endobj 556 0 obj <> stream xڝX6 q ,H` *E I2 %㐔fwpw01">d꣚=xw*ƫH6U)ƶn[REӘW4]OٵbI)N }4R23>P&r7_EW|YWkTff2Q}ɡK //ߨ9)nѕd ?K]ON& 5ԥNǍXƯpB͂Qꇇ}_M0%;WîOs2Գ4oz @U}lȚE+ִtf?JJ„FT\²kW/ -Y`!TH 6_"FbN*0F~W(k""u7 endstream endobj 559 0 obj <> stream xڭWˎ6 +q)ibȮv))8A1#Ȳѡ3; ZN{?i ېܘS.ލ _\QhďBL+Uaw_mBcc3Q͸KO[HfY6N~>ƘeXepI~L>j^Џ ([4@^7 >$iH&fk9*o $BR7IRk}M-|=' \2 5ۇV d~>LhI_5 iL¬`rz~[ yUy.,e{vXW K@yGP998s=`vc-h(nQӪvE1 "Ɲ.(A8yO~X#KJ Y R^H.y;dEDR Ϧ 5l4dEí ʰU~S"g5{-68Eb%h$O+~BK7rf V{h/Bk]dcWDD(S'z78K;yI')FRa,ua$EIݱsjQ1wkd }բxYcX`VR/mNI)4:k9⚋"14FY+ªTo8e9={P!NEjoM[TMsDE7]NQYvF{+1klynW ZigeAvp9;JwؽmhG.b%bFz@} c(q|v)<׾]3h}4Rߔ3xR?[ò$ endstream endobj 562 0 obj <> stream xڥV͎ )x0d*z[CS}K &gڵ>N_B_=}'y/ ť5^D&% IG$ίI&aHDHhӖDh%[]?((dAEh׾ԡrVV##F P`00W] U cvt+?W|xݺ\tF@)MQzw{mL)xziʧo3:??X endstream endobj 565 0 obj <> stream xڭVɎ +v(Q"%rԷ(/9xz UQpJ*+/V1^˵B׹jjEsu"i a/?`2麆\ kAnYav/26C Yc1,-F H]:ӐUM 4V=bxo8&cSKh&Z6s8O٦S LaOBJHJ8b,0ߕ~b8ՐPai\Sa㲌\K_b\]i?}Ԩ72D]ʻ3D$fگP,Hq8 0X.. YVXkA= B肹xM{u=0g? }],grdƧA &}>xKn)[Q.d6 oƕRJO7@ޅDl[('J_Hïޚ_:#Mvó`nhE, qKH$¾]i7`(XX`;O SG2C!M\CA"RC`!B2;DR {H1{&E;GzKO[@ ip 8> stream xڭW͎6 )v%Jd`[у=HN6.f;񟔇;C77_s0,Hv7SJclpY\1aq7|^q9_F,Åy!] F(Lj$_?{}#X8ivA= eD ^(ֲwӷ@YFQٹߞoGo@wq0_qehpg8>3641= iJ J2hxV^5YqaBB ho zA}Ph$0^lqXD݆PfoՈHH h-;Ul8ss1NCBp;sbKCyBcɿ(; ]P%;ïe* ͩ~ cjihYQF /LkZh5I(?oS}ox␣I4? -À8`09}Ŋ }IQ;!LXehzALeq3)!:YƏO®ch|Ym텪szE }n|˂aZLj щ9 cis@y(3H^B۳L n2a# ,boURQ@C!N⁽R0p|r{'oth޲T{szˮUUc5\MN 8kYb[ dj#SM쾷YlͬdYmHe7tenoFfjM W9[\^;BͽG)Cw. J+ Pa jzDG&n{q[I^ rqZ&DMʗJM}?T&c?{pM> stream xˎ6ޯĥ20ȡ@[s+z)юYl(&lHO韓;So|_}/4O1"zn*M>|/~ :Of[Ǖ9$Gdqskđ憳%jya! qHH=9|8o8{Zq ~ARjϰ)㐷@F#(Cx^֞e +bjXETFY֚ 5Y/5x\=Zn=:ʕVu3 J<1 ʇ>\ѿ"B- gР|$(ס:M`yPVbmtw1 g} 4/+lHCpaj->ɪ4w|b;ƁK* U9=B $;fS% 8aDs즭8geˊJ dUL&2W5tYvⲷ# øBF-Dz. BiPzHP +ȩ C=Ћ: -u@Zv'gݸ$|bSދIR)Nh] K]tsRu?+b"]a֢Bg)A"G&$wGqS7-5)0nBPc7ػ3!޻jv̓#[&[xnCas УkVш/KZG}Q/&kbt_OI]*D5Vjv_JBD.q6 *k&_4їf齱h - m[LjA!Qk}Q5*Z{~=T0")ABLA1UWJ5p/U-4=s\4| I?Uzf?KV堈)jԂɽUMw_-IwSEJQG)C Qة$ы9}ʤþ~+Fqo6f _ѡxНvKۮKWN!={n{~wtWN;) UoUŦEJIA(pRn*j_a;m Hޥ6w3۬?F\)gkcb2#+m,U#zɞ:{4:TDrky"4, o,g]?ޫ]qPrٵ˙&jg8:ZkrW6ב"[f7OwA#y֤WF glOR4o  `=7.ZEvz9*K^g² <^k1dk5ZF7n\sIAmX^ȱbrg0E§MrѰ^F[nbOmMWۻv(M@t=P?z îEL9=Vh(io:0w Ѧ|&ztbg$Lnj "_"eɺKUR;f~$5qv:f(({"h;|n^{H黠xS_A endstream endobj 574 0 obj <> stream xՙˎ6 @ / []NrW]7Hb'h0#xltHQY_ލ~oL):^;a98&p,. 2u&9pI-POlÈW}?* AU) ;.t2s?Ngz0S=q\Cx4N fǯeDy// | O"9x'laeAlWl U@$2_.Q1vD/"ƌ]0݀8A?P*!Ai#Y h\!Y-ӥx{>R'<A)^6OBр2`@{@ZZp~B0BA վ Ht6QH$# jHc^N(xOClS&14Dq 'J}W]gDyb 6f8; Cf2+9g! >QaWO:JDbM'NR?W2Qco]:p}XD> stream xڽWˎ: ߯0Ȣ@[]NUMIaɱdZ\"#A':'_t/gy~t>CzQ2wzg}wR{]߄?._QT ҇Ek, Qq <2c8P(;ke&|&Y".ǾziUU&9ZN/@oZBh+8Y┙p>iZ(ĀCL9қ)pg)fbp$.PLO&ǐ5YY!yDt+>!ЇdL֯c5bT帆,nM!IcNH#}Dl1bp4u [EFҡ>z#P ǔPA䤮$rH{T9עV7V#FCcCslV[d0 c}7a2䂭˒MڹXoiW‘eeKA\OqޑFRi@dZc `b)רּX~R g:x͹y$vֿmEEBIUn]kGRq<RdNu Qm>&tR¥\Sܯf/+Ž^b" k b)wN?5Mh2 =tq͢-LfҮ*wakzp9'nyw]|׷m!Cp):5QDQVF8 'f]rvg yyK%ZQ\ĵ%YЫܕ 1S>*RIN4!ӗ[T3AMSw|܋z0H9x iv!6.A ]ɧ1Տu_wNlmdeNv3(ý_QL7* HkUVqVY/a+Du BKA ^ endstream endobj 580 0 obj <> stream xڽXK+5 +tTuHN[V,d87j2qΙ`r?q3??1"mEfwvpqwجdl:kr74.?hy81kwp,g 2V罝+( ?R%vvᦁ,qzHOj{kI)4&;"7V1i՟^ò=yni*%ZxJSٮ. $k+t&k 4uWѿݮ&{TS&'3wd5 endstream endobj 583 0 obj <> stream xڝX37 ~Otk.~Ot R3T)M(:ƣ]{+%Q#'}RO:-BwhӯS|:[=c뢔v4{XfNpCb+Yn{=[3m,nZnSϏ'Y;#[,۔~ŒшO2bT{(Hu:k 0C- m[Y37iGQ*. sƼ'ZuoʀvTH"g9OfnZY0 l Zm>?}DH?C+Tn/{:Ϲ<_B @RyHBњ\_Hv$x} 8PM[]i?q-5m%蔞tb2#D g=0=Hx]}MZ};/ /"vAԤWd!/*AyD^mR+zĬd6Ϋ+5 &`J"] Wk *mٟAaVreԇ"wnkncID*53 Vy?)g§8K¯'ckjP_DS|T@;wܫ :[~ t]ܔΣq""KwÇ|Qt5+Y)yA(H2F_*4 &a2,B)uO}+ٌk,%ElB$}9k.LCV,^+K5Hiz_[:D{'NѥGqd]>OhB1~Ƌ(T[*&M 4Gھ]ʻ2I~M:zoC %o? /3M endstream endobj 586 0 obj <> stream xڭX6 ~u C@يcw_J8A9׏I3_E-ӯ_iUݏn#֙Џ6tka?hco fs4uya.Ⳗ""p)4BUTc϶Fb꠷.v``;RPwtHehqLh4/4cZ]h|!oi,,yXIl)͡$m:No_={z0[똛`PߌBH BLB).["e[!7Y288FQIdvqaUsMwn42ouxrݴ:. r)JQ@PdRV,h,XF*ᛕxǪjd [j >pNWtΎ`Lh`Y%UʜWԉ1ă jJ~e= Y20CP; clibWj݉U9VLJDM+Qʴ!SU׊;:/xV8YKeyq)PYk'm>|3&n.iP# ?i=3#Ѫqn3!lv sHW[mK%aiKEBIRU62[(X(գĒ%tg)5ָNUŢIiӓf5VXqaV)u|O ?=C!35.I~{rĞ.'oyс9J6Z?7:)F7mB9)^xp֡\Ucr#Z3gNz-=@!btJÏRMc+rXUaًE=NidXޤ]}9IL.kb72x9i|5f+GW'f* X`Bw$\[9sm?-kKem=<|ᥞx ,J\bi;W^4?-tlfO:˥XsC*ыE_3Fy]觝7 ;=wEzATGEvwn#76(}F}R!`Wv340Ů+ G-݋p*:]ژfee {QC?Rc`Iߔ | R z/gFګwXZ?eG_(%> stream xڭX6yИ`g&3#:ѳ Ø!(uTwt3gt+ۍ}@Yi>si 0F߀!*!fc9ØV1Fa?x-4 W *y1]6ܛlHSc0i(sxa"`~[aLˑK ߋU$V DMkڸyRܩZ;/[|i1XIǶeWSMΦ:˘?d`'C]N}_ ZÍWh$)$Dm;#W@/yN߱wS Ku4.֚ȉA5~G $''U-1f{ sdۜoDvT TZr.ƹ/g.\sb+0Wyl~ӑZ U[<țVXbgjtsNgwt̲s[¸tZd){KCLNRaG{P8pYp'E3d.8M=I30Ħl ڠ Ou5N`J~7+7Q$ch+ZAjaIbf Wo?u_"IF놋f׹[SiWVy^+XF"g4?/X\}sOY&2ϥTO YGow(8>a`C ] `J=xfzOzWzOQR2EeILa̬ Q&c-XfkB4(. knڻapQe}(53 *1DUVՊ,4I%Dً2೸Is |,뒎;~35SOyӜoCs7vT-9srQ9y NZ /aaXlrݓDŽ:gԯ6io"s9> stream xW6 ; H` =JoBJ,yERߝnD/zƗ2~w=΄ab7iDF=i^hX@pzClA{l3.4#>~#@ GOpl&ױ[70u}C>7 H _x 0Q}{g1{ F+lLޫ3e[e5pޒ'bq϶0ǘM%)j-gX9mQ | Ja8&d:*7nƈM "#¬W:8De"*: L84E~ʶآ䕵ł &TNscTT/bdfɫW>)s4{PϾTuc*U)D͈NS{ҼώZ>j\QET9$T oEƂqJUYyyM I|nG[Rh}dRJAhcR/Ix}|۶5pٚV5.֦S}}i\ KX|{#otKK:[\ThWM‹MZj7F,NmT<; ޑ}V+ _sQ#2_שӵzW{0T@cc{6v|2tcC>|s)divO}wC&; 'Hf<@ߒ12|T ^OPM~gd%lɌ罊ui46 L] yNq nʤ&P&ڶvluQ|QHv7Fj7B# ;[4[]t@ٿO_^|U)Jʶv{xrH!iwJ\WKpDD缈eL3%oI%Rl̽G+.*7V։2Pm*~_`Sj퓔/ERvT/C.Em+_(,Vhn*mXQfik{h~\:+ endstream endobj 595 0 obj <> stream xmRN0 ͮߑP $@CJ(HbSQ x}d=Qdھ|YM{"ҎMj ,pv!fYL2NlWyZ.{LL&4).Hy(}֑픣uƳrO8A4VtBnXrz)W|!lt-$JNAܺG+9N쭒/vyGl3Or.{!5Q#,2m> stream xWˮ6+ffF$E.B~eErHR\{ <ϼ? +O_p~ Mp@;|v_pk0Z<ObUe32z~ѨK/TPI/8e&ldx*=.YUMϵd*= /ˋW̏ ʈYF(߽ԛ^RP)s_TˤK"j44US;2><U"6j Mظ*.;ރ@d vq4SnF12|T -[Ix *R AzڪE|p@0\jRX"@S5<$_5#*5aQ\`e۸X!* hVިMP.9r(F6l-AN gKbQ&rfܔtS ˯H4@TQ#5ϳInJy o{-NzI;ϛ^N K'K9HriWC&)ˮY2Y\,Twi3T|4Gx(0}>177kh!$0N^KS)CL@,3ݔmG茏O`(z#8GUwRNlUrqW+됒6#u{5fC^<o<#-z?<Ɍ#-a9]]3ɯ1O39Wt\`kcE$n>uI Bs 42}݉mntGIe> stream xڽXˎ8Wt%0|X`w؃,[9jQciJf1CP#uSb} ]T֒u<އdP]҈<.]?+4Yz0Z2 p24ϗq8Y/ Ni& ܉tG.,)]F@97'B_$\ӘׁF7C@ Z<,v<1¼Lُ}? &Wt/{ha"<3Q%&(,H=?ўI]3۩7rp],KJ)MU *G`ťgĀLyPk(hlG}` "n!XL8C&,"ˎ$ami{ qg* ;[hPvzj$Xd"#*qs nQƜ*xq 0ƙ*mf Aԋ^@02>Jb/Zљ&S+VK ansxca?GW~ {Z*lLC&YIS 2l08֬v\4rH l];9g\Q,1iN |^r#Ȕ;mS!hjǒ/?Y nQuvqBj:4TѕK@GX9tcJ a|ĝ3JWJg+Up^?a%жFRgrZfT ' Abs&t[jǻi^ Y; 76HUtVr. vķZ%"ʺv|5q`yŒ{Z_9rXE )naK_ojf*Ҍ)^G^ _wJbh혏n {{O!E&y:{lp+93f9A9Pk_9ֵӵKց.ֿɾ-X endstream endobj 604 0 obj <> stream xYˎ46v-zHfXc CUdfнv:pfk2ft~GxOY9^ *0Q)M^6[fϧ6o7m8𖰷>_i|ޠj N οnSD /o;.BRY2TAc:px\˯ >Tf  an, RYÒ1ٔak b{kl@m{"vx,iڌSp]bo?j+0̚6L!iXޜw>Ap1JM(rg͕ AM-Yk{ݯV$,_ŝ\/Bd^x˽\OKϤvDXd8zk-ƕ{m5J6VLYG7ٻ0D r}q1lktyqy@9h˭EYh®,b_ub#Y@w.#wAZ֕ifw.b4\ɢ@@_IIk/s 9,9rf?U@S,fK9qHm.YP؇K*#@79f)r.F/Zepdb!aνr#ޥB J%P$kٹ)6lsRzdűw>4״D^:ֻ^nB.aQ⾖%; ga endstream endobj 607 0 obj <> stream xڭWˎ0 +q)i ȡ@[=8CRdq6kck(II3tSПSCFs.t@.`+$Kfccu41*Nceu:xd;z&G=@OPy+_-)[l iME[Z@\Uх wMOjC&W4\AA +ynCk݄qLo*(R0c^tuQZ!at:1f 2 gTs6(fSe=keِus<+aV57httyY ' NtnVb,z/ܲα 窉I6nq;m#|r W+*s֠1yJw%WD51 gI]qy(X=H1 l˙fh$KŽH~X#"#G26^UEcÃMܗU6+mt9AJyeFMŘ21>/=Yws%ل[6nc0>is*)3qlll>=tqgޠl, _)\3S0Uux&!*Z:Ӯ߬X}=jWrsGLXe]_9mm{ƨ؃s endstream endobj 610 0 obj <> stream xڥ9F0+qO Lf8xlO\]Gw"%3)vw1 i:L௟xz|3C6&xvY` =^c.Λ+ x?@z(HH^WzxYA$RI! A]LlQjYIo?Ly4ERC8d1o+ EOC&Y8fȧa'x'Ch^́~2iV AP,(vxǝtQ/jGѴCѭC1؄RVZ'«$dJEI򍕃«@$EbD 2I 2h .\ݸr|hуdLɥMkwR2܎2ƍ %&!X%ʣq\0Gj[]#>JQL8 |ҫ!p7A}$G֒2d 94]wP:?'VDU+ij(#u+:gRԈU ;#3UOj^Kq^M}l":yƍ,/iQkk9#;z cISKU|3v6ط$2^䬸Xb 7nT@vEI$C1~I=gP?ͷe>~]0wߜg_xh ̮ V%%M4Y6Jab/k' `SޘX@Sқ(IO$ ^aN 2X(9V2%kQ>uUG8(2.h:|-v\G3޸-*\&J[po4zm%x .CV5;wR*S1i2$PPpݾϵP/}6zdKx_Sq4QfP ,jSv.<56;l幀۝Gm"^黗x>y[MfQpBv6+d^޷1 f /eUs_ Wpy#jS'nrb1.9Z>3&{/Az|rA{ {3l\wK; ep ]©)>~5] !Y_2Ukys]/-b%!Z-8h9 L Uv=#j_7+}NbB|7xɠW3 Py0xZdКah.-'mw=Ǯ endstream endobj 613 0 obj <> stream xڵYˮ6 +RoE@wfWt1/gESd3$'6IQ< b#'/ _]_aFڕ. T՛ g, RIh&=K>YS,Usv ؁.ش`pQ~b))WToCG$mBgr<+ IOgqefL C2ɾ3&[R%\pjR@RJ)Sx5w' SQ7m h`kQԒ]EO)xr)&"b1"5֏\O$VQV4W"PͽhJU;brc<˂_f7Uq}ؿJG%kҝ嬈~cV;J"O%(wdfI {1JoRԚwh[EݏzC35JⵕG4ߒav (ǢV~;QEfxvJc-pZe*\<+q="_)L:g#ͽ%ljP[J&^CZ`@''d!6K7%sTI ;!f ͽ< ;}IG{ǔW@K}]qTUnzE4-&V,%ٔ|VZ[襪VW涫eff&mjZUHaWε=ܗ6HgNGDё{YIw{V5tv[S?utXoxN[Y7:u:r.G\AEZݜ>lP!=p.[1E-/jyQA(E1ܖzt%GmL_?V#nvq.X`p[ 2j r5]@OՠT |HzG`e3_^ߑB:H2;IQX|C T)Fv&vHj ??A>6 endstream endobj 616 0 obj <> stream xڽV!c%kHItE)R7}[D6y3eǨh OWF$KV&urF.giL4x`2=<4'S3I8oXTNc\,Y&?/(EzS@ : L#81D$,eMh=ՙtHIXlI$x%d )& 8'ka@uJg%an> stream xe0D{b f׎/)JHtHE10N ٣1|ЇMkt3!$U”29Qj(=o.؟"fL#K6Jc`lHx6yAu29,8ƺ fdԒ$sWz}UJ endstream endobj 622 0 obj <> stream xڕYK6 Wdz@0[у{R/Q3n0ERI]s~O|.n~/9ꗏ 0_Ct7g}*fKe33ֿMٿ}wGZ7=J#\) K\ޯ1+o,Jt{G],_?xROGuЗAD\Q|B)Mqi5M`e{;n{ -yX>D lՇhMYRWE`u'HYLȈ8<}̢8]-F˅s[-  G6T}ZX? -Fv]WwF"} NЄ)q ;>L%&`9}F'qz%М[*ݞ$pS~bdSУڒ5ZpG#uѽm8bA}4iUHW(XE9FJ$Q6[u=uErs%6li/1+X`d擉4&Oژ*G[F+=U,67!Rc&S=. mJ H4lJϦ_R$$6'r3MNܫ"Z"1 G=/izU+voe3'<s .2G4G;X(W9 xV}` v|Z3 0Fx@_.?sT˦2q2Hr:0 cܑZ[#J@q\ChҚ;Zh!#;7ZOak/tj P'UpBQӦ\ - uKGxG2RȟM6qb(3݆v]+ผ0꩎)UZolFq~O>-sHL"İ63V`>|UʡcE'SX^ͥ-vF㷮m=dhDY\yB4 ,%h3QSmK>2OEzė-)޼(q7wCٙzb^[m{>-%=I R~N*k6[&.|Dx4zcJ!Kf;7~RaY^Jf ٖ>!a3ziLk ځYnHǦo,`DenF&Tn}z[=fNuf)AcrFO_^TC~7+'70Dӫ\gt!ŋ+-~tŅj Lm0.thbqm^Ppvb}',^FI{š!oH3W:㵱oB~r~z7sW (_X endstream endobj 443 0 obj <> stream x[ٮ}Ẉ`Z: x!ADЃ,B,]Csj6p#r"粔ԅRJ]+uB+; Q\c]ЉS:2 BM]+2v1'%aq-]9AfpQ \b@] 1.ExF)t)إlqR*Ph(cZ\9w"`$(.G Z( 0 *]&`A;3. 1 `1CsXlX8N#b'KB$<G2|3tP '+aE8jX',HF,Ь@4WS0)```!J=4&Q,q$d$ QNx+yHcC-{ La`̄Ĉq[I` D`ITLr9FLA8Bb ú Z= = J6cKў.M i6F# 3G|!6~@:U8&P 4m]M BWKB*!qŴUȜ*6]ؐ|E<1``ds 5'b1 |ls5Zl81"HGgbm6PbmLcJ`gM͒VR$6Ej; ¢Lԭ`cLbGHMd{>bm2U튽s`U`#+ȳ%>fB4c6WИ-j1fPXbEJ8a[T22TFb"HOFlClY(6OYcElGy`Q102kxAӯΏNw>>g鼨:<}a*gwAٷg-g*퟉ۿ߭o1Wj[D歕Q"LoL??ޝ>y|7gӳ:}zۻNx|3ܠz|}u~{:}oOxu{G?o_p{z~r#x|-G!z瞟[n~Olb)CX?VА>j >b?!_7kC}@~w)|~|wϸbhgW|~O^c8<>޽S'rp/vߘq2V.& ܗ9ܰF3X1tPL c<ɏ绗@`iJdV#{/2^̷/:{76-ٷM<ѿ})W4͏*_pr.tμ@-Y.β\TP\D:A HS^NmڍY/Sb&f䈖1#dZ ]|p0 Cμ 9 /CN@!'`e903( !<3A`$q]Nv )D*qǮYLd <Z1ًtQ+/2{流7292#c/>2َ#W܃LGƀM|d GpP<]UD CcgRL~,IM抶"Dh/5ySjm 2f|e.v^͊&RvNUbQ;,;)'jӘ.lбcQZ_To9NMjD:WQPY_tZ4w= |ӣ7=15L^04o?ky\\bL4;y֩v@Ց"_<> ntD}UPoeܻ|CAx*@yu1껞Zq?ty(bk]Vdg~I{\9ԱrOÃ)rpa茖vj{m|h2ox^l_pOw)L556I.&{5/ryѯi`J;vVdWaaKҍ+V+_V抮fToRlRݖj{.Pʅi/4C}OͼR\ւ]aivNƔ+4|Ye#jNi`$c\v],ȗ/lM-@B; ({! 5/)5XJ;IAN"7'@_c@4cK*7(%c;Hyz&p|k'S)iYmٽ$=̯%l]h^c?ڪwkUVf]^ ju;Vb~UyW%8ֵ Um]q| aYp+۾ p ׵X$+ͺV$bH5+E^xR8,䤗r_m endstream endobj 985 0 obj <> stream xڕK$ ^E , `]ϼduw>",ULBXv#Gu:ŽvG7!,VC37<Q=B!),|1csz >P|EOy o"-8|!bjȉ##C[Kl 6BЙ>Z€;#2vX>]¿h@[_3Q3LEg3ȱkGp]AnM mc9ʦ-Q%R_|1* 0 lH_1fჲ_@]yH'bd:HXiD(hdQBtd@ X1Al.&V`yF`G:D nieN3EcyrHN&*GT`OZMlp ~7j, C"geBPnI.,$ԡ ʔL$e:e \E2)$,Nc$)Ydy`9 "$,I&lQg{hb{ds6:X6(ڼ}vBp>: L?&Lb,h):`;`.f2>9 -w)`:N4.4/M0̭9%knL:"R`j̬3 (HMR'YLk1~Ֆ`J. k>-,Sv6 %5Icaldx˩bYEH"YcAh%?Ҏp?w'i4OC3]Έy_Ü0'!rv{_Ndt <}s` Ǹ|d0_|>ck2$F8ed* ϑ*ku?gÓAl{ 2O-s&J?|cߌ2/Ex|k_FBqg>U>jG#saۻŴs?.CYE ގ.Qj2-D_EY1W V=Vc+xlO**&^1Lܗj=I @QK||apߟTӨ4V̯ԋ2]0VDPiHAѧQiDuf8ݞ[ &hutU \ק~?C']^và20fe8=J C H)x0+}D?##vȹlC_.A7r[*E֪Z٪"[QdlEWUU\W z{s6_w]xV=l|UP4`x3twYv/s+iE Rn pn}xU+>?xv\n=l~mwƠ [ퟗҀmU{"V4}YËŴ(q z"+^iHqUC0۾ dze~Ë.oݼ [W endstream endobj 986 0 obj <> stream xڵ\K$9+|v-FZ`hV3ege8kCO*3_a礘V!$eAdTp-(Y [eO~>gT:YY׳SK+x=<^G.I*k7i9LOWeU4xΫUZECx=#n 59Ȉ8 @2>h%*I.244"rR(HN*qz!F^YKjHFQ}lF8J$2Bh!*(Gp(HToMC+ϳd|D},Xf}͑УT.#@C534"2"#("=мQƉٌI.&,֨݇C"T5N%}^O4E[@Q9݄͢Bfr)@" )S;jH$*H."2k(-,=",Ui!2j\!&oOw4 Hz|"t=F@4I|ABP0Ae#C ?^Cf^8 H-0]A66汩;cd7)jFs7;2c8ɸ 'lg17{"L"O]QKų x K{JŞ)D<3(>WYZAEn#e$ -:4}tzzº ؞7K=aunYyw=>_?^>~tcno޽K)6 Oy)56J'Q}R5[tҭ aY',LGOzU,"_N.w-vSP$.9+2:ӣSEXQ.K{AK$р BsewbVnO_w-E9{^ؿ 12^ haRR~Gwuj|VYia>Wun:+lG?`⿋z9]Xmdܾ'ri`[=MJc跏'*f8]L:9Uӧ|ďV'WմziPj 8%a 0DJ6+:o@s-5}Y: X6t@Rvih6~cc }kn+=OZKp]+*  AcUl:TF0zOC ye.:=UY{(!O:kj6'l٤ޒ˅>Je  q aB'69w[WT`t;Ծv2nXY` C5oJgAY fS4 nWуY!_AWt-5v3vr/ص u$ӆ-MCHa;.W}rg!툫#.ujp;.Qsn8q< v>c=v͸CLq1w8+v-&HOWoNϸIXƺp2_@8, >a,vB jG6TEq1my=:v-þMu&Q!M8uC:toTٻ6 ^3rg 5ep#MYݾ)s7;si9|22_/\ZңңN5mf9 9o\6',K)bIQf5> `3 &krGXߴSYeݥ2QK;mC] 0|\y#|B[-z0⡴KqW 8{.JA$n&=VfRR+kI5t jZC:熭R{=TA 2;C2+%Xd)K|&vk ,v&C@i%Cw5r֭-w!X72a;p OI\by?vo[slӕ|s|}FD\<+XS ;-HM}Eޖ\ּ~UP{p2N? C |9X0A7TTr,ΐB* ZͤZVՉ)~0NtdI -0dߺc3)># i(>7 o$+AVܠPxSm|`n3ja{I#JG$RE>ӡx@q]qYq#XqUqSqQqNqKqHqFqE8)I/Cխ՗U*_qŭU\).V!dVגl3ԥ8_(؊W):&"s/*b *֓bR&TUb*JLG(~O_$Tꓩ{c_QiCy맩[Fi;*K/̲FWt1>Q=2)'u_/BW`ɲkXV ^mZ3!o?N $qq&+W 4#;25.iAzɛ7x㬰A'ZIYDt @O^$9L bp8 {J1j3N65*,IxF5čk^g/N"]#TM$,k{WYaX-M[:vDcR\Dq2X#I\ExցH\A@<$!,$.Vb.@XcJXbIkTZ6XXW bIkTZ[[:`kh"oY4qkAm5C_\T>d`Ѧ endstream endobj 1167 0 obj <> stream x]]k@s,·Bmw47z (s_缶;s|v[ġswq5=[(-&o} ̟:=>=?^5~^Jy$ěz贱N,1ypW1[5ݞkȵ(f|˖Dv2HSNT5t\e,bYOmnqPUݣ]JR {&Ux2IKg xF%(gZGRkUJ2Ť H"!KP/A3K@O 0MN 7)HWacq4JSFL #!A#TH mв@ܺ*=RPq-9}-2Zs(Vn=Gl~a87c*[K_wpA endstream endobj 1168 0 obj <> stream x][o@`ǒd0TVՋ+f.R5~/q$rf fA?}3ޞocbef|7[OVyoMǼ{5/U|fw=uNVRᯱyW6~Xߺzx)v.}jO * L5nh|2' 3)A1<2*@K!tBF/@J@Q%&P J* S?i3OAK6}<.a*ifkI1c@C\CDbqs<[6M҅*I&sTJ *MҗR* CSk!Dkkպ}B/G$(,qj^~p1nݯVs~> stream x]R]o0}We1K d,PZD ܋ns9r8]6Js98gg[OHM+Ϗ_u0yxiin7 D\*`b}9Pv_clO,+w\.6kUul͸E('ț)38Uڀޔ7+bӤY6}Qno~Cj؜K! =! A$1!Eh3;:ZB. EvSN.B jNB*ɝLѷ 'tۑr4 %PIRZ{VtBvttfw_?sv ֦"p rUVm>* endstream endobj 1170 0 obj <> stream x}QO0}l̄LqS#[+IZұ{==HwhOmn{YSԋMK{s55m[R4mݟa0. 6B#D2!BY`!O5e1Bq< +ҩP9o bP Aru*sg? \n6+Sr([- hķ^c@wzi`?ܙZMLV 9 ۖ endstream endobj 1171 0 obj <> stream x]P=k0 +4^)%q >rpc+ }=IOoO5:얠z%mTܫ$=)x'YN7_gމ-_N$9c66qaQ4cG8\ȈX muG7)qRavDʲ45AvE?^yhR%{j aۛOmp endstream endobj 1173 0 obj <> stream xcd`aa`dd r v 44 l2 ?d1g!"Ћ?,OAD~j@1VyRqfnfNbs~AeQfzFFcnjQfrbobIFjnb ZRaQRR`_^^[_nPYZZTWr-(-I-ROI-:QH30129|e֩rm-]ڞ!>ۢE 17Ai}3]~T= bǞx;3y?.b>sWfܛg1"5 endstream endobj 1174 0 obj <> stream x]PMk +渥|z nCdK$+4*&uf|dVgDFŬN 8)M-fnIF[n|5߬mˊ7 HwHYٹ3ӣ"gP\*̀q$:'8]i&j/Ψ=䤮\{Fb@ j(nܑd'ԗ$ށ 1=X BRhDiYzo endstream endobj 1176 0 obj <> stream xcd`aa`dd s v445gi2?d~1g{I "_ Hu PX9(3=DA#YS\GR17(391O7$#57QOL-Tа())///K-/JQ(,PJ-N-*KMQp+QKMU]B9)槤d`t,<3##K|?{6?TΝ;{"Ǵ r]]6llnni$0c'vNgF 4WΛ3{Tu;{:9['h1wğ鿛ʛH6Oj.3s"_قSM^wTv9.> stream xګOD endstream endobj 1180 0 obj <> stream xy|U7~ vAIh l%ipT@wAq̣66;2:ctq ]y0>NUwWW=ssϭPM_&G6o*ůfݶwE[#.\nNOq`9ݯ֭`ES|~|N[tѪb| ٸ,$3.WaE,39s?\v `kX~sX.6H(J{Z c00!goz<@ssI5^xw[ř?'LHCBZ+uKf;# 8J<ĎȯkS0x}h\n{#ȱ]QgmOx n$G:on=]82285: Wj0 ̈́p"9VA5+Z=˃\ $g$!GnrKW_ \rE^ |M\řI&{"/Nzr.:E7LEnQfهk|59yjyr̨vzyrڳvyjMXȶ߇kֳOU{^7_;'ikѴIu-cȗI$(-"{_5!F߄m&<ums`h\Gdcޚ.>BA5-a(#s CrI#V;؟mҰ'iY zq WT\~'<6_[HI[[x)jHrj)&3'ݮ}LPG·۔p,).R^*UBC*Za0z&T3ӘcJP Jfnm&R  !D#D*Qc, 3@4 ^zIsHB-n&ފ'_ AsYJE^#g Y^ktQӬ<6KՉ~7|i4$ [v,f?v 0ɞ@uD|ĪbթL1 c,?X7@TTv0!a6A$s'ⳁw:X~X^hA\5b! :!c|DDcrR, *{U}!@v BX'墷MX L68xJ,pZ\jdV;9 "Xk7UA6 vh:$LaϘ\3:dcT XjR!"@|ܧGTA./G"/-앷 7|Ǟς!E/JwI7ŗ/Zˑ/m"̈́m \:vt%nVf+ED~Kˬ5E Nӄ5򴰿J`Vz;K=ݥI)*N;ƐQ3C+>tJCtr␧jf"B`s2990G{;Ht; $*9  %%A~T Dcp Ip1lt+/Jl5W~Ӫ7):=f{urMpr_%;"ʵÍ4I;|XyL6^O:>u7az(7ZAja oۥ2`$ҿC\!Rq]')m$G6̶e8&htbM3CHkZ^οIo &0vHcn/h1)ԢcrZY9j-ӋzOɃ=a. ćjt FٗA$,C03/# ~WSzggjt@}{ ۙFޅ>>UxۺǷloqHXGԉvhWd, :I ;2E\r} Bzwj՟ #2 d-Tpb6Rºq  yWN܃E` 4a1sA un_!p r ȠeY>Hw<Sb , D: 4%Q[KHdXmG}'cը /#AT"q9:6E"1Sdp,հ .P Th f@taijbk~E5`*.3BXV7m.^@zy]tw:rzAPzz=FXI, R)"c1 礟38 Oݞ[9{CZݚ]={#VZ&] 7mZlixmO4yrSS&:"qju"tjE2܋1@(s0 !Q oXrD`Zd{0߆OoƝ=Bdk쟁*nhvw9[ i2v&D\%FNSmJirջ;q36C}3ܙ|\2W/Zes%ҁN:QtBȻZ=wRݩHG{?F#:Hi/D CX 2?/s~3_3ߛX5d9';n?qߪ+J?֛W_4y,=Htf#"TlUrU\ 4jUU6ζZ=5U Piu)*+%ry< N (}bq3j|ODqGzWtTT=q1N#+)vS3d{6afe3 3ʆm$]%s65tL1tR]a%ћ_-\HdBU؆ܞ.wҞE-,+7̍mZ>{'P 4`8ј5iZӫԚ:S9,e)u:)ԌG)h&G"qB(%DcF9٢1d >^IQxi\7}<9WÆ k#_meyuJbҽ nBR)=bOsړߟ@4Fmp$v>f 0uU׽z/'kPn^8e֌8wݳg0nBc0P}VmӤOۦFC{U *~b&>H0Q*(b5jJ҃UŝMi.:pv}ɔԐu(L #7`yQwJ%(n+I,5%2!cqQBD_*P s)}PzËiFg@le˴t8qFő1;&!4d̒ȍ{W_I_TWMƗK)5/߾}CEyY9l]υsc]DWo!z&PJ`#ՄzaXn~!FxupjePr`aٳRzsp>M+>e` bo?d 2Cj˸̚`eពo,V5εw2h7n6<'2Sj(\GzLd& pg<^:V>NɚJv KIF}%P r޻Cz_/_v%4T^ڛtٯ[_3~Dw˚@oC7 ~i}y2NmC}iIuVZ6֚ZPϖ};./Jq];͔c&OWt&EmSpCΐRXoή7s)6D+.\che.O@ús~cP]GtyDfnh)}04+M3ssf8n遚YcK#,󖎟|#+6DPEjţ\dYilOʱK6rm,yAPhҬPEr>8M5&JV9X0S0u\+u3W: Ns\ibÀxSDpSn栉Mb=Śqa{+~Bn7,ziQ) 0_İ0Dr&AW"e&`(Ef3 kG]I&fXKFmM 7նY4bf۶ʶ*YxsVcȁxwnG,BЧ6>Ta .'̼3+dҼ P2vǔn/o_ ?o{{YIw X>#/mjNɳ_+oȥLx1*V)d]D'ZIfNw9՜鎸ǥ\& 8i@$0VkKQlf{|b"VY78{3W*Yo5ga&MrZ|EHycDUO eU:">ҩ -xIs<Ԣap`8W'{qXH͔GtsDiT&DZ:,ĴQ!##9E1Qs6lЉwr3g̐GGgE:AmMP!Ȋ6Z+9 C==c7DK.߱jCft5Ut+zm~Zj\]H?̙jޢ[ ^yco$".v6A nojHM ν)m>G~~݌ce^˞wJG?sW~7FN9W]&08ȆV!+5: 3UGˇˁ K卹sЏ э=OZ/H[.R0=p@d̓B¹TXF X{N"o=p*J)Ɣf4| )-`|#zyuވfa'сae1LfgMw9v ޼P]k >vg =\9iRk^~#[&Hs;c=#iICVZf{Mg_[Gͱ}I_^p%'KMI˹бD@>%S |Nli@ _k r}ݐY3:[ݭyK ] ^wgUΪF j<#IfY :PW[Qx"AG4eFR(!%l G;.ȢwZJfs5{EX;!7_*ƻ_Z'~7eC鏔ue?^mÜ}PǺ+E{Yܧ !{d6Ȅ9y fB33I;#OɆm8K|X;kXᄌM{lr=ꝲ}FWD%I|[̜fx(7PXgV/qJ},[A$B ߨІ|dk[&uo׶fڳdg^j/'4MaapúkKƍ7䦋6aÁk(4*fsU0ә faVAJqE1 _0B3&.&q:$*a܊ wgQ T~Ѹ!c ľ~}|KL|l_.B,竟 :5PEIJZy*g٪2T _.FTT*evVhZa=|:ͬ7 +UcfҪ̱D Abyč `5ǁZ6inF=Q|9[F]4)# tG9%K?^HZ:,!bba1y\.$9\̗rU' o] +aƢe|ba3^9w23BrjY. U$G0 E$dT8 A"Ȋ2PElY+ `Ԃf 4ٹl:9[@@n:L<.DffC@>Y$z!Ğ7]ɘ m>ep/v7|?okxߏV(0f  +eX9lh 5QۖР,n qFfxs;d:~֢p4:H)D HFS#~~BvHkw_kLƇR1 CvFj(@#r*Q?ЅzgFPU‡Io0~CZ+pI DNN=՝IEZPoRLFAـ7.%?sF ĢH!9TUȂkZv#W4塺w<|bSS1ͱMޖNMئ7-s 8ɇ0UcM°&e:[|zRk5:"XЁ|INT}?Vrz0*Nu_FEhxsy55CLTJjx@3N^V苵W? )R7!S}`$$ ucG簳Ӓk3_+< "~8TS[_-4&m̟ l.e{^!5z-YQ(T"֌gQ8yӌBwa a 50,sYmI 5*It)1ǻ.\0Ь9Wԓx+o@tJўtyq*ONmIMyX훃#:ɸb1[MB O6ˆ*fkp% "qCO [7'=4Fg^@'mɞX61oO͸]K"Q{/`5Ub9i^yb </bdī0 "hԎ,u^dY4rqkUtBӔP ХLC'I|xmay)_x d${ O*<@`φ8 ["xŐ\rI? XzH"cz:MijOus9ga;%OʤP̋yН'5U:p$qE&=xPO?t8pY+g~~H"_cIjki 3vS;oݙ+؋6m6U$Uba,3X?#cz1Ɣǘ C/}Hbn6ˬj}"c` G]eym:£7I#zÏܶQ4FA: ˡ<+>|q#u3 ]OÅRB6}.7&+KR_ciL{uőm7HϝP/&7ddI?WGZH߽v|BIlK= nO$C 37:&$7x(v`0;g~u:0zS:#V~ =rMSXO뛳2_Dk}ɟ9n-sxF0VX& 0UJ 0^3R+VӰu22\ eNS{ } 7oW *Dhd/ApCӂ !'P(O/LLFSmiإ.Ow`~y=gXYʿ n\ؒu3T-qM055RXf;mZ'Dp ͡ 絢Vtt~C#iAIrj˚dſ}7uo6#ci6}|Iʺ-ޟ3;tZ8ewƧ6֋k |'Mk|>ڦt7YUػԉjY+*5*%t&ܔҗ^w(yG2<"}0ᣂxMLS yc< _ZS}}Ji#oNjmU*)wqҋwIx<VS}$'ӉL5 yYM$ ey'Y8AШ$!L|bzmJ6z?ve:n2<_ANH,`"s\6[Šl Ų80Y Ÿp=I1bp`j zzhR cWcJΆDds#'yv@"s1-x]\ dFl/ sP6Ng24ޯ 26 e[D^V0 JzKMS88~TCkڈv UQĖ W$}GG߄IG)w9tRN俉 *'4c)dLE9(!bB\HQ&T('FXjZ(LRvV*:VL,f˄*>&$^JRfS9 D8f=2̐CHXW1Rdҕ!::OG EM_.9 x}\.HMw1|ZjeR=|\P>]HK T/Zq#_5s]\/ Xq;`:\:ԃ 1,RE8!Ԅ^6ȚɂHL1cbjj"_Sqd~0K(DWتoKUo鰃UwN2.6—0߀kYx^^PJd^VETe>su.OףkbWkp̓2Nz\Z˴|NhH)U4(| }}\iJC JIbi-Peɵ.֒1('X+'Ȭl4^JCԌ ʈwEe"njZ-j-Ly4|tgwغaWڰu[~m]*5{,^^Zd,u: Bp7Ʌ8# z XL`hBibk Dz5g2t.8[ 7@B u< sW\z/Kt~ɒ10&۪ Z]kNc=LT ]4q?|~fhCtz 7ވ>&\&4@ttt0B Lroѓ[~V) q7u1߈5A(8У&rT^6"P'Wtai/? 1ݬ_$ 㝤7 f#Mq6ҌLE!HXh9\֩ (eOoRf1^#Fm6U^0ܼMʐw%;~A6&"y \L^Q"e[>Y6C?J,+dSH!p#CV62w˞$Kby UΐW*M6">O!ӬX:2ˍJx6~~ jnk÷Nn;:7WH_BU7 7Ɨ=q/]{ݑҟX[K#Z0x2ѥUf[9s' Ji/{y!R#ևXmR0d&R5$ ZL&YLl`pmJE!S|IbAh. %+ܩڍW\'=.i7VQ?@O]g?cVKc{_ >i3KCzY ^A[0;(iR-OY4aI"hzc"+C;G$L+jm0E0# %*w*)\X2aʘYX ^2V_),+aIP+_ IĈ㧐xxG zZOPe=$\u!;ؙӨe")=9*T.] mGg8Ƙ"?@mFWJ)JplIw,=kF<36כjlӓIΙWmsHek*;D48l!\\֧S+\*UV<!ԛC!+EB¥'ѝoiUQIr|Ah ]M7 !y7-lY-Bd FO_uӹݼ.{(TTP ~b-8ʲ$MOmxq. Ao\`#ŮOs4w-bY\fCH(37kG>N$J9nѧB® E1MU,Es}W?N?(~Th⥩tH+8c+x)-Zo9ȖK> $s[ =ozVz<`Nn 3=k=|гhXMw8e:ZDNQCNcy(a V`i@E/MbiZ!UL%p.&fh\ o8#Ér?LL9?~9R-ǎ;&4>cLvBK:ЃvdI)y{6?iOq(r83XTΡC!PhPiq؃ɔA|<c@^l#xty5x~?]//U ah*2{Y۱i|zJJ} ~\UtiJ˪.% |"kR-j5a"\&D\FsĢS^H" ='B~feU$lN`-69QC>msCdN:&<fnwh<9͚ds@(T*]Xp*`אa8 P;c$7'dM]A~c"X ȉ2Z_9cNe@9:{-5ZBM3%{"ִp3EΉsv"SCML|eП4 r3Ģ4[n% b>Ǖ^8Zt@Y%cĉ,+ٞp"G z tl.{WaFf|q zf+6orMJp=ח v]a}Sك;4ڭoLlލNoޞ!4ʟaQq#sz-+?QOC,{[ *fb9L_0B]$I$bÕܱcc'~~" 'Gr};(†4RaD0$NjH`, /Xf2XaHK2㕣kҙ4[Mv̈vHItTp#ǎ^<$;bɊ9j%+3ky Nouި|jk^pUA%:ž%E4Ħ/[RR1E{:'׾N"PzvޯhQ)8f ݽU=ٹ.y$joȘy\Er) `ULEv~4f%󍫍+ O~R98>#2fSg92wY 8՛K^^7}L@E#n.BI8YK3V!'I}YIk7O H֢񗋛~~BԎ!\G n>+=[?znܽ4XݠSUTT_)|x*߉Ey;K2=j%fl1C- M.H.Ty ] $ú0t:[7:!翹yE/ J[7Hpߥ}c#e]s{rO:ڴT\?rYN oOJҴRRYm5)Ftnz@`aq/ȁrqJp#B@0{;Mˌ FDJ%KbJ?A#=NM#A@$ X"drD<x'|>{]z%za_^ͦ{ *>'LB~:΅ wT[נmTwxj'bvAޤ=Hz| i _Zrv/F )Ġ1JoleK |v6,@iyf(Ij2 H),? ܑ ¯]3H>{ Άiᚍ;һP<$.|͗ք[ɓ$!zGלv_Ja));}]T2BD2|x*sF&H{p^^veQ˫#<,\\tB8ADb[?/fwVKLʪwh)),^˳Bi3} ^L}s.p=,̴1oL[Uiy{9:Pa0Cq&nqU~uv`h4%0Gs,i[եBX``N2 Gr̂C9Lt\Fi{VENzsFsnet=+Lm Dc2xFP&v_㝓.a|'G<{ܼx%õ49M$N(Zz;-ҩiͪ٬сq)bdt`c'xA׊P L/c88Lvym`)2^v ]x4bD BEv/N"8#'Q_ z&&naGIVnW0fA3 hy.y8"ߺo]GZո5]򪭣o\occ'QCHGãOksO2".y1]D|M/nډr{crnXEkv;}T Fv SpnlSֿQ_ dU{-zՄxݮ F2OV꫿wLa AI0|Ɗ> "!4`-^' qU ~i)>E >,.,9^&usY E}[*LN pk;0gQmL٘#~1-T*I+[6a,DžX&v #n6H3]l؀F1ymQ/K!qby*ɑ+84fcؗ/mZ DJ[\7l Doao(\IctBr;^h%Y>5zS⺗ rk ?8Qy|&Y1't[ Iخ-AWCtA5 L`p[?B` ~i HnF\LWs\.Z !E`+[B+m?sܧ_;[ON}ASzM4|W$fg)߼&]ܣ=rН?L2&m@8jN@|Ie zzagmʢPˆ9QBXѲZMλ"v萱V8u7t>/@LDxx3|x!Ef=y>q?Eӿa$ ^$.?EO5^)S|7KNcd*K?~g Ӏ[Pi-9dB?i >&v:*JHJN0'x'+0ELM&lJ6%BӐ HoSOCSburif4*M<tMwK; >t]wWTe/&u.&ЀkF]ir̘ +gHRgs:o<2jQ7.)G"P'*ӈOC ]`NKv}ݶЎM^4Jӧј߾ٛ{%ObQ{/sGUDLDh~lPNUiir"vٝ0rnL:ևc3dtu"G6*EF Ei'p퍛+E qy_Zژ[\J؏Q @+`I`58?+!1tGÉpѩ+;pG.ΦO]CvM<=K' OGuЮsnel#8ν@6 cZnp^ n -x} n"o'1|Зod{l|8Ed[w<ki;J.gu8s;?'hM/0ABDy7y;ZH5fqYySik&{Ӽ;SSRޑ*;8{ᣬp\E!p/кX/Gf˅h,mlYꃈĸdY2%va:̖͗e/Kd^ B!WQS]u-uu]vO? uVeg =;#O=4NϨ>T?r'z2xGIVRvY9?h0}w\HG_ ukT@-.Rr&6g\)$[4P>Eݔk! Ҟ㔗Mؼ?CϽMBRHI*UqKFոHJq5Wd$!E?28$X #P0*jnC/ (YWlӊ͹ɵMRÊzLn CqaCL1 [Ț%a* qϸyndSDfhUF䁷<>"B d|$!t$Q6! thl]a!jD' lu+vt/!kLu9+Z&BIz!NT?_'U$קP{NsrFg5؇V=OUAenzEvLmNEtY?'~EOzѢPgK-nbCl<|`af߄{xO.ۉ@]uVo+~[۽e ^;BՌ]7?l榗d:SS&=UޅG2ha&C=KS;#t3Kq"x/+y[-_,PV+?'œxnDj,uɱSy]ͫMf7?H0׌_wX|E} rEaטaC`Pm&, UZjǒЂw򊽸 y.v7 xHB`d͗E>h'@|"܌Odg}"Ou...y98W-T׳[_/,~Y<7<39{}lKͱLj;Ygw?dE]\a&y44vle8<2]|i&LIz D *-i4יR5YEIM@'t89Ia\.Dt"WMKF6 endstream endobj 1183 0 obj <> stream xګOD endstream endobj 1184 0 obj <> stream x xŵ6\U;if4Ҍ3:Gh_1*BʭKwu̙pRȰ5n8sҕ}N{1p: نr){ GR^;Ŵ!(av798!.5L { BDbe ف.̪wl>^nB/Gn_H<yqme8-w}w|A< %c/?fk2,Nmpփ~Avl{ pf?2畒w*}FVZΟAGsHt%EFԈq2.3t=SPpϛ} Vf| ޅ=Nd!#y,n[O+Qs%SQa eÂ^a}vKٵ uu]ޮv1$V,m|m{+;'+wy);*[w}g>dwxF8V ӡ :]enzk=s/&TxWX>da@Wrݻv/VGRb)tLWj׮.oEW{ˆʛ"YpU7y̮k,;>ɁnZJx=P]x0U{a.u 6﹏.i%y5랶mWɱuzWoE:9n=MæxO%`Z]c17֎"),UFeq669On:|[}a EHJꀓ9s7p>^bK _ oy Q;lV%MMEO./_*kd)L'C)Fzp.zMaqY6AޫVintW욐pNT@ԽKwE=TZ#`n`}+KSॷ^RvYǜ; 7􈀠:N}! fHlHW׫_UEYxS;hu ml/˲Y-bAZ5G 2@FP-[/[`g.,D%0o}Vo--~*z>M*$ >kl|yot=qɝ@}%co'8BNRTm/~`ۧQǪԌ0L91'|-P5!=sn&YiwCRyH]^܍LA3*fgoN&[ +Om~$/g[)xv+'Iv!D5bǼUõrQ@˻hv Yd$Iy>揬L RL۸eb ڱ:ѼUA9څf.!<$FW?6n1@?7!~Ӧ4y?rM?nnהgnzuG?|̔f0+:| /{S?6xv2|44* ;U#$:6&v5Ϸ٠6BQ=QQlTT^h`32(&5q(RE6 Z~?KN"9<_Piq; [&AC,_܎ţnVT7`崝EY Δʁvpv/\a3Gmnwz=ipLf]1z+dI<(ITbf3Ye3\\K @,TQ]/SGJ?9]qx H5T5B+nzp{~  N8 o I"f%cfP2#NsJ+'V+wS#򇛮yv:>C)'#E[kڨ6ƴEY{I/k5X넄YV;NDƹ>&"xr,9:19c0CFCœ+KB#H{;nȺM8aݦSqo>?^&NgI>#6HRQ:phɛX3H?!$xC+(\Q|Cw5eL<%kĄ`d"j8B;G;YFo"<5FO@ NLoV܃1phVɐw3oz$(ZћYBSe>FFyGB,\'|c''J߉tXOr޴j"e2nLI0R&;N*QG>Z^UryƍW_|pZ~{Owvt,> '"ᇊ|bُWJ"p?y^Agp!ĄP٦s&Esh1{rÖ."99,A2Qm1%c*MqhTif>ќ1O73wl#:DtQr,8rGFQqmՋz]j_;I\Ds=cd&0}R=T?0X<_b&A?YWMv{ƅ/wOǶ&ݸwdroԬŸZnw4 sȆlJJ;d;lv)a7H[d̙SZ]Q:7iԕtڮkm_sri6鷋A7߮IUT#D̊ޙ%:,+9E!4@-16_98~s/7E-›K{2~^;O΢%YYξ6-=}7yyҢ?.Iñ{o}E]-ɴޖe'ʊ|xz(w)Ӎ&k4PiFɢR/xe.$ <2^iV~SbU.hTUiTU;%"nc EIk;ݢ #iF.4t\`)Q7A7_ٵᾄGnih?Ht;:Mlm|vڂnUϧϬ 2oF\(TG{l!aiS=;Q)Z.UgI]RPjuwdLk]k-q|n[|L\ݮK^1Z mSF\(&gX^)РmoepO@nF9ܼm&9y>J]rIoK!YZ͚*fWVæÙk{7Y9MC Sҋ$V\6Q3ɻ41.^AA>x4Kd0» a$xTMFBMU28)E# 4a=c?qt@N2gq9,3B@?TkjQ51+j̭ΦEY BvyyU&C/fC#.קvNUbY}8 eYq(Wo IԤ&S.QБ ĴCA@j+хW9ysU=F{JNIϒ,GfVnw< ؊ o8|P\f+&3z=[[u}/ߵ?%'=Y"$eflOy[fTeM=K7FY'10x`:ڤ„_IjUB2li6;]UGsR6Y釣y>ƚV%eS85.{}\T/PLC0./,?'KkX.?Δgp{†ݯ^P.73-yGLNKd,c3W[gp5;7_ ;6wZ]N{NJw)T:CZdD.ྀpOd$S|*iyrwfu~gK򚌾G/ B/`VmY2V=Y ACl)faTKjJu2`cXwiVPQv 8I#TJ#7h^518e-l@/jRas{kKdTʋϚQwQwo~Sϲ+zU`*\|lgR-י3#GS wҌ, 95᱆y ]s_>*=^}K<'q5}7]H_٢wP]{KjTaحB5_.,|_%hfYfc`Fp62q$Y4|;dau%+D0maQTꋃ5KF__"o&IIO e셕>a'K@%RZes1Y}*&z`ܬA[.$֊Ltx<1--XqCpvbL`ޕGG?#X|蘼檾⍛w. Dli"W-]X)D, EӥXL^^~ჹ**&[U!q Q@q"p67/э gy -woEB)A jߋ0zK3}@ DV4S5w. ?,=gJBh<^~iZ r3P Awq%30T 0^>K^&]@'Z JHI$E5Jh %nVjya$5Բju*V;^%4z|~/G +㺹P9$^5;.^mOEZt"gr .V_^um,̹*s<yϯCX?DŽ@=X) h3QnXfw;Rʥa.±s&*lEKݸg$.)ܵip վچN?X\,sCfkzrA?r?sSn5=uX(h[šXU, Wt){-ʤj&,oJ N5jZrK`}Syca`F*]M\*n*5S{3DoOdInq`@66)$%Ey*+h#-MCtJjLF+`PU a*Ry^OZܼ~.rЁ=_.Y'~ )t5*}}32|O0*؇d )H \7mcxAIC]eކN|vPu*^i ҆"!Yfj,do.I2GXۂ+eݼLMI*ୣoL_~>1nWC?ح( y38&)1LL̘rg@J6$u|ɱWi(prϒ 2Ltg}a!狻 Mg_ RRq6nfƥQ^&p,a~18 @#lgM-x`Objǔ[{_J_B=8TwON_dF㞸D5&Pymc(F*MU*Nv2nG rf0l%6ShDX@OʷRbX{eXjoK_(IRy({Md]v \u7US]&$ |D' vdT#~Mh,n0-u.RYۢKZ\#RTNRC:ZmD؅O(q5>,]]1. )+gl sW^dn+F|`wlX21 BX1*nت= F8), )3{qcś9lu:f/v yС7vk6,3W_k:,r1$*s-2fZso󘒌Yo]jӗlȝT(): ,T@f%ܒ8^栋4ϙ-kߩOzkGtM14{g/T[!wM-K'绬8&֟f˝ iIx= cZʋmQs&(14ˑhsvP*:,)_P%5(0<6"4*d,m;K$|.襗kr8.{\q}wW0<"Fމ;6akm^0F(4h4X4 v铱&r <"hp,&ֻds2āuqA0-80Qwc(% ɥÓ&c|~WjL4M711PA}Rڠuz6VVx% ڇɽgȣB6DQUWiW@20aN.9f4ZT7rAm^F܌%!Z zXIT wJaULX:4WQ*v# XD0W'?= :&z"'$ Hrm\/GW$z(oMxg Z$Ma_OO8UIƚ"a [&?(ƃĬ4ED2jz( 34QzАD:w %AR95+ֳ蒞+~qi`1Wec\%Yuk|>q]sSe]gۂo4HWCxQ.,о'c?P)e(R[+{$mHmP1NIt )-?3?4 8 O+^ݜ3'ѓq7f5,0 hͰ~pj$0(q45GVjHV.&T(γ\ l*3<WiX*J{JAo427- *s*QstFw (_ -R,w8YN? Xސ-zPdNhwdCoؒb*9~(8?1#d&;+"6&Og^ܷ,=gnHnmEGNo_hcpEHBJٛћYktj)4]6=ҾV(~(mD>''33S儽I:cFcG+'XNWfM'2fei$._--٬s-@$sdقOQ%H::wq /pȸqĽ|U36ΩٚML쩖?ƪ.1f LOl|p[޺l ђДt\k*9XgܬҢ6DEd+.L,}hIѨHMS)s %.|4\F $$HF#[eaG'XF00~'!YDw*PJ^: D+ y*eQ:yAy̟.x&alwR%]8_|_k#cqbS=2AxrxГ6hmtj ;}©?Kӯ| E :Ι߶tܼ_^P]ʚ9~RՀlIMd;M{yef6z7=9@e~Z.Letbu-L?Kq:D}Uh )co6Takj~E߮]ݒ΅9)@M'^$;O]|-s)H2 0ۋiƅ]'Y5 W1jIkWQH/)*<]\_+Ǘ7.|wV<םLL''5pWJ;7?ɟ^pA)3]$,=VGk%>NʫEM@Snay-c,pi_hqQ aԬ Z j᨜ MuJ4EaTN07HB䋋-XLD}-;vטFvSrt4--|m*IիbT*N#15gp$$ݍti ҟdo3ކ"UZwøoDRufxJީW3=*+Ͽfkj s$,py s7NƒΨ8ax\;Y>,?P3=)#1oB7]BoE^ vzTEE&v؟_3^f!Tbj~ja;O}X>git∠QOQPx)'F̧#ڛ}A^3y%jm[;_;[d$%aGT3m$؎#%%yCOi5|߰_+2<\B"?c2CoV w3­ ZBWz&~yp|sè= =i;Ð:!-_N|k^Pu4^zIE\៿R\kQqf52ȯQr=-R裪u((*!gP+ ]i۫(kF\.GǑFrCoϿ?7!\ _Y#h6\~Sdv\9[{my wGkI`n@& 2`CSBM`@1`r?Cz4 OvЖX?Ea*%w,EX?D9Hol[C kgk縫}S5\lۡM+iHwZoo?glj6|exĚL>6OZ46uUi+U`kn[ۏ33 OFOr ߳qlaǾyƕz>.6/q1Dψg~& H*ZG8P!=I%,0Q bQUfP:YC"4/B (obxYThN͢X(4<,cB …E-a"4Gi+P6\[E>vBە7F)HQh'/ ŞS8ZNPN"-y#42GzPDhZ~=U Fi'wB+瞉4_1]#4WdL🏎^lX߻s.wW{_awVaa{ֲ=kze={{V-z{ʊeKq-^x5-^~uԞ]7E24Y/=)ψ+eqVw-^پ*wOwWb}jGuu5$WZ+|+p[ùӔ}j$yyyǮ,sٵn GR ]J-3ʫ5 -QZʸAa@Nw-j4 LA+`s:[gHkuwq*ܽξow5wQw<#{qA{E+_|2m>|+]y e?ՙp\ kN[]b5*9? $p ]~}5'_^2Ν xvwj-/Fܿ/>L_p֔g<-fOattOb8v1}RλǵGj>b2_}4E|Y o=޻>Hw B_4$~~8H7;CO㱧cC⮝qgPa!}R~,n,1=G9:|pŦB3x~x]8-͐j{#mi{G21ʒ&gTcRhLchpXDYFYtjV *r:d0 0ĈB#58y!X%T"SQJ aK5n:X?u8>Buauc螆a'q |_:FokΦ-qM~_bMߚ5k9o瀞z>@zqK$> stream xګOD endstream endobj 1188 0 obj <> stream xy@SW7~]sݐ$ =@1pE * ((.(EDZ[VގV[kv˴c[6eڙtՄsn??w瞻99B (l'g4eխΑDa|ae7!BEK-\!UBS[/ * +`?aֵykba-\M/4Ch>T,[Q-j-|BHټbA7~ 'Ba&B,E8Q^F߆Re4-D>9#y VUG5t3#5r~PM'{cZ~)*u}A OQeyq/,$ уt3ڋV\AkP3VgeuuVj,݆0U~t ݄DkQHf'5i66b/APԭ8P+=CKRs) ߁phۣh5j%Cn^h28a\oNv'3#ݝ{tj4QjԂX0H[mLա(m$:#=xN4CFA'ه\3d?v~\nd.u)&7>J?FnlF)4 U5(vݥyMQ}H@5P@ m>KGa@JmtwS%diwBU w#Gz!Lts r]7<~bG h^[[絛 6Btb .vv3pseegbvaGZXKC0S:a6¶;=^bkp;ݷMxT"j4x{ n7+i,RlMa6g6֑v4:Xj ʩ%co/w>[P6bfB :\>0ʑj)SƐnﯩ @EIA'ixAsMrj0}0Exj W_M4q5u./DK]nr\MZ^W}bnCb\'P:.ET"),BpƇ7eTQ%9Qӫ*RrhK wqmG gL(ID:w<4*D#%GNNl;y ("7[',+wTv:T4)ݠ#n(C'6٪NCX{\̬rlPMR" ꮺêDCcƹͶԏ>\vzqʎ+>)/r3]'n<)zjj&˻qֻWlr$fՉ?/xM;$5sIRKŸ˦o2 :nlxŤZF:y}=~U~lf.Grc4iZ{ e+Z~Ab-B*Вd hzF}&Sjݓ){HD kRa[zjB*'Tg7ˬɘ2|;rK-˿*Ӥ攏UKb[{W`oASm;̶D4>ѫr E?Ǔ\܄1ǿvZ!BB[8 h]>/A6*{K'ixN5er!"ahw#T\Hig܂%mL0L>>0D"l]Qyv5c߯m /ض&ꭽo6^lh\ρZu)eoؾg6z3@[MNyH#6\b UoP5MbZz!:f:ZMC5'jTSY5 "h+Tl(;*ƒ.RLWhCq(ܳh3Zz <_bÓFXtWu6KM?=tL t+^'U~1k@e@SBmSJl|u֐YDBQgbjYT:z ȼb伞{=Y64 ʻ2TXGaEܩ;GͬhϼR53ڽpczvIRLTN~- 7câU"-#ݹ?!Қ{-ٯ~2.msh $㪸 :ϳ <"OfYT;$q4/r PS~";Eh.U;]o^i0tjNk ^(&.yOPׂ#&ŸBg= #%>ksJ걮豶 X%/x/Ge`xeᣓuX֔k4g}!FqZYϩ.V|IY4Pcm_|AQ)kw O6PMlXLQØ?z@z1l RK\Xg}rMH''$>8~v,#208j<̀z=>}(ER>o$GȨJe=uvk?] 7. wኣqw-`[oqҟȳV6IӔL uڄx{Fި?=%ftޕڑo˥#mSY?]+ږ]^Tppzۏ'.W>D|JX>D["LGˠ)on7t.\c-ԵJ<Pt.9#F6W('EAAOj||Jpʳw1} >3%ɋpV_*b!i]OZ<^"w`(vD h.#'K.*避>N$ak|#uj> ;V^^+lutSB]V#Ƶ+5QljaFYd߅k\"4hvҌJ:bf-2EkhLndkŘ҄2NC߈- ٩'$ D?{xu؇v| kP_#gCyP112 B^2[ˢ3KȦ6]עolG6C_L<s%|1K%N1KZYdcŘXTW[?&h|{H/U!TJI ( |Ҡ@%tA|~/XV}n:쇖>8U̡nzk6ΫSJ?y1EξChu3W >oFKmkqyG߾h}ρz;qǮ5Z{\OvvעwgnIMI[7ܥ0+G8:A6w){O5CSsY̒$<",Ue{NA~#VFNff0 A7+(G4g\\W­Cyo@'BdS /43=/6~^5r|g=uK@ǖ m/EtJ"LBJuɫ[s،،53 f /G'\?[3L%"ܼpAL͸3qT- .b̧\6|paHN8A}rvrظ1-)2uI]_p%~[|#b6336e*$e5Oo[Y6uh{ʒ wim>3ƈ({a%qQ; JF (VcָD2jb숹K#'G[(I(@y#uNg.dJH XFMF?އō8Qρp i\+q1c|g_w_@ʼnzOC[;Nĺq+n(,>#cW5, Ϲ%GqyӉ -Ȋ"er="J6.7.i6hVc"Bbv*3ϫ6t!;p_U|%g8G\8ҥ]"$ =`@0 |q(/a\`p93SSN9?޸~l,TƄ[q/?*6 m+<|l9xC12(U3JIbtZ(I.UWWYV-Prߤt-$0ڭ~0 qEaH+/aݸ=u_pveS,9saȲLS.@)5j`&uj) * jd`aجaՙXI\EaSϊn|ƍPt~y-x(WHrbn8G\&vJp\llGdK)4iR8$ i Z'$T96=Mb,IIPX"@A={o`4_ NU'i0\ (WR 2=:n_|WfӦ&WW&Q{KY:p짋k6/m ~~| tVstHE404f RlǛ!p|ORj5j)"@%q\)WɭXH%wX~S8#|'е4["';YP2@HL\D D|=s =xDd\!ʶkvPƯyOK:sth5'rVArp_M2bp>QKb˳5Yz6w8]wȍ$N!;Jū6J z`^E3,!DSՌkVk<D!sEIl>[VY%<ð>=W z4( @NG`j$c/fٯy|^r lgE,;0eƘ)XSEI8c\Y ]s@nL |v*Z]A}^yZtPBzM4e͂C]L&[kiY,eM5YíSk6֢ RG6fX/&^/ u,vм/%@jBɟGƆWH%vIs['bx*&7%0Yz$נ ex· qWEeX&q--\Wh3i~~<_7@ kd oWfkf8)h:DaMPjע%{#p+zF̉p^lq79t[kNs;@W>>1>jѝx eo CVHӳ\ϥdt̩eq&f&maY\;zCà2xd0GCQ[s qĈbȢ$s\i^mf̈́xa#Ru]VAEDHZ4bqUSPblgJR3[ߚkx $ةW_8L)fnh-LBFξ?P^\Oٿ\[!B7qFgj^d^BidiB8-4?6makU^1+*vG9aq+Bv^n3vʔ1s @*4m6LhC3q999 b!XWO? A>5l| ’+1GB;zLic[7ٔɣr;;C?6ޟ\/=jg}dgR2bL7= EQ۔|`ռgJ&Tu = r)xðw6Y|[3`mY_/ƈ6㘫iV *؂Lh3C6jn_܄= h-'qv'{l}ЦwMCT>yFV]e$x-"7KDAE6@%sk8H/4N@vcygHh0Z2u]M12n4ޞXBvP"Bذ(+++Cz߾]Gnz} Ձ͠uY"Gpd z̛B>8Pñ^6_Mps'p1/nEFΤđ$8C#t:\T99߄"_`vtQz{ʂmRb$MyUtJa-ֈ#J|O1[7?R1{R|8K.V''l^8hʬVU}X^S*UA-CX9,"ŬbPKӜe.732|dL[e^`BXkZ'ɾ1w7ZִtɍTokZR_ M誡 Ty_,O~؆Ejne?=[9sW=O!EV^4K˘6"S5{2(O҈>VL[WmRgW .CHkn#8LOlm|l;_DxݞXmV_H&v ٞc^}C4p\2m~m?d{`\\˞u_xo^C7uY\ְTﮚƆ;nbnȷ{sdpHNUZ@7 d,*H\(< ̈`JDT3DCrK.5}K83Sft2G_ ڗp _p~-ΰ XS}ECQxA6h*]Cv;BA,qjlLE~Loȟz\v cvʌsF~f欲]d>~ǃ;טHcx؅+B⩑]*Ԗۛk6(5Շ8θ)ׇy8N 6"#x9RTԞfVYvCFO}t(O0X/|Ѭ ,,m0s͐"!cAZVMkoyꔙ#f&%1U;gSSzlDU:?Jp-L߾!lŞEB+쐐YPI$IRRZ-JMRH$^Ǎ[G!6qtDDn<ʌPeVJh[21lR xrLBєogq}xdFurjY=SuzMk~ͤ4'ٔo 8rud} S6k S`<4P/~~`TrUdE32K X5$&9wXp t g wg7O'O8 ZFBCx,p^#4\vQx!>mZ72*LF bdX KeeX~J=V-"b,$HC5aшy IG( & K|"'ByC_p du'ِ3qo}KMuO*(%Zm~L.;n. Л *P\DeM-⭑)*Y]l)JRJU*VW "eoCG]M|%|d55y ṄX:z,o)495yrLYw#Fp??ysB ͓35\p&}%=5ng1ڴJ@'B$BFYEAMěxƓ]^|Jrr[OR뒲,L_'͍[VKF}} *tDY)SNtZ˽;cp%` j:G]^V 5|"Ĉ0 s:] ($tHP- , +?ng|JY7$O*HEy9ep?0o ڟeP_6޶;j`nO\ӗԇs=%ll(q+!ktѿاx$^e,a9ExxO{?[!V$YQXMR$"a BޗN໢,VZ 1ȣ pdĞx/o[$dF*Oq #2 uI0$IJVT ll> ,E$$KR80іN`&.%}TVBg'*2HÉjřZh)JJ9)4YΘO5L7hl;o uQB[Nj3Z/(?pf\WbR]n&vL ik7  UlpM/{ɜc2pÏy&WUO:tɓo!oRv-.t>غ|i^h{u Nڜ@-_ΜVKߜ*2n8<~9O1Gzߕ Rl̍qff:df#(l &7ظ؂K{8NL- {3v43`|cha AMx6V2ܡ8IHE+23'TϯW_\;iU{^IQNJItd>Xdk}+BA)\,Dw~X d@843u1یVu >^p5$L6NLڰo`̶Rdž8 22 ԇȉ&Ih._h߻*A йF&6pgxӔ-ӫʔ>pM.txcAOM2;3<)gOΝknGgyѰ(9u+HfтmIIq87d!g05m7E9)@U}Kψ2ESLn4-bAD10on A% ~d4ט,{:cČmCGI<4Nv~5pې¡YMmuЉ)|̴u'-<iM7 ߔs2R㾫<޸-p8\{sv19bߘ27ѩH6'uTܬ`yˆ:x&Ց؇pEd m!Zy7^y7a% zU}&cLt31?+h=iLJ omIzS|=!S;@{Uaz[?b% v*X5KX}}=2lr3QN[nq>7E"]ī=x<~M~}u2 !:S A==뚖0xƮk.^d+67׃&w_Zul͌`Y*USDAf^qҰbc+U9b.y;}шqu< eJtLl~}}b Fc.͈21yyQ??+D{__I Z"&{n|eQFQ̴}>Rfö-I4os-7rC}es S ~[#&LF!R/, WӋ[Oxt#]"oNf=}}xק2'>v=pr3Oʥ4ݗ7[?%'BbM7n]N>bB9[_nFyv2 c!6@Bo.B B v[܋UXS`ɶm0IL.SLg2*qU}I+%* awn(26.c^C:v >Bp GB ʑaj b"íOH3jy ؠ6OZ.I{ShѪM@:;%`~[Aw?#.|fH{43q|2Ef#{ua'J7>9FɢF,#ԗk9 V0N $*XFR mE;icBG.hFclWc/`ڣ)6 cTX>ȋXR ſkZ%P261gۗyy4cg$L,#)&p *G]~ĩE)> s!%6R;>_by3C9x9Y\NaL"E\H)dFj$"ɺWT00P0mP@@^:4B$0Y'Ǐ%8ϒ/H5#JIj>NmaT`9'3&a{v@ސoNϥFxY^^MaZuj3\鉿zQ_/m ]y+t~! ƣ:VN)VMт8$#^#KF~UC!5M2A_{$ L)`7)`WZt5)t5q:̒ɾad;iq=TA% B flř\-@kDdZ<31%gIB;ÿ1T)9YE[ę 21%y'kTEg.I\X>bYƥ:֞Ē1k41Sdּ9K>4k44{4ikԚƘ+),[Bb|8%'q6mFg.[~Gje*W?X1`[l}hB?pHL_ŗ}l K}~[T[>1MK-)*i,7km)ŅKw'əu]vnn@횗=ڼa KsQ|uA/~yV tSNY">l:&,Md,WBHW {6  e|o xj[?཭&YTъQ F̀AKbFKa &?끚%h)yCYqPtR6)x:,* j[ܼa fz9 H"oYJ,3,ؽx{9#[DхlE%_q{,>(Vy&1Zc,~p ZP_63#.]I3gV]xЛ&8>+~N՟8bɯa:LB*S(m!VAiPZ%q($lDwIo^I%%D:a˜}( Z$#O𖋾|kK ĿiG^u-c|]r.5,s}(>@~%Laps sQlz5n 04F) ^nN~D8fhaq&>H}nCg k.\π;xű7lY;g0oÞzRg ;Z&N|zٱԳ;w͞z;;<=ȊGGq{zī~޺NCN![X'ΟQ~̋O-䨨-pU C!H~[wHHo $NO"UT(Q5}}Br !rAz~VM_w|ыAMwOOV{¸n ~:8:fݗl jԑi"E'X >NS(#E0%\qĿ=;l^#5* +((fG*Mp*.)nS"H7>üPd>D̅7d@^X@wv_UPw6Da,Xf² ̂_%evu娔݋rN4XT>s(;Dù`{Ɯ&cplԭEP3ߐC?ށr⿟~aa{ O_꽇0>X?d!Ia[J|"3s[9+? LF| ԭPU)}@ F3G?|̏cI=~:,1T~ `beKBTI-"P8ɫt:bnVf"14yx\g|1:^O1󘻕I,?l\:wUp:A@sN~Ew^/=WG$E4?kKwU&i&5I-66ӚbͲnnvY،lFG=XtQ Iɘ星bخܸq?9(]=1\{\7T  sHQ3$HIy3SQdK FP*΁d[2e]hLF~dLL!MiepEZtuApGt7yC^CV*3(}IPEAg ~+eR_UJ}[LR݆ 1SpΧ2fS%2\K.F=.sPṆ9ߕ2x=].Cz3!\fP}RB~$\f~V)^E.3FU)PD(eR IHl&t1eY#J٢ I}(>>_(e;9e8 'ze8J}eL+>2N@LU 29 #?*sp+}UUnQź /p-w׵9sfI W4lZӴiE]kCLKS-n]霺`Xnyֺ /+W;Cdw%L?'u9}dzG2(5t9[W/XVbiᥛ @+QZ ꡴琣K>d>3tl⯜7}$ }>4A*: ‘u*gÖߪ>XPk'5u MPӬU PZF q)|h*-BJeolIVú~H +]CxQސk2.q5(R—z8 +GJ+~7 &XHK9i¡b<Zv^_}g^H/GF-/Ck.G m{钔e1̌f19CtlZG#M8 =oбrN|m%|[>6́~ ~E/r|E ly_5|_~*{u+/M/[_>2RG79n<sf9]=PwLREuv:vMݺgΜ ;?dž>?.cN>&hI;ʟ O``Gw>Nn>L}v8{@=Y==t;X~tD:{4-,>? e:>:n$=rZoPn{Zmq o:IqTCm7u*+P19"*JG;wKӪcsHaWl5"SW\ CyzԢC_1?u*>WU%Wvo,YܽU[/"塰*-@+[ݫ7id endstream endobj 1190 0 obj <> stream xګ?b~ endstream endobj 1191 0 obj <> stream xyxTE0\u.[I& H M ˒II BaQA@Gq+2B=U y{?y˽RuNslU7 ҢzDPבcQ3MS&C{z̅O"L1l_BxKK?ШP?nogݕ>8NnBxrF⮺~S*>NgU˟AhV,Yu#x֬G#_-BI1*,*x5 _Bf n @2*~ e!B^nZ§?!M#pA+;*b~|/dCsjL/7Fxe<񧊜> G+B Z܊֢VjD:ރ]h] =&LPCq_PaVq p،7=N8VzmJn7FE0v4@P*$2@wCiv'’CH#` L*,TFGIt[RWK*ᰕmG{reڊq6ڠo4_#]ƒM?J4 MA9GAM sאw &p-#ntWUHy[8,Bq1_l+LTAxAƎ=*oÆ;('{䬾}zޫm=23uMKҹCrRb{;e3VVI.D9؟/ٛ*إs?(-'ss-q[ % oySn}Qo ]FCy@2.pA ֛ʙSސ]8CZRMF E-BՇpٽqH`%Q>_K! {&C‐ĚVPjg7)E)I) $aEȜ8_.yi`v(:tt+A␐h{~B7oS#&~B|s 9~oNCQC)~pHkr|hx3ݡ5 F3zh: ?%/;/3# (Q2>.)p)HNK "L8Ik"?v8ğ _]52o ~v gZTxCB jrC4؅7H2[= m'۟]7 xй)ABA.r,P4Q\ ȘJWlܥheWgUB!Zl6 E#(жO@Cݽȃˎ eI %e!O]7 ApП_bẍ́#del1&E$6'fԌ?i0JTy97 ‹&́o8D& 8Koo>vPGov{F*Nr[Z%3 ".9x*JܖG s@.EiBroH˧}aT<ʫ7\! q%f('ݖA2ǃ[{Tchh0BTn `HpH`.E.i}r{>eACбtuH+L?afjOxhKo /- {}BF= v=8F잪FSs{$HF<#O䖷yܫg$5ղsC: wMS:CPk4}RpMJ;*fYPAY,o( C _?}ޗ@DCz}^S (ƞs7 Ri0}[V1-xJu""*E.]4[pϞ9Эk3ٷp}p3k/OZ~e˜'۱h3ݺf݇&w hY͗9@rd%Ʌt: LΨ9`fĮ,$;ĐxI*:"j5) `+pYYI9`u,NEfkR{%Tog Y'iU(WVOY1!PYK)!ppj @5H\D!Q:b/ $`A-]]j>ṹÕ&RO;' d$[$A4Rc '^JҢH#IdܡF׋/kɱO;]<,fmf^!6ވ?dGB.@ʤ[ڇ}y,nmL nA8;oSu:h$H1] D:KTN;8d2cEz2R_FHseO\YoVPZ f4eҬIOrh3cٓ9C&[ݡp&;`^,cswX V;+ xOyaR gFP^}`͵BEuG.sy w ],j*adT隷 z;vqq.C&:d3ᰋ:QWDjZV穋=PWՂZ-n хIfgAF gR! P9 &JvF{#;ɩ\F p'ٜ@>1`ܝ^« 9bwL^.O:g21)6a%ܮ%64;S?#:|Ғ%}{}gHr'R{xBiS;zوF? Q7T g"l;9B"uIv.t>VMstW+-p8@Y =Fd$"-&6. 'ۉv?Դ7]q d ޿A8n UJ'}b;spxr7rzN6jZ F Љڢ$lgwԙ'vp>΢| |? VÌ] A[j4%h$l ̙y ;92w90:wWa^5WcS&g4q "Qٺ:N%uH^izZ6HD:|i.WQI?mpiR Ra0S=cUs7oeխwM[6\5_{'CG#m@Px E,4l{h>;wpl{"e,޿WnP;S@> [ PJJ[`{Z96S^\5ԏuк0(mR2U>;uůA\>5yQ`(-*`"5NQކ~ր  u, UH 8<fGs!^ ~ZuG"'rjlbuHDqF6<.N1NbbZm %b  &o;:"VTi3  Kr ݒ:?-jckw>~ߦǔ'x*' c&Hy_T 7w#f:,MD:(JbmPFԁi zTFhlQgAa|,QF,uG#L6>&O^oU-"7I6->A75AcQl[xj{LH}pAGokk۾=>v[tr|]2ۙPgw:x#ëx8:'$H}{ǔ\4ZX,>k2 K(KAױI9x'FғY= !)fIC>y9i+l+.r˗ݤ;j[_?c gO_8oz>w~g͇A/Jr9rNЋJ,`:6:.MWu:ELMS76&٪ >P=Ie?,yoZ Nl.1.n$[LmfsMA]AȃTq2~{e>m9!AiN6BF6 $G|A@X?)tQꜝIDae13zh_õgp[ >x"^ӳ_ZA7n1`/a:l9'FI(M{]48{;hOC`C8h;%{HfYD-AH+gn$N%ਠV'kmO9}I#wW:tՅ K~bݫ`޿mʭlܴ?,>jOVOّ|t֓~T5jR5+6P~gEY(&bEt> Fq(jHvೝjց:\ojGK*ԛ x=<ls]{EK6obwZy\Yz;?O/?zfbf^,I"U@0 $bf)Kr,(ȋ? T`7:FuHykl_cG #,J\$QsEb |چ ^G>mzLnwnQ6*=b:Ϗ'YomԼp hv /^8r!L;p|qc`*>-%2 x)olTPc#=eOKE]#y"@3|B7oa 5Π==tC WnQ&_ :qJ '>Fpʷ?*6|uÂ')>ĝG5axl]1; "eq]Jy;~ iaU3, 7`y=1ۋ!nK':|peη^BQe+?5LPS3FB4Ua# YBH8(|,H"@ &H]DYH;输<m oME l賳GCiXD'1⑸Et a (Z JbnWxir7W<MΔ\1 +$h5v P[u7纜ASZ@j8krQYI<x\҃rOK{nLU/!ߡ&G8oGWI*V`Ixރ8F6y&BiNs 'ds?q`a'%EZUHd!ZU(!'=qs"۶XX#D d\֬w%9uC]Pp RIV^o0X]$6jgdkUFbh% Hzyݩ{x$OTV3 [Z{ =V=n=-K^ Oٴ Ƙ35+F6|ӣrju`Ԯx>d V2P4Ց!p3NIÿ}ę,G75emXB(t|&8j&jX :%"tP+X/S~7ẇsyGz۫TqGk[_+߃|P^+ddEX2$M0f2UDl;9yaK}wPs?O4-&g?+ʰ"d}V ~$ ;B;G|8wIm!1ޢ`|| O@bȉ"Hm$. Sd.3Ng@v[LrߔCNą6mo򁏮Oߺk=gW/k^Pܩ!m K=O=gXԾI(IH0.9:/Foed_O)|w~mLϲ=]!`E6A>NE,"Ŭ)dV:N@v83{w%E:eOFθ9!i߿ 0#"R<Iū:&"UE>N@8{NS5u_+/*eE2"p'<)+r,TF+E)pKfYl ;Lɇ}k/mzc nQƓ, Rc ]Sbᬛ#5x WUxi]pВC0"\17`aђDtk'I4)H ϰcq3~X.3g&GP؄9S ~ 㨌s< ^!PZs{ˠvYM08Y9EE=Bs<+JC%r.ƘX*95,F-]1*+119q&?H0 ԍJ`8)j5u!:{iV!9굛{-_:ha#b>4x8@Zus5'Su W8Ԝ*TQ=ox߾vl7JetN=)s8`;l4Lztn>eeݘ*~YfؤyL+8'#<_^K_vʿϏw-eQ&p#m x% z$Նlj+FVZmjlםk\A4yAHZ/I<"sCYm+p-mۖ.@DK0ӗΘ&Vc R#yA`vĄ6[jNm#3N ʧw_Mcu1U Iu|> #( SxB:9jӵhK :m&Cg`GR^w92=;#MQWN9`tؒs/ܴ=⎛gM]/{¬'-楫f[7,: ~vtL@&X[Q^O?#=8Wx,2O5PWsVMi.dBF`mQ1oj8&_G+jl?"\PpQYN㎭\vtkx-+W/mգ޲GaS[͘*# p[M '2jAB/7^ ?<xu֑uo9 &ig҉:b !/h45lt7nLqr-@Ke J7}#ּݲ]WXf!,KXe3"yHnK, ٨l\v~Me0~0E.4sz%-`Nkf]=1)9)mLv&g8FY7(㷱sM:ޖp/{5_U]ͺLvK@$l#9!Ǔ`T x0ZM:G:= ܔjJ{rigFsn{E]VCո9e{?{rgv%c봨k٤D"x?Ev4itK튉9m:JC 5RD\܇9‘kqйȋϞ Q;7`Y"35/ΥᏱY,k|K}nC[7lذ}\3n~|[xߡ~2d?h]0'ء*7烑7?n.݈V実 Q >3{\Gp6e򁩮BO_:g,? owNk[,% Y 6HFFw=Ztjۅ yn$\# Ο^xK7 2u-sg)v.3|魿] Qd|dw8 V+7:h5i^iY$%\st'o.y#tP E f*<ܰW6TWWd# `$z1:p"sG<ձ:L-W29y}~(fyHnOgZcv@0N~w}ۭ< SJ_ {\؝ڻ4f֏[.^c_1TE!ux:ǩ7a,.Sv j5gNdСbBM g&ݚFR:|j_pHW|c{߹8U>_9ݪU:z^@.:maz T城l8aQkqx攅7*;m^hWt 'Elf3a34N挭5,bgac_y[yvg28vsuh -\1*)FrA+ĸTѢ]``ts#nhI2u{f+MvuA~a}=;<ɗl]Sӑ~Wʯ}wd=  th&୥^Hy p|ǼJ08oXEv$g.Y];Sj.|Ru J1*UWOmQ8dj4fàV & yapF08CG퇤'\բt:URGyJ-xZ]!Y܍O /PI,^&Cg$UF+k6چW{N ]83VP3:x&x oA)ugv4XnoG&M#‰$ԛ zbC*Ec3۶UbIϴ$9ǣ;6;3?|{s 4KÃfsOavhf͙zyPL\H0{s&~ 8bE 9G_N^}RhX8pŽuo?PWp)PNb »MS%J]y=hd]- +&F!64]I\8{a0Gba!% Y<6f6V*]ga غ̶ز8fȀ(?=KΜ4ȓ/  oX=m;\m=q~Ei͜}9}vcyNyGqXTUXe0:\:Rp#4iRd|M>T4;[8GL_K65?Kfm39(amEyr'Ag/W,j!I5pf7Y:Ǧ"&#h%G-z +p{NOzd?:ᏔqS3c:} 3f*? pќ26U6ա[-f\4Q[ףw-=[,t_LGOSMIqY8kba2cp>VTf+Wh=^×~!kĮSut o_6I<ͩsLFf|U_dnw_+p ^9v=U`pmiFrLLz3t&kjZd::c+:C.VaS&&94QqW/jON溇/}э{':/=h2/&6mmf9LΤ]Hi|%~=]?`֙]@0{WlG4Ͼ__:b*v uiS$fEڽ9f nt@K0l==|s))~vܯ䫥P69oC×S[]2IXG[45v8!Gќe26_1 :b6#IѕVaR u]GH*~l.z7G{t߄-]r Nu=<ԄqEQJyf).<;=%.^{"?%WgRGڃ՞O>ɠګJׂʋ(4ѠdAY9[]OB3zen_=Xc/^/}1>/<6DaŪ w l[5ePq[E9O=ͽhQؠ79lFzQ7PL"~3?uD +R&^tmz<1xK!3xH? d`N8%?=j#-g6SK9 ,ZSQjYUC{_0:R_½jD }0h훸 -(by ٍ#dG#X5}5|Ix蚹zڑ#@_{ X}\? "XxQdi' xWk/щM{<=m VNd.` ae q Hؒkj]!9a쇶4h{"y9p\~ţr8#tAMF$xmځ Ch*8p|KJu GgŒ :,$ X螔ln/|_[i!vmzZlO4q /VY/I!#l?-MOu%?V!c3yȔ F-jDx<*l&P.% k:w0948~r -@0(E#VTfŪ.Vh?xǑ9k>$#Jg9r䋝A*G!7 i[ cOKA#iuzojq n"]JشwkGn1ߧl l Fh \֍kd[@^;~m`#DZ .Qeu@ع l6G \u r {<O󇛿74%@ѿezŦ Em-B,,pD80*A P#ڀ4*nQg;Y4 YCߠP.cITt07Zln]z rZz4]Z4 ~@ ;MS f[[[[[[~f^BqOj7w5FWn2R;5V#XNblQ<ʬ9`3CM!M?f^7G@_q>M>ёd9L yo^X(e2*KүT媳/j6QC6][}m'u0:' )$@ aacgB%Swӫf<|%r򽵫uVg;b~E˱qpnm[ۭV<<Ҹ,u1\6ǼQ1ZbccvB؎\鰭topwGܜ.?9Kpoct Lx5xzx{nB=nm[ۭv)Mt&^C/8L(#'6O+[@OFqb! gG2_E"2phYB;ZV!9--kpRWTF:Fzǹb5{^ WV/B!Έ ꎇGhYnSMuhhGe*4`JQ ^ PP5j[p׋:ݎpNG]Q7ؽhUg@}/EŬ*TR=ﭥCit\V3CX1b~i;z^MŴ:o]u6;2U3ҽSaa/UbJi1JAQfC]:mb(Ch)*ayQ7ZZYRZޭm}3 xTZSK_LO햚-I ebRǞ>dUL/WD*m{1jR1h쭱q$@,S9M9rˣܙ ~/8~;2α=P.NGnP+5wጼp,p!]qHSc48r=u~ 5{@h}@8^gu_y8?u|]N'՜ o{[Rue \)RueNuN%y>WgJ?$c˟8<9}K_"@fΥ$pq}qCv;t 1tˎ`1!`?}?^X9}?>:sT?OzNri'NVޜ l9$yV YgŲޞ{4{/Ǧee]K%X^@*aŮq18)@Ɖ"xVKX:Iac˙Αngqt8F.xYB"#o4GRܻb$U>7;&%eqyА: WУ> stream x\]7}F+~Tɋ?7v8{z{GdƘbe҂i<]Vs !Aw<njBCY;.fH;40!7+!IpyH$ 2<E"N ' f$F08k# $Fz6/|h!7H f5Mv<%|BH #AQr@L&QB!Vf8"@&GBJ"9A khpi!J 0E!LD 8R3 DT0PH5qAd[I.C ,\F }ɋ I!P+ŪMD|pdX!S3j*+%3 'ʀg84dazʐ5׽6졚 n͚' 4`Ь@tc$ÓYea/KE* Ó!bU?8h$mġTY]"pʐTYOq.!3UEI1g4`?$Ne7Q%mJ;GP͹9jhKth5\蝕IXޱ* XFL`^)ZYTB C\rxʎ1R85,fWőăEͣQEB?)T{:V_4-S iEz&RPXP ܡcz+ES˜h,ڬNPNT6b PɪZpRme-KNja u*QC_i}s΢niûdzz}y;ιz-N,C'V !v zǀq$W@|U#r\d q!!r8 yLoctMQV#u#"CO)vFҎyJlf9XۙȾ9!!3J0z7>kx\b@n  x$C\Cހ~:Uk6i2:c[m%=IuK!Cʎy4M=+A1CLFFɮbhLJdB! &O15 jG#<$0[D6`2sp(qHcnԂq}]hb S~IKm&hosI$6gQ18%~Ò)vCz` Hڜ$J6gdpJ*%lsI `E1s?%9CS\%\v`hKeH!abk./f,Z/ћe2OKb$~1?Χ>,"!{!&JKϹ b&~sA؀(WEC7'2>үG ALhAȀǙsehb<>ieH0O @E"CH/P,E#Mi.A1vC`@H?D}34h^&˥&< d0]Bdظc%pQˢ,",:SA!'rȴ:$Nh$]fP]@HsڥXnʆvDߛ߇qow/7;/^~q?yw\?6Wnw.+N_I|_?[_>xlnWUW7^l.g LJCiU>Z[-SJ+$h2Z2j?Yy_,gI/yT;B{THG2NM;~WDK ~E Lu n+:tJyR2/qMG*Ҭԍ:?ږބK+>O:^_[kWc8Ǖڮ|Uyr՟Y"0TYQyGWQMSR(jľZHJjRI}5qHEbya^l|eXP>.ݡ %z!,ݬ=7Ͼe}}~vyVG<^߼޼ä6nFK_|]򷫺xp;O1Mon?}߽Xn%]w5̗W}ٻ4lgeB%ᅞ9ݷ>1RB=n_W6o\Xn@p(?]^ݬv}{k2݇fsܖjm;8ds3}囫szk{6~\rk]Oxt<|_fW!J/" W/"Xl1"10j>#AJg3P'YҶE }F ~Ϗoh#Q_Xb7A7;A7ǨIQ?#jMb?nͯ>W6׵ z~uyu$nN 7C  `ѷ8Ⱥ(8%U!fqr܌8iwψ]H AkQoƭc{}s!V=0wܚnnߎZLδXc=.IQn=ԠJkw7?6gw?zyO03h>IɯO_~ϟp|I$ӆ#6_'X PmxY,]C)nv endstream endobj 1194 0 obj <<0ef014335f0bd0a312d6f6ae3280abc9>]/Root 1 0 R/Info 2 0 R/Size 1195/W[1 3 2]/Filter/FlateDecode/Length 2753>> stream x=e5q5333̌1S̎Ҩ&mCmRL}otݹ3s9!_~BRp/G!"Lc|o)\!D!d AQ-mf0{2+0$LL`VLls`N̅1`^L| {}^=X aa,EXKai,e X+aeUVXk)$a\b= !6b3| c l5c숝3v c쉽7 )==c@:޷̖ 2P!-PbS|PcvB{^S*T]eeB^FRVjO>ZU)k: 2Vu/c(]2Aae/(FetO^.RjJKZҝ^.SjK~ԕ^rROkүvyNi(} J#U^nRJ?/)ͥ7uد_]JK釧^QZKJ|6ҿ yy@i+/)%bp:(ʙ>tTvJEEyoɮʬ]Q>P JOEUzyI魨V~/(}Qx{*jwQ+KDק^b@E{I Q4dPEzDh|6/)#M*% eiWdhoPF+ZK6E+*;e=䠌Ww%e}䦼H9/NK4E6/e7QSt||%?eS2G'wZ2Wd/("XTo|blHgz)NYͷ^JP*.KI2E_e$WiJE} e8:e)RVq]/)eBRIqs^*Q6+.sKeVwyB٦'^R+g/(;:e&SԠV"qԤUܶZ}xMٯ /u(.RrTй^S)UKqc{iH9xE/(OKci3GxiB9xW^R)^f}%%<%2W3nx uwn܃-q/xoc+lk x/3ۆ7m{0n)>_M{o-a#|W:S2P:iл?FUE!5Cn_?+ yF[L5]^gw^ +TWy'##Ż Ogwxci7;N07z*mn0|;?f`׊+7>ݷGĀ\{re7; 3%?qp׿߿Eeѐy lmY@?'`Jk<7BtΫ>0{+%_my3gCsv͋Llnqa3;/Y0ϟ@0o\d>S\3}l7s!30jJ3jJ#.氦9mY~;-m0m?2z!9[ A K~IENDB`instead-3.5.2+dfsg/games/tutorial/instead.ogg000066400000000000000000042371611467622671600212120ustar00rootroot00000000000000OggS﹦0&fvorbisDOggS﹦0z!Mvorbis+Xiph.Org libVorbis I 20120203 (Omnipresent)ENCODER=REAPERvorbis!BCVcT)FRJs1FbJBHsS9לk SP)RRic)RKI%t:'c[I֘kA RL)ĔRBS)ŔRJB%t:SJ(AsctJ$dLBH)JSNBH5R)sRRjA B АU@ P2((#9cI pIɱ$K,KDQU}6UUu]u]u 4d@H d Y F(BCVb(9&|sf9h*tp"In*s9's8srf1h&sf)h&sAks9qFsAj6s9j.s"Im.s9s9sspN8sZnBs>{sB8s9s9sАUA6q HEiȤݣ$h r GR TI) 4d!RH!RH!R!b) *2,2,2밳:0C KMXckZiJ)RJ) YdAF!R!r)BCV: d3 (  ?z=RN*!+ "8*QBׄ1fGI:uW*}fc0@mN |k,@Id V@ `,պ9B^;Ӟ1!#e-ЊV,  h]lV !QJHj$c9;`@ Tp xa\y5OϮMpk@n,,:h6p qB-{|,UQ=Ҕ`%,`U4 |ID@.Hֿ+p;! }yD'qpJ*(v R݉V\Ў g@ċ[,,"(9@? `OWmPWZBoRp *hUׅń|!:O,XgcM!l9$ AR4h^R._ .X*r@' _~eYDV Y|Q@" ! H~fx9R`,!uB誅TOQSD$"7G-hM@ifWM]Y#r & xՊ0,$ `]Ő MYsXҊ<Jz.8mQ=RJHA`ΪaI{rddXX6h_@D+I<&N"ĄXSJL I "+ Dӆ#S5c3O<ձzT!TӐʨZxy9)V'(! TӐ|\EŃK(ms+oV6XI ThÃih24V1=jxJ"DӠfUkJ[:ƢL t4Q4%k.t>f&HڱSElp=5vRc4u腌+nj\v{P`* oo=}MyH# mNKNzIIU0b̎\1F͖;1'~vt~!p y:zo }#K+M#DG=Ht&j"l=&D0z к!PC9L Z!GpMi  ~>Q3zB43 amy >F_ pO\@EeX̣T9kG2dD5bJ٘g8w#,(~Ld Zo!ȸLVN &6\Fpn CtD ȄӰ֮MڿlpONҖb\׾3—|*HߺՕ_J> ڷf!:o ].vn L!Vj,IG &*+*G> v1<))5y>&$!zC\E,²jg=<E(er5a`<Ѥb?=E-Kc'zqno&>rU82|=^kvxj\C{<$Sǀ_ңCjR:q0qA(р//vRo<d >,COE P./A8}"8N;4}k08HpErV Db_lbI⡕쉞21,zWTt@ܸf:\/]m_E:mK`5B9Dsj%bdN0 BRX A:a.T;~Kld0ZvbV =nX@)Qt5݆7; L=/& ?ހuCc$efy߉^XUn6B,q $~.1ba( c[.n P3,qJl>yEdX&GIhn}Dc@.CB8)t(*Lu@#AlY(4 Vg7=lD`o 9MTX>;n0r+X N˂kyw$xE̡$1 %< mk [^|+DC R9p+X,ر=[104 HXu1dMCbWO :2Bqq< 0u+b&ϩ«#/-xCLHTt(*=XOK@[ BzZmIVC䒸oOggS@﹦06&"#!""#)'$}~}wsyyGt3K^DkZ1Z~brqED?^Mt[auPv|;5e 2DL8]}\:,i"CA+ S'\YT^,DΤݗBCNd5LX*&D/F܃}:gp2s]]j=[#W/q(b"JrfI,SG 8亜)75U/` ~$"Jpk5O~>=b1A@m@]X{ F`?nt%* C\1ȯ8a`CDfa.US+/NFoP@`u3pk3yBL5A9>'~Tjj>Fm@@E>n͈3ŀӰj^T0xa/CiH YJDRxVogCB?e }zn!0Cv>no'n=u@&@Q"*Net*?(yi2< @߿?;XOp`Bܿ B( \GC}cqz|e!. jpVQT^Ŧ؈-'6G=84$#)OibhnOaSidwxeKHc~'r#H05`+ X Z XF#F5"Qe`:ҿȂs8^$&'7C41E*j*X"fSw[mf@`v"WApy4  )A;r>_k](Y 02#0 ,XPFaI ͒b ZK8<ݚV1*xj?K]D,>أVx6']BϞ )4w  >Ns|1xpUɣHliEVvT{nzrhYKD넸-wu="1*xRsRCL|c_ *Gnk Q_ 4{[wi*&#; }D7H, R $&TBd X@0nf؁9IAcKq-WNGJtxh4ag2:~騈O0أ3rX*@i:B^ *%xmc*<39:[d+ BAʭʠtrKc^HTFxwX\ġԫ'}̮FSrRΰ@& F]Py@&Ƣ y{P1I@ OJ53ޏ%fW(WT)TFw$0"BeW^Kle2a/Bo.w:Yj>Qwk:EO2 |{k ز{!g~@`Z U%sjX%{T1B{%!蹊b E ޱ.˻ca4,5^w47YJؚcUJ$=rbm6D}G_K#c ,ַrW0zz9~!iycZA0{BCAqF5"G@d XQQPa]1J^$&vbepC(0*E?*U 7Wz*c|ewjl15JDt&TJ0::wXwE1+r BFҊ$_H^#B}5B"FP!^lٔIrg۱z: kRXjq'E|Q.쨶ЁxiCkg9 UQ@Vxx$uH-f1y%T}nT WDBFd ص`Ą]4MEZq X7j]3{ JkdA_qG<)ǔ(iP?yB1e.pa:4 v+N$ްK닯U8ʗF@9 X"K(.(䤱j3Eɶg/b,A ׃Fh'>io|7ooV zȱ ց{6 @J.8EAi X" ,( 6pel fЛ0V$>N*:"%Dpm]he:07\aADY~;|& xVb4 a%Ze1 `5þ30K)zZbE;*c~~_J-()^QP avLZ`@gEuHE+^t`p;)]@t``%规1֞xk`rcßÅO7w+ w6ax H6ݝK2ܩ՜|n@~ tFB={Ņ/v?6w^>em6nbٚ p"OGYOꀃFQf$`~[+CtU&ڸe0G`0HJXTR X"r`PY|"ދ^dm2Ĭ=Bm6D#l cΛR@ζEBH^5~ cĺ}buL+_q}M+:)9j#x`@Rjg.* AjADa [.Ĕ&&N:lآ8GIDD @˶Es7Ls2~, _.pra#[!OGi\vu67FbdI8&EEE =>;Q>9V{ LT^#%"?Ӹd`r윫 +IۋD }Q@ !8 ^JJOO@rV?B@a1-TIHr^l-+Ԟ'C xKS]^G" $;F8jvgWF׏~n .fc[Zv|0!F8 Z,dP"JE(1`0 {nemHr5s{ EeKpr4p# ^Ie}>{㓘o])Q E7kP0ȁ숚@j\ˑźjR&ea?BFR DX 11a T>|8Jnt2&+BM0K=ҡ? &Vre3ߕv[6"?uE<]M4Єs/;@E5V,.J*g BK2Z P*7ncH.Y,v1]OggS@^﹦0]?!{{"&&%{NGÞ(5ӋB>eQhuGw;2{-37c _ iY06ds o>hP,$ &dD-2X?"QEYuչ>u2P-D M0>.EPTpRO0G3O!wq TN彝mAC*W|@VJJ(J] hPm="/_Q 4X!a]n\2OT!^;tr <1f FœϦ1²0lE'ct{vJgo tB0 !ezv`P^ pcX Ke+Q) Os] R'Zm[^X kɱ Ol*HZ}o OCg|(<<^ʼn1.H> 0Z(b{0  9w2FDDF2 ,e>KxebL='9}ArP z 17IO'$\7S=vi'O 8;,- :7%Q вpm r  cUKvbP0Ʌb 5~ު-05rd显IkaH[>WHӉs=|U8GK!>-uRNW9rUhF{.UkAqd-tDU#Y&!2*>ՠvy+Sq(i$‡+?[®`."H_ m'hP„W+{`M :ɠPwML+Y  @A Zqx $RuP- i*]nHH bIk 얏il@/MŢh} >VȥV["l } *Xv0nv#Y !'4@-u&3lF>barˣcd[ ?3FTJRveR0 SMҬ-xrz]G f@- &I2nPU##fkXTdP!0%aظe`L, ğCp!ޛcB`HoyKM&܀%Ks&inG_[iU>O)N*T͵ЗO띟dHW`H08 _PVDޕV\t$]mo|' }!N5RJ8*ɥ`QΑ~xI>uQON0l2y͌CN]їATAX0~erMxv"ckrmI\KYR V pcytPIowa`xMߴnX`z~`vh h '60Frx_~L>Oh_ǫJ7U@ ϫy_;eua+'DZU`rz1EP6su4΅N+d,$Zc{of3=!hC%H+Q)G} M/5&\wzx]CzVL)Q~.V7k<׮Gv$=DI \&@niZw;ucXQbjdFL3d%Zǚ*&4vX]CI:g[H5PF %&W i]7&$ z;z=Xu+,3a&w$S fyH28a//0^~b㹈0v98G}DڛɫeJtMZK'ZbM ""%"^z`{z$Zхex I`KHY?VsnMj)4Qd-i) K*ɥxQ| aGH|#kRb %@ ( pV"$BS54Eۍ]i=|0BsU՛R@3a,n2ۄ[0'mFkv@lI޸_XWf;'z!s2-zlvt ?50'wgë}ɫܮ=&sH0q3G"{ lơ^<eӦM$U6FXJX|DVc>E [ĥ3=\zO}V8o{}_?҈WoC e,[-t&ᜮEW-G]naJk3X!2~4C v3נޫōe(ٕh @3bE@ZN }`TYwy6~&1͓5a{ospݞkw-wE6WmO!MDDolcS}k!LJ踔s%:+lQNSڌLYJl̺w]x2T]Ty9֣Z\SK3h?6xMHzbBJHD$hM};AWC2߾s:=o؝$hQ!B IFuB"4ɳ OuHow׽-x zXR)n>CR&L @9]@t+kjW"z"'"v#`8؏A^KflMPpm-ر#N0aX&$B!c:%-Uj: J˅ >.wlO-?ω[7+; B ȡc/% n=AfOӁ@Z 3P8h b ԁW!$q|aŚ`=\圪tU|H~z@"~lFv K;IicG й?NPA:GhZsE0|"JvlᰁLpc0o ?BLǻbPy5NkFH"r'"JT|6;cv|{۷AY c(ӃU@[R8@/L. n7 $ ^؜ ()6]Poz+ lf͝%Sl HיހRKp(Cx}(8?Nʮ;iِۃia U\f) 8 8ܩ(#i*|<>+^Nb%- ij aZ˜jNtg`AK1i4!R @U'zE_oFm&P S`!2jyRPY-`ݛtR% OggS@﹦0Es1|#"%#"#()""%! )(&}%!#!""(%)~t?'sn;pMwGc=ݡ}<])NG&L֫cIwbY_=vy!PW` xBD%1Hv~vY_ lnqV^S&P>m&o`A2S$<%L.6j3`Xx׾p .r;ZY Fcܧzs4>6d0#oqB\J3 wE]K,[fEۜ IOa̫DH 볓E|wӞ!6Z^p 6 ë/d . Qt pB Kj3n˅ǯYHz k4ʪ>5Z$U #; "Sl]¡Dp>0WkM`#hIb[+DGC(*TJ\ KoOO(`_O3m5Y1U ~QMi蜇\!JQ bq>fDla,%+V4E:^ޞ80 姫ɈCn}?I^۲ߐ@8寉/PsV@B!FAIa\"qASSnrC%ok EF2 ;ŞIKKk+ :LS 4Xu'^ϑQ"8z#^`n w2[7: _JGjG![Ypt,4J6HM 1|*K*Mt_OzO`o'Ʊ^5(KKD`$Ms@M o4̪ B 3¼RkW# .vdue|p :++m +意cȌ_T?}hngP䓗Cx냡znEw@OF+@5rŨ'Pihƥx;GD2HL .M>b zxϢ9FR- Bb/A'HD'REC4 ҊɛgTϋ+Jˊ/ ZGJphCJE0@Eepy̰]p[(e,i"d J "cPr,h-чATL#&[NezV+7Qy>4"9ʹh˿ܜic6~ y\}5x=Nh%N*7|5"Cܨ Ll'~F˛#Fس5zQ4"h!yڡ}q@6pt|/ ! Lk{h89k<7cȬLß+b0"8AdY|SՒzmWfBL5(hh;k612nAno>dYh@Oq348{Ctb$͛7H*Z$[ttEeIo*!uPHGGzy\|e>Y0*84EDP8?>ʿtUy4R鶥B́*I/árGR5X _HwXoŊ8. 1*Gm.2bO !C#<"DF:}nܰl9H~?[]BW!dw"Ŝ URz \tF+ܰ yɡXY$*+?a ^zxp9er|9{_¢$CSS3\\i: ~x]lo6=h"UO% +W"my6@; NY4:\#KO psA#NB>K`3i2d,irb1SS;Y8 e)_2O#) "r`cn"C_tR@@/R׉7 %dtsTFL.P2I3^;t2ΌQ]Z_p*#DxQ{o{G?ːf*d'uZTzx#X,@u Uhfv F[X!OcDR up1VIk.n ~ C,s\'zs":,BB(~AyԻIm7Ϲ/(ltÀ6Q54U:N迺dmB:NQj E p Y{n^Bi&ל`ˬGR/s ջ`y2b `={m"P"p&V:@K*VfyZF0@@ondĂj ^KDKK042GVb[c➫{~cy"!S<$0d?9W.}] P ^y~@\X tB ɦN50X kIJMH ut,QQBEo/}*qb9/BQPҷ׌Jٌ~bV$ry^䆛Mmџ-z化9= M  L9h@s DnWk^ $eBLJ 6vm{v;ɘڬrTT iڰyb]Fw•xMW5)GDs6twR\Ua^UMԦ- ~Uj9igd]1*+^].E0%'OTR0\n)|&T:֍ cР~9'Ә Cm>9V_ ݶ'JWs.{qI?hN%Uv pPpUuq/0z׽~J`VD FN̊(@. Vq(9F< wqHRjihn0>0 OtR ^gpFhXA BHJ$,~ ĥXSuQB &AE) >J}=t&^ˎQ%ANz ˢ|(o]։FxoK뾼ʦ @RzӋL\gL!5VZX~`LGgqS2 !SBT, OggS@C﹦0Zp~z}%=F'*f͎X˦R pAY| '"G'cS@&6 d~3 *q_68'(``z ^a_`F' >rmA6/ɔhNrD PNo?<zE@@ >t@feN ȭW k^8-kuQ *:DqlZ& j`Q1LN|73;+1/~ublmvqk>t Jߐ0VĖ6InD2WndU%+zo[49 ~c-zɨHf)IJPRƇՏ]HJcw_(-׌xHŢOe*=*B']t5 )j8,8, F훁 ue.ԒEܞ=]¹ if)>6%lu®8 yjBd!ݍ f~NF 6h 0F Q0wPp z Y X9y ਫ਼I r=\>[6tMc u<=s*B<\z)* xbq|zYO8zb*z iC[vQZ;W(=P+Wz+*,%!x*bZ~ fm"hknIH\p(?{ֆ{N';~kz0BGB4u;DxKDO:&,3QT}`|lP+RIBZ Bť7nޏ%~tpcٖCSR#%M] 1$έ4O¿F\տ#N"X5Z"`  ->,_ |BD qtH#""{ K. ` .mnW*p\':YVfѢمd4;Q.԰A{2BCsJ@j!$&ڭjAz!q_t;j ڦJT*Ujt!0IJ K5d\ssNCG ^ u4Ng|BITb(oj}on`8H Gs$)* @*պ]܃TѮC-9k= L1!$eN;)J`r٪ [v`p"$h{nm&C`?7;]h8 ^ld[/ŪG7kaX9WQ X̬Gw#ɑ\ %+ç(r<Y,1!lQ F) \[SG*6U!%t̬5؀i8T^.':0m:GCo%u_2?G9-z_B'kWƈ(4p{KbX*Mጐsq,-hˎ%CC[ H=I{`W%J3b4xɖe gYCszZ p^ۣ*F X/[;_` n D*̈́5Yq2H>"Y|%ѣ)"da_p2!-e:_XkB/"%(qM VzhGFP+(pܬ #^{N`ۂdD0{ @S8R&~`7Ual3HCC@ \nq\$zq2H #Xn%!I7\nBVrĀ,Ș ^K.h >D$Kibf qL vU]!$|K:Oކ:G: 0#MO$Z@M| "Pw`.,4)r[D0-"*>pMLgM[\qSG ΃u*2*:]}/_ uDD\xn|d{2cZ$\iq[vhlaM@*{Qy=GDD0^:~"&+gnx녷$vobjDXNXs7Ӡu3 .\vD0տ LuLt 7@ >>p d .Dݝ:vv9կ!>1/S.Y椔0%X~/g$\mnC︅WRJ9>7R\,@VW@`4 `P2]].qPtAUQF2>^[ĚAt[ikl paxs\q"Jc-rc~aOcAlt#Zr׿}}j*v \]a G$gUIjb 6fZ`c cJ$+>b"Z$zp[lڂa `mECrhODD`-22q-h}'}oز(5V@^VEA(E(βRT"tPم1QLu)52 PF(5d^\V[A|V\> 8.T0'&%qub\=M쯇K7b{3nVQ{R6rHc ,B4.v p})cɊA@V X,)BW=k%Jk_ђoҮ$zh#H&b88TX))M(b9Ѹ{GOm~p=3?ɥc˷j%qņzS jb+D@0Av_@\!B]">k~-FZLpaĎCg(j)9/>;vB<nݱså\).Bҍ.qnQ5?zmP'eaMnABd/2eICC CZhhnP&,0= T}{D$t"4"\*On^jM#{bAZrsm/S+'V(;oϿCW޾}p0|`]XDfXg 1mD;0-E-]Gʅx!7p41atM$bnq,$Kp5A6-*䄧~i6xcB3AJ4p~#x{ęymNH6zݗ#8_Q}`ߵ`Unt n\ @BₛB$|OggS@﹦0WU&(&%v&##!"%,))J Ѷw794<~i_-wC[H,gK ޹vxޑ&AMeD aڝ~L*a Dbx?E=`z dP]n0YDQ-ȐznK=,nfODLpnL)>d4W?HǑ mδ@o,Gފ߻N#NB@ e B7MUdr+$N{aYnߪw:\JדN~RJ$2Zb};=0fZhc;~ XTvŗxDӡN?ݸ_}EooyJD(Xrwt'=pӴ@ fA,u%R&7Tqqp#1%h)BCp0+6۶VqA~upIdfɝa^&MmڮOw^M7]cin|[e~to%ҿ'e2Bu<]i9<[b0=aZkVZ7QQeE 7`d]Iܸ9L, <#{z2!~UKT<2;NCoZL: Z>MDDyaͼM{:Y9?cx栴%B"ZˆCml]L-棌WpqVe2!%n35QD6bTf%3"x ;qsAo؂-qr(?)f%=hai:vZHnyhˈJX<Ҥ'0r|ӓ$8=ޚuRi_rZG=/Uj?&HӑmBH%EV)ACB \n.1i< ő'{Y` ,~N7^rdEKH'n,5Q"h4Xn1޿a0+ٺ|F?ɪAʽ\J܀ B6!.(!!8N蜷X 75U`]]Ou%%FF6s25#IAy&7(q%ئy #`P=Uo]zו i ZxzSt>krcpvq"(~ˮRzW]zPyZ;J"Z>gԶ6jQ%QWBlm 2RPE~LciUQ쉪\*fxR=m/۞_ )ZTD1s .5e}C r>E2g r|]Q%(]#cV5&@T֏TR%#ic>Ô]ư?R9CQ }Vf}?lі5Dlԧݼb+fܺ% ,!ᔑZ-R>%cm}O&ųdڟjm6llM2懮xK),*FS;N5Lk#U/ 8QP3ĸ~DUЪ*3gschRh%f;mnoBDY#+>ᜂrrV I﶐ xjz:Tf#rsou,OXЯWwc}gvd-;FHT}Bzs2_bm {22j@Wta{#V7/v1q hzw(bRy I*~;N'iX,Uwׂ=)UbbpNwH0a^DcB"m¢ :`|Q6zBttz}'$\Z@ yFA-?H`dlFOG*҉"*~mR'BWIα*MFN 6m⼒&BP)o+^3K.\6#zt==⸰_Lq*] ܿb4ZkDdkQtBG-p YHr^GV [p>y(eQ6JB"DC#v#:)^?ڼpDZw Mi LPMX +nTD8F\eSXty~#[S1;9*doaCZt(|Bc I @\,Filu"eY"n>KdTKnշ)6ac-M֦r&7^]`Zn H) ne~'̿xM}21ˋ[Sszio@@@qPt<`f:_]YQD5HI I;NIVp/cYY N .+QP  "O%wÉ?g_^5B/4fq.w 1bW~,Y` k P ȇh H[+T]s"D" "Qܵ:z=Y ;N1)]vb$>ׁ_mu~LՎ4Sﯿr=eҨ:DwnhMT׆!q'h}bѸDT3Y~?=|3CYbJcӧ4QOSx? M_R6ZJ"DbhLmm;!r`Rϯ{$)5]lYyT:afL'sY7^L~YLQ&TYYrsgnZ ǬSꆬۍ:d |&J0vI)_pn+IB߃ ">?as? d*NSO9Ar/nI~_+m:8:>|M*M`J!@r%"f`^S ~J/ Xo+ OggS@﹦0"8?+#%#$#$(&$#&#"$#'%$^M(& k.X1k]9v(H6qJDDDtb O7tuv>e}yU 8@o*$XN/ {|y:Jnɬ6CP':&E6bS>LSrh..BS":pU7`0q;[ h8?x!V$jB^rd iNdc9OPy$XyW42me;?* wp8J*a~vlJ{i܊Qht `mRğRo _:Eo!:b|/4aL ) LOJ@h<nbPnF# %..Sr\bIwiذp)/;qf7Xk˔>axc;OIu߯F=;tl`ce7!>, N^dV2/Hx--wkB1IP)kfN%~hJbtbPJ>j&"cD|yVWU+jt nv76@ }p,#ՠ`2& ݸ >[6bl=.^-6՞Yb* 29$hoUָ<۝2w/GtQ'_W\\QQJ]D E @:ܬu:@,9 Q@crlHY^*Tj]Ao"%{1LjlWǠ㌼N Lz/Ql(Zng~ލmT@4q C@x$*T +P:{*H"ьTLSӶ?\ŕ/ HXGH(v䨇qeċL𚻨$>{`Rbo_^ PAz_ęJCWf2ٕr1u!<5ݷ {n?ۃE8 -n+;W؎+\Nj@ S":稜ŀ .SゑPIDEYڅVx(HVѲQ\b%SJWn'CDp*F|eI2%n;x2?{{7ޟNiO`&q-V&x6 }1p;G4v]xdGR%Op),>% y7C&eKA4$/Ι])8|\yay77eC·cYE4@2n]GK#I 8kNC{^C(,k# T> &H%.+?( Fd)RBǷwl{?: N @?w~I+Kv?(b x2+EI +!q~6f'bxXFKx_* Ҍ$kkuUW>z/%W>if2RcQ㳰XW]s`@\ \Av&.ʱjA(,&+L_KR`weW5H&d!jݺ{ݯΗnq8:\y<"; _?CqC0փ/n tQ Mu X+@pؒ[HVŬŶF %"NƘ&[|RY$""/|`ap_>dx!K5sa/? k=n ALP*HT]dXʃoLXł?UtҹBneL1y<|/B S"XoYW-Iۗ+wbZm9] -H ш$,*LB"(T'"Vmf@ 4ebRq ʢ&1,KQ5XK(~55t$Q oc1^\y¤U>p1,MK(< 4]w~|I;nP_DMg^]<ә\[z+ILڼ]$Ӭ}:\[kKYV$`[S1*0 ϰ4utt jI, "+@ȁW !7fF2܂.ɪB=>N$pt" B %)Q@H=>,;P:]uy7<_YiD"h3̊.c9`@72MU $wĊ~ M!1M VptG!%~CR!Wl\Ph)'\ps2"ӆ5r|O,R60 1A*< }Bҁb 07.| 42JGP sve!~-&fᛌ4fr 7r^w9 Do*5j;,e^<><7+P>pk i#A4Q;7 TB+r0E)`HP%.~+־CD l>LJOSPl{om4#"dDA2'4˧QUavq}\}u[|96iKKn&mij-܁t0T  `1@THf>.% cJMJ)>#o++r$dFLQVWj[hi'!d\u=I_+(K1-gd%싀Qp .Op+POggS@﹦0 J1}~25 t;ecKQBUsRU S=M/[~R>=L}Ja%oՓ߽8?gǺ2I)$Va) hdVH+ "  k*ު&'1>ec{2^N@D4=™֎x-7.Q|O/[V=PgS Xyâ $`hcAX V-,KN%`܁گ4sL+vt|EHith<۷=ˑ&[;/x,D&eBS@& S{N_@xtbp`m].tHX65D"Q-/ , fǜ@m)ϊJ+0AP!2BjD!> q1 XKH?(WOq oռf[^zb^+uƪB0jH7.?+ DB< !&!a0!"ZVr.Y݂b­f>wo@") 0K^^aż|يO@(qf/h_K @ qv*i*-V*2 _j)\.πpI! *#*T %~~9"0^n P<69QIn2MO9/!VG?rawC'|ځxlZ&pE5P܀#np)Tp3R f5Q XPK,z~lӚ:8%<@„ ~QJQhný`x|?K6ya!&ͻ-ޫH0n@@" PH  W=Bޛ}/7s"(x54ՠxVW9ꗉ#@|Onx6zau+=yq"23g_Lr~ٗ> PJ6c*b86po˅ AC` j 2 VvA *CP $܂1lQ{VKm9ECn-PyLODNHǑz/uO<.&>׻n0P(goAZ TSHQ <*}dGErQA|"vCkTݚd\܊DrYx|]2F[_y,V*)ko<tυd,SaX@[O΍Ҭ ?T/.VL("-FEm n kp8zsň$/=xw-@_4M "w]_S+}a9hț>Q|V$ӮundP P?ڀO7&d`DMwN! P]#o+vn΃ 䎫nAPN9/b <<Gڮcf;ұu|پg!^J(!>;)&FE@?13Q7EX9hAB~K6iN.(8nkf), ^D9=D {ZAm=F/ܻuKHN]wk`m1װ10"d!q@`Bq`=jD׌I^gDܴ~u:be/|sF ta$"ђxk\}Y[xqՂ! Q_~?bӆ*!ve_}[nJT] )@$G M@Vt+ qALf NwbUE">(=.h٤m<OKi4f]&63Eڣuv-1@PD"X+Be,r xUFEp0 h Wn-d쁗])]USjp/;ZX\f WfϺ$[گ?y3Ar h j@Kr``iA XA^  07`.X2Sм@@ ^ĚmK V >6Yqt.Bq]~t}پp?tSsw|w"/*!']+^ғgʳj6h@}p3AE['D^hI ^EbE=U9|=4[\ppWJ2xh/roM7Aq~p痏Kv$hEO RDUcַ\ZIi @djcI"*)h,ڥ~,.hu+XK6 b`WR *1 +ҟkق{wNg3y=˨XJL@6rwJX*AX'AhL**]U+⃺ӧX0-k6m//ذIS Fvdt*Ra|3ζ#c[n7fO^ÇNjL}&UN0\&)p,GJB7 Q7C֤$(ZC}H~Kvin#(\X^fKثRSrTb9i2w77^<N)H\HD*c[[4X ܀&xQh 0B+iE=`܊cͥ>`$r/EܑC+% Iƞ"*_x~Njy Ԏ~M㊭Q}Q7 r?"a`-5* 0b (Sl t.Q^;n5\ [E/C;0)2 D4c4''v=ϜofNGo2̒]F+-tcİ髯5@5/`L`$ R ,>~ɠ#Ulrx9xQO$ D"J =;oGGGvwݿZQ&mJ^kĝt/ ъ ) K0cL`0WKun 7T^0ǹC\0aS:{_%ª{쳷o|Ǔ]e߬>Ŧ z᠆sMv3ibئZcև%G ~k+iJ%1x J&R#Q7j{}Ψ)/+ɷ%KOߴ_o^y}Ο1l.G/g A 3aV̠FpJ ,ܒ^T: z D ^K6i 1'R1 c=9*x"HJD*mڇ̓&V*4itܽÝK|poht,ȝ06vZh0bS ^"|HmF^+v㜍x<=b6&o?spr74x?PU$B"'o潔׳-ѿ~8uώg/~{~ &,2:%425y JϱXSF`iA)'bD! OggS@﹦0 VxA&,'##"!&#%!('+ejFv침hs>,0]@D$̈"Hϫ7;ԁ9uigO^\ GƯ~y]VL#9:`oi&epVa !5 5q>l㙍Y$ު8rM@Q N8*WTdw'c_lhr9w.04^Zh7)% 0cL%]4tB+aYʋtW"YӸ" Ei_ߣ^^뙋,@hN\igcSxj#޻J^$5ʷ]H;a3kgQ̐!Sˆ=E H:阚L8hpZ`Vd,,Xp&A _Rч*rPYłb&{ӥ٦cc'Y,ly1\73E7WnϿ} NH:Zd2s ,}݉ngb >,t&8:)Nv)!r^ (j(kh"YģO^WODq;cc7q(|L|o75sjV*U 7qMM$@;BqKĴ9?QEe n@%>v =P.{u=/^}.?Onq}af5ֻ~uG1.n% ?N=t`Il4Ju`ɪq[ MTT: )5rÍa ~r/{_b>5.x)Mmc=ms ퟿;Z?/wg0sHa#a 4~8,Cxj0>ˠD+X:Yc:Ie$ª .b\ڮPV*챑;Fe׭0?ۧg_Ϗǧ⪞CqgwWGv˻;Z~xϘǿU]@mXZ5HpFX:.&0"Ai-VJnbPu 4مKGmN E]':C_Ͼ* .I(Wf,sϡ+%0J"E$L4?R:%ԝdT^kY|~ަӷ]S6-)KQtVTFw9t́F~:^{Zet"{u;.2eLNLbz*lɘуtP? G@8GU1$1!RP+2SB}sւ{&>zNLq@A^!pYZv/fkcg_yP\ |@"B^gEcEe%t^]p\<ɉFDK;/ٱ돿L?O)(VX?#iBmH#T4 X,2XSQ摕ׅNH<rq^ &&a:s^V\fn1,`79GE" D )Б<]AO{^秏78CU^a؀ADx4%@ r5WV\H! Vʍ$N뫼+S<~)E6>^EpTJAS-V0u2zKڻ! ;(+\~ *"_G \ FsM9@ ­($^-gI,|tn$?Ht8*R"KhGf [OފvDZ8y۔'F[&ns)<p%tvDb18]HbE8A7Ɉ$Fq(@@^MI7Hq߃h>z:.7^jܡYA$}]o~Z0Ib" @OY7 q&! l` a*Mp~ ,l.&M5Y~o/Ok͵HK~UAw>J (Q0@@&\Po'q,{Rw=Fn~<~{<AyR9`2r,p$¸ `YNȔu\(!$"az6'7v#|lni K۶ٜ,R/cW[ADC&29hkt_@R7x:D^ON "9SAP܀KT,Mڗ%q?+w(mT)!nZ# ,OGQVMC|TݳD:Sx\|߭%pR>%: $EG4,Kz \l9W, j"Ryv'@e5_M3N2G b#6O= )es5k0w(7<KsBeSW_J 9q\3q\WaZRujl 3 qKl(Koon{ZTT]E*t@LG4pbhf}~3&#qD>1):Ƹ, B9=bC)V,1?vYá9o@4Q""LSs~:3rOOY5d_WA1pW7IAgb]!U;@\@7x@\ @7A p 5[G$m[9aE$U$T%վ:J(L隡mǍ~pWv]s%BODtw2Rp}t_G`-@ I7`ѴWVh* NP|'2XvbH7.nBe*+,޺B&g_Wͥl!>Ng)HZ[,G-Ɖ(|LJ}'ؿ:XS]7s 钕F7:J`)EwZE41s `EKWyDqx(GY꥘+~;nFNR3?|T0 m-Ox+R`YNm7>. "Mc-b][b,3yDwR)Ƞ,YLqqzĽlNר,zfL1:]6BØ]ZBGCڧoDƓpNS h)!hWN{3/>v =|};BlF:HDT D~=8Rr}\ IL" f?gZWkm6 J\ }pH܈=$'@b sc C06C3GGcv22݊΢q6.c^_#wXPo>땲eVAhv3<'I'0@?~զ[ Bq5G'2JgGúUڭuڈ A-;*,-íyӝkSJ$@Y(7KC*uYD)є-U,\ { aWZsKbJ4td;ڜDW0 :<][+ vY1t MX,t1`6HF=xKM(G% DzV$7TX> 6gA0ftK <8.v5)  p\Լt*''-Co޽u/Qk1qS&΀n%B2v1CĄ 0:g dnŸbgHCɮ4 RJfDDSVp!u7[)+On0 gȑ<ZG˜,H61U M@*@? F`KyɁPl5x 52BJ,!k|)*J=MDIb=(YG0ړ OE.tzUWM]&I,(K#h>1Y˻6) i9q&sоiHBཁRHӅqir P (EJ4MY򛧌2Aln ]mXMSi  DGfԼ~}rF[纭?1,MK&Mo<7[jM|#,MY/cYO>_,}pެiI $bc7 UA44h\کz*B4O—fZA03'kgKu_ϴ +8)ثba|\D>u߇rxx BQLYJFWS*-11iYsf6wTLWJU X8[;a3gë'rsr5+J$3=(p~DE!/P5!Kb q4I# z{7tXΠTy$8NG͑5% `Um ,J%T~mec : `iz.*AK 1`%g(b0Kh묖R!VpdV$2GU S U0@4Wbn[N,/"~&ERuZ4a|qE!֓r; )-^U cݴx!'.\u*]8$J!G.NX$5Pw\C nE1,zk , O<0 D$ΆYe=-+*jˊ*!a7_ckGQ[$+ՙNpq(1 1IxVX[Ʌ~]q!r5uiJJ9JPH0KDV"랆Íސ͈ע*6^"]uv1mZazI"  8ع1-h=42"^evb BGhd'XD{LfZ&t07Svy{!rFtbrmqnԖ!^嚧!h:ih.`$H(QTUHZ|kZ%>~,U8`v6UZ$3=1OHνmm#)76h ~h TH@T"AWbTԅ(NғL&C1R^jpҋ!D4PctGN!6톍tݥa$[H@z*E8W "Piu &*uc XԂ(> vB.& K//FÇK]W>MT\°7Xjv^~,̂;1y+Etd OZWaA +GBVwNAh"]>X,^+6i.G>p&ܯ]aPe"AڸZ} qa2$B<2iӛ3obvǺ5O1h(*<NCW *yb3?Vq_I;6ux 7F+b< >Z?QBoilա=smdڳUٟp[0]${-tr~0=MbV `Dn QUbxIV@t !!dAh. 0"шnOggS﹦0 \0%!!%%#,(%}{#!#"%"''$%)$"$$)i@V8N1:^gQ~lKgp7}".[_5@Gq~X(8~+*{(H4ccK&'45sM[n+P;zJΥAN*H~ 6_fm=^ߜ%ɇSgݪjBBpF@g`-vCw.N' +=*gtq$Iz8@$ ꄅ;Xy({N~,ƶ15wٓI,c?-Z'>icg-k2ÃEꃯ?QhXxܘ}OptDP6_LD7 ^OX nV? Q`pnĮ~;eb^ʌz%E2= CToH4,vS AC[D]RoLז{|^clT7EL"ۂ,X DX &<(heC+oa7C9YK9Zh<+ʫDQ/q)K;_nKvu?<Ogѵ0(Gzg$|н{NU+ N|M ΆEA&@z_Pƨ1X, O] ־V{m+//l>Z[? E}5{4 `)J{0%'ho$ѱW&Sj#]hLJbA{{ؿ6:B(#uq@k-HsH7̥045|=ϸ@hԀ0j&Auk*(( g+mc5lϥ)r|_tzDdQ6"<~/wF*軜|S診VtKP v,\((jfa$Ql&d['^p .ef!k|,.t:3 $Wd$ ;\3_-$ p,ԯB>(3m$]qȎɫ{E]P>x%X5b;L DRB] DX  ʕ:eE*$I̫]/\.a];|%pu ئEu&8{58%Xk|Xwz*7p2XD+ 'ִwF@(k&3}psK.%KF+##@ͯ d 5fׇC<9y8V>s\| :J]|V9 X? C@Ŏa`RgM!rMz|܄Zϓo;@W*"B"Avrד5:Mj }M^1 >g_B23Y6iDPH ԘO&‾aŤo> "&+^RTltDWʮ8/F1 prEi&m~!5ZġO]M2) gr+VwE5`w2l" `| ´!D9\ e9/@Q]\2-.]'K+cPU4" JL%+_uw7>}>ljּ@/`W[1hsX+E4 0ZS͎0*n"x YELbTajBYoyNͰ[+|;2BGPB&i$}>5Ȇ*^+LB**[&D4Ou湵p@o|aNB!%d2D1ꄲ=˭ iҘ{8]4m5u= OuL4DU 3aϟs|=9:䨊ڸTD]$'kI-tVE㞊-ZM)pkh2E|(D>>>e6O[.Dw JyEคg4{J.cg`􍶇ȸw&zӳ@"' ,^Gun!;pT$>{ )ygn7+..CBknͳ_)S)7$XP*O#} aĦF8;;UDItHN  BhN($ AiY5QPQ! _%T b޾>+eWA4J+ɔQ&iL. EԠnf=F`@1ٓ|{ =U UT Y>t`*5 7AC 4mȀGZtm8CRj U^+־gpxZ벰0H73Aoh{[wFۇ?_Ur&C,G9q&uk Q!6RV NS*su<| :t`U~#bD(#[\ 9,{lsW >5W>(xR-aZ0G7ʄ~ 8\:m&sk˿* |UU ︬`|A8ǻ&U+¹$N P "Cgd#71b^|a䐾X`$[f;CWD}B - (՟(@oYdSh]}eƻܨ;2^v0H`B|u ޯނ2poHM"& #:iFp%^[6IW/[t-F\4*{ nyPDD@UfVpkJW-AxC;#n(з>,UGh[$P.I7\-lqE4@`MB[ed<WbH)QA).PDO4qnEj;n$ů,[|z}3ǨS>rͽ}S4+Ҿφ0cf!`SH}WZ.\6]SK`Ky=^f~] N#k!)KHYi<t1~X嶮~)֍%7OIņq?x<ߵ>{*'bîH$ϚLG!IF+q'yh{3yOggS@O﹦0 ",),!&&"&#($!"!$"&"*'\YSVw8 2h>~5w·Sq^LDUf<*uClRpk^= U/;L,z:|.j;\XphH)ʈryZ(#CuẃEHOHAq!ҩQ:ϧ_눰*uO9)d5{ҷa":-`KxS _XDrl:H\ *JGc-PRǧ4l@H DbU\ m$dI$ j 2>r;"A"m/kL v%)}+.=.b𼰰F{6i-Ne,H(yxaO0XKAcc2a g.@4pT0pJm7mwSԦ1cYi9eP߂@ě?|=OX'Vĵn6qEfBIqq6pԕS"67(}y"^Ŀ`Fh!)s_(~!aq1"e*"jKH aB6bJ| R.<#R*%vLבdy z0 V2GLM⧊Y' W\?%w4ʳ'{\{jXb%c.0ɽA0 D}l_oHq@L17Z qϹ +oUj5Ą``+v]+qIF+e"bjCܣ7HⰦ>NԿá݉+Va-tt}TX#ܷUN9H1x~j8A5~ߘj=DJ$fiF JdnJ^ne,("=q11jy<рVmHCTCZ,rZ÷z$Va@Ju+*w9֧g[@0䏉"= M@;(9:BۊYd :Mvw4#WfNc1c6+X:ƜKh 'Ps8ނ*S7:Rb++IѬ%a9:% 8$j DX@saq"ní#Q.C2˔F>K=Z;عvV|L;%ޒyfTe,=XJҋ?Q~ZF%¾\4$"c:6a@dޫmc7VgHDNENxQO s&>c|X>pX0H@ȻiXZDe  bE* Eh~{fג~ !c.9ZM0L3#?؈1eU":QP[o*Ԟ3mݲLklrU\x+ǦBK4%c,\51y!ODDLYF@+KGy$U ׂ+BnJIŞ'YP32Zyn׫1Ż#zd":&7N+ /==͏ӛʶvkwIRK-:RbT"|!'r[w7γ4ijzxޖ'G^JQpv0ErF=}0D4˳݀ik {id庻GC D4'"Vuegf'a}\/LSjM xl~6gTQMT؃~Û=_&;"_w|+e|rVKҒ\?z_#Nvt i͒vNJqU\%L+6c L\X>[ј"/bua,75# MJ#˨ b@|~@*`̠;+P tw{QU2W)/b{FЙ1a8>-2A?v9n P-Aj*:3Ěp0JǚvbN.r!VX|r 4^Kl)EtJed{ज़MU:}J ;Lݿ8}* ח̎I%z`ҍi?0a-c=K5TIxou$X “AHCt)^j%.">;&6p*BZpq`Wh"ҽ>G7w3[}2ve?6*TF_ue \ >Rqu(q/cjwEh.Y5 D vcBU PEfb@0z%?ͦ?a -px\}>wy8֨#=ƶ{YET L4\z&HG:/\9lI<UD_֘ n􈝻hR_pn-e`@.ȽϳZH[n-4}, ^WSO[ G)Z;jЅ&C/FFAHiQOggS@﹦0C\+&''%&&'(){#%$#"#)(%k6nxaH0gd N?/8t}$"~w$ Uj9iv{~)XvU+VdV~[4elR1A   c/nj UQGT ڼF,̻UUh3$?͇c@Sqۥ!vp~i4.vV̈khpBAAtLQ .YN詵isFcE&P &ǐ`@ETD06, m 6^ eY#s7 V[EDT<u[|kk:kOh\Zҥ'aBWǼ1h u9N>[~VxUA,DD49Mג&\\ÈW>S]4]!y0`ҭ ]rIAӞ`zv H09zq $`l~!@L{  @{tfH vDҲXcpUDS k v_7~ۑ7)iz;  ^ܨZ*D6X/NU vGQi#,"nmzH%d7[qGZStĖI|Dc^fFVM4t|?ׅ]~]il1Vu@ cu]e&mP#.J yGrDOJKQ+^ރIT ~[5P-p$2.aϹW^%~XzxYLݲ7ߋGT DG Xkc#Ʋ3p)E/Md|ܵ0cR0B d(ґ .RD*6!^+nǸlcCŶ.B=:݊m;G@w%?.-/F&#|ާ2@FmOGI>YhVHƠJv pK nǖ>U0rwP2f42ƨ"Е&Z~ f˸܃Z&%.3 )oܮwiU=DDW_?Vv9 sm7(>Gm|vf>g!Gdz!T}ᕙΡ}Krқs M9b*WW GwmdI6V~|mwt6Ν~wEϯ=rYzޙ;4^ z*ڂ bWP,@,?`"Bz V d 'H7ops򋂻u \s}Q8Tg5ɮ[^U+~Ulx7  ]O#EFڟ5M%wSx*T цG*I0.7FdP;L4k9C6_|SF ze5DGw5+a54Ie1Sf#D UT?~A`t7ӸhsZS>mN9,W]ٚ~:h=r~>JO<Eձ3oH\gO(حDA=4ςVT+g?r@dD;,ÍӞ=\a㐂%K?Z!~o6:MO bTWitUPl} {02%\%yq-):LxDS33y/I1OC(-ds9-Z*)r2zUƅ=J9 wq|uVFNŰ.U%BE&~R*˕bf^kHmz@]!WQ ,eX~LʛIa7>9=8|hi0y! A.iiWo}W%YP>_,nh5de^HHFY+ ,>Y'{qCZ{}| IxUS% GMG>t":.V5~=㮯3NJ E@ JJ_1G@bD)8;0딘p~[q p[fgGT@$녺鵋O_XeyWhADD qZ⚑7*LB7-]_,q|eG.׼il< Ӷ@PI##f܈ SLĢOI,"q~+zd+~M1-}߰W.H)%*@^5'*׻?_=;7%_P $;;6'EڛmRK- * r{x-po'55 ;r Z82>H# > FnI2W0.kV-ߪ/>SŭV"(р;G}ﬡ[tf P ||mp.Wi.W J@O1 dt`DʎgP>!Υfة neo.qZBJ0~Ei 7,68ݽ&R44;09m&Q!hzinpi &ے+) NkFdաX4 $eD uyjIoGxFQ3fUJ^k(]&ze<_.ի2һ?G0YOfVg'ZXcpy rFIoNwB$O嗫H1e1Qyh,&*X-ʫ Wދ {ι~Z| H58D =jLw4Vfm[2t8BK0-^,wF8-b,gSޥ0 ?N3cb"aq"RE.ދxeR8 7[Hk}txl}'%ptí)uguZq`8PYhC`-q+&6JvV^[.}sgs4>*,ܞ;A׌jDk%K6iJra*TTY,pS<al:UFJɀ-W SˆU HkCYD{[6ֱŁ.p!̝4FQ-*tXgGǰL$1% o `.OggS@,﹦01~>[n^Х>п)q"JDx14X6JW-O=ŋ7:f sqv?a"w=C,k]3%Ja9#[Ƭ0c M(`2zQ( *H,~M .7`r*1:GWH}pן%VP3A=st2.`}j,Ytlz"|qoDH@3IJ[b2zodc7g=l5'|Q7 %"P3SKihL񚨈U@!(t_3XMC~z,&DȽgSZy b|[!EMDqG>I%v9UNo%') Cw'1)m琱>w\jpz_qK7|>5JӈhN ^|d \L#r}\8V?=@:k9d=\=/?:.ruw(ˈ_}x?ֲN:7=y,v~<}t =r/RN>JIp! #@֥ 7;GƲ(CmYU.l6C~ %{*щ1h}OVv pEtZx0耈趗at燹ɦO6zexӶ|8'ɰTMq֦aX~[kFւ6| m\l0,Xj? *=@qojy<ʣ;Jj2bKi*0l`Y;mIM ZaО  =U [Hl8=f[]܂Ɋz_8XoO1p^`%Cw*|q b!U-C{@E+aWu" ;em ǩ>(u2ӡ<5oM=̒͝' y[K @Pݩ5$ĪuōRBJN].p6Q _b끣 ltc&jJa[~+fO ;$C]@pr^U}5=%{O/+)LotOW{,:m;7j}WFraߦ=o~5^ E|Uyg.Ok~TY7D+nfr e)}~+~YV,\?t)8`Wz'By"J:}˳Rt$whf{C  {0회eou|dņ)R(w&Ӓ;mċ\unV DDpmtR $+}sZY.DG8b'׫ߴ+#XO񞴣X,E7h[e%ї%˙QfIXR.pZhcK+#aUPۙ&ZTidYt2s T. X\kNHTMY 6L WٳIR]O﨏_Z/cV|z+(]ii'H "UsZu.Į}9H.P(pp8oJ5"NX\{.qG3$r4P/ 슫E'ox~w-"C0?=^ɻ'n>C 0t[w3+kTjɝ"kCYn>j+aȫH 55b覗\Z+ D9D>[fqkGazX=K]PJ?8;Iت0^87pVۯog)t 0vD{1!S6Ś%ri2fl9P>,#R\|1y;`\ T>63~ Xic=W7 /Vn.<߷SEvKՎ[)(|1׋$!AbHeÝ» jsd٢jEyY7.[*ŕ>;q I AKXОeYX.S X Dv|QEz}i>{ Eq˿Aw̬m&Q2;@'O F@mO:?:llipkLX- 0/;B_ {vnL飬kNe^H}co{ՉpVԩ&jܣUkӶ)6c9jRk׮uSq%c(q^|M)늲_O5{ld0BkR_Kvowկӷ)Z`$M>|vKC+f׎H. 2(X:gW|"p0m S =.cڻ>s8t .ȵ}yDkں$-:<kVfϗnjYNVA~z'/OY(P*P\k6GKVY52Ů҄D.Ni\ =g]ᨶj1%|[C8m<.tOD˴:\3ZBHEH!4'{$EQd[[&e uX'(0` .&9sV,|,%Vjla4#:iY@]9V Nn{"ϟ.uxE}Ȉ(THeءJ3NJw,TȬ[T`@ADުє DvʳlG_7ں߿z[,iwEF Lx*..b u۝2|b=zL(*f53gnz|pr w|DLii^TNX>H~+fZ.{ɑ6'"ٳVI$-.5nf^ߚڕSҰq<=/K_GTFx:JT1~)b=#'HڨzӿUw_D'Ubh|=+5J~)YL^]% WhOʗOo{~J܍abɅ3wQn[ڑX }NftJ 7#X)IV-۷ij?8Lǹ+";+q'H0%f9"YJwSBJ~ؼ?7pg# >nzb C 9tFȟp4+4Taһ'4Q*%zlXzVyrE8mhM]>+nX.p"mT?*OsSo(E?=_osol~E+{qi}Umh\ѼIb*YCP( ao_8Z4 Qil*e6E )ǥE2q~K6G.*H8}nbeQ^?UCΌ{^?]wy|enn^*@&uA& d0()ifxvWE"Va"a\[Ҟ|dX2<+Mkȋ[Df/V>r-ƈxbӑ@UYfJA?q{wc[,6~qo9*w},x"rr RH?f4<'\fG׵ d4;|6I)=ҁ[.DBf+4)l]G_|S~gy D6<2h֑mv5 8+?&ަQ3 s}`H|q}u:^AJ91^̳|j1Q۫-OggS﹦0%(#>c Y=R 7^z5q߂-0q=XEK5Ö[{SAOa+}G?,լPvWnwessS7K{ @ O~%O'F 7@%8$Ll̔p3`W\ 'bWye0m¾ݳВ2 ՚YaG!Ou 8.BAT4ߟqtk:5~-TA:P[a[QF;Uߍuc])m|R?pC~[v50<zApEL=@|s"yep" 5|Jڸ'\^{.:e$F;! EW XxeB)y:OC<7vXn|ϙaƱ(s5J5+,%Fc"b"~ XK/ `avEì-?pzyLh|PEv[v9.0+b1ᦺkpdzʻvı36`ƱSG՟K[\##ɷBmGJaVNtk <9`)쁏 <ǡ?M p'SyH$ggPZo~%cqg+uVwg:Y-qvFׇ H,ݰu^%F< ! ^ř< ǥZ1"!Yf-H@;Qbc%1n`%^ Eg~wg(+&Fh>taV/U/@"O,@m#hݾX9!J4p}aaPDR΅?! mb 6껢]i;jA^kL$<BTb}%JTǀzSONDK78%]KA,>L[uT@x*1;p՛ؒ 5,;{toT$F$ %v,ҹğí RyV"Rab  8q5E^01!,BTzbIEx"zs,1竧gI X [Oןwއטm<>wOvcI=QMfKf:T*@sRi5$t;5fZV#7vGdFi=nze㾚ƞjm}1Y80Ѻ"),)!.x9i{P[D RGZDv\˜P-:EGu OMc֪D,rH@7xN;Moh öam./O\ =xX$AG< ISnj.bKVE(ե4` =_Lqȅ۲`5(^KE^>+rDiSc.`L0v3?Q?<ՎA=[ =9ݺM1pTAk4E1Ւ]yR hY`!A7 7@.(FI#Fs]rX\4F7id.*FZ^g.y13s.NԂ3r>,.H/ ;ַ& @nݿ oKb<|A c@#cV4'NVxflzN(3"Tj&el$Sg^:\[I}V 㩉 6nu:n{'^Y߽uX[\uFF^P].[lS55X4ͲtRYUg[bRh/xJVY\!E~R'e©Y\5k^1Bx'شg鬦ɿtUYF'ʋqwc6ڭIFyUȝ\2PZwW xedSu 1'QjYUerm TpLɢɫqGaU˝wZx59Bn81l<^RQ qmv ~յ̦ 9t @N{. kPd$B 8A'&# e @ _Ql DF~Ĩq?QZ6kww~I(+^;D; :18v$m]O&6q^0H)"klp2I&@+ JV-:p+KD a;ozA+^%PƬ/1:Gս0)O^)NZxg(3s۰>2MF.EW%JLj4w$cFZ^xWo`?~66҄@n`vֆ0a(Pt3&G֪9qo}Vs4=]]Tbqa:x=] DK1MMj&VmUcbThWafAHSI,%ܱ9F rg WP(wDn⟏DGʮ";VF'63,(T栖Daj4Y m7Dӭڤ?:j[ч͢OQy;,M>^g8%>}}^cU;0dھ+u]5ڭ}Ikw8k pus}H+a^KE/8`kabɳo:*.Lk| h/C)DoW; PᬰDKXC%>mV毇X$vYjr+J)W>ݮ{uuTW«D ڜkq`Sߟ:MjZA\[%Ck~.a㻳udE+-# /<}@o&V.yRϪOa?1ƢkBtIѥs : rO+)|n_PeG>Nuaš0Vao K]&+V>+ix 1B(v ;NG$wɚ-6| ҶV^H w}X칏}4*@¯@`w}²cy5'у jssK0tF@g-aNwk"-8M~mvSW!D7w!%Q%HXp~;NLGXc{璵l1CjW.` Jq>zs4~\X0J} fLG#IA7ô I/SҎ׍{;sq/slنSQݐ+0tw EXM~+2%](kʍ3PlxhV˱pTZUӁ,0G`\zws-WuZٓ&]}nm=F=b_ օhB$-"CqֺEO<NI`3Խk}6κ>a#}iBxwgUq0R`H >f !S1E%vpZ!śN%G+CCHf:0i?n$u_qӳQ$ĖM+JkD~YrZaM!"FpBW;m,lbfg_`ʕm !?/̽ˇ;1zBZxXnDKd"QYH+&RJeֱ }HJb+^{#M|H}^8*{`:Hם1ƷUׇ!fOh4Q٠qc֬zz+*K^o{֪N6wiz#w^?7[u>wvpOߵ;! bep0>N+IjɎ#PFT6pV pU Pq2M{-}n4HkBnv7N|:C _;]sINK׹60F]n-6]|?x/bj"\X!}}?ar3&R  ȸA+N)(1P@J:DJNX*858yx{/>aI1P ?Zw{"}[Hn~Vk|o( y70c-Lٖ瑐f~0mU_rfb6?{)=7dߜg6Ϻӳn8È% ^¡گ$Ȃ(qn+3:&aeA?y<`9q\SI' Iu5ccƍW#q}' xtH5Gn֐'7>R0D ):Q\s& %/RG#UF > .D\!R[:cs:|> t'"R8;gS̼]%0QJw t-L"INgvQJ^v=G*?fHf5@hxg2E_Ӭ-UO-Gkx tb eJu+m +TDl 3YBBʪm Ta*D\P}/'ْo}>qgu|k7DsW(kb] b?A oa6d)zc~ߑ5Ͳ v%=C6x'`!uy|9b‹~ZV YkvnBR(Eߎ%-D]]'~TGp6G`LJd7Zй_:vtJPAN_6WmܟUu~mV otWVkFoYv&1q) %[^.q'ņVTjpa[N2 .*֒iIHF.\?.TҊ>{ :w\ŁՕFvl|Ǹ|>~2X׳|g Z1iH,1{,kIZ?so>aE k#ۤTum^j r|ˢZ6P"KN%"s9N{T8kYq1l[2VUNQۅ% #FB/ hut vh.@ɚ NY_]Npgro8ZQ?qn\5gZ;|j5QLQMԊ@0^N&6lU]z50BO7.Jq0Fȣ,F D8|w{ ?~ꪬ턐 VڛDf`4.'̿ 5aw[qtpnmY#I\fխ4B9GSM\ʩfEZ4o=bT \,;Nu\e۰5] nZ'.5ScӁr 0湏IMl~' Z\#V{nӉXbRw;$9K"L[#b`Sm sSj|C͑Śk-Z]6 "+ ,0ڥj!>VR9S_Ցp.OpvMnIV\7 mE[?7s"iZ.m@N}:̙]Kl}8 i-gםԃqUS̯l=D2}NG2q59PH/u)yzj+%OggS@N﹦0&¹ȃ_M2W랧wv{u8WiF?q$ss89x1cuRÍ#Q;??OUZȁ1dQv+tՎ~Y Cᤗ!z)~ӭ;H !V3[24R waLkt0,H)X~u͕af ק6g5pƎYNN/¡OVSoJ,޻0j}ԥj :-xF>?VGj vv#ndqRJ'@gH-Gk~E[rQE<a%CDgzp.Fp _$K#oyBO2jNf 5p*J?6zfZ3G$gk{s+H|各gu҃<G  8\kcuṫ~hy=ke^m½֍1[>ϧI=-FyNw4N}N u>ӓטI_wtr䁃,_vgOV un=Jڬ6)Enz;1|_ ~́.h{ý\(ae7aWjP3\{l|L[*5!6)"HwnmTZhԚoZWs>&5C0۩Yww6e;|;wvS/t j,ۢMlǍ組O#u/4eV‡rt ^,g?Jd2C'؁E)`f6/=$6Ü0vmߨ. ٽ 48vT= !0>ѕ;g}hwڽ ,q'!t/|yx {~t;2ĤE7NGV)],VHZ&UeO~atD~+N"7ݎ.ьhl=\C7XJ)x4I.'7, 42q\O7 4`ng4-zqm`Zӯ$Xi|>)8`}Ke~S=8/8R9]2ޜ0'O_JLאͧ8n˔i\1B+|0I:Zq1aZB80|H)O,Yw |3]a~b/_Z#mHzJefk(y[ʡF5ξup+%q%!WƹSP EAQ6(5>Q ^+ZKcՄ_,oCi্_rgT_ȍulN<'y4$! F R!iQVo6}N#N'$"ߥ~ rl6#mľxdjY>!犄J[GSܕ +́^B,N.WOYeQ0Y XZq,׵ާos/nc4d]V'GR7!21 p_|p<E\YVJ5um1n\K.Fi̒XЌdM 1ɽe N[nC߼K{XPC X$$vuw&GsU͍rYYhb4qk\ r@Wr !8236;mG~{_ETeOA_څ#Υm8߿߯{vjcn>5VA*mWMHƬuǨ<~(,n-.KN.Bztkކa2Uեt8.MYR"N4G?ήgÑqE Zc 5%]5?3+:&~8]s%ATs>N!4UܮvU;31RݍWil%W'Nic ZXEѾu:'K H$>+@㣭eUlU,3OQG=b1ܿ5]P@Q1usuyWҧz)_c&3/, sZ}ұzRގ}ɫ޵>${KN >HL%|"eD ڐ !ط{!!d{ݦWtéT kt -~yqSLQ]bYa1sیQ'x-.@^;NLPË3fx{ndZʡz/)pvLM_3SwE4$4=# I`->6_a4z\k4D6.@i_ؕX_.o@4g6T#r Z?8k(U@un{}]nbgiD K΃ֳDjڱ xȗx {$,6cʍ?iAjo0{][ZүHfAP"#}ܙrW>TW~TxʞN5&\}.9+!h䫽!/J&Ii=ra= 4uIyG?x7{h~@6&b #-Q`H}Uo$WVe>v@_,Mʝ)aM+AS!Z˗J?~8x>nl"]J#Zj% blk$ΔCkY>x[0UVNVӭ׆me(2j{EZnc@Τ '^iIC/He]#l Z  w v+v́鰣5cW?0d;pj #sl<=<++o=q둕$%7vt?u94!Z_g7e?Nٚrþt 1i}6yܔP" lov'7ԋy_kCĎKXI@dwyDcp w(@Q/!u~PB@遗xe der .P,5Uxq?NGQ= ٥*$#.qR޷/TӁ{:BMK!g]Vv٠ѸUA)!d~S6$knƀ 5Zr*d'IN6 ܤv.M |Rx~ާ h#B4& &% ٹݹRBe*ujx/}x]uP%OU"KQ,Ԟ 3Ba JXش UK)CyzfJpt>N%wn gbziY* nO б( D0-NQ^YP#tLw55{^cǾϻzq<9Nos=VF6.\HEET!Õ*HU]6 gOggS@﹦0k2! ԆU$kNnǝwL^G%4 ~m+7?b S^EL1?2nހ_^ǔiaRsqEnU6O6oۉ.6""Du]a1)Nd1uqvk5WMC%P$iDE! C{/ +cqq7c4p&SR(Yb)8H3~9D5)GOHT]9 `Hiܒ^@ q  #>ƛF3:]*4l?u$ p-@|M+ѸQ4pNY&@ @q㡽L5|2Wzm7%!M˓dMg:$_gp$zkIr*SL 8B8 yu~GLk0+QTt%*2.bwEJt+ʍ 0kC-Tڥ0;%<$;ݦR\=0|PCiYT>'e?]|{BzH o"0&AYutCh "Ac L,tg= $yy7Ś5{ msoJF"HKTð)wk cZtURFO~zu@UVR A0PS Ǜp݅zyo-$m?_&(;a #kYϏpsDvHuc\n!qPorJ;2<bM Ÿ9urT:o>Q3p5*~BɎ[m`Gg@9=l3 FL"\Vx&&u<|=K cjEpdtb@Zc:Xf^6[5odƳCQj/Xo[u(?#W+43u[6T@;φ&vK/h0."avL +{ogo\cM}@h1uW{ 떮v侑Fsdߟێu$oF7(qQS hJH}Kְ龍|Pq]I,b^KkP.Ŗ) v~ds6a\?iWSǛIwq](VR; ސѸhʆ\.j -H|d<#{4Z?yfo |L`!WD;!IÕ~KRDD^zTw&,,F?HJv{"#D9f?MOvR8&G6ΪJ^_)o*@ |~6;R@XҌo!? rZhc;|=$ S_/JXGq+ ce'^z)@;sPN82*`GSf6n_H3PEAZ N-6YJb =nv]Hbw#H# I=Y˥V>دs~ogU;(rE_- K gĜ^ePs2r_ H0|b ?@P R{./b?"Ft g*H25SSismKIxq~=e/9n3z)oMyNv39Kb_i5ܙtdbJ5,Ik~KPFBkAeB\抋O-;jR]OkhX̗ E?,ݽ!;s_kvv9TGVH$LI%86Rڿd jW!"(᪁!#K~W:v<ѹ# t,]r5 BkYy) *0/](S<Ь@6vH0ztH:%‥6 zT͆^Ks`lg9us!~3[sޚ\TmLӊV)T)HR+qzZ, \PIE^v@B^ra([tUG< @@)jDP9߬S<;,0}YUh* yiJ봅j7ا^́7HI6GrCӳ0j6jkL0udWHJޣp* >:}Ohm^ Gdd':'>8*UDHs;I!.?yk3{v8 =dۏJ!dx ^-vGy]zƺtN,l{lаLw0^|ƿ;lpW9ePAJb$^C6޻j<GV_}XLu.u#{`lEˤ:0 h"WAb:ot%Cސh )>+]vg; zq?[/&5>6 szVn}^:GIJJWf%JqV w"k'ȳ(ݭC/S*D=y5(<*,E[}߉Iۣ5-So l){2X|=Fat/E}1ph6RM )ŧt%*ŀl=ےAtlN-J)cY$NS8@o:JJ&'z_э~;)Hƾ1>*/v!zTO+_|1.:#s sv::n9\qdQdCDʋζgBw*'-=$ vh)X( h8M͕*qbTPfKMn] 4+D@9@^  -Y`5b:\Í76UD*?Ǯe(EiNU##~FZa|}O#JV.t,!uWHUB+K_)UX޹%!k9IEwDbwQ:\+ D9?m݅o_nhyB|< ֔Z |[p+m*'ɧ7  ̑{5W"t d \jH U( f$x۫8w=o'MEAsv8SqV&;OIH:Dʹ(a%-9RZ%un8۲FQl{C #i;z?w?G'9 לӬӱDF% ]M[,0H]DmQ!Zӄ~7!ZbqJ=SkqV.L9ከT_'  vZ UyFIɏl±[՞##Kpf PgJRq5#ߛpRaԛ/eܩ`!ϫ{Rҕ:| 3P LW)Eś(4pJ!ƀ+pAOggS@ ﹦0"#''!-*>D605O1eL 5, 3>ԟ^wBtv‚@O'X) o\OvK-qvxLٚZ$i,n%0(sGDyZUQ@,1>5 bEp ֪Dp@q;©4nSR76 .:WP 0d(raϬܿmSiⵁZta=aA866iZIwаg+hRyF떲V{|^4"QmXeL ,I2C҂sAya*WIéJX7AC)>oo]U}6цc^ ȷ,H+)nv:DJn1A}c{Aojq:g|7+InlLp9`/_9f7C*wV[}V$;a2\jW2V|6@QF %2";l$7ho\XXb)h &a0oi3~]}mĸw{¦l un 5 #YJq D^+֔vȈƒi>r7 U;aFV^YC腁o樠[" r*`t/>$"id8h1znC&VwǿsqM/sZ!q|-.xqr%By p eqfZ҈hXOSԯh\h#X4;OΞ[7BxӍiOt-+w^Cal42M9Aidۨ9qcĴMzޖUo7wC&Q*%EWp1nWZ=b$X Dx>h5RWɀѝ@)rظVJH|WݧlWO=^*Ba\F1ZӱsT@|I*WӕGV5k3n\K(ެ9hH?giJ?VC+1RjJokdEV 7`0 MVU\*KTE8V~Sx~ 71SX# Fk_,`RĐH ^8Dڮ"q cbURذYݴgrt=_(|S_H4Vr._55w; n&D¦75?uO8KGiOM xL6׸3۔aR% 2EåԲ Q]Rl"F(;D G mbw^"\USt4Ng?7 Kɲ-kZbX} >C:D BW `G/@t~<:)g,8~N0ɧ^ ٕ)v78{A3$Z`?9gu1i% ej?`|6"-S=?Aކ9w5+9#*+9?ʵHv;U}zwC&,&1pzevխQ~?N ~ceMwLliiN٠*- aQ }_gp"T[kMV  㻰#Us_}C ,Wj{P2 çlŕGWLW| 'uD +\J45xM"J4 LCLU:UFDHR|ýqQ]!y_aK::&H"z+upRɈdX \ifԭM|J[zQ}*]n '.w}4Մ4}/a蒒u-`n/ȼΧ/W5XfmB/eTksl/5*ˤ<|[ `J^;V\upAj)L|>B@r?= Z >|ASŢN_3x{Fo kiPcdt]wDq,_nh̅Y:Z7}2%f m\+Z~R霾n(˸Z, ;L&׎B7Ӫh=>?A˻IgV?zYpz/d#򦇷;sYߠݏ`]0A( #HA02ɨt]+(?n4(GU ?wvg"1^jr9Wk3KLG׊ < vY;@Itf>(pfo!-4cDŽRhv'@ ߻I \c1e#~sQ}**l4::tvG& XS(FD$yefGhvoC3%:W"{U͗Qf)eieIZTJ~KvdL[Y@0"KSH MXBڬS%p_;mt{}[%eo[[so8M J&;>qxl_E?3#wԟa Z?_+p(sAKѺw ŶS@jGɶ3N;vKrWڷAo#/N';&caHu0CiR^ւb`61 x(Y3<Ӧ,cx:aӛR?B+{ju88l!%>) XVQ @ҳ ͒Y3|>7?9NT#ɻo=75/xGq;(q]x^+\?!Qu!=φ̫Iz3kOM@7'^&~$4ėjUa>0R[<0Z~Ke & L^ȠZ >89+a |Բh-:m|/?|xBfHKnA i І VQ/p [FOr'} _4V?<{֭S @eZ:N/ۧB/%4^1 }ceiXOggS@m﹦0IUf%kHݨUc҂Eo>jsMVI^?uLt(mE >*)tr+1 +fw$T4u0"[FϷV-`  J%+ZW?Dc+Ém5Jlٗ.һ7 |&DCh[-F+_}ѪZvFTimW~epչї1>؈K+6~Uׂ+CRIL*&%u`90?LAu'R9{wrwl#: ,tsS4*X{&?=qu$GG">` *|ӧWSfDi]0IZ=ݘ??Nvx 6( k]~V q^Q)Fvl'KчA[eXX77Jϋks:mbRmc^Ow׮6|=tqJO,"}"ٗRĠ#$箴qn^RJ2֚nݚ! S=i{8n˗۸{~w7-fC^eݯ|Q< ֽH3KB{ gS!N \)a<{/K&Fڛb<ą~~D}{@@ݎPq'@t#yTȖ'ZYngg| )uW绥w.[[ iwgC4,eƃT G)<‹j6ꕔ|܁Y7Kv_/o.OGRdZ+X08wݻi-w/v/K*;7ui\;"p_X#L/{BcZCևTXx:WxljR6wf9}`UiRৃMf=Mg tkmπ^XNގfs -Q3U D{7(H#w?5|VGb J; g%JWMEE,Ldk 82؆.p\#r]{swDZ0~NוjF˲SQ4o5m2L۷O'؉"oO2*%ȾU^|(<,{,Z;t~ \>TRk[{mwfiuӰP׋Vã> y957@L|9&q/7yv86#\0@~@g0C`\Bt b9ۿ<?,+i%!7wObZ+Y-F^s-~ЊmJZ){wk̷fYg|^6kA&.]n:#z6@|mewaI05/ ,)}?stZBʚeij͎tNkeFU8hKՉC)"af rb5Z+s]\KNo8u#6:4~f&ϥL/+P?[SR2_xw_1ڢӵz˫U[۶ۻӫe|mdpl^nM-LY qDHp:lP $2w2E]ʻNu珆e&q<N|s c}Z8uW[Xn:.1zƢ*U ^f5&݅"7vN;e㍦B 2!.eBk(0N ț"E5fě]Q5[ʏqigȝ;|y\31:D]#Fvwݲ­(U^;6Aj/Ŗh`^h}\Rk?>}[UȄM_taX>Tׂ,:tғpWob=7ǻx?ѳvң@K:%W I&:nk(;)0rd?S ?Y_8mteOS7ob]Cp5P+s\{n.=[qRhE0DOggS@﹦0[nZN'VHz灴2Ů+)vl!WpY vGg:DZ팞<3"s5gN B߭"Ld#qh7@?ڒaaPv{J#kLה.wrXJwυ 0{^5=oT(7}LM_yMb1jlg5rK^xr|^@֤^an0~_- sbR3­V}ABMŬzU)Cp]@lXOpI硪W:58ĥYF*.BAhh2ɓQ֋Eq`rg==~=w8ޣ7]2%`qHAA'F8ߘ3 .5B <|b$mѼ I9 8q*"B?ǬBPd{ƶz{BiZ4uxM5Rwj62nsq𱓻󷻃{8lQ/oWrz\`@~f^ֽڒ,6%] xר+!CU~gʝUם.n4 y,o?7t%t4+gW_%` ^ՐA4hh}R) dx?9Bs(.tzw/N^fKwk߀^]pbmY[T[.H!S]׏xr+mۮ^q$r%ɧ? 5mw`M26 Rkyq?kgg]jѪm$K!^҃Htj( ~sLN?CP$J/oE^|c}w ]Kf|@L%I_$$[xlio ;vxc|w |F9#>K+襶zݷ~2 ѼVt(*k.h^ @Rcp*k?'Yb,߷쳞gAHC4(teHI% X7K&;.O0<|SSV3' 8RwZͲ<)7C-pb*ZRZܨkf1;>];S{pP<"њy{y;yAbk먿l3b3"v$"bo2t>#F>>nfgӷt_="[n^yښ5?G}֮R1 R^c_{JnWޔtj E}) fpW'RQI=^AeNt&0@yv5k=Pv鏜7(u;0|͕VE9sZH4gH&2CV8/VZKpˈN87Xj+97֍7=WT{_5pe~ CuV=WhC8xC_?;ݬ6fCƧ9e 8\eUbUE%1k "%wźt/5ˤR"b++ %蝷lzo]__:y'Fi~A /f1ZVNE _ U FxZ ts*G}{栱8bGC=\VQz#Wi",fOwoI 4me|&>ە10u_bdE}׹?>!/T}r9>x1\r>ZmYW鸰4\Lgt/9nΫ,v^.޻'N,@&)LWenkkPbGL~ Ivn^"Zԇ8h@EFŹ> _;dXʊN_v^q^~<3M^_m0 d!iyçՖnT_)H"{fEnQoڗe.za5 +N+RovӰrײR&x'#Il̹`Š㥖)`qJ:֜?Z+P@vҞ26,>UŒh 5چ|iK.0IdIZwF wGpo4v9n!f*駖r5>W^XWRq +b(X6[7*!뺼,)``p 9.Tq`tL xZ)htyw;{G7dh6bCqZj5Z( U rM%k?`B*-}mчlE{W'4voQJW|+V~nLsx&| |!萐1.3 Te6i7_u&(ܵy>sP|tV59 nZQ?p5ay͕jo2+pc ytpz;_u#˙2'v5w"E',˂Z\od$rǕ(SOOggS4 ﹦0!=."$!+& "# ! %$}!!""!"%%&vI%UN kzS~˦ps)ٹwNS2?{N/?mxA3y]w, f|Ʀۿ+sφ>ћp 0A '@%q/nL2*Fzs/݆:\˧<.bmJ<;(AF*/,Ĉ<<@کߵ(HGDߘ=<@5 Z,n$Z)Tr,~/=+޿ycѺˢD bS$Y9@hem[#Wlvl0$SL.9> cyMn~葏d-t*F({Դ[Iy&ga]ˇO[V}(^ʳ2%1?ׇ!1 8'.ww]$%z7(ĄS!B@`~. ]& ( gkڮ0g.BLƊE9o5ը-P@h{FR'#)j@BMyY"7t F5Tc-wp@yC@* ߋo18jŴ@Kh[ rNFk\8V8bR@_#"16a׊H?1 zζ#hVGi2n6E 5z>LBBN[Z7Z9Q1H$u`?fkPխ'B3+'^պu vK$n ~'`1:GD՛}!PS-}lTg ˶p_sN/Avb,Z|$ZV[XSÊ[{9J tH1|?q$ϩ5Q|(¸+.պP$#eIE*PY53"u#lA>0+JUq6ٖ;7<`$bs^h pxہ(2Da O؝7l#邇q 4S@O%Jh?ژxj EQ=HAV#YWňIX/]~bw?*< Ƞv8Ǽn( ޴16*KRjO"Ijy1&Sގ%)v\ ) Q+ ɷ ұ4 ;Z. LG2-7]Z^Cr{ߑfV,|q}nBg#C@+TW['SdI1?.U\%{:ucm_y[ {*~\cT+\Yk//y+d܆5Ihd  Sm'@P:+SǺWV^P\1r_뵜 Kfľ6'{}:f%ZHNOkɔIs$a':/r8q_Iʕ_,ݕPP\#F K5XFpފ%@nrXЖȇj +c`Ƿׇ9&CGҲ+N_8-ꂶ} oCpni[ƹl 4o118A#1 R2-R)@DLuo\K⠅^6D aܰ~#I#n'yb,Rܞ8@ 1S$ pZbER"Rއ(vZ#pm@Q~պhuҁB H‡|U~BL=ӑ7hC|,PbJ"^`tT|;kU]H1"+s&sbq~r25K^ l4uw\_FS[~H)z4FVLRG]KM`r3LQ S]HEM  eQU~RުCAf<{aw4@*DIMA]ϸو-#:m=Pb5֙%7fh)>`0 KVpJQ!FXS{AzE(nIHQ1gEcI R B)>%dCCA% cb26wp1[5=7lKzǃPXx4h` +$tYb wV#`PGvaNH IIW:,M.^k.H:, wF z AK$Q[^gK<>Nsd"ŷZ"tѡS BxP0PGY @ D!]f}Q)M".Բ 1T$r\h@UUb'@n"@fڙͫ M^$@CҠ,ԮQ2b4T%[lulIbZd2é rVyf&OH̿ A, tnG1X"!ȵ9|bzȒ[Em9gpEk\U ji!T_ B{K׳{:Pn L_KƠ f(l KG~~Gs2!R5TeI͘na{ZI\W+Gj@TcA/ \Œ-6Zn"g [T_M0 /_/./*!kׯ*04cŒ׆pW,ɨLa),5/ 9-ס*J4|qaV3?Tgӗۉ!$/6 C,2-C^ +Ͳi[=UeK2NQihc%ʰ6H +R2\   ILj@]nQ1wacEmv ˝91/Js!EUc.ݻ*#PkY' 1'h^+$[pԏ_7CY[XB!DK[:`ZCx%D`p%jn\r?ij~(Elj-AB]۟uCA"Rs4|FZA5F1k^rZ Pe*w{%Z1qϙ)<`DDy&n܅j] @Np"#Ip@RR48L] F<VJ#֧ʷ1!sÿ9(@`iÀ49rQn:IPؠ1 5!MtIK4BvЊ$HD^[CⰏٲr08:wZq`{cqTEp@F47jF~_8yv+&[f H@D_[~K<%FiZ\z;ރ [xaNT Qj0 bxdńQ¾'u3F IN;n  ~")}m]. ~n5ou[l |Kt}%%63b}X ᇫ`$@R`SEJRBJHeܙŠ) b}r6*xMω`o1xpN N1"*I<ѮpC,ՀVhN@*A-i'"urQkn0n ִ%C&V @EijvS'ďKN*7+%"aж.U@pi UF ءª =& 7փ6 ^@+4DϗmF, e+u @Lo(r˩L8"f8"_Qr#yv'3Fbu.Pyf)Hvu=)WMjr?4) Av4_4a0( El< ,Hd-m2B -1 90>5S:P|Ny/DFP<hýע'v#a^S c+:>m&t*0HbRc, 4P(ТZ]xMl( f AQ\jp /1n-kr'Co,c֏-EO@bh-E^@Kba-@ BG F,>{)fJw"_'n#NB/[A(+_^uC Bv:&D|C Xԋj/~QqvmQ#uo4DagQbE $#JvS^cu%j`1D .@ ,F{A GjFx)3`pϟ.xb+WO?zG-/Ʃn @?A bk!m='VwK+ZELUe$y]ĂtQ7-Ơ \H4h}W J)Hj: P2du}W9xZ#U8I:=2D4 ,)_%t*? P~`QJ`Y BB" R!1H;鰃8a٠qhGklJ_xg|W!mh0j󵄏>+Z%xMJPD#,WR(A ^"NpZ@6f^T`v,Wl3}Hs C#-R_ |5PGvT"GVIUJ@:r{޵05^."\L`}"\>5 {T#aZiW߿1c}vy?!n%m;fXToHr ʋzmPEkGg lyA)x&VSDqi^ѽ> .f3'`7}܃V]mH4/:u'oh̯SͼH2h=WZiot %C]t>1|qoX(x[}ܕM% hq}0ȫB"~t!Z; Í1B au)|-k"6mOF7X4K-Msh֛AjLw-f+I7*ڄL!\ Yɸ(E@ )Ғ_Tw$x,ث`kB1$~sF4иm A#H']Ht:kRb+THIթi5n>j o^ w(HBEAY,*\%3EBKq7>0 ?]qxAȤY"M`1۟~?e7\nОe tƫ&hP =V,[tn h0Iyu0GMW# /֝oVsY^nH2HX |>`\pM= <XZ:.6 "9u\ϫrٲ>x #,(%^Mh<rcVx F^!?J %,du[oT:lٗ~Пk{BaCjuy@/XH8@NQhPų◃nVUO="d.P2Mfm;ev |LN#$!DipJLn$!9*LII;tZrCo!WQ4c s@VJ(m8!Kj5jSE܈cH(0W~i;ܒqWKGpa4#R♷~IXGh}nhHMگ&5 (58²:m#;% 5&n , +X:Ÿlf Ρ5#V+VTPjY]IbZ.nZ M(qX.F~LrXoQxeɮ&AƬ~.; n(#1A\'`Ojg7kx?\&J6,wkIw~pպpis%o%S/*L8F@p !@@ nK,ʥ2<fIIW 3ҹ.lsAŸ݋Uz w홾#<BR%O@Xp\NqV_X Hlr+PhK4k~ f$ ۳X 9XӦ}O1IIulHحe+xD$ޫOl*Hgv&Qپci`s!ϲ; bJ )""dO^sfШH].!p4@EU+ ;f},n~LìԒxA|C) گwݍK݅>yς彚݊T@c,JDcrUZߝof[9]{m],PAO&>*L ܨ&JF钐[^\ cpuP FUDpRmkxrfF4V#&7H3g  ^ND▕),j^~ZjڏKU&upZIb[.՗x uuwuzW a=\N^ҊW ;¤hAc`넋XU\b \HJt ^r֞ ET% ڄ0f 8ľH)Az^qa0nvnm.2)o}4o<6ywdR2S= tdt e >y_\}:r\YgɵإV Œm12K q[)VdC.53.[ӡ@R#)L}V" ڻ'D&3B{Eb19(rr~-~=?W˭ځǽP0@oTJDlX. ,w{_ ] {}kӪBftD q N'm5a%;1*H,י R*E%T,.^L^ʚX;uKufovU}AOLqqdh,2|?ndeBY?ѼvU83>6(~W[k :Vm%ćqʄ(lnr9 ՓUi!Q`* [nn =a .n0p؂[0U 1#XDS[)Yf{>%’D9]fAВYqqL'N~Ftn"kIjg63,^j)2 BB@mpC .R[h``:1>@ 'lOl~3 ]gRTtxJhcL-;;]xzoc0 /?+clu+NrnR[1,e-ju)Fl4o!͵^"vY)plM,`غ}f8 S#Uq !sf7JoVuSr7NC\b%+ n!.E6~?,7:xHS1%Uf$ON,m쏴@/w-*fYm} )lgûXGEISkX$` h1ʘu %>=F""\]T ,K2T[|aeoQ$[n8yb~뻽 XL[ Ã+RtFڱ 7.ojTaȨ`FpAeQ61X-|f0A)ph HQ*3Yb<+&4Z mMu GEA r11֔TP|'X"QDyW匈{!,; #j *i?Ύ/lѵזZZ汒јe74X2M~mAfָ믤Bg%ku7P~WǸatkIwQ˞2ŢgVkpIY5jPcY^(=%l&a5g h]Q Vʋ%ttg%ú8m>> RZ$^3?ȒQŤ!6Qp@jAqLw2CV{VܧϺ#ZҾ*Pv.KZnD1wq޼^#E= = V7'QAZwAR\I?5RǨ.ӊf$=KǺ$}יb (V(} aW:Rg a%2t8|L>+NrN w wEcdUCŐj| %iB,^$? BN*tzrl]nJܔϫA‚0ִMPm#  V<`"<Sc~p2ZyC !wS\ux;~(2H'=dfVh~RRf1*KA\Na!!gxa(PJ#WUtS@cdZ'ֿ%u6m %H5Zw#Vigy&cx9J/ќ7lTW$_4qŒ*iɦEXcWeEIMBoI Ksɹzjq⃁636 )B u%2c+hڣg p7H$5@M3VƆp6Oa]*_2ԝo WmsivO-+XK?ZyoK}c #MsP>n+_4lрà^\i x:kы2Uq߆J$w5#;oL#ɪ$BÁ爒*Fzl*H'%%L_>S;bzϫqʎr)R#P>NkYCǘ+)Mk-)$n5v!;yRkYVÖ 2!ϛ8|qi:]DC> 0+8Y۽QRjL32'}kFR~brqW]N~4tt1ߴK6Yz,jTV|~lNv4[bw'vP n{Z}$%0iW;>G׿FZPBA: vi8R$VN~Vс% JIwgB4ߖͻ\n:|6x=,̗q0s.o2Kg>IhU,Q@^q  熱Wħ\Wr`&+GVgp҅"iRx p ҉ d@tR/GZ8HJ3%t7=?SKZoBy'X7J2J1_gqd隷ʴ[geBW-4_.8 F,@|\ynhV)+Rb*돌0E~iԩ= @/TppG9FJk>%`ۡWo B0Ջmٟ;bJMsiNIԝ=֝fG6 ): 5VyeAkNA%;& tt=W֏kph7Vy{ʀQPaRﶢఃAPaz;t*ڎa<$T< !h:u);dNWUq6Eu0/`AxR|{HҘܳU n5 .{Rx66,%-kV|\QVpGL?=jnl_tNvW)7/_E?ZS2"~;:h* KXC$ojJAu"Hqw/o`hz7~@ \k wC:#GĺY:1jt>pV=M0ηalu?6V6wNnB{v M+Fԛ|ϑ1TFg -|`AhJ>Sk&L؍K$ f qD h5v_nz0)hxs"c=סr.d39!bMs_|W7|=Q'<aϊ> GEUe P/@one sayp:3k|BC賳}km='􋼗=̳[{? G>Ć!<(`HBhNH<wvܘ`vkaܐͯjMaZ^6[%`bFA!>TYIYd_WX{R 0(=:FN leb 1ux./02;uuzlE &;>KS5nx(3O>LG$SkɋyFJRϳ[<._S;%9s̯Lês¶qR(#q{F2s7]D+Ffu MɁTQH5Mi+$$N]z޴9CNipl.zXNe47&՟_"F~9K=Sot՟l0nu._>z_ܹFuW6S[ﭱ>[Ƥ Ÿ9Qެ5!@Y,*Va9?RBY)s3 }y2,}^鴕yRW1r^*K5cHJ_.{PCrkWCFVaQKSL1Hi;>#=p(. OHE]*}%4K7οe9FR! cZ2Q ,uPc~0pjqV-4ü7;Sbfe&`]d P|MM1;{1(nwpyZO?^xߺ|/ǧlŪQJ 얡 & 4ϯn/ܗ:@l _S6~JV;o=OnktݪF&'N\L !۵LSR1A]1ez-b!9N6.BUǮv}5;ۙ];lbޯCthXz'ПgE0nvmh1!~$[m~I/]ceŧ`IsGB#A{"#JD-å`"[:  >j˩&]*G$t-0\?,ڗXsVdP)Տ>@ isaBzqN%I,Oj{ŒZ4R=,\<jnҢ ݧ MLr װ"e]]2< E.sn떁wv %q)(8MU ӵ:rvV^8*k,2W~4xA9 R3`71L|Dd<>_{_Qњz[)FI=Rtm[J;ګ{@E8LZ_v{ءtqb!y+;Pc5^=-¤Sy`9XzUahAY L"v CY jt<2$T[Μ`_^\8ꥳ>3qJ"d[Hj9yg*(\LS ו#|}Ѽm/jUA%.\W@30?g_fԂ RFPXU4DU6iT^,?o|ZRl}ڑL[bC7=z.Zޡd]|u:g~?g/a)ԎiòC|;[#d]AnF˩oNm;kЩ 7)lcCV93'-llѼo8D$Q!wԮW:6Ѷyr@(5/WC@D,$L_Q(E:z\DD˩7^5-'whVƃ]! jQu[|d\"'a݉IvW<_g6eaŻ+/y%VD44C K\. vfa 6R&}\W)*@I` %lRFr"DUz^椸Ay)=C-+:VnB4LWbk 5SgZ絽BBa{8hQl[ku2qzRt-Id{+d]l 3Y˥RSݬF{14i\[ o^E\Brz7_ߕ]Q(CZ?#dC,Ũ۹ZGEiEfqfe|e 8~v+>FJA^ .J<5V ;2B6!w-Kx-ɹRJOj-S qߝo O&B(±;Kz&Á*U8ȂpgQl,u7vVC{%VX&)Zҹ̧nA!0/k^DJ2g([BJv&Ұ'~0|ȥKŕ`[c]+˾Z1uŪa w&,x߶Kz7IR{DlMu!BP'[@r?] D$Ӹ;FTٜͩnOxLһ쓍31Ij&K #ջ)ŘsǶdwcnX$ZɭW<3TWd5YWm{0iWm˒NR_8\Uiыa qRϧsU['q\WluI=Ge==$$VϚ>rlY2,N*6WzSy+U>mkIjqDU(Soƒ%,vJX LUSib%ZGv4}{jb\Yk ]ގ`/ٮ8A\=yᔿӑ*daHr&A6IP*PۉzIf￱!T_E˞w+JL9V_Ht*W;Q3dƗ;0 TODՋCFLR"?h9t5W_W̛0N{/Ws{vU Usq=N}Zz?$MJY@Hɩ8}t ʷ\1a\)-~sH7o7\'p7'} | p~]~aE~܈Kx&Fs]5_ٶOPo]̈%޻<ˎX 8#L٠<@"&z }a eRR5f_qڶޕ7/r &w^eǸ`s0{},6TULWl^|'M6ϱ&s ɒ\'~ ocMOVI ˤk}&F|Bx;j%h r[br 6GnwkV|K['n_zǸnsñFFx4̍V+NV} >W&ʸҮkbtDLw,ɏ\^r w#4q6Nj]5]0)YwwS1ѾskJ*C Ԟx8?7mkyqλueC`{O}fzqKiJo,M-׈PTSTP8q)H7=!LUhX5%)S:~RfNi4%gEl[D8 _KGxi[ K Tck,!\p~|^Xز[cKtX V6\5W,(!7:_x5irߺPjL ;"3Lg< ؕ^Xn5)n5Lj9\VAX,jW|,[>\›-w:J` cʆu5/칢8ΝbTLUqane `5Js@IBݢx:g>4d)0vI[Ge#0($p{ДSN|aַL.{9Ƚ1'}XI7Wo/zKhwxـΔ8,44 D֥l7|U&|*?«*`WZcDU]F7 Y}vO/Si%rrY~QOtT@1װ BèӖڡ[C6w> 7wIq(rrc jً44Z2ً%!ٝY WF`U$w0̓Jș(?O.ڞxq>dB*d1 'UU.fN\O4O|ebH$K?*pX'-s1_Á@W}U[d55NzȽ,rOj:j,+R /§^ExY( Zd!,ddFLwT[|uț8.v' ܚ51IDWmei?[evzyO5gݶ%Uu-TW`vt52sp۩nI\n’E1DS) H< ܯS@#~x"LUSzxp݀ *[QYPB̭n*!F\YFGWvڏ( K5yc+%@4S"ӕ-9xJ Vj%Xh-=g&n(+l](Xdn;}O8NrS}3Few1h\g0XCϔvxZ[R~ۖ#dž d>?pQؽ\-Pef~|Zu`/'x\Q\Xܿ{yt0&JضϘr(a#ї=}+k}KߚlH2˕D1 [#i%o-79xɓO&OpџKkBdY9_X=wc [Fl]X̳;V]aJm@o![^e{5W7#zR ?r\c7~8hjJYZ^fR,:DUvը*;'N%|&}wSK|VTY6U/pԎ99E~&0U&Jad]Xb%N>֐`ۮ6;o+4y]O-zn~)r3ND4=N6:#BwI1=t!nPyPHeȐ}IْWxlf%]f'M6kp\tdZ9C#h#ejQs p|сVRb{ uZbds(>A,xCK^c_ s%dX#dT 謹rO㢩LnYAV?i/LL.6חy:>X]~"㮹rkz">7F !\-QwIі(.l1UQݤ/}[BȤR'`Znf#w6L[W,FpynlݙTfn)"TYα$ձ@}% .5aO8Z٨tܪ LU | [GhuW ǭ4W4)rďK,d4w')w?mD[LyTU^JɉS-{nMT_Oql1Co1әӦcX!ʟ0>'?Oc;虚ld΂X4=YIrSi!~ln|Z!jKӭ׼yiW<ڋXS.Q*e4> a_0=*j9 CA|YG@ub3y̎TәN %;$(#^c'C2}I V5Y!eM|H1,lgl8 ! i:behRʽϨ\48aBPz-l>=~, |1nnG#dmT"bљ2 |\{FEΏC=U oUk/i1N7u1cgư9n{$P[{% VZ / ֕'z|0=L6ޟ,dzHg ;l_{+MR"<n@*,%Eo#սY{tb&}k_;7CW_<]6ڠIIQ@JخcPXD\4n|5NM< "Z˪m^fW8>o|ϯcEE|!z|%* H$u.'3?/'okCn^4})_"4Ho0^/o1=oêdA@|N;^鏌$Q0gx[cqƤͤ.|3TMFq[%&اPpMP?k Uqhx鯯zmւ愓lXHG鲴޿ݜ,Ndenw Ft^O}5_[s%v~uYC1x8j}4yV:O{'΂ jr(6|mtM1q5ִoeGIu;f6jj_o+߂Iŕw|$Ķ" rGOggS@ ﹦0ld*$!!$"#!(&%tzt{ruv  !!$&~.@KW?|~FxRWCԣ7\_QxXI=YtR:! GF5C %v6_ӛqrkЀǰT_oo)~ 75D]/$ӹP(!P;ܱ@iQ(-W,* >Nрv\'%^=vSyܮKlӇY5zu֮4 ͱtƻxo)=i2xjNǕImsg?o!~z W&kgUN\MUrH0$U4}-`!Ba>|.NBVV\$%֋0ɮ(c P)[-y7z(:wN%ShXf"\s Ij{9Lwc0cf^HFB7.4n=zQəct] NIeBX#d^h FyC"zho%fˏ]^ϥ}A-QG&$>6xb5Y yz(G-e)B[2na1?i~kc<)  窅ɇPu]+P,>lnU;./x<29TUT?}lQL GWOG3yثSF!bHo:'_k,ᗿDMok1]Ĕ6@Axvhϖc:A*y 11JKnvtQ:l.ހЀ`aZ=)aj8ԅ |! ͪ65m#DDCvd?$u;U< ǗEzR [I[;LC+^jv4I!{)kFՠnbXwi01H>&rdM4Zۅ)ay$q<3gڡUB,0бpr-" H xJPy$<,V 0.$rAeE;ƁnVq tqH7H R\0˒LQa9_fXyoEˋu$ZWOD@}x}5QvH*%%H$0pE~. [dvl\0,D)U߭i2'2bÓl#d8kdz q&}xɢe5畁H$ʀZ*h`E&>1 ?~n*j`iid,#RȜr?Oi,?.Dv/5$U@`BMnex/* >!Ab!D>|Lo9]tɍ_sa p4 pMY NĂt>!@"@(U@P752?&E \( DmI+f)щBy/LYB,}!Q$rkra'gEdYHcD oF^.^v9HT[#rj@l @][.nF` * Ȉ`bP ,jEaT]lwl>>՞tfNuJ?g\ \!N, LW(d"7~pI^Y~{5ԺH׊TW,K\lq`{pMMFJSr<[ln~+?^1|RhF|uy"ALWtv9F{qZf}2hRP\]ᶅ08 >W<7JAu_ ,laWvrԾȀgkiR-rzCZ|0i; Y6&OSSX_v=;cK UUO-YJG,7+OwÛ˳h qک4e9xhxu=F\Þ+@Tq}=˜3lJdC4e7GH7NjMY+lz,.1%.p;KDum /:LH~6Rv UߺK7j., @+!Ù(YUD}BzAB+c 7`Ba@BDs:j9JY;1JN5drE1>*e>lzDlbcK>7$\j*84RqŒL#naLL/.O:Kœ΋lP ֡5 # yr AP[U[@`Ee><~ V tlꆀ p]'èy"&ADP³ ;Uyp ox\+ָ?:vǑ4@hOn0&ƈZ/[y0lzMkDe zڭd*@ F-Z Ho@S/(XTۄ'; VφYNDDu5H"^;v; Ő[n H)iݣ4cc_R ~ [ 1L1:u- R;L԰ʝ"cÍ\^jGnBvo*hSZ2S:U%HE.&TQ3 K;>ٌdw[ Bȗ:q:V)/M ]kxC"g+IC?Zn\h{xpERoWED 01*!n&rR $%"J"K`b~~j#ZxvOggS@ ﹦0V^'6$!$! #&%$ ! #!&*% # %"##! "'%d =pvb jD!w`p@Sm^j`EH^8xvNe_@FpYx[ QԷA7..h!@ L*}zc\No=biI s .p6*Ƹtx]+]TWg^/bG nMs3+ NpqkטU|I/y|^"-UMArmȱEw*"]2_ŌT!&l$T2oQ|ܽT\!tb >8+R#OEp!bG!607mE $;hs\!?>1GK-}+78SǢxy>u٣gDm܆6cPP x&3)' ⌚v uȀ+$)A$! ]+ER ""T\k;q Up])M#{Ch"2SK_` %gɸ ` n(@M]-jw.Ǒo;7sGYF'ێGxT R)@H ݍh5h ׬. E3~Lf;v_;î'MN-qm0qlǁNWz{Z'hlzrϏl4*/M`}] 㣊PO;D>ABº ^ 6U҉ x\$c6= dx>F*ǡ?)U3 7E&hADTx4]״[ANdPkZFgpUڰFߖ8^&>1˧vӿ88I̓5hz9 zݼX)XRU>BNUeEr4և,o: I)A.Օ#o]=۟$q>9@C*ӷ?y{3òT1ׯyXX>PPk!p6ªy(M] Fw*;&)Ս[ 3t'HO5:j*nugiv9o7&7}\Z'FLv>mbTS (MRvqo̩E^h윴WKILQN'!xk3Ȗ5#u=1QDMM+^>U5ͩՊ1lvv}vIcI>uGf{澽]w U-T]ۗc@o[ws%vs/mEZϔlcQd8w@Is=U @v4')CNAzf>1trٔ 0e"ל_Ύb,a9R*L~zQgrSK0Z4( Ԡ4BQIZFT*<`cBH2 ^WJ.mzaA->VP$9B׈.ޜq|I%fu=% nCƂ>LHWtڏtc~^ZhRQw0/Ѭ8bW/,+¬}(NEI%A h . X( ތ'WdVU8$]rJ.v1;%ieBs&?qgYUj}fhqJg_Dc#"8x` *4{`Dp.?"&.Q1 #Dh[6@25},LQQFm|>`X&BTrҔӛNϮsfVݍU tе: .D$d[HDeМ</[{1Y~]=a2WÜ T[(t_Uvzk0;1vD4O0o|1A&_6xe|gG"U:Thf)f^&/sr\ko2o^IFwb[ ]P @nGODЀ < .Y pTG@{UZ0DXp|!HnK\T qGP-Y O4},1vC I Ajʸa/d xJCb(Y>VkE2`KP<%$AMIMp$n𪅛%*>PDAۢK4vqLDj6;6-!ī%k)D](k?rMU/vw,2m~Y݊ CVM%e#*o[ҹA= fÈ`n,ȨMp̡D,ThD7H2EۂvD"޻n?P \U?>ۃI;$rjk*ncV\U3b^y Lw-rlQHVLUh~d}^Q2[e)d[on_|yoI6 ^RTOG؁@sȮy71;LU+nƒjlҠUvu% TYuԕ!ec]6o8͔ZZl_HD^4%ldޗoLSy!{%ROK\S,ya8TQ) OTO;;&j ^h/ \$<~ "ZBOggS@d ﹦0ޫj0$!! !%(( " "! &%%!!!" #%&.^a PNϭ0]_mYw`)$-,x~F'r\i5Ɩm@;Ȇ# # @sPP @PTƋ,ntIAri0P#~">l6:]_fզ@wj1<Ѧ>N4k[|6_i s K2ө&S^m=9[;Kv.ë?zH|(j$b`r3)(9Ņ>68"XyPh|()T[0X`!B>SꋃƓ|f#x}~M Da!dRN&}Mꠚ$QQ^!~s.پB0b @8) ڳB<A!p'-Dެn%F*b:ds S6ODd)?0:7^ekO-$= njC2Yk֔"WSM uR P`?>K50\v v[Et3P3:AD@.2 ^v4;zw0ra 0#;DG$Wl~$޴nӧfUl) I,@4Ɏeg d" ^A$B(pB_5X\7n%Ƈ,%e9rxe`b)) )D;{fQ7'jOYNb# 0F$q`CEBQogsα3 %CM O4`E[ƺB 3/xtׇ+A ĨDHaFzxot3mͪ#.S,c4a[HgCY`Tm[`(ꔛFpk@;GkNp#S%1H<@~b(&^ &p;']ڠ z^ĮD($O=8_рXgq֏j/5f/IqBͫ RV}*AaE.Ab Ia @dpDq`A``ƲPD j( 4x`z f_k1äVh 'W84w/M=vit+[E-1(#Ou֚UlL!CP;jŨEBn@H, TNQ8PY,u[ADW8* $^pŬ_C̈ѧ \WiJy[E`2_Z)dFU\WMШJ)qƒP_N ϥC2nDW)q P-RyXwU(p LW4_+Ir[DdWBWU"ڣH#rL:fvL[ӻI}Aո{{=Ź2cIY-*MP1: "7Bĥc8xXjU^< WҮ?&-"S6'fxR:(vU2L])j6؂elT6CJYZRn޻J4tܙ.)w0α:[aEPgF^)KE> vQFnE'\P:(9']of]kQ#d֥33|viq{FT2t B :f lG90JxL 1᷾z^w+s8KȞVpzo8bБ|W@N9 3>#MƱ7JTc~\X[x(iymK&'s3'? FӛC@A]I x6 c-"{٤ʅqo`*WpOggS@ ﹦0 (`&%&ntvqz|w #! (%}|~|6>i (~N 0׳'Jhm= 2rF e=Ʋz90n=F"+P#uY5%zlbPHԤ4d2Dn&)bㅵDA+>|./|d% & DъUֶ K!։('D"bDc?5[,_\d:eح7đgàHAJjcp^Ԁ2r\L80bQJsRunLunnJ3+W׏8"d V$0j88h*%{-iBRJ%u EnQ]T<`P1\R+X4Ћ46YOD`}U!98߬~0h1eеU**m[qp@3ao;%nB\P\J HnҀ:=b},뿜4ӵn]vn\g'G(Sƅ Nǐ !ݚF֭J R,uKBYRT)U"a~^@lLSU®Lx? GGoWvOש۝mvm}q?dv!QFhȈ5]D*8gᖕ :'"Y㘻?noQ=evȼvlv4:5U4 dZA2Wj~5ri8;*1 uB iG|+q(ig/Cs6,\e98ltx<l}!b-umvŪ?4T A(بDM92i n&2J8粵_6lb"G1(ħjҗj5*]A3Q\_䈫K R>mJSDrǹyv}N74\e٘R`'sVdeJg.sdn_]/:1 A`_qZB 0> “!̺#= INnz=Rs\qѤODFaqHysrؽ+P+@5y]H@ 1uma1Q#m o\d$Yɺê7^nI=Ƃ>M-BXSƢӱj1 ɀIE̴1aPi68.!nWcJ0 p U-׸@,<>hi3ak!K.5RkjD"V {UP$RHaۙqGx|}ze(!JT0+) c)@ˏ]n\H@DU( ?p", "&cfXͦp";T y)b"aۢJ0ץHب?8iBGT)H oLI<FB$ZqA^ p >ֱK__ ,h-Z1 #R@_R \Vbq L^A5NLkGl x)$SĄDY4Q_Bso t({ IiU@2@ )k]t-7+ K F@v;1҄> X>mX$DzF*z~Û3rxP`>hl\uۇaT 0rmc|XD0D0@I\mXԈwEȃUH`PT>r.E L[ JhBe,WVZdNG:v5k) <[Zg#<}~; RTH1LYMСJU͗WP=&d$LYOeq mYkǽN`Eo~|\hT]dB@U?o硫oxknkz&m`[f`7LCWDEX/179E"҃j^aN[A7\}}"2^m?.ϣf4u.ŐGvxz|9kCkBRsX\^ l1fHI_\LCJ_YuslG9\ t8">DKiBU5<"Q9ڦI]i?2KnmF#[ BeJ,Ue\$1b8|YūHJ'.52%YԡʨJE[]4lR)̗lnỿTkNp(e>1DkZ* L(N@8h@-cPg >T#M ˂ D71J+ \$>Mw81s禯 t `nț4MA`pb*lPl ABR^,LOggS= ﹦0!X2~!"!"%%&$#""!('%!$#)$#%$$m^!sjņFhf9ucֹArʌP#FDiv\sb)ϳ .:o!Ϯ&7pQ!i5o؀cg.$Pd"Fn iZM=R6a\ n@;!6ۚ%3|VK:]@G3H,Hc혇X^uTe#)ވ~-* 5p P`> J@Ba5\"X"> K_VrKel Ω3L4;W)ׁʪ1SS=Zp8@0Bc@$Po.wS pJؒ܊B "V U MQ[> @A~$aZXۿ|ᕩ /%~}vrm7u/S$\`;: _ #|vJOr<[`Qݍ\n/n(9"yFGePc\DW*+S/=cZj,uDSteʚ )8<^DUSծq +'_Fu7<"DO ϓ"B^|YOM%>sDQHtrij͔"kbYsDWJa~"5 (h[ܚd][+Ϸ#֯ ۑi.LLY r</8/!'MP {3z6E0,  \HqȟÜ>CSa1˜> xc*x󃌷>brbS*_HqC׹^n5;){*!떈>&RS̽H}=)vh;"U̒Mn0muݽ/aH zfqaXTn( w-6^b W#F/-'VcD%/('}f Tt[LODDG\VUX[aX\stٔt3i23h7 !ٺSƈ'a5KzdHbqVB@Q GdI͍W&̸V?@Q/ڐ|OE%y ]|Z7a#H2D{C!Ƀ/E%N.͑1K9*wS3 W,nh)j'0U0$Te~PF֓X{43qߧLS%jyXVTm54ҍf8.,Sh3Hs~ ZlR&.׿uQ LWfMQ(e@F%8"!&W)r!dcl+!kp;WܖO~g\}(Z\. YQP.ɚ86ASC9O]m56ULh"z웩փ0Ik!Uӿ!uJHO@}ǁȨz9jTM6 PUr`26"c "|>zBKjRNY}4# Q ՟dRu UHt"$ҠN>K,dŶ$GiX.<3w' FgDz@W ` H}ρ} p!J" l[d䝇m>cLHInvCVP%=ai5 L('ND'L^yώ2O -r <dPzDYہ/oZ :Fe;AD,VUu;n~DmTIrc(!ks Ek>UKePPD$|_a׍I;^Ԉ 7ZllSP>) L~MH#Q#;ߐCep#2$dP*:.${w .DY)08ĬK'-3F$(<ʤF,Qӕr}rikIO}R8~o~*cLS˨/[F+}Xݪ4.7&ۡ% TYY!9 xsث89?.>7 \\]R׼H:t^bL aa%m[;kB %CNlU6Gx%g&(bVX0Z3%e犪'v72;^XW{u N1vnrqޟ>ɓ~;ʅ'STMUszVhWǔ"KcJ7[^dtrO̡7q@X.?$@R C QPtӡgz-׶bAYK]TWJ<`JZE;s~Bմf!R|*ULʐMX"C=\ @vX1Sk:a"R!`bx+I@"@']{6RcD͔3b9=q8\5#i">X6bһ]~񇗿(zvÄѶ{Ham@w3`U@([H3ͥ#@a 9BRD|:ڝ=ڭT,!v \UK;6~=_:޷sᾧE%)Qje-=$~ڹEkpt9vz^=OK![eu2D4E(A @S Ӹ (@ )P!z~Q$iZk]7?,c}ea @[Y-s9]4MY˳Hnavsw<\b >R$Qڟ%t?Fe_w!Bv1[%OggS ﹦0"JZ;""*+(&#%$#("($!" !"),&%%#!%''% !"# !%&%"%#'-LY_l( uAoDJjn*Dێ֐ic81cK ,XJD^h*FxXǡqQ?|^ձ6<[a+6o8<ܞwʗ+zڎfr~2^IkY\[ WWs=:N7G.뒠?Xd_dZ`i0iKJObYޮGc6STz+fL(xb# 2|oNg@3$KHk8oEnM|PZX$.m3mpܬfu[ιÊ1ebU !uFn: ǙKǯ 78;i`P'c>,oEC pg5uFl~iExZd,#\imt)fVtkk S#LDWw/_;dLT!>q\2o2|}uל~ dف!5ەzٻt\XUa2:L+d07ۥm~L1^Ln,l/`_WȈ~"r+MK*DΓO6ZGͩǻJdV+)Dہ3Sm$nD<;P\I7Xqle2,,O2?lHKgsTאS7zÆC Z~hH[tߚ{ $OK4\W(N>)sZ*Y׼,1rZE_֕vLcA(^TJ4`6Q woYv%gãv{mLՠr0=h<4dۨ7) Kړ򦿮- &p+xZӭqSR,˘':*R&L׮?ۭx LW*|Zai.3b;UKY=7z3\Gz5SS^'Z_ba]\QKvo$^rU_>aFSħ G$ow3U*Ia=ͮ)[U>D5{ ^C;;Gxr,moo*PR*0Շ9w=:f,>zAmdd}jIeaWZsI[K)OU\ׅ?}4fˏ SoOoK&HJ&Gr@88 pDa$[ n7P1 mmL(KO?$QS QbL@gP ތ޸>& G&F4/}h9t %(Mct)Ucw^ ҉2 <&휪˳+ q :sd}LQUvvt`-|å+0p;`KmbU>95@J  b̵_XZr(3׹>SHgߺ$4cFCSCYO@^A; r(;)X6bĊ`NiBE$_T5,8g:.\y&]zڜWncz&"WA%p|jA`[>!9TNS `5\z_>:w 1dQ!_@]__wnb,aJKvxI}:x̜P2Ibq(0=U>/JoKKr+Ŕ4p_˨ 8>,6vAv?ʈ'˸jgv;1%l}CD4G"Esau$Oj}E4[2*g1R3`e["!Y zBQVDDj d4\~E])6k80\*PNűo]dP̓IrAu>G}ƨ8O0ЩSu73Ǭzv'vxY̿Ǿ<Ge:E6W%~=?B~sa958qz}r|B̻7~ K v) 9hŚ*h3&Ϧ!<zAKjdkLE+K7M81lG9MC#ѝ[q2d&$%2N8t]0pJX.*(S'+!R [Pa~v6"+,UK&/xmuA|13YJ2XDU*ng֏\ ./w}n5[RsLU'ae_ yMR$QdʶZ<gjV?15A${,O٠&uxJ5M=wj_X9Q4OaTN]ٻd%/Jr!Rc6.L׺Ʃwf}(x lW#,L]x̪K67cmJZ1,176]0 T_VaB>ض|wG@SbhřKϮ/+z= uHcʹOv\IbJg+:\ zNw ?+;f!l;::9)Øo] D_ N[SY׻"=kMI*T_Ȫ.JM8$Ty#U  <'R)ON=D4%b Z¼So&uw srr輶<6(wVJ4k\&pJ2?2ב>>$!dFZ'bX]dSD!-x&,.n>8&&(:<bi"0i_atBDHOf۶6cVKlMcߑjPCXA +$ZZFyl~<2+p0-j"adÄ~z 4b' hĸ /cEH,b7Ĕ9xybS5M .=#uxi1qw֫Rn2sY|3_՛,n FlW7 T`hg%1.ī^zUI¦G !!,tJD!@%iFX4J g΂rS;3j!EHjkF̷M8xR"PA1Χ74%SjrPGG,^_bPq3L""F`gT~qr[F[+,i^1ƅo9l 8|-ݿ<7瓦E/"9)@4t`s>2d3ڟ/&빨ˆ&뺉1"G?}TMvc -|4Wv Ӣ'D[ƽ^ޱ$nϘ |:w 7sjK7C YEfC PB@ AYY [VCjktOoars0/ɡ5?fnǓ~>8nsWJ7=M7ͧ-ŠQ2n&( J}je1@vz+Ih\QOOuLc :Kukm$7'-̗OvQ;vܨpp&RJ582J8fB3'XX `eTYPJ-Pm,~MWMCt = lj& nU:-UKm1!գ8p3|NtD)k,IJnKOy#^Ef*`ʔ"o`9Hb1 !yڒ0qRPoBgd:!0 Bѽ}:JD4&vd6̈^iL6(qq;aFXvjt.@pLhJs<|)o4('^35Eb"?f=n0U(e2$4CӤO?JʰN<0c')aAۜz2W*94/0bTꎻKB:G!ݰu܅ ȅN;6ULR ^^Ĩ7?(92譛P5Xx<θcreݩu4w[ q;f~c.2WvN﷠ys1D@=UPڶQWݝ|mkgBsjeu׹J\65f ^,.2I.j^@$vS/GJ(ԪI`\cXcԋHb6oc{GuVr$"TBtwI$qP07vN~B#a- @ҴC1Z-lхܟo4(+*j;q0TAvxndl 0JζzpPVrYUY[°DL4wC>crǡCer2ʤLώ4ԓ=ϵl:5zcX)7EZL +}%F#bMZ fkt( 1NIo^~3O3Kc|珺ivKdl|$WCUv2H\ rn\]MoE 5q@,@dָ̙APQ o`iWyMS0G=2mv &|[ڡ8q##̐ɭRι[?׈4DwoА~%:Q:mot8J{eho޽fkHwO!/{N#z)a.Ѹsm8/1*!޻uA{k|.=*ϲ&$,t9{q9І囆qV+R;q;P L%d}=>m}݈$ $+YY$ a}HE3<7& PY,`F f@" mp1ۥ N̺aXTB3jeHn(HSD3-ǥiyJqT'QۖCšxII 'SOTYѕVh)^R( "^ v)@ēBXw8/( ₑ☰/Id&[ÂNq1L#3`=,XaP0H x0JT@ X,D+!fAFP(@ˍpN- ƙVۥ X6%Pl8Q,`EM#e axqD"CXN=x6[q('8ݡ%0LG"w%Qt)\ ="Mľ/4a4* JЦpmTG`\V\f Q `Jq OggS@]﹦0$A1a`(|$""# (&(է$!$$"!&'#_C etmE:zNaJP )QD%K'SgkKf/ymns TCD0X)ȉu(%"(K$>\BJGJR i~ $|)њ\7YX2%^a#it79驧鈴;;@LP$hw,|`LAwȊ w-( БD E;Ɓ0eoBex 2q æv_|(hxOļ$za*/kx $" cII_=I2P ńNߩ#ꁟ{c ~S[o$֕2ܽ 7w0(Jks<~\6> 8,}$ٟpݞ ff,_Z6YlseFm^uOy-w.ܴ-n{trTrسQڳz:oNxr Fya/wք,w茚r1ud/ޝ6vuIOڌpR曟Pَ=ə[ @ OBtX4fG#${r($ kXFR5+(R w'7$TZ&XV]ܷl Z9Mwdqb[ A! $l ` K>4DohsAx-B_0RJU='je@)>}g88?uP"$ ठ w$QNmX;\YuCa7ɻLT H+>]dХbna-J2A""WHQ_Io$*\7^"0~ A G/VPDޅd C"7.x! pyM7AA`1p.5 &Dv 馡ZhKg{@|ƔRcH߲ƒmj@DYN?W0}VR 5\hVYУPRRP#PjR 8T@*\_"ka :0a7gCZVWF\'D[Z:}` 7r~n1kzZQk;-@Uo{UնK{. g柀86j t\\A`-Zq|ZlY,ru5J Y!& 4A!P#-LQp4;UvT@~)GO OJpDWAs^'wdS4u.TSQ qv=xP{fDiETDSсJ~|W𾮏+37~S[T]*f]:0&<֖ؔ򫗺mSצU$[BJE|2`ˏT/rjy]ϵz-7zutDQF{jޏϼ֒?{Cm;oESj m7h~vvg4FT1&"vϝb-i n L)|V>5?_ROw߶D'!mݜ{DҊVSͯ6M }F qrH+~1]闗\@dk&QhFVi椼' ;|37Xj~o\rTIYl>bG o=3NeBBhNK}c;}[u:=bc<*;{:ϧg%1{ClŶiƥF)KM6E nqfnaU棈~\U;&Qjs%:72w7Hcߋf_U>Ӹr xy}f[)zf8%i-?%Y ܍lȮ<k!qq%*6ǚK# 1Bsb %E ];5RI %)R7XjȶV\%*ɲs_e >^>HRCEuN,g = p|' OH,.Q_oc-?&yFňY A;1': 'p;nFy+U`T NղhX@fsPR }ڲ䇥=ϛ.w0lv.?vkoMatd 4̿s=`V.+vl[Y?B&}61491sב=U? K;ˆQlY[s}䶓12 Jcb!-7&;ԗp?B~ܙy`*UzUR_AѴzhݏGztî XTT\B*F18jCC!(AOsrv|MIP\S,SgcW5:jJ${a[V6CP@GH J 5 Vz}F8_/KÁK/%ʓыb|W /m>T`Dc Pm.J$h~Uju(t(•~bSrM;{%QJj0cjQ 1H$F-ꍱ,4ƭѯ2h͹~"m.3ct{}y 8%ޟ$͒* g'/J#4)yxxPWwmfncs5F%5 F D}Fdڸn > nan+Júh2n%jAzC(wFT] Wף"ϧ܄`oƓؐL[d/Bkpi;N%En'2yR 64ZbkDȜ]fJyU0aa+2%qzU rĢ󢘣?8s -NX6@Y(-,70@3˧nTe_ʄ]8 $"Ъ`QCE$MX\"V OggS@﹦0%P"zqnw}{uy}}{|{#)n%UN|:QNF33246yrB/;J5z(7  +YW,/zFů),\R Y$@a 7aj^c^T}㪌 }`K]aJ yaJ*%ecjTC@ ctkJ%qd `V(T@ F|P|XAͦ4C(\ D<*vYaJ}ln$ Y rn= <(ŋjB/ ;;AJ!T( "Hb>-yÍL?qg+Jt ؒ+.%.97D#Y\2@)nXQ \ k@4Pa>L.M@fwffR+M (~^*\~tn+(gM2/%b_$ң[@x4Mp vX-deeqah  V ӡUKMÊL_RLf}J^L6D$e/SxPO=9>"(0* }y#z|33DZGCD1Ȣ*T i2D#2XI)D7 s>UszZMGD\ Q$nQ[Nс=vTi8=`*a%f79(+]SΚz=#f}ÝHa^ P@Ċ(@JD@fHjYߑnAqRj!b^bP#T .ɀY?j"GSFܹ&u÷ Eh||gyBN8+Z8PO V%Eb Er+AR XB#` - vQ5n89;2 5ܱeLO㤿\ӣG/Q~ YnFp t}hu(`,X8M'MyXD>0(X -uƀ0 `cn B%ªGzrd^y|;ӎoX(;nse:߯_[@*'0:!DD*&@ڰAW}#$]p*^~#PEu5YCJ fހ`2mf2JK> "G Yӑe/FXU ]b܊/UA(䀡:@@ H1AJFr Y'YeFm- Ŏ5>fL<1z@hKQ질)MBe¾rXٻ**,(Z e\G nVXnHbN,^]( ElV/XO)+?y*6X4>Gcb} @I} D0`Jq0[-_ ` Ȓ(0Z #.E~F#e Xurq7ʐJ 5킀4S!aC%ijFQ2kl<-p(Ҳ`lCGI0Q@J61s!* G$< $m" @>c/CYF{+A$.()Q$|Q,D)?qb8[rlxp8t;*5< U.cJ]%lB +z5= .rěMf$HK  ; nh,g<Ӗ"X *6DJ8 |V\ȑɛ5s5wT+KD pCMtd ƪ dw0QtI µܘU"zP^"- /t+7@"PB"1P(,t"J̀eq*%t܆LerTu7Fv.2.3aT6K$@$6mV@EFKĜ6Q<01 ۘ'Ѧ0D^때A/n\(2>,BlE)SApAh۞t J L7PfҀkpQ0 @AS1{ clVfԺ(N%'HOR_zx7LgywO{ߟô5/ (bd) |$E| vP C.%sIG|$R$O NWѹz`n9t㛛T*ŗE2ȧю;H]| *Z\` qB1"DE ܸ,d np@dIâ="-$f)F8=\p#* ,TTeШ_n2Fcq fok4 Vb40ͬ4>hq#hT 28 `K yڈT\D"MM@Tm!(UٓPA1/B>&3nӻqeg`wv!\1sJrH 67 Goy c"|PoPXR‚@^LNَrC_y cՒ-;"d|vSz0f8Jك.~7b c@a $DP} BCQB]<m+vQ6{ E/ДXP>x>F^ڼ8>HX7X)b5'7.Jr[ӼcJlKB|UCf-UEȊvpI[@X.*rHE'ڤ,ۥL4 X~rǥ LӭDH.b`t ZًGEb<{SK͵&D\.6(~OF!%$4Q0@, "",v@c~fK<]/id˽'#ڊY'ɘ:=_D2>| 64ٕi%\hHV{dM$(%"NlXB;mK)Gd ",RFX!Оi i?}$SnԈg Ko?1 Gq6QQ8E\a\M Tq)C{yYq$Me!7=؎!amC!`K-"&~7+v1<.QaQiSUDӰQ2ү6ғMфlHUΧC]oednx3Y=O6(&r)!*uySU 5_IF C@H~v|MEǠt.3sޔyGi |6yb2aȧˮ@ K@Me,sM7}OP5RЭDF ?kvӊ\.Tǔ/ mZcɸw8"@8TO$Q&y>sdTsܲ]ETdZZw3k1Go˪R32ҌBSZ&v.< k@ m8*H\h8$5 Xܾ"m덖nӗn@ 05.HslMCƕB1Zz "-Klј>B3 LrRHh]`KsR*Txj:6q%;H7:Lpj;wD. TpIFJr. 62'mFȾ| %3v1Y˓5". Lb.jJA[VQd<>8xSS8?IUHU, ,#P&7("#"*JCu0%aSl1ܺv5 _ȻCUJW>neE 쨰F"YhcXD\9=%Fd_(VDvB%l,'אސdrRk7@haRkUjB[>uHvQD+Z>|΃ʏAn dH :7@d"[bGӒmJ]^Fv>ޖb_)6\~$ 2HnB$+@spo/d TT % ^LN>;%;sӢ bp^={H8%ɪ*Ni,&QӸd`!|>э)eOBASbJ$7Z R]Jq4 }",NBL7M^S]Bdαg?{ЎD$L 4YeQ}{XhR }C![ph8ˏbh`A%,NQ҇"\Xe X •+NR^RU7=^lX@F4w>($MV`Mv6#CÜʶFs 03vy( P6,@ $ONG1倝 ,@,* vS*n,`xdasJ$TTOݞ47uDxm ƸXsit%"Xh߲#]rԒ&d~l]t"Ԩ*bQ)( ^ͮ"B7.~@hISzDFvd͝jyF]:=O$Y2'j0}ـL7@`{J:+s#D2+h~9X .Iv$  Hr]u.Ng;-4!;_Ug 6) 4; z}~R+W%vb@""J؂"CdRbWeN r 9jV%?QEa)üڛǹP:lW)E - "BRA:Pj6JxO-Kab\ӕ4-A@BAABAAA5$!֑98^|ֵB[$`KXTZ0]~'MKQY.}4+qſl?]ۻ2.hwE%MZt2u&~/?^ mPT at8bKuoAYFDW 4ck0.nBQFDv5&NtȠꬥǀ/v NR5ґ†FE3WW{F_ [HeŘs3"dF27whLmޖ$lVc}yvx?Hcޭبy%mGk P h\,9 N p ,܈ # l^~5OMR  &IFFO82>y|'ƧC̣F #40(- #"(,<00%XXX>\@D+.2'=MeszT/@I&J'{wo=#qd_:cSFއ9jo"C@/*XXEnv#eh!b` U#+"" kfAnǂUz3NZ'9%o1}Fq/9~7_0eH*W$.u{%x AR׀j%Fwy |\dʻl>:7Gg-pDCd.- *I<& AjhtWklht;D/y< ^qFkqW-wPO<LOggS﹦0' N({'+'%&%"%"'&( &$ec/_I0TDh7^^>+4Y6s6ݶ>OUDW;}f|ƼC[?q4H͑ w18-[l5^rK2n%A H%IRB * Hi >*DhF>w";h$^9a+Or>2fr _l#*v4153;kz'B20]0@ )@%W\~2^5+]nhJNf~Mbx֢7oju3}ozzCs UP"\/RVS#{M UmeyAvw$7D;\À@)"R QE> $xaS!NW\O4%wS37_4{>/*7f~T9Bo#{M㮰1B @`%Vb:+Mk)>QFCA?#(> r [ X 91"-=)^M%ڂO&\Dx?>`zx8tz(* nPH@ V²<JT", EaAnDAD~5F*r1ܥq8O:xUPĂI~J9=Z{!M]%/bzs}GTn @:UH! _YD@߀| pUP ,pp"rh%pfYM*aû/V3׼hqJ"J)aJӗ|N 3a6=QrSV H5WL8z`Q"Y$VÐpĮ"k@@9TU&9HtW=L\\FaFݭnIѺJ|D-5;iꆫ3#4h&ZQWODDg7 Γ+j 1641G:Zc"PxԘCRh#qG%ceՐ }341IbYF b׍ҧ  6nlBRis݀[1~5D,d{zq{,3@vxIm"DXj- Wqf7yuMZma5t1{}"5S 4k}-Kb\4RRV:~)M;reA MYdT1=Q"" 5oUI?9 ?#btO[W)#@b*@3vT֢iaY|Pj=( Wlh}a[s%TSQ*$ъex5yoptn>7"D٩u U6><'$7{BݷJ\[ eK)7Wp˦4cS74[JlDįD)8@w2+$wZyGǖN4.uZHҝupQl(22%JW'|#o$5sv>FBI+o0 fa%VkV N V%ZVQR ܎0Mɴ$X X!;T7a'ao7.Qnu,{N%O!VY}vEz8p~+޿Y178׾n3eo])4ZAIJNP̨M1u:lq\61E*L*b%2"ތ @|g*qvDhBj}ĸل$3$IO]yhW頃5B[d EEwmzƁ'8{f_7Bxjk+5utk&I\0Jdn^q >]N)4cr7*D#Mb`X[߭GGG_]jzIGI#6ţ /A.(G}jXuz1 ˁ.PSfc_RMYlxV$=$VLj+, N.JJ .HA@k]PU)xі}7Nc&^su iª*O%xԀ5>lG!UDpuAD.9H7¤"pqzX ">\g`GYr ݬ]'"B;rY{4TC5`}x_;NsТ7)"XklG|p7&MS@HV:g.7XqB6p=])bP@?A^;־[g +L 'wP)%JfޠBj"3pEw;[n,_Xx_2A,1RBD *&|Ic&n~$!^hy'JEW<-X YPTMD(iw?/S2i0ͱpjI>ް{u[ p4;WTQG9+Qjfd}9r[YJpsVHOE\ap_"ErIfxEB͇}({QHƲ{RJlJf=pecf^} AGz]"J8Ձ9Xk\DA1DДC`J2,'~f݂Tg?拊 J "DMd6Ãoۉ>3u$%ʏQ.qD rMuWErp[N:R1_H}q,RdςBLҚYQv2]V(S OggS@-﹦0(dx`("")$&%}|~!!!#!"!&&η<~fwyѯ$&=:%cQ,*iiy~佞yfq2gAL4S6(W< KNз)~=5&TY?k+F0Ɔ\$?f};GgVLYdS@ەr#N}ʿ82?%TYR;E)!J%tRT9,L>N *WF珐O>?^иK}} Ӕӄ'W~T3Q?_n=d HMnY!Ӽ߇X(hU@K:poHjYY۩OaC - @1" 7!!K21Z冑 v^y9-8%h`OBLSE8m>t>qhhi0 /1p r)Zdpi *R > QqFA>JVB;ANL|NwSZ_ P G6=s[VnVoMn FNL@p ,@b,|N#a+7`(^ #& X*E >u71,y\kf1aӼTFY\uV֢i;nuӤgsb\ѡ @cЩ]B 8\Y>ъ1H( *z,707 r3H! >,ŁVhA+]VPr"[lB[IFًѼVbxviO"p!Ic6 _G<%@Hfp+ $RBABD L… ) = @թ.fnPFʃaLu͉!Ngn>'[ pR`wZ[Ut2AtÀEhW]ld_KAÊ\=A#gt 04iDԩ'/2e?VigXSqԫ4̫-H2Şh_/ JG׸R (u321ucBDT \r# ,ތ&A@|Go)Bva\~(҆6b0XykgrUE5i FҢ%*O2Az{kl2ֲ .RPP6 ō# ތ[!E^?m>g)I&gϕ86U*MSJqj#'gة#kÝJT*<9p} Tu`K .% &< *hbڡXEDNI Bo8%C}q1(:iҤy79?{wð)_6v{% wIZj$ɨ5 +a,QqL0+8p rXX6FF9?NYWS""t;fbѕ]e870nmW?³<;Zud]~q Ew Ҧ:ThZB8x8y؄w|/ BOqeC, #cHoNeA)ڻxN0병 BW, wd\EgÏ~6}}U$0EFSLH 24nPB-@12]K-*fBmP)4,؉.rW.]^(F 2֊t|5h@4"Mc||<ٲlHkVF_*"_ņPC2ޭƙY7Fݢ1j AĊx}b߂L*:Uʲ QhQ}X ;ml(2>^ /:ViT?4:=n1ni/7u'f.c798tҕ,hr]{+6+kL+PJŅU_ӜKG5btR"eB ~i+02 0Hfbr1)9U2Wua1 CUj` u'4G6 Y(geY.2J0,B!JeN|)a~.'}zct9v]V2sU(nrQ9|\|us̽ţQJ]Vq7F.Sz$8Vj@Y<]bSW+̅ش#jZ: $aM4SHGW>0Jn_ 1D!$H+"j9I{ە~V{B)J뎻|04G׆v'pӾ><Blłxc4Dg ~k;u*|DyJ5йG n2dayW ad§iϹLsRkM1' 1,% gORJs$nE Оn< iq[*h˾>^ IsvFmCnè믪>GT ?TYBWZx1JM~  #HM.EwzRtkXyid@z]{qz="mΣߒ\P*Xjx vZX,2jdp> 9CggNržN!U?n^ok~C+F&֡q3´ΕMѼXΗFjuF\5DzE\DFL驕A Xvy}DDLX*ٙ}pvch48qνWY|hh\aL;ϨڏPmπ2}0X`Xsku.]|e^9"~5A41OggS@﹦0)O8J;},` |6ڷL[e3WS"}V˧;7|ZRߗ}楬LQ{<*.9H+duV{7 gwHm !cY4G%9nL p%T`<8`%u?is s\fLB][zL JYdNt^${ԔYJfdW^ֆYn&6Q$UkCCYOEmmk*s7J9h,LS)HŦA" +4S5\[IEA.cqm;RO,BѩN:i&K/w;-Dt~"^=)7N#qV|b,m+=)=>"gWG7Kb3X4bC(9o\ xZ@q]ƀh˂:mʮ@#H?_{(k}ŭ]8Q*+w )DJEc2>6 omJ gfU>?R*b8`I1D#!z@#Ռ6C4=.ũMtw$US?e}̚Es.A|!Pf*A!_ DhІ^DIS|XRBf'Į9dG$Tu0;( Jt~|1y+Che.E7T$aP1`[!8@ސ&74nɧA-E_7'BKWΊX.hV"Qa.~|)E% A~hP!VJK,>9eA(CeR| 2"vOۈB7KPS8R•6A`-n2C6hOt?6j(z(DJ%hqIn@# @R#Ŏ <{>&~L`i|%%"^7'2?\%͈ꂡN4RA]p*sa5@b{.*i{[kݴ*:^}XQ*2Y4x, 1OT1 ΀U5{O?~Kht"kB,, |XUi$MWH /2T۹eO ;2+$^a`J&sE_{vmnv!fpS =&*@ Xk66raȳ+nkZi%Dj~~QaR4gec+q0㫖vo$IY6BkN5ZX`Y2'萈9 aS)}vvm~|\&JSFQJ>d$ T|[vEJfmeB"G"VͲN_W:-XiW9RrYU(@0@(m-CHѢnA5/uF#J-j$ȖRaBrA2.+F^G4L`Ƶ*ݵJn,tbTq鱼:aaw@:u$A5Dss3 A`ڃT%M92R]fo|J唠־g-8eio}{: "XP#,` 9|R⒊X ?qkZ` /"#rt1=},9lUb0ǛNmu9=_Ͷ5_!녢Ұ@ [.e@]= OY|1I Mh`Z"[}" ChtH]Т"7$>P'QݍfCv^EG<VWf,w[jmoh/ft<B]) n M$`DSJ8 . > p3@ |a!>tMo[XD.RisykU'qǷ_8>g³+/o;h"T_"Zm2WZ`?P$|X9 DL^SP®kD<"H~\c'( cs/.o/1: @e tk( b#@P "[!:A.QbH0P!\%*~C*j˾E+Pbiu5@5ܔ\YvZiBڙ(&?x5Q\=ڦ^V*|j%WQVndE E 0`SG9Pc{FO- @P@n`,`#rd^oi:1cxaf~wd~4Oy)R0ClȤe?GЪ+xq+nBYR haQ˄<5"`[&!FO=@aB cLw+ڝa,NBǺO_u4ͲeeUY&ήiJ]14n*$WrSpUu.>s\;q1!܎" l 7! l5 A(誰D!ˮIQIyҡJ)p[*>.&N?\;XJc37: 2)@ m@@Ym0:RVλI X"驱B""0Q2\UE^L.!?q~ɂXFK| d]&KaLI " d mˇ(O.S䌙7qB:!iA\ or.$~`CuE0sT`@\1'N}kFhgꏨ|`@G[OhmxN xa0y՘+{b̆˺D%GlqY ')q̊@ T c͘ly'x><"O[}KQRI`-=(ᩛ}O;nOt9-D Ynu쯐hD8jqnQoG|>z'C$eaQc*7м1Pq;$cL`v&""{ߍxpgY8?^ â6<O2jH1i i:UXi:`/ks$TA " 4/.?Kt"7" K 0kiL xcC[Ae8sϦ]`}޺bKvc%f63 <NWޏFhz &PZuKJ!ª,a"뼞#E2G¥5ڕNA*-xHn&m]b,vXUUj`̡|_س$  |Nj*q:o~Ccntu+!~f ?I,h:A5fRJ%W& pY "nɪ#Ibwc]'7#`oXј촑B>qYK5N"d1fJkIZ1#(M[Jytτ.F)D~a Q)H#:\dn?aQ~@S)f, ؑd7{ʆ1]5cy`fb)1:1P ÅAPF ~Kql@[tLhHc xè`Y^ \M43٠ƚym UPgnm7'dkoq3bB7 D$WL{w8MN=7G_U5FBL7%P:Dߤ҇><>w-b,F*U~A":ޠpۋwi&pGh`~??EDSɘI|t8̊*0PU (kpH*j߆G qs9PqhK$|gS+KMi_kg_R3ێ7#"yX ʴ!("^FXޜtHy 4ttNA">]+152O^=68!5{c? s^Xؐh[b5.}qB@ȏbjuoZ@4ǻp|˰y /~gSӇN8 pügj0Ɗ?C"[r ތn%/eH䳫)YG%iuJZ'|yxx*߸8?24s.~.ˋ%H_[e կR>ϲqFց(H! RfP:kʟ˟]J+b-)("c,-$@aD fC|c'Ȋ>JRWO޼(m^?Cl0o֊a{ pN?C8u0a&f\o=(#Z'G t"7GRbZ܈Z+a9Z87@E!R [ [6m4T?Ԑ~uxtaTJJHD@SBJo7Gmfu|z20̆WCu؟7__c%/Y JaVlA ryQ}ݤ[irjT7g1k.0nvr"Q`cW(eKl筛]6:L.l~_52")i25&\ݐmF8:yVלY1cJ>f2ll,Zc܏'s>>1Wv>B\jxNTDOXo8ML5zc]Xh/" բ(Ze,y]SRp 'MsMįo/]_=y7w7wy4YòVD_X_1p (X( &R%i6Wj~ɻABpK2.½Š DOggSW﹦0+.*$!#" '$##!!# ')&$ !| _oY j֋Tb V}g[0>e?Jo/,~Jal~hK*-!: xjai@|́qɑf z&wҡHvٲRRdWiͳ c:}5Deziu)XJxْ9Rc5+ xh` ƨG(OVW>v>`\<|Ac^d򲀟ʯZx >aH w\;”x+4:k Y 5ܭ1en>TTZuzRU,sXBk%/[fdg{BW P7`\kKLև;?ŏoe5HW:9YvFf2@&bJUiB6nwHZQ\w|jʝJ!jԨRw„ rAȕ93;_8qy^ޏ񻹵T$$*ULu Пn֝) +tь}L@FQsS{et1-oSޤh]1>y{"oH\@P>H+\k" V1JԜZ…꒱xO TR%"FI`-EDUMѫqdyQՊ,SK]̶tMGTYHtU4 %M^.[~%aω"%YCa n:3H\`Qjd`HA0IzV bh@{ِDGiJH+F#_ S_5 }-(MZ_fXES\h1>j/(a5&VHncޠ~ƃA{6&Iʢ_~sK*\S wVqXtbqi;\1Cu|hT0S׀ePRBI X{ѨheZd(yW5T + ! *6!&pg+Ҁ0+&zH,ơ2\&h@G-bvϷ{WM޼IQT1,o:!XJ;Q&6:q}>S_Y\,RJv&rR3)J/@ m%Y%UaU<3KvCED%GfC[U$N(ffR&$]znxhLc#8 NC # -`0vs=PS L7 "t_L,܀">l1B/ %LNA>WB](HSII0@ңԔ$IXzԮ2^XMesniz{\F6%p W+D k :[Y+X>nTcM8|9̹GؖoQzoYN'W6ܖ8XCgQ2΅ҵqQG$DoXme-Hg nʍLW(+)/I'$)/8P,7 +`T# ~ݞjU^>x^FFVO! ܯ̆̇I[X^9ݲu:WK-Y~U%eJC-nT$8jin$P{S þ̞s &qHOէ_^KX-mFdqRndGƔ: 7ެn5[.lͫ?Qzvi-],gɠ~sb8~yۛq{;- Wi콵=18S"FdYJ$sF6Hq.Oa!Ck9doç?V}Ȧءm3@.i`.#AqWR*.% $T>x6 j E=\Ԟ O`2`LXesO_妷xazHT~RC@ =M߀#b'r/Kpa/p#(! \_V:Qav:W$7%Е2I<[qkStK}u/*s\ e)R(TQЩ+׿2 1XeR\[jawm6Lfch!W"D[k UFߢea0Bc LW@96v_~ާG9PMBT]QP;G=&WFz)Lm)PT[d+`n^\U&LxCIکQs?#SDYz.̱C҃ה/?s) {fa:4j֕ΙZ樣Tt*|kdBGq9_vϪu:!e>lAݗHo Q:\g 1aE,j j.k슷NM P2 ѬCgKJYki 过X*Ƀ |m#xAĨ2ď˂2NK"%-l /Cn)1-#Qħhj|-@E 2:-\̿Q}n|ǂbᲈ h&^! G6N6(Zʕ[H[R$iTf^9ZֳEwÄL w\w~n͙ş}uS'#~2v =QE"d"XQj|HpSJ`:& Cؑth"ڝy:+oerC2RρaiƯP5ฟ&az&o:wIgʲx7;!ZYq.5i`GE[pT|HR/e5'2.(oSR,S'NSu1% .]RߧԉPO_`x̅M9@#?!V b `&c!\[˖4ׯ!Y^*/ jl TWbȨ caT {0ZP E 4S Eu,:T\j*2TOggS@﹦0,R1 "" '&x#!!"&'$~t~~ !!!(%wzz{ywTYj 1=)9J)TKF$Qz,N9փ0:UOPDSQuix ~i_ML+1+DSshޝ}?x0؉r5"ULY ϕRL5ϧ ε'?aM l]tUVP,. ǃm>Gq)Ml1ZLE {F z"}~p̌#p6@t:,s|[nz4~ùgSRa_9WA@mא, \ H4o,WLAP 7F`<d_S 6!܄E"1$.8)q ׬N^BA,"½DZ.c69y?3wi-Px =2E(Vp0cr-Y5Y9&gU%]wUF* dp~w;f!ѳ?~߁t{`T $53 XӮ4xv jf ch䆗z-ݖլ #fU1C0J~Pq=m_W` *ojq]ط Ԫ-?GơՀ@2ތ̀] J 6J;JODoYU0X'e+X|:*T>e6O=v q3ဴ ȴnZΫRd<~IF!:eEn4o%"upK5,,[-QOB~f]R!$bk#~dՊO&}IaHD 79ӯ5 eݯ1f>;⪯W? F@@{ m\D\nlT(XKDUӪ TLէ'}Nr4PbDOia|q>i^wy&Ǒ4!{3U$OL%'"N%0ڧNCR!uŠ\W +2 sj< s{LS<`*&$Ly47C^3@vC;7&R A$!JZ`dvw*m,,&rMSJ> :"/nTA@\ˈ~|@&vnz3&c-X q,+Q^,J a+a/~1Zc:^KJoZˈan B}Lq5ppI xFCKvd>rڔzΣ5"(eD`*խQeeKfpc)!(TMdޭG9SN/{:ô0Mg@D9.~$P3 i/D%.F706dPלPቋvs~Z4ch@60mWR`Z4Qo˶}$cL̿uv||:LC7q:A{R'Õ"K5~'Wk7b 2* L==1+9/O0G , in8RV t?2iϦ4R$Grv(²GmL7 ngc#hh Q jYF`cC9, }|( x.RXB7RXH^|Nƃ=0h^FpRwXw=0Br,#v!v203㴜7LE׮qruy"jl|w5h@Fd,H^c`0 6+RE ~+Xfw4.OKNB7{Q ?,װ 7X4 ӓ~-æQwFnc4n!ϊL@P@}*^].RX#`H(H`!Q$ W_ jڏ+M?GYd|V?`ԍrIp_c6l<\F>:=4VJ|4Wd[\쪋 lnX54l25~ýWQTdaujGUHhᯭ&2vkIXDT;te7g\|QLJZ7ZLblϳ{1QY 3NYkӕc8ut0F:_g~<% oZkyht/[y0wFr}X"l9@ob N6va v#+W(`9Lt #0~2ʗ.akx( ;=bJIKIصp1oY鼽C,[VZ@h;TG T 7;4D.=؀DDKK+"0A;~g 4}8<J71)R" c_iuD.[b,3MtK?_ _BIeő 7$ SQ$:pA{4aB?6q,d!<UU|@_%TPHTjt˱!6=l;%j?NC(=~ (Qdp d@@I L6CƚW,;h\ƃE)fe'0qMe T&/8])mNӥK'|NX|P$t0J V( 7.p].N(%y~4` J,MODDm;/f'LX1e1&j#1K#RU&$DJ R|1.Ĵ@ frqޜ "zyɧ`8YOJkA' M^U7~}}@@zQdi~$@N/@#_G%:o%]Dr6 R@G}*E*G5E$H^L.ژɱ4?4X^Ș׳Q%)&is^Ѯ? 1Ta9  !-#h\XNt[ey冺  < > *E ^5ԃA"o+/%!1:5¡kgO/o81;tey>h=߸ggw |\i@#~T @|u F=p޿@ ).& pW""K:470vQ]EZז%\雟 "Nw.g{ O5i=u?vnF#zIE-C/[x}])P @6?>]t WP8%RɂFLRJ @=4 WM ~{N8eT%հ$"8I$15% 0x1R4p2eÿQ(NQ~@&Re$(RЀ(3X(dB{@ E7JD9p%+) ]ɪX*f\K :fD,bh\8 MT[Ni"@zMvN3e/wmCk(~ŀqGD b62kY?.{uqF~iGCLU*4>%p@HUo^V?**Mz F?,T3k;*< JQ#\Uϧ*b޾Y<mܽ]R1eU4&D5Nj]j ]O3VJ薱'"[v/FU,V4#4]X]/.'Lc_/÷&cSW%w5 ΛJʶ/:$nPJDLם V,H֊\QCJ+PRpi ~J.W%WlW ^m 0AXluPâ~:wvgәXWtㄅc}No^d}tДUau8%R0Ln%B(,.>cQ-תңve.onBX${YKU#V~ ^қ/, o.{5ȳ;@ڟb&""$@=eĆuuZ-Wbٞ4IWFZⰋWQNW8OqF]q,H0p4Wp5ҀdR`np8JCuetZg-\OztQxK<}r屟x~Uhx_{ č'u6d9R1!>)j1RCU}j FU8mi%#*&%N5K)N)`d%ܷP87XTKA RFER  Nj8YUcqww sXjySyօO7D<>@vRK H^ @SScnJC͠WU)p; gQI6c H  D# Htwt{7D[eׇlP}T)a"H_K ݄l*Kw|گȹyH-RW +(*10d+8Z)g.Tܺv=z% V".qED=^˷gb˱שn ^Dϒ s֦km͓Sۺя^g_]#" h#An'Qʫ'opKn_6bGKbwt"a(*!g=\U㢫 RugV.xKZ^7?L$\@q /ގ qOOTUji_.[<&_WTg?d%dWT6H6wFW{72T{>jPD[$e?2۠l75El]XtUV~^zޝvL qvJ_elcmm,`a7XSb/aƉj;Oyyz{vSTߢ}!CQJŘ3HGzɊaB &(qP){/@V+1mhw(#AZq``?`%OggS﹦0.h:#"$"$'%$$""$$''"%(! (%$" "!!(()&&!# '%$ìޜqlHch]"ɜl>A]I.nHhM)B4bJϰH|QtAjg&XG+gUX*v[XH-XqaJPknW)EK}4BQ3_wQ,GRmL?̹ؑgA(cfib)e!!ZP.~o_R] ΊRwmAFO-e:!]bMӕn+f鏣,vf+%E \[gr{-DR{7:~JD MT]m(oޔ٧ƪ@͖) ehЍF4Q15e 0i~ZIij]LO@Ueϙ5|XiIrtahb TWM5L)9{q dz`-dۖ-h'g(RUr<+)7]<T[Nʼn(~pxt\dչE+O;iªwN<] U|_}wkRE=ߤsߵ>Zv 3ߏ>F9˫W&-vSߚ(8&xꆃmI2x,hO 1YCr!1[p MhH[)58zsE\XmEm% }Ǔk=`UX1JIT,I.Q6*A^udwZd^~* x<̲1P_18-ʪ6N ju,/V.~Rs­?!$ iJ8̣ABkP? bnI1MvzX7W:vzUjbTHkaR DSPHBLjlD%A\}HĐLU?M!9`KtlӅv>_~im8Tp@&ϻj qA O;IX6z0T%H|_w:eq2Jek.ndd$~vNy|y[}>PcD Ehz.'澚i/npv% }zURԩ4q& @ɽp9~N9r=nlb~z*Ku7qr#ߖ^yV %BǖB!ϊSXBɕ^H /CiՐ=x+g״[TGδ!)/G<}Mg5Ŷ}dr#R W,j$Z6:¬Y[˚C0G5϶]d:Uw]I2?$Jmܶ}(L1 67~uQGA*{V';ӎl@ `.9s}l%8btMr#o:_z|x6u%cFN*\ݖ.Ŝ\NJ}$t5kPDS,f\a~h~3w/GhZJw\|<uҭcR'ǴfS6d䠷r&imu{TՐkۦh05<!l w1'DWjW[$oe[[C2 L0U7|gC-6ɖg폜/*L5dP{1M啚Y5dw^u$ǯdWǭkԊx@KYIl(:mBIdgsH(a᱓."u# iqΓ D|Lͭ>! ة;nT[uwZĄlcz~҃FE7niڛL>3.V{!0YEG]9`5%P)x'Sc)2>ʝzr?a__|u X({7n_:"c瀈FT"* `%,֭dȢ&?7-F5"EX,U5) )c4ˌ}G9Nr||bjmRB9`-9]Wo}Xe l5hA,D,PެPF *gy$z2":>`Ũ8Wg?])MhCd;jTGǟ{t A;w>ev ݢ7wYہʹn;HBApE',;Ibd@BVI6{nl2ZJТy57Q  <><VcחX龧a%RvحJiM0q礥q{D@3?[ A"TX*@;XArT۠9-^˚mYrT< Ǎ k~NY aA.Sd6U5d[8^g#vݎ8})/lQU5N+^ Bq$k^)Yi~sξxUgN\_b6}y} 7YeJQ I8>A\]L$/&گ/A⃧e05=zƦbɊ. ~PkzL+èb?˼Nٗ#I2Gy2q0/Ҳ̺Ɣl쐲X&Jr>]*`'t5!S{y 9:+(+xr}=ܖ"H^?5SëP?Gq(BH';w1>:>|N˦DZWИAP+&ǔ&$zg4ޜu}t]&ḄOhW|=:9]C8|L{&VJ,M$IG1uF<yFϒK6:R^=+s,o}%J6v͆2lS-)s~Y>[`M?EA0w+pݛIx [KY|֋iah1э'r1[+jc} #κQ؁Mj'F PP%MX'Α3(UL*A,:Q6k}uHV-UwvT_B[<7aLYԢ:2{Z/9,IXhOggS@﹦0//"# #!$"&$$ ###%%&%$#!%&$|}LYh gnC u DWؓA=n˿؝0#S|sx8[W)l5|~;iS%44jؤiK-7W!ER ŹT>Vo,E\_¨ (K#2jtoFt_zzq<~ڹxXtHuV|g}>LB*f^WC\aI dcX7P|,D%c8 L>rValᙆn⡝<C =n-w lcN՞TLNÔ7d /FF\[X.* .Ɛͷ49ǷT:5_~T>ܾ> 5`RA r xtvGfa:k#ɊpŸ"igL>v=&POSt1]e{շEyc_ǙQ>a=nD+ĜO?iV}KޒJ2Ny s K#4 /vtkn;<(]GmV>Y4ZCJ9GDy 0j`Jv d߰|pD`߁'@3U["D-QRS L߁g͇wbڎWYvQҮƷ 1)<op8ț/]e9W('>Ʊ&DW4&+!|9jZ?+ތyݝ^L_ s.G`qFÛ|sVusf1\_ 0s_ 9!ejt-Ο=*U$\&V"0 iY\](E7C])2>9tEdw1?;[2Lf+ I6?qսq>?-H .Zg?.&/ /DX@` !*,UNKQkAaU> bv@fR6J^)h5;tP8(2ɑY*a-IAjXg#U&vn딩ws3nޚHrdLZٜ:yN yPK쎐L ĊՏJ(HT 1Ҁ^wźi<&gfI鼩MĨyn5'b]֒P:eI|Ԓ!vDcDzTwjQ\g $T4j * $/dW#Y77oNWbtfjݭ1Z` f8%rKG7݆F9[qT/}o/@{ 5SCǾq%ܕڤ^9iM5kAYTmk`q@$\Z.|lע|zo&\jX0+]"CۚwT+VeXP?Cu˱n٘]v ‹y, ~'ܸk;y8 &tQr -aNLGFt" /|>]*DkWu7T?FL$ؐb mU ɝJ}]%m n'_B=5&IJHUYXV*iشGis'Mr\Pcw(rZ$]h|C3@ tH| Pc$7aő%˳OA7s>EF" f̪g&\ 5fW+M6إS_r}IbۆXߺ,tShn+ {߷U;c4qPHlNUL=B|l^4yX2ӌllxΖ1~㺥$XIt?چH Yzn`rF@ࡩ^6,t;6*jݥ?< smQ2#~qL3ip)ǒ~%!SjȐ~Q(A>j?ND'ן/*5Ik7&ۯoβVRPish.J*>\5C/K"= Cٯv"B\B XVz>܍2wk6»>[RJd x)ae]Z?J* ]PJVK OAA dG&`@n|)1] EwřcMYԖ£b~&[NPN>/ɸ,)'u1ˇG'tii>CKkBIR7ޠh\t89![Nrq(a|~v*Qʆ(r#!I+S85'<~f0oܒCp,U:{$L>IA-7L8V%1sYڞ:HS?C2*tMoۇ( ~}E>m ,z$ҪDHTK^\.Mwܻ ^ŨzJᅵY7`>za0~zs]<؋") ( 5@u>6Qe~CwFvfbE$W0^RcCR`qCED6KA&`}60p3<Qpx5if&Z.^< V)M܏slBuhqleg7^f:\J6n5lJÙrkն;fsGYxj]j7XCBe)D .,0C7U 4`{QjtPT;Sw+2:ߖS׻|~"Μ%Ѥ۲mw2JYa?T(#ҖF b'jH^J+I@]ՑBZpD``{A,]\]DAU?Ƭ;Cm>l6e}i2nkwGIZ3j`n8ڹ]BB8Pk, DI  [Z"ܰ Ϲ uQ`x^#6q3HCHv4RBSz iE^jBY^7lAv;N^"A49 oz$X1,f 7i|DJPͰr+{ e m*ˬeFPMp>,IBI^Ո |^b{ #y=\y6N58Ong"oíةѐEwMSԾFw?cqU?Q5;{ng} 5]1z@aD,UW7'=>1!+ԿxǷ`~y|lls " mQ}{6]~qM)s%T9kKA!"?ɫ.FLjx-8 MOҲ%a1GOggS@P﹦00'Bi1!! ! "&(&vsx}xnr"")&#&$#"$(DY(:yoI /iL[fzc4\OJBE,G̴#RRpRR &UI_z֢\M+ dž$f5D5iPc=|rlF9 1=]jA=#67av@$bfahJ!)V|2(27c)8yR:YA'"F06ڌ{Fus˸M[-&(:Q!#V@Ppp,'ob7\\DP`!)`D.^lImwd:- IE"1O|E3/> `m4x[pWPXA#@PK|H nH\yP( }DUa1/%>|"hC asb&6s V!Mf&u2bW.C+˶t@1.Ȭ` %H~ ~" uȐH/HprA$+vX&n5؜x8ɣsj")uff⩙WY\INfm=dy u!AJ7&} p8REjtT Z d]H ~v&=l i炄1鑈M~DF 0w3N{M2H믨F5T1cdO;KdAP"4%HE/\L,"%ޜCaE31I~~> `+88/(")R(;(M%ôg?k0&]ܣP/DP C "1-Q@/YTpӍL""b!R.G O u55 bE]t]v8&jP}I <|i,6h@@$a6 bx2X\jt:o\9  A  {q ~Bğ?T孼2l޶/zb1!eZ| i4|7yw|27:bvWst9d_JY><蠁cym俞m$B kf |gi  e7Rv<9jw֬;ո[:{SOatpZlu%-1Դ? (9P Jju7z~&Mr˥d|F;o^OY7u|r$t[?_| s8"~Ni,~ Nie4i1V.OO^{OyÅU??ݤ*+Pǀ͒ mQ8N !QXf)6 "`^cm*g?nحBAUM*.֣@u ˺܀"^\nHZ!;.T5=Rz M e!OKnNm[QD bpx88u $Nlh l5>Ƅ*@G1 p Lw:"9g"yM5 >' v@X^<.i~B XQ#~`ϥݘKQ8Kf'kf뉛4o~"ZG 1i#0$(?FnZh/!UJ @Ge#Q3^.@)$&&TqPK -1 ?;#Hϟ{)çV|Vf +߻TRl=$l0s)$>4J@5`HGF[Ǯ"*p]n$P'$+0*S6o@1@{.@آ.P|m/CRŒ$t[n.fdz0փɗ( -c7tlO߂R@T7Tx&  h]p(X>KְI̋֜pB9H:t>Sj`Uֆ3D<$//@3s/&duݜq(`S,(@n :* @- %(ED(U Z"*G149ԇ7[x(P -|IpDYJ0c53| c?yR/PzCgkmٟԀD1λR(Hp!1 & -a>Apo F(%9#p(T q M@YkN߿~'M j{Pf>0َdwQߙpS ^ M4A@<@$J 04 .$3$kl<^?U4GH>D#HLU8RE ovB- fkO7#ʹT߆m{;At[K4iO+DW*5{vLM~:0$Om ۷+ΪҧI"bzJ\W7rÃm=2Iy7߷FuD]yi7D;NDIoksV?>#h88zvrnPuutl?yw p$(mf/l?ǚy-6 rpxyur6x?6:޹i7n@4,PvҳsF^z솛|' ! Y]ts}K7 >ŠwtV7@<&!Ϋ#J  $u){[T@ O/ fF4&Q u#"5lHťWviuQ4e V穿!%/huvKFXTXg} wbIb E\.;- ftY2 ct*rBDVnd*j:vtz>Zqh;_0u<M9{]ukyfZ1WZ/9эi(׺—[Sڕ'#zUszok[k?J8bݛ[Y,v[m#!+É+D-^h zMF'0^ԌްnvId'K.|ᓛ&N3:7mnvS 2`lz4FqN땺Uڶn4C=gU8KNO&㊎Ld+e 8A 8e*)):?>T9saG4z?K~ R|FulW1Gg;jX~ r▔6I%F8֋Ӈ|2)(j,o+*Vۡ_,6h0OggS﹦01f2##"'$%!(&'~~ ! !*'~"! % *' Kx }(JJ/~v뚷hKMUW|D{!c ])CQHSDŽ=zHR(7,n^DD5hnNodOGqq<7B[] e\;cln$dۣQ]d%>vp b[yKv "p(V_,߽Hzxi/Yl7{=&FBLͭBw'@v x|C@gUBi`A{ B L]Rz <߿at5f!sc6(S9Fb܃t>4Pŗ~n pŷH&2:|k<CSK-6dX7S뚫hitzr`\y/N) HkQ Σa8΂eqO|!)R`c KcZϢp;ptú9*$wN:mE*ԱKK/@m@u=a/gvvïWr*!*o Diuvrp NŹy(ha~+x|@ .JRoVV(ɢA B!PҘEV [İHLW)2?KƢN}GiPoDU=OTh^n΃ds)CҜT\S \}(Ͻ݃M~-7k(cqD,UT4yioxƳN<+bL4וL8L磯ܥq pSxXDU?nϗNq݊hU.Tg.qE T݆ӕc4r+mU|6V].*TߐcÃ\LiBXg ld]lKb{{mfjtkL";|eV9 8l:+oI7/gj=c.僢k] v-Cl&!~L F|Ӌb|Lad8щ:Ҡ\I.dN74>jaM5Ѐ%8 *((=yrM#7_T~a`2  bEibl`M >A9[VWWc^"Ӣ󅞈N2ʡvj>K}UH16eWXPjf*p.Y\W|RM_p 9vTHuD ~Nb2~PEcLƟNdt%(xb8@ 4 r2=FL/YK`r1?@Q)bE PP-a=DòDI,~PT A %"<:B2tŷ y^%S.jc?;#n$K v05Si邍5@ GYc~Ь(A@ * F+([e1vpaUq~a QA7<ށ w+ƅ'o{>Jrh6=ÿbۚ_닦ь,ߚVt ] O.` 7>2\^ lnB J@ǵT.ct$ A*4fP$2eD;ٷgw WӬ~r]+mRdlb(PtPh H0r~EBpo$%N_xuk^j:q@ 1 w ø^}΢&2 6 @!O ѧ ,QqDF ^4>/U:R13UR; RDTVHA R0(ZdWh`1+Q@4bWm@ZLgH`܋QABIL.U5.ًdDtJ|.<J`H鄬~@4,,crxΌ?Ṅ %T7  *`% @rOVT#[XQ27 |.4D >PT6 ?R@?+2?wB %*m[T=yìD9Nd}[qon mTϏO!z-~XU4Z*Nf4Pp `RDŠǾS 7ZVT GCD*8BBmLU) 0o.RxtU5$TU* jZ]#}dɖԪ^n6%LUAYH69)nN} Eo*cF\WW`VwxgpckeEDO\+SlξfI+AZV +dWpE4?< x3W-nKvÆ B#$\[tYv[?;N{MwL*WK&{2k 5D݄_ ?bًIyj$W#ƚif"$ ~;+M5;GkٺTl}m$ĻP8;LHV.?9ʃ{ `\V9q=N-1s8SvuZbdY3E]Pm!i VWV-(w&n@. >w~(n+Q*CI$HCb(T0Xł4!"ZX/].bEW0"-&fS#){4P'j|G+nyPt»Ze7⍱Y+daTἊtC2p/ȃV!%/ 77zZh;-JXRl)RD&.l0/c7~gT2vɯ[` A`Ѕfp*PUv F;,jH&fA$Q@_b\;",>,"V=~A3H'E "HDž}RR,$9)-+ ][yat"um7MWF2AZ!5 m@;ˆpw/U{NZ93@x~DTréC܄E#R$d4.YIu2y$F-";5!a@Ɗ-g@UDj/Oxtb org."(~A.6Dr:Rk! +!\Y+?Xolh{msrXJ QGbY"t]F.;uӳ{.M:e76n&*:st_7Pyܯ<^q6 lJjPDl]psEY]6|ΑH.ܚJt.K,T_Y T_ySm \W.q[<lY.cw< Xl_W@ٗN0mYeoR%)\]-~`OpNՔn'lne)Vl](EW9ϸFwH~rqjF@ZVM+ z?B^U&O-Whb?|'V\QJƝ4$={՜@;/$ad4EI*}f5Hݭ񙨜Gh' ^>Ծ?eg@mY2 Nc&/YMxi>$pa퓢2EC&f2!;͖ITZ hI daiBj&!I!GNV^" G1#+^p]U[hX6E ǒMhE`$ԑk޼f  ]TigI)̏hjxy5D(//gBKF酭5N"_p?b`CUt3N]@C'8>Ye=OمԖ(+Œn)R\ҕw~c7ȸ~\T]͞x| O]/>Lf<7W(sX _m&2es`i`&$$+9&JhY:/q;3im^+ [B+7{}xk.HVĮk_{6~2>$T5S=Sc|(xgoq=&e+ZB:R?E v^xF)]~JnRd RB, fVԹZ:IukD#ЮNR_+1~A[uQ)co%9T+ۡvY&Cz)PGH:58f_d_/4>&kMN&sE*$StWz=7ow87%j,tZTWmՕʟC1RZ]@TYtE~pdnP!bzI*t]#g$8[9迷&UWZkX*t,<Z;5ۄ88pR}:Al[Kr_'o'{F@ 꽵u5S\[{Rזpmz| ^pyIlMaJzZF/%J]%P!w%vRܺ+Kٿ?Y]yw##˼prɀD|":Fqp%ӄ؃:/fΪQk4tP ?^Hɠv](оL8 jz~ @,>9F*r!6q!+eKȃR`q[2BK@w7c#9B S@\ԙ</R ϹӦ ӌ ܰ]10EmjAds:bbF }LX>pū~+D^7W?DB s@H>tyAȹ&E)0Jl} >  T `@t 6)H򌠴zܪ?WDhYp#P„Ei.-MtV0_: ݃cl?z+oߺmGw4MOӲ^!k眺! c%{:f_WV/Phz205vU$P x7C 7(i#4yW" e-Q\Y-෬{g?oY'Pe(Hf7D[k+b_x{o픬tt!wnLUH){#䤷NژVl \WJU+k.?+UDLWUӼH`:u ^4+l[T1~6݃Jfuv+Y$Yp"4_{X?:an~̧|ajls>W1CP bR|n~ƔVXuL,v/S#i e'Dw|""':ʫO{WwNFRVwH?@NܿHo]ub9WpRqG,&*)y6 6K4Q]B:hޖK4Y,dfzZXwׁHQqE?҈hb&땿줓ľlw63Obo{_jtR>iA@|X}Cq c6wDRӭ M`Xq6QIUItlpWnMIx4R F2zHoܚ(Åf(~@ O-.&nSMV O>"` .k3Mpe, x6GwXlpGS<,("*Ѫ7X;O0[lM׀ U14P ȡF>afը1 6<>3D+$ktCHJVj^eAe-(2."j[sӑH&zSZƲ?A{lq c6`7egu vj V~t

lڲ`=k}pkmd] uD[VNS$.Rl+YAO,bniYZ@BJ$Tb9AE~~?sjL~D@b1aaSMOZicf٨?KŦ@V'\'vt oF$}3D|^z jFYF 6Am+&e|QՐ^if EH4;~x/z<>1?[{]cjVp33(d? شxu3"qD~J 75 ^KC?aU&u C^/6KZ+ N:!R$B x,9~tw  OO>~eR@} j@. jb flZ"*,۩B>DHU o\*R4J NU(r#*5yO=yx~owՠF&M5ͽhު|S|ݳM `{/85H\%@'T0@nxWP$,[Atll@"T>"&0cLUJ%Cys//I]4= TYVx h7ϻo14S*f^S\QxGIvPqT4StTU"`f̏/֟~ ;XV"dWJ^|8@~)t`yX5H7\WJjuykLZ0í3TY{_LE$t)]\edS12҈m Zi{<}z; WcZVDma:n_l6p)'2qC1=FdR9OG J&sRD"*븚[:V$7MlK4_FOFl +hћ"0Lm>Q@d+ mXtqA 5O*8|~\F9܃>:2u YF$&:/"%)ZЄ$!LYlq0}ѿ-+b& & J. Jb((Ya<2A5cjq߯#Xm8E.0$Aj$5:2-+є_˩OP8@KyhP{p :A.[ 5Iq,+X!;xnfW,HXK%\+؋)( $!bQ gOͳYrn5gñ/nكET ʇ@Ȧ/Z"G\ȃtc n`vZI Zn[ҼdB$)J̓[Ku'ױ;OoՏīዧn.J ɰ['NVU@Hn5 e2r է(~l>lC.@{X sAR5DB"LDV,MvlIN694Kc 2} Er{:%p2 ءJZT~oĈ!:3~`^ p|iF#nV=eQt; -0[cńY4(kS(7s?u X=dW*Vk@M@B@0X%(KI4A ĵ82s8|u i{u]V8`:0.L p&$ AyA;+9E-\v-`-]c  %XY4+@AT@&TP#+^LQħl/nޏ`0m4vn`$";dl\zzdv~,p}O(yY Q[1 *a34+zh@ ^|. [F_fs Ƣ1 c}, vpA$3.bfx TSDu~9shp @)$tI0Ա Ҹ,4F ²D$qdLM;&S? |0ְpS+r3.H)H."Uw!26n(< @R_RC`K祂8~,e?q):~(!i7X(0rk_UbdŔjQ>#E%-6}H޳ڴ!X?verOS=W a]mo?햼!KA (l9'@hPnVrE ݑB)AQawo5Wt'}3[HYk$zHnRq- *m7$|mf39MR"()j4;UtOt㿥6hsP_k\DO$'QFp;۱X\OT HH@BauBu,~L}!}bկ,L!»C7ĂHI/V˹蠑1pbqɏ# "ĕPe u!P4[L_,,ZT`1$WyNA! ف6> &L!psPNy}E!~d"L.'$'*וwcs>wǦ 5Q  KnW #xic Wz2]LxRU` &[t63zu1DX_8D֤,F~X'~yb'F5x2`p ~Onؤ<0@'cšШ7j,E6 HkWV K?\Wg$ = 7FD>æMb! j8u (#oiJN&-d|z xP ^LPr;ox%5,f4$՞AYG?G*> 1 K)V []@fc U XVgH2JH~ox>^zl: @/4fRRG+H4MR6dFC8Z@wAY'XV^v 3ˊ!wX~7'(ɄcAoơX0@9+_؋yqFΧx|=g#ux[xr+UD[PP ptB@gMJ Uu' ?zZN,=A OvY94SeEf>}@z'is|W%?p@`FW n0tv-¦cËsXBO)k) }.yYaOggS﹦04W2%"$!($*")$$!!%)&#&'%!&+',%%&$!*vCC[5/-RsOFLfV(X[,& MWp Et)nWڊx.wshu e] [R.O&sݮlƁDZMNu|ǻfe(+3Ҳkv6+T_ ZIY% M dbZOppلT_{C[ nJ-d-y>_ўoҸl됝n}{_7csR/t_~J~4萦WZ_vCn ,O >5 LsÌ",*}  ag}?ɷ΍|.ng jKCZb)5%[Xϲ=_;/kxm?5KYkP/UR) m7&u&eQ ^?C:QU7ʦy.5c(ap ܬ;>HNoFݧ AGe 9 +xp{5W}72XK"<  r((Q^+XVѼo4׿"h,Fŀ—x؍mY;{y۰Ϸ $O}'=ЦB TӉٖe;4? ?rpLkC:f@H970H 70PDS6fڃԀacvT;@-DSzY_%QVRR* DQ'jIyxy txc`"~4c}bj$P{NeeYtb|2lJD\D4\IF͹ uŌSS[ޑ2!(:,է!$lfN~N_$M =穠Uv9P:2XVGt ެfi~9Q 7h#Ts@9.Bɢt|0>).4[tfM0Hn@p>5-uS>+"A\ +F l(/* c ;uZ@ld)1B`,N?j./XwK.>\o׎Ss^!c:"ݸ\dyzҩfG9}Az24BtDE\"@Y(z;I@K?W$V\F\R5M(XOnajd]j۴>gY hĢ; V:h$GLU=UU`jQTv{繾`'D2d[hZؙq2^M*K5 3O\|B 1T[tk+b#x/Zke"a%CKCE*D(uGdܺzۤu|aX߭:'v44 3RY .( ]q(X3s5w!n0!֠#C~};55("S4iM#h{13;+QZ_PI`+B`dW;IԂ]jr~Ve9Lu9# *VV̪Qcz` A%`P|[j,:I,Wa|&3J[Q*$I%XF >;{q\6p3dՔ>gQ8CK6#V.[.݋W}8z4uCnVπU 􌜊|6nI(+"܈{ 0" n8j~_JȶmT*KziVEtr_=vyS?d<_SiӜ<EJ}wss\.Ad҅.^olK|{]oM(P?TC0@.L斎lr@/P3CGMAE?Wu*k*rX%3I,#  DQA*~67&i6KiAݒ7TDUU" |ͺ7ڥTDͩ*F{G~G@NuCپeq d O{x @` 0qѠw 9TSF_5:~m>51#DIU5G/EAԿ;0WZ"}x%f_ d]1˓2[A^kdi}-2o5PXTcbW4}Z$4GXRMvnӹ{IJ<_^aJ|0=A?ïÒ'k=߯YȄWvsY˵GXC^S $ĒVW3_ ʟqGu061nXeFMz'>49HM5e;{sp8f5,VgpWkp}r<ᘵ|3_:#EQO8-p~N@ ? Nks"<~[ ȕm%EDԎ= qm+ĩVb™  2ue+ʑhP Ycg_* aiX?ҽP4bi'OOj'l7g;|{4(+0v$]XBBn) [6}{`O/Qw1LhOd<Q9;y2v +Zs2~buOpZ?" ,9A Q3l?3m3pQ@DH0-9*bJ^r=fhocr8ṙcZ;i&E %h1BgV,7npb`E4t׶eyח$!]RopCZnL2Wo_7/W8Sܓ%[0;n&_Tb~Y_@ }6qZ/ TцtT=Ӯi9}@_p)cKT 1r|Æ-ךj1LSNQw/fkEZO,.l[|xVjϭH$ppIX[-ߢmCGܪvC e痫vhBQ>?2WZq42kƓSj𳘤t4^}Qw&eeMI,D/7kImcI14E$uZknw0fw:,Y /I v֣~EޤR!(sAZR)*f"D*~nͬA0\F1bu]0'b*J#BmGwgnBWי6$ cdoN+KhuQip֍=h h]*] x ȱ0~I$VH ~N~oK7RV83WIuݜ~ BHcl?UW]9-\?Œ{b?,ual-*rV7sN/ұX&7ָ5>nY iuR'H|D 'b- +\ѳtoRk~͹Uz.g#B9\/?ETơL#)U.1M%;ݟT/˿ba߯N'C^8[!ig_(R @{@G0@ ДkV* oߦKBQ/X7G w!Fӏ^[FVAllssMd /ek@h#DƄ\[Q%J bA`.\nВvQ5 LW$Jd>}ӿ~JRd@S? Xܮ r'Je`Wj\ցU\;{CXRHRLꞱy L_U೏cKQhhKYFKO~&Z2\_K]_q '^] )8n3i7LzƮ5sr(Ǹcm8M+~fo_V&OS.j6bIG!<*x 9$TK2U^>t(Ȉ &v\iw7wObG\=J (cI׾ ! f,h:IV8n;ܱ\zTUWMzkAKN#]z1S'>Kx/w㦡v`Mg3xs%,8x]|%e˯0v,酙o*qXo~gt7CH):O!kzLvbw`g%4˗`!7Ft>I& t~k9#yhTlsI{Lݳ^5N^<"1IC"Rٕ6*fw!9`Ffoz.6G7GJu͹w W]iy-ġRj,mq㧦:ǧ3f?pprSz,2opf .I㠃e_,a:o]^myu9) kOw I5X.TٺOUܼ ~D5g̵s gQ#϶4u4E80h#\a"m%z5So"skߊi3+<݆!5=OzqBq,D]/*LD&?<\> iLzN!mNDU)Hnn|;@.YKoh/)h~®n4QU6hVtޒ߾ %NBZL[Ֆwh~ԉ)8_C"\{шFlT3T[ C-.MB`l]Bʎgŗ-I~L[ :%<ă׺^wĨNmtlG<(OzH-stx`U?\v@,l_zsVgSQGySκ*ݍ.v)Ѹ SqCחOXurji^Xj\r1۞w5~?̒n jVpQcVpGg>afl F%)H ,Dz:FǓ=R;TA1 Y$+4ݞ~?Ro|`L)KoޗvK6*7UO<nEĢ2Յr#Y$% pBKvAU{yΘ7 y%)HEF.=ÉOƢٸng^q<{s?l~>,9EFL]_%TL(ju|XzإEXU㸪+lEMJP͍$`}BA$D|֣GL[Nǩ!L(r(DJXbh`z hɥ{l=bcΆOH:wL I9uq۶~D `F2{QII3&ObmC!FS7.Z렖[Q-plŀ2f4F@ sU̹)gH?_?m\/n8|1~qK25hC㯳y/ƒHD} ll1/鷳&]6îwo)<.λ;&˘ݗ'v}1 6xsnsօ݈mg"G"<~LM03``;VAOt#J *cӄPƊ?1.|^#a.  6e)"DiCGfl7dtaCF{4DZxfLkZ'1[ӝOb7 A /zC/?azAц{Cp H5$F8I`bޫX%.jv$o{?Vts>gO։iDcf,IbL!'%ޱEL;/!35cHE?[Uƍ& OATLBP-o]#m|MBBA8:@Ѐe"?%P8=Qم|wk~>>ez :KPQ 4yX꽀!qALQrtT#cG "I1GtnvWs>TQ@FgXǽR s:j숑,9)WK=R]T806}h6IyRq>`=R :tU5A U?ef*n *^).D7KpE(CPX+6L A)^BagS O d?ss̛1tݝx5 Q:aw&L#:^v3+@]{^}ykw%91![0+y|w\fUT|5.A_r g/`lej`Q3Yg>)]qZ%sv 00A)jqȒ=DτVo`VO1Ey62HӔOval JPA[NƐM5*A۲ѩ,(p\;\vSB켇h_YHv$ N8I@CZ o`f($2*QL š Ha]H˲k*sR)T |,@)v'ԑE '"]ȬV]0I@O k7w7;؀Ν; 5  B$MC,Ud5Ho7uh>,/nLץ jmg8 a_BbiY0x 0r ["K4I:&˚:B{j#6X6(+ lP"$I$A i#._>2Z%)c֎3"̠ I"0 r@b;bpoz Pt}$8v* X+vъM|^$/ϩM55`;Êi42H" P8-#)sM{9xqx{f|=UE0!mKdlnSP%$c 8F@.~2AL%OC A&F"!ASWCxRSB25Ziƶ:6"|'B SXY;D> 2h 47= ~D7^?ḫF2Q8N{ Ő t2kʟ(IvHEE*8Hfn.0uIQ1I@æ@aň8 d4A I յcrc p܎'^ً۬ODȟ] veʀAQ$B t:CBAF*!I"NQss59&h2y`]--0.b̩&7 h$^Ge@IXn\%!t~;~) T)#"F}|' (+P"$ED ADk?'{}ޤicY;e;Y^ѶUyu=4|X-e&pɁN\ ޫ.]K`YdY_̾zvVL:t)գOnԕLjdY}]Yvhw8kb8JPTYBQȶ/w@ ugH:KE\W$fWQG_ksՕgBJ>TWl 6M0]64j CDW.{(2Q;ͪdR 0ʬTY\mi&oܺ GzFWr)VqHJl]X%ȴ͠]&?mxyO+>E6PoeRZٕeZ">38b!OggS@ ﹦07+ty" " ! ('#ѫ#"!&!("&v|ywryiǤ !vz':Mh<ʕ((=MbfHsƒy㿏M:zw:zE^Hb!SPM|\ =*Y MLsޭndy1#N)XGDTl֮pXٛF$q'<ɄQHH~h1a?gAvr-^f` T!#f59 @=h >8ᆱ8_ *XRJ ^,NC[&8F3#̿{T`d 2Į"$QH#9pOԟm;i3y?|!p;# u/ b}@)5OA 1`LA4 A&x`E\>"L0'|.93I9·sC-BDS"Xo l>W!u;CE4T@`PqceܗP"Rw%ˆ{4 ! Xܢ`A@`4Y1#=Kɔȓɖ'"]1d_X ko VNHs@wHkG{ P%kK4he>e[\$e"Q2 ([paa^L;J ;۱=Fo‹W$08E"ҟ!h4LG ;̸5&FNaYMzsl=} (E lZDܑCi-@@]"6K #펣 &)؟W mP )bb3QgޚG็Ba= ZwAmt!"\ IP)׹$N P `jqAVUDYPQ/KMR60^{~a]׋/e æ$<F"y)IeMºW5Bյz`oB) x+@(axBQ -ύDOjh#~`DSAv%,EH.َ}d`]qT4SdI |O k8ҲƝU,M%*˵ee1Icꔩ)&tghV`␸'Bs_ݽlzvNsЅX;ma8G-"Xӟ&>1Ēs,_:m]oGwp.ͷO%fKYJ?r~2Ej͒{͍Qkԗut,B }.@_ I|NVR1 p,1&TYt|@B%SiOviԱ!+%2@nk F&$(L쩒3yݼZNlIF8GGߟ}Evi?a*QAnX-|v:AsLu1A>"iUQv$"2Koߎx-\z^k/&KC~g_#>*9fm`o@aD8"Yp'xqM>; 'c' ]*)ArKD%" D#"q\)HR~=?3IBTZTYWmf~?h=9fsWʙN{DUhQs]rdoOVqثUmLQ1'lv\+ ]S7fbY j:4M*.em|B] LWTUՖdxYݛd(q&&G*DYb69惇!!~}Q&tOFJ:'d[i.!8Z~>y{w),uz"DdeaTWH7K6j'5>l?WuG^8~ZWJDG}GvW#ѴXt>}R_7=zIr[n F5DL";$"]DAY\ PD/E_l9\<dDn  76`s~vAU͗.6@$UBCb?I LJi]?vJuP2Hl(0 ܀Q",`"ެn%QW XѿN:B?ȍXЊC(3)0ڹ,$qΧ/cc(YN t+kH(XP`6Ǎ.Yԋ |$~HnJ^qQW~.j8%biZvI m1&ݧy Y\_^P /0r0җ- D\Xb-7 F\>0p^ԟQ թqcMbNڹhrB`:.3nùGpӤa cH e`P#.( [@:dchfp;a D,&T܀ OggS@p﹦08/7 " "!&%"!$# %%&# !"&$&"! "#$$zJ/ oa !"d=^S{,oݚaBq D42u;hU{陼?ٖUnXLaБz h*V \.TB@ 9(T| FLU"הPח~qՅ1e EoTSS50?x N[bsdI!2bITSu4};y45ȝd%ZE TUH:7 ~Еqr'qvIDSkЫ. j RyfVx\WӤy6|$dKY #RDQ(>5/w!M!UۦN ѣb+T[ȩKv껇@T5v|m{k>[[3&sB`x`4}@@x~&>('T™4ٌ&V-@ >>Rӌz0Flє0J]nc'7"$44HַS,B@ Er%wQWO"Ƕ}`q"taը)hKPP.Pܤ&=k17SLKҙp4bPI)tFzA%&oqll120V캷AQt 2xv1 M@q7>0Lw9L}%غ'a\:\EQ u4Fܜ!5A'~Ngx* P HB RDr/ٹra @)baכivܕBN:a.pp 0&/.fw7@Gp+>,v=/;h֎ }ך a` JA$!usi0zUuzU=wmJ"oن$:U(0-7~sQ$MP\"^XW-b&ea.\]6ecYE@vW-Rlī+*,t]RkC3]ԋ !.t[RkD{X<9ΖȒ]-%y \YJg{ŚNcXY%c8} \YvaER"\=W1wRYUJddYܯiGiͱ^/k0ʐ.d[%F5gkE={TT"[Ͽ), |_b,+ ߩrXw-'z߾:. gRTcLaL:=/w](\hؓ?i厰gjZ@+湯2vJ&a柦D#G nF{I6[$l}-Li4:?_'T"QT"?b@Ө$uE#\K|2T$["Kn. 4? ,֑2<@2@  h=!USjp(AS$D{aSJ臨Z>|콧u܋AESLq@`VP -TJu匦*L;YI1X$ n$Q/+e-+I75ј -Jp!ĿKZƲ`mW'?WΎ=1By+X'+=d56N` B)-9%Mwj*'Pn~(T@ %y@t~.$ᦋA糉,>W^=Y gCe'$"˿M}?sg<}|>q4h4R=!rӪ?wܥ1V1FՃRT `Hh ;aX@%TW€\MBw?ɝ|$~--b).RkW8Bj\Y-Օ̲| VP|Sj% dWܮgJK{ nM/ߍwCCUl[F6WFЇ/ t\wwQu4Ɩ@K("Ex=C+N@"%G&͸}DzKwqb 0ٷ# j@gS* "@sP8AYk D% ^WU@GtW`%̾hZ&´^I3AͳaQ6 Xf4 AѪMP)&EK-Ut͔ҲV잰tUEa  fݹR`0P#E U~!+٤1O <=P# W(o? y8Q>T01r"DL<5C\}k,6.W,޿ejӠcYNSsSch@R"(ܲ>E,6e Zŧ\]^F_`` JRPnyJo{\WFZ\]99`m )HQDYB GYbߚLk>yZƝgOJ@)w~73WeZR KMi LQ6M>Dzi@tTa$LWM(k@}!gO' }_FX5>KO!T^I)ND(L.Xc:JװǤ]_-{vu81Z "g "|wqso_[ekĘmV-1J@Lb$ TKE*@:d`!^,FpPS@ N`2Mm)sð UBReƇ]nLA^4jXaDߕ͐ej&% ) Ʌ&%Z ~{EZ.`Y&pthi?tp>>$dssĨ  (5c3/wMVZ eZ ^I͖+%@ n)#?J6 FOggS@﹦09\j&{}"! %("xwxtww^{E ^ R +aif@b,UOTd<:~}Ф)OWQR )i*Q bޒǑh+q9­^Me^s/K[pr, ^,6ELV( J=K^'ʧΪ߂"{8nzb{}lтjחITd@_dIr 8`4`h$X>]b,ыz5S3nP,K+>)P \mM̮у, zg8 hfOc̗Buc}nr4&PD‘;4R+ #$k5|c$c9u醱ىḩvBLT\W4wJ8O|f5+?#. I#/(G  BP0WU:\NaǯfESB2C3sWP:5X`ްۿr89#O[!$nA!bjJy,Q00b {ƁqEp34sLvvؼ}f˓2$e&>n+rt- r@D{iov /dw_}&힐y2+l<9_W1 b[ѼsJ9)QW 'gZ" ~\MK.PgNC|}F@DD)Ŕ =7Pn*fWHާgtaDZ _-fI]-*J I;d%<߮,A ,b?4+0&t]ԓ/sIem[(]i=BÄرc@S($ 1G"|@J+>%$} eh A@( R)A u<$O$ EhhGe,DR?(iIboCPPz!xpojb)0*$aE9^+.ol-B KI@Ebi`r)Q԰qiI-Lq2lWt5ڛ4EN? @T@) X"QIjd2Fu+94B)Ѩ+26 HX^T0м[ ( L)MR@8mfǔ2vl(z٢ƼV6vOhڂyh2s8!ave4o8Gb$px! kP X$vjSK0tK SD eģYfYbxJa0nɪʽau}u ,%a 9*\7#Q2J(^c`4T-RDL`#riu҇GxoK/#MߺW]nN.Ma< &ιF8YcἪO{DH(OٴTm>`]a"~8ޝ-[GL`qDO2 B"i`u :L3 416`ՠoC%!q+ʋ+iہr.  HJ'[XjkA$A~͞P@>&57x'i @1%B@T 7=fhE6 ZGT 8#@K.(zFnXshV.%♹qC3ϩz";R2vP2HEsWӽ10S0/":oг׀y]1 `N8<Uy 7" Ɂ-.XneLH 4af<$q+$P@"E"@6"-g{k|θY\>QDH.XQ%PP ^I9I0ȅ[@+pd" 퍗 ʍKcb1 HP a * );CdA ? ,%&}qRJ*Bb!Dx$kHC22ƛ4=gy:^H2[6mm@=!hT%`0^lT D9PV \F_D""| N-A.ok@JaH΂4kly3c FSM 6zqcwⅈP%HK]0Dmh nPJt\*&9\$0@[`9Dlƃ7)(syJ&͍[jݟ ETBDDN&–NrvSWlf_>re@F(H]o9QVg E@u>,nRFCt=qfRu:D֘ RJ'$nyjUfm=`;;f'mXP0 L!JpB%XyfEJhO @V SHy>tVxBTZNl4DwOnWG$qHKͿwNTPmzH w6ݾ \%6Yb:o5֧*2SyU_[CDvuL8-MN~ riTZQԮ=Æ{ \f!`q~_'|| rR?`&p/F[z]?:WxC ZYmz _^\,<+ e"4{Nԗ;@|.è 짓5` q D~zfg^N42Pnr|尤 Ȣ R#>sҍB.v,q}eO_kkke&iQ-C+Q>UCp}%,,aOggS@J﹦0:)0#" # )$'!"!!!'&& !#&'$lRDaՎ@P|ZySlυ6V`.J"ij2 "@JN+8}EL٣1ޢ?nѬN/! )}K!G1*jlCh'cU\ת0Jp) t?OM^<cC Ai ΟMJ|q\ /H" 2Dt&cg[6h|Nۈ7F9`Prv]2RʂAp"ɚFY)9 ၮH2+>9^5&}oǎU F=*[ . *D13^)[.S+BZ'!y Nfc%m ,PI]! *epRmbeaYM t axƸ"D3kN0 ϒ5,hۉ6b#9@Si|Zb3w驖f*-[^/xQAa:0P4)U WCi B$7 PCqʅ!>ˇxB\ұ[^W-i~Qn D>Kv#mk:^+Y fa/%N 7D$y-Ok0]-p҇$ ('\YpC?Z V@\eUDNjޜ6(6T,O Nw*Bŏj=sVBqrb&B!!P&A xfl>튂Q?EAq$ȶMP$1LvbmW t pPh6GC"I2$QhJ+aR4Ÿl]yC+º/S *6)y)hv9.1qT(^>I6VD]Zu_K dKM-X#~gps Ȭ\I@9p"XDnU/uRr UUm4*= q4`ϗH-I~Ò/yFZDY<>uUTҠ`0E3cPDYLD! q}k+$WmZM2$-F(ID}f/r&:8p;M~'Yۜ4̇%\ǎfvdalxLԌ[laN` kP z$V`9Ym2y<:܉bd&"|NMC#`u@>?%ʄ<#˟~JNgO:L:u=lo~!*|gޟ5$7&?w5IA6OGU ~]B,xrE~2o@9{<.!XF?#NXv6-2(#l?;.{g^=ד$N>06,'8;/btNqW;4 /_=Ah˜2Vx#t+L205A~<]WQ) JeHHG\괮KBI;.b+F!@ iWHG'>~1ҝyxpޓ7FtHbV8sL6˥7r8iޔ^WCvvqCCsMV,oJ? Vq1e< .nk:|Ń(T^ f1A_;g5t\/ú'LSV)xQO67^D7N̏^wۇ `Wp2%ҹs0YLpUKuQi7nZ\X7!{4DT]1P+DJƧ2i5TM2(VePq節+GBңxOvg6@~e Oé2Bf5I)61DǷeP΄1(ƞ-Di59ȕPr=$"A'u H8Dvy#XʖKK*R(D69g3n cu>ʷg=AEO-ĘR}hՎ!hq!5K@ ՀGN))00, $,A `Q#R;*,DW!(ov0U6k%*j*Lzb3=x0_^%}wͅ kET]N(+t[bw ]&ҞY)ZW*<*o}4%ɹbJn,KYKsbE <H2;^,i~xinS筄4U+6V,OJբ0ڠunBN( 7{r=]¤F>{nǴ7o KբIJWOȑD-ʺ!gߕnцZ:bFLyIۍh J, HuPKa ތ^K~,كREd309j(|L\4Kv0ڶvo7 @K,9{!`\((oiDbg0~{0`gB-4J\˅l>F 2/oy[e6(AW7(QL ,D2v=B]M_!tuPHGPRjpVS xk6#Z9t H\\;ѭЌ$?#}qp0{qN::+$^[ B̓`DpJDw%u5_Yvs\UqwI*"`[VQ| OSu҄A| FpULW!`tĤߝ$;[5Zޘ5DLYn{xӠ1kZq~R*TYH~9LZcpw¥LYHi:5ɶvs"V LUWEUO j_cРgY':k)ŎDW='kq^s| i#4c7:}idY)Kv囧l`"ͤDrS\io=d](ZEW//=u0=;֪ܕJv%6cķB<}qr26<gϒ޾ oNY&PM5`Mힸh% ;r;N59pr);MvW1HJZw7Vyc$4Zr1\4Iz9"^S-DI<P9q(+3.H_Y Fٳ_;rCt2 J370@(U%#*8Bp| d*U1l^= EG_6xang-y9*fD*DZ^ɞ{QӾk!BRWqKo5m@'%G| T@< Z3{VN[KB"7b$֥o(ܰ,DQR`?Z<Nϟ[\R54')LՎO.nuL͂2 9@+J=a, w2=??M.EӃFXNY cƤM~p} :}dva\h/k[>s$ud]@Rrony")I"M $KhݲTzI>QJ|,(5 ,ѱgILʀ"Ɨ`nz)aZDf,׋áUacQ>F`fYŷs]~e*8`x~wXNH\JҫN HDS95w űQC\א"Q6ujn #G,M0\<7=Fx7>JBB MϱB:j녁]Dsn^gjo) mDrʵȪgrk6][$@΁H(ݤ \bR')J9Y e1 K|^d`|K1cvzFLPu4H%ټol챁cpx汩?@rr&uG²pG,rS!r B)rMJ\NFVx<>D!iE R#i"((3}bo|p/PLH5{,SdW-7oF `T<2BEF Ep/ְ lB W $ %aT/ fXVI.DW)+:on8cTF*59nLdyZV10T[+I7/AY?nA*͝] LDȪa=_XH1&-SMM6ί7^L׺S=e?_:= )Z-S q&I,S գyzv>@.sUME7y/:7\_\ mߵun.btY + L_LJ/6x@7|qf*UrJa)㮒JX˦/w|~nZ5J?f.i9G_ ,{&nhZ2z'X9Vdm_C%ʐ&I?#϶w}M_3KJdG_'kJk;ȹ#ö~eRC JuP}[sФ^ZRV߾zx ϣ(i>|m:.Rv&7(š]04802GXzpv32GSoę^Gj5%*vV5d{PuHĔ/J&CuYi&IEđ o9}̞p[Xcn*~%uj~5kռjׄhGXxOn`Ϊ,jzӹa'f>iDKkBXƲFkgza38a'q8rl6^F!M,GYrgRI2J)gșß unwYYkP:5-}QPJs9SJ)gx{2v~٥ @ Evj`ehhyt⊱D~?CpĿ)hi"ճz_j_뵏gD鎳83ۧYzZYr$t]gĞ Qᄗ E8-su Zq] [#9FQjtK+1 sbݲ+tbD$Ȩoj׳i 舗Y0OLW矪Hz^j>gJfv>5\P 0EEǠ@LxVX¸4x'?}u1j:NΔsn<[|S480=@Gq܄vS)mir Lݖl< ; {_esVNT6Ѷv;phyTD}Lߐ7ۅЊdVe>~"NK4$Db^A xNEdƴK,S$R /l0q{L2dZqdu)-u#L]tS.rn^3UgQӹLo2o?;ݐ*=Vo~\H&^$>}! ޳N>@];as-\/En΢YֻkقhhZH}İˎu3UȎIv 9yS=>19wnzs?u_L>IvtG|WCꧻCBQ/Ҝg*-),f 5b>} nШLvQU#ND8TcvMd]=%o30oP鰈|aݠyl~DT@.^>e4W>ѻ2Rn*ND`F֊`ųp-.#&Y)sչ*1IIvt/z6{GMl]S$Pu(# wvvl*i`q DRv3 :K cC@tYfK`Y,RJu[2y^= `93N8pjЖQO'o~l3/-G}FtADn#9ohP6lXǷc9r}58}p6ϲ;R6R*:}_=Mi2`hE^VVD`!^ {-MUBXmтjZZ׽wf >D""U^ `˜ lIe]}U(Mziܛ3 ~4ndldh̳_>yմm*M\kNQ2Xn0^^*  wL3 ̓߰SARPK_AH%rz$P1-"gq>#(}c>KO:koxz_{vC7W!svsӻ^T&uKIso]WcڟYnR ;dR>nx, )%R.˹@VCTS?&z+nGM/FPT!,>?v n>4i>C뿫SpJ5 Xar *hexu,6\Q$z B> 6}@-@ 8 j0uugpKAdˣ3ى8W@  5qk˽ 88)4m¦rVvck>BSJfs1qХZd,3>^WDI,#P-Ez@R{x#)M¥V0Ə]pTVe'/yh $iʘ Ng_IQ9A\;"k a)+*炭:ΰ~UҠ/[FC0nxY^b61L?6vwL=ɒYQgO}^Dr Fw׾Ԥ[;"utqÝǵ"$)'.a S$է,UD *ynsw.옊txS%cdLY ahu[bi_5(T4WIfO9E ` CK DX1xpVt)p1ܝU\T[Te;Ғ&5l]qD <[ 8jNء\B&{D[ihȦTp\]Ϻ~ߔ՗~߼#oa#D]-${$₃Ikk :f.2&0ZHF1D(css8p)yh$y|jtNTdE%5__H2@iGJF.-ME*5)^];Bn?dǿ9ޛGz`3l#ϊ!=\T~_iMh,hU$6Ƨ >rāz3&j3Զ6y v `K&p0h jV +7ȀN2xn"OggSl﹦0=fȋ+!" &$%"""""&&$-1:Kf [[ܮus: DBZM!(I"5ܤS!,uRLoҒ%S PDFpD]^t## `. 3 ? ƠTmpuLJzısM G #;c+-6D:p#4B(d RF4=1Me۝1ѭ!DhQDW^X d@zo~D>6]'E`u~ Ls ;7ѭ6<]PG @֬5X2$đHA$G0R{&5ݹziF (@o ` R0h_<~V J@r\7JcvS2@t# H2ljb|-6щe#/$Gpۇ]yhU4Bx=F`_`tNuAkEe@ >*(Vެn诠N_s#>PkuL&MHImLшE?^<#=Dt9M2;u8,E@ k,À U OFd@Ї{"J9&Jv9+~)YG2>bEȡƹ 2$A R$ڵ&P#;e2!vt.g&o?H Pry8㸚5@q DnF~_$ 9rt{Lv\gک-i|m_bߡ'#*rL?ʌR$V,֬@20 2 "ETߴo^[RՃ~l5asG;: @ zu`nbgV$9P{\DUQ@ez4纷$ZbM!$: TWh |@078HZMV D[- Xxe%TLmR*,OUY\  7^֘M-\[pjO"0 =ws޷$c]^.V Ta<ؾ_:MO;k$%'Z+[1(@ |cV" _EuѸKKF-/`J'iK:Yĥk{a6 8>m Q²mV3{` ͌5JpNe/GvAɺ^|;דn꫟Zk:8u= 6rֻ,+"";cNrrޜNm""߳:e#~e)"E? ,LwaQ.&o׶f_{5d<{5I´`0Ur2)А* @\O1,;͍v9Dn) TCŵlnlIcsJB|t\8 J&eĄXG31)Lu;31~B:.SHA@az|` $&ռJ7(*)Ѣ?@rč(~Ln₟V)1B[p!~7,0&€5 R$]aÙ<Ȗ>"Z hrB|kZMJ БRZG.nV?D Eɓa@qa~Kֺs0֚5t Fc9Sk@8HNK)T.ӛb-k\Q :UteLw`QTF*lzA 4.1z ƨ̀zaHkN#hcyLQIUԺ'`H_YWV4̕O8&>">4t~391Χw礥iA[ ].D d$bg 27Zp $JeTW bYv F>;vi7Tl͚=*86%)e;-`#0mCBФ^'Һ6pi1 (F`V@1"R@KS eFUPzEd''WfztH&(^]9A- *v%h\VDF&H/u@wV0XP/A2QD@n ?X8rYAoqOsyA-rM %uPjqX$=*uģ v^ !BD+(C΃bcR@@8t$p tdHf!/>[WZ뚿T22 2lySAѯ}sPڞ|&21W+_YH A_Vaꒀ1@X@lMA2 7%/ G5WTr/]Q+ѵ;S|TQ4j̧n #LS|i M1SבxkNrE)SJ[DQΨ ;U~1 ^|=8]?8LfOZ0`G? @W0K*D R ҟpe.EbNEviʄx| 󲙱dx6+zhy:.Epz2TI.~5=e\@!)՚D?ŕ]{~2 B FD"6S[~-.Q YFJ\]>%Bl.1h@lѸ)'<[m$ɬc WfQLs߷sSǹھK{,]O>ߟ&fJ%=^⸊9+p 5 @.@Gc&N*OPƏ;MjYbB-D,&8qtW0E}\&beqmԱ|;ʋGi= 5aePYr"QhXĖTsV"5 I@8>@!pA=RJHTsiL̹Y.<-0 Q:FI m`cfPL~XPBg5x _BO\HPt)E&&x A ޫW[Eu& n B/}I| Fn;oS)"D+̷5lwbB>% ?nmkN mEr,A3 ."*mQI&f,$khq|"> K_~'d|_%_vLftwTD(tz''Nja>{òk}upsq=|4눌?V*Gq.Ѥv-T68@:uK$>\ 7>aA -R;уT~eI5@mn1@EVPTdAijceYW ;Y[ɡˣۑ\U,ȧ. 4ҫ@ȸ)i~@=~VܺKaD @pQ%xy oVs~bVfQ!9ًZ˗Xp6U$ tn=tg[[xx  |y!@RNp%;_t?bC(H't A Ԉ qOggS@﹦0>RԠ2""!"" )%( !"!!(( !!$")&~~x|~DقO@`:8+HGƍʹBHy"Xc]T׉*4ji9_J# Kic4Tj+4oܜןw7+eJ1BL-⟻sI =5ۘ"\[3+ގLpt#?)'}ql \_f )Uz`M+oB&vP9es+IӓxUW6Y'yOdFg [`Jᨊ(O#ъ I/yg45[ U?FKs͛(:x:tJ @{7\.b_ňjD(:#U? {uN`|NŁ;^ go>{Qj|Ă.W`C-99߻X$gbs1Lxj&nà1^~Pq)hP7%‚qM-& X&X7D*!zbEhBP\.OХ <%t7@קHNw0.w\]5.U0_絝p>4_Y(;|S^剋V|fsBz&ikі`cmRY>?,'rfqD=JIMQhIE(}2%ǖ=7e)U% Qͮ3@u`$B(HG'&BTH\#dF`>lf)P7v,NӭJ#0E0FND7m4Ne'.hwgr GP_QRal" 5%@ɇ#5%_xU?sI5 …{ׂ 2QE]V,1KR UuN.h_ _/3dlt?5ن?8@ށ7 _ FXJI҂0=s (ue%_;KTG]<~rP}Q}9AK}'WK*f}J`6kE8Xeiz) ph=1 YWl'[,)bEd׼XsGfNpCFThDSc) 9wNef01XDYJ. E6$_y-ˇIބ7rf$TYd:WvX6~+vB4qT[d+Sԗq+tp\( ;P"4,Qj=L=q´{8*# #DDUtMѧw=fK{i*oH K4WtE]hzvFiwмi#]+k달LuUC^(k^2{`8-|Z͹ڪw m( Z]d޾EgȵYs|q.{kqܙt:L}~H @rAXnPp $`GghZ #^mG DAsou: DHDHı;9'v_7b߁l]O5X/E@`+0\tk KhII ЄѐEy?! (m>y bXPI$BDhȕS57@%@~&bŷ6p{ZF1R#ME>p 0M"EHMy~!S.`6; _}ptb A%BD7TB!v>DD}Gq\ 6ALB<~L8: .BBIiHǶ&i;1XrĶqha5:2.H&J"NqTjyB?fȂ YT,7 "i$2u{g뎧 hwA4'H)"T݅b7r&vOF֢hÏn/Ci0PpH@#L<@\n!Xuɑ $`Vl62haOSAoN1 i.(9e4ItѸ&3M#wY8O^5|I`5\@ #_,ė pH~Lfb-*<6S]agjssae$P0!RFaDۯӘarKVq72Z<^t <&%$If:tFZt@!f@A{MB(d'h޹_Έ6q+x:(E(H#MDinL?Mٝ'l܏ncn@҇#U0I;1b,\ҀͯX.NaU8UXA^Lf#6~S buG+s:T1g4DDo.tFM;1;kƀƅXyUaSÇB@&SK ^O1@##J#:4bdG;&YEX$aV m=jJP!MD!3Mo@c1Ê]4˵f$OoȮUi(@< X?:,EY74DT 屃2@k gqC'@4J8DX3Ap@e.Hd @EjJ+*J#BA@"Uhb4/Q?h`X\C&YA@hgx30eN\k}w VXW] qk~aTl@O!(S.0RE)|"8r"?~Z\ ~pԨ7*7TRRD1M)iY_=Hp>h q&^ZĶBjʰoT\BXE9 Z9$HXc# NژS%QkS r5%d"Iq2O "r7/6>cIü -ںԀ^vbGX%,e oӨ h) tiͮ)yĸpաp:.n!A )狛1۽|:qX/)4Re&% ]WB;6Quk+v‡x,DROggS@J﹦0?a$|$'" !$#&$ެNݡ~ msUC-.[*\@!kyR?=ωM'ӭ0cS|~V@A[dhU(N>B !@ NS?Z|[>/Q5SYX2!0QADL%򄇈eZcwcb|]yq sjQ$(8"%"BDFnl#?7Gyo&rY9=-u8˥v.`$j@ O6nhrkF Џʑ ~T]e\s`AFRi$n摤6D_ .14x@ $3a+6p'B۴:;楤~WQZ&@O&ɍ>[w#Et8$exH)!#=cJݶ>xҕFhA=C9d 4d@ *p=O8XDZ:$)ϜiD8a$,3yC r})~|6Q1^qE Iz- 'īzf'5xf,WL?;] g46NZTz 09tpkw Bp@ 8LY92ĸ \ԅ8 hB ր<&>%LdP^4цb'yO1#LHoc?/WCjΉoDf`Y 'r| Mvc֊ /W!6G$ڿU t ѩ)µq?oq}ף譞a/+ %  J$5]1Y*ûf`*ZNph < -@ִܪ l B&r.sp,%e}|DUzC*q@pjȳ;KuX bFP |-rTHTb9n(:AnY*ѣT{W(tN0,0KjAiVcwy>y36&]a_8sLiFh?N ߁Z  ((0.& `c &`@M5 r PPە^FF ̴Fs j$MKIb]IgΖ2ϖe`fl9=8e.noUHoXa@- IfL)*s EG(6\ijQo> Í+QqDw>>"@K \(XXNĪ?GZ*zҞlZ3IgߪH"T 8^lHR 7ȀNhJ4)@T2%n=a|wdV;nޘv{4n|G mí?w)N+.DC,k5@Kv\e4ke@m '\9@%(\I.!H/?Q.nlJ(0MDR f?UZ"t}If*}q2t阋^eMF ǥvfq\%W1V̅8@%~:U0L6 bu#Eba7EVf~ׂ]y<({+h/g==vzӱ?KT UU[x&rRj_RDȦܧC 7Yl,m 4W8S9G !}L8bbGQ!*2E;$ ,Y-L6ECpY}/G/as! !X)K$TCLz:_&0\}3/j;}k}%@H7Z^. 8z0YS~%PM D0Չ .'"pg~VG|*oK*rb[7J&L*HDIclJ˭da,عuG W9]( 8ghm VD%`(րIRSL~MC[mݧܔ >H87Nih LD$H$H-y1-$08a{N ow? X\,̖Rh-ElYuTLx _/FHRM )֞.u#VWc<nHnݚk   )贻NK[ }P@ #wgoNv<R5F(dȢ<`  NERG~S3$ݯԚKVR"IDD$nTiix\L")wh8~5]Xp*my$5@bU  ezi@2Ҿ0Z Yv=@^NN]u@$4*M2uРNh:|4ߋG} VukP 4e ILt7߮|*scXygnωOWm}WrUjfYHwÊiAF-4=('$J.Vڼ򦳙r/?F.6&7<,Hes# \}]PbY) " nj{XV 3tYe՟!wV!y]7?Z`V𜚜(SJJ%rCq370uތр`l|4%1<8"M36G h%v4~^vvdD$q0FxVgXMƱ?v6~kMǺMV8Ʋֲ}לxs ǵ=e$,vs#G,Υ"(/DY^ށ՛ށn/-K/x°ηk$7K8^Ow"x1(sKWWwu/PAg:V wP83cR?)nl}+8moT-ӏӮS/KzˤY"٣{dX(Bݕ t\i *OggS﹦0@մ+'$!"!!" &'%y!!!!"%% f^bҚNf03$)bٳ?.MivfL$ט7 [W 4׸Y~ A` j _7~ӳ{Qz/Ðakae[RVLh܄7\S 2E[LDK{ACvj J&L DPeZ|ɝTVt1Q"fٺ(zڢsW|QQELY K(OTa5'zM[iks2V%j o l|=/(w8s\e1 B2޼n,BM^uzu #$w@ U\ lG!1%܂Vw5iZ1UE1T 0([u.hIu!2\: |nA(e\"aH YN@ Jl@)BhEq$;Pg =@FcVKv5 |7+1.+fZ H(5i_<*vAa*yCDBjYj-N^=Z_qsçvcsoD.P?1Au <'P })PQ/e$I2X.]jG}7VtLYm>')݄uƛGM\^J#~Ө*=UG-g>79UBDmL!ks]ODwcI#!̖Яmܟ.{MF p&D r_ũcl`B谛_Lc7|:d$!} Bj0/ЬÕTa ^k 0 EH_l0u+}O>?ZFG}o W5oMoÔ/ŕoztgv@4m\ȶuJIĢ@L۵K`vAy!C\(HUcJUjASbt;>bvZ@ f1ġVv `N0W&7ɔGst4M8̺\C*:`<Zs)a\u=vy9siN8ˎn도[?!mz >7 5/ 5B B"E Bb0ƫ3"j4}Q5S?'9Oj4 &s>2e+O?FX!W@ĝ8 eO#:Tps09JI;r8$Q(a5p- (ň>l/ih{gnjM"\p S kxն5_a  T")Vp/#cCxǕ 0&˖r'xg>}hM+{X\=#$1Μ,ygWf~ZEwzY,K-GӆMM ;:.Ϯ:ֱ5nG(`0.#^ IP$mGAl-DO!bThx.[k>|}:$bTSan^+M5sY-C$W. | 7@<hciO 1%˓q^ܙ8|3ϟpm_d.?*IYjm#섢f(d}[ꝗ o /V?~:-SR6cE 4cUCk%)¤$>XQx| . HS[>_$& xf~I1ꮑ/Wnn'Q)\qgm!K%.g٠Hj n/ | Hj{ z0,[.ƁqÎ1:,kv<$u.OJ3,)[_ Sߛ iWasz IU.ĕM9S%Z:, #?+Wk-*TրyH=أ<@g7R^.;[ <V\tJD4u 5Cńܽgɴ4zʝ^QW$ZHeFoEt 8tŒRF3j +\JF*I6QB#IXgb(Y~~+vE5ƭb Ͷ#M?v &Sx[Z}h ('}U,:u7 4!1! #VѢ+H >*[;vztgt֬bMEN?[\)щ(}"S'vso6e詞+o;)@Vp< ;QJA\#Q nŷä*&]+7@c`F*DźL u'$-,s\qn*ܽ]#h֕/YXQJe"3h'd:oԺwsNFnwB:ҙgpwW1" /πel16L܄OpH+rQ-íӡ}M zDykW|~V; 91yXJ:}"|b_U0J.G#L(wGr@HuQǒ>7UI/iX\(XW)酭H},UppGpr vR. ]LjS=6U?%*:e4m=ǖ]C﯋Cw1Mlz_8T$S5j-.U)"d~*yɸᗦ]uh-?|HlNBN·. &]U'z$7GLwG =Uc_^;9sQ@K/ o8=XT ^o*Z8-6#':)LBWo?ćked^< # q9j<4(+ؕ#!FhVQUr q:JNDcfIÂmtx};5OJFYsCԅ i|*x$K  C QY^uUPTrR$O <>s]P'+\7rkCԿɮqʀ> wPB4__S`6nlvv|Jm7WܲP(ʀ2Q11) >+ E]>,6}{,2|PUP`7QeU:l86ёۖZI*?u\(^9:p˙mb_|= !rh7_t#n @aSz+aTXUgo@+N s$Mե Z \I`H kW,N-mnqx3M9m+O2M`{W7Oџ;q#BȄ{r()dGqF~ d%"\#,rg!j0zMZ0! (a 2"d^ V MΜ 򽂣xiM`=?yamU>MF uE%Di}. Ǖ*|ߛ;a ܰHH'7[@n6lia‹&A"g8ҽvw$U.C!B^TUT *7Z/Cu%V>DQ})GR?`]NmcG2EDWvYʘӟx $-WtAY#X2\LUt YHl,t]3jȇ$DDΧ:"iq>V5{.ܗ%+\>)!oy~XjS/< |~ÓȺTYNPhZZ+=x2w^ZHZ_lX~M;ՆLWBUi9\C~*y2:&O7>: fNsyh>ad$hW[3_C./ʪVx9&U9ϼ5'S=?.a*x[C ZӀz\E% AF(ݟ8L隥s{~nlvj˚:ZlۉΣRԘr~6^Ռ4f. ƀ煁]ljWͳaLa6wD 31_w;Qt/9JM^x*([<$pN6& trshO~:=tQ80T{NR 0 ھPҩNr4bLwOӝGI>Ա6tzuFC\'Re>O[neC)? >W%MT]a~Z .ҍ>f4]t M1 &6&Wc4Z3c?ucaFt'!CrhKrt T]eǣ keZJiؾ=r,5*{un*t~u= g%a<(7*\Z?}ل"=kL X`%7*l(yD0pefHcQ{o L"Hx=*2W DD}3X" z TTP1dBٛ<\cEDdSR T+!O;P5ϖ4gj Y{$&l oof{L m`* y uIڸI 4iN#Y*GcD|X֤4 opo p,PV ^S.m0LlRV9$k>19a%Xpbqi9h> 6 GЅۍͧ.,@0/ K2eG+ ,:baL2?qFθl|7`O/λGevQMD+ ])̉Q)$p50l*SkcPS՚nx+V#=u ;뺑+R` +Af~E'~Z5&F-o2IId7eKSGљ{tKf%q1:jfjJsc%EB!.n2X]F^54R29I:jPB )ńvu]QʓPEQ  "bt$$Pe5&Lq$מ%8'!nAF~8UG|WRYدC[$(PS?2ۅ) X Xq;E`9l`EGE5Jޤ^ 6 Cc[a (#eyYW]l V5,FMZOh8i^{__m/\& Zi;nT#Tw0Q+@?LCjau{ IJ4 "$ ,!U/c)HW/Rb(j-&87)CUkO65⋆9qlB6CRu*øXE,RW\/5K" 5 K +Ry2@z' ȓ+ $ ^3_ @2rEZ@Cda l1{t24*Lx0M[[Ġa]+$@ [Fb )\Q"kؒʊp@ D]Ba!BX)@ _{J+ 0/B r,.FK|r W9nbC:e5[,/>m**sg Y;CA(q E,bMYK"z- I\^4DV#[]z`/j)OggS@﹦0B~&#"#!"#&%%~x~(&|n`$pSZB+vu.B G$ <m ݦqKF'̒"@*.¹Q*I'5> B9HiB@F`+_5@܅o l!FXZ_ĚA5$HD|>j2kcфM~Vq$`.) rD:x\r*bdZ84/T D @XG6V ,: %\P P@sG~ {zHe5Mt]GP.7VOD^C{͠kèM CDyO<]QKSg˞\6MMcpkx~so?UF .R2H *-~V5h6-sT 2^ >__Yք R!T]Nm|Cq(ҸpdRrlll{\[pFYEt`W1ZLU*7M/q5L4uZhP TU¨ 80C[~v=ޓH5k#N.TDSf Ao~KN-R;f@&u(*[*T[6( v?XS/[')*Ť\TW6, ԕdL0ݮ}]}T9#d7Sr[wݺ9!:w^j=P# !9/Y,,XӸh  3:s\ѧ#!Q3uK/Wupʿ-ĵd9d3OZ7Ҧ߼ A.rT ?C@jրшb)X AגCEHXRC#^(8?G`SٌQ#v'O{,"c !pfcI?)c<ߜ8)=o}1i>:8{CTfFnqaԈV5X?AnpB}QފH*x9[Paۻ1dy*(v;6>mt_b9,4S_&BBs)T3- CZ?j|6XnGtw9)5:ܜ 2e]yB"HD[+ > 8 rO˱E02[1?J S"$w}()^ H(k1qHR#C*KfC+d.YR8(,JڨrFW0@glaB ti ~CU#=22=t"Ώ2:ٹd#Nl;{&s84ÅyDV)#a5Jvrgr0JTKZ(iWS [Cl޹9V= Q3=,A*Q-| t ^i]',naszɢ4gWiGt^ S~:3Y/O^vwO^oU'kb`PῘ5!@C4F=+l.E0I eX=>~Gev*eAe2/2̊ Ɔ]t.?莒;sOx2]ݺ7_~GesΧղykTS,ύbt0g') z55L`FynXuVU= J؋n ,N.StTNoT$[&\N2܅q~z&=3 FR}RŰMph[w;_nS֛XXl̈́LieӪkudQ1jkn;R9]vCPswkqG0:nNIJK@&߭5: .jzNΧ|ЛeziOѥٖP2'҄&nFܓ1x[N94P&ec V~_Ltß}pɀb –D^|5A"^#L`$wPM/?=M ec{#YI=t<]4]ԤqS)KPETV.KCJX$E\ZJ%H A P X\d^A߲`LvRCP/W,ń~H.RQ:2ueY "H RrQ U #hcɻ529'3Fi7cz G ^.*Q~!HA}a>0Y6萴ȶIk3:*q #JiR^pk*DI1БXQ*wo,%b^4`[]T iVD.$Waq~Y1 nm syN' vX0h9A:e.ϚzEF}ŸrF5Ppq!"&"~5A¥~Kd0?qIDSz}R@d4[yYڗ x!$/1e j)b Իr[cڣG WjWq8B1S&$-Q lY{)ip,je:nШ.v(E(r1Z.^822qz=Y{;/JO@px€ǴkQv\D,7 %QQYQ,v(,{Ն*@>/uO)5E,( ;׋bץ~$5gfp2ݗYM;MmIx*E*@8&_PV*?7>(RTvUѲDe*}ܨ1ီhX{}=$'i QR .$HDxw:x{'KBn\5vit"*.H V(ȵ1*ɹ:vjLሏ MK 4R !;)h؀/? {bpSn iLf&[ew:(iVE h`,`,5-%1{aK,$.H;` \FA>MܕX0(MP M@I ňH8` +DfXLd4|1GhV%`ʑ<SPa:B.@q@P!GOggS@﹦0C0.xuyy! !!!!&%#%"#)$&"! #!"$KBQJ(^REvWBNXP1"F3L`avqK)1d*hcaB::t.JF9A  0+BXD&~L.2RBl`ȩ=.' ǻW@YLb1nTc$,) }'}9.|S#X ^Zh[0,*%}Y D׽Š`1ȁ$~{1?h9ZqbxSηveb^K$̥9wk4:5o9UD1`1 ljj7چaWV( 1lnC?#J)~i=8sڙ 7"i ؾ]l u$QíQit֌a~BƀNkP7 H.wL!$pAB0ԕ `\>"J-U/k, 9N[ڠ N125fnTS<|$R;=.hAGW<  ( }(V)datPI" ]KNЬЉC@W (ݲ22v"֏Rh]5`Hhwi6֮TZ?|XsB ] LtBx 1\ t2X PHvLQꉋi'y߿b85iE LW$є96ypif-[ǘDQ\IژcriK|ڮOI22 DS3E4_><8gŵReWZi EI>K-#i?!ON" (6AB Υ3OaW3poÇX_lY̒SwE4r!ZO΋i9K@nC!'7j 8Hn~^B!{VWPB\,)sG_w~-F~eS]}\3[Z'Eb9V +'t޸b9Xl+cOMgla^7%,v%jVl̎guuU_嗟Fl?f^j(WJUibN;lDDcp+7!-c(>&iˌQLTP\*  p/HW(<){`*V݀Qۭ!`ͪdI]u,"bҧ=)\PD(0}P;ɧv WXBs@Jo 2X@ƨ7^nEl@!܃!BWWq >f "#GǂcvJbLص.XD'RJcIhH5v%t*HpPrx>%(!{9W5Lť, م)#7r7 TDW'+ ]Ђ)e1o)_^ʼ{NGKZm; 3n;Ix\D(#@ LS`G=#iSE=ؓ2\HbDSaS^.`xGFH;wKf *4MeDxڰl81{vI&!"LQ*|dBEh1LWg*5ZQ,dy9JXqSHjZmF:F N o6v"ߧoji}Fǡ "V͹ҿ9Xn̝?]z6589_hWFzȓ#l.h~ ]7sdmKhoŤ]٦5ˡsnԖFPl;[1vA7_?ζJK@7(eѦDi}E}Qp9-JqyW7O1ս1h-i`^JErH-9Y_m 6YbܶQGXgh&>ٗnR\%{{kIdS /̤(x;j|SSsoB!YhIg?qcg}eޑ[eb*yXqڿ/IXˠ,n% %gTF5k\HZ},p]N7cqs6ILwV[Ħ8k8‡!RI-aw7 zqTKC9Lz~,Qߦcy)n)nY%{ z 7'ѹT-ޙ%T1<՞h kq8ZK8zF=cU%|\j0֑}üd[BH^vdHbY/A,\3ZÞ%m/87L{+Ҝrde٘ZcM ޼To%<>ச%(՗^1FeMVc<;P]c=:p[B<޺ ^cDPHAP`4ϖc4aBmJ PlwVMY^5TuMdž* 01ePΙ vJ*$]PK,19C[6Q?Tba]leWB?@2}f ="?6\ظ؏Hz h 9?]l|i! ȑ Mxu^EYlV>::zqj2, ǪV@hEP o!>/9zg3.8\V"VRJ}VkH6=9 |-ZT"ȍ;s砼5xcA1(J!c7Қ_.>\wH`1=}PqWD;UZ<X*OggSZ﹦0D#N>G4" % "#(%'~zyz! %#(wvrv|~y $"!")$'!!V .]kH<Ɔ5l-Uf?~:h=c ;۩ѽJqY;8ZN{v{.4d 6ʡgFnDAIa$ݓҸS.1yLY%C]=gNALL*{xfN?-br+JXXm, mPAKbBS5m YT]Xw5z% ʔNR%yQ/3}]b3y'^l-"'jU & /**c%(P0@t#p͈H((#|!=,.   L!ԖYV]1 M&f Xh@ l( 3xbrY2HHȅ.nD$DVA |nAK" 紏Q؊?]7VP-t#wsz\Ft4l6lu'[*+\@SHMt;J``ob | ؂;EVdEDDD|fxHM#,I"M29h:D, 3,w&/G?ܟ,$Ϭ1JG~vBbIZ)`9| $h4Y$QZ1p3^LNQ  /AC4V!Dw:$70rY.S<:j_#t6v엋ÀH!?6& G"RLK=cˋFȡd JTVx` n1r (?b1@7L62@i;Xm""Yfl >Є7q֐3i*# AY̯P@D$JTeČݠgrD\\{#.arVC GUXT鿨8UV@eC">v%/z!s RJ\PTbX q;%c`|Z:n@= @ŀ`  (HX. $;D2'G)/R Z/K]Pߓ;1%VoAW sZ8Э Ct>e@s_@o "ZBQP+)RF?dtKZh(ZW &][Aт2MI bu>Km'Rb1Ϲ3\:^]%ood1: el | pQ O\|" 7p (HLYg o^=Z*1WSILYaA5Ss"ߥb' 3B, LU 6Oʽ,mb{y5bHRDQQT1P~r~⣤1U[dP"b\UUB*+$qdbH\YuZBaDxd-R`u `7@x6y ;N&^|%$   +"+f$2Schet䴈4zE ( PX 0V'B:$rn~lN%I)NQB6 [jPu4IB FD&ٸSlճ"/Ďۈ7$tz@U0x [)~L"x1bV d^lɁb= f4 +~N;, 2EĈHDFde_"v"%:k}XyFP}K}X `,%>R\҉1čVO)F `sL@*iDBiN޴FGJl9w=8Kemf|"MJ@s@B70`ZI $qqeEZ9fl/=fcpe?GTtJK ,c/X슚*=`jE2Z4+0%E@ۨp3п PzPXڔW2 "iH~H \!iEh81Fdq-*y,ԀI~y'Js b [)ӓ+`> YV{$%&;Z nIR~'Oڑ<J  #;[f-A_՜&%}8X?STbM7 '!*QB7B-H,`PтiP@ 4YӖN0ɇi/?G 7WWLK%w?*>X(Q]! ط%7n|~Nƀ;^ :'+JQ~Jw^a+M$A g 7lh}eh. ! *ψ( =! \,BjLˣ\X\n + DKNZ e$bόYLt@w"f9QAD2uv Ks]^Vvw CA#Z@9a0@KIY )I)Z޳c Od`%*E(_JvS L\ޮRYH,h=ܾxU88l&HDT5֒Ŭ9ķ|7YW0nr8[.u~u@r-<_B1YG >`EXOhEZTY+Lc}E ʕQ*qYTY+('/9Xx V'V4jOggS@﹦0E{7+!!'(%} !%%'|{%'}DWfYBYGW查︒(DY- oĻ/Y<سӬC*Ϋk L[8,-%>8j%Yԯ^@ލ?1Z b؏9u0"DJq0Iqob>nqÞ<hIu,P"YXi`oMi^F 2PɊ("Ё `H3\(|>p, y6LY ]E".+# [H$"@PX>f.̼tRF';΢mR+]Ureq,@W `Qj00>,@BK.R 5&mm9 IFx.dlQIv8(=n'" "M,S5~bw"""y[@"+. `< `6@KʑY]$KLWjáǭWrN/waLȯDVLShGD~yV~ռ(9 b -ILWbS?4r`?8F;=qHDTyTU!7WG wO}b ɚYs㣔pLS"ו fjmO EʉAO &mS%r kK 'mZoŦ?ܸ3r)ΔR Q_U9bej fFcNRHDHT4L|E c%ɟt>si&:[A$p5PS:ݐ4\@`:m44+,ynjqCjkB ǒjPc&rtn:2 -Ǣ0aNwLۘ7Uwxfɘۥ~Ej6u5҂tEc</}1hb46ϧ'  xwÒSws#w (iX'xF2XȸnQ뱺,mIJM@R,mCCMLPA}%Qs2n[㍲"p4K>lEBC40$P@PK2066~7/z-Gy#"ʾk6 g;].?i(@lbЈI2r:_szun|ًF MocNwVE%^)vh*jPZ >˥txTPBPJ-^fkS&-Ƥ`۞zH`zVXm'XRRiLSo Y;NOI$~S'u*uv%ņ7а:QC}-vW.2GTpC6 ^ ,9k$p%΅)% y_ ٹ#$ %U 5ˀTcC @j~Pd$<'V^JEbDn"QPE BQB>@Kq3+ $6PJ)##"!z6]KloLPn#`]EX1{{WeFEj1b,4s_L Fbb @eQ[A&wf'4! `2M2o>+G\'x*o>0$:@S$iJD D F v3u%KNQV"%c t҄CBlEE\\ Ƣ%G2Gm]001f$~5V6eHo6ͧ!BO$ M!(Mh>(?OD,$#8CWN@1MFГj' .6#LR h'd/i 0PAIp 7"B" n "fedZeB 4uA}.4YQ"|Wڑ\N#I-,=ef ?$Y.vwE)PGh 1 XL(f9PŚmE7"+2EJW%I+p.ƕ{eZS60"ID$&i7ÝMi\֔U aA^P[}Ҽ#`Hr&p pN:#lAC0 `"\[e!k=zi4+{tg,s)]mqdpYʛz`cl 3fӒ<>SZJνzl|_Z/âx%nhٍJh#Gt7^kcvJwTabG9ј14DSװpT|B6`AɶVEY-T* Š0!¼l6*y]}q ¡40!28R$Prw5'-ѻ70] `.4;PF*n G)b$E' PAudq-Š]])mV!/sk1 0"  @Ձ1:xp/ow.^p=7H-@% T~ p·e%`Z[>ғiS(.𿖁h1tJ_'׳2S! r!F"sҬŧ> ė"ivQ!0_YE-h_0K PH9XN͂Z` L] 8ekm~GqtK:|dYB%6`_" d{jIvs]=}ѨyқD3d]d2Wybč\P$ä}gȄɩ|.1a,g("2jj[x])đ׾1z`[w{٭nF_:h:|*:n\,DF z(nIUd?k pv{ApOqF̖7IwxV6ǧ&.nqsQ`Nm$)ӵvvs)+8rլiªBKq'm4D,-giq9ß/BNj揁-n [BxA|b#9RI0|8֦U\T)bnA#J PG¸l.OC c/h[} /cRd2xLaKQu\my\.3% *HPH;ȉs0WA a d*(_XEn˚W7fy%Y]d(P0T,(^0igL A;s,j^uѪ.C"^S3{QD_ʂ@i> Pk(Eab3rmoiYg-ѥ p fD D*|gFߥ&*JrJP0=I?gEܪտ@`oT+Fd*JP:0n"M",HD*hGBE n^\ɨ#8Mŭ?D4Ϭ߽X?\l 7>6!X*xd +4_L'o~ +FtGԧա+ZY^ IR٤l4u*,Ը x~d- # p7 LUajt7}At4[F:I4jvRTUQ`u4~ZkOO2i O F"DUU%=n~$wV:Y(d0 %J)16JЌ͜;Z h0Ef$O9By"I|IVwJHD1s{cMf S'5{'J `* U(!l$=Rq8B,/$x(j?- .R~ v`[ \Ñ4a[g5[I|݌(i4cNsN(X k>V%XVw.Qn%@ &A*TWT1`^M17]ZЊn0خuz)~/ˍ%$'M}|t|ijpt֤?;tw̻{1@v!8Xz롖k-z|S}:]qkf.ߓOPv_q0jQ}]DZUMPx}=S ˑ-{nS"pfTQ^:x/!te=C1q I\R~CbĻؔIwӍ7}Υ.'h>Z߅T?OIi$-$Y"-P҈^,!;mwK/3 K XR"b2y>%YŒ_>BtNJtP<^sKne@]Ÿ |U?ҚlL!ý˜lE,FE#T@E~-,^)PjK5>*xߤyzD4._5'{`<ʝ&-/8D9mRS?@$ @X& X$R cF_vB 9D&] 1܀:*OggS﹦0G>U@ ###"$%#"# " '$& # !!')$&#$$$)%&""!! !'%$$# #)'T[M=@{Y?-$Ao*TK\݆Uye4!dhJ5 RWLΐU59|m+:@\woD!$e4\*Hn<(#6f|*p,#Yd߁mpXT軕]^T׆;m_@o}ǚ=JkO+TTׁj?˃{&D97uml]ٖH{n- h=6r]ѕ&r laml`[wi\*+aKf%$EjcTr"ba)6#׃m7-uGvېk':́O^Ɲcg ^煅v⹠Vrhe:ӡ L;DDMoc%>_rJP@ Pp#QðTȥ.PfX3(B=eo )ꇆmFLkQJs^@C PFM[.z94 ̹3 dBk}h4]?o^CNݹ_k9{԰(^|Kܱ<&,nnr!b_T?Be?:@!>wÃw m~j:Fpvc go߄x2+e4W.,Ǖ"+BYIe,Wuz\О,bf?2K MRI1D@ -meX="5=4}MU\ېQ~7ht+o=Ď6dި\Y6||\>aAjZMf! bClڢ{9=~[ZzFYc\E㼣=p4qʼn \׸VɃSl i|NTݼ3w^|۝;q/;>&{LLu 4?{#m?ͥ'eT[L,)1q76?u(vcXgJHbTېkڸܜ;R;YM!(8~Rzxwu>{FJñ 7r~2>|^Th0 ;OCJ *+ʅ>9ELgU6]֕v!k(ocsYk[ VZ tEvvx*yDl6B \8=&X_uV|'>c&WV\C75b2 Kx"%9\k5OFV=船eR6Mck_ڮ?yԻbz/iccܚײ!l ( y6b(tB1W[#p_{WEw $x[]7oяbZpnqIk\n(<Ƹx ).16lU6֞/3gVT:u{M>;Bv$lYjOU7o{z$N58= d_)@')@i}{AHBITU|j^ҳA Yc}TUeT{p=x s7-1oS2dWrGGʶ925*5_º/ g܃/UKUN9TY - ӟ?,A8fY#k6r_Y6NOggS@﹦0Hq5%$"# !!#&$ (&('&!"! !!&#$%"$*%$&}l_ H`B a z64Lv^5^MH5mkbj-iWPHͽ о\]B]bn[5^e.,Pʛ~JVDuݽݢ [Q8R}p[oy:zQD(/[C#M*s~4;Ez Ak05kJ^}cv@yqOp:KW$-%;+S_}: =j?}BeJr 49ڥaqQ\V J1֝'usIl 30qw^70C#acUrǂK7NϱduX^KUJ]ic}bBдQ5f,ȋl5jtä>0 1xؘB.~k]Fu~J{ݗQGy]x: 7YaZvxBRPf)h@__ѭKk爋a,rZ7?.s}MVՏ#aZݫ|˜S$qmwn܃)]oQu=XCFʘzmqx|kjqb]^WNjGnl(~Fl5kjTF*Q\;<end %\Y1iȵO?]u}l&^CTHܺTWUן{^LWC'o\ C #ϩwA"T/\YPTt,y𠄯CM7gaxCMDcz{ ɻQPlU;:.TctjLڐ>LJNȺ@x:)uV?tcI7jR5bJ8/[\Α deUz`k>{$hrC5E_l]+,rYr1TrΩY0{-4XZd_rE՞K meJw_o~??{.l_Ռ"hOG+IR77L$AîѾ̾j|e_9fvAB2!ȽB.WlۏFL};pd,8!`; ϵGDNݖfvu\]@pe7Z;GF{rA;7e^:Y*T[`)*W/WipmzUpDLa6Hn%a*IePz$tcmo=>)Ph{++O(>Be\_+ltxt]Mި7hSq7rVZID]aZ,#VjWa].,\[@zH {QܝZz1Ox\D¬+ ~lg/·9F1eN{˺F% 0?ʌ˛8({-J_("Ը̍//z93ԝ,eEZDgo6$Id~6M nf'j]&pu:͑75L/ǘꂓ0nϷ#;wvkӼ᫠iܗ  0(+q>.*١yMOJf?!ڒy^.r0;Ysvwᆱ>NPY%H6֍4$$鶗j\ K=7 -݁e$@wJ+DEi:JH,z}\ܲU8lrRohD蕙5O~q>%T0k)ge@kƤf7Ie<4X;8a]&yc zc~cʍ̹֕LZăx' iCz5{@BL D@IT _o %BW<ےxy8dOPνMc5-ߝ7SLyx &wih=)dKtE5ވE!zr[T=\;]4&FЅSn(1~+NBZ%[;`w2 eE*@BWgYWisڹP5J"]JF賂qo.r ŒBRhHGMARR(")]`R p>T* * 9eK&y߯٦~Z6L<oGp;;psVwsfe4;ƹr^#ݘχ P|{L;ȼ;ޚPU!I&‚'|oSpyVjؽoz]Sޛz7>Gj˱b.+QжnHY K,~JU @m2Tr>FZJj^ft7N0}W{`~J40}jx:P) L,䦻YYX, je]XVtFRiK Xcz8>cP ke@8VY8'JNޟG\ ә}eF;qM흁{w%Pu !DSLV%6M/g=ʡkxgF}_ZFm<[l#>&@AtH (,bق |͡Z#0saHeՉ: $B|qQKsX-lo ;it9!8 @A2X N3E<*qrF/^l0Io=Z/²3U*U?AZ@KpcR|DG@/9][Dߋ#PT})L>9DzzKv|b 0Ѡ. $0Q;kgNq/iP*vWBF,yzZ%5[hUj  +DZ( *\Lیc>]O)E,?5 KA0 NUC& DeJOD5QAbq),lqV1Tc:_:;=V/y87~I\VR\l8)i>HtLPkj>ζ'9/"uws[!%]h`kZ. "*) ~R3  O ^ iD]3aͷtq)4bNJ[7O_2MKHVo{\0~**>>PIJJdE*H^n>Ł8HF B`Q)~"FATQ.:JFv0^zan'v  z|< /b-t!(et8vzUBD)ŠIa *OggSV﹦0Is+!""! ! ($%zx|zup#!%##&%ޫ^@v1 @|<<]`J8tBH1 8J/ԙI3©|0-k1@5AP_/1ܜ=7o'/5gnSUK2OB}Nqkڰ+( vFۅIAMAbX8,#OH 51;habݰTNzrs^-O\pH WX^ %[NIǬCxLT m,\.gc a0đ"!~̍t pl ,(P{Sn\ݙp15Ǧ7f?nܴAX@T)Ki]ȟz~dnbцA {G(*t_-LT5R7я7i^ugLtgvF*m l7D ~k]od^XZWSp#2EfxU9| )")YMvONGh(ðM4ި 8itg'H7s(DzBr8ސ 竾mɠ. _޼.&ig'Kb.6g"y8ơ-j%N&$ B`tsf\>7}lm'U?3SD -5@BN& "9"e@VGdK _  >4;ߨ.ܕ?ivt;"!( !DLhay\RL f!dl~,1@5+E@ R*T{ t|FYue9GZTBY I @8: Ȃ$u#kf:;ghvܘNJkfB!@S$Pq.*JǧE}jΏ%a'ow6L 0l3P@?5lXr``ܜ`rQfOm0}NGiG"-X-fR2‰/='.dSbHFdmi4vr8Qv`KT$[_hۈH*XVDܞ##g2=&<5,aHdĐGDAHiۑR<$*踪:/f;k!Gc70 ;fn@ 0@@uDn]${30O + P$! F)h@ !u!iF|QEJ2,|@t DO5 r,Ơ`Z>|.nͩ C6FfmfjLwB2`BA,tu)bw:Hwp }%EyPv*|  i25xž ʂ<@%xjF\7> ,56A5^5~7wE JeDHӏMU,*ץEW֯.s"a}X'IBM& 04kF]k6+:ʾF$tEd 6ͻBS7#ɘ 5,wԛBu\1(9kŒs*HGxdpNeZ6MEVG&&R+B2e3u+@y}wr;~--I%Tdt hC#G7+ٔ( +Y\hMeB@{ ?9O Y0s.qeBdDT__^O%)Kc?{ϰ„A6׫P 6' \C2SCp‚gD@It ~`bDD.^CsSiT\ BLߙT{9sGnҁ̸/kG\ { (g9(e <2"i@d=T @>Lwk5B-T[p ,+@>8A-|. ؠ6DDS$3 Kb%ҸQ@5Skg z ګRMx  n/h@ێf[t ttE,~PYQ{JD%ScnFfd5= /v /@ph]0_,"EnNcIx]wyð0vo( a K=' BIe &\/l?7GmSp,zb"IF.Load;;NԁwfNLpjx! cϯOe@=*o:B|T@!טͯVM(3`JW.xKzA_!XՃ;VX^\tF= mc*_S{;S(`%=qVֲڵV!!6^k FZ?R,vjFWwi{էLx0"yke\5Jf3>s30(AF.W 䅫2,&0,c Bv!gYQ , ,0H4xSVNw2=)mY01c;`fƢ8ʘx6=ˎZih'm.тcյf2{-s~ͼs~#bwV@X`o&{d|_VY~g{,]"@b u ]tzR ,"35f wgI˗1$z. iIFOƊ|ݼ^dnvf6M:K} on9MӹL6ޤ~)FDH1m-@|MQ9G 4f]hrϹ>z3U'?xvv+LcՏpaZyʨ ě=NC=`iK]YAb$N6xdK)%kt-Vs JgajPQJAK 0nL)WtG)c 0>6🭎_8vgh@҆WB:Yxoʫ-Ln{-݆R0ƈuDTc  ~e.!-Xs5s6_ʟO8]{3X\@l3W_|1n"M#t@w-U ҜyA׽CY W)cF5! ~S]Iͻ&U([>׻2 |1"U-`@geɧ㴣g/ @16(}VRpyB !4X9S*>jp}0" *-D(VtuTiBɪx""ܟ?I !Ok6d|Z!zLWݴNR} i`o| H%YIQ[nlJE+\"A\UNM'$u:Ici\΂YUT2yyJwRuy,MdɆ>{{F5k|/7ZLS1TT_j]}Ҿhpv(LOQUG"k~T?Dxꪣa=fkulvWtL[UV~H<܀i1tzkGh/#Tc嫱e8.?|?Kz9[zf#.NixkKB26 GYtq8:y!p+>xRwʒݕwӹw?"o 4;!jR-DU#LR=S߶N"[i Lϳƣ>/oaQ:7ȢlzEe]w*ˀ Nn\_N3Zk c.g9eۅWGx 1W2ќԬKBrL,dմiݣ" јDWz APpo? Xc)tsCDZX J@|vqtL;e7E.nՇ0G%( ɱF*O44ES7ϟ蠛=ք+@ ~}5;\(^/uկ++ ='0 V@jR⒅"KN5N1k@\H GLz%"'I֜7vJ<j)\#nC"tZes2P.f>87FIsHV봯Tp5r a|1Q9-ݮ5Yz=[.؍ӝl? 7='>޺b޹[^VE깖6h(I3;2v<Fo@$tj]xjX1|^O #gMO9vjjOjN6!-E5D;O/b۫_h-vӹp"T?kM'C =QԘPR"4X*,KOrY۽WVfͮ 8L #"=n>}ݡbƇO>! FPnnn-F@p :*7^M|:$[V; V,դiΈdAL&  B-CI)dUέ{uPʍYTFj6߼]i U/TUmg ~ok Z1ͧRiqƘ<)y_U=gG\8wJ*T[˨~-RgR'|7k_\_Յhןy6s\5ש=qk'C T]*R<}B|wBY[ܒ*/U@Ěw&ړreҭ$|z$)weO5ڳ>?Qnt[ 9iWICC2-{3aU~nz<Iα?jHL|a裮<kw+^>qrbrY'.݁C\lD7ìjJ*6J`3i|=.JK^2Ś/b$65n39J(q!M" >c^=q:KjKw{߰Lr#=x%ShzutZCj\7!2o_v>k@!p.UE\>3 OggS﹦0K%-!"##" '))+'*$&('!! "#%(((^,@|"7hjO}oa2ko}ChvVi9Lhz`jGHJI7hNy8#xe"021}8zNL:}n`j緯{21Jרf־4z_̽Z?ie Ɔ CnS V~bpZCfX-^ duLFE߱5v-$z; wn}0ftk$Fcivh|r6y՝<p w;o<}nm#:1ٴ>Qi-/YG1JzVѽҊ %Z!0,+Ca|&=BQMؕ?Fxf963:XpsYC('_&Is\߮+50*XǬ=ya>ܳe>OQ_ߖA!:V6uX_[Hpux 2ec&[DxP^\^LgV "^#|UċH!QEwi֚o,%*=\7٫ٜ.J^w&~8r @6 4N :i4i ID1#[;fp2=S+`7<%zBrP%d ɀ+W#yI]O[&EDN11)K>%{wvJ+=(2,X)Ϗe+J}<]} DWO`om60  h:@#,YݜUd D +HR-7I$qlJ$"%1fCgp+8HX:L}M+$1l`o>:"`O]z jӚ]UW.:ukTqݍ./"Dc %Mx `s鿛ƥZ82=__}*E# a5rBы MX޴g 7ϒuPD-p3G7K\1ZV,9#A EݤC<֣B$ŹR T.`[}X-Nwھr@W/[!"IU R3_jVfeGQoN4c _5F5Z/Jq_]yl Jۈ ܞ3i2xy? -M**Ir(f'ԌS_d6[^$2j@z5jW͟ee5t&Gj{ls4>iĦX2RO@a~ffM/JgEsFF8.plίʚQ]%lD.-L c㊺9'QW_^=u4j ȕ547:x`U6'j=Jfw],u\~rDQ! ~| rcf!ѫn*"vp&L0[h'*3ĉeNdvȋ#D_;{ }Qz*k;I6a h *]EޫY[1]\f(`TK^gvAEOuh(zյH|ۅ҃*a[M'bhgJlhU'QџE.=3Kk0}qpmi&i z /2J1.+ B 2m:.@,W(x|! N&{_^8MADSfI/WDy_㞮E*4D ~c_6"D(k(%$1ZVl:gRޢ!D׆k_{H@)S)tӾ9سr,68i2#7I GKKZS7r<KJȊZq ~ֆ\Yʞ+!8v+(H}%t~o7L]R'H}ڷ."48MN57Y&vCտw2 %`XBh{赫=/o']KƩ㣫.֬qntq#:=i.[ؒiIc&Tce1<^‹s`"c 㛯|qtr]dnuSCTmsrv`l:$~=MKp8^}P㫂 >T[8l&z! wNr6uvIlO"kf_1LW.$Ȭ]K ]j~gn}uX:F ǚYi/Io:4\ X遗.tghiӂUN O~ ΁Ṟ@ 9ԓM7<38#'ůޅ;<?m[+Ug_gs=xe}n8a9Ox9`e!A ZLWA;}\-_Yd HTN(S!.6K }yfN3[X9'N9\/< BS:ol@˭6=V}kxs}rGps+cį=rGe`tڝ1w3|w&y? w+ն'DWU.Lk_y0ɡ:A>w(% H#M dNUVu0kaoo132O9`D@sq~sMI<~pC 3cTbTYh 4W"VpH$I;fdIʑNNZju]cOggS\﹦0LBtK'$ !"#%$'%!""!$ $%&' !")'%! "!%"#'%(&'#%&(&)()%##&ler^O`b,Cq+^l>?Z\\ez]Y<<8H{5Ӑc]\da@`O ^j)GnRCS-\a-WW%<R MqnXR|*T_ qdN%b޲r:9l2Et_N\7W7_<8i bR;.ʒl__WRZv .XꞿuZ0<]h^?7^AF㳯}`Lhinp%D]kӅ𮣃)<^OyZuF:o<>-Lշ5XwdŪ5||ut_dA(@* >pZ9 rzjqe<_JLH]775kbmQMU(%8.K1\7v 𪦜:4kcJ leV#ic DcUr/.0 IDfmMa*kꐦ ^A7S$Oe x5;wf{E8}Ş dq\ђla9|.T>(կT_W!UcQsȯ8JD#HTsstX w-zk%FN LŚ^Khqc| R˧$MAjzb~>;~w^yo٭?b)LS*EXMO|{oBfѤUI&ot^(ݮrd]ז h_dDx9]٤nQ0+Ӯ^LWR+sc=ih*ʰt__Y8): VH 0~}?t_)U z0L뼤zݷR{͉sl_ ->>AvJA1ݑs? nM%Ʋ2?Э`=8RrO<Λ:즦k+o.0Իub|&?1Od](>I@wjG|w oX9la 4\bg tf¼g R[ aiD~(sϥf> 8)isg < '3"M>_w}SsC*JιDB{ 78~mmtӄ㤉kpo'~t0)E|tV|=\~%p{9F<['K <8BϠL(o T_c(Nԃ7D &4nwlȊI2ixĚk55/sbL "PjKfoh(`jvt#2_W݇45+A!8verS }l84ܻ>k(pW[TrzOҢcOe \_e 9-6#{KoWsOp'<_UD/̥Ѓo:gڷS^Y;%M8`Iv.Yy6y屾us<wyH~5C5I[Iiڴ/'}O7G 3Y{-A4@ݘ6N\l QK[zꌾIqai'czc Gh-+8Rl71D]6YTI@j|**̧Sӏ{~a?ߦ(E4[L-&n\j\XQ嫧{kڸ r F`1捂4nBo>^O8~Ral9;hهjܽu$9&cIwKHNՉ7@Sp8YQřCΊ_;,,i/9?d?py}Y]vp:_s'9|v9I7:X"epƷ0usTY=hk4x'O9yS~?d_2՗Rir5(yŎRHשk[Plc. q> b;4獽|wFZ[ĉ JMex7߮)#-G0?NR9D4]M~WM+\dI)`e2DEpScvƺ) Ν|s009*.4b.%mQ R +PB'Ɵkc,Zx~Gcv <)Qj ^Y%ٴ5IaBCRΉɶ DPa A!r0 rKeH?1.xb77nE^\ B,i%^H 2TYV2Ͼq)Fc)C{DU_Y-bΙX?@)T3ڰƺUtS{`*%țjofzTOggS﹦0M8~P*$"""$#&$(!#"$$$!&'s\Y5?+8i[zdy[z;FZawUD G&?Nim ^th1͙Cc8|qf<fS,;w(d礝7JZ1RIؤtvS,Ooψ/̶.>ȓ VDspR>u5X8&}xiY1#Ʀ0dmUIVٗ>ʹ\w "A̳<3{˘~hUw[0LgH +dѓ ^l / }]`Pp!>/W'õB*q:Ѡz, ԁA̝cn\%sIh琲W+DW5cק&oǓuϩ>7j?~ w(و!RKd}4}> := _&L*\2Z\7SHba?Miϐ s V?~a*-QM^ѡ>WFv@E,a`o}mOAGV@࢚{FgnC%J1 j40`HT X UU4ώx7߇\. 3$yۏvͲNF[B(qTж˵3XmjW[8e۱ILفjl<ɭ%%G^ 0{ L]{UׂϠ>S͋%vUT2D] be߼C6҈n:u. J%%%p~DkO/d%oV+&|?86NS ;i+v:!I]pmY]j (K;fI^ڼy꿦J3ϯ~%pݵHiKq&\/?"Q+H{"I SLI_懫Ӫc}U0!dw :#H]'4 }N$sG֭dϛ#i[J{gWh5.Ի4i?0ӃɰsL^K[_S^sݣb%mv]/ׯ\^XGcJU{w|ƣųK^F溊?U5kdlG֖t,8FFQpaZH>%&;L3VCeф:eEkU7>k 34\ix'I&J.]bM=BhegHj57=画n˚+{\0봫$ ȦSkI/C噲ԧ^ Ƙx aC!a :<* 7YdO@, {]&%H4$'y=ϸ%"Uc@HcJMh@pz p!~#7z֝5C>qHJۘ%)2@!PQ.;~tcd2u#d=j~GZ q|I&&Ijf (3rA<'kTc(#w \1VuQ0L{+`S",*^ 4+7 +9d#e20>XjwB":6ӊ^qlk~qְ M)QT/֋5:N7`G/Y8 M dYF L `^,QEEJJSX X7K)8rK%5Es(hQcCJPonhC?..3x*[Â;*`?Fa{|u6h!fUHڜ0b ]B@<` 05|wpzӌYιO08 ȦdqHE!8%ϊ*fAkɆ"pxļ?=1)c-IO-ǵl9]fmkoV)pK@ ih؀.*@AM!ŒBý6ې)C[Sѿ+ 5SSi?EI9ߵCn.rY0 LU!PI0 9*rR$UWi8 :!TLST4ߜA0iֻ+ѩIZ_ <Ղ-|z ړZДތXPnL:IT_Zh:D r<-k6)5CΖLQAb"/fkgw/UE$?S¤e,ӂє=>bᥖݱU[5vrMj4\~Ko?r'\*elTWe-\#/½5ޮ}- d[F/@{كW.ӓ$Z(y. !=7Zm@6=.@i󋐕5}1nںqjnuL7:o)LKf]/t0}s̪,#)k)Hzw(L5`Q%w[վk߬ #5U"KTTT{/cL2ӭ` i"R<*ig*WENr`9DB#r׹eYUUm` L5@iVs HtieJ2 #( tԴr|ͧ "&#q鿌N$ sZgu%&v<1,ƚ{t4*M"H9 h`c@k ~ֽj՝7jSY#.Eg@%}#n~lTOȄ4ZV@ 4aLh:C Ce [fkWP-0@82 +j^+D#٭ KL޽v!!P !O!hޫog;M(-;[ Z<<Żwa|S>*\pkᰀiIO.~<1Exf "C"$  L?V򓿡|Y)zMasr>.4ٰS 5p+hWLƱ#cekA+ui'-Ep,j8 bp `l*O1HELB8]mcm`|5W(B@U ` tArvXP/KťC&}E.e1rۖNE#&'h5pJTK:Q)rIfP WFqe3F.\t@E_r95;O@-F\gLiZեc@ba,nh7,KGaXP8F"hZR>>h97^ExJ 8W 9)UFFʂ$.]~+v5j{l3XU=` mu%OS";k]HΧd}E:)UA 8|*@j CEU@Mv1{oDVFP ~*yU1*"+ +˥FrP ~a@0bA#O)Q!EЌٻWfSչV{ @{M\P@ tX+\ ]U%ŸKu(R?~cT_+# $W AÕğApJQq/͕ևh_X|BQBd+P7 $_+s%,槵0 eZbN4IexaVOu{`|?F Nόټe0M/R+/v(A R!bwNV$NE2W pXz80}.1wà 8+sOzSUE+'>UX= Ts!}=@ATL0DқoʾF~X7 n-},os). 쓔곧Y׺ܞXVhwsw ,UL'؅kwi=[kXB,ULj&:A2"!_n%Zɛ"q,UЛy{[S6$o+ʈ,Ou5Ã?|^70ˆ+<ՂM<1.p(jOt%hzyKu̞<'x$j9|[y C*b:,Mʇeq۟|3-@5CWTB.,>5<4Qv {L l tK-c!nV DUu+$\w=xۼIlfX>')w.DQ *2E3SGӯ28CQ$_|@@VP{:EdG+E? 2Ldɮ%o7bTu=s^qk>-,Uͧӧ NH+InOV_Y_ϰB`p=75oimJm T_Ri&*#\ kXp?.D+~!X @&L `tzDtdR]N~yw9.` e + >VªN DuxYCXHPk7RT^ €ї*H L!3hZ7xK6^R'[M`g,(ݽgtRG!qDHМ %qi{P,2b],IzV)%&JYnD"eE;A2K >ۅҁ ` X~&߅q8Lf)3}QQ`bc\[˿LKidS;x е(Rb;jɅk$ȊFBr.IDKS-쥨B#kXqY; ~ :VZ炅G @!xX4+ӟHi)u_K%X![PZtG v`4${xKt(`@DnłRM˪ ME0ZGP]^+ڃԗ|HSA]OLϛEէ 38(R͓:"1 @j@1 DBm=paVJ9N3,VJQR`Īc mֲpK>'jXx03.Jv?>hofoؚm?>|FÝ/s Ti6;A .|G9YR]sqKQʵJ@[m8#x+fҀk F1Z9XWOSBHK3: cpqL G#ȨCAPg@*(3`ͨ_jmHHu>s-f!ry%F"IDj{^VTb6VDD/(LZ8&&Fhe;?% #A[<*ofj/z5mkR-Ԛ xW;O cz^f{-J[AN!:d;Mx¹Q 2Nq*1<pQKnV4,`7q\p]#0З)|>*jҬYMR4GI=<cO>_ G9_)5RDSrQT˱=x;ZŇC _l{}a?.,KO^_q_4|NFQPW)`Zؘ*X*e) u\W+ҁAnGu,\rB&JTx=Y3&ć\JfziQl0:&F4@3p$nM̕eZ5֌F{ߠZd8sRuWۑB JB ;&HL0D4{5c Vz5@lT)/w[% ]-n`gO " (0 0rPYEl(!oNJvq,LqʅXD\hz5xڱ/TEI 6~"*&u9\ ^9CBڤ/%-bҔ?i}M 6V=F`&Ni^tGqyz=pD!# r`&"l O2ZE?M--Em(Q"QGs~K1n [ P|%uͤӴ8\+Ѳ3k mEf}1틴%O*HDgX8\@ J50@@(2lS36K?IQ k )f(Dy #A1,j~;1.dBC6-͖EdY`g/kÂ5ua O)ɶZf9t?-ҲmN am3(ncp<hl@(A@pQ`d+KE-VNq!EpJiXJVA)|)ϠKoe sC> `%`4埮>łUGTDr.owDewX {K#GH_ 8 W7\[5 8r7k N׾(qԁh=W10gEE˥:n5 8 NOggS﹦0O*'^;& L?p0oV GY%42KP"nV;SIU \nu?e б[`|@p7ի MKS$ -]N0a|:pϰ#KuSt{S<XhU!֊bt9wźu̦7K;'h)zȊW{C.݃dԽ<.|C|(jU In)y%@*_! czlKەi΃n~@885sG^K~:t15:|U>7 ,).hnrN)Uj 7D0^a #Qx n+V>QG.S?eN8ƻl[|>F!CX(> P R@C]ן:}PoZٰލ_;\ռwNg>:! t_ JkqihE/Ixw.WyTJgvjF O>O=Ҙ    pG$?R 2t()*F5T|sIؠkCϨKH{§{P )jp[zRA!Hxu%q#D/6 `UJɮR`430TQ -v|B1Zr!\l^`t2at %n pxX"D=>we`-F6gٵC41轞m 0M5riB }lqR%qHZ 0`1֕Bc̩`?nɧmޖK"Vx]+@`{qu`c%4i0m^ICE%Jp ML};R(V?^Z}w> ކ(o^ʩlkyȦvz_yZqsh@ +TUT)Y; ěߥ1Xq n;&h\+@l/FbG/HΫ  (>"P 3L(C@W4tUP`Haq^;F9#d IJҭ"`>#(nc\NӉo,lcOOvumZ^4M RؒBA(L(P,"fv\gY,_<j{r *9ҖAu|- G~%\_ŊM@z;){I)\ڹ_aS2u8aM"5#l)AJM+ Yr{Ksݕ @jQMY︬ݦ2i'L15sVY+1JkTQY ^t5/-Uh(EG*> G HG6 1,}@kk䳒=EHĦ;JFy7˻R VfPj H 'x,$Eԕ519ݢvH]o*w4} .eCdv)DsDӓB~6i?>$r *Z`iȊhYY쩕+Kb~2w)$pn k `*0AųP@ ALzh^+ZF} qZiϚU`RJ5VD #jQXz^JNF1i+1 -F>0@ΥO)Ѣ2?,G;2F=ű ZG=" 4%,xNY!XuKn*5}]qCMB~4_J(D+ܰ^\Kc+5դY#KJ+DL bJGq25z7ӝ?҃Ua XA'%(IpP1 F}ziM(阦1dʶzYcx폐--b٣k(uӌ%~K.E:-#۱5/Z4N`J2a[|?t2Tf[*a}f)[FG QP5 2lLgT֝JPg$:g䶶F|+Ϝ/%T4cXdϼ1B4*L~ŘȮPflj~+&F(?+:J3VwKaODC"iIr!lm7~8-<$/;b<@w/D|H% k)fTV8t2>ks֊+Թl90΋.8 >1^leV^Fdf%Z/KX>׋-܉{.JB^sUbRuYH6c07/84* p'ڷ@Zm6@/T&Q#Nw{(^~;꺹=!홾Z^'](W+U`h84Wzә2KS M^1E@ Et/bI߾_pUxn7]X|?qo/pϞzu:sE~q|]u"4tD6Ⱥ#ppKr 7|9f}˃}9 c;(mאOPfŢ=4,Vg$M5QߡF/MkkZn9h8K)V?T6|*"Cyg'BHwܦq*8Oc6tsfK͒βYjc%V*DU:z6x$hQC2{U-O(Tq%Dk63B667Aڜl:bvӬوOHJ=KkGXI] ~|K>T" Ġ"Hvm_RH<֤h\o>߫ΌId5AH0%<h~Y&/%"֜g duDvCwxoS;L#ӞҖ-D.5(reu쮙Xqj߭3⍱nZhDUzsCy;h-1F!%t#o6,;vm+vw1qS@j(δPt8OK}A V 5_P+@ RI/(I18pY^j߹L,VMOו[^\( ozxa뱴 ;ňh]*x hVZ7)1j n6 iL8Ucޡ%1@n(!tqJlK(W?&'c[n^>fp5XqSsrVnjvl,WkbZ\SVJUHr`[1MU;42H |`NAɫTAiꪗ>uRfHzxV2~``>< <  +} @)Fc]2Axu:ѻB1 G?_Ǵ҄RٝBͪP2~%J79R |ΕK3CDŽ|hEN4T>|:$rM*fV@ 20FC;7l0;GE/hnͪvE&Xm3ĭgI܊GZ~'/tRn^L5ǚ('_0t.9d?!??)ß[Q-HE>|+!O4O&c?lsZ&,hK1V9C9PPVA SD*dWg7]wΎv)NʙL3g ceC3W(O9gtfo vf@Rn5i:r7#5dʐ^l|(0ɩX4B>!9W?[:֌F$z62GOaB( M R b `!Tٖu!5za2cn\.(tN6uP}L]g.g+*Ի*> fM2\nJiU%PF\{٠fWZ'skmtߘ:JDL֪>z0J5_ ]2@@f/?VH+@d*Cqhzm@|Xtػ i*Ӌ2 'S1 [_WѠZ,5}ػZJ4F%e2U!sB6A1WʦgtHOsoΒ)"0YT6UwZp pBmJp+ N$ k4Pfd7<;Y1eBx!/Xk(iLbJ&X5G]7y^mX T~C5A0Q7 f+kkwvS C3J%#c@GsUp]bV9dm2\AwwC@IԠLOּZgaw*i-k]1EWai h A=":ԛ7\XDw4^bp^ |#V {/b=ZWZW -~)sU w]w=INF.<}Afzpkdp%$ajC1e/EDDE@p"%bHrWucPv<8,p5GPq־NsݦPW,7!XkXFvP>:&U:Fc\9@k0O'OI 0#sz8\~{P-rL@:h#?;ICqrMy@ %C9*}vK"\G+3+DO&CCrxc`,^qQfdW*7Wk ds>JVE8+W*V@6O€~ Fidг.wT: Y [T-vCkH :Чn *ulKh6#WSR8({WkwKkez> ܧ7g,PeIԤ`(Sl~ aQR+qx,3Ui:ʂ1\PHZA肍PCi ~ xSNbܒx|Ŕr2WUͫr/}Ӷ_*3T}wUMi9 59Ve|aRuN<_*J~WAw4h])-wcg%`5>H*(UP:\O[5R 6Mha fu".vɭh~l=oA3SJQVTۥ=WA!~U$x_^IqKF #+a?6_Ԁb6?,(\yX r@ @,D  Pp;P~`qc%Vp7ŴdXCF)E-Ѯe< \)8.a @#i@ xPSdS+#><\~Hs UqImT@ ] v)L Z@ͱloؓ hj"DVHnNß MWBq|N} k O$.+]S: Dsd̪:ndh*QZSs[>d#|%ޒ}ze%802U[xTGzRc\'Fw+oGUEVp̏zGhs]C|n.Ua&dQd'4?,gD:$© 0 dڠt@3 (~nw\7Y-Ǡ@ @ư$Ya^Qװ<~PׇQ^xM҄ ;PACXn.H, 80%>4*.eM,dT`+0eL煕”V& 5~Kǖ/u2֒ S`!C֓l >r6LVM%D҉L?1zcogݴq Tl]a|z=voU%uBD~K,-v:Z0`>RI h]C7a6d#G]ȘϞMt>zu m-Z0 d/2:@F=GX[V BqoqE+(qEBXjy55ަo?HA($#[m՝4nx_b0~7Tz"_X\NFڂ"v@!͚Z~QHNPp72B-]⸰edWIU +c8,&5IxOLCE5+t TjOggS@\ ﹦0Qe +"+%%~ "$ !#(*&!! !%%#"~kP1V c\PG~$Abeh.dxERZ'’+* y *L- ׀`0y/b`] ՀT $*DuKmM9rjVP jY.ĭ^{f<{HKī(UExb1'ؒ2slԎbVo+Fh(@(d%E/RZA^5MD^“Pq-ذsD}E2H:#*~k4 Qd4[yc$Su@:F™4a?fdDGaOb4! ^VP-p)^U'a,bXxV/mJa]NCVN6ě+eӴPV_հ[\Y ;Nln2Җj~+r( CWb;Iاu*R7r"^ua hwgSn ӛXcN^)qm@g4@PX6h5G\aeQMJq]qYv3Y%JpS@K0ZbRê* "~ƺDdR0L.:7?хY$fnRSqǺ1F4 "fciȷw*#@P;TjSe؏||6 nr^SxFĸO3Jh$4/g/kݑ]q׼c іpaY&*2*hAb|pi7uU1rbp,r3rn.~E٨e㣀У>1 ;8N~ޘ&JݠQ(1P|u#uFjNYnT“*P֭ @+vɍL0C3" o N[*2v4X]P89߁xv@^h&0@OcHH & Ê:Q;Y9ʚ8Dmm@J7H->nVJ V.P@6Ka4֬Nq|91@eı,؏h:#oіu1JGK*JD!e= A (O{$6Z (q095br-nV@3Tj߯Vg? bЌ.@ 9K!z=,jgqHʤTY1S <[z:0QM|r4r} QD>5{>^Jj@b$@psƨQ:ֆd֏˱v.B;6B:!rGQ IY"$I-Uu5$Sp,|fzLZ?ax "jUu1*Qnj>;4F؋-,,|`-ȕ7+n;*Ȋyyè-} դD)z"U^h=rPEC.gA 4lj5_|ܠKci86ɦ|&EFzfcqje @ѧX 6(C)x~><ӘP eՄQx. HGgEfgldVhL/=|x@ž#eF QDZCeCbPeڽ 5j+ "Sx9 n$T\H"};ƦT=m/R L4âeN֍ jĘͫ Kj丂`ǰjV%\H.gEbs.?V+طGH^bD@jf"@sXĒfy<}""Nr/t6iBDv|QhsM4w#ҐFyw*pbY7|Q7S.Dnah+j&+73:kKlLk$ U>T1FAu(s6c,\_*m_mb%&+Q@/Ю:}CV!GQ+(Jni3+-Q_*fhD WBr ~+•4VDi DTi83YyeaQXx+L@\ ty=NڷНw3lRJ=͋ Ĕ'F~{9%IUDzSԒMe.VZ0?.cT<՞Dm`~'0&c蹢L:ON\s]U>vnɆj[ ,тhtdog!Ғiֆ/<1fIANj`B^8vf|gfvLWa>4sL&q&cZc I2uX.4M@Ĝ>h?M/-2ܘ5a׬t٭Om|xLWEUY ;'I6Gel6<TWzSUwkR)uiJC|[:~GpLcŏF`Dz_c"fEb0J6N mw7IhLbu9_s?y\:h鲄pmU!G sSme%ነ]pW}Bb:ILzPX ^#JOggS ﹦0Rh *}vw !"##)%˯"!!''%xx~y{+Ɛ!Hv \!:ƿ.E'"r4wCtQ<=[Nw?ؑ$@e-a$V(%܆פraJ8Ԑ'Y ¨T%DM6;ƄXS*s%aj Ic\\?D`\1TSz"-WZ"c)xl=at[DO8).!˻V)8ʫbU98r1O@CAq ˵]/ $DByG+aC_;ϗ%l2s&αP01%.YDD{rLhaaX>'{/qF{sTq"J\"yS dY]t"2u5YAֺr>H= IMZB`M>+@>۱@6)UOw|H?yvnaxaR٬5em 0>zĥlf40I(f̅V /"泅FFb KMVC V/m |bdR!0A~m~:)m) +VnݚVF' &*tcQ\dUj3i$(%e Ţf;&M׸?@Pe1*&Y5$0)c vXI[/X}XP'>Ix\ v|޳ĮGRQB~&@ pga IX(+2&00x~+&t-be wa \l uKi7yh$LbolG(|I~}ġ0A0Y DCGq9Y^%K_ddw| 4OzH=HVPk[ XJÀ*. ?_4JJόh^zԏXq4V6cJis8mWƸcTB6'_U2Iܦ X\n2Fm1zQ>W_ iWp]d;ew3UaB;C FT4G)b2h(7GݰGq*#=0w`=3udGW_NcFfU9|n 8$t5ۆ4rI8?njix <ML3NUcBc\덇Rnȥel%ep2ogƪLX*ShQFֿSq.XwGS פUz j> _j,ᾯ!zָs;K{_eҐĺ߭d/giY'lNyp޽XF mP:}pPz]X/"dVv*z]yxSi]M3'5h:Hnm&_KytB%SUB=:;@]iOw-"-vhM/I񯞇 'o߫F_;$d)5H#>ku4T?ZToi\W-iG=t.R*b=_Td2St`$"jF(MLA,T,xWMH:`,&El&0) ϋ85/XD9ßJ3>|Qo?t8 tT_Mw "RTXwDCtGO5b 'EH:&qVO:&K c0\V,OP_ N[ 1ξkRw@%7"%AGTL]"#`x $J&j~)Ԋ$*bALh $JA,ecdH]$6ypJUD4ڨ׺prf{6GfW̶ YI658el-3`6`:Jq eKYx`@iY6%Y bki -@Ofe-~bX74VE'43Mde^X;=pe 8az9:" +\| אt8WAdufIFr'+os~1jXlbOggS@2!﹦0Sܩ@2$ %#%(%'"wt|!!$"%"$%$#$!#"(&(~xr4QI3~s5SIZWǻWWXQ4Of->d9Oef3b</9|Q맛BnvzYb 7g {`,$GdoAdL|UE,4i,riUm/?z=bQoi i}6?}!-:F?=/vTάlD9xKcDFAn$%SL Sd@Ս47d ubIV~sZy Tɫ9XDbIYN~״2q/܃a9Pq:N/~J;-JC|{ok64e}=DkE?FJ +/֓O[^ZE=6420#oK:$$I JiKdU^E@]춑Ь¿kֻvϼ ! 1Wz.ՋnI)q |6$5/,k M@]S"43,]HiL>5)kPr1Y. pdf-l wg_XۑB;ZxiDYklc !D{6QA4Ӯ?b,5p`Mgf(ۼ~;-4eƍFQB:0"d׊9\>C]j$n3VBc.TV#GrU<6c\ 45Xia *.Zq|47sɈq,qp=;E!49 rAEfh dZ\\ф@~K.+h(Qw;ZUΙ=/0c"˲MD?̨s?S43/hY sRu@ɦ'(Po@-|gqr rp*^IBapZn>9%ea@^&Y=Rbq*AvIԺ9OƥÜ8ƏUTN)G6VdiG@pP(ʁS]B,MGo{x0_Rӓ o!V DQh << xRYh4u1eDѸ!Y4Kk7jS[2P"=}[KfX/A%?ڲfrC.Qsz"` ҔB8#h?0q-=iҊ{ qT ni@`@*  Y >༘nP(zp!pfX IQ-!^ -Q5q, sl21',%Ӗ؇QO$P 34 @ YR:=X@̳sX+ DSDAcDĘ?!WEb4 %>tv#UZVs)?Rš/s/2I\?}; t w ] Jj TTޓhj >z>BC'qDYu TͰ.-n/Ň02eg66Y @:enZ܏NY{brO"^V~ΟϽ~Ӽ/j#V37]WP`+8{`lX#Sx aUIaoyeuJ#3[B-E6tZl^ VP)YX^ǡelū?X[bU7M|߅#;t側ufzMWlD<27|琲a]q@)MC -iraù KTeyU9x t l5_TS(tŪL+Mvnީ=G{WONZa <Q6[7w}Bc莳Dq6Uo FǛTL];9X_UjLͼt%?vΧ* TlK)@Ӧ2|o Rg&oRc%*1٘j@4E*Y)Ry68FD?ƠP;.UMX%C~LDɸ"#MҤ]<cQXfB@=PJh';K>`A%@}A@$`E.--McXzƵ M8Ln[/0!G$JEc"L7*q?Qi2 Qp#C"gG(D#\Lb T.`pOggS@!﹦0T_,|zyz}~ ##$$!'%{~ #!!$"'#x~K&`6TW+&iB`)Ɵ~JqiF8z6Wu|g U2'f'@2ԬFO* @ _ /^' ;Lԋ*{#c }ͣ RD ΁R kv{U-<8q2z0}Zs #$ 1QDP㌌ v6s/wGԯ4MhW4W@X-`LhaɄ RDZ¼ H|> fDn1utGL󪤓D;0^#R%M#\@cpLq_'`z(>0[S>TêT#IM>8CELHH"PʻX%lȌNv{c[]gʒf$u<]dE";@>|0bHdJB|.TJDlz$NcxiD5ӱsl#" =3qddӰnd VNa>h b`uČ.n 1eJQF hǴoF(kbo@Q)5i \VA!n6ުQ!QӟNOd;n:{F G[(l41!%@.X "4 vɳEI]QKo~:{yv kP^Q#%#wARk)].s[[./lOєXDN/G&a 4,>FWDsP^;7VJvXZI Ƅ,.T? z'M u|fKF JM(1 дKlŁ,TB"u+Fm~ByQϸ>Z[ɦXd:'sӍc ^~,N \@.8lJ:NWy:tb01>berlĄ;^ orԈ <_ۦΠja/`HEnM.@|əԇ;A:*xBh(aոk'tˈ V_YECE(>fj)pNI54otz6 gQ"VOM /qe2Q@׫BȺZdE4p<$H}xk\t T!XOJGjtދrK'0Y:j$ҡNr5@⢁0ԅ" ¿+V C$@w/K/R"!1F7$oɀ3@;T h, A&N"L"^A ^ 'сZ+qĢUF 0 %T+(PFgЊX-VP@b !X8)a\uVNT!!l`S \(oYre,kVA + bªr88X D( 2qQ+~;&\i$-a^vDU:/H(VN;Ua@&ܚFhgOf[6gdc.Ђ>xH)@Kj9Ot#@!UH'ZK&|/:( SQPBS@G?DPхOfRc ^D:@Ҡ|HY,mB́qAjj[9~GOX2V`XWϹK~PpHz]Tnr)Q!@ceNP0cV:<-.+ۧ]$\b*EmڇrY[μ9Bx"d}ƸuZΫD4Bɒ?Jsyu^ycP;cp@W?8(UV(b1A2[9YwEƔX-ލ{fC!L+cq+'g$l*uE%2CBDUU$n6xPiha7x^Wd4~]~xyjzBFy d8R@0-!"f*_RV #< >@!'OggS"﹦0UtY +~}! $"&&"{zyx|"$"#"$*&;G&EKPM}H'7  4[Y95Ҍ2з$sk H,0@ DYŢD@A3r% r~;NmeI]#M @7Ow2] 2a``(GHB `TnzjKuT 2(΂)J$_H;T~pbKX%Hi4Zlʄ 2D1 "a_ŽӜd FmN\#ƒ.Q%GfB߀K >1{ET- KvXS󻆯!zK B 紛0J4KO4VĞ4op Cu*7X(o8QqP vYMW VİȒ5*0>,v¿ {d{GC^ra@b)1!t")B>/=}o;`)0=] J mf!wg1WZ Y:@%Y2Xts΢]Aˍ~K8@vnM! :,ήΌG M^?&JU ʟw h{{Vu'w+*nP ŏZ@:Iv: *=sDrsXF6,n5jlM թ$-hĜۭtaט,\]79H?Q"j%02(O< JǢN@ _XoR@?@+ɴ@ppA6S Z]hgn3D\Јc~պv|HpN>Fq=Gyc"4fyb8emWyHA$A Z01$ˢ95nzE{$˜W7h`TMX0a QCCdH Fm>E2%Z/5"RQQJaڈJU ;~;n[>Y~i  I }Ńt0lL^ǹ4:+wz}EobVrW2 o >+Gcb,c,^pSW` $wa=e'Ƴ7_֐v%JR?, ]uT?V5L,h庖WAZQ^@DU]C S";A +2HD{U`Lrbb":eΛ Pm;|ÝE1%C"$ :i}DAKS5{@(7 2%` j#ZF/7 iMs:EWh;!ct4e;zWA;7fjcKyuIx`Uz/d'+Fhn(kzC9ݜVC,FKC]:x]-nZ!ޜnT@kxVq/PWMDSO9{QܽEțBBLș6){kQ1H*y'mӱԨARx=V ,Vi7ʴ{R"&}IP@ތ.U* s{aIv锈b:cLyѭ 1Z//̣59RG iޣ&jf0hPe=J` .W/'&FS ˊQ@|\?>V[,,:A$@b 2/Q aUQ6eΟ><.idžc[?eeȵ9=||?txk̀ADA&'e~]?xP c80@Ĕ(pIzu5^xĀYT+BdDQrQկԾ#`/sM q(![~Tz6cox``i8 ~8** % \§?ǟ7wkЎvX˂Pd @(@]c@@dGABŅ^RoTΎ1hsPi))((#bD̘ת}y!u?tR@@I@cx@  ` Y$@E [Ԉ H~;56$!tcBBwċ;0lP~ĘDl7ESFơ2 DT@'L. @ QA6`%Y% 9d0 }TgQ + " $kfB[x@R]2u>c7*y 'lEDD:P-UKګg@%]?wľ;  >\}#,H 2ȅSSmhyj0>+N&B6I[]fV[<+%#Qu$gE<nGk4@ e ++KDlScQY>nF`ua.n}m<V.űnh3HEկI= O"l/_ɛI~zoiᕦ Iw5wW$p9{Gq\ @.N t:B  ޫ]WW~u A }UOW s\L[Eq l=TXf[ H]Q(I?tA<h΅p,x+7+yęΓ/GY+>??YƒӒn\WIc&IGfTDQ7<_y索l:Mr!Hm 4ӂOlW_,%*8,q(LΓ2okβzc·F \؃#?QA%)[$z^46ȟ T\_1*H9F@u~Fkۻb :i!ʀӴ2CTWF>cJK$p5nZqƷS42휱&:"-{}& ͫ =( 6{LWMZֳ o5BZZckZLRiV8Z OggSx"﹦0V""!(&""#)'|.Uam> 0u˚͗1a#rcwӓE.ZfQxTiow0M3`h(AmvVXWIoV ^Mḍno8qzk0n2l 8Ulk;.>\65^r*s ]/]Ȕ&aPvp!MΪz'?Z ƥ0(UX@`2|DcUq ^_7T :fFq+/d:g}b1%?D 5axղ ^,vvS(5ǮJ7dI pIQC]8D65`]9[l. 4:8%C[20 ,s-6/ R 2(ujcvZ AxZkD+Ƅ2(yb-(N)gd$qyc."Xjatv;\}5HyE Ww22.|Cm<Uq2q#+,7 哢nvH~e0]1@3 6RRM ce@XѱM `9N fɉv%iDtEJ JpK8ܬ=aA)!GBV=>ETVC뾙Xxͬ9IC݃f[C䕴1l7S~nތNcIVh5}oEVFÕR_s2bӌ)]3h~?#Ulъ[ _<@OLBqzLR2ՏQ|jY448E\SLhv5t1€wkWWrL.ޔR'P*rrlڦxijaBLs7DA멳h;>%_ JEf+`M @B(hl˥=\ )L|D *pMc)=^ܥ`kBݭH R,*40MSf0B  ,3uS(mU Ą SM rU5) n94dR!HЅD8@@]h 9B*;^VE| {ㄅ[L4'hv=r< 9goՎFcf{9> l _X^F> pUtxxȡo@A, =w8`U/+lRz# ͊ "' N+ZTd4A*4bY19 œ{UuЉ3(@0ZV~|K@9gtػ& 0VBQ_9RT{ YG{ D*uC"T TiЭyB9-O|>[b>9Ǻoa\2J#Q *S,_l95}n@r9dC@Hfŧ7o؜7G9Elڮc\NvCl8;FzycHjz.gEW.1bu\8⎵ V 2@I4`b!Ɗ/?SDiyセv]Ǫ`G_ 创^]taMSwSY=i-8Ufm LRϹj3ϢJ Xqo^lo[5XᇵqNi\+~鵕Tuh?6Ozesxm&q=i!鰣ci?ۖYړC5Ǟsn3:a73|vem?F`7zͭ5>|=k1]R].G1킀dU^8Y^ Z/h?ri +u4pq5;ϝ%L۶ M[ :g|sfoݯt>0:fw@nu3Uc ~17Y Ļc=]ax|PYi$K%w PWcPJ*`=FR[iKFd.ޅtz 4**Xc9!Oֆ4_I&h hbD*njxr;?FHyo]{˿aC\xS]d"[i⢆ARA\e8|7"8 ّd&Z!aq(rx)u?ԚНHcggs$/fVKXҢ8|S˓6۶Ih_UV҇cRxNÜs !J\!#΅?wVknxB<#Ő.yz(TTllPP#U ~&TK x)%0 PLZoAH p% J|* @ITWX mJA]&1_'R\W,)S0aǃ_̥ 8޵XH*6 +<! AdAXX{?}2,}Vp+-gߖ^+m:/ 7zjυa6:\mM%Hj:61oZ^1>JmF ٷt7`Mb[W8}m9d`;KB9~f?GX4ӂ' V_.Vonmpwb\_7dDŽF>\eU9҅k5bAFJjw'՟!I ,|!t>zR̄=$eA8?O6t2.fbM2YiVha~~S\@k\{ K*T i4~yL׎5iX}t{8g*`D8ro~f%-e+&DY=CQVpiڕGTlφ}na=b\_+Sm) 4!)&ҿ7m8en:cY#0FZ6⳽ˇvD$ s::]]z;Mkuؒtѭ Ň1 }Hm?B+~z1JKi7i| U +QyEݓͷhm#M8߈a %#r_exAu:m8k3XB^jn<4 ;$|]YtpGӷX \.-6;.B9s8|LOcY]F)m~G ]$NF7Rς6K}D;v0Iq.P:.=CWΊ'$ u,1R,kwqbb!T1PQ"(*HHѣ&-ӘexSMD@XUmp,hNBۏ||DG]dg{@]Z$F񕰶mklvR1Vm5BƁ;zq FϊNgaP3hFϧr\h/ez͔2nFa9! Ats>1oI͟lHhGԨq.I!ųDT&A$-ʘfLAZODc:xSK5PkԓbԸmx=Z&yή3{n( #ҁy*Ǫ2ɱ }ؾY=q,/T8(R* M( څp *7VG[{N^NͫӟT;_,-=w[ճ=Iіt #X2`2w˶F+Q둣 *a0MzcO{5}úY7& sK,\.spO~g|j/ɗ;ol%QG%Q{#sQw5LI5~qMaֲHC 5$m!}]iVЈ {$3c7 ԺBUM!`&(ֽ1q+X^+GBL-Ӑ 3֕ʹ:1 f-mf9[clq2d 72YTn{ jn$ @ %~YvbI7'&_5p[{ L5};mI?HL} \x.xeR 1ck ^"҉F#[05.ɑ u%2@ݔ*G$2ӌ0ޗdXCހ~wSӿ(E\[ӹݡJ5yaptxYj2u݆P즨 q{ mS>?`EXL۱^f•hoR eh] +S?0H֔iF"-o2p{VaUtJ 7DFw$z7S @!mѫn]FGRhv$UyJMkVw}Fih3G^ey(eɏɇtvYchܭR6nieb W7I#Xc:#Ն­(^\U'^ޜVэa?K5aAXFHBƑy498Ke'dGa댌DJA1e훻2WdF`Syz(@yj]Uӻ|:]v7 c!v$s,u;u 5U@uFvEڜNƄ(ꕃaZ:4G': (1fa^qqs1m5&V9lҍ<5ٹuvxՍD>2Wv80||eeпkS[5prprS8_ }Bw8rq`\K- s r-0M 1f3[:(_O˘|vzY&F2$ݿ<297Nn7y'v8edg_CtNnjoLrn.pӬ2nNJ˲ +X1)p;N,@%0̻c]!О e<kQU@$$I}KM*)Ҕ=t'k"~( ҔeG$2I2jkw`q_0ُnz̤\:ɬޣԸ>i|*v\3uKĂ`}M L+ ؗ8:ܸgDW9N&?iuɆJX-MDjn=]:jL<h܈ƚx4$LѺS46}] <8g ?LYeUD:&=~e_hy%;$bƭc;"D)8؆@Nдb]DSETq l:yknc*qe2!O3TWaU$*'sm:O4>_dFTUTETGh+PD0Ϳ7Omݦ̾%eQ?Hm #VrD2 )CX^nhفj&ciʌ/!ǘMo|e>FG}7>j老 PPI=я^RA r:@Vհ"딘6P(VRҋ["yoA53"cWmܱDT~+:%h[2e4)BCv*{lָ̹&i-͟9XG41~X.3@uF5$&P?3\L@3J m;pM^}Ic^:r8W(oƓ"h-w_>D+F4Ɖj|cF`M9Bsa "$}:E>d ɟd 㥯tcQǀ)61 N @= +52*V F_ ر".T^3 w6 ues)q/;'WcdSbQ X4>0ɓ#yJ ȣ49_P4`K@=4P0"@ȳEL'hnkja-vVj`E&eBB՜|aiHDm/.V:2c0اKMZ{vu*tܛqS Ny@ G-p# G“Y,H)QYǖk]Ȧ{}=G_cWsc#ufE!b5ZiFb*("M|^An$RABBi.kxΥrIM&E ߌ'-]T j _*@iX{jAUy0rƻa:8MCOv{Bul:lx}=VQD{np JJl7\X;U+>U[$^H FњA|Jcc|ځ#݋[MxhwGYpgES P86@)Zyz4 b_$Z&7C@Y(IK>Sm>F6Cj-kХ"zuf{M(K 1 WmkKۘ;Ѧv`VH5 Y24DKLxN ~Usĺl9zl0LuIƨlB+w72V"`KJ~5& &_5F.z7T|$M#f˾ƒhwxFn oH>tNYvyqa`mjkĂ* cX@s7Q;[:s_o1q8{V[qBL#S.mF`ح\ 0!"ZOu\jxtKѨ'D"/[)vS}?][*<=x]~Mwry] rx:GVjPeo7;<[n naH%SυNp*faWeu+`9s9-KHk\0TOggSB#﹦0Xb**! !#($&{zx|zz'!&" '##z}u|M&%Odf{p%'8!054Mȣ(ۺXqgmhUE],MUWQw]ypϏ.\һ6m%IDՄ/ĞVF`Δh ʭMY7TSUe_lY31Hw*EگELl<=8b:'Ssي6؎,Oe/ 'w6<_XGǩ{V/lsc\UQUU &$ӇwQgQKXŏH[ү\E@HLq '# DL 046LB\FF=K2ցo^rΡE%f E$ @?QjPs&nx *Ѐ K6BHYt>^rt'P-Av.!a F4Q$"YLZ:ȨDeK +z/^tO@[! Vg@MR ۠1 HaKx 8@6s>ԧ5*bv@j@VJD1%DŽwvVv8yb1G-պ%MX6 uUO0 PnY7h'O5QT7.1)`&NZks'XtV`DWch㏽~Bg[h i]+ pwN,.2|vpQ PY,,h A.uq,&-hܭ#2>@]`Ziʱrt-M9`<JہfpО.tAn p +duz)ˍ WR=)X71m;ˈ?9UC<*YƮaJXKq:6^ŸPz_ƀvqEhuO-%kz 1ߥK40%n1H HR# $RK'DD+ wѬѴ jDLȎɽ^M | &w =We:.fOxWq.~ >B\d{A8RM$ ˧d}s?_W^-[p/v8Q$ ֤Cm-:BlfJPqRgn1:N}l~2eW3dlݏ1Ls'܅Uஊ;Pم.&EakL-E$%LPj# maM :bDm+P_ՓA4Pͭ*@4Lb^7C>q3rX}Ff2g`8gŽ_osX1hv**՘BJ*Ʉ;~zlvHY@esL=L01;= ZɹF#pd7eh»a;RV <]ouC@g55Ƞbn2'H%Ch[1eNkKfa8m5~t+0G8 `y%U^<.TD*y..6Flk.K!^ ϳ3VE:;]2[6? !8Q΀ 40@ {Q D;P]`1 -9asR?[o{t$7s;r82*z%p!ECRU֧mx CyTYc9ajҦ-c?YY8E*0`EdmCq))PF>wjc?3 K d26. 7[h@ }LP2hX./qLtoQMkx_)=l/]]]fZ7R &e- sGvv<z0I".N/KMWrx*e; W 5F9$G5#)q,L %yJ r>x"""  7 ӘɣSow=ӝv4Aȍ\Ht$*k wÍaXALKފ,MWO %& !< ^<=iiȶ0\ U-d\[i]<%^& "qPC]TdDc:>ư|艅+L̮y^ѨvQ#4"Ýf"~0D@!@IU>FF_qHM4L=6ǰ('EX0+^٬]ME6~Q=wXvuR8~=%l1V 'b-N/l#XgG?h|ÏSOE+ UcU*Gۦ0l߭ aBn@ta0DZ GkD)Ӛ"uD ;L+m b8Bq,[)8 ^j;va2 #>TXځ}듽`ʒ]!wb G !^7 DՄ;Դ#=8K(u(LS]=\S=yu[s=\kDUQ-1͵ق$vm#/2Nzu\]QPӢk\f] 8S)'{7vDzi nڗ4 1L#S]r;"x$@k%ZTOcB Iy:SG曱փFaخ\iX&v.UYaWH PAp'!el~v>G2 `EJDWR[f+ϱ6LcYjQ&bbPw@}I~}^{pPS; *~e4V\äX$kh ǹ>[0kۈhɝ`, IͱȮpdqJ=ۗlL\U$`qjw[M7e:6pisU\P^2,. @L~\v_\6gnTB<$"fscS{YZ, h1( 0N@3 't (ʅ]@'1ؽV k~L#ÒdM MrqL.SYmgr-edߕpahQ-lOVV#$ɓ,wY橧סf-tn @* p+ P &@;`l&($ֺ܎j?*P(w~KYg5u"ZK6BD?DXhp¼xi~x'sS+hQdC|t9Nef;$^v;U^hive1j^#~.50Pz"JODKv"1@Ӎvv Xe z@xSL0%Jwe( vV<[&0 DH 2(B@HX1$Uju}eͣe^ַXlnUFq_KZ[XbI ѕM$>;26C tcU ]+3鷒i`\01AhC0An$e 03H[|l^* JȂ5&U:8R1Tx ZC@aA \:F4։Cp5߫^(śn؅Z?3$5,x xvKpO@Isd ސD&| Lܛ#)(Ҁ-shxZ{atkV$6cH}F.H7FBR>+PSGa(ɴN{?^L!>ܞXx_tΡ (^֪A&m$AE?h:N]2dh ,JV\lrRKV98zM(Z>.Vd߭B ֢vTKH D)yGqxeQEE&<\J*ak9M<YOϒ\ڽз۷gȗzڠ.) inE]D@ahCxmG y|Qb8=޿cswm[R3j[ENQr 0MDQ\ ?8NjrcV n"lJ64Uã*9^Izi!tB6zUEЦS.A ;z J.Cy_w~{hEa0>SZm WWZZ]5jUHmi ,@XY+UzJ\ {^[]&F̸-c$kv. @ RD~Nw Ԍ 4clcpS x < .U5 4pIxa:RTFK. Sj|d-ؽAHR%x[W8CA$ҥ@"S.NMNZv h@㸸 G ym,@ ؂(ͫ+ >n0>K@%1WBgudu_*7untS <$J="rb!s6)~@$ #d]AlǠI"|І{sr*iV `@>KFPhY(1jjˏ E)Ӟ p ġP"%$4u2Q1t0N9pR(Ud7 El@!%f @*dE(y7H aDHHK@vUȈ:hc ! dDKO(W*H ڀ3MTFvůǞb+vK( X= np'FJb>MPAi-^,/V=݂kxŇ 5sX[qR4H 0 F#"9Ղ&lnW|9oxD]d [U= UzhWdE֦H CC">!%D xvKc'?Xƴ›uO)"!aH(.;q4|7+sՅ=nKT$$VGS)T_@T7#kљܺB$JB440o KЖ;VQ?(BQXk>/o"+<}B"B D9sRln]Z>,=YKGbs]_,npپ@ߞ@zbaCgb%)gTL0"H!YBD \hs őeFWu+6|s&_3]/33v]AR' 9Ӫ\x8 RT徵W9ƞް`#WC>TU/D'ۑ{\}P|ނL`mմЋF "DxS799\JH`]V/2]^x^ ے?%DW Zkȑ?:޷'n{2WL]SWF+XH2]GjTԢ:fS'Qmp#e L~ Yyfm_Ko7VDt O͒ΕoѢQ6t˳vjvy4= @.I spG$Np_Ds7X5x~h3R|J@b`dX lSqC'#n]6z*'Xvg~$"#;?XS[:na8OZ/;9x`Hac @=jdPAT76XH\p 1BOggS($﹦0Z vq|{uywqzw}& ^]{ꄓ:5e1d۬9 G$JRH w`~zl+͡E@r<4 &@@(B 5227U."<C7[7TLꡩB `_FSLDi~lI,Mip=Ur/\3з>,;4(n<@B hZE-\W5^<,B蠩}%aYSKi ,>]<'JD$rS1fO E)_q ]` ++H@˃CSK?Rmkֈ*S"ZH]^ @E`DkwnGOk޲arw+^ߔDKğhLfbٰhWOi>|Cy@—He3 x "-p`i{*5\bb F@!2k.\-3!J=Z7>1 (Hb0md`NF_ ˳P| r GX`~W"-NE0 ˖ 8r ]Fpkmm O٫ ߖ)"J@54#OFXP̡DLDHDWADVG1ҹx (U ,^,U4q}(`b5x A>|B#]aKdYXߺD!QLfӠM22rم>?{8AdhA-AG?`5%`Ց 9/uQQw%#P^(MGJ(z2DTӨ( ͱen,/7M 4[#> 6`$=OBH [څȓ %xBl;PSڍZgStfѲ@$$NdsEbp( #9a0^ߋifA NQ> Dw,քYzTarD~\jB`Il-UH}HvHDD!d01UF'3hF,>Fu23 *H2%X7ҁ H VP4 "qq#\-@نLKlSӺQ #R",U٥iYehDn&HVŊHPN (`"f "is#ׁRK4BX(l D߰c&5gbQk%1H<"%gBSxL>oW@1p'P@T>QF"LJ6PFc0RLS&~qZ(9ݖR<"Q+@6FTx@*XTP'U#,*Jb@HVqE2.t+F4]Uq*ȁV].Ȋ eJ!om2 ~vT@j(`p(|* ̢U>Rd4xu +1>ť`^F"l\nۓA&!)A9+s>G"BfӊKO5!6~ [v <1%#@\ c'vȂ\UA>gF!VY+ҀVD^ǖDu"]+cX=dm6,n3a>~ωmĻ(b\!W;n0\] BxT:XDvՐ~KG _TŐP)W(G(qܘea (˕SD@ƩnF@ nT$NL1nyqZ>t9ణ{-= @/ w_2{ *I"0T߰dp^:"GcQ,.H!^ErD4 4an6AҒR^8.%0%i N+Y2F Σ| Nc%u2*0`WlrܑWf3KJx> 1~b5#gîZJD 2^EmR/ih^vU]Lvq[ӑe1.[$cɦ)TPX4I&*6KwVhv{+gRSm %8룡6Ts'gr齻7:Z[RBy u0BY 1 ^6X' $]:ԣFqG:ѹ>߄VVPB%:[j1U ` "@"RO۠W!xT`ԨN&~ Cyvגo冗ugjhoLwޮגjDrH֊eeܘ. 5Q DA~N)R BbShHoHHˀY 3d*M2bb tʪ8^P. t0?OܠDЗ/> c'~hޡ̆Ҷ˷=VzQY6c)w F4Һ ;2JX4O@=N?H䜓]k\`lq:`yD -4E\D'ƀXlOV1*GsQ9ה748KSʴcEQ [zcU;zB/hsXwT*ںppnd #Le-ҫYbapa9L,i dDx 'Oԅh+/tOP'ŝ~ 1)#|;am?=Ÿudc- 2TFn X^{\eJ:; /NqzOM]G!u_WVCs:CڞW\WV5{( ^+&]VPh p͕bO \@L67+'oNM L5IAURUAn P`J$l bcS;õr|qAxYf;dYqTuDW+ֽePDbK2]NcV1aX7*KSfeTܾ:Q׏Ar9@O $$ @Y=! NECO(AnӃu_Q籧O.ҾlPZQu8v_  ⭰>ۥC1z-mפ'H?p\.00TJqIHC9 H;Qq> '8 /Q%VS68+_; V`h!@hj!ch(4GhbC"VnuitKl3B${"KNo.UH9y_1y@w1 vM5 ;s'/SG6]<[S-WD ~.O cg) 0AET ]V@p iHI[ ANu݌T0Z;nn*7—+6BvE8*@M; ȀA5 9 g 3,؈= zd0aah-PK`<ۀ X%` Pmx&=S(.^;f̽4_+P!%pBtMiRWiΖdwD4y &7x:S]wDMȒh B4E,ЅF `w$ȣ ."Mc i BK@ 2S;b7"HNG"/@|(i{ \P`DVWvщv̯9%$_pxݠ>*r+q8<]J1ժ7eO~ەq2.vN+zzX}57q:MdI.Q3=2F=:$ޞ4@?E}/@ Q#*5)2\7CP/+jW*q?i_)TwUl!~DUiDFٯ}tSF[fA#ӢJ``@';G<- ߐ Vw#p%@rKɢ:B)E68UԆ؎JJ\Z0 X"^~ 'aQC_m!T"bJPSn4nWIS2SrODDky; m`0v7{TIN툆xF"cm=85nW>y1etR)8BH-ˍ@ /  ~+2P/6 i `D봋VO4&K#y(f1(}bvbYLUi2k.+J'qoZW{o+5@wt+Fh(=q{>OnXN{ CF>c.5V~cXB~^ j b( fnyěJ&`cx_:/&ˢ6ѯ̌zT,+SP9 qYm0eVr e xQDSv L-uRjbRd eO*L{-+nnsV_E^+BܫelG fzAVzDw QFF~ . #/)ƉF2X#6j5eFִ=4cYIC%EZG# z;; 4u >*P 0m^pj҄K =[YuVn70-qXu>I0XQN%NQJa QFla:3۩Q.}t;wUZ9eH% * &y*Ry=츱^XD"p iBʦމxVel@xsY iTU雦9g E{ Q|$+&aLb}>Vz cdP X4,4Ҭt'-e uq'fH&P-"S1<'TwSK ^PIp֣QZ z70+u[n4r' CMtej~lNބpޫv96,S()!!M)J\zݶGcy}4t{E0e)H)n@0(,0QS 0!`B>AB=VpTLWلg"dro2yϢ| ƣXĆ20RA C") t`Z{!T6 c/&=nAUyTl)l  7\D  }xR#"QĤ&+?n4ҖPJ氡iLSf?ټMV=dR:1coG2 26 97^43P0V@`!W@ /<)0vRobdADC.+ҭ__r(&垨Fzh5 z05k]FDĵafYW:pa24n~evmءks[Hq`w81ޯi'<Zx7ok6"^x27q[JfEwʟ31>H (h1Z~ZWnMop>B8f1"H/#v5GjNMvi3XΒ,씐,v"Pf~V[J?"M.7TZKS R'/egXUfvK 'R8YE'.@M $VnP?|np׋r7QbL$j $rPZԁ\B^ZbLōե 6sd 0>m=JV9ְXZgP`K2u:},.*@:gۤN^S0_!<(njX%bs%RzU8$5&{[:q;#p o3_W)!к aR?=tNs "sddH<Ɋ]B-8(> @5Hkh:,?7NGwm&A(f痩1;)?[t:\k`@9xIuxX<H g1(~ ƾtw\gWJM\On'GO>0_aK2r"Y/JN%TX@[ƥZŀN걆R,le<I$ʄPf=m>Yf-+-7qt1]a=wa (¹01Ȝ+Zu$ܯ%Y(Ls:]%c=H!g4tf bg 4d鴷^4;ݪ?[! xbv d+anrlVmי}psGݰ+++KL`WiSJ~wZzˍe9a0y-.\OQRP] F{^`awwcmYULgjхBzEÓ! 4Fʯ;iBt9^], ̾7cxrs?URWz,|+]ө&H* cm겟R:?e,vkX]l4Z?o"'8CYӿ<=>:=֚lvq} N),!Vz1X+2tP%ZD*@@@s FmnwĪFbS{C jy+Ɏ(8gUC)K"e`kF_OggS$﹦0\[(,&%& ! #!')&""##!$$#niqqLx*6MX+ww3n{_3Y\$+DJR[x²o7淙`Txj,q` @s_u12톄Li4Z}^ $=@. k٪]n,L⚌EF>PG0*OB]# ą2l 2M 6z^3248?4/!cK3ճ&u9t3 r/]FtFtBr5@\f7حQDƒ4X$j"AHZE5`clnї9P4(Ѥ1<7RdtQgW7F"Κ7;@@ )Rhh׈a] .⩝I`5ڥ 7ފ?8 HB̆f(\NA X>U2 CjdMO&䲲HR4l3槜a= EK sbzQm2ar8q8Jo糈'H?Vp܂ l;cFW {w긪D#V?JXs9IoJ=O{|+g{Hv;t/c##c W{'v<. ZJB3XcwE {s[U.5Wb E] 1F".$K*&Od*f]|v@0!j9m}PP,K5IrVx0Ξwm8(K$Kʓfr͛L݃]՚B(,ω#>Mòr8OɉnrW&ڇ+DfzsYw*\nhbjS*џ<ט'{6^ɍ6wK$bJfTrz=qv6S^MڷӔDUKJ]9v`p4~ۑ󎇶#7N `8PfjO/+ʈ֏Ȉ|YQ1B%EMy ENٛ7[p)ή fx]m[U-苮yfh/xH|bE)*Hk8]czCH]-^4c2|nD`0+˴ʰZg-~% -L @ˠԫ#}{cmnas۳~N06 ANO%U_}i:PF͎K7-f.M XBM L;j89c|t{\cHW3;SS) .^ PD; huiVeQa 蒛ihCTM x6(X``ApR @ /P 2H&l䏈Xjb^`CC? bkT5G\8^m&H F.( ~ |HI k/WE|61(.1jl]`%q6C)&w GH&kܸaD'EmY?H-ɢè`6;C#RRCi :GżҢ( |BԱ묨R?V 1eguqZcW^}=tݶVb2є)u>ZgC3-m<=IT9S넃rf)xܰ,)J BeaM_2MJ)~تH{AK ?t>D)SC@0cl7WSCwwDl^4U@.eBߛ Q+\; ǘ$)7vUCS<,s@;wqiy+NnԪ* O !ܰ sZ,>Ua0fv3V꧁  DkΕj\zםYi44em),ٺen]R{ɒkl7Wn.oYYn1-^(@2"Og0HƧɥ#[Q=c>7o2vZbRd_Y LX /cfVOcy=T gKG4ZkS |s&\R23=vo͛WpM"|6cs;(#A5%5|XYiBe T䰯X2n]BE .qLΔմ.;<Vi_ Iد8 @<8j[ l_Vx}cX&(f7TYYն뚧ʆ]!ڷe[L.d]@YW5 <[_WJ)iU#XZcٲpjbX#A+NaI +r ҧ(clF^|1y.EWXHj-hʂ p#a,mMPpnl`i-V!1?NH`%H*+~l)FVsY*A€i4u G"J)bl:4tpK#F_Mv) 2`P@3T6 p $*"P};^Ms=y䲖dBf{e-,BȏHiʄQI.r@s 6^+6)`K><I$j!B q  +zė,vC0Hvs R(-(t)Zc%ʧ_ShO9  D>,H@dkPJ,F Ssq$X^-UbPta6nR@W@ &Ba9,ĸn{}G"9 #t 6> q*7JEv“.w#J"2OggSg%﹦0]ϲ#~~$""#!$'(#%^LֵtYk%yBMY vrӟP 1!B=3q' $hDj& 9NLd?e@h78b0>b5<(K~ޔJX,cjU2z)Q"y!{MCw _qCz[SbD] 'PUDDIʽd| | B}*+7+Ů9aam2m[F&0oO;:+?h ]X}H J\i'7Ipmxy=~== *## N@@dD- $ id*Rt}G.ZĺE8B.,% %1TU(h%N5(9P7uzLQMd{xWP[<-UgZPf!/DQAМv3}VgJ8tpB+7}F4T,O?gjx[P$ܷ =$ ,q@㓹 hno$ H!r;"k~t:WZJjL@\R1j *%պ`Zk !S얗),=~fBhk@VкP?"Edp;E5I5KTjpN)L ܔ^fOqt߈Ė6|➵Cl2L1nh(ώ#U"A%7.$1+#~&I"R |rٟޑ]6_2qфGq=&[CT' T8C/z,aȢgip`+K\aws@j+cx5nKkɋE뜹FͳK60wXW(W.^&A/4es:DdeI}u>aX?i+%#@E㠤H̗ U@a2eV7T82TIIOP%tbIUeVqX*"\Dv>-A0pإc.08X& BJNr#3Kf8gAǹvmN 4@@n9%w@ƇB-\՛J+^e/7$Q_$VIMcE1DK?*ތNe4@3]Ҹ(4r#7e3i,/l#TԻmt8lEQ|1&%Qli? U8mW|ܣtBd+SC' I4>!M]ҪzyxxYѳ뼄Tøތc#e$ӾIa b^93PTL]25ltc{SyhHg'N4 VWa x.ܯ9DhJK aL}LOd,ܝlfc/|qO" n>pWӮv(\%vH \/W@|Np ?ѣ]4<-/:7BD[v pJk2!J %Y(q 7ufٲ"SjY܌;xjvQ{1t(T^L. 7\Z*Bl@0j% a3\ytj鞙%SuIz[ZGz @R3hP]&((`@rcBc r h ;.B@ Tn,N!B є*Ld<-sL((Z6XN`ק{{O9;/6 Wpz+^Doa#HE4﹁Vps(nE`U,x6_Hz%2Kf: g(R6u%δcr- 7(ECEd <HZvUXY9J`4̬{ɺZJ6J19'u+(ӻn!=%%+ƢT A#m.YX2c .MŹ+1XYjtlQ@W3/Nj* j)N KԂZYcZ>%6LH<Ze7j.($&Ze:w~CA); E-!;|3b 6YbUv(~]PzP4E8$U1Y+hoʝLcEI|hVK5;v)@ - pi %R٧E>cW9}⧐ṌXn& /wsx%(.>뱩s_G e~G UqӖ#Z`GJz2WlY@6vJ۪I>wڲ[LDIG-u%\c'!}c~qmpT0VfK8b#,A.0@x~K7 ,%Wk2BQ^`S""#qڟ'A}5u¼Зآ#g d HH*tύ:b-7Kz6#^閒"g`N >+ؗ"B@kǐ ?  SLMQ&I ,3fD/$1/L~}~ewiMgCs6~7'"%cvӇsjNǚLW+QUQƝފ{L^Kuq0<X !&з&m4ۄ :FĄ6:DSs%<RAE<-jm%wIOQJ- @\xm"k#p%O lnh"wFLJ XeK1>~C@ۮ  Պ eãlZ<&;Li3 ry 6OG[6+IFN 7Y503:P%C\+@ %O1py-5$jVF$%S\!H{խ;.M PqqsNf %vJGL$NƖ>]>ޛn=ܬIku;0@EC@(5h;(*Ie^K )XDZ,4V+<#˲PA˭iܑ 3r.U@Mȑ}OȦ逋Ca!lBDc L 88ptekcpök>Y'Uȉ0jBQr60w&! EF]7ҵ ^N~ ~cu{2ӡy'$ KeÀfy]ec2,ٴp&2o8$ctR!bU]a u$#[c-4sΑc7IYC% @o{N)%u`RpN1AP0J&DB D`6~1ir}ڙc $hy/̶(EzGĸm\pXɰ>d9aU N|h5eV+B +Kxm0=ᕼ_޴e[^ ; ΂E7}X8olJ|&Jsw]B <`0O=Eb l@` 7@f(6P*)!@$۳XMˆq ԧ3"F7-P *&t>YѫcW2iZ.R,?fdJE(L>y/N#I IsphržT.VEt0xEP"N8 Vźԑ$Pa=bS "~Do 89ՏmHp{tâh.(z,<#/T H'h\AI&V1z^C:Knvm_ :Q]X'!D<ӘQ\}ϖ}3Rk_Wu<tOvT:tBQIғ:2̹W4gϞcPo= DGԴ,͂_._ 1(A ÛDՎ9v+^پ | A6&DDهkUl3{NsZec̗7T^mo &TCڒ;aTdzʷ_|\]#]WwxG〨NvWgߛN2OggS@F&﹦0_ R@,$$s|||#$% " ($!!!"#$#(&|rwte]9Ykr( S;N,vA0^S1dpG""AŁU2~}9oSKyoeQ*@le!?Bw\!tmrڥvg*)|q؏5>&]fAi6P%_]*%O%;t>NΗ1$F|w   b gLtý@@ $LAJrQ9f\qmīpQDb@>;f43Bp oByu&)GW\i+8FiL peiJ2gFئy 4r>y;8r/Yg2\2f~U@$(! u^hǽ Jax2IR 2:-5|ht*jȝ!뮘 ~Lf1H:rt:!-2"=F|OE}{(@ 0Ce7M밋>#@E[¦R5ݰEPjj]=]iK`4 FKh|fk!Ch=4R2 lPJ]SO˯ö4I/5OX[rG+UG@~%QAe#bP+FZw`dbGɲPI<`D bk,Y Vb[y)*ż0-uoͳu.^p|SJD%vIbVE6*˵8Ex^$]RmD588\z@'w>bPWn!+HJqL~=/ \\e4 eH^),ղuz<<l FѠy??k=.jckB'ҡ5W\?ev,skDY}uu{Xjz7:Km46R  EIMx.f)zT,1W Ju}kSg{ 8RΏߌ~ v})G H Aŏ 5v1< U#d Htѹ@0%>}H&78uw#3N#1HૻhXK뫗BE"R:kQG" !)e]PI+j1%Lᶋ/++^.+=-^L^0l!V>m- SC) [Zx'X)fsv:G3MYBnRA@r$[b( >6Y~ ^h'U5xsJ;8 e@ݦD PS8 KMٔ=%§(wSaXC(p88lK=wV*>Ihj?^We @ ]U0k>Vb `dz rJジkUk@"fG*jK.İ8h1'uoD`sC 6ha.l2O_g7G,_\0-2i]'$9,lu$)Ǝ3(@^2 +cX7ηaK>XL,>5B;`Ԗ \F]CҼ+&I;&;":E.mF.d }@/֥۟)ķXmK<N2pZO8H$)d*@jA{ZI8"(sx1ngΰj0*w.~K,r3X7ESpHb0= (S*.1 ԗ=LD k-%V ޗVC3@yц51/f@kZ5ơ '` @@uJu, e,~.>Fڿ+>%BpIh x.(ּz#Yi-Q86^┏CO I@!tZؑЮ>2bXlSR:?FΟPN-[_}9\`QSȭ Ҳzٱqɕɤ^e$C`6LS A'a |ˮuU) nXCwCxAۨ?r =^^چe2̣ˡp!jܱ{r٭u*+:<=VXҕ XԻ*VLdž6 c)64@L8gа_hޏh#?4~a0= %2\k<*D`n Y uku?+n=|xp,]{Z (i Jᓧ;|/IvE"-s0Z8x,YG) @JnC|HUP2E*h-wD\gC+Q, OggS&﹦0` $~"""$" &';ڬUbmi?\ΝI~|>(s\ H)6 ^{KE}<@[_ew h9g' %$KC  P  V} F()p$Pu/ ;F.~oBwHmY֍-v-%I6NTD)o?9{_ONcrz4PMC یcf@9ݴ@cn&JA*>R,*YVJiw pjNʱ n+u_(5UrD6FZn Ǻ:}vݨc R2:%:V*?U֕q fcp؎/xM50@5+2 gPi \aB!$EU"dC{F#B7ʜ@퉪;Ʊ 7+&)C|^cܑ+ɟ~JbQwla M i/ b.J_A | MėuEi;xYDL3QIA|PF&>,N   > 9J+L%O{.;}0qߖab|"s_! !QBMhS!~Р hn NoSq}ӡh73s1(սB|'*yG:N鼠ǎ1=Fua9Ե>,ҳr0kjP4$^$Äcђbi!_5hwP!6;h$)(^h-t A!?DUSinϝ I >Jɍ YnR2&.4=W7pCf)h&CD@.͢5ǩlfu2{{'Lh"nODc]Ip!A@}zBIq&co X7@gs'1z/Jo^Ɓh)y aiEZFHG!,et.W:NDyz KpS K`V9^\vuO~9uI,gúqn4a x%e$i< 2,n\NS<aYya@ĝ`KHD8ʝI;fo$.csiX4b߅ bdjЀa!hL+p~+?|߽U};ne&u1[ DDg ̉2"tv[PE2# %J n$<6Fd$Y2Nm B[(f#ߥrS5~qfп 41.Mq@Jm5p5`3D@$zpX )Bܬ @ $/TRsTp7o]~+fL&P+hg>)JZuaB  B0@arQNgeyx9a#m! `3 4Hq |$\9D VR_jv.ZxDD +ҥJ8h_$p "  0C 7aPFnڃ7!T֨ρq\Kȫ : W`@P0܀,$DihI`*.!YR~;fRDO`8hO#tAK\*F6`CAq$(P0 /bї;;XWLgՂZ<H{~h0_\.t3Hk3*O U` nXhvlDX9 1TPY'HsØQNv! Rț|Tɗtݡ]4p\u=2qWt(Bw.?vJG#=3y!ABn@H:(q=8enX)sqs)j¯+'tIK_ $i8|V=~B^L. "޹]駁BP9#nhWɠǏfc/xz1#ҝ7rcV.vY<Pݿkm C"$u/D-U|bn;ʕ}r06vC;t1<73=$f)Nn Ku4~B eb\څawLIK6g:~ojxrO6ls^Ś85yʟ^7W;79?*=RFA.7m4&t qZd]gݻFoeXCsZ)͆}9Lkhlq@"IP+}Dibf .<,Jo<"i&28q DU$fPD|j* S)O ?{-u.<cYʜXiGb7z`J4z95IDYk)X h}9IŞxJ&by8:^D˄xUO l8Hɻ Km5 N"0W Zɱ/YPqT0TnچM¬%^Q]*wZWYZAfG Ț?#lȭu2 DZh +"KƣXZwV [iXLvO& gI(C†ϋM- Ih",'h~K=/O[~p ^n (.|DFH3 "C8JIQ繠 G#!I1Aa#VJ;oEbWLS&І V6pAa?p-y`lх*vg$f }CTM &HCK":R+ + |n %&"F ROggS''﹦0a˳[,{~{"""!%!%&%z||~& #&#)&&e0 ?ZpƂ5Ӯt"ƶ;8dfh?1^̝:Q5_2'jt1 `R}2!_Q)" 3z6y')'ΌjfqRj% O!*PJETu2,^f(O!KQZɀ+Aʁpùfݓ \C)R|}|؜6U Wg)y̨p: dĴ(ԼOA\ 4 .x ȃx W ;N'QG3#9Z2"Bօi|0_exwn?/ 2hxDhy $8+\2yTSDl?Hr#LM@c"&adĆ?XY/ 0`h#l^m&Ȅ-੷4a.ҽEwyH]V@n8&ɓZ*FX;6N#^Brm-@" KgG W#܄Ah)&~XGW{l4YvwѪ4/ @rA|9 "lOq(b]n iVB Op4$, .Kv" ?K.qp/& ɀ%c6GMZZ;|`?1W6U)(@>g.&Zvl@xUj"[]7?.hª> TǨ0Vda|^Pp?N*Ȭ^L#^xxmX+lF @^e0VAPWoĉV/orsZqUY˪'4ޒSUKDBJjҗ.^ F2`[Y/abd#e:E|? mSNLJ?gLhl?Nx- ,/FMHJ*@+M@Tp,jc?@e3+/Ђ.Iq$b@? Tض^:.qI3A%YJrHZ$D F!jgЁ}c}q#~}jޓ4@;O'Zt3bIL1cf2/Xw 2p 1dP(w@(`|xu|#n²xx #!$'qчP)`}GDԡv;vS`29,r]o~'D͝ `W"""jXX^F=_O}|\>C -K|j`wI \GqFܛQ㏃68[d>Tܲ[4z1rKb@\CVRXDdf)r>x^jyphaěMʔDў41crLZ _5H4D,Mef=<w:lպ;6[ BX,LӸfs!`tu"ý׽d4b~@o[G4m]:jDOp:رmCUo< 7H  #\%>2L4 nɄ(Pn#XpaTTYtsW8[@x (09@u$wXu@TPMX,i>E EVq݈"  (nWkE~+6E<@7uD00Zݖq=-y _BŐs(ڊA.xA$ !UWk O"1ⓓTʊ} hs4#O@MsY+%bz8-$PG?_"r?u퓇a߮do_yҼGTԫM2-~P>z+` \ "66)bn$O:/DD Y<iApH5}{ VQTZ3_:[bF{@7\ADu= nl|C`SEM4ӂ`_<х}J~ʀ+ r|ֱ`37bMWݢV?;a,ZfqJcK"ڌmMhv˅ >" )-A9 d@\^~Yeg816IlWnR}}N~CU " 1q*a:%QJ#J7K]JU|.f@x=lv¨tX`H!$l_p8[4厛ۻ]c""@rMʊ@P-E@0PbSA.c.qYQ^2|HBh@VӐOggS'﹦0bWZҳaW׫kY4>[NHkUh՘JhDR\^ *gtJi HMu .Ma)3Nk%LgUT,%KbMv)JTH "u3$(VP` @ 7U.nQqsr9>|NN dp w{XfX(8_f/1koDt7O Up2@@a @r{`Ip*,`>$jA `t0hɀh8~LNt"P%tݝd4sziŢL.%3$g:n71l ]g Ӌ`/xlk ~ rpP8Bw)A &3$a%k+^aQ 5|c&̆(zsIN+Ɛa$ K GXj;社D%IkR@Vc`pP` tAQ,7#cp] ""e >K&O։ BX3ĵ+$0s#pLxnn B+C05 $.Pj0}\/9hv857v .KQ9#pmdX:EVD_įp2$ jY  n-uv8Lxq5S=6$mЋՖƲSZ"rX @ӴϏ,Wt Cvr%>5nZ8R*oL+ٕFa딦ьj7VbILㇻDE!\*E, ?R-G:@1sƩr W9=F䇉,tX|*[mV9AZZҴa;Xk5ot#)nQ "]#m}DsEI_TF>7_'u<ht.v8qNs7cћZsPk,,2z9ۅ:BxZzşC| La9R4 =j:VnYݗF;VH2/ I ^] @:M ))a!xc~^GhooMe~Zkt~K2m| ׈E+\ %Y A%X2|^`QjU9j&r<<݌Xte>$ڃXk!JD)Rc Nnn_Nj%#l_T"gұđ5zN2Fx-_cRá8H>CCQy=$RZ-j%5LUR^ *4E, _#3Q?iS nhޜ??Fk"u }( B@F/ǡ ,#z$*f%ubSy{!C 9Ms6N/j<`b -c:Rk5 j^`~h<$DSr˜\nf8=~|Bv3ѐ ıǤ,p8dH7HΈq@}-#Ƨ( naŕ5?&JB.[?a+1Uv*EO$XF ..~%2vC/ |0xfe ?DەA0gʗeBgۍ@z({8"Tm19n;OSap:n #{1o?wEU6\V\zE+}o XuCƓފ:z1v+F$L>?H8,k埞ߞV˫1t?0}R::iIXY7x!>m\8 FVU .3SҊ:D,}UrKePWސ`PRZ^(TEVYj: iwܝ;[g\ᰋ+qyTq =O}uoz+z497YR_!qP@%Ё}.fU`Z.95Zʻ@rpKf^:q0gNZ$(:;%숆cDKdz>\u]Y ;]w  ݯ>@:iE]@,6pg ;VA9]jFR\b05=XßӯujlVBAlJ 5&|&;)6[T~']>륾 ﴨO,=[ͻDw82پ}e94`FAB`JcU. 3BR P2}HxDRʯwJTK:`HׁGR%&.-:ثky JFSJXqdF'|.䰸uMz%/tukn2W΂&m0u]SlWc>D!D(DrVAP#T}씁HEiZI8l3~eo^3bI6,bu8g݋שF·Ås]A()5nhU%r(oA[v CygF77bS뢁QHK;3%aOggS(﹦0c ,& ""!&!((|}~|'#DO3pN3{ꉨIˑ H5DD9$]6Q\+w[)FS<EsFu&vx0K?K͞IZzBu7+,2[2מ$|!),ӂf|_Ck_rbe{䮛BܭZ7,Z?r@NsHͻ7yo~LthG=X,ye5dٞ}/L[Q`p#uvIzJs~=}JjEђ.dX;|`#D$e&Ef_= -,S"*Ŀrz}ꪬ( G#y_j#GdBͮgTjڀr%OI6C{Z,oYo838i^ + e "niŇNz]YDyM/<-FӘ-?vz#֜ ̪qt u<51ŸRFcnoߴt=5t+&# w]5Wj N5A. ռ~ ƒSp$PDPWihiUF :f;b\~y.JX@.#P Ik%P+VYc|H^VI1b zŒB!E*`>E _.$,<Q J]8XϮa&QAT@ tЉq1 ƐoЍ9K!jˡ$qQdb$i- Y!z H;'WB@]=NS"""55wK"N;5KԖP}hTct`L#~Cf{4LO3O4Ýd[#v=vF+)p͡1?VfńR :b, j>0WC䦃 IPYaEA(~S :a2:꧔h3 "ChZ'C5Z<^dZ1}g)zvݾu!& pO$4`杙_Ǐh,1V, LpR(e7TچLUA"[)hK\z9 2cD)s,p*?)HaLi9kh(^F\Wغh|"zc:Cm0C K{E$`"]v2( U%L ȼBUV@!b^ve4&Tw+MCfu]]5Oh7?wBtųofEt.yWUjBh y*V|%EDKPӪ3E),F&KreA DntŊ"FMgfbGa$ȡ^ BmE@sTl%)%{h!s;<vܯ*)!u @] @2D N vw ILC *n$2Lkޡ: C /6e(d5{0׊O㝷[v<<'޸0U.݆9@ = I a Bܰ J9}xK=u0JbhPN% ' qZԸVtqHbt!)jP&AA$1/7XFM3Hֵd.|e2A?p}7&HFu38@@ (OXD7oBXBXa J *,1C &FD!_vҕ"]2|ab)!vNB:t]RF C +ʼPEPDOH}®:APd0# eJ6=tPȈ҃ܯ|*C RqÄ1w;a*>vя@Ș̆z|m@'>:a Ā| 3 _*p3(+pC~6A-*Q^Eԃh/!2/nBm4e:"Ά#ذwze=}d8صD!XחDDwAQ8rG#{dkW!H`~;$ufӀ+ї8ᒒ-cOi *dkc'|֘+sW#ҍd|{zz^<l(7^vRXHSDrP#ֈ %cUXR~ 1^|("f/<8OKz idKjU"2Ĥog_x觮o8r:s*-Pȍ5nuU"-xY+#z~$W]l_o)Kk|ꅢ7ح\d($`4Q'lK=LH ޾%k[L+~]: |] Īſe(訒U#'7ɒ)eDݪ{܅ar[*co L mcD$HPSH9Vd_ IIӭme1{1_JO0%)OJ4`6{nJ4nK|һzܽ+t*nAhTM+'BuG >H{8w.:2+ WD t&п?HuK̮dre.LSeUtdn*EK~1O{͞LWezUМ(6s{=Pڬ,#[ZfX<ֈE4X ikX\+Åz{8 ![gddHN8ydQⱈᛷ-Y_,y}&@EreaA:0.MC@E, /:wځ`~[جPavRgoUHDf&0 `@ rlK# # 'V:xtUDCiF @@X\Y,5 +SXD*%&BD΄ [fTo¨:2ZܽVKL&ɤ %+JJ.6 `d(-z(+0%~%n(FjyYtkNH X0uc .ln/aJHn8*%7턓^XW1ƢWbw!}h:}PُNY4b:mHp & GGR7+"z熥V|2PnXG!VDOggSf(﹦0dt6'$$"!$!%&("  ##y### &&# "("(&$a+t!(b~s>\뛅%c;^5_rrN`a'go`Ոjߵ - $9Lp)55L'x-egߨݎeu?' 횯Q 8kps"be\.Vb4Xa4ׂk?1@a* 2°T4Oegxk[>D$RF%9w 3Sߓ@Uv$KZ3f~?W9gS T$⪛="yTGD֒ըfTvQ ߵ IoL-.$eݓ[SJS4UK7ӑ:M ytE.moJdLW"Ԧ1w'Rz$ ۩* GХ/ $k?Ix*dUAU#T`GMKa9f_d;B?U:+ΟW;1Y3d RyX6F{>n0DD.awĦCK}h4^ugN4|wr+Y0מ Dpy  qєi@8¢I;cکQÍqA")pQR~;&ŪHݎ,z! WZO2>äZpSWvCfW0H|@P QmT~P,5? WA.^3Zy$5"`QD;!q;f>%91:p#cc9GKbq(?aJl͘Wnt+ `@A(:v5"C5 Eɑ1F%HX$P!"^LTیKK a;-Dӳ)3'D.3_Hї&L/%mزHx* )C& #^ 16?7I`QHQnsdɸNp뭊EN5^nVbE~N~ LXiന*ӟHtY]X:8|aU]rf'Oi{ueR=K;4!P]B'CXLB][kIyI*($45C: I ^|6>MPCLhgj`p-'pD3uf "@4d4hyN42*m:j6(A[8H"R].& H7՛Dz>K=e@WpFE(iN^|<;W#fmz4bONQ\'RS ';dI9}geg6~CQ nwGD5HX(_ )nA)j/#! 9vKAƽ08,b$^LD# C0˜KuU("M)44atmd/3]0C /{kD~ɢ@InuH/b0(+jkI+AR `&uR,KhVR0%E%M%aێ_{.V6"Hb"2_nL>r,}ۇoo>m]_&m>@nAD} WX?b&܎ B<"H"Db50 bE-eղQۇ@L@n|>%JhfMܲr^%gzpsfR==pg<x#X8-A-P%GHn*IPO^[RCJ#&-#¹1nL&ORf2?6L`fbLs .s}Jk 91eL'3"s~fN΢ePA4=7ԄT~W&F8Pj@*.`*+:fh ׻Uյu7D5 > &d,&2Ӿ 쓂TU.ʯDDD"h>F1(O''1Ojdډv!LXBcԚ|^j$<á[J {8`ּa]f,Nڱ<:;;}#iR hoA[ȍ( &%?7 ņIb" h]"쨸TD;&O2w]IK6,,ʝ\II1#dT `XXoLIPW(C !T\*X(~'a ރFBRC)QR‰crhhǎk-F;"@pfђ 0P1ܷӛc.G0tK&i1\+qn0')r_RԥPz{W2,$cgJKSJg | l*JDD͆ΛFA[)z},.uTi޽]N A2W'ޡQƬrCʆ,w,jsd٨|:CgYw9T%M+rwT[0hi)!0?UɻlgV 1\s>&z5 ߝOxⰚ?.bE"vL֐!"r +_AX׮ĒD?w>rW*Z\p " Q !B$E: Ȫ~"$RTFnİ!ԀTD{a( "4tew]ǛRjQT1Qv}86rh9J PM1< t@kX6On(n j^i<lsn9/{/w|Uap˕ F ,OYʣ$EX8Ki+[hZ~,\\a!f3ӎS߲t \iXΜvതFT4nVc ە00(F[ `d/ `zlBi$ߙ99E˔WL(C͐ >Ƭb[[ֱZ2lKE]f[_1W~7zzw0~bT9x_! MQ=v%>YHaXu uxLx63YtOL!eڵ.CòWR}gfԆŵVD {w|f)eu2n5T{_c&F[,Ѵ!PpQhOggS(﹦0el .#%##"#+&%×"## $"$"!)ތS,$*=2>, >QTRdafΦ.LIϊK:v X,Y@)2u r QMbx_aYnX]Z徊ۏm5Fi~<{nO(+DEmH54n β^LN=?zq9ք a-QtJ%*Ա(RFΦjN6O;n㙋]MKB5୼@4#|BX$RLX17DiȊ}7 Ո9&q:&UcԱޤނppe٢L3V\P^|.S&VrD{|.sX>_2-a;@QI`0Mm$ҟq>?~1(DahG`D4K$0 CpS?Mz4fqxq~qаk!_N[_$Z,,R^bk|" Bu!ZHFYq5?YJ.-s:E!Yq+a_Hđ`T8uJu/n?{DF]aeVk8x c/ N65ۺ4W )EM`1/7,ך~LcC@@ާ년Cq9˳(&!3̕XdpqOsᵋa!F"  H%]}__g5Я!?: & -;+f}f,ez}RYiqxom&uV;]- ^lֵF߱ZP \ vXj١4 ??GRAEd'G-l5mz4VHz=ܓ&$?CIs}'ɾv^1#vpiROֶz^'.&/P.=\Uq!{v;o8ߊuD?: -`>?EB9kW=ǼU<sγ'E%Nv^ õavxYҰPbvu"?Α<[O]a &0_ 2ڠw"9BG DUB|dJsί.993IL[ bֆxNw栖I>*BLѶ.NX2!^" !+e5ќ!&/ǧj*i?w/Vi1ɸ^)9x}N͜jgȬ?ʼn$̞t̶Gw:{Mn7R Mbgx`8֙^n*LҙϚ:KrpK74lZo]>Q ͣCAbIAY V3Md d8QQk!3Ņ-o#fF;NU&`@b `#[ .MPHhg@(G+iܴ";yЌ0;Iuǯ2FA~l5]nXk$E }IUi)I}.HM0 24c0e4/N;O0j9{(S@Y.(/ES4P @ bK $ `S`Tk[eJK]͐hksȻ%E4Vf.{x7M.rd- F& )>E\uIKZ߈gӣXȯfY\AhK/kJK @ @9!+#$>n VaLUY7%+y1U~r0_<\Y^Y vSRNv]0.\Jg-Q"LWUjcjݘ^%QDUĦ$+[9iXZEQLS2*J?~[2Pvb*LSIXե xӱhX݅|2dbdY!bUXl _k$epF5tӣ7JXdcd6(MBԊ0N%'JA(X J nPpd)+OA1}$?MpVUCb}pM[Y-Y (E)] Lw *(HXIPIB} k6P! @m`;yHjA&PpWqS$:)U(`O+3# 7 Fx*- HU@{}H9X XafPVբH͂(2.HD%^LNwUCy*XHz. MLLS"J\ŧYalqF:"|vx\!p L; <>TtTaċ/>qD+{+7!p6KNmXC =YT 2_!2sJy቙L<׊H#QڦiR4 % Sl,C+:IV H{Oaih!.1_opsk4ܕ ſ E"^ UXDYd'S<Kٰ]ϴ'wq֢A\DUT_A) ƒַ=IsY7XmcD۸<AppK|7I}ُ鏏|4[y$҉7a%ys74d8n&mrp0r;}x/2ujd8߈jqES͙edmBȨb5b^|v>]Aą0kwaۈZQ=ADbNM)›uE&:VzOl:6hݕZ'1^Zٍѹ6Y԰9M!],nF@3KDwIQ<~5 #nVa b"^v JSF躓[u"s|lj/;>":(MSCXP`Qp {;w<@1B;/&R;{^P |װeUBU.iAR{g~h[>RЎKXZ-9^GP Ll-g!` N鴨?!?'_PUSw:Lv bj (/ VX|IMT q<*mQı8jǂUHL"IQxOggS@()﹦0f/!%!#"%$!!!'#("! ! )'&~{eڀSEW"FX6[mw'u[5$q,H*$-6 o"Pj#_έ:Py? 2u C#T瘍0)(pǚn_vжb4<Ǭo-q:ߜE'Kpx/޸rf^+fBKD.b6K!RB +b40 NzPvzV Cn˰po~z i:wqT  Hn,+"Ʊ#1MCAˇp7Ub fZb(nHܺ!v КZ04`)ý*Pt @mFݯ*(9W zh@SBt}Ŋk2 ,5B N>-D "ܽF6=t=-F+%AmpGM>7_ǥMUkZwvp7ltv}:e _Bb0>!b  4" :B{ * V8l\I $y{dcl,jd)6U )%zU(&iLq6C/V],A,V ~i;1@ɑS'*X%֧t*YD^f4"2z@!񢌡yPiJ x;D=yQ` 9H+uAk^l>bЀ{l%E:躠h-*Ut`!25i\5gT'؞tz|8}'hqYbi?D+\10+QIQPXj[P~\DBXE\srQ#ߴIA-5?aB%BN%,9T4"ߴ] +0q$ &KI?~0 _teЗS-mE}Ułx!G3HVk6m%Tlkƻ-/p;~E@O/7xN&JDT0d*$o.s( TD猐Z@K64 Uxϐj\"qLnBW/]W!VTwcY#8HA")~aTW w?[se-gde٠,C'6e1ʛGwar}dgAޕ&yvbw]L6.mE]Url0Xu7\^ӝ;@b\HۆR)a.)(qQxYbz--e*BY>XXdcU 6z 50R \aPĔ 0*u\c~$ QwI10r#j Da`X |-^|clrX)nD ]ux4QQilDvͻͅsDd)ʄao %@ `8ɼ6ژb7W*YdwFm@7,5Tsuk=QKR|k8@|}\ <Ӻ)(ZrrF%3,jb:zP,~6}jJn?U` FT &(3$ě{ա&H4"UR6Ԋ & \."kv 1^9H%jp"YʧvDDD!hRr< ϿʻX@~cum^Cc҂nx_X*Ca1aTv1#B1r|R ˢ7 Ot4S".<#@s|R.]yl~fPԥD[MW  2r!cf)G_zCr Zid"$SQ㊾\ܮBK!D4}vPk1$L}%"-%SF\_Ojʾfq`ÝiEN⽓4TelO\!{iԼSs'JfiL9='}5_*Yl4u4  @:Ng\6>I`J/wA58J#SK**$ y\_ݓEEB `5bLSH6@?^j';e5}_(_R8ՓV7CyR5HkI}uPnYe!b],~NdR%.1.A#8i Wӏb0tڢ!甎f5=bs4&+cerW@rIQRWi0`B#w_5/*L*iA[IaQ{>w.QZ[m5HIXհTެnc!VY=KG 7hJ*;hGI{n43͓EKz.NcUD@~2/óAtWhEmT)×}2^/(SD%cmyB!Z,EA/QQB.5/ZK d!P–\U&xti4"ܮ F摆62R J6 }IƸW=j Yّk`sxwI{A)J2]UjEn%ÕpTw] -pI"~I!%.\+Ә\-wݲC:d,βa8jhmu\%אjokNb\jPDҥY} ,  W@BOggS)﹦0g6U7 !$z!!#!"&&$)|!!$#{#%%uXXEn.H(+ iyt3DIo">`mIR}ˆx@ "D( N]Z"?֫L=F롚k0E =\ƫƝZ1)u*ӄ@uoi8G~+wD [1dqN Am!~Oh0\YnNLV2c'!kp@`B0(N'(bcġG>BTJfޔ$: 阐jILiu%|:&>а6̌bi:>1$et8;5kd侌b>𹾿?bR"V'q"!jNE H~% FqOZ XX&Ng8HβΦ;E lA4ɮ>\`oiht8tgKGްY{"tm +ئ72i2X 79Eր5o4GJ,GI(}dûKi"7b~%\X CഫD#)Iv6[\l[oa!A~fZ58LAԈdؾDZKaRFZbSڣgfvةM)ɦ_2ޅyh \fH_ƈjPV,;z@ⵒ N ~QsM&!ő&̦]j$+Gƀw ~蜹VA:'@hh`q $(V ܃YLkZvUL.nJ F!Q<%*pep-ֲ>KWKr` m,P _C ƨuY0@21]c좈Σl ?"ɽH3>`<vPZV@grfASA'E@, \:Ƃ]K Bu, IU qn{nE1,64`( 2tA_PBkn&qyJ1=#~"&d[T$o U^` pJ. /~g XDTWUUUӖy- `k{<@rWZ\iE4UL?Uu ~IdgZ,*@eo"D]b( 2 c~8=yY`(AXQYZ*UG| tݞ6PUPC⪍F}UV2tA >BP07ğ.t4iEIt^,~ËS_2_19Qp/cPժ[])RE ;+$VSnIԂ8 J Oko'<Η{,ne%C9f&~;{hAta9M*K-9/s_.]4$CUS'A+$M5*}pUYlG&b]ؽXi[!x%HyWoq @ltGQшh"GE٥Tkm'5pgݵS,څD)^:&A</!qKRA+џUAPƓ~W] m.4O guƠ!C MHz@)b e`W makdY=hQK4aR*Cc0nCAf&Έ!vX$ )diɨJDtaNU,OG_?&.1*C== j_m1hvG_@aq,_PMNfD0Ǻ6%\ we?ƃ%!/@<ѳa'ĭHi&KWyWuٳϐt,.O&~tZ||;awPW@@`DPQ6kD|(F1U(+y+U= Y^H|Z!.EM ,i. C{@ }y.SHK:{l>uqINqϩn>T_ P2դ!N|:]7=7V77Rf@A~ADNٵ.2XE XUG>^nKLVu DуD|NZс&4/3i _$Nᒱ]IhPŹn0kk"gD%b`!]"í *v15~,m$|> @ cu2IAeA]]rދ+ tm#Ue>lMux>&j Uk d.FUȊBP%0QHN@>%-[OH#{3_A^F!6l6,1uV$ Qo?27%ޮ+l ״*Y"':i%/i0i욭mTeSyk ;# ?iVOLgYBY+3U!J]x1>ҡr"F[_(R,SQ\-R 9Q{UO=j=$$ond$uNF&?Jwm{nrhg7VGx*?9آ76=n5F WȮxiN+ֻ1?]];˸?Vtni ^Ys|.>-j`si 炄Zƪ)h -Xf2Faz<uK9 Zroth6%qAp7X:xW7v:]Sm +n[!d7Fy *DVXEl"#q/ٜ_\(ϳӉhQ fhDTd̗IaZZvlWj0p٥ qpFy\b 1^-L DK>d G*!sMzJl D|<{Ŕ aiUjGeWe H?U 5ppwH*2#`Ii~lNLz@j9u&=!4`W꟦iIt2A? EĢ&Ã\Áe(6dSfQ+ZJPXQZʵ cIDI0 E2\)QDC,>\"^qOZ+J_4nrR UŌN|{:3%"Bחc2cP(-nWO Gev,ZAR?n;?2R$ ʈ@Ĩ*`r-=,SCI,N*eFZ@\uWؕXO)!QWܱq[KUF ` y+ȜnЦ w$j\=~yoTW^,{{P $#"`K *H %c x_Hs*+KNAG=6Ȉ! 6-V< ~S޸~sd B3ykwOBFܼ,1J2¥QBǽOggS@c*﹦0iFv2zx !"&w! !!(%$ ""#%''%v~\52K.JH()]TbJiF2ƢfK* H% 1ȯ{G<6l뗎&c48;:Ʋ*.۟-O(;b ˮYʡ< ޼hM^Ri G"٩]R,8:7n^,G]3}Ysk 6G3kpO Ɗ˷Gu)O$ٖЯ +ƃЛ]1 {DQh=_ఞ|4Elq\Iro22CsrrV3uzVkpA^zߖͧ1P+XӘJd{{wxefGQ{ PE.>AubT00"+K+*~Ѭo,e)7l _8$cqW$VH ұM{^si7b$fS`z>81 4aaDVfIB@XxUm'H\qQG0T67PV(Uå1'ac H0 V:Th:YE;k4>6 ).Y@F¤ǐ`I^teK=rp&V@# >Rݚ_ AIcT`@XH厀A>ۼ @u uc^M]҂@q] (J"JԂY: -= BEyVep/z$2< u@t*ET"aE 2 dri1T } >X1/)Нs *%lmpR?%ȗiy5ٞjn?~4A`Fg> ]U@,6%XVKOc JXAIV0 @H@'pdXDSL r<5KGr+H6ƨˈá]?NiKBuSNsmtfGwp]X,:?%wJ qC]db:鮖iZu& TU]#<@TivݗQݓFzU{".UP !"TCa(EB]|-25kLK?QgCO\.[!ɝZQ,'((0jDɎ@@ Z QI )zƍh+H(J2k=MvͬeQӊ>1Ms_H,rYE,?KDȘ/*V,H\m 5OYDIp 9ъvXDCu>!A2\JeA WT!d]vPzxoqlgVFbL"\T;ω'n:ێf3{ \e=Y}V7~X,_gkj7=ȭdg=YϼBn5_}DoӫvI1݄"`^î::toѿ}0bo* I:j꜔}Kqt|ED-tfӡ3,g#PMkc6Fn}~OUw>=%xQb,~KwX)0I10J7KknNqNc kӡ~O mvc1_]ܶ]?8oF$(f52F'V#ߎћl{hK:;L'C\5<$V2#1 *T$ތXoNZ"0ODDH3 s)YO6lݍ.MeSF犥J$1>y79H;F$22!V@`Zs5P<"b7 aB\N! ? ٵ>PxNGDDIF&9jYDk]Xzezma&b/l yXu7htC}]ʘeԊǀnO1" ]Z)ڃ*U~FYAR<l.|1uH ԛ|6=?ɜ$e˨ M>좠ScI_)bڕ EJf HC=˜3MW)^9Ciq?n殴%(k~皨Kq{yeehFUHhQHoC#~^R\LS4H]|7I](L]EKjH\[1f+ÃL[%"egڕpa 2oDT7] 1>*=:۹#xT_;"ȷ/y°WB#P*S61up&,Y*7W%trPϛҭhQ]T_շrl^ZTpBQȦtigŭL] QWhz=on|<:GZR D[GՓsz|y8 1*\+[L\Q!@M7esFܗq^Y(c"\QI^9 `PMT  &3rbZ <#;. g`#V#Fv]RFo w,8 .XS+Nǂ y?L""mkZqުR33t(ڥݠV ͍J1$cVV/S\Xk~A>D H *VL~!E/]߆oc,K%A9v&-⒓4%"4+YuvqyMQ/;3 twz:E bIǿaSݺΩ٠5$jh`GAkrB̬ua]\TS gݟ>\:"t+pMn)!ATW TUIC ~68ojJAn/LQ*2ƒ>ѳY4S y<.x0~Gv8AW4$Uuέ}@:o',4djhI4SGSLՕ(9TP7AwS%TYQU\s-#fWI@mbǕ?} TcbO֬-;'qE3e$)|l/23)LZgJ, ͑*4AШF]eNH?l8NQ&]U ;n5&^ع̑`iTI6 itIHB,F@*EWo~CҤK/Gͧq:7hπqR;cd8cy*}0uSYHn' 78 _ŗ:c BZ v5^LC 4Щi_Ü+kB!А""ZwKM2>m#\ג4K)c 7b+|+MF 5DO6 x]̡$nʤ% ?)G5VUЪIv*:1LUDSUoA{#5֒ ݔs\UeTB}xhww}`ckHx\JDS T%܇3^ qE0DQ U>1^$Zy;KciTW@橻VOB}{l/7Y dY}{T$ɘyÃC͒roR\[SLۻ׺TZ8hZ0{vHTa/37jcKXLH`UYx \e!ZV yxݎh$m /Ɓ}/']Z9[<!'DGULׇ1Ƅ teuI,t:cfFXnniU불]OOqK#]_Mpng^}{'e,f#EAo!'ds*y8H5[~rP$SAyzu`]`h(֭)\eVm,\OaD=-uq"{seپCI&|OeIφ~okg"aMM`E, ]kw'Z\E2X8#V~5Xcy!`WDŽVS6]=er.n,|^IH4Zv6&p}hKPf2 {%5 ^Wk5]" e**V@Zq7I^1% X@br:I4*ut:g}z|EalL[~^mWM5R]i+$ "ͺjfN:۵B ARG'aXMҥ/&KzfB0 JL8:2nӾWl,jc~z8[O;!C i ,)92!x=\~3cGqud z%l< WPW,h5RiM.bAP vVF E w,[ %hpj~*M#NAR*uiҴfߚ9pdFG*jqHA(@]7PK_ '+QDSD/KS:w0M> X.3Gd XnW_P>˥:RQuxXr\v,.&Iͽ8C"DDDa k_gO~J;qaڰ75?T^N$!U:έԺCN`eJXb~H#1mdTE2Ei@ DQ(*H3<\_ݴ:g0> 4YK?Qy{Jc**!Ԁ_DDij~}\{! +4O/Ց9޽0_٢S0v˜e$MU'OGz8; {]#-VL( QDV,iS6Qm<A£]MxSd?BD]⫮=qܖ S7Sߛ)nD_LC79*NƥXʩ&Bf͒: ÑQGfT@`w#_Z\s9}a|8Ԗ9mKҋL.i'v֕Q&%ɊO9!\'F)i6o'ӧC;{ d݃WOzJ V$ Y$E*Ir,7^XtSOggS@)+﹦0k1$$$%"&&&'|z{z~$ $&)$z{  $!>D7>@χ&iK%?Lh/Rճ͎3 C1|t@m@Rt+pi[} @'d0ocIቾOUFV%Xiwc=ɍhՕJ."^1q0 iJR1;Iki4M)q]HclhSv9$7e俓ޚ:6ٰ%i{  PeeFDMB@ $(+EYҔ pe,`Ze%L_:*PUFP+VKT#lf&FD##BeJJYʌ.ԁ UCdC;܌jՈE$ k;[}hC(}EI7u}JS #WE>X YK(~L.>I_* xn]!P,F\W榩Ls)k1TXggbc3oC:%M!J :f5X_l"2cJT7, OvDJ9*(3 P #7&XՌ]C5!+7E0(e\Q䜫g/BrEшQ|>lx5/"h ua\J{*GmBH8;5YfX3yg}/n~m.s(OmFIE=cuI5"rq*jVS'޳rP>SH7;e*LF|1I 8Y$tJ J+~q1&!Zkw/X٫g}mk) !#*OT^!a $mO, 45L! |I-V=1sA .eKV"}pX2 'g# c,@:JK)uoK~մ}Ц.>`&{P 8 7@AØk@A>IT{ o NF2H݇#-ځ9c1vAmV鷐b ƾ2@@OU0`J!$P!ܓ˓s#.bTJ'ĨЧ/M{4$8o%dؾ IM `8NP@#N1` `j$9rʢ\ȱ^] H%~J  U/ j_xm^>uA%O}- Ұ>,Oh~\iUxk* ,4)Q5re̝9q@z DoϨywT,bji@H6y1ԺbnL*s} =+/#´ND UAQR ?7cC _hAO}RPF2  } r>{+5PLWZt݆\T]̭=  /U]Iz7uL5%TeUQ0'M+D'_A++ų0nۥI2`HQ+eETTs`]s-?b\ĵ]46o<33񁌙c*oDCQ5AvL_K"fI# b-N1_ xu:;Nb)E,tn BIJvn).k[D fi( CP28S$+M'vz4JΟjl.6QCҢa Ŀ_U3rќg%; CPcOCiaXedw3&( %"B|Ԉ iTوM9mq)BĉN9! ˞[ynuScۧ#10P@5D[`2勼8[QsDD$n6-fhL .$uQ@tvD4D N!1xzBaiLMPUegD"r"O&,n 2Sܭ"#;#4W~\13;B]LSHz1j]IiNO0`2|ОB%K34҄H-AtRb$qX 7#u FR\tWҧHRPRRdͩvnK6萚{tH[#?S1A[rE)T[h7wa:]6 [DܞQƂ~A9B$)+}@"F9@bRy >E-0U%&0ZMtP,u 7$ʒq^#LUjSՔ3oS{]u[JƮnr,SUO4H|aī݉j "DY=C6Ãgo}Lx4ܲD1QS;^*бr!^=Rݽ\gє P^c97gճl_h6M]QFz'|i~0Qu~U;%Z6'0z͢tgRIL~XŪ{ Y8 ϯ"X*q0ĂTo K*0bp4"q(U zWA^|G88|g]mnCysA9NXy բʁX#ǞA7 9(~(6hP,P7xG@_C T!5 ,>$HUZ*[--@6u[AC1%.`A.@$d@ 'ac6˛?I4"U L)B.JD#X@(c}M!@&B0s  V[F]hk2 %By t Yڅj/*yIȩ!?QBY)2I83İ)@SQHdkbB~ &Пkŋ:+,Jk!:a)"LYS)~i!PN(BhQۂLS)&`I7V;jsykKDSLu)6j峕AIc0)I+LU UFaƫ?pXQ}uO)VDSL՟3ꪧ?hǚܤ233QaTU҈)&xU,R)٬_ R,cĤl]"ʄ &Y"j?^6(k爫ͼ tgUwfOٚ"i0xTKm5 :<ɱb- ccS_FYF!2. e~J'|4[M^kRYEmcXlH' |UMLϵ2',du! $ ,'jq:H^|:6 J$k5 g,H`!%;єh `::!ǤK2䙔:5@^:A A>"[(@ bxMYJ OggS@+﹦0l26   )&vw "! ! !$#$!#! '(%! !)&'^Lv,REƗ$xw 8W"D^Ռܴh(qZ"{pg}@t@e :h ,=~aYGQJzxsŭW'd  *M k vnHP' PF<ߧëVZDDD0Nd^<[p8?0UeD^ƭt&J|ם,]00  }Xp~XH)h8]"$C0g1%DO9o)ݡbv3M]8DO}@O39+B ,: DS⣩ ?z= īYyC<т5hWxHu_Ka,OBDzD\N (:g$I崃Le %Qi/'r"z7_2?\2OڎA̻X,iP lkU%RW.:U(Қ0*U\YcPCQE,\0D,P{e^"3ҋ-l4&I ^@.yI" ~U%A$ .JsÉ7 ָjy԰6 x 6žBM`n4uBԗnl%hT^Aа I cλ"-rV^E"Bn:HvӦӧS̒ef=QM)`f [uuM9{xWB,6e"牁& ڵiDsc%uK,WdO(} eEIx RXȘwXvsa' --7dA) A44,>E²0|̰e?W@ #<^ tC OMWK&[1DI/cDA@LtwuCH%Ǘ^"M~(о/8(Ñ @~!݁pNSXcXwF4N`:: .h &4{Tn +AMOIiŪ@DO!Z!7-G×\p^ϋj{{[k~DT{f(7@J'(jN:4[ !FHmpl% BÍP(ǜ'gB9R! LWUY젃sۖUB|2yÅ -<<=}~vFKcI1V-`ӺE*0MIGxܡþ6[PtncdK+`*@[KbJik6ٮPB*%i=gݾpׯ3wy^B_B;e$㪬R>uvR]{.B l%r/2,\E_ n0򑷔_ɠVG u >.*Zl >hh@HZGQimluERzIYF]Fؘ|n)ʊ8;ƥAa^R{SI*k'󽞥ɭ o4#d᤹^)S_?"8غ _+ pi,NüǛؐ@r"+ %ar ptW0fԒ#Z25yކjb؊k)o,妀8kVJh,-Ū+\Sê@NTd`vSc8W}6G*VyOF^\" uF_ۺ1:p MwR:G1]ݣZ~ֽ6Hb-UY(CEsz@W?єpը]GڂlN>4Ç!)#Apd W@`(R ?F{ӝku놲l oŧ%}H [Յ4JBTb>\vxI%ol|k#J4RH? e=՟&#X;Qgfڼ c@m1>jYB &Pg"vɥE0 Ti0AKaDmdW s/ڥiCHFCL0RJ.V ȝ~ڋ~tNĢ=%ID{Q{4@!q#X}b|]ܘx7H]TTaEKbPؑ[ald}P)րDQ)fr<M 2Rz. TS9z̺=x }U!)hXDE@kbd !k$OU&O5o=;WyIK%ˉOmƷ/^5pYw$M{?cm TxN3!.t!e;?>\cOw]`'RX5=v%?Tg8X^֬T6N[@~ %c:Lfcd%v'\^z4,RB`C~T[ac8_wZo鴕?m%M<IAl.̗btj^$钴9Vե\LHgnАfݴxæg!{Lu0s*ǹhq/OoxyBf0:F0@eEx OggS@+﹦0m'0}!"!!"*&)Ʌ!" # $&#$"$*$$Ɵ>E,4׮$%tp}H ,Fe|P+}rFlljLvcfBҰ ]Xlͺ66q/PG0'&{ CyEtAQe@Jċ00 #i#|.@]kBK$m$)N,H u[ 9.K3_x5ծΉW%G>XF%PR[At!n4;S5V+.?R$":15K/&D4EL>HG79ʍmùfGsŠ   d* 4fHs!67Y>K  vM$uERDSj.<KXo^"wlSRi`Fc0c |k{^;v,7Naq.&Ժ 7a  S*TZ2=e6m&γa{Ie,G TNvAlA@ b9P$^ =i y@iD%pq ,>KNn@"ג5@- uf&pUE /AB@O訒,ֻ*KV@K0l0a,.TNFa5mm (- p0,:^ͲEW _ǂGJd#~-17ia7P0))ڈDuxeBZJZπma1[-I  L9bh ?n9P]]P@C*b|%= nLSUTN0V=8YuDUUUݗO}4(NQ-DUUE]'coD"#<E|!$>3߀Adr(+%E"=eC ~fGF! $B|s~ 5@*N~o.ù^u gJ)3;Ou %R~JRܑ-JJ{F`c:q_/ 0'(@-xgV+nttԈ[96ʜ7Ƥmժ+}2aoT!@@UGu[* a:SĨY{-zFǂ}TV5.^0 `$3yZ>PĘH]]W3p6f"q6vML PLpAȔQ6Ԣfpq Ҳ:CAՁn_b\=GN=§l6$E\I몙K+]41.^{eҁ4` EF4*"5eO(Xa^Jn6(In^uSa%8*:_?=QN{ƚMa͠!-:}iղxoN._B{<Mw+s;ڶ;)%J:OggSO,﹦0nuz7}#!!"*&%#!$ " "#" #!"*%&!$"#% '(‰{^E҃l\E"d5lNSzK:8~$3]?زeD3% 5o`Հ6a ptZQ2Kak喯eB]&x]\m ^%6˂P# Eb~Œ$!0%cP0sglQF`aQßX<8xg"VP @)bb"(&xsz++hU)IV36 abHtAB\ڃ RSFxa!}G)a۟2ˋr﵆>x FJM?MN IJH-\ SN8.4 $z9X:7N (=JbCD k7?Uے[l o}婠# U$ KZk(2*͕߫В#6+dPj8Kڧy5?þ7EH*fxlKFǔ R"Dddx4nv:Y(wne۱&twt wkj!\u{.QoB-l8[a0ykLGhh |r",L 7u Fcr{¤ɳ򟦆Ѕcю# yv  T݂iᎊ>hXjk {FlT&w!v M%joϽ A\d#p(i,YMɔ 8ʿ\>C>L%Њh Zӏ%t~n()T8 bK0/OT@T}0`%sX;E`CYl[b, cl-\^jkZULUWp`!ٲnX]W w:m\WcDQV%UkJi!fMLJ(Z,\Y-LЎcגaoDImfUTYGЫ͂Ncg "!:)X\WQU!e^+VÛzuL[cVJHk<ϬHE 2,ҍ%U\c}ī,fVY8TJRgͺgӦ2[5Kj`'*Mbq'깛ʂ%(t>Vתۿ跷shnQطrL.*DV w[XXb$EsSw_? A/~[&qJdE2KmS!JK +Dp^&'LѲ2@h8eD4ܪ֓[va:(дv* z* JXDp*Fp`>,Ҁb+ƦYBaF[15 < =(zE2FM14 a*~<%nDtCMy.qH> هlmO t`n >a eO1RUݲ0F-FbjApT;<xF_\DBsqMlUI-s@e47=VHD"zz Ib@`DNJE.L֋AIZ(C~BR#]\.L$RJʚ>^B VCvfKG45+mc\P"",wb}`$KfA/kmp7"IK y̧H⻄{b{s #[傔KÂ嬯_u,o sǸ'XBI!$M˱"^BSpM}-BvuvΑd_W]_H;^!eh3LQY Le2kҽA"*ZMAl/oj:\01YHe/{!׶ZpX1K{i4h^Ri0-Lf$^ݘ痌yt1Ụu'")Z~fׁm~jSM d9r?ۘwY8ӿOp12O.ȝ{E"4>.SM,|ZSPxN++c"a@)Irӗ?{ljfM6˚ 0A`sLNghIN1&c1Yvu>a94 8$cAZIdJ! ׀ޜ6KG xiW*J(֕ĈrIvz.ånEt^<m`j D:-v4@ nI[!VC(:BKêiMBQG<~\hM {dw\*f z,,TiZS-=MS9%xlO#TS,0=ʰD^a $PQ` fA$kSwXQ$&rxRQ^l1-N~LS} #we`QR!86m] ,i6)cy$L%:$ѓe7x\eKYYJV7G*{7\uOlƽE,T 6R\lkQfVVTӄ'Ń %)l..nt8֟7k_~2vnW@'\Wi20^O6 'Mrme.*.x9~1ОSj$ZRk>^|6F:dRU\SJSw{,&~Hî:$QJJ2R&Xbͳ>:ܔLH.1#]nl] RT'Fkg ƘdNy]$G: Yk%9S~l6n4lmh <ġ)=3COD2/#:95hRT-#OWMD;Tw:Vr.(鎗M #xb SdA"Lq*6`vcIͱ vƩ-{oY)(f"lKзd7&h ǧNOi^֔hƣB$#S4 XcD<npw?mۿ,DE5F 7#RT bTe^O. q0šclW@5%PɃs,WP\SfuLհBB\LU (A[yۇߧ4ɓdH( TU)h2}S]d뜩1 DSeOTQsY\vԟS5NT !EIPDOMёgSe|w]$QDYeQV+!{t*Q~4H\_A$7M+Ak'i':utrJ |gWw?3F˹ ]pR󗷫:,5 aNLS%~QZJ}a?r~L>s[Y|*(fpN"M-B$jlU|. ID0,򷾽~ 88)kz ֧=9]Vkc^(WŹBR5VEOg~qD"zdkE 'Ɪr֏0gRQ@SpQD P9 }ىti~IRx+x|${t1 Cf-vE qQJVe5ǪXaH (*^֮X-] Aš煀DcB9HY= gHikz+-9^0RٮQ:*Z:&t`vD2zS`M:H%\v`j#@roKiz$9I$4|tX$YԢ[C_0FVW؂VNM>شso~c#{]7b`e]^+dD*KE4@&R  4 N+D"7KMM\$3},L8_vd!}iZRB vn_ix ʨXӾ΅g>h{\739檵[1T{* 1=UDTދ.!&hd> `EOcL>v*MxF4z46nи M1ߎǐ ѐ A(Һm@΍%@A]Yw9"J3}NwK%VRÊW c1.EPLrG491ғEKll\磈֣f&ƩÉX۶1_>7jy623;Lq2ʗ8nsX*f~8 qj a T.ZADֈ%ѵ7 gPLM̀+'"e64&3=>\>\ ' 9w=8u,i zD*fN[`O]LS @!v|$]M);8,&[gf_6%zcQeѝ9  Sه 4~l e#: jJH>}'-hucwazWãYc :n"8A^S:Ƹ IŊZ'OP'4˸%mz/:UeGDW+!9\JY4MÇ׺w\cuH SHM-Fc :֭i80:5BvY/HYKEy?8RqUhGGgcnnU'u$:̮tfƫWPa~I:γ[f6;^q)fDF01(jk îFr"6Tꝁ1 BЬ`Rׁi F)~6)܉ ,-])p紬x.`8fAXu#l^f_[3+?J F %J,iXAp ,*WA^\;. 0Ҍ3C "ywQ˕.Ie=pcl~ ,T`+w{1%DV R$ [ q Hg + {Y)rفlySatiZf!paE:D΢xֱ)-  3?萶ۛoITo2m/p'(chJ rePjJؕ'TV"^wOggS-﹦0pM/ ! $##$!% )#'®""  %#LU*ԫ2Y-ԄxKocKR~j**DSL*&#=SM㾌}FRDQL* aAM;ZwPDSU)Uk7!#LyR:pM|͌ "- @2IսF^LS2)Võ+GA0)|YRQLSUU[)A*CڸFäz~u~\g⯳l1V$K" |{/ώsg)tgav t@.B"0oQTz|vɱD4"}bYZ&2ELZ,NvG7MH% դrXmULgOռ٬ Et4Mcv sʊH垣W*#z"A!lH9EU#A]X NÇE)C܅*~6+Is:?QB0O5t)vC Fj7"5 +HJ,:}鈠s8+%^1Ƽ8~V=%_ŽI %`5`6.-5|.U``c*LD.5+Wt*_O/e1.UyM}{פ6oWkc*А#(OKA~\.Weҩ6 &˨torxbzF x?1?6mA{.Y|6#;7 +=h>jh;'6`/}mA!؅a~/U'F?_=\ddh,V6mB~|% c$ d|/";(G9b%׿oU6+t|;Ow+fBP_;|҈$6ae0=C0̮س .TP&t x(煐IvQ$KFldeFӐH 9UF(h~Im fWzgBHeh{a{cy !bg,6޵%sضˍ,U5,/@ڗ`+/ݡ]pJns&B {)zO .9?a`iPi2dyj,FFT̾܎.3.]NK=4Tى!7ۚNvsG*4{zqeV):^eM}$xԿ2vi^b r-8 ^l6wA!bsL_"ӡJcq҈ }ӣx嵅n/,sX|lخ`߄EM\N76*`)ρQ."u]>ύ<8wl7?Y_̚{tV w|5Y3ϩL)ɻ 9+]d9!"S<<[KNw(=' ZDtI `dVEU~_% ^m}+6ʜ~xt_~KN|nqx(GPhƽc8|kH!;v[("r(3p0|,yiҗ~DFff^x1{ N 3DBn'(:w?r{#G1 P6PZ =-o^ ~Ck 1ߔhHU"*qdkD,5XB%+ჾ$vŮM8Dth~?=ɚ6 ߈髧W^u[Ζٯl:i'^ W *n=-BZhPSijfۼ^ciط1Zs`7~ 6٫Qn6zc wޖ>V Z y8QW*nOngVa}tYanH1k|fRdgDOggSn-﹦0qxp5%#%$&!,&%~ ! ")'%à! ##!#%#%""#!'*%:3zy\۳N ^Š,Hy9E~Yqq{Ń&@[涗%(d[RvΦRk-;M'[uP1 u~KK3 " = Gw ྈH#GjTzVu뾊ϵA2[bWIloqxf(DפXi'w_, ]]KihXK$Y+.*_ր> o%, R9W,Rsϊ{`1lV!.\*4YY_ruSnM:HJqH4ςCY ]E|ȡBE! 4MewRKB\%lCNfp,R͂xe`([+"-%[Ef Ssރ6N3uWRf_}"T]Kד *[`V'eܪ:o\eK⳱^'h,\UuX\kÕ˾6ےzQ TseEl _F^byQYmyXhvq1;SJX%>H}=R_YF*5˸ jߥ-JY5zMgǣ1~eY=Uz~[Έ=B*/ 5`\>e1V;.Ũ~2i+5ќYz;4?sjX!a=Q1-Szb ٰk0,ZS?w-JG7h, ŕ>mGʎ m88'<ʪAe^l'lb/Ƙ煀EBJP@X2HՒeOVYoƍ5s@.)WooQ=U Í4%7Irq駌"M_[ǒDQAV`UQřp~ir`Q߸^?ccca"cO}]Ѻ%U啽|Hy/ V3}3{qn(oPz0~F1R{ ;*UkG9zyCp1 u E  H՞UWKNiE]a$)g tQpr?$S.AgxJ@F)oOY\Ս(;" ?,JN4 oϟ+_Q6#bNra,w̤ߝc/T7v&- ,5n .1$`#}L86ȟ1='2e˅'\'Qcm9{D3tb(Asrԡvjb'bU,JCh,壋OxơRo(v4F<\P+9jԒmEjceeyM[Fk4@ H)˶&Ǖ=6Z+1 5#êe6U!zJ" !iXdy6;rg~ fwLeөx)=Q3:On_ٷ+\jH??)`!t9:tF/h 7S w]4e+XĞtkrDgPS?4+mÇe%ODEG7.nusuyH':i=vQwִ)jpy2 E $3p(h']<Ktm:ƠRd \LwA(gH} CW* wv:քܚJYz0%LX%#0pU L;0W E4!jM0E՜^1;vכЃy5Y<8RkoUVzJ'4*8YtfckVJho,. {PP 9g'nV{MOJև:yk@{|m+Q*!˟~ϧavIFs,ˋ^ؗ,7cbhTFEf4h ~&Y\@Z5zّ4ѼHP5]BH=⨻5Vc A}IU6Term( 1ƒ裗LYIUV֖ehZ+Z7FmZw%0T[q6c4}M\^iv#PUi(n\Yq+kSL])$l{8ŐbDWՕbXШyy"FP<)KrC)lV2phpOa\JnwHSbT6$BӊKݷ`BrI +[^8&5Fo7Leu]›}'""B֋\R3_1Jħt[(P0|)1fY{LZ`(a+.aޯZ4$grgOM6[c6%"<͂fη@P:드+~⯎k,spw\.m]cn&"4O /TC,ЃRG*qpe~{RǪ d]kp̪Uzxp?/c2eFSuhTb*=;ؖ@f(5HI(cS8+EӐ@Ǵ8:8F@>VorVaTBrTk-ќ)e55HxFn9nKgIHŢAg?Qq=F 8 "X5Q|dԻ)~)Wy-]=}Nq iڇ#È*KcTBY5}H1OggS-﹦0rIg/ # #"#,)$! !$$"#$"$##''ތX)%ߋZsal@ųfrtkvz0 CF[=LI>s1\@d" ^~۟,P:4p`kJz )vuGu| c׿c )(ŠPE7opy>$wH0$a E`!;b^3vbuHіtlJָ<4BjhXr@K-Hd@ȏ*Gt0B4} @X#tH~ZB.\1Q)&\T()+&>.kyATPkNVL!*(s՚-?13t;9)ESx_?x:_%mC7P E$0n ?9ƞ: @x0М:concdŲKz{ʔQָ՝AL d2\o#Xb@[a.d դQH|zA!V# ʖ$>]\<"76dv%j?*r BZ\u +x'7=auVz<ܣֲo/C1, u).iQD7p%kR"un!4iu G(xN3yYJ|his>KlXȈtT1(/54GcdD+& (jus|ÍF(\ ȎA{X{bvz"f掷^N2'(D%U>Cr)BDHnPo&A b=~\֩C/RB-??E^]f,Αwzb@T9L,S}cfzVJkM}N {'Q5CxȚ7m5m5)*Q8+ k0֋H[5hԡ^԰<,Ɗ~Lv=ձ!(wL6hwM|͌2we,>WlGɜP#dy PҚ`#ng;ȁOhz=[ctqk1؜n YO=&X!TbQjuHE9X]AVuXvK82KN| ߳Jd(2N#Vӄ|`Wb};O=({fv6:ۯrj_C9&'\ŏ@7ST^6˩c  E&WbF@^uެcl, v>XNsg6rIQ(T,LY1̹"]px5{K~bqԺ1 #ܸ~q)^UcفƪewڐvSlP*S qQ 6^]^gaN[sou,$aqB$+~L4Qa~k0~Lz6?eTOCAV_)6҃IkaIZoo)% r@t >,a~ =2x읠,IG$s6 # DLD`ߓZ[y&98lߌDj.8&dȒF@ZkbBد(jΈ`cZ)<ᕻ[T,MEG}"[FT/!d?>2r z$d!!QLmMh+?k廆d"NYa=T1QiSe M @wEP0ȃ׌W6G&0L[«*[%]MueRc%wQTW+ifz^SՀbȋ(a^%dY-V?AaȈG DS?Sjb-ےJ5h^cDS?Suܧu 8&t)8j,Su jPTVbn * p~4"!dY!bjeQ&%F?AFQS|h25leAVMud٠J@i؛{}LJ4:fѱTDpL%4Ts@?Q*EYhZY 3qC|mb" #m]7PRFL 0 jPa+˛N1 .H- q>Z)o!@TԦaaAV,pb@.@B̎XP0}>]\$Pk;]N=6Ep~.0Xt!DDHDIlzٯZ"sajXlY\2'rE'l р^岍2ܿD:Vx?{٦R^+ JzDk-3=o Uj).vygHҜS:ӴֳM./yy|FzOx4t}U EWBPoB&fƬ:>v NPFndH*Lz$2Ү'M- bã4nx[yRbm[%b̈GX a=I>QUDYQVphж3Yz"K3m )ȯ LٞQVޖO^ ?)#RU-74DLjD[Ֆ=r bgDŽ6 K*׸5LWJNk˯}mO n\V̖ȸxKfڱd%9IdnZSMYVk"Zv:gTw׬B 5XĹU$Ja,5n2Aq5 NB@5z1HE*MkD" =#Htj2'cz>lC@$3B!TJs,7bm߆OQ$#<@ KXxcO]E܁OggS@0.﹦0s Zԉ.  % "" !#"}!!!#!&$&{.pJj2F@Y!8xtȫ scۇ…հ-PVa] ۶Y gzY:l2C7C:mOhTeZoczׁ}m!2Z_ :]Ȋ!ҽoE35^{KLp?ݪφI">d]#*HlN!#cc[Oco%w4nxr0}QØn6+$r4FЖT*!`Ei@>{.3TKRMT%Ch;+Hs-n]h@$ 4"D`>枮2dIbEX@^6894PP=Q|"mmbi#jk/P_kf@|o=-R_a` קUEF,gC2Ql` j h`Hͼ4ad{Ƒ06svu2{wۭN|n `@  @$yh x1_# t!#ʖDWuUS2QgY Z--PRPTWG$KUƒk@[eHJ\Y *hcG %[%k25LWSGUS-J<޹/6-B%TYUAQS@#27 A2 4YuT>WUT] nతjJl[!TuU('߱%,D~me< lc6ݚZi&rN]#V3Z.r\D`\aU% _"KEcaϓIU+4rшdS8wDsX/.dUhP_@@@PQ$H pV@ ;_x}=`N,ɷ~ 3fP.VYao$xd-u~|fmٷDXkMNX6NX#&fOXAK "&Z@KbcjB@W F v(9e!ch-4q{&q)~F`7#V3k dVt~Ѝ=vw/deV@ w&"Npkݒ:-  uIth>le{'GuX;M.Wr)UO{uq_^՗jkЅ|&UҺ!En„mrYQ.Ѿ`ySR4⻪ƛm1F_)BXQb)6~}ns~P_v i])Ui"$d$MF;i|pqYL8tܡٳ ѐK 3Odp)*qv JH{,aX:08o xn($U|<,1$-|6mDFK|s9"# %oz' ̓Ն13Z/F] GPJ`F#0П'rD(G FSҀi T)"- kfk6#@(FePcC)şDDdV;SއüwD6P9tpQ[CuE2A*\( .=S:nR톫`%1{Y$C"+& ,Yţ ;+T5TW=Uhju$xU^VI 02٦ ηL:OwT6?le'#[4GݢN_,Mz iD[3_2 ŇDՂQTh?xqBi4$Meީp>9~K5z SkT_+rj}T2B&݆tDaG}L؃@;$׈]8B;fǼ SEA#`~E!9؝'ʲ(TS蕍GLJO߱w;ƂgǖQdo~ ,9څ݉ |$J{3vG_c6ؘjT:PF Wn_\ɚ'}K({XfPNGɜW/bl6'vތvc,^07]m@ awr4}54RMgNiqiVaYHkl H;Oƌ ~2 j*8@p^ 5%5MSƾ\Uxde9vZcQ~z~B.~6@.?nQ,@hLeVhwsO|0XHեֻ۰2cЁ3F:`_*7uh*ePgm5 )dsoJYۧ5Bdk):Ec#/ eQ\*Mat^1VǛk#O皷8-.A9-Y:Zoɵ.4 .(WT\SGf)Vo w:TU_$ۦ`\!dwz5MDz@"U^YD'a_]8&tĀXePWNkj|r>VGZ! ~Q2'#!da ۰,uOggS@.﹦0tU1!!"$!"!## "$ "(%%yvz $!yzvi\Azé4GzIU=# 2x[u7ڗJޔRjU52(T3u5!%I376ZJ >;*1׎KaH`.؍"4Y &ɸapZ=6FO^vjOpsAK!@FPuB7 @%Z+0P]<K'$Ԩ'*dTEI+Z`-Jf@Pa4JF <4f|."f4a400_)t+x< _ 'X/Ztjt rs 0@s`iVG. 49Q)l/  (Q$!g!{%%pXBB;|0Ho)c*(z߽ȹܢ daÒxi:F֏ɶEͭjqt_b$zg: 0YqJ4`)EE@B@P t?Ba QTSq*:@88~j* e̹GMB.>"4UL6S:iÃ1R(YKki\UĪ8UGxpq2c<}ךj%_oL"TS*:s9)0~7?ĺDUUd*:]iuioG7H(LSӪJ"rzgݍ7pJm(X"DSL<”Zz`#6h\W|6.q(SWchGT_dU"yp˽\o}Ql:5\>$ͬ Q!su02 -Һiib2~GrdJI>=jvbkquX? 2h:^0 =N`f@H()*5T `w8>%~dnUZn~*A/@>/,(1XSb\hkq}yhhIgGE[HNeޑhYDnC^Tqq#ec[!V$Ea1Ap%U8FZ s>1F)N'"g\&'NGnli$V,X!  QӮ*68F%y M  `.dө2xf<َ s25rH?Fg#MT 9c J9k,#\bi.JIH*!c1A-Og^u'x_Eۣ$JJ|D(es01]L!g랎ny>=ؾK  ~м!(GĘJM8L c3\?/jY]@Bh|X$VAAB*D]T:{tgC@C*y2:K.NJ`#dǜTQ~-C&7_ִ+@JƴLW-i>5BDn@fM  T|…M1<ǝ0~{Ux7jLUIT= +ԭ:;™:c$QLUGr`zh>IB,KDQLD):ɓ\׫]=s[6S{UTWbTqzOZ]/_H1aD[K֩Wi {)5:|SLa WEu~M溳=>!wX#wmQĝn8gXҳ#0Ρ&>־ԏo-S@H$""@v\2ܓ[,,ΉYLg ]whDfFWjȄ9!u]D?©k]CC:ﲎq:҈f-)t;\j!YdBl bދf,i{@`{DDh&9;ao4z>~[$m҅FDZc M 4ʋ w`d>:11p][ fLLU(PCEM.S`"v'H |fi  Yc'<|cH pT@st9Fla(B#nJ@ NWr#nͿ<4?>|ʯ`8y=fRdcO´9]"9lfiDHLpzx^xNDKS٘6h:ݲdnNß.0 Z  I>RUkUXeH"RPHirB4,"OggS.﹦0uU!F5!" ""'%%|## !!&#&~ $%!" #"!mKXw,!; \B!DDo9ȵB4F]V7?8""c?DZ-;J_{,}9wUvG:q1\oc8Tj=ipK7II4RQ 7hS#ξ>/|]OPR C6c~Jϲ%,dvaRrfyP5$K颲P>uoJY1(`g*FDZ saE}pª^Ů$)S0gTdNN $rOjCo:̪ӡʝ00͍WB/7l;hhrYP]"2vcXYB%YrVֻIqXJA?dP$H>jj!4v C vS3'E[XBH~] /!Efp7ӕU_opV4cVLIfɪwM("!]n `P_+rnO7`HtT"uL"W1D4FjQ,b,.Rc%$n[,4O—hjMG?=4&N;(kG/u=9I31nJp%t);_2*EkDi NNhjo)JL;f-Yrw0a[KlLL,wiwCl{z ,TqUk4mۿKkC/ক߷f2m~TeN +1Uqs6{ל^C">/,:>b9ZETrݧǥb&na'PT;@Y3|5ߐ%a5^s-M"x'έg%!l(dZk1 d2Wva?- B*Trg)a{#N}zSK$ Y>.me&oZJDžvcs:16S~D >f\36&k7.NEa `DtCg*;(/?c+{@jY9ףS/kJcH)GW Ihs!DVOL1m2 r1Dz2 PWӸو dh Ӽdžz¬Ì)]өc}V;@a+^ҲɧxHHR m酕~9u{n 9^ 6BЃ  B.#1 I c^LNv1pi y?%O Tq{ aaaL3[fiKt'ha҇;fO NZއt2a7\&ǪNEbد$۲_X]H5]E\[fe< HonY UYV"DtѨo-ո,g6 6^]q>/wEyIXzn+C'P@!ǔ 0R5Z#ˋ q\"4StOU eP=?IN0bx$Ue꟫L1@xV6}9NLYYU(xd4_rTZ'J]RU<<e@_ϩ}*GNW,Qeړh0&+{]^SvzJX)ei4OI^[R;W=l >qR8,,մ5]&T&Z!VN܌o߾XTc UXp,Y(%SY[QvkLg Uقf8X#Y#qL:Mj)Gw]mͳr0Oc8Z`g#wl>8UO)D<{GrԜgQi!IC?v9*w7[AMuX> !TeB1 B-s܄N\=~v`{@TKGtA \CiedE4(NrD wWOo|q}KywaHCXM@@'Qa'uEPx #uzR܌d o?K09^\2% }YNBƈhOOwJә9I^F$-p_oQ:~\C-x  & =X] U"۠UH̶Ipb!E[f 8nz@`ẍN2&>b/(\Hd}o͕۝?M(T#u) 4!q@)B2V1A7!հ y[Q|yFOZ X DM9odž0e)DW4dDO#*#H d[ז fn*sӲ|^w~\el6;a v"L*x"Y0^|w|1ź0:J)dIii̼RnGL~X^MyN-!*8Pc=$N=#1bn)/G9 {<<bmWGnI*b(sZ҂p/!~\6T -q9Ts`6v>DDd[iLD,x0Sb]0CӂibKT #xr 02aQ~W±uߥM$9Rbtũ@+SV⦒B;o8F@xcV-o ЀQ`\D$D^HDCQ5Vv _URS+}hRԮ9;v{o @1sʱp/ 8jފ+ e( ':J(2J R.nQt/,K '畷z[c;IԞM%4[Jٖ݅-cpzm=HhrLx0䓵'E֍21b/?DL؝;A lWKu4SZTtP~:X[qu`}H$MGMQ=@|/cII0Bǟu-OggS@_/﹦0v`1%*%! &$#)%!! !!&)#pqy  #$$yz4Ց5U~p1O1UrfNmu,4[uăV% j<L{^F%TN8ۜVHj i/翓^KD[ kU9RY%G`@ G5Q47#"ca̕V_gmwchf[K˗͍H$̪rqg$TQ6W"bpMpM=*1!5Y) !҉ o"ܱը-av푩59eurOgü =c+va||L^5iTOpGzbQk) .Au!% z^,N$X6#CaSd&fƞzq{a6c 4ѹʇnG۵̓XJwfYsn&gApm=dZ)w5ke q6T>+\zHDCn^m9F xҦ#n eVBN敱#17=ʖi{G5` IPoJT?:t6Ocj[g. -+ I\.W^!Š#>;&R Z1uu #4< 89bcCwE0 ~¬$h=8\~=F_ M6 Va_.r i刬HJvxA?Gm؈4T㲢.+ >^!nEܻ f _E1 kҊ*\OYd%@HVӐGwP4@ v:M5; dG K>QM_r~x%xL I~i .K+(nWč1f vi@8|ZD4pQF/hkamcO,揲yV~65!nFmE ? XsE+cpKCcRh#=2&X4޿ˑ3='f}{'HA Wؗv|1U/ FtMA0ZDWMU4X5]ߖ?:ɴI/3fϸAdeQU9RFSʀU(#2a֌s5:lNР@@xR A `<(EQ|zhdnM⩙4[7vZMhE0ݼ\L\ڵ@TO mHUԹ]3!"J爌Iw=JOqX0\᷀.` Yq|Jfޜ. ^s6dcw]EUo0 QnI]HEF:O̩G&@S.8!# CB]ф*T}5SVC\7}fuW1ϝuafChp^W2/t%hg*Qlu)jes*uFvY hsêZ ͮed{(̍$23"iD_øB& N:O[c#%Mac^;rK ]RR[.%$|bdKLEPHu4Bdk^PBxfZڅB(x9D-bQ8&sxu4wi'7Z}.jUOǠ>jzLpձ !B 2 }H7As겕j@I$UHk | ]}9"]YJ1"V~kĢ S^u=}OhߺDU jG>m]*m$94uzRiB(*2Rsy*":fGY|r;6}F{w%ls{74/7[QVBHtN5 +iWjSJSLl9gVl0IHK&&mchXZ ܜI3;`ah^~(5ZzbҶ*Y,#]]4Q4\V`h(,XC'5cH1@bAAH"2cpQEPAOggS/﹦0w6ty{!"" $ %%!! !&"w~  !%&%!!!!%#Ƥ>ڇR6ü4ӱ]WvQU"DS1B b)` S F@PBd\%@ XW;?W/'S,?(DU*BUIh%*.6U:D /`D:-0NJs  3Qcˣ1\_nrwE@CR% E6@ Cr*xh帱"^yĊQ$!,,[$MT p EU%D#QQ妗oH;'33l8-E 0a]j ws~Uj52Ǭkd-'P9Qd\_M1\v(DЀ7LvI |>`UO" @RfVP2ct=y>A `ȭ@4p)(pDaֿz,Oad!lV!$c(*VA_`bK־2xe6 Ȍ@,#B$F~5EJir!8]?ޒ旋t2E4~DVB5Dʊt!Ժ2%ccM7+n#)uRCq˸^TWt%ife <87L_3w6EWkHDل#Oi3GyqXt5 o VKڼ%!,;׵_F贊U `=M`7Q"&BԐu}^a]]'!BwwZbPPhw$h9*@vQ$`g _&LE R\WcCjɖЌb̌%QUTWU௫7Z{tAdC smJTW*ad+QiTk{ 5 f7_F'õۋطTzT2M$ QXq;y^~&/_nPũ@_ Q1my +^7 Vmpq`YZ`y&!tBu눻HLb \QTnz&+o\o-Q1򡤐2DWUe*uZ_DExLg}S=$;b)FQLWG՞Z.̥.L0b$zzԧ1Ȏ"ŸM8P1+]JwC޸Fl=c] OAvQ7& O`^}\j3@5fȦA_+膯o}z+ZFmAc%^3*iAa_JTcL "i13B5q-ɘo_(D[f!N;F%N!\ !2a@ ^Co2`&`.H0M k.(`.괢*q5/f#FSl:e!V2$SvX J*$ ÔkC>I%ЋΩճS&7¬\0n@V3}ʅ {YwH+-)ґm5@q)& Hh:_^ƅyH򏕟XL.@j`Ipqn$HJʏ?EGJ<̞뽎x;mhXXӏiIetU@08j?bHРu{%R(F{H@$8-kcSF^Ώğ?.@8;gP8[_yRtN״5z8F k$7NF4me5OIncdk/uJ_8+ۿMS@ܞOSqxSu:^+CGJVˮm[ta RS5Soҹ(g/*vM-RQ.kϘ5NP)+i /18EIrG|rK'L*qکm{=40cm{>V=H6A"Bήy04>녦VZ+t:Y-+sFUtRZv_NEXd.bX$ jJ~ dc3̭( = CiLt Hh #@~ p_tP3lhЯBð?X^dt %eLIt^sWDG}~UE,ϣ&4K?v^eJ_&ip^)z-LQMXLeKU|.Q+缎B4Qh1q7?~] va0γQ45eXYKUZQbYD߈-_K+ B(^V'iݛ(` 쓉HEu#(`Z 0bZ>q ީNc" i|Nw @Jǔ6Pw J#rIC"ۢ{&I8&)>`؄8Xogiy&ת% Դv{&u&2zAI5WmxKYJy%]/t"j+8{Xߧz/{0Z[ò/IC gI1aטx\,o/ur,(n  D[zeRۆ8;VHe\[֦ |?XY RԪU¹|$TYJUp$&J@_~C5/ՓؠL[{z, XsԮa/S\Q̄\لWVi땶@|k\Wq D(wvtţI,a Lۉlg)o?qϞlc1U$n\=x0%]Mc6Yv[J)v?\ah1 Yu<ݕ|{:;O::NIf"~L˹n Txk4wȃlCy>^TaGkDu-QmKCP˘"D`1ǐ5rձ-(e7 (\@A!p,6G1>;V])|c^ֆzqe? w j'rK/$ k? w y R  %(AIl';TjpgE*"Eу]U >K&Em$OJZ2)ƕPR]sJ}": :A>nx V@= 7@I@HF aQh"3rhEYw2|XJKE" &ܸƖ }Cd$@L]5,M 73 ꏒoE'BX~pHWCuf BrܐD؇( NQQ",JnE8Ju>6su$iOk.6RH8jЖre.I,͂6ꚹzv+xΓfl +2*@) K–elsK^fϥ4 ·]ʒ_)(MQjñ35u%1;g8;9N@@ېoDiswPSV9@Hq]G{Nt?aLoX6O+b8=f}]ǯB.;#ֺK7nWitCEje!jptޜp56XAN+$4|͟yӳN%ir 4V(Deviin0ަyj"MBȡLQ1jsbk&qV}:QKsy[5>5ɹkg1IX%ͳ^\40 E1A>/ +aK)EJ-磛ƆAhqNL\Ŷe']~ID,,57$Q\nup,@p]ru&6|. B[}IYy짎us0+6J0זP4yPN?F.@.ֽ]~\5(w\6 Y P9R1TiidF/r#"g}]>&(\ 򷸝HpDT"͙۾&m&TE@/P(4|R[ƥw@/w b^C|~Q̄2 JRO)^iXg a>XxJi-Qp,]TZN%YÈp qT#҈ "$>!."Z#XdWt9ocƋ6* >J^c&"DOZƔW/[ו>;B:\32,Oei + U'_B$!Fh4rO W`\kgl,rRs~gڊF7$'hNr$vL,Lӥn1~4Ii{PHgpoP9 Hk"Z(|4`+*{wP@4Bl>vod#hU%al95b}~p`b'J36rKh,J_ķ׈pD7*$F9D"΀e;1H` ["ROggS0﹦0y3!&$ "  &$~ %$$ KfF_*|oPEBL,f>`["9L$!3yhin6Z&Qayl2Zyߚ7Ò$|@sg@ f +JPMrf2AN{@L ˨E`v5"*SDUUAU1L4'mv$TK֠\S҈(Yb ^rZ7"-LSLUU=It0-}6aWXDLWUdSr҃kE&&D_g[ AJ N+wlYѬ`Œe^i"$ۙ ɸ+8er}},qE!B7]N8حgpD,Am6MS7Ċk7^1 u&|P9A`DK"` eBΡ$IviN\Yl~iF>_Ui]hD13`uؗ]/쥏IGP'of͆S e6`a(Z&L kh_"f)$=J,YưrQZRcCVLLb>sŢFx8`;?IDISN)"FKm7b1rD]ɇYS-4xfN=n~5q{4;>WaX7r}<4}p8 \pK|"b]#~6@?S'B9z0p4PF8g/#bl¬t@B **H B{ EUJnsg:{Jޡ,v*Q!\p~%AMarug le](fe:[QlJ+Y0{uiCd3d <2٢jHfsZE&l.5 NrsL䊅UX B$*%B~Gضh KJRh &RJ%G-Ƅqb8IyY֑ii#&ѵ:a`j1T h`m+Tp*'#X>G$ UmW<,E&!DB@/P*4ٴ L*0FJR0_IFaVvÌrhEK84@ B)BtguEGeGwunJ2 Ty"ƊP/R& 5 j^+VMz{;u|Ls2짔FԸ @WI^HS,oB ?ת`O>' <3Y qJ 2_<tw P  Q@@xrQQ^[D<?[d!WJ[e],'aH"ɚR S:WS )wxxR@|0Y$ h`Yƀ(v|#.,0JVX΂LZ-c-I,"u1aM@Zb[DBXȀԈ(!!k%c0' +f#UzpOAJS TJN vO#-huAǭQ?$n2.* r(x]DUGNUU*{ Z{n:T5" ΏZIR.vK} deUu`Lh^G84)š L2{547]a[+1G.΋H ÌaiVW'|s@,G17weEbVrV Ԇj46 ǔ Ʒ xgEBL̘ b&uQ7 |vt 6pѱ B<]+Y?M)!UhXIrBÓFhLFfh j)Yi tJPaaKNԊZB=AI>ܶX+.*(k|Rv,ڠE$~XR6s#9'}.#99i#5UN~4A+`5HeDh &&c`28UWCW0BY_WnHTFIRҷ,, vkɝTC/EnS] L@|ֹ;;@0HOx\E <`jPUXrY^- hF@ESLzAh<ۡBD+]U! Rb!b1=>G@ eA74dgQܻN68zU20J2ݞ|gNvETƽq?{_wY|3l6) w콧!:Pf \?E2Wl;q?#QbhYFxͨڰ\6^l2N3 Ռk+,#Y5Z$BPM7_N^'puzn|ux엳CE #"mQ!'0Я^CV:wXKkmlrM!.+ތNs6Ķ@ fok%iK&J$'7+m|u0oz61_fʝ}fuAq|WXYY?pxY mJ1_޽ʴh[pۅIUX{ 3GX9PE8m+@rc/@wZ+(e`ig9+'JHټADnV+:dyNzrYd :xTHd0Cსq4{۳Q]!Pb!'P bV8ʎm^/EA"|ҷk}d# sPf5v0_ #E qdpyٗ>gΉf&MG}17rUf+dbHFrQgWȎQYPuK|ԁђpۥ%ITֺn DSq'JC]F/Z +t4[ş, }~үUzT9;\%]_ѶOV.Y4zγe?p4y=v\GDRB TkZҽrcԨ=>oÁqޞ8"~sFBQ: E7\*!K+t.ob#{NG ߄tWvԨ1HH\uF3S5ǭu<ʉ2m/#(f7$j bHkv D0X-0@*"R5\p\b~<'l엘\*^tKwܗt.Hov#\0(t*$rP6ɗp4\mmjYhy0 $تXS;8.(HH BxA$ -ތ6>ѠqkFmVsh^\ ?0$ЌR$JQMj4[ 2 ҩFV$):'tؑTq}A@ (3 " g%E@K ? )¢ |.^^lÁk>;o)%# -F)(P0RHd0UA*fTI"IEqo{:'MU0H0 IEi+, '*%ޏ%+I+Y]G.:;|N(i$Be4 0=ۼqqjGZ@eнsvsz`%T,7YT҂6($*8e`Dj@~\R9 _n'e>`!EPΔSENF"z0݅cPcjs Т̀fX@)׸coXeAښZMI>lv(jh%o &>q?RT^o(,HG*o,$ fd۔_|jMk ΑuAM_+7EJrrXT4 &WJ ^5vڱy8*Daӣ/ZI wNb?piQQ]Eڡ~A@ A,Љ? "u @]cyL{,'i`}0Z ,;kU[2uAYf 5xS3[A9ᢦq13樄=c=V V cZY9\j ,m>[BoMd^J 5d@  22"k͑' wΥ:u7 /p{Xp(п@L]~D*h)F`g KFoUh.O6LEFX"Z/B .0  `$MfF"g|QF%=|ErN9@`PPP%<@Q@cEAKBxt;Ɣt F1{mb 솭Klknc7h F)PbMjv]G?߉\ 7p:緶o: Naq 8EPmIalKX 3\@?ADЕD_(*8.ALU )d^ ͧ%OU"PDUL92xajJպR#V #)lN]V\cKX+ZXZA]-Fef^ct-zRS;x%K,AF#VP2LddE1b݆;=4RyW w{xK> ӣ6*qFy˃N:;oۓ`:.tۨ!@n1P.L6)`VvW8á³)RẪ 64G!汭Eccӌ4dRtVc60eu) 8 K,[!]Vz㑨pj5 B};~. |i?h@JbP~rgv,0uh}= 3 # sP?y #<"B(L4*jT"P% nE*Q^E8`Bbz ]Wz0{aP! *!^&͍d;Kiݭצa@1#%6x5mRJ(Z]0 vBu iiU ۵yӧjw[G?p+y,~%LZ ̻[A%@}$ N 32Y46;Q5b%5ΫX&6!R';@|7^" Ƙ;9H_g'簺ՑJx%+ ,1DRX\ޛoׄNo昤ဧ=n٧ZslĎ~e?1mYBaj}7Yw+.A"P!6aN +R#,AR/`bXP> %RoPwE ͇Ü l t%cFwv`.i24q^8TnpgV s@q*S V^f I 6 1qOggS@`1﹦0{ +=p!#!!")%$œ$ $! &&${!""!"%$% " &#!! ('$1f R)QrȟD)4̺-};?>m >о˖RN Y$uPDytˆ>ŀnFD0bv%}/ 1ީ6F# "R'/rm4@s^GWӺwdI<{@]42Yf~B=tTnH;hҔ7wpܙ~}A[Gv5Dm_y감#Bj iDb m_ K+K,Yf b< 4XR1E ,RlzǛs ~ӓU˭ε*4b%irM^,Q /垥(24KC,՝a9trC9E$R<b^?B[ErU,MV~۾w"H6`x|:L[{)+lKNb&-567n>3E4_G=>La~A>W*CjiJjfAU!j) D-Ry\E-;kdHQkK!HHεnkd7K6mЍ][g}V㘒 FXPLNT `Aՠ2FX'~o>qj QFJԦLo+1[&QyABJ>Ʀ a NSψ|H^0c0qT0.^Q ΒV _;x". 4 @J05-n &֕sFXrB-OFxhH7xѐ$tiδX VIKwƢFL Zo8b)fSzN@)|)%;~Md plpil$?߈K?X>ixm!KDi$>:*P! i6&~l3)]XkTk3|yCb "U;VNZV8$[UWbK{>nӀ=ւϽ Rڿ"+a20ǭ DQl4rϹ'_ChSM, xT9$MD(B,$3%#$R-(XrĚ,d2 9}8 Il["W%T}e\ aȋLWWV|MONiRj_7_A\Uqhv̫J edSc-1lY"* sƒ P~C}Un*qa$PD[UQ>E;Nu["2´ HlWbQUUQڕ˖I{g1%T[V`T֗ڛe}\#2NG/ULcdS$l`0F.;M?I(1^-⺴%uk x#sҀAXO*Ohә5b X9DVeexs,:;yJt 6U|lM_靫:3c23?&~Ni8|}8:Ӻy.觱(ś>!!o# tA UDu %.TdphEXh<1݌NX7wRA _)@$Kڏd1=k2ji <ς2f]x tg˄F]&}{%Q{ KU'?%eM7k[{#2( ,%e)q{cxx-V_[b+mA I^4gL|b܃O fŞ]50$,͚Sf/]#*hG tr4G\__c՗DIbvgOr^X0PX7_2^ucąޜ62Ӿ!"hf:}Ԏ,D8~4XjD{|2֍WeVH*pi 84(vq^MIQ~ *N4j7ͭK;K 6G奖hbx I?PbYdœ.S"$^G@9F%J?&nt>MV̦{2np#.nhBڄ N`eO04QUA*)D""U `۠jcr7phFn"ZQ {K{S糽pǶ^֡HHD),KȖގ?]o/鍉GaKkuwSHg1m˄^e@zF Vn1_Jig(_d E9<#1D?H7i  L]U̝@i }OyBLWe omG-^X譮=i8KLUgJSr#* ɤq%]ݠ(T_}CYXcAHiNq BL[BVv]vCZ:1ET[}VΜ4ӞU E\a! $ݖeq$-?+kTX,[L8 F"1t{0%(QN\g+-C$Pk*5HV+-u%kѥ餫3C0Jm_w4D>@gA!hh5.h`yUܬ&Vl%B2U 9J G|=uۄ P@B_9*O"js:4$~SyDEm騯2:qea,7J jRhH p; A`$եT V P K&Rl %I`]2@UhnDWg̗9pcI Kg3kb/*]uQG f(0-XnhDT97JV^۵D%bAr! D$DSLVW #xuɃ= Qָ <[U^]k'֧5*<LYzؠ9U{Y{bwR4Q^UqPQ #اQhA"LQ OB!+&D31j) 4S OWôL/k u3~o674a{V_$+|f$鱽z{LeBUYG%?1 c7Y%JV`]/pNCEyHgQ+?B")ZIaitX5CM;HvCsD |d Y+=pG$鴊>J0:UML_Sm/^;19紟 OggS1﹦0|9OA*! &#%""$ # %'! !\$w xeYjMAv|O.ώ7yD1W۞{LC:t גLVM]P QQqM#$iAxrȐQ$DJj@C‡ A~lW3 l֥;ɞdq]/`4sOi$,|k 1 мF&-FF7L+:E@P0+zby&gzWr-Azh\;R\(Icz H\VK&z]  גRM& Y2Nx1c~! ;s5ysFxC(rlMH)ҹ {t4 *p,."a4EAP+B?h8BR0g\U$P9-bFєS^>>DF |6 صs`,M@. W#9mD񊭸+h_7݁kU8=T)uvǒ=J%g-#d ~V62J |^Z9B:u,2@-׵MWD1i7,8$;<Svx:6/#Hr3^%};xb1ğ m^ܼA֛)ΪċinJOy4[@+A\X7ԓ ^\㲙@&#^q9FC0 0sNS$3IӬ{Ne4u286ےq3IzWq6h0 HS@B,gƻi?1 "D薎-^kܛoeu)gYbvR-Ws5j 8ĉ+`Z5R NK'}P $ u&xPl$U8L͵srY Iİq6֟{@׏w))L0huXYn 2dgcM|}#{WvHw7-ڷSJ>VCFT(=RFa_1 qӐ%b%KɁ0VP ~D鐪FIFޤc!ch']%O1}[a]o~' [FloZzuB 4pey ߶_]R}? Vԑ&e*7\7޽6+D‚ ^<61f]51 -\ѡYs!6=44anƝ1*˂2J"'hHlӝHY01ATAC4̓|Yc:~٫sKQ>-zkH_g>{k¡5X-Fra&kHձdi煄E*O'l;pXBX5yޤ,]33i.. YBo;7a$Rq>vDSwQCH= ؜%=Ϧsry>P3C8&Υ05ud(e3kep W$> F2@3͂I 0mxS1,&W?\R5r~07\6X2lKj̾qڣv 2==vowfc|L9F2RƬ5Iw7i t~NCKkuzv@]zRړ, #p+$ְ DF%L vDm\LgXxY "P&i,i,Awj3ua *緻VrN<<[GjOCĵK| gw9ghr* JxQ9`$;il`碁T{)8@UjOXt(C\ΤTZ)W g+ݢ4͈%$wIƒ0J cwno+Z=B!CFPf7X) ql@m.@cK-kwAexsVL|;k%~mEhwyb0)`J0\un(ݔbZwe+[%tD`V Y('B5d7.G{t֕E"i*ɎņQ|^mI%KUJ4$_ҤS昦mNKGaWbSSVleE;̢}^C륮T$/iI$T9 YEߏo#ʼncsxr$K4"{A :ʖwR-`A'J1qb;*kzNY+o`$iY0J"뮀ش'$x \F`~?!v^.LU(x2%MJ|yt1lO 7آ CE1?DS4@su" J2@x9W4ȹeueaRpEPy#3%\ afŻn8H" nHe$QiA@Ɔ=R u{{IPj[$KeYF6WoGK;[=VjB4Qeʟ6<\=3T?ri!!0b`^,bC&1=rrier5lOlxjv?[Zxf-7o宦wPO?Ʉ KHJAb?:n>ZSXBul!#Č׼:n0%I\1>Ci@Ԙc] 3[rmY wq|!Pn@4q;=UR%TOȥ$6V!IBAgح[#7X Nx>Cg_uEXOni4IJFNB\CNx:$蜕-ƚSޫG|ǡ&4F9jOout'J 2Bmlݣ-{?+5vM'kPVZV`{E\A|%Uل:łiaWOO-ikIYe[_~{kB.reD M2dxߖggFKJ׼?l?F~z%;av ɋ‚@ .&z0Uvk?(En8  `OZsW+,FAahGTW"7]- @ICK=$lQG;OggS!2﹦0}=:'$%" !($(s"##"% '&! ! "!&"~! %"{\Srr=wK>n{\u] TS{6ZQ@גx$LUêQV¦ɴ\$::q 'Cw\cYY*i$D*wvz ueNoaVl6Ѐ;|6=Ѡ7ݘD<Ȱf㺸߭F1J)iFx,& u+v(Ͳ ;T27כk_VORkiQ1bPCHQ# bzku|N5=>3AӮhpO Gl;Jc8H q!1yᑢ*%ԡ6+z)l.1.dҒ(V~|uYK>:vو9Q&°Ҋv&{fl1din\iW;(AYBG|B0@Cz]zgqDZDWّrsT_X,X\ &vkurTzku= h_nF{ŋ3 #FH.o_wO_>#gI+ {9|-d8AH5,mTqfjnoۑQd*OCH5T2?_Lv%,V,= DXn+8XqST]˻N)6Iάj$CuEd_)υp%c&=]Tl)hJLۘh; j7$]R|4EO{gư챃P_z~ID7zR-W4ςf1;1ݽ +Pb%h!/\ep1Sa݋ \]ԨKBAŻ35ry&DeeSA惵k2?*,4IW .br ţ!] `/tk xwŬWaR.)&cSqN 9_5:eԙfsl]ESe6o]Q'7v|zXWzvh `C.58 JTWZ PjLTZ>NSvwK9UFi.,9F,'㯜G~ݦ#a#eb$uj\D4;oטH WoU{9{hy;&6VQ%>X!!EerNbsǥ{N?|BsZ-`%*q㣉ɼ /n]L 7-13vP$maT4Z ՕzIӡNFnIEcHWĜJD\ Lv'8ɮFċEt `" ~:Qn΋͉4i:av32b|ow4l؋">. (ɭijUv,ƒ>9Ɨ.$13Xr(U%(N!|8xhYƠFct,?D23h k4%DN'4Gfkrhph7K[-Rݜ`4 ˆX=Š7ncC?({N А:\I鈔N3 20c[$1 czmdW:ݲZc$C  T۫9Zr@0AG'\\}j<w/H*aHgnHUƀ3.l= `WlskB0tp)Q"2n<1zluZ6ώ/Ʃ߸ZA `%$۶@mQ,ϢMduj4+;(,l#E-lm,dCT ߲ 00 \_)TUK#Vw8ѱʹf;g+ně)s4b?ƕ)$ ^k爛~$?)~v1| tLӱuxl>7d} ]A`;~]UY&J!Kv@}mgM8x@+?6ŲD+^1G谯)J/8sݴ[C`}k 7wctGOHT1`V%B% 8u󹐛u.@ǸiL7QC^{ JylAcWJuHyKHr.B=kLW-XMVv{d]csƪor!]4OeMS-]=Gs4Wv5%Dۂ:->? _u1P`7{pgBd &/0Pq k$,Ѭƅ`1W)Q!q>mBD8$ЀA)a|q?鴝޻;,WѳWǎu~Żݜ*pBn``2H+'bKeH[TUS@ -ד%+c&^9۪TUxhJvGx0~4NK1LUGU¾=EDqY;< 5̕UKTWIhSUQՇ{@D݀40<LUUєf,Ne;ٳ4DWIU|x̖/2GeZS LYezՑY4"miy6d\c5+Vw2(`ӰcÍX:e j_>raVT-v@"=i,&HcDh<on 5J.궫U'-ٚ}U7l)PHH T2|,Q#p#>>*^nڝ VC#A;U{)F v+HӔ2*9V m,G5v͟mk Yhx(#R [d(R@><[1Oˉ էHKic3k-%S[PxUvAOI3_d2c\xx&9SJ&]wOZ{6( 񽔏_|-pNGΧ3& n .0a|'.GB PY@8]cqB2 !5RVOggS2﹦0~&u36#"$"""'")!# ")%$! #$"!$#%$)"$4KBIS!nݣʒDSu ~ };D˾5I-$KTtWLu!\`T )ӃIA'7iFGyI,51gX6yi7NbEzrlpn YLckc ȵqlG/+dBӬs8>#zSVd^l xe**V B Jijt-b'GKP(Bέ4qS+(H֩ !B)Fkg0EV_##nUQ L  EkV0 V/`7!?сE6-5Egu.ݿ#f0B٠j>hƜXZA!]^K% PAeKjIPe"B"6äccFL/֧ӿЪa:|tJe#1,R7+\a`㡍Mv^O$>徼n{<4H/u&B-i!ӊr;PxFAB)@"pMIZ~Ek}tc5#}r,]Ntq'A)p 4 k"Ҝ99E(rA4F(,VE=4GAkR_/pDdfYÚ.4>#Fɫ(D(( !6ץKݗSьEjS?*VEY~)\y?Rѷ 7  ^ zsc ѐ4YFf)tC)'/s/=FoovcfSdXuWx/"QRf_xs|)۶PVX iy~49"^""©j,bvH;0P: 00l(axŬ$Tơ. q{~Z0kӔef_ zT!_Be)@c^.%Saf xiJ <8imD${%tydeQVڤ$G;'\Zmxlfk) kLa0xxbk"4:˅Z%0\%- ؁PHe-:_a )ҢFU-l4>_JrKVhщt˶bo^%e{&G yqpy(4 l-w׊(j:jafk>}D%"h7˥&y F̠/ O.;;ODTB7.IOKFyoʏ_ m : z7+\8}CrF\Q"35i(Rab2Q$( ܴɵ%Y%YKXI#tԭDljx@]D1"͆PwjUc1@uAA8p2hߡ?ǗeMgd7څ+pu;=wה (ڟ# %~a,1ZqIU,HA  z,_V)5vGphVJ)~2Vm&(ZTKaFNp X <U‚Њ Ĉ,R6тr\xGtZZz4v#ȎRwzѲj? w9(}94=[S:@e5yޗv\avNL'UP\TeeYxpRzcwbMLWHڼ-0*\-R 6HE9WQff&#W\}{8@߬TMnVNogyddbTFaŒI;W&l +Xr\~H77Y_ *j]*8>ox|VoDwh&㣋\cs8~NKhm3sD*jG,>tOt7줣"$i8$K TqH"B?׉~Տֻ\.3թu~wJmաd^vJ1{HXKc%ܻijp%uiB0BpSK!i])ٙa(_L'Q1| SOʌH坨t(#V277 -.SPX8%|Qn]֧M+ żk :m1'OggS@2﹦0jť/}!!"#$#'($##|!"###)&!F guT| x.(Y*:OD@rizP]v2Of%UwFA7 `1SR1X P^2X?[P&^L.V A ^Pc #H)(DjB0D(,\KlA P[>"/ 8JaF)QN7ߏsc\T,S%@4*E t ,5CaMT*Zb]־F5>iOWCsȃdm=0^0AX1;I\CH951KTzIbIƉ^e,uiw`g#H9\wSٿbZzlu?ޠ"]H9k6PXt*¨(y~.A+鎸HB'sګR.ONDh,3Ҝ$ KY \Ę5!}a_&hvu #O6H<jcĿT;wm/TՀ<"@  Pv4$S -Pe)%AOyHFfnLLyѳعz,bV3e c"l Uu"AIhGO*PPG#)q;_Hy.E*u=lD$jf,TL"R eP*-Ʃ?єZ}w_s2P՜>@b-aǻTBP0ɷ 0(ܨDV$H97/LpTVM(I$H+~V2pl4`cqWo̊4U*U zk}}C6bCL]ԅ{PKf%]#ݠ VYT\TWy =QyFo%`v:rixq<׌OvbW}/R8ׂPTuO 4MZQ, ZGI$39wgGV 4=0J ݭT;.j"bܭv-<KsdM$QUp4AY Aq `clrbJɰRBbE&2ziP+_V7Š)D*q$/AQBˠ%[ @fߦH$`\Q2EIkEKv#4%B[L=Uz;_C-!̀vJ:>*}* ආHU?mBڡ)6n'bHB-5eK/7v4Ux4Piڟx&(#kA\TYqƣCK[ 5i%ƮTB*T+7ÃW0f;iKa#!] B2LU!:\\҃YeӪR)(4%,6ota֋f(,c5AxQ=h;׬`s{W6]zC-BG 1ZusH )S֭%m*C)j 9>}Ah>)ЀtGEӵP3Ÿ-0k:b9%y?֨۱$_nn5y-[pW6alΔZ˙mݫ;n+ɮ}M)Vͳ鳸GrFWX/[#zPPqZy&c.p,,e*aXe$eEP@$m:K@BXĞCK0rv}8RD90LOv+ds Kt4d7]{G*Ұ )7$X Y$&`qa;hMn渊d&"o3.TfX(Dhq}1{j+:Nvtx_ wxtTݶcjoUJWFpƧXrfD]zD3gKTҊn_.Y`I#= „>&MVZSQc_ʜ`nܕ*^qǿ<&P\eUYV:X9B$܄ljzc.U23}PI;}!Ϻ2NJed1"ÄdBdA\o|q8Pf0-aLj5*biD'-uDnҼNV ŕb`QVI~. Q X@ l]eLId+ :Չ1ߎ0178~2Ci)"Nt*-@lɦ4@W0՝^7|YsbRR">auFK~͞ڍ cv_zUU< `u#N( 05D&2up9Lz Au-4 DQ.%XWp޵?9!ZqQ+zA;e p,sZ 3*KE(-#/"dY(~撷S"CMD A45xZ~D:3O#/3a,Z dkw(  H3HWvͦATcB_R[G>Rq}xLabYXS>|()Ldcdm=8 xc Ҝx*cL_UYL@c^QT2av(yb)UL ch=Ĝ8v۸}*t UME4DzЁH>6*江n9;;.<\ZNE5V.GXᳬ* 5^|6%⥠ŌM/9ݑ`U i jRfИ?iEqlg΄}"")qYU >t!0 he7F9*DB}&O1Rp[Z>CM,8F\^L/1qŞ2ih^0aɹRF"ZXya|!H/4Y՛jفmY e{tnctԜ5ϧ:?UP堲b.zNs|TVx>}^g֌trC{ñrC RU p h3$3N =K`h>C3UivK6E$;|lG0D5; ȮV$pD ;PQV hy☚!paj-Bf@h!oAg |T85T(<O.gfө~ [_'ofL{IzH\VwP`>*pcmQXӨѸ9I޸f$$MҼXpv6K$]Hbޑ.ř e;;//g_} `5ֱl0@kևqytY\|:֛ZqRM4+Sb6(5 @)^[#5\ F.n)\{Y]R]P(1ҩI#"5a 8Y%1hnMQU@\ݩ#۔7?q/ "fҙ0"x%$Rh%fkr1jur.mB!uk} FNa&KÑB!Bv:O'h+F&=^!uMD”F#l$0.Nz!0/  B`("j aEQQM\A*+{Bfgj_Y ! 4Q]5SU$M J;΍Pim%zzMpay+DiD P{$P# .U," G]AeE J*.bATH$Ŏ߅LU èIJld=\3z .LQLQ+xI[DT/gb\QTUeTZxs2{H>_OZ DWLKUI`sX!tQDTSei<}{iBuR!uELSLģ*U]Yh}tpR/(T[>.F >Oy 1;=o;%deLڰ{cW4"*뛚ɱvcϷvS ϏLYQVi8lS7*yM7TLW$▂0c/7vdu,{nr "(jztɫ-ۗ7R6Xғ!D܍.!{;7v.|7Ǔ=ɬDU.(b_vc:\8v iDav@]^k֙C"hċ^ + )UөN7FQ#)]<\Iό.[ fG*` P|ieT`H~ʩn* 7;%g%Ͳ,6qנ"4XA[kUqsA W E|-2Eаx~F)uQ^$E1XpQ]FDY4o41 5w1jӘPUw@P@@P . u<_kǜ(gZ+V l[-" {),&e 4GJ3#B!˹iY9niL A&5K}~_Gu8:6jX -k ćj (Ff *`❔i\YU#,&5^vXp϶.eEBDNl'NxE6`Jŷ0eXA;<ӶȄրҿJ^D]cMDݎnwDG-]$Wvr6),Kq'pp6,B͗DA4KJO ]>|i-%͗ǚʭLxؾnr`h/$K`4W$s*f椐xV3_F?FkwLa >_'v`gag>~c z9!SecV˨duūӟA_6^/x\ ]A$CS;aL^#j+3f &;6׮VXQׇ`eit0Bte\ʂL8-.$^r^N ^%H}+Quҙupavʍyc1hhN y{*5+m*CIj/ۦSo M&5kFy!_:s&!<{`Ge'izj~FQ~f<=6cW@&-%L^lfB.& -6 g1|^Oi:F19W oӱd/'Kga.3Hjpxr͏.1,^S1tJ7ҴzHj $0K x%IȆ0E%b 8?/o:ˣwOqaӶ1~s>iKB MgÎNҼ 7) S_O`omsЀ@$ ݘFв@`s-H zMwd"RIЄZ@ ,vuzFڈDCZSX,#-IМ^XFG̰ﴛps(g{-Sc6w.tN &ϼҨtw` F!pD5ib`wiM(#`hQXua$;Bb1 Z|FvhKJjZC`aKpS\%+dzz` bђEbz0蹿-$p/h@ `lZX6k?ߏucD}"\I'P}645خ n!+tJNmM)Ze0qW'P"pIjn]>;FUB-WbJK />B0\Ay4]Q*-\QK;>v}^f6Fio@p4*Шc/l ld}idu;YBCȔ:K{Ml-3v-׸eP\V2Un\ZiFd{Ladl5ؐ$K%ӹEH1 &JiB*Sќ bKS8'nz_ ˝o{b&g\k_\'p/kNKW\^$BD+eL$k$K7\q@-l"9^M(iˠ|lK ƏF2QYD(PHh'+ѬouW^|=_i Z ZmUd77]*!@M HV2!^f)d+U9#Mi6YV^vIΏf G1+"0h @J0^i5#6S4,\ԓd5c5qٍL&|s#m j^bmV4(T[hP)lwT-!|N=@0`~>`T BN&:? wNϏwo]9XVUžvG2Ui>Ti3]hDS>|1㋤{%dIS+QZ),5. i+Bl D@c0cF8|qyG:Ifch'Klv^Y)eP61)WQ!F)u7شzrNX5÷ly껚X R)1ZjRiYjPV ӿ-3/qd~ Cp@R)b\P®\#-OiZV n FMd |4mTcNxLP8eHe`% HåNݘàF! v%䍼\N`UA,b礪E,y2)+o :Nn'DFH qI”@ŀŮX~."WXh(7ZV?Krzp!Snv?#Q~ROc)F|8MMԉUƺ2oJcf(A"Z+\*16`'d j% 5!DjLYXg&Ӭ/Bti .!$SLDS8s5,¶-pDYOVÃXat*>:'@PkD[dS=ÃG 9nxM(F$0\4QzC)2I+O<gy mw6[r%OsՍq"d;""MDAG ic$ebdaaٷX_#R觅WPt>ܨ(Q1E0SxE[O1xN;O?!I0c_%1xQv#Uvy7y.DEr B'C7@ ǨLw:ч)L*䁒Sp\6n0<.EHKF"1RJ".NwеOHjP 0kR b-Q$":e?L(70D/pR?,F+0b5W4"jH9 FZ#AtIgWWMu\N%/߲U"@蹠Hc"kc^vÕ p25##C,ҦS"&L!R U Et2*6CXŒ+ajgޏ c%F+5^o L5"UQkF^^AwBwZ ْ'/I2O`tp0{ɖI]mQt0_9 c"5O$v0P'A#QK93%VFMvlsZg'4+Eipя3[eH K-bYD5RzAn+N%ڢ`h7ck ,b`_H0Bi׈)91iƒ~4NF5T'&q5hwsV0d@m*h50অT (XVnT>E=EQrÂ%%"ެnI 1g2j] p8c;Q4tiNlfLȍI9㙸LJ}sEcdj@!X7 @ 45 zD,7ʲ˷c4Vj-5Eс#r]s@1JS ,V_cU=[IZ!*UTa=i<?X; s'Yٷ[vE1JmATX `BrVQWL!2J<4e" w`lDp5޾1i$Oӆ̓E|)8FMuIpRP,DщgAm]/ ^_Z* SP[0(ʢ, cS׼V_$U4%[f 5w~l&h|^>#oB D^oEȉ۷iSŠ"DlTC">吷Hm:0WlNQR̗6gЇ?!%::D4Qi;Rn)ٽIX\;. r.0h~|6&@xg2JsZSSDDƴ21,Qmv,UA&DЬPzP \Ct U-K$HI I{jiUpMHx]?W@Ŋ|y *T es 㹟FR@/DSa'15]5ӮXvl2u2S% I79 \Uqj.yu4VX]Q$LWz+a3|vx01)zLYUez<҃1 "ix \UjJҖOJ_gͤ,JӮLUtUPyHfXa͛B۾VM) +K%IRql- soS]HgRej1k8"3MQL@32oojUhu^K!V4߸sRn x쿮`;Wlσ;]=^|v& P+>{ $@9+]ğN)i> hF8)m;GQiS' I:h; A{hBvjZ7IB ϠT%EL A~\GHiT)^ @iSF*'K҈.=L]ͽ[ꁓFtX;fqi!`ЪDT7 pP/fy< /c>>“C qì bJ}0f.b@aD.V[foC@`xUj! "dD<;,QS;ఋ+5|Upm혍[MG"~["T]t@3g@cs5GFŠ%?IHDDڅ\\qaLWd@(p(nH▥U\_x sItfT_lpd񵿻*ӷI D,iD"nQ(U^^)i4т5g %OGOx>2 :ObLR Zxa~pwvR%%N-Wc>6j)-]baD oX^vFՠ9nh>~&0NwS ֆIGOO!gؐ1V퍒O."31(^iW*\C>󬎴6]OggS@s4﹦0c0"! "$&{  '%&}"%!$(%$^CNӭ;?$HhmP\ϙOL$128vZTt9.Cb;aY4.PVnjTm@*P~1#f.p+:z ߫sv"T1ƛ~һ.AJk6Y!T?d9hnɖQ 2&LX&f˨1  Mwқ] +^%WyuzChl!FjXT}Qf!wɵϲ+!2ø!Ys4jHckS[% sy#^r!j LvMn8E+K>":1w)q!'QL9vJ- 5WE ԨD%̾7fp8I$V ek=Y3z}: j]B wLadr %X G6ќ L]-LM 1 NVsK晝 qdY[4]Iq6D$uq !>(5 o48reC&~NɦqlIOʟz!ɟ nPX95RZC({P8/zGC4{&dd:sݹf>'#$a@G49q{dn%|hvphڸ:hZԮwnpO~lS&6 (*Y+kXnV;,9m  9B$DSUj$$S볭~{'ınt_]ATWt++r2_Ilݕ"2KI꾎DiG?m?Ew0j}Am~]XXob(?>! cD1.E$>^/B@"4o/Kz3H㺘1MNHJG -IsjF%]CVةþ;X7Xp37&X?:yelŠi-aNAH R'J^ݞzVA"v{DӮSJ,i4"([[hV0}P3P(Y ]$1إ`v2; `TxZR]`\u.IJ6=8M`-N<@%t"20,DŽ9 gYH6T[ ;O/c$gdL d_xC (tUhHjDG5$P\`v ML[)k ˜:˼ӟ|Dx$/Ĩ t_`o:=!xWҐ+eULٌ)ki̘< knKHxrDU hjƓbM{H5CHME,,M4& kQwsaY(5P$E_4MtZW)ѳVfnǃ{ލRGy*Tai5F"5i.F8ڞkCz4ڳ}& LcW$@ ,:FkQF1z&to^v8?6|Fd-'(i'|9Mk8,b+"NH*I*Pb?pEgw~6՘rN}b} y6t\{|=dmʧ&< ^6F2I-kLpv'i6%q)ĭeZ➞o{p; sN<v8L@B5p -}pi.+U=+4G$t JJ.Uɣ|t;sMm 2Z?QBBLJ0rxr6q6lc6aiPen8l>T+d\'[%sGnwwdc}l,s@,yf!k2̯deWz"r~q>\\tۣԃ:;&K@4~ӊUVP$70_/yWIѨϛ0WJѼ84GɯqU_Su?J9=R:|()0u:DMM.ڭ8X5^T>[nN-0̎5 ?*taPV)xsv|ʩ͔틻 ]l]%ݿH+bkDt=ۘن*`T PDMMk!_X#q?HHa2 *^6VJ_ڧq9-j6~JDdӘ^zXYOIfe$㎆nyat\v`Fi/>Wlؕ2%o)KW,WXI=&A YA /5Yd:AEW >.,[/Z:xNTiDH:dl&lf?˳l-J;Y\`c,-@dw*4(alrUO|:{3R?2/zHՍ?K챤nE:`SgAE7=SB؄E圫<0(02r32%zah:u\섓CR_L&4I1t;R&Rx[7hOzd\xL4*)W=$-a`Rɍ.#PXJ ] b4g9D)-tN d\vITn#)&vfSut/^^Pk75 \: c &-Ư3 t(+ *Xu\*+OggS4﹦0 0"$"!" &('  ##z!!!$"ˡ$ ܠL37l6ǔ'b=WPî*Rx24 h/YOƪBR/Σ{+쪂ZJ$, aI9=H ݍ  :R?=m7 윞&ptq-^|0GhXj A5= ~ X9%ȞEF%A?DFV IZR|v=ꊪX|L\+Fw6 '((V,(-T>i^)jE::.{@ =̢ @ Yjޠ8*pX5ȋpgGB i.Q#|,4 5(DUSJe xw8EZ'ѽJTaat9kn:=BzU9 ^uddFỲiԵʪ|$g!mU4S⣩Fws7֠+/Z5D*d_w):?shnn\_,i[ڗ9؛u^;ެwnUwDcL%1&E88)ѐs}3GV[ա[}?uZ[Vt{{Fm969?A麠9T!53x)!#Hg. :aH*P A "ǑU FQ;#.ֱ Ey(k6? *+cn= > ьXXOC<sa2(hLtQӈIK5qOeN>Y_GYzKmކHSF&W-4 we r(?-7`.Z5xNLխ]*h $1̾}0F^yH o) â,PO7 'h[YY9R*/ՑLUi?Y FK U&LKLp"Prj> W\!Qm/+>L)%רuqϑD\s.W6ݚ]홠Tco-'|֕M< %_/52Fm7fP)B%6@DYUVHuF+,7{hV\pLYS10sșj^T_)w4E#7KLWUaUAUNvQ$m)u&s@ ഫOODdtRbYL7'kfGX"Repmtc;m|<çO>ۥAb^RȸGAD1&%!1-IMkpӾdm/ =D)N2N3V n=]9hk:|bc}ޤ!ڙ@@!pIѧbp xMlCU>ۭ*rLQ=DLvkƓ*A(\3q (@(B5ePͶnk?^&JV'qT뼉#*~߿K w,)H4 nPH@ >r/Px t\JB !]0` !$!dY}m:iI_r+߱QV*dY}WV[{ˆ%)kzoLT klP!yMԬ|O #=[Rxk647<dadc0 ^d9x" 1v+^F= 0_F(ZVa&ps/YFM,kteA B|&UD,YA3+ pX?~\rK`{H_n}q老pl8AUFj\8)D8[lnM|-6xm<؏MavfԐv_MSBmS;mTo}]gZUbN"(\~kb C/ ZA@NNahUI_]}bt頎v'6#fZ \:2RXBh0jh(3v+ɿ+5wS6{2?e_ýR-a!UڌzQ@A dw;B{.lU@&0_Yd`v%SY*4iϿӉOX(ҏk1JZ}MS+[>m::L 3!UG84J-r9ӍINzڜ3rpn~np۟`5Zy=+`MHJ[kZXjRn=E{\'rs”/6ߔrd{0m0da|՗m8u\ If{T~G.6cXK84:g?iN+l<; nh_jujLshn]ec +6rS ޜˤ_9%Ksa?(,aGKMM7X44`KA댐$I 9F-\Br= t8u7KXЪisfٕ$FZ&F˲1’O0l !r# ~)BdN 9xpJȘs.[W?Xney5pe9TDE5R?kR_ ,t4=tI͹v4m=[Bû1}hSczmz_wLgĵkgaj%ؕ[rK(iERk>*K&R:TUD@&>?JgT_{nXܺ9+!LqqS?mf[y/'s~.{1&1'zRNC"}j@(QxҬ/gAB7Oߛd^{C%%X -ºuKILS҈+K?k⿼*꺒10HKOxfwɪG;WG$In*m٧)^b-Gjˢ\ȗ寇FuqKJq~0%Ǹ5 l<6 Ue1Ebm]eJcv2HDԉNOX,Ep=Wpµ0umwd@]P VT%Q,1a: #E&șICY`, Kn'[a~|6I@IHehxe"$=l&Ax^«H(A<K3"Ufg"2$r7'uzz+زFH6,U̫DJ`.TP j%ʌU"U*5Ơ7tKD%%{Ʒw8o;5eZhp6& 2`(Fe.1/gmW˜{; !ܴ!%B7^:?CV&QĢj"X͆}]rFXYUVݺm'_7A [/jlj*!ZMӟV.-tuаk,j09vܴw9>(R]rdZWLS0 <#ú \-6&O^I7U/(nMM50\O8EbyjڳQv B i^-)HeIt@a`ֺ;&,?"ʆ2HQ$b Qp uKB4S@̬~k<~v0j)DUsEfC<\S0IQ%TWÃЀPz )~՜a4SdI~>6`^LbJQD z*x#mlUyj*uwDnXݮ{,oчvq'ăgKrHaQɳdZ-p_+N5c1!#ST4J1ˌ8X H؏ A HՉ mv[S8!b"+ .#|jc)0Ún֠9*ӏ&I5i'fs`BǍ󿋡ځ"bV9/R)e7dUJlF)n!|FX5Wx8H4"zv 5wZ F3+l/lBPO0:Х$ l7m2NWZe{pJP% \Oǩ9n܈(:Xj5~t-[J%5BH|v)VF"^2ywELD /g.Sͧ{2ٝŷ6"r_~0+( xJ*>H@IARwUO~܀Q7^m>PQ!nSC?@ |C <0%L)ӑ/bn)wh&..5jbjX"z \'A@93D I S"v+ݞP*,1!{`U"5 BFdyaC$Ӯ?93e@I4(ȷ諌{uxqP'5(*B >d**AM7xnJ)Ք0VݵbeF1#%mքwnG ެ"p׼@00sy&ɓ5$woOhfw^1;8^Eil $4X(JOD Բr9UA @dWt1#Ěa,U! #UA1-uJFFBz`N⢕%)&eCñH7a>۷1Upt&* RCY 듻tVBTѧh@D@ 1P+GE96   Ӱ:iZe ,|}ڿAqf0&EOO0 +j(oo&w䋪V:!LjP>j K}i09JP$K(Y7]UkFj2 DrsT UAE);Dd#GO_VgFb:;{(jR,KU.<9.nGޜ?U7v%J,MGԎCͫ?vO~bn) 5PT8'Z@mja<{OW$HȖhTSuD)-KȝXgW <Ӊ㞢zO'[(WQ<߁?e4!LdS8<͊W۽I}7 Dgʧ,!s_.tSxVdg" b<(3)5Um=>ϖ(:,fgR p0,f=ˈ,G"c~$2ڂCUR P}}7͑=J\ZS2vcy7\#rܩ*άbfo;s0{|Crs۩o~j9& ;~{>08X:6DFCFy@<>ކz8]m Y?ش NTBL$:qvPu*^,gO?:jjbp<]EM2?Hs5QDY!U&HhM%!I'  T=⯝ۦ!%)p+ւ kH`4^lw AȂK4rRC\EL2Y|郖B]IF cg$gBq(e5 XRU @0@bU&D &0ֱ,hIgT,%D[џ^,I SV5SoNI"s}ּj3$XxD4Ƈg3:&'yzUpr)Σs0`Do#-@B?H\[FJ:)0b}Xf6ap.wMTW ӧJQz\?5) ]ǖ(LU تvCb^ |5ŌF-R|;%C~\gYp?I nI ɋB6ރNԪq: Ɠg&NB $- C )`ˈLQDY{UFZH@YQz8+AĞL=¯Y|zG!\e'ewX%m !fB2XP, vRGq L0hu%1@;xI>l>& "(7lf>7 F<&s'*g1<52&F\kN\5L 1BsJHsJ8*M_x>E-R?El'A, KF><6>@;ۣ3t W L%)}:peڶazѵNy§w}US>,Ji,d+*8_I|]IEZEXpHZEv{ֱm@X$~4Nom`Pt|n i4r*(lxݞv;I<ǏKH BTR_Uա3ʬ[t4ꠗ7GiW K)8}+" Ka (2D.n<ӂg꩓}]T\R:T2BXUDO䟧Lе@F7889͢HE0<͇2LW!Zt@x3ݻ51Ɨ}]7\4biU,sl,T%A(wEIYZײ&|Q.#%Ðj"=agwJj#l;<Heѫl m\y- )c"(86jغS"|,gS i`2o7EId[/˓lH2JWXan4#ppW|T}k#m_&IHggy@}H1sz>LVF/F BFt)1|vE6&|hS$/ F#Z2- y;xF.vXĸlBWn0m-B{1@BUdqN9p&+yι׼B17B$܍sܽۻ-7Wp0[3R+G6aq%Q =~fENx^A-%/OIrS bvi->{s}{f o-7L6`%ɗ3]jWwy6JlD/FuϏano8˖^:W%:SKJw#Vh l[Q ( Z3 pEeIK5caz1e+ȖNypn66ԓG`IR"K6x>k4(톦JV3Y5Hй^MDZacv؅H>nz ^\qd[:/>]馑K3w] `dh)Л#Gg&^@UV~EURPK7N>Lj4$snt\| Um!}+R|}͞<-5NfMF^Iv6u:c,9:qs5x%[bAC >K&h/S$Z1 Pӳ[DM=}q 䊪nx.NrLljC8HrVN?,v+MNu"t++Ox 2ЀjfR0ZnXg(B| Ni\.׳{z50zH,Vs`XQ4qEYkR_[ඒ,('|n {DEMB O'(ߩ$#|^uii UgUKtHPCKNBd:@i 7"yXvZP*#c ¢`J6kL'g0Œu*0}BȈjOξ8؁E]r š1̦G[rGqj4ƺ$dah0j}b}J,{^ (,В.AV %S#H^Xޏ ++(\]ؠZT%HR2 Hb LWL:#@&˖ĻۍTddUd vq sҞOAD~QDUS.+UYX">{?IUfdYauU(7p Ėu 5tgdv (u 1-/V3&^+ -1H SL |8l]+qЧQ[Eaɽtw櫂1bYh5uD(8*$s$24!8*BT;m ̷@\ezd#0F{}\+d<8N6On(H)E׈A6r+§ ;A3fXe/ h}1._مh=Ҥh^lNN;$76Pzi5?kK TDGEbeBC)) .T,bKj!P6[`@<ph cD=ҝw.w$rhvT#nDmو4@@^p "G]$EI +XO삮хؓىd+oݕ'"#;r»P bҧ]tvH϶R6NS%j!1^멯Tf_EE1F_X|)͉!DƤ \-S|#3P8ҥsNHVv P-'y.`?O' >ALz$MV,Ȣh#RRiӦqd9\PLS iL*ٓݱj5{א^TLUP]ʒTyF^LdVEJq)LT¹AK&.>X \v|L;S,T'SFFWBnDEw-ٽQ˾i]g\ (RF-Ea Y1TΖ>31R_7TEA=#f1Q͂OggS@5﹦0x7"" "*&'! #%!()%  $% %$# '($%~uZL3laM,P01eY52p\)$Ch$ /T0ҋf{{=HgF$$B`55I)2|,w Xc_Eb( B4MeӦz{~[XvGJo`a Ymi ,<۸#.e]8r6`lL>a0('$ĚK1nWJHzBE 3~˩`ibܘ-PSҰ J]T$1 XK*Jƽ;:T_ÐX8. ֹ (!{"#gXa7pyBZxR~U-, LO6O>+˹Ut(>*aU+ ~ _Q@lǁ"p]@ɡ.(Qă%R9AOɈaFEHEѥ7`ZwB咚137B@5dV@H|@po49`zi#X(dmJK ^nS+*^غ6AI.Wi"ʴ ErEy2Nf4[9,K1^gRu' c Y(V@T;bn 1RS:usbMQMu(>7dԞʶH.cD?聋X kR /Z7 bຠVrpOSYbU/0ʍIs3 GfSGW1WÈYa٨"9$HUsuq% od!. ߅T 8-0V}-Kr" 6Nk]KiBuZےjd3 ~R9_u&2y:DD4gnv4hn./6x/|Wi+HP, v BtE ڥ+"M$KT#taSQm++ߥ"Cq)u@B)4SJKU)0΃gہOlgK{"HIL^OS~֩Sn쵁QN%%K4KҸ&zHdi崫ǙWVULѸEc3kn }%(x -yiVLMwG2FϦ2lime-Uwa{1Ҩt킉 * !3d(=f^15 Ky|wUy6{'b(hFS5}'UnF8ԏr5Je9v8?'$cGNZt4ʕ_Qʷ VS kna,X1LpsaKP^$1ccQ;_.X0eR0Cت}Ma%1wߍ î9@ ЮCZd-$8/"a&~dAK0qUq#(TDSLvQU5Z~C"^}^<qL[?da,oQ惡) ިʌl/*zzLR:X".X`IyZ EeAXTEfbF5җO9qD'e3e1+!1OosRb1n ɳ 1e 2dѾsؔ%*YHrR>|qbެ f|VL6 %F/f.?‚݄)'XJL5!Ic6<,FјJ0``4!`X& p )TU<ѨFiSw$ v" ͊HAmfxQh-. 9d?I [~0bKԛPPDwOggS@`6﹦0V0}" !!&(|!"! '%%""!!#''~{&2! 4ZHF,Mgh20\رtq7vؠ(86ۦUgTPr4D @+'ƒ銭Zajx)XAt\[{Eq%Z LND||6Kzg씇B`ZbB绡:Z液_4ڱx7ݳ{1f~?m$ o{(^Iڴ1^T ud@3uCXʢ =8:@!dq۰ЈzS/7ŎkɎ[Ev్D,Y.|*laB5w*I}mmir?&Lv~)cnWƽ(LǝQ2%c)w-XZiy¥ zD!eX^\5&H~*4sZ_%N2:Zf-.:FKe![J"*ze.[9H:{?qJnyBjQ@SՒMߦmt_ZS9 eL $\7(w) V%h\NA @]P[vWQD VK(ف(f}>h4%\蒈Nm9( G Ofv3unjU I <*hH,R%EΡ,nX K24H_9vG~gi՟0GD[mo{sMVͭ2ҹzkXEu<vZ圷d; f۸ċITIDObvqN_r[ ^nhiY$YlNYUiG-!OG cXV$L[*KM2٘QJ,_l ]T6œ[fMiOʥSk>Q)<[>SL/I {5ޅɅ;.)1T,[U54Wt x@|d,sTl|L[Lі܅EXb˴LiA4D]2F8Ywm"+UpO*]>>]w#Dc8{QvӸ(M^wryo ںc%J`ukA="ZE.ŇH狞$IaHqJSz]{,fIJvΐʪV˪)^c*?G+,YDWvV"`0$)+L"Q\qrO+iZngàf\o8M} X(|bo/B m;lOTfvA`\P2ĜOv_ЉJb*,U.8NJ[n'zcd.E(" # DƍHU^|.nΪ`=NKS 2 v\JSJDE! pYf Z4Q2[houؗT[7! fy P"2h5HV2/H(9+ܡp݈ n,*l.3Sqwtc?M8X9QL?`kn0ʠX@-U,2$,ƃJ8Ŏyt{-hk Z( <Дè n2X7G?UJPK5GLLOf6ZFQ@N&f:4jnOAqZv7 , %@QL;àJJ&KnܒCC=UPs0Jbq^Fн })Q @ X 9KRE/?Q\BԷՅiqCc}.KT!mah0x"H@ UU;Hzlm*RGA*A}Ij[T[D!ߖ5ydDڝ,SХNGRRHSU!L,ϣațjr9ݼi̢3@uxKtrKYM fsZ9%i\P ^WEք{8(kEPIU>+SG^cW*/Ah<<+'"%q Y#_2>"Vb/fp4"f4"է)ݲ­n@* }h&)ZTK%oX6Ƣܻ|B0 !CxP;F=8 . %>?UzX-_ϮP?ԗ7{k_yls@5[৛wo^HMڌ>e1dS%ם\vD5Ґ?,T4Xߐ@?PSs1>@d/]Oj!,Ƌ}@&RKTgUY!D3W]fxprs[ k-ѐ,p٭{!Y`,V(#(Gf-Δ"EAn07ld/$.p4\*&W+PE1:V;:Ϛ;B MÊ79Rp6׃c 5^k/[c6QpS]+E(Rp5s^$/7"r9 ~6u2ܮaE \]MYeM׉5xV2Nz)"uA $S'SlLWϟ~wx%.Fo)Cn d_=Wג I]n[1lk1^!'8V1+dIJOPf";t-\kٺ']uhFbe&WQ$6z5?N1Z0"SYd)2'FUIqX m uTE)Ѥ\Tݘbw&O!'uJq=ȝ#_ *hͩ:8b.7P'ȰɠAQ9؎*wM`, po^NUXIVkWC)gM3lj#hnDjK4f1o?2aX,9#I\8'F @ 8RfXwHkJ U+ cN "KDޜֱ5D= tiVhU!gJ@I) (;Z1L]JQH^`OggS6﹦0pf4 $"$!! !#$"!!!%(%#$!#$!"!&%nQq-[k.)ثO~tXHiáH#XЭqZvig`.`S͒]g@"PVp/T0*Tԁ 1 (bTW҆)6-L3Ŭf_P#5MhˎhWO;-H#%U'm~|6.[ pϱ  ӢSLDQԌ9i'E;yf gLtk^ [W]Ҭ| K8wzq GHʄ2Ei;IܠF_nΫPBEyvd Tv{Ʈ. dB!hN @(~YFQQ쌣MZU?4@fg{|S-tAx \~hu, s"([Q~h5_qN˅o}J-KQ k܅9cTY˝qHC@LUeЪhN==E<[KWQ%DUeBSUNKQF&F!(DUeҧȡ9u<,y^IJb^5mz Qi**TUtUo`b9wuJQg#d]daQyx QT7u?䎥)lgavֻgj|$ă![r(3u%/lUZB@ PT(QJĐH^NNkFθap-sSUȉFd'Mȋrf."xx/h谩gnwr` 궙p A]sJBz1>l.>u\pA asIZIX!iT>rjk1u,6#sݜ:5qu`,!!ml|G0$HԄb%u iI\qA]l TvkmF/ӭYe3! Vʲx>?EdDZߘF'XH&,cfI- Z}m#QI #ڨ8ohLe2 |稵tWo[W7q4N#0ba95.ůoV+!o ڻ,5LwDo6 .m6s#> av 3Zaݚf_B*'y$a5:+V0+^'Ѹ|mnRn(#*#yb LMCN#xc\ l9jɛ3Ð7'w?`TҿF0ñ)sZP616IDDpPeGWkthf0frc$&@1>{gK}ƛ~8 lmLd_>Kw44\ dg| *ge>leNRh  [.XLਂPi.mh%c&;ۯVY 8JBmqqzK+iKUnJzePaH2@8-ii9(Y.II[oY]%]XhKӦlm))k^9d~NnzW8#P;j.t{Y68v~9ϮOI|:z7W(m+ez/\UZMEAaQJ^+Msv&3w+D9oӮ\zʜp*:8;{}76)߻y'vt\ -XIK5<3DIԴ0BRyuܩIdUi"E(aQ,[3OKRnYJOBray-ٚbu,KQ[tDhHVوxֱt֦ r-pWU]l?_턜$3 iMhr1_8HKXHˍBn]e4ݬ[!n2$2oCHu>ay1G/xI% Y+d XIbH JGE@({iJUEd3~2(cO$cuˈ.ڠrUbI|w]yo?v70wty=^sNfD(C~4ԾҩW9 "Btb6Ij+Ckc )B LSMԢǻ<\7۝~#FɨeO9V ӱ%OAtvC4MO<_9҃bì+1TDfA}ͫŭՃvuK?5h˽W2dD*k837-xPhVaؔLgBY#CZ `}8>Cw~}ԧɌD$QڀU;OQ]}&õVqԜ݆7]I)eCHbN3^KJ>j*UHg9q|3OggS7﹦0,1s3  ##$%"" $(&&}}$$ "!*'&$>ncZ4p0@Z,EOrAgISJS6͟on^[ZN5Hcjܟ*w͐4 =kX@![ՓvChx!!mZ:ZF,btyrXG" (>v'1FK* c!Z8zi[%":'R]:8;a9%6IKᣱCFxdqy?"hDvY܈:_12j׈6 u 4s%>BLtcyU 7҃LpMb+*p",66cڬ+cr'@&:a.1Bfi),]#HIŋH,[oTR})݃ca[LG"bSq)V "Md(!+jR5Rͤ1Ț):CVӤp)H!(n5 Vv"#c*TWe*ri+YƃRnhu*!Y TY *fdYV8Kb-TYt+kxE&xmk=ɕmRJZ\Ykhq퉃 霧>Ji^ڲ" zeW,k diy { 8X Y$tbl Eݍt˾6 bwZШɢ;1F`O)jeJÞ8_7CL EUIƣ3ѮIl\5o]ndfy^8E'^8'eI9փFoA-uFQbYukrc,TlLc ˖|@Fnpʦ^;~d]9/CmvNJP~J)as|7]l`\uV [ͽ&ػqbqA}(uPcuh0v6ja ]cAE4KgHpݛܑj #]t*Dr-WR1DW xpjsbHkӤgVMm$D'[@(7YYn򚱊 T$ML5WְM?.eRU!<фϳkrs.WU # DUQuf|QBLWl' Dt:"{kk&YW)hqmnܿ4Rde`yˌ v?Vs6\gbU k=ו 5Bm.X_d꾶Z= -0c4 0_(QFzvg"!8f2v/l~8Ri@51|bKH F}=ww-;Pݑ5THa'OvcE_Dg +$ҒHVYXhHb~.S64]Rs?=MFtҜN^|eDn"1>cGQ =4pJH1=焽TX~pv/;ۮ韷B>Km+#>XxLa4T ) (<ɺH']*޼vuJ@]^*M\D/Iq&e,2Ic8.~Ȯ{mDsg] p,XgV*cê[- [ w6X)H#RN(FX<6nöUV޼.$ xJ50. cϻNFP 4Vq0]4@Ks;#5Nojf 5*r2X$6+KEY^Vw&"FZc)N_x \2+9gfV1s,N[e?:JB00{Ɖ 0AR<~"|[BU{6ș}Ԭ@#!O~S unN``D'lN·ͳ68dld|ڔR<CGEAbI@$bJ- rVby?N1:OϹ cn] &L\3ҌI=tdq T,\.L Tu1]iYUҧlSgs&O n>:DL}2DǮfKIt+Ƃgpjgb%rO(LTɗHn „"SMD*5\9| -TXѠP9j0/#[hLSIADrQX^qpq+<tbi')uC˷d Dbva{@5ҰSIRS"LYirJż>2ZTo5UDd#O6yCaoeeR{wYՌA%FDirL[3?>CE8bJi(DWӤ ^@$Jt W}DG=OS Ta ਋A{m7iMňhkR'hVFHP[ш LcL%0 V\GQ*API:GֺkАS/ZJ >2;uݳ:5H& Ė$@6d8JBo!޾! @Q"Ԯ~ JJ֔~ʠSQq.q|i8يf9Whb 4a21+Ȑ8)ĜnH|ROyBR>dBw },s}c[)n {+]* d&P f#DX y"]\} +FWPTYeUVNGy듎aP4Ҵ*TDWLOUBby^I#N P 4Wu(-Uu㪓`h^ʫCDTWtUUxz*2vNCΒTTW骊>&%-OggS7﹦01%"%%#%$&'%$!!" %&y !""(DWd#0ec8*xV.KZD[eVyVQ :ؽhS c2Tlg!uVhn<ɇBr8-ɾ 6-ғA"%}5LF%D9iҲ0 jݕc>G-ŹHay9-anei'KTȶ0 da!+)id4Zpne}-#>]2SОN7oVP;]Z낄&nFH' ,siPαi6:qvcØ+{cHɨ`غ H$WejoF YOP![Qh"Xp|n&2MO'qA¨Rq* FDF)SyfN˦-uS CI&+^9KA_HH;| n1ϺԎlM$nt^8t֛mK$K_vXBƀo[};e.+UODƢIIB~V;yogN57%7^U^ p"}]A.T/ &lT5>Dn  %"-%R4ij. ;@<%ۺj$ [L5LՉx74=rm}IOL沉\}[uDH.ph !o{( )T:OvL _=tAVXV*DA@xVM~ZM ( wjy}8CJMu2W֦);ius`k˱WE_tk}͆u<c( wI@q 7R,~|E@ pՑ@Bt(#?tL333u:/o9[[WQ&&4A]V#,4oАht|(JU@BiW5I>IX-VIWz`GM9&MBN 8:dC\ML[e:t0"5iI50\\]ܪ[0j\vEr |v$2NE@ tODD57IBJSɤ)vuGNat}`8^j$IU oҔqWu^32@I, R8޸晈E(ruSv**+D|.V[|#,77 xN²R!m"V͋2@D|y&[/=3 M`ªD M(@&:NjbRD\r%H׵A5x!Qa0.5I 0t늦Ai?b^Il<%#c2KMD!.'9^nB&$ Z4`ŸBQߜ 'ܠdb.(4.QfS-܈rvy⥰fy-?^Q]ҽ53Z #BvY <^ \)QE攕+i&r''uN2EsH€næL '+n M6YiRa>PnmXss2Ju7"- IHdTjz * #.h\\94">& z:JDF*s63i,tzqa~/1- S+u ;8'z5N+u4' 87ñ{D] e?t9n~'wqOggS@7﹦0"}1&&&uz!!!#"(&%$#%|  !$"lc=1LW]q,3vas|f\eSYYHIY9y_}C|N2l나Za> `m ֲ8`n*z_zf0 Lc5K`8\}XkWHG*GI뢕TM-/\h-77"bQ \ův.85 ""t~!{:s/sFjtM}Ô=CpC?֍s5X}kp@PI9DX>N"fv) >aQOD K:XO4w,;@dH Mm[wiGe MZU851hb|N;/!mWߪq5 aFmFۍ,k>Vr$H`QH^t @x۠1HZs%ri`Y1=ڹe;tLm\6#pIP|qLC!PBU*cQMCܱDx !p'2XjdN7[QA6ӮxQ <0$ȌE;.M.h|tGD+ m@*%2 T* ~Ndٱ SKT&G$;JtyCC6Kn 3_2[h-T& IFuqt4h*2 0ʈȌyzJLtnT(z-(2Hʊ Zs0B$Dto!cV]"}kkA0~:WGĈlQ;$?Qc :6R>AP1,Gh(&˛KCǹd2i> tHB=JV֑IJ5 r>-.@ oz=8,"UD4QgMɉ& Zk; %7| @@th 'kꦡ.+fH .jͱ.V$] $u BWA!‹V>@k~'""1uI$͘0JLx\ɣaz=7Cvlb&B  C١Hlu1 d(Bv/jαh˱]}n8D`_p:}C@ϏRًWZ)mFaN?oW{t("bElf)$e1`ʂz`{Mٞ^nIՓװ-wָe"zi[T]3Va5L}SDT]mnR]zϙxS蕛憦DW%@;扑rΡMCtEDk. s[ωz+TnPfD~Bi<֎\KS6\Ƕ4/ D?I/IU:J LcbDm6iIHNSǶ`TeJ Au@!sOeFnI#5|3Vݩ Z 0'RQˬSUnڑH|)x8r׽f{%$g 4 :^9r8 70 =sVG_L]H3EO-ݕ :O[=9_jEI܁thq8&GAt~mL؞_9IEbt 2ʒ}κPNtrb=z GGuut'K uBE) dHT'i@!9p'6(g"L ?k@h0ʸ xe,j!ތnus'9;gtqqxHu 16I0? Ho5S1;r`!d5 ArU T@)L,"Z[#"EC(joBFT)T({f>k̼D&E}>v&$"Q0x+jAH*Rq)StVF8C$UZ%=,/MUu㦘uaJeyrL+"&ʛr`ǖL"J ʄLWQ}#j:,._6Q mFچ#TW + hOr'tuB֭,>ܐD\]ë+ndk^&*a0Jd5JbPLW WW L[|Ȍdj+pCJ4Q *&&?}ͯ]Aj;RHu%LSLQ*vwPj1gd]!b֕E$쏠("%Lcd2=zDiyKaMͬO: R"1a+ AJ{ J(V^2d4cHiqvQv,MAh1m31!-EDÇ*q瀥o.DYI|'ps I H*X%lDrS1*^B\f6ݲ 3G]$q5:m% ũxU̞s/ޓ;pqCЍ{_cw)+\Iq揿쩙04>We뜍+ QMY+ݴU^U< SF,_4b\ "mEFNÛۖ?cy'~(1[2Ƥ̥2iP>+vvߖüO=q˦-/!Od'@dFBӔt집mQ´ R1!__{ #J*>le@L1V4e5?>J #my|`ngM jqЀGnۖ+G]1a?zᏨ8~-SXc<篽I+ Et;[UU6xT}BXs4a!`6,OggSM8﹦06%""!!"!&&{  ! &""~ #"%%&z}y#!"! +^!` 0ރ&Nb\%K!L]æ 㸌IWa\d12ll>" KÍ]yZQYǷ䭊Asߵ% ]J߽^"&@2r$$KxvIW},+"Y_=w=/( +V hzoh}P4 %k 5PLUUpՕR[HQۚˮ#ҢyYR,0@bXS 4 `FaY"F,EPn=>7tU4~r#>vDq4^8DhHxa|ӉRvUbl$ :ㆋG*!Y_$@-`V4kVnj'l3"Z)" DV$!찊JXƀ'$ 63w-؈4`0lsGQ aSu0׏?_-llcӒz%rdȄP+@``?X ]cu &^gl ׊jk`BK.6cٳDx-{Y"vs=2#TU \)?N+ȍno$$>,mBǮą^xN& @M~@ 7PDvmԋtY`LJPD(Fu)X ALae*c%ZOXf5L(~j* DY*K°lx]5LYc\vҸl[q 72 GW5Y:]W DYu+V@'lܨ0*@LSYU$>̓]r.Wq՚7*ILW)k quӳŎ^DWeuUV|s("Nñu7%da}W7&"__n6.S#v'\gda6hu2K>j}\uY+3:PD1gìx@?,*,b*'֡1kQΣ堦I0Kdș͗dLi OeUԬ;VZzTR:emÁ,5p1O!)0 L Anj9NƃPgpnKs`SQMޝN$o^ćy0}"B"Rr2YH:v/fG1$[ M)02($j&2IݣY\ :O.S5T,zFΌ&BPD^)c!^WHUoFq‰"ГﴮJz""xQHL[N0♞W^%+ ?2jFFBz#00d!xw v%4;GJ Y #" [/-YO S*CX8HD9iZ)aowU8m7f&ޱiQbTT`' J\`UDXsѽ-ҜV(XoLaQ8H rlL;=8;p҆/N&z)sd[A, 4|OAoġr߳NA-yLnCMn`TyiKؑ}yG֊ƭqSz3?P\aklMdM9xt3ub n'\Z Da(~˜Nv,k{A5ٯnV^/\@ 3]x )*QVJzߎCk8SHQjK0ko0Z;\u6e%O4èkgIzy0RM4<'wm[nGw1;؜6].G،f׷kH6;Ml} ٗkh"Ym5FVAɫOG""+OrC ܜᨱ)%َFcqED1͸7n!nqضq%62]Okyr~,B؍6vRDX[u>T jXxT 瘞(MVKsc`2Ylf@3.*$Q C XJT)G&FM"˓%9*WPb8>D۵9R'$"reFNEc00f.{iKFJ5\m@.mʢ=*#|MiLW7{uSkwϹUJb3Q@q8,dN8P4 4uz^CSX:i,wt0'[nFhh |I\%I,ܬp5$T0͍en(.דYqS, %A)(.AXG;HZU6|"Du0tivN-T${h4OxakR $ԋQD) hQ,n|66͑*7H6)W KRXP[$ֵ3+S p]ճDDivdJ'62X<^irkcCw~D( @ T#ckZKdRrPo:9) z@>KO̠h; - va0Q%^Zc,Lwgw?qrzԽNWPA`C j8{Ӑ2׳Ga-Sb<I!%sma ^k&Dd 6EP/8@dPʲW>Mq+O?%.yrqk;h(~mCD'5(*| vbW/iQGTf ȧ31E M Q0VEE!$("!Q ) wLcj}f nQ$I/HVP#D o}AsC!Ԭʪ[i }kT[Ayx E9bT:/㮇< |E=P4 8b:ˣhVe"MtT pBzXk˹eWb={:( &Y"0Xs~lNvq)AO9I9O@'\ K WJ)Ph;ߕ 9c%6KĢG[VXD mqw.'oca)4`I\ ,+0. /0Pn\J%70AXK;fZ, e'q(zJ`}a-M)q]lye.)"ؑ=s*rVHF®KViZKnh8E *8mXt\"ʺ@.Q.V%;"V"Zv*FnR\OoiX.$ܥzϽd*`0H "RlŔKJQ5HEݹf[1y)"ʊ+ 7D.W@  )P0=0@Bv4Sl(GS' {=-ŵLSIUu2*F2xFFKͫiWRq#edYsĺv>͞|T0{UtpٳKiB|.*A5Ř4q+ 2%,'9֧[nwPfP;I|/Z@ÈPR@@NIR ~4B |@E_ 'D%J:JPnSYknգxh^H,2z=Цj4I ^ٔShL=X{S| ٥]VR| I@0{6ӾQ=M>*QhYa. .+ڲMS}_a' F=zz!Z_1_(ѭWt20 0ee9e"7 H^xw(JX3HR,BJTẰp,=;gdx? ~Y}ji6\YdWȖD[vlN@& 3& R xО\j6;TK>z=B[, kRtsu5VȕίCd[>=4uu=Z{N'ݚ=3Ǝ\[Ɲ%9AF$#L(ޛE(A`4FAi"lsʻ?X1Fluˆf}h||J7DͦWe U@9C}xȌsc|dizْyccdz78O6ţpztC;41^Hb xLn#~)j~/e:QS7](b?|"Lu@58+2^|fݣ)v&h6W#ѕ:}"4H2-ʈNX+_1soӫ]inKꢿÞlQ}'|k8׽'-/@Ď4ҖHWID*JZ/<6S|xfSxh]ǔi`yڗxlFɆ؟Mh01n"|VQF%=wT1-1'uI͢(6Z%CZ6Jz0itiy#p_JRh^v;u%9d!-!,.!MJ" :m& rn$Z7a: %a8 UI"2{7O|7BnFhFI.*2DR*TphqՒҀQIc+_ 4hn23:ĘQt3diNHinc*, (MBOnONwH39k.c3FȎNJmev*.5 t_SܭA[X-[Lj%lfҁHdϋKU)!LNDGIdvm^d-S'_yNь'ȶdF@{`LXtb*5=7sŠ]E] i܅ 7pE(|6N7v &~GQ9uҽ+pUafQnH9&iuꩶv_[wC@곮j#q>>ǐn #qKZ2BYbV,  \=yQB7ތo -[r8i1^>%,Ҽ|0 d:Uӫ "]EDu-I 4aqIt|͟K9Be%\EeZ0o"~,֓ek](v@[ b(V*#"!Qjt2ʻaQэC#چq$H:;}WJ7%.`-tl[@5Iv$CswL ? ƬvQ~92#TV@~uPdpʽ K[T.X.$]$NKfmmR4k $)!uKw~]čcSNRJӳe곻(B|1TB\=ePc1tn NOggS9﹦0'pE6! !"&'$%#! #$"! #"(%&}"#"! !$%!QI;_XWZ8]ʖTŐZYqS+?zuz,f%ґ ,0~ErtdU`|RsQ걛F>麞钗&kӎKxlv1ΆQ;9)Xr+R)0:ԯ0@g ׽'wE(B)EB~+B? m5 W~~nHU[8@~QeW-!Yt4Q/nr02"V:n;~N] lP|̣Q8wׯƦS?)C(kRDóþ:c]/Vx Q/1}Ԁj0h)~ݮјnq F lEDe"S;1ElVZ.7zxQ[HpWƀd,&?\m|Ia YQMP0EiFBDg%Ns@Bn~ `iϴ&:r?Q"VAabZMKxZ"kΗm.i8ymD(M9rFP7Wo՘PB;U"ݣ%O?VRJ+A*Xx [d_!h );j*laqK I|9Ѧl:y #\ST[ȩR3@J?@."LQB!y1ƒsY/+=\DUtѕ^P%KhyrE_c)T[UWY:x gs\^t dg,8֖l-LE[rȾnh<[6V NcaYMB5YS PFY#5FſL1VhU ?Yk4:&Ǻɤ&4pZr]:4i$pP$M/fpe=^j=x;oH&;^=&sQb'@XE9:# >ns8C 7S!Ϊ5Ӻ?S"l^ܦ㙎%v'0uu5fplkl @I g}n3m-0 ӵw6䫪8*E"J.3D$>nK/AtkkSiWRJD"T56_ ?:a˽~TNOSv/{PV!-ae^7 JPF3ʢWD䉱$>úTvKP1<E(ܓCqa?S"M1C\4:W2:\|l^bZ]Sp~b&d JM5^ ͲaaxPN:Br7F0! uP,5->ETxkƒG >E\WVLYQ3G![ZiJrmƵCp[LX ` Z}.xұCiQ<4{)x̰<V&E(<ٞ>A@ %e׺J4тJfnx=O *? D[jO7Ãy"=uȟ')\a5w,( ]ͫh{lTҦH JeTeF".0kv':|%h 0`1+Nuoݰ/4RHaj4)u4h;YZ*̎ Ŷ 6b,X y?.Ahfk bγxsosMwGY|?:ow>n<&:W,'st̶ӱyg:ǣ!}>+J1Q >.-^Ҫh ӨTD<Κ&514.cgee*m%RMtc hgq0Hwʯhe~M//g)MYgk_ .c!\ĥ ?n *T% (@>vFY!;Z{'= V}R$1Be^B8ϐAF Kp {&7 N WVL VNOO$rXxur#[#5+6, p+BfnY\g ق FӺiөZ~Qҡi@` , F؈iQpOwIHS݇]8"i%OG4^4mv]N5` E<I"j$˱Eozt'WDZs>n nu(+:na, ]Ghc L.^\N!|pͬ6јtt(<(_rt A\vz OաԢ :ĕA9мuJk+z;%PĔ@T!èkŘKf4 &ں-xNVi8qn\L=^(vba<}CG E}@vdT0U@R}Z3%8qK it/) l\h+rTCq l^$Gd+;v%rYPK^ZU2a{6]aO5(-kSDKY.W =eSS(|2mymM{ Z, ś?=O@wo55Ez[;nkov?7.,PNeņlh3fӛ|U>ujvIf|p8ݘcw3NȝFUi&m4M  ccʊbwx1{g~߇G:췕9=Fm%{ 5Rz}jU>ܤO7+]+ \͠6Ff24JL>e:4;,FRo?ڜŝum)KiI;H$R5)h51%⭚5Q*7$%.FvTu5>+&YdljŊin9qy 4bzĎ y# 0ܸY'nVf}ڶa& vm}ϧ8@(ߧxR(vyrej{+κ\XJsҼ9 ɇ޳yֱ; ^*jқ0P.i)B o3`cpGddKĻ IrFb(q/,QehbX?83z_4_P=0\).7"4if?c,9lpPX"TW 7EE<سf`j"$~ ڰTgquFzZn1b/% 1Q o-3^ 7&<ݘp0 Q))VXn$?>Wݨ_ߎYd1.PjGLAA\.$j9(׾k4a&?ՄB|P5?A>Fe^N(@n,!.08%e?JIJ -ʌ 9T$g0ҘO3w% LJ7 Go4%̠DTV =5faȌj]F (&Wh+}6Qpל;V )}ݶ @F*ӄ W@h+Ro['!T[q 8Y'/ER\]뫡Ã@[:h&~FMk^L]eS`EO x"++ ])LYWln.gФͪDtōTS˪<|8!o4MiEm=G$Zde , ?i@;v ^SkrTad- I$`wRbTn5ʞQ [ LedRU`JIW/S Z E<Iө(C"(B!Ch/5X/Bh9#ڬx\tP-oR,?!hmIU*hFz [ TXmJ,Kus ژGb~ ^,Qԥ HnyYޜvub\"U%BPvU*4Q$I(rb!D5f;XzvvlQ4h;hO\d ]VHkAc*E`oK7kE`6+2Ԉ I*% n~6)ZL:xf[MF, [O4E891>w Rc$ #HĄ_p$[W4D dXAe1N4 }v|Z|Z<{TGq@"Q.9 )%590ii^ݰ5wˆvއA ,35cqT,&\ 9,g**l D "dW-aUS5F`&ieQ-$d]QBGyYaZ;RPGRL[qV$PDKަ B&8\W*adE ~c$ՙk" TWej lhvyS'5c%"\YqV٫cL~S6Or1J\a+Ujl!u,on;=qﶄ_תTetWY> X7]myXy cj 0=(0k +~*!YMwUӴhIUUچM.ZHSEC q0)./5_7w+JB 1‡u̷QZp#afxﺟtqc?0K"W.chӱ&H]'RQ 04S⹘j\Ge0+(AD$q'"w;Y p*}b MFbۛ$5-@^H#h@Br ^޼. p.2uڵb=HetlfNl\&㓅u#s{= 2A P'k İBAE _5"X >Hw\>{ hqٽbpyŔN،%LmҜvvZ6 +pB2qf]l t~q ^q'MaHcFa[-hPW֜*&DzU K_ } EqOggS9﹦0+S. #"#'%% %&#$"nSB_ !?NHgBryR!llCH!Ez װ4M?|AbI3 ` SUEة$JxSd#8 IP -]~* aIn{Y#;c M`;Y|zBeiG1k1[/[2G$7Իj`7Uv𰐵NTD7Es s* `hX P.$Ԁ%C>.vAkNkE`@jD9[9mƸaEXf iExZMwWn{rW_h)?9wOT΄GJ;M_j-d*gUd#$ʆ[QfpE iT] {x0ogG˲35,#ݪ <ׂMՂkdj*Ƴ?=}w bKITݕI ٥ܻt!=Y4b"n! ^;c f#R;2\A4ׂO6Ã<.$M&rR TUj8@r=]Ў)F lRDB~(Uɗ= O)[V:sq T_2.& Ѷp=oP3טt귛)DcL 0:%I &/ʔTfaR[L [sw0CfB6)!, z18yً;[z_byqVGӱ)f1ޮdt*q `C4Q!bjٵ.b-4- GܡԢ0U!<^#F P\N`6,sT)%ڬ ݐ\>g(>j71k&ڣ E-:<,Q+>׳?iK{vϟ/@K W"dj:"X$^ˈ >QO(QiFElH۱Xuᐻ4$*Bb%g}!@ 㺶Qe|Rq,[综Vb7${]4U½@vH,KwYXhwEGnT8/ 7 4he`?O[k+ѫtJt*0{~N)klʵ9K.=HjOp y=EZ30.PPW)%08NGj!̚z;U$DT)(T"^gDSNU*4ӖOK|2:ú l(LUU@WVHH6z4-ҨJ TSUxrHsmuB(LQ WW33y fZm1*LSLifd+<4J LWtW V%A0oWͧ0v&5I"d]a%>׊ VFݖɿ1vlcm hjWB9G݃*;z؛)ns]N5Q/mZ"E?ivdeK9 t4.ius7Agi'9S$; ]M1c%i("?%}ՁEsȗPC7 iUL z5s/D& 0^ ;LV)U8yKVs"i' ~BMD,!^ .cY&fj k`9V\h4&h&IKtŹM/6kuBt.(i VUT0ÙPs#Aa:{aPH+^۪;z5 Zn- p_+?.=, # VDH+JQ%Ŗ#H|N=&9`u:ĢJ,Xzf$i1&K%3|ό\[YIϣjLd@3M & B@d0OFyxBFŘJB+ B\ߒ+es+$#OdF5gE+Zb~zwk)(Bɒe+$B_r֞8~?: x1"-w[ W lt@UA _Z9da2i ] zpȩL[ VP6yZhHۢ 1G\W*L\y)늩,E\U*r YC/̯hTUqjlHp1^$s'[2fh\WPLʶy0qDGi;j%Q%dYuk3e3KoH o91ܨT]K-sw!G(7/M}ü~l_$*YE#3FwėeF wfz%Z1LRF-eiP,W w8sZdž}L QRۚԢ.^KbC]{s ;D q&M=b]_~cnt~ڴҳݛlǺ)bCEq^cR5B,)fy~!EZ^\΁aRcvi׵R6jѲ,E:;0N^Xl4"ȌYJZ2d9>;V; Jv8̦T4A`'w΁F {kC1ܩ썥;h}j)u\{2up Z5MZjRFGBPv5k76!s.)ʔ'4=ε65Mv{oUJٖٶeg߅ދQ(f(pPZӡJ7I'NؒΧ((2Vuvz1fҰh +I@$b%yo!ot>Nja#S"ø%fs~4<% v[;Íi~ BP(ZFj]j XLleE8@zA5 > p_#_`Nĸ$my438'̩5=nqI5;4S5Ͻk^]s2PQj2fj6~:nœņ\4;pGpKCg0!ޘJ %Z H9܌c >WN=ӡ*ŕ逑cp, I4(b8qȺ+$[rJRf, uv_˺A'X*?=U1"F Kmˑ{Ӻo^Ӌ}Ii"2= 8cSp.5;7a%ҘRC0UA.#c|v݃ՃUA׋RkRٵrQc?XfcA"p9!݀&iZ#*1]b09L( H#dyA\21R7{Ua|&};UFFF̾L?[Wc~E1* #?7<-j畭rB̎ ~@\Ӣt";O쀳ѳ6rcRu~n휌JJ4ݟ2oWdqEܛ=;-e89oSzimMyDfLl"qn͗,!!MJ`Ex־PM*OggS@A:﹦0~2"" !$#~#""!")#$~{}}#"!#!!&$$~kvsr}A"`d1i&>A"`|~DgTX/>΍f:,'ܽY?ٖsm͗]MX|)빈]VM5]ZJi7IIr0.fiwgGJf[8TӹܨOXcZ͐ɾt)> wZU*ZKJ( M>YL_ ƒiU쥹BMq픫Fn׽km8Ԏ>f'-h^$.gSuv4ԁgdj؜gDue'Х^,LM4R_K5fu o mޕ3{clK*sb} q| ԑcoMO?{ʁ+WO>%ft ~X{@2ɬ|~D$A. )=I  le4NmL~fWո`4L޳(ZkU$APIUTFD- r "-N"TmkbqO` Fa봳h"؎ M7Lbp`wRN@:pZe2y8g>=#}dXdZ\r[{y0Q?U,V9X^^2 KA $]{6cF>5n0̙:b?DLcpfr?$M3'=}D "G]W: ife{JO-BYcQ7H?1C +@%RrH eO >5I %u: 4`MCҜAa{f`zA;!bv2rer@@F!1)uWvW?zJ~8z|@֛+q"V[U "⅊$fFPGn`.qS|b#2![„]ӟ(&&B\Q7Gqm kM^˹:S.vM`#By^Z!_eeD niزGqF͉wn:Ud%D><"^IjY$W~/aʬR?DDD e(cqȈϗjq_(.\+oSaU4 P!) B)^oϸ`m/-VZn&)y@_$0< NstP t;X=&z^F.FԄKv%ܛh"S;zݵbQK&C-i@[>})Zi r+u 5IpwD2><SUŒ*V+<<871I*D,Ot+ U옒zߞ.mZê7Zx =4['KCd7ȭPwPuGTO1]P;E͒zclSV66XYD9m/nBvjG E=> j 5{ո19<C*l*;}>-I ügtr@i(9kf.;cq4.hX,2shGz?3BJ*&TF@ \p ֋e%T;84 F!!P4NcJ1A u1 B/ mz\AsA^eI}mc4FSwgfS qdO;V #Wdr^K` E yCt@p F%F,ǥ~^zvOc%9 r7Ie3 fth$2y6.,h4( B>D"CP`(|T UP☦˫, :0Tj ԅXEy>-uץN_EqR"l椦MsISj}( scfanbIƴ-L 5(K\q;ʥv*q,GD|(A`Ǩp;|) > 'FZncf;^BF gi"ͱߦ [7: "lC.Kpk rs_1brW?Ƒ#,o2uW|nt/w^-3|s{{|s@"ʤBݖCH'$ 8;^zEld45/-v!%@ k8J}||pY0J)R_ήqu&3 >m-`Rz-L_+@^bnHzŹ L۸& +x~niS$j Ch/%Kp<_. ~ŗϐ8rB4YKk'损owcxITrfWB IU5br̸E}>zcM!{6<̈́KF;=^7 OXt"La<TfdAXvx6L/4d#TadjD?X07Xmю5iv,ܽ\c":X5?J.^ar@۩b Р4 p[ѡO%"Je_12#,*1aP7eMRnYO,W&=KIUS^fքbA)$8o9/1R7Y␔ۺ5R ЯVH;~\f.jlYI"N \A(Q,t s,dۉs [p_.[YZE{ rPFE4.  j`@kRWn/$uF&7(~l6WP *xfނܢDSเ.@$YĔZ;iGNqC6.>zQ;h??Qp >" atdR̕!2XAq)ul@U{.^Q}8^V,Q"7s*1w"d"Ա[ *0>%]NγT\䎗V^[Tv wfapDpȬxvJxdk>h%c TJ% > LPOggS@:﹦0h6! &#z #""$&$"! %% !!&&$DWL*uίV-'3eVm%XWuAa\YWVHW ~gfi(LUGWUEUA<դdb"/)23F^ DSԮg)bn"i@v{kĕLSSI)*, n`2+ayH²TLUIQUUAմJx$s1EFd[}@VU(`zօyڒi!{l lemV{Z-(74oVxTG1EuPFGۚ\/ Y(eFY1)@FJC1y6CVJK2TkD^7%;9.Uo;gVPWaLpl (t+Hn%;X!h%$nЙ_k-qE4Za! ˎ[s!m.`<fsn5GO$lfs$ODD$S0kIH v~v9%yyN}z@Tp68@ x21 [SpWr7q/ʠT\R%~l6)U n9fp]zF~!٠CfLi~_| t [? *SenBZV#Wgb,r_]"*^ ս, [-Ӷ\hb_YNeD1>TKd*H%VZc]~um4}]N9hvwC E5_(ΒsWUa-8' T{?"\(#iIHE\0U,Ot"`5%pɷRyLQi 6y2rOt/ aDTz.6vh桃3itW)|DSBO*<~i<ھ$=y/Fu'͡Y{9YR]=ZMմy:~@"ma*O"5@_Co:r2%i t8lfQ00LFJ:L~impn2ݴ]&݁?_ӿ1kt>ګ=N)s(j[]s'uЌK*^}.ECb2w.Ձa(sDy!3^4`Npv|ɢ խFN?edL'jID:/[~2r#54zz'(cUZeevWٷ9pi1!Ld)? 6E}V(ġx^H¨:ODrBj"mٖYSds0\ `W}E(￝0Ni4ç9vSl*gzŒ=u^eP"12bd.!I"2@ Лe^c2^`ۦBJ00H45$Iv5s${P/+IQћ8K&^AwYK,XI!ND)-B9f%huϝ;<[@EA:XR/ o|'Rru cT( Jpa[IVkF\F,%D!3MO\.Ŏ 15D ]_oo6ȜM?j_~%FB ,QDj"#RKQP (@8>_R3A{Ru0\*\Y+ kk}ɆĔ"K1FTW*̽=iO OXF8j+TW kJ|K@Z>g_>RUWLWIO)@C9w]`nAAQE DWU&Ҝ+`{r0w&ZL'%Efv{)1o#̀Nmjg M >Nϟ,ʚ""S&"d8C( (Ii Į&I%5]trFkfXeʱ@ԵD`ܘHRuS1>aTn i2r~) n~׃~ѵ.5(Wi@s J*]c5XSa>$~ݞj ,v3Hq]ҰhROH%Vzs dtGCs#gi#VEDf+E+I[Ei!"&:4 hQ=ҋ%ױ"im{ VAhq| @{H'WvjhoH-,$xqɭ`˅: #SD4PʭUV\ Qcx +tD]BSWxp Dl{]%l_}2̖la*=BM7C1#\T_k4_"kLYeOUUE3Y[/tިq&ܡDSzMa&k;R˃ZP SoPDTS0)=ucPG{W2DITW˚YVdg t%A1A9n)llcVfO&8lIRG]x%>d_\gUw@HJ=,SEN<|ޑ(ŕ67P߰6DRo/kۃXd^><[Z{L"ke! C; tĩ/eHa1>@̌MG̠ڻ1=yrGX[k`()bpE\OggS@;﹦0b| 6!!$#%)#&$~{}#%$$"*&'  %"$ #%#kcP@C޽k}&Ж9 Q,;0Jt""VCfI@ؖb(2 /"RH(ҚXJIb@lI =s75uHus1D+)tΠ-X^AZ& zPGu%*̖d/Jv. H< d('v X:F`Yd%3ag6-HVA Тhllp ؒJi,W 7 (( u*Z0k9zR6)Щ8Î^^GXP. %R'(%m2SȟhϘNzm~nW}Z<(<03 ,&Bm.)%dq3 K29"]X$PvŒPQƥA!YH#E)y\˗fL/,4i&2+NTPG>ͤOЮ)=I8 #j!`EҀ nv1ޘ \j~jZ$@g:px.H_Y QK @yj֑4cjMye|DdId2` ,eIV^XW4UBgu#\xHA ~rr<.b?QGP1 T۠9e~h+@*(H0@8f :FE0T 8BTAF mHIkW#1^ޓ[%zu-m5Vy.]@ԄQ>&b-ufbB$ !]R(|{ hRBr%:U2J /`~~)v?Q/cŕFWQQ\G^0-P%F4U7Li/5 :q1 ɛ|?R;JS][YTlnoutuas*Q!^@t)U뛄eֽ>sss<~U !+DR)]>:V9w>.8%+ k6iڅaM4 km L/p}ơ-kQJR-p)>YSt9-;~7S3GFl?1d{ۊ4 ^+;!yZ! U$j ޗSB^w$*rW:g8J#Q)8roK1qCL)܉ÃOH1P#UZk+\cxq]82+3JjqbRH%<"l 9G ?^xdGi2V3qcL$KGV=nu>)#2{NSkPL] D΄`;VUN\:{\BLctEQZ=|mƇi #q*Xd콚 .`& yim09 %URr< lZC)oJ V;5B.+A@5!7+CV2FƍoΥ+e,Ţ}wm@G%}X`Ny؅:5nc b(gcI@ ոahYLrHJxGp`d'3 L;^ XWR?wZ25{g6 Ajŵ&;NPqzKȀSDrCqBpƕ,XF*ENF`rq% 2:]׆S㱟e6Ͻ#N2Ὅ葐1 OggSk;﹦0L)|!$ # #$%|!! !(%'¡E0QHB)}5*妆誓5#n6m \B%)pbamFDOj1j ΡQ:\Q2 RBHUiIq~{% srD0F~$Jm&^.3}¸\l!F2/h8T"tL}W+ C`xH%E4ޑG좖8tE6&v(.!Qhދ%z p#фVfHpeus2cA } UKU-*$Du;u* `cjfSSi<L!\|5вRN\I'.~dF!t]s=vͣ>]+(~@%^]c1h YFu_uф ,_>6Y16KvưF3d9D漠S8xO,<DIPnⱄB>\q AiTTdbKdJb%X~lC%ԀsU'd(r,;ȒHyG}uuS[FVdLcu3Ǭ=?c轮v1oa;]QEJ}w3t18ǍRBDTP%)\v̀e2@~LnșEhܧ̶bӯz@nFwn~DÙQ$)xrry %ƒ'} FJfemk} JTH*Ĉ V;^S0M pZ52E-b~uB`7T.O&J/ U::o{cdVb!iF]!}C^ ib CJ2Y⡹BM;;d.7Yjecz=_xiHsRV FEL]**ڋ|pXj˙+5  D[LZw~vyNw6Y yhS 51haMA%U,^*FJdwZ5+2r#ht+_R˪|]Zk4z ?7~5emQLf5mc3 C&'9Be@úa)W1̀ )~Qb$Rit]%?,_cy[v|ۀYBr!i-@lbr1l>f΃ԇ IBN(lFYE ; AR.+XyT*M.Kd l=Rf޴,'m>Q>6+ɏ1%"˝OQˌac_n7# 6@@ȅX?8S'`@OK PUۀ#\H*aQPA F 5tWV1>Qڦ|g@ Մ`.jE Jg( J*ĻCb'KMXUq PLڗGPjAqF!s `.u@su BqI qB+PeZA !iV(\$F/V×1=8FD;@ h\-@ h %%p~,Q T-ړ{Yv 7ilm0(CP~p>P^;BIwaLDU, ~4|.%WR[EAO&:։131EgQ(g @c .<~ jG*vDSK"gnEAVo$Xs(9@Ta \ETCআ!g3ܺIs gMp0461v^z==[DxBnY{u7x35j~;yFIsJwӊȊ$ѥTi"%GOA#0X/,i5Rqx|X^*>,[(?}h1!Z]_mOzeiOrþc$RA&7\ IאbZ uy4Fz x˜UP&FֽhSgp<u[6:[Ba$I;vQ_`Y4YUjl'fe<DOΩDI%T[qh+@7ζ`pιۮqhН1 (.TaM7Ã~tK;є9BRͩE$S TAyگ _;ױhjT,QLTZ3뾽w_%\NK m\}&,4Q$CˈVqZۈ;EߞGMW\a!nzxpԉu}}QL {975lgV l[2RIc\ͩۗan<6ё c":HE٠8wBt⢳FnW˜4׆sMh$2cA~Kg'wQ2k|V,[ْ5'Xx=]{OrYUBb8r=?Oat:ßڹON1⦜~X*r1RЗ˺;f9`5 tG@Ӣ/|K޸)(illo t,$2^a_M`pmPbn>nle~/<~gڷ :w!}4 [ZzsF9nD}%I)d,]|V_(TI(̗Lt^}7. x.EqQZ60 K7iǑQvBMv\iDXĚ W;(\R͊Jw\ 5 b m>d问L=q6NOԳVvbpPp!q<nsÓ _9Ht(aU~9=!E&cӱp<]2S#s3~:φ%ikl XPs?ٱwD߯$I~٧G֑g`T'ۏ'vt޴@p)9CR2ȕAի6|vS#lO&=`>;[TUi3U+\~Ruo$F#UQ0TUeȬJ\UӉA^ӨDa:XfpR}}RD48C$M2o 1^0Fo~p(YJbz{M0fu¸1:D^銱e7;"A&"$eԯKD530%݆<3w6!Sl;Lws:3^Hqh@CD.*lj X<bΞ=G\\>Q pYBB5iE'hnY$Fnn<dzZMG8PmJ;]d91(HGA$N"4*ܘᶑXZu=E)RD>L6eA]k %+YTD{m&} 7o`r+FOs)|$;Hve(AKFZvj}6/{`9З}8 whG"Mb0YBI$ AhQ 6;e.agt\ND-_AFֽedLP~}S+"zdcURheFF_EWAcf+(l׎Yv0E@,a]͌[Ր'*LTJBٱPorӀR4 ctPYdYÃ- l6ꤰV8<>_%ZLX( ,WWQt f!&^L;&. 'mʫz ‘A-#:vS_JyΓ>BV?R {e^RVB[!R $Xp)cV8ᱦ|qqL)N,:ڌa_l#ִ>+J PoVy~7~E"c8R:\(M9rq 7@Xm3#c{ES76šEOaujW?&i )gy\3ub] Pvl5PwkOa,?paXeVڱw>&%7 \|:+ Wn,*)lA*L$5Ņ!4:82DYué 9ywa,"z[\7e #O)RǪԮQGCb?J;OoSHY\Ў)&I"<6 + F~|lc0b0Ia>P!QdQ=UkjIOkY?ٍa]X_Mӊ oJu VF{f@غA^:--jV8i(-#ۅB& xJ6LWYM6rx.AE\ƫRDUqMt9k k -*ьn!ޘ &M LQȧÃ!|E tRKP4bh.ʊ/߶^ޔ)LamTV*,QeœgA]xE3g{1_+QIG,eky.<88#oư6W?J/'LYUP镾+50ǿ ÿ޸leNhV&p" BhDHZ//b1Bl+.glk!` p/d|k)_|d6xszv1i pd+I0oڳ96bn8LpF5x0s>ٖFi]QNюVBbc|rbN$CzJ7u_i`4>M=Teh,Fywx$WlHM3^%2 E▻ĕMLBc;ff.ih$L5$1[qiL'SFmhbŲhh*S=3%?|x=a;,u톙vvʿo~|ܰ&惀2Bͳ\Pj0@OggS-<﹦0o5 ! #%"""$"$$&å$$"" %%&~ %$>ZʕpHh vfu\]~J"r%)N2t8εMҮ2CBG3T"PH*O$[͆i$% XpwgP%Fp]dX <6=T;=Y7 p}vD gS"Dh-)25&JN6Avͥxb|GX2Ҥcc\WRXN\^.o)VI6?S*DSJplioQC,IX )uҨu smW`0+7!BaY© %w|hS;Tq!/~#4>c{]>6].żO r]g>7H۵O+ei=" ,x0#j躨+h(X,'_ކ_L`^|v1exgjOLvuI-\46!UqC#Tn'f2rR &c HA@phucQyg!kYuQ( `]/Ądavr >l~ 4 c;sUKvsx"B%;Mzk#]@ƢHFyG;:zzJV!)C+RE C28]QA!Hw؈c`(! _Պ{D[ q-4( ejPLSj&RfVP8~/zĪ[q?%"mIcWi-5qdMԛ{ Kv(Xpz`V14#e-l[ݶ7ÃS> MѳY5D\Ӹ]D`? JfW\anx OjM&/W;55I <׉㞮 Ęg[ N$h8T۠,M{O61}8a`6xBgM7J!,KYjle ¦/f^nJS+\cX98 थ1CA?!sZ3\gYX pߛ EL9*?Zʻ~}KS6Oe&p~YDe3Ud]NBORaNO5>6=a0͒lj 4yOD1ZIJj=ti-E:_nc|Z y`4kşOHޅiAYǞw-拧ʹl8_||W* B 7}'s 2DrDD %lŔpoBrxClbuӗoK3?Ejp;R(!jH5*7証Kmgymb{CE[^>4f>͕* Á .mL:q4=v~x^!vT5lѪ1>&8:~p&w7CeHӵ5=N(SUN>Y8QkywJ a, V ޜV~ĥ`sZWRUGf0 m!^늍::!(4̩zŢ% ޜT yZ[5X!+a5񘚛 yƔ$6f 1 h1"8B2DM d$!]٘~NHԏsC=7wQ)O 4VtKTzY\,q"4u#^i2fmho]Y?<ת})登NZQbUzmp#H{}\1@`I gWE96B5&W>O `*)⨴9xtyQAx|΀mՆFZh %˅ ^+xp Ng9f7y|lN10<"KYuv $! K4\n lClSD[䟮 xjK F]gz6kM\]hԏx :@D#zJl|g鳠=h>;d$}'(gW4ilD2(=yNHpnΒ-w\Q8E,R.l ;9ݓ !I EC LMg4* [ !ؚDWYNf6Ӎ[DǾը۱z\[x'Aʹ`)mFBZh4q]Fx\cL֐ŶHR.څCh*} }FӏsjZ{VtFw% DğjJq D!ӯT/JNp9~J,*&Lo _Ȏ^`6|zvL9IpF/bF^5tkZkjp׫= _/}Y).rhm!"X>B;h$LG&1pa ]EdOtԜM}LOqYRmϊJn=@;p1AAd eP❄JQFXEш"1Fp'xY<7ћkj%;fBR9-N|S0,Yb()~^JdnjK#!YH]@K) GP/l2)O! aA@Q(, >*(ge:FLs[(BRb̪aL ~۽v|eY;b& )޾"kD^Iãs$Yvy]4mƝ MBIA2ElU["U)"(TU %\sS@R!XFLU2|%Q+R:Gϡ|XHԖ"T rƂW!H^s!(탬e+ߟFj, qp;4r;'W5NvS`OggS<﹦0+*$'%$%)*%!!"# &#%>^[!!%.SrU\6ed?b\T iAf?Ddq!lg8 **{ |$ @fS)PY_80ǀnLYU\TSP]T5 ⵨&8,^Z;߇HY4e;'K>]ųӡ%XN,;7c"N' NͲ_'cCĬ/> U@MB6jkijIZtHu~SR%v3DY2bpɈ+G!{e^ZAf  Y6.{RcNSs$룯ճ{ʓ^7EĵO i[^D@oDt-:B1;VH\SoXvѨ/e'ܛZYK+ \ҋ7bKeC<L$60cNz:b՜JhD`Oߎ\`k/5v;@KwSy[2Lٕ'ٳ<4QXi9-<͞f1ӟv+x7?MKqWBZ0F(($R%>8~xw/۳׸rGJ<ձ(Z, 6Aou ]uxNm$U/>WdM:V`~ek?C?-q~<] Fc*^jRip9n*oᓍc|Wj%=QF"M fVݵl0(œbNbΖ7+ll b__gK,hAo`H{.HGedLhPeipxSY5[)x*\{ 0X VqSuNm F:1ml.H^̈lDlOX&Q#[دΧ. #}Y# f _hb'ur2?׈ pI^OUD' p#&BtP >|8@pzHp%Ʈ?&Jz`W Qހ<_JF"ڞVqI54L,i)`ɬ֜nCnʛ{z;E 5C)̋gܶˑXB.DXYTUB [% E hp ,U)Rtz .f{02*t6fMe1\Ab ׸1}kl Űx%9O.MfUL`&&i(u6"t3"ق+:Dl@?T(e!*(ӨΫJ13NGdѳ:njvQ^^fIe{ryPL'7Un#븱}[T7|T)?q䓒2bkͰ-V6@4/H+pv)U(E9U"v00s)aR^QKU'{5!l\2.vj2 utѪh1x XV9ynN GLvPF_R?u(wMn%t6rbpX`*YdaB1YQ D^|5W: 'm40*^'"J˃"O" Х.27K:_P2(Vw*i„Aϛsy{XࣳSߎ|~H2:Z!]!oH#hk}q0ni%Yoм/u(D~eSqrp(H&+!h0`u/aWp!?FXVhI Yvh^wqkgf7'e|uxh9{,msGT!hT^Tb`0`Dw|lL., n|Ѱ b>Ę 84uODD z(]<5CcwkҜK?khxv9]s4xmj qM(X(@B~po0ĨI"hN`+SJDD:h-,7nTn('n.\ 鉟g yr}3ouvXcЧő6hmo43 <(R/jDb̐BETt:Fh|R3<}R"SzIcKnӧ;90ap6wSP+n0MA~k dc^l]+|J|x- ]#N2m.?HҼ82cgƏ마ź-,U1Bn бd@:4á X=( ònQs5|Ϡ\*+BQ V6sG 0cU (zۍa˩/b!y !S92*di߲Y>=sٴA=)L\ڈZK>cݢ. J+A$  5kkgPj~e];n:߻-)6x<0WgV\_rQd L@JTYcCVМ`* =GY %#LSe(i>w:ƶj(\ZTxհBw(*wŀ˙U~^j: վꅠQ/BIvҜcQf]G18>TaG32dľPlVN hj7j{WS5TӒ QCֶ߮wֺf9QAP$*D>^0޾ 0,,8Ft@ì^xW)ɳiDܘ0A,v,MݝkqwUB{vtx91#r_.cmWx{\tSچrsF+kR٫dg5u%AnAsÊa\kֵnkmZQ`/BCO\[g򧯁`{]97KʋK1ہO KigEfB%NJi*9^7.>ɱ`.i"f !Fy,]%fE.vvcē5vq>! &P(\TcW9 (o?dD2U|HDق8ͶVW۴9 NV+a8 4K Dz <9itK I4Q—( xˊmDk.mX+A,ՂC6!׹cc]Ad_5ԝJ\a* vr-Sډ6杨S\dc"٘iR)._`rKk>`Q5 0~lчua%¢g]0/J*dM+*ޝN8U6iaExeU¨Γsvq'&a+ 0m喇5N:!܂0^&۔{kZ8g:0J'Lp4^[@m>֊-\8t :";&K6/`6M]eF.UCZіF9ٜvrps㬃ط%#ZQ;u tE pKP+5 \9åHR@/J`'\$YF~" L`QA0 J4^l.RPʧH4P w|/bU $.8dh!$@7XC`Iys}oKq]ņNt/ uPmTʯGIpE"V[RJed$h^-ݲh&*kˆW1ƺm$25LAJ$[ +6 P89%xEXy]Srr]B\!4+8yJ݋ XS @>bp+kF{aPyb[c놊-n"LY*kOԅ2wߊ҈}{%U\Yc@UV9=_diP= Tc*\W~RX՞ WsXLULQUUUUJ><]aUt3BsLWi*v젃͹*xB>GN!)LWUDq{%HT[Pn(! i){1wɆn:KMdcH5xm@z I_OtoU-KS KubLX$ρq s5`G; qK u?8J9RF3#WUeaqcJ!*]Bk/vP @ Q dP0@O"1c `]دi{=|)^!>Y@*_kf[DR #E\[W+:6I~\*6M}(\B"F$GhcXXJF(V 0|\-1I_yyVG{\Mt""99Oy-s.fD0CN#lD[@j"&1Ǧt0RZLKC=~˭,pSΊ](K&+ª..BQk}sAի4.f]B'q"$,(׈3a4ڻ+lsƆ\w߯nՍ H@F @ FDWůZƭŠtX9 Fs |"[.k'5 DQeU#T+G wO2wZL߸kx xyn}hy_DiϬf.6RHD=p԰ՑUARu0=Rn;lotmmj؍qsZ6# řr/^nE怌/]89-t|$2ioH;2_iNk-"ٯ:x3ڔ])ͯ@AP3 Vr`._h4ސVH.mOLhw­`4-0WRJ@P1dIB)j+_AnFQU#O%MZT~eC; ĉd-%:(84+ #kz{|il=eǏԤib0%@bYIF*W;6.ȣ]!\[C󜻅AY"Ǜ y[ʼnp e:-Q 4WTU?Lav"̂A5Vh()DY/Uu 57D6ƒk\j$2KJTWhJ?*@S׏ "T[ʣRՙ~GZl {HíSnsٷWfleHU!f péŶ(G!yYJ]Ӗ3Ms{P[cvjŎE O'2e!h6 7r|h/yK-Is83\TJ#uZADk,?طKr!U@*p;j4;")CT01B P eV0/~nS`"!8A !Iv Z&\ .ml>iY Bcׂ*=L,+.!np*$]U G)XE"n6"D8@"R5C*^ͮnlifO_BRu:") TFbw܁KyDnkei0L : *L\p(44׈ qӺvE'F,+xA|uw!R)0ԝX 1p+KP ;XzB~eQ28i FFi茡&1k^.s۩<mۖyw1 |[ĥD`)!\s ]cVh8F!JA`YV*ZT]Qׁ~m2}K*";I1Y\]̪О@[~Uz{z6>U; \a+,b(#A:ZE!{7TTW:/>b)"LUUĞ)U̥mg&txHDQ Obv<ѧMu=n!h?Ƅ4S\U=Mmz<8ϡ`l*d_bKCŃ@*(X.푹Yilcn6Fxjh_ U3koVl {)=' zqaS=:~۞aVD't,DJ( - bsa1*h4Vȟ~'3l2Q]NTS(B7`qGa(T=iB$30bQqSApŵ.2u(RӒ:?Nx<.!a65%+Cm|ǥE38~D#Q6g:ү4fѴ;hDph'.q߯& @inp}RshAxxuH>Yt*B ^|ֱ3Mivƥǀ봋KDv"DDIQOڒ!R l>R4m: t]\Y j eg~#T<tsf ) D4S7qQ'm8F*ˊu T1.| r8a74ilN `GK\%1)q)̳,K,oV@hj Ȍ41#E,QKxQ~B>v+8so7 deOƚ2ۍ2,;#tR#3qy"CgVETU{u NE! Ae٥9m&[W0\&~Q[]m2MUjH+ ` .L#$s$\Cn2'FŊ6“sq)2'edEsӤ}2Ħ nY( @*)Yu4n!Om G0=Q dw]ϚΗZڥ]X jEԯkU^̅^|!T^{YF Jĭ~oX2^ b)R74)WPfXq9K2&iXr H؀<q^vxKNXCr걬sš;f˞i*DuȫxV/FW~4ٙ$uȺ">^zF:@-!4{ːxeD H2Ve?rZL+" Ѽ|1ɄuXpvm=ݤlܿ+>~Ф2PCYSKT˥i P8[Vm~>0/Qy6n]VQ0$5bZm`4\,gx??N;H4%b۫}ks<ƫ!ˍrAl7j"j7@pDtK]X `E:6H Dl]\A?4CqIb'nW~vu9 D,'QWg6/5H Oh'|cw`C!|?J q8[};˭xs)*C KBܴV HA%4YQjo.[$=: N%YרCqd_aPyx zF:Nm^$AYdc׹8@+FROFzy ho4ق(M>Nskf)y ,IU/4!c='%\5TF2b¨",Mꗧ,ɒլn[PnRֶ OggS=﹦0 Z)&&)$""#$#")'$4UK?SE~xd]Vonl8nL[t l`u=4 [ޔ7}ՑD_L 1:NfG9.e=N׻7:{&ub f͊L a'J-X&9СD!I}从cǺ6eDt})1bD[K= IOA\2JLn=uKh\7a9Q}^~8QQk3%lk;@<.GA`ł$.T/,f1VfD BP)F^.gK˲p-1gHcߎ&q )Y\odKٕ 4i#+Ī$w |qU,Lm uEP |({pi;杻@JQ$fǜ6qH4 Bkv6])qDGbAS+r^2;{ռYH{.FoaX]! @| q%J)4BÂM$-,\c\UJM~L[a}vUr!DWLԧ*UsOk22(HI*~ZneAT[Svq {Njp(L׸D?}dJ&TcU  `YSO_KQ2/ycxZ䶜5ЪhEԷ%mQV )!$*i~w5/pVY^Ąff6Zmš%Ӟv7xιv}mX+T5<$+B[2 &k+b2>6U(bwzZi$90=&kn"gGj-lIL\>HvljEh9``A@%_HK~.ErXXWhb(. AAp.^ƺ O&d-ғ4.A!EG,{ǵ&ҜP4(䠘.GSa+J'%nC/mtnGa[Ps+M 8C ]P XʇG .&Yew]rJ< C~-U$XADQ6ƅ0l; 5!MOTS@5ޒykLZb< jG4.Ff 2ZziޠnC$Ұ y~ Z'r ~|I@Ngxfdt& qqXI#rgjvONB;EM_ 6@9&Tc~'aj*Ƥ1rJ-7S[qOmnh_h0}N\g$G=K8Iɮ%cx}~%hYQU./HMlyݟGڥM)ώլXSkp u:eDٹ!^ Pߕ:- #w qybj~U﷓2Mkx~ǵc~yngb38n ݒ3 6Rl#~kEVI#tFnfhQ,7\~6t3 xޅݣ0 +s#||֖6i\|*QVϧtM)xءk!حػ<' XƣBCxeJG^G(c֖ЧXWUȝ/j]=e0-NơHID4:N&@ \C|1R\ܡ N/(̼ ;viz/EIbDdC]ݒnv4_xj/| )iɣ?sc 5]RRA]<Er86dx&c )wH+ )WK RKXir|p4Ec- H ?$W2'7UO$cicڝ\h ruN1sxKCg)P e%IUj2r#v'|bIޭqw_wo8:;):[IwJXCSMxUu]u,K 3 F)HlQ\ ^sE5X(@F<}N)P\#$/&v& c^EGøpj/ƾNW3Ow],n-c \) Ϳg z`BCwa˴486.[FDT )$u^I!T">lރ%j2V,Z `4Mބ쿪$ h2/6|t9++p2^n@Ov= HSxJD˭mH{-RA  R\nZTM\4 {"hc92JmkdhF2QHbOt/lV߀tkYRXs@]Y(A1*(LTAQ{SxU)֑̖yF!.UV4M(Gf;-JW-+*P˅R*{U4vt5\8 2. dU:ˑԲm:@at\,D+DE2UN7uL"dFyjW9IP<7ճ=5KS== bk'Z]iL,]bHckGm1 ߟJqxaRl6Cax=|N㕪$IbpnM1avntaH2,Z4Nyer tdHȬм|AZEmي37z@ri߉`xc%V̓uXc;l\i-)V@SVVG,B~vÖBD+ơ0 ~^jKA4P4|wRLϪz, 9Q@CKe5S k }>3+ t|t=Mrog2ڛw۽T5Vu}jP$TTšk$y!2|.|6sAd\ ȿ!MQj6&l﹦0Ӳ0$"""+$$ !## '%&!!$"|5F4`Wb;:ӡܡ}Ko7 ӧ#cf>>u6lcz|lB#p =$&p ?ɦ\;*I8Fq3S~/yOpRw~;4̝2RfLZ͉n1b%F!V$LpӠE♂U0sct%pA11NZZnj2Ӊ ݜ-2-#;坵!WT#1vV RoG dܷ{ d疭=5+byxМ-Gm~<&w@riyxJ^`B7Z"X0@;M^c}>CG%E&<[ %MȧAÌC2\EbF,b Fq! K2QJם\ѝ̏e]J~9lʼnⳡms=&?B)S/Y0uOon=cWR%: Q#>M'Y0!!>/CƗ'a/ݤdd5Z}L]Щ l"ڮغVNL=qJ&{ӧn?)CwSݥ_~(2zO`]nJtdRFb VCU bDK%cd ~Bߘs/.su_d?'9܂y^?=H*n%dV'7'OmKmvjwt=/Ĩ? Kq.w l:u"pgmϑZk*oc:Įo䘬;SZlsk>ſ:Șٰ1 :nJ 玑zi1!,U yzojyp'I YM4YLԋ)SLۃv!ki$U,Y4*?8|O@3qPWT DY `YܲSxkI"D]Ch~\Cb{.DWZL0)w&C1($ QL&Mt 8a:4Ns.(t)ȆP!Z?01b-1Ba+#@ {D$~zNd,2u2REbH3G"ͿE/K!CڈYU 2,T`IDP T P>ё1ׇ(: 2nH`@ "Dn|N8ć1K.!sv$S,j,mWF|8ӵH#J/*H`dt׿D3&%Dlhe_UoUEvDDV($[+%."M k`R (p]pT1""FJ5긢RɢHub4ØG#J=;.iig" n7W8.2K`󮭴8X%bQal"a-P >nc*s٭E1M낄}q" Ҧ<Vec2dG΢]yuP(_ۤ7͞Ų‡~]G P!Db8K{*Mq@  .: nUPrt?d#fL7q{Ru?n>,6R)c*):A6h`@nN}4!k 0\6"HIаp׺֛6KD-;ݴm @aXǧ@\i($ox&ҷsvjX]zQI#cMY: `tA/h]E!\aUXÃLij?\12WD(ֈ=9ϯIЂX/*4* `z/V)E~++I4т긜h{`W_Ng;:6qBS1IG\ATDc>DȟӢY; ]2o:θH͈.ѺKEwʰnoVR $`\~ d߄DwHj*.qّ“ -% ButnXJF*Hb"ZQ{$wU> >\6.vH{ .S(9j%g?pj:LǘqFQ'8ncܥ.|1"mA.j!8NacnInҘ:*w^nj=ԏ=rk]K4LO?%Y: [nJE ϲ҃mqˆbˊk(MPnX: kf5T 7+NvU|\08> .\+[,bqdy |vH;Ŋ#.Ax/a)Gzt'b%Pc qG\g[)<]u2Jm_cCXKUGm|c݅%-u&HTYeW.,`ryV(VZzDWL*UF}?; qӼg!CuTYcī29mQyH<!3dTY m .{GE,TA!˳ngH8TVXUI|)wנ8ٜtu|x~l?.|v&Q!%sI3<&"@Ϋ4ͧc!Zjbݠ .28iXl:1˚_Bb>nDk[GX{D*MAlI+cgݠDV>mk}hRe` !N{td̅qlTwn0ڎmEKm(ဂ!O+jg@<Bn=T##[?SݹGH"F*9(jboXsDUHŸ> G(uOggSt>﹦0O2" %!# %&$ #("!"""%$'#!!!$'v[%`)\D[asZ}Ҏ˻oGdKz@)Q%EIn36f5ֻ_q/%'RV3QuF< ` Z&,6|=`-YZWX:,楠6Dr,] &%TԭR&,SlNF; =h3T[T\_Ks &KKҗXT_=}9~Y&V3$^}|_WKDU}DѵhH+|d25YGIH,Meʛ Ú?y+.Hs7qK%=uNe4b2":x%5$4\.ET[ xKtuV?̓l)&um<oaT]bcK&M/sF|\?zvE2 b(f Yy5cD8zuT|Rm/[jsr-p823emˮA&CO+h^#%UR ~ݞk[q{[ESI(G6~ *φ[i)ALk{YSʕ1 몵+E`ҠHE~nCfx^ uAU=R$ҷ0NMdΓvj(Quf.Rǘ4& vAV:w$gW.LoSJ+I@<5$^1:q&shNYjs>mkqRn7)% 2׽vɁԝB^EC𼐰_9ÒZJI8y&onǦiD84r4uˣcL+٥!*qvC&A#q:TVov0fqfRVC)11K49գ=2z_ZҺ/B WD.L@q~E!|)$*_҉h; G&LMFq-5%8(%wO9OzWuK/mb,s֮jeʎ0aJ.} %^7_oH)zʈt=bzE+KSap,[ *M2Da%0lHc9瑝edIC랏64+&qՊIr3|nX4X9)o+%ɑ.js\q95j4t'Zk}@VtLK"';YT7)؈LnSl ++]yoFZ#N_wEQ{18FVIb j_b,bP(~<5}l@&$6xJ:)hA%8/$6{C MgC"žVo7 F,Y, (&Q` `BىõSf 5j=rJ4aAԷ obQ,vs0hhgǜW4ff.w/>9渹IJ.6x8Zdٿ\*UQJ83t|x]`؉خaP% I@ @9@ e%#$''%6VնH<I2.bAVD\YDUel=ؼ?}nK Ӥ5"TWU9=ȇ%.Q!q@\[++dhoK'JJiմR&c ADUU*UIWxгFͮX+ DSL(&hO/^>弤RRN0DDUGFSL=YF2J}=q^~JK1kH%6wZ|5z&wLQŌ:Kh"B= @tJ%,k${qCϵnfL^THF!}T,R-fa1&b]8x'w:^.}\!v& PD.ܢ A9Y+dNbQ<.vR\v3({@/ $Tc?FVv "P uJ):ُ|wO*l/`3~:sȢ|2juG~a8 Dž ^n}Iwuc' y;=(c.4NUjl#0eؖd,q_։K3a)iJͮA(MLDrM9zr8 $Qdi{_` j3zbQFCDv}78 BQ1mXfR#`ӣhT[qŊa!BxjFB(~!!G(\3V)))yExZt%4~"H궤a@cM`LB@&h<?a%o14J(DEgZP G]O.AU#l:]̭fF yBrJa('֯%dY@E!`̅(!pd:Y8(٬chӺɧ<4X[2)F\Jsm_Mz|k1 7,c$_h;0f␲ֱp&,mv -;5֢44~14z:4Q!j`˵HO7\1!E=-6Deg26g[ZNǶ;{1[Xf)B/y(nkDT\t7A&Jri1vKN*@vf'5IJxٌv镧4i'G1Zh$i:$5!QzR*S 5"r=">ig)+H  /1)udhY $(]pq7Ve_vVl곤~M,;$?Ms,3%Ӈ[C(wGL 2vO ɶeCW[I;};CvzS<ژjwϭDW-+3Qmr4O-$?+?ʊҾLn ] T﹦0S1#&z ! !# )'&"%% "%"dcloWkrM r/ZN;u1dgYP L1[8>pRMӟͧ¢i ;&' `NSaw[-0Sh"1F$Ƥr=].*j 6FֈHƟ؊· ="VьoP nn$߈iQS\|^C8=OОG#wj Ps ̘mjs@.l$E+ &bsUpD*. 4Os4L`j2]6F A? )n&">~U1b.݁ʁ^z]PM j!b\!A(dЀXeH]H]kFVOE;%wb6AkAQn9B[i޽ًKrNxpc܎.%BmUMD1d"0O3ӅnX$ {z]R .B&)$if.r:135-䏉=^Tى K0Liȱb>Y._@Jv#qJb5~k`dFL4F ADa6*˺%V֦*fM>ҍnhc-֓vN((S YGUcmȌڷ~KpTTln(buC`d=$#(azړoZ(i䋧\+Kcx;QHSB!Y#?<p*XXԋEސ ]p_C]R2jN V-"BUҡ9x}Џ"^e1ᘩ ಔq KYLOHIJf<;|/WmM\*{vI5OBCrv{,(nճƨKu' agx-Ft\5 htNHPa5Paw||t1!mӽ}BSFB´^&@|}Jd\)OSX8WtH5Y.,kZ_c4'+WXeRA^ FAJA~őFE3%N貴݋]/|1Cn=67U  LUT{BA%"~?Zzt&O%O}[7 {g{3{{NU_.W=O%I9F `Lc@*^[.CtwNʍ Qg"₸. \[ LWU+&!f ~+vE79\Uc:_N.F-h@5}cTY A:Lٳdl&cbJ*\Ut੪ Ьe0?&bR-ITS2ȡG%ѫyAT4SlhVUL]x+|sUv0nWXť\YjR_u?x2ߔeOBdrӱvW#|c@6F!cj"ANCj_>k$ֵl= */]n"y~dfFhsVُG<}b )9Is|>NM#;)U[X (Zm6V!PjpڕbEg#"]RWi#i~|1hQ{4OfVNgI)zp?5rksج~R`@-YOY1܀>UNw!$E."b@_܀p]6U[ eAm%j09!XM'tIN9҅ŝ}?N/5:=0;[en" @cd@ @YWd@as`&_"q`N4`嗎TJC{0trxrޮ6?wJRB122'^DFD* Mg)q#{^fD"зZ@DJ_`PYH*E(GUde!-EbA&2csY*1J`H\W8^ @Pnm0M'OE4\U*_a⸮8ٕbc.TWq,+DR>Ȧ'ɗk.H\[Uka 2|lɾ@\ac1s\_& adXFtd,[Fޠ0`nU/ԲV'9rL&ƚJ[/h%V'bz|~~2FlÈݼ74lJ)ʅr<2鎃՚k9D2ګ=Fe%8۷w'2vkʺ˪EկqMws£=,r~{ԻlL xd54:-Zqicڒ d OkC:@ViΘ:}L{_6*hC$@&$x4~lǕXC;;Zڕ֕ۦ) .y*,66Cpxu-AҾkftۛk:3( [_7( +x5H(T|HmR`;AjkeE +N@`7euV*(-WR,4q,&{_;q$$5oNhnSJp2ˮقIw'cgxVoht'ag埏lFʡ%C|:6?FOʊ뾾+2ݛ_n5N}'m'ܒ"WQ ܲz-2#"xs^\N)_7Bfp(9S`"e+sfOetln ڊ^[e˼ri<4i/p}kN+yZ$3LUj$u%ېKB)ې4j:6^&Ƴvkϭj;5.e]Ϊa] CnBL|ŃЛ~ \*4q>.`' ?Urc4Igϛ۷˛-l!?W:YLF:kMKp}?Fxɨ^U:/&{{fѽ w84MY[Jv;C(4 5X*^.Q2 ځNuu7$5+R|gHNOPu<v1&$ M0ʛgI|^$!)5`י]:nո S-_j|=E+m-1)2k@_' !Ь~2ăL65>nQѵbIV2FYKUHW;r?\4@ Xc]U>l6>"< MJ`9(3Rj_ Gf0o6۳cHH#CC(,1pu;P*r4aBS#0넫7{d.z=4= JhFҦƢEV5`R,~̭Er`pMW(=eeo:f`=_/-0L̡SRhd+Ord^Lp3.R+)a"7z[rڛ_E srz1R.CBf W*#**ϲpQTWCQ@E;$^ J.f&T1F`phGQ#H WB¤.o uDƢ}әFqI_czF }Ddzf)7;/csjm#Z<(m~["F:~TG n x/кRk1V[[i}nDƫX1)!M0` ALz"x^ ̳AB~K #&v)IZꭒBⲂ,oE jWju::B2svVL?r\EgI:MVߙ4b^d?qWtWg0;FQAʥpzG)`6M 7pvˁ"Koe'>Fm4mz|:=.7-#_bEJ[!#D[Ãzh!-SN]r-ML[6UL7'/ L$&+iS1VT\]ï*kGW_΃ߨ=U]F \_ikÃˀvJZӯ%I(+V CK%{~ʇ&DWiNۉpu~ w,05ᖤ:Ь5ܩ Ǭ7W4*@r/oȿdy#(\~ wA:Eֱ9@0! nFo]DZ" 9zYOu|؝޹EҜy?jeMGFj8AHSnSsFSWe2 ZmcȯV]bqY σGޝ^[/oqn0OH[r[E`zf'T3DRY!쮥4[f^&˪\. :kg➍hhy`6'I7!9yiXc^K ) #@Db}cr0j#^~k,5F_ӨfcV =DV\6fS4 iQ2@2/^GcG٤ {Μ%hf /R DWSvTejІ{p)#(LQlkf^B `$/Xbؘ+daQX6yx %wJ+|Esi~(]liU%9 f'wCSi tkCm֖Zkwrb0P^uo]Sv҈ ÷N=D,#eDnS 9/byD$cۦ ed;K'q7O ѨapHbIu5ɴYiZ-};us2M \"L\Dv6VU(+6Ay Jr*.>X t58c50s:&Ng2_dİX~/ ΚmޭNM"/vh5OR"_ !dta7\4-^ b6(I:; f""2 A:,^6+dpZ(*9-8_S"Zr':9̷NL:@~ (sP v5|6QCyDuDᗳ-#C.zh!U"ɊH "HNֽ aB`mL/ɘzlE?yM椫uLkĄY9a]]o|AWXtp~NA,rk x[H4VAA-A-,omC|s ԑ"+#OggS?﹦0`ó5#" #%&&% ! $&$#"#"%(# ""$"! &'lN?)\e"vL2rzݬ^Iɾ sIn`% Dݮ"mP!d"%iwƏ(R.َ҇a#A;u2[=7{^6n lUש z$Rg)afihiި ]Hqd%*;(-ivoY!5 `d "?<1XgJ x1/ra $X"|l!s*q"jGB{ v.fW:"IQ &JUP ~_,m0-:`jť XB] 9BLS!DUr/(ndR.k(-ߚ@,>쵏 %+›$3HiP6N&MDuo.7J|5J\Rb}2iP  ᳎yR& g%p3%a^ȧVDTP.cJ\]tYVPKf_:2_l[^yE&y|fiق"TUϔZBl<5\lՒ$adY̫ mr d7S3 ]Π 7[S)\Wx*uzΟxeS[w-]BA[_ \Wm+dk?q]PL%(uݚdabXzVF$( 'E}s鋕 q:\cYS'ר) eߍs4:{:SmK.nXVB,P|"bx"fBJ)Y> ו䞛'}W8,,A{˭ZLB$UHH MY^/XԶ(*p(b\t1E"x7\v&vYzvRf/7h[˒:(4h}G ^L~CbQk¬puj:Vj`ھL8<șmx͛b̥H'/R?Ao T7Yܺ)+R;da_,!U^[8RS8[6m)6PlaeFQ{}anR vRv?Y9|\v ?zR|L.5dvp'xa˧;B=< qyyJZ{,Nͻ1k 67NSK5\Y =XƽQCo]s1ӟTYtoͅ;&u{uO[|T)?x9i]Hb= HD[93J׈tLR%L I`@܀se5YEn-޻ DT ~=Q>/%2*mGT[ ͕߷ )n$DVrnطaodadUx3y~pmT1\n쮜-kګQ)pcB|վa:a:Zٝ~eYO6;Nn79?{6cҸd)M7ȚeU|Us6MaWow7ʮݾqn`mTsS='?8َu-{: lB2B(Zl܀m@B>mM"3Z[sAF]XڎVnՅD:ηLؽ'}Q6hJEbS|* s:6(ǵ\NUz}7˽| AZ"#JPoY" `Uƨ0VR5b0w - bXF{ms4hsZDKahf$>zXF 'E?`B5۬}S(Rm=tj69nAƍ0\, BS!wNݵ9vxr$ȺyF 6]H쪀LE0?W&Fʠv'nvlj3džY*tGIhwm܋1®qn@ T _n #T!g|.i D᳠T1^T>,IbPԪz%/]ߐ"HFf)D%hT/w(1hH4 =foC噙7^ʝrqqXWfylE>{=PI<q"J!C.XcHp/[!MLjׁffXʅht>IvOz0V{s2 yIFnn>p \bJ;D(VN_sIHV,'\;eZW7,FPQ^Ueh75 M|.+Q\/ڶ4ޞDv_ӣhoƂՋY:_ v>`i4r :"%@CV qE4 VMd3aDn2h+6K2f+X\;&GcF@*CЉ.$tu6kw항LxqU`7&3]:uZPP- PlF<j@6 |R=d1R2^7!5^EF bBb*w1`T,yG}?*} 'ELD K\^$p+)zYuEx^5\^ETA|ˇUI&" ,0F%)}rIH7LSUŲmBFفLL nv8 K TY k+r?fͯhzz ԠQ2lW++.SBA;@y4 1L_SV OHu̿arIz{)ALU*ͪrd](F wQ) .TSt[~l'x~"0d㖑\QAk# Q\ 8 d]!PB1`>x(Q tdv2|TleARw@|mh6h-NɻZ4F/=ccb0>?eq}Նc4-Jr%IMXVodk^A[m0k$eZ- 3%mcDĂ P!tEAB{ +mcGu5o;ysŧc:^?n[IHs|]@pX>MڰPdz>#bLbvZ̴;"tUk J"C{i؁a'E\%#!"A8H9"<)1+‚FOggS?﹦0\4 ! !!%($#!#&&&)!$!%")&)ϟ%! !##V6s]jh Ll=BXE9ִt{wAqa|i11/L6@ %f)#7c(2׺ zш=$^P~Y(d!&G"!OiTDagnp?^$5RhfLzæ"垎{Zj>ǽ'>:n:7~ļUӠ*s !bOsRcb:nIq#u=x=(yC@>ޜv? ~`@8 f:B_baǘɳ>j v6x&u(+ ^֍m\^l2P*aojJ*)P%a~T&JStCE a1c^}^Ʋ"% <F VG<=וSJTt{X)4,UlD^m*nAh省(M@%"Ҁ`tpY!& AJF`"UۚM)$B0@`C~YCF\~6p+UQ" s*GDvYהRZ[5\Јo [ԪB@WDu`Uk# UtEr_g rWE`Z\n2X7Rڷ\]a*Za,їXH'6]eTxgo|m2bC)I! dD?`{⏂0 APF$V)y DKujA sF|dsJzRVMQDUs  +N2^JC-e|eʹ7,, Oɉ=`ӗ4okJ~5ã7Fg'+9xܨ #l?y g0pzzb0$.yS1=Kѕ?k63g.戺'G E#Gq AΒ7'H@a+Bj!';~r?u.qVn4oG e ¨wík(-cVE".Vu%b⹀b%$+|>hHZt =[8"̒nHt|I\vjK B( %,\=;a/;y6'_hPff%#.2 R,X'>[dZ tz C p ˜Rg4$h-ڡǛIf袮$K(D8Ц/7L=+uC?GA),c)kC`놯 kM]G']I\V-È~^L{YێZs:,YuSS dfy[,ۼN TɽEFf-@xnK,zRXXkcW?N0ٓN Ho$/+&yE簖lK@^8UP1UXA2a ^^Rd0.yj"dnKVmi$K/4'rӷlD4Ǵܛx9=IU \+=gfR=M_KI,&eʘieRƜP[f筰^S nX5f⦏?pAV0ueaPlE]>R2,*.uZ=ZQE'pb;=njfijrn11ieI]pvQcc\?I2UT#(Pl@ r@qW @Hn:Ȭ*ޓ1ii4l{wNfY͏RZWKs- 6"AvSVvnK-l9.Zץ2d0)C5#'5oW0Xi^v͵yN5K|2{oVg'JiqJ J74ʆ YUic1)T÷͞OɔNՔZjtj%~S?(fp׊ֱV6 m(GDUǒ*C>;gkYjJY 4QEӒ:~s?dV x^9va 4KIu=<Z{,=%h.KTՎa/rQWwJ1TwS\l@p U,25RȽnR[D1Q58XL~+] Oޮdv\^+L%zawZ\~٘pnw;xyi}VuZvwU SƻF-D!83I@ 4?y^c۰="nZ[P﵎N޸хRo,F>N$dvB<. ;tMV-e|?xlztWQMe;p=;^iC^IDK &Q@ (H}+>Wdu ;o"I}I?" zz$ƪ1RpxM>w+$kNet!`s|o&k24`(#% J챜Y &Zœ6V}$!i ,'-KaZkF$V  ,/L,,GX16%FHHЮ=K$U8`6 HCbHwgHa~[>A$lVaӋz:DQQh8ڹ)#T ȶn+DP<.'i* ;B~EZKl[MW֞?lͯ!ychV^i:M\[j ƒ/k8TdX U~vQrd[*ajG~4Uq3\q "\[qU*[LhqP\ViWlYvu7fu m::ބrY &d\W@Vo>Z.s`P{'NUQL[ï- yWV- =R$}&}oDlceVKJQI^Zt:nHOggS@S@﹦0'}%"##%)'#!"!#""'$zvU3ы eulx~"K8!9L: (M7SdF-3rad8DSj jⰞ\FۯA_sz \5yH/"Y4>JTQ_8փC nąr^Z@}^#\$eI.PJi(<:?zܹļh^<^G4Rz)IEw|:^AlxucxEcXE 5Pb-Pލٖ0K81J8.HМ0+(kʥ(*үX>a ?^YHr4@= p:m ;UR% M`ջDwAæbB3\̐\gnK%k[ɫ )+o~.׋+>ud84)1lZnCd=^kCӝ]$i"p;ɀ*V @TB,ub1 q@B$0J\U?hZYm_h‘Rտsa]L8:q@[==x/{|"$MG?^H9ΨIV:i dWN`Z<Nj~/y7T絢9F Lݘi3?9A·ܮbOz,BTD6v~j>~]qa1R{b+sXG,WLYw?LOe;of6Tjt-Ta c02măW:gGμgo\^@W BY/kaJ8f^ɫ6/pvu~X%C^ƀyY:ưLA+-O"Z * ?yG?aY:YkoB?ukL~{j^_-SxkTuN4kqZU5&xlCLEcw봮?hh+&.\h bxJjRNЍ>8摐qiV[7FFoxҧڠY~;wE+.V[^;V&fx^fE/mthU#Tܘ6IOŭ;]j3Sj%B$5\ rrWK+OrPqģ1x߅nxdׇtTǛ>Ktw֤ˆA,g4' ஻2``w yauzhy~<.>z>wY-)L/4VVD]~8ĸWIɩy {Α H 鹩^4J I>jHl߈h^m6fKX1_}6XHtnQ9{ +ԑJC[j |eBL[Ed ][62x[ufyF]8:>ٻS!aVQWYvoGQU!'?) Q8׸s. mƲv8Oha|o#Z=ˊ),C4[R^ $ 5]@bu:N5;[|e:K._e6G%vvǟXȝql>1! ⦣H1SXp8-<\aa%߿_ךů nw?qzcéUt~j75hN)wC?nhPHE˼ m=|8DWK&B'.fo?%G3HcpFI B  ( [QCzf* 2?g]콿wqcX(g??rp믅GqgG8ðynD 0F?Y+4@u-=G! C)5ss)Ƕ/ۨtrޯ#;pnY{҅jXrT+T;;$7ւI d_+ƒ 8pjhL~qח\daQڼXqqG-y"T_›+UO}X`vX͹6\[@*fEAK_Kl.UT[ )%.%acœ0l#ּMO]8tEJsPU*U%t`CRz`9l[ZR6Chq5@ leYR0DűPr &2iWq(5L#r;|(1f4Fm4酫GA@h=ɭ jA|A]U .@0w&.Ḑ>HDܘ8L/<.O50rFL$|ŀ}Pw%%0:p\ӆG)3<=lH_?G:~Җկwwވ0KH{2+5Ap# jv SVC,5m: ".Eb5IML* -bė~U䌍uYv41=Z0j$3ͶosFmmBAY=1V#R]hbH#Jd ] me%A2y@$c(KKiz ^QTc5LZ  4Wˇ"֡pD6ތ7]28nTۮHBlXW(6{(4JX IpG} ">x+l[:?&>\&S^5i`2ХXY)w)bR?QJ= ZoRہ#yحP/|6DՎ@U")+QyQ TڮVĈ(B.>ڢ5(>Sw޽e4'b2|azc`^UDD-Cs i*1Wk \{4^ml^(]%^7]>S3{ݸL>>\o %=z&K9/Q+%@.UW5W;R  û%6vUB -u}xXpY= \#fDDHτw%{_ϚT>2zO|gO-zpݝ<홍Vy>oNd{ 8v/19;vnte6|>{Maf #60S|^% VHAW5#OggS@﹦0r) < # "$&)%ɕ"!##%('!!%(& ! $$!%" %(('&<[S혜c/)dvq')%*WL[˧j_cFmu1IjJ] ,DcQ BR)ʧqd1nn4HkHvO};k~럜.}[\Ӣ8 m.O9$f1Ͱ[8/*#UtBh`TbWڀg5b-a!;cSVڳX:8XSG5,2ncʏ6}Wn7e7ͩ_K/6677B@_; ūv8]X8SRT[ga~>PTocSLYs{x~~d2Tb 4QL.~a[W>h~wFSt-q&TamNԁxFDnOBw;;.}$\iak[;OW.PV!H"7SlkNya-',M}~n{a9\{Y+'2OvEk$p)/_r'}SBX%nlaF4}kok% dm "e@BsQqD 醫I,pKK%ٚI!<7!tdO'5Y5ʑR,a޼<9rF?,F3@EN w(uhb~A6;D KYCYqq}Y|X%"Ӊk3M!S?P /$*ۄi!]!!>$+6j% ݕlNQ@| /di"2\<Fˏ[Фwewgg/3܆=OR(l  pBXJP!q" *誈R56%m- {x^VY!wM,<,2F.юAZd 4|mcΐ#bL Cٮn'ZAgN+$Z[Ra#p#B"؉dUܬ*nf3ݿukSL*` LWU)&-Z>f*瘉'lWU\|S(cu)R{\Q"\U{򮩸y23&JʦcJ\Y{OWU;N=ħCͮ>\UZUi|Eӹn]N2)DgeL j>Q=);}ɬl`lgY"x)m̈OȞVF4ۍ7Y+:<)"Ri"oee! Rd"WyIK ½AeiBMҡc ů<\b}bwJLݰn,P+5:M[Ͳ g kG}vx3I;tf*//>va@ixXK'rA vcj ڡb'_lx-xX$3JtEk!9H\O\YWd~r=pvcsIcr鉈R" ' R]Jæz:] ^=':b-k8.n[e>XFJ= K*A)%Bq]B  #D3HU@@  B56|V&e@XLV!~JgFJOY866p{e1U/2 uhd{- B*3S7b/ofM9Z*4]ubiVUw7n]R YSqp$ `T ~,h2 4h`]\%:S&:e7Kndt1a\d34ɞn+E`ao׋Hlq$GzQ+W bs|]iKHpCƬO>8K);&L 6jÄ(`|1+N]4ΆG]zpn)~}/X(i@ SgWh`! r(Xu9ne}+JZ$> "ƸB\1m( P^,?B!OD<[Xא.2>?waxɝB†HG49y&dGՋۢ} ))q:{_uqBHB8WiXԈn%rH=/#ڄWOZԧ+.- /鋇(vU_'DQBJp?bt3ducw""{#F'W_>}%+Gly9сxiG4k:gqsҶ3ĕEE+łFgLS6un~rȰГU~>9OҸ\Uah޼}:B W|)Ob(d!U8~޳1:彽YoÝ|=AETU'ÃӦz4ҾL{ht$d^h\,q+A{zIn\ÛRCML^O<ͻSYaRHxk){;ߘsD[ʯ+Gr=@zڼZ}G+f&{k˾ 3deCu9 l[fz1D1ˈ8nwD7 Sc=T9 盍V׾0}1jvfHb)OI<{ãǽ"={-:vY Aʆb^뤡xt.XFkb<{QHHv pm"׃yKhDT /4r1# -.4W`Wԝb:vdiugikVO#kۇq1u=X8Tvm|f!߷nd0=54Fiib&]}FKLD,q0a%'­Z:u$~PN$,NRп 4jSZLQ֊5^ = Ѐ.֬DMlegENpʤs7'|>FXj6]߯|Ҥt&*;*%pK@;("@ PF7Op*]{ (0ݟ_;\K꺂)FS&%P L7L֊!G!D.V6c lV1+H(geD=s}Y bι)eg/:=x֞}\h/wb]]?X,L 'b_J FCj2gbCQԽЬvq߮Ȍ{"oxC Xdy]uq^$u] t[Al5V U!ʉ编nJ^+Lی,!]Bϋs5(#$cdY!hut~+A}jX#ij~R\Ytj ohߞ ƒKnsC#"LUGԢ,ieVYS.YOElYTh9R-ZŠl-+2ӟ` &XD'c~Ց|)g\ebYÃ#mUed(=41nTeJC32 D|ۭtNH<60;HɦG_Rqx(L*K!iJ~j|򸴧N_4ɢɒ-0X6V!V^e8n {V"cm#íGҫ\i>~I-) 1=Q npoh48jg_˶ʑut`&ۼ־w`buWD:XE'(l0"u9X,tXQG4 7j4ƊgzNe)YvhX %QF\7!J&B-)% z•|.2@ 峉MI!!` z|nJf̮uԎם5-}U:okhJ5 q;]Y2׹ZHA#nհcA;VzCr[>֕SY` ~\30C}iH o\4, JqFkb|Jj]ңfb;~6WP~^gv (Q  Rt3}sYx](5e #%W*尋2P,DQ!PTuxǗ5Zk! O\Uj;  $UKC/iiHOQThRsb#f1|˱T&L3Y7֖7LgQCEBLTQɨp`+}{YKipHe2ڛDLp؃17謊7jx-q(#{^#le=n&5MG No\撛t32v-\g,84ʷ ̳}7\A&ftg,mOHm-eQSYRI3250zf=`V}Ӵ:)2LsړRKĮc$v[5$M--ʹ^*nWfO)b(DTuMR]x1ͩ(8ѱ8"cTO{|O; Ϊ!iBX rP)7cEPO>nfR hH0էDDDS4&ţ,t{a<5 "x",Ȧ2R<XKOggSrA﹦01\W2# !"%&'* ! " &"$"$&&()%${ !" 6EH o9|^ڢ!@Q/D.aϤKNE MHKoMG؈hKaCwʳ*#"PR|y3W#z6yxsaoC ۀq0vꋺ! ~.SM 7h6!V7xtLTV4G2"c;NBOvȨDg!MVc^AaBLoЖkg32XkB9 5"8M W∋#hNVR2Zq@C\C,BiL$3s]'Ư9WwWDȮtb:/4j.Pz |'+_>\"ش`!=EEFY|ξ^EĴ(ZU}aayuZ]՗ )E%[ "UwH|PӊYBWN@ Jhp7Tߐ>)ݜXi<q^" Cڏn ৌZ,Jkwn~+eOHK4y*K.ww&Ze/> SѳMCYu[h,:@`#vUQ=@;>~ᆢXP5FebJEX4iuF к'׵{M{! 頰4Oe??+W9MAu(rnaUI\ێO-O=KhME&%6T:WaQ\@|VE\ӓ}ӝ׆lmIx+ lG Kb<\Dv;1+?AQi!8_*vL[o`d๪Iz^da$P3B ƘECNg0Y^lc6F1M&U V{>;p%4!@w @yeQOAzk/YF~c6{A"ҶF!i"eyZd}'6yrI*u#JܸPOwټכ јv/V{]ŝH]0!g^@NPe\y+N;7 tX"^n>Cڍ[6²9m֤Y\6C.54GHp.(Zi^k  5FNKf8]} Hj& )UX>\N[^1D DB F՟"&Jt|t6*M pRy;>R.m/lO`<8 q )bZ %«!<Š$3'ⱋ K AQcދE(\-B:4xDT }o%e1|,N2:wb[BUrtFx!lc*#ߎkv_?jOC`l(/O}']{>;}nmOH5Mc8/-5WR?2$f~,@-"OA$F쏭yvָ݉5Kdy< BIqTDN)~6}ڸ:wNm#]{ hf],p 7YGpbp ]P>\ ⎓ű*pZROHĎ:ߦ>[UO^U lԊ*HCshA[!c;yu~k{wcuE"Nj:UxЍQ\P %(y+%|Łތ5X!岋{Հ4یeOy7s"Nw]%٘nGu$`ZVĆ#zoJ᝗չ!6]DxRQ)!)R#jQn5U@ hsXEa0pǫo,L/ݳoסkdV#U3^W*^e-RR;br)]v\^aPMC5 [#$R.3\5R/.zŢ tpQdbb2+:M#.tyQ"T4t)D-Ňg:bjNPVψr$'`[Xe1Tk 3.q{vQT]}g]6Ys "Rhc!T[{RW,><<|yT Щj(l_ ÃWp*ӷMb,պ*1LWUPQ[zw9WI mk[D4LW"ٗ Yϱ"~K0ԴOggS@A﹦0|*# '&y!! ! (&%ô$"!%!!&'&D[tK"WYNcIO|9+TYk>.Sv@{|iĐ)J 1PDabM_#NR5e[}}ST_zϗZ~O:؃(CJVfB/RWl.AdH0*O!&.v>s٭Ӹ,r}'+H5T9 w1ʨ~e{s0g&=><3VdwL  I1M+X *qXJQƦ +Fc3F hG,.,cv7.LhHN BD3(¸b=v2Q0Tψ3uUT AR$6JĽpFH0*>|AÚ,]ĭ F>gREY4)aY%mc [F̪CAu6qʠ*AAšNt{^+dqB4|q] j-֘8Of5WϏ0{;w9'k֚ѿ7*Y}8rNjDف B&gǍyB`ތ-!LJ4ELHy^+:)!Rw;T k48%l@A9cj"R0jf6=w}n2Է++֭U]7]EX~n j,m""0&- AMBfz}?L6_:?y;F/l)or$edH63\,TakdDlCK=w(i>k>*VQtֱfc!r^0Etȁȸ>@isqb;PZNwD댽AQiCO $w,m8P!Fn 84':[Ki m|flgHuHyD) VeTqdu:^dgYAݓ7"42J]`I6 =A`|Vu71Ɗ[;sZ}^YrHXGcB9 ʙʪk*UAI 2mRg8?JKf? *#x*,շ\(3t!Z+g{AmiioHV&PRG. VaEêJ^>.Z?@_uZqHQs^ca:G7ۡ&a2\ta~xj0tv$i狩;ɫ?2a)yr)#؍e5{=A&Ÿi^p% U. XZ2q0ٌZ%-D`bX#, qu̎mAZiH'+~RF Byˬ5g!XGF&&^1 ycӒ8~:wȭzlsfOaD{KXK"׶ #DQE)U~hUxac`Br(^isiUCkp~KfSd,+YT\Ȫ1iFmUDbOmyX4I < &H;). AZӘ&wWh˯Ru⠗-zb8Vь7r1L",Ml)dxN^1`TwkÒ<٩G[בa⳺h>>$^aU!KH @K .!݊=p:)8%5 gͻ3e61µK!=tF1H?&Rp'ˏ3%wJ@$ĭVS&@!:la?T,L1öuƖw/f_c5,:Ek'IuB@rs"{V1sRpik?cSCOs1 |qn][bSgPJ6HRJd9pzA"#~dFT/W&_ga9S\}54븋*v4lakfƧ>VBpa @6tZvݢ}S$|4Vڬc><2{z=!~&3(By)v) Wv>Ҫ }%%=p(0\cQl0ƒGXfo-MX>PB\\[*wx%f[ђn_I` # ϸIKHf/l^<>UJUbUVgDQL)=UխiX6!.CPeHd]YEofI=,&&Ql'XGdcV!X =mPTU^,}[Q-la^i/cthؙ~LZ/3|<޾z{}Y&9Xtq-{%c1r HЩ'AS …+J&{U`Y/4qր *ljl>ͧ=lTZA%@wl*~ ~]iXhDJDGͻ(Уh.Yrfrkɫ[M׍=p=dе@(/5YL </ S4?e5",d/>]>=!VФٜ\D̤u1=QŠ͑1(z ;VbpFR\or "ɕyd >yjioT@6gfUJKv,v{&RjG.Ckލ5flggǢ);=HT۵Fe{=iY]gj78ѿa|QFH[Z.LFSlv:A&躪fe: hcN٥^VcC`+IW8՜arenKFiލ Qjwoǣrugo:K+#^ks蟽n i-Cޛ_Zv a]{no.ƲƝ `oěqQ|ՀEM3`b19-VuU_L]ԝsiE燱k_n 32$ڀ9|P@X%;4M߆RbܹnA7׸{|y4+B:_b-7e(][,V e<] wyDtNTHNQ$G=ի|ObqFwg.b;lcPHژ d53ݯq޽9 e{^59Nﲕ~Tx[U|LtT݃lŴFRcslN(  [ed|DjiԩE NeU4E^}g G,r`3)CJP'$w>Oo`Z/jQմIS>ٍ"4JxVqۘFD5cG #o&TQq ~5Q X=* xƬTl $׻wfI̦tp׼beWߦP&W@A5w)%!{ddr02Go8UP/ edlk lcXcehwvXy&QL``"T(ꃀp=_KS-J/-QmQ\HeOuDdiCFlg™hlAV`厝G: PʂP9Tںa,#!&wJ9WCTʸÞ:ܤ&M~l?؛ĿT~F :.H3'ٔ&X7ƣ)9*K2qݰ1z +QihJaSȵU8(Oc'ݜy E <2@ 4L1v@'`§c P`6u p}ʳhcH'D gy+kr]U8D H"BOW=Eϟ3{Vyl?jG֫)UD8n\ @ i(y76f[-k82=(dYR>StWo:[ZăsN9~uB&ciRLU*þ zrB3huu" \Y@EIM@ ;`( qDQ6OM^]9^=uY2IG@Ĩ(g[fĕ:xc>d1k`9M@KV>'O{[AoV Ad398/7\Vjhb˭qCq~ *ve&XV&da4 i{ߘl8\[,nIH+ʚ@ ll$~u`* @r%jŀȦ!I1 @.BVn$!l D(.>EB q:H.)Tk95AKev{LG#^IV1NMcCbPo2pcnpj`ʾx5 F}`Trh`V\Te} {ip,Lۑadx""xVjQĝe^uGGm fk"Ӹʽ4f~&h PG],$-@#őtI`"팀 j p!daHrIrV UtbWG C,WL?Yt:7RH ?W$XTD[֞k,oEAQQb|7nXE;I L]QP_ڪBQ" .ALY*&v_ɀY8yF.-gn-}"LY L>rdP?GV^]wu]4Yt-B@{~&.ҜνyǬإQ*dc YYr]}>Q e6i z4/me4͕؇"G @NPo\ _r޸DÑ9P%z/W`W+:TDk'&ʰ0blhY6H OggSB﹦0Tu F5"! ")#$|!!!!$)(&  !%$"$ %"#(ޜN ,|R*Xp(k%!ZSnޘ:ݚظFvrhh:8۳j vI%M9 Oa@X" KLUh9tDZALC6gR!{iHX7 bKZ *^|֩A?&~& v-LJ?ELc,G:vI]2_8:=cx\zA2ޢ#9#k P)A"HC è 0JpI4>./;@CA}W(Rŷ%Kkv/58.@(#YnxWi90*]qd(!RJYﳛ͕GC㨹"Y^^d8U &xodcei`]B.TUipVuN5B Q_zUA@ IOHQjujY=Z;nS®O|$$$BF$R=9qNgMehƆI,9eNR4,ϛentghRESV rJ ΩھdK`(ܜdY`X« m1]# |6qֺ 6/h%R]r,[*#/c_JqִhoU!ZW{?U0J"U Gs WJj+_dAaH*!p YtY=cD9D$r\ "7[-0{:;.(6:;$)KTdQj"IdD&T^4E5b%,nEp*`vUFf>U B5(R)n'@,;$T:v[9ThU?I+R?P/i$|XouBC@KpV!=K&Y7ec4 g/}h1@ <pUOHkT9pfZb @([@Ҽ1BUۋٴ3;֫ Q1=|@Ho 1B,+{ Y-9I1 oSD[ T&p]1Uş(Q揪Xfgބq49K"[hw2Ȩ&"I$ njxU&DWqie!x.a ABhZHB1XA1F~N˴hf] К炐sug.)i(29dJs$C+˅M-?ʨxȷ3 QT% 5*Bx|Zc@|DDR+kzHX>.\4Mk;`P+bD(b1 8O1LL&!bZW D9P`ka>m YI[n0xA!au-2@,|\CA^d~.<ssyi4{qrGS;FGD/wJNW>i).1\OTIh[ʐ^, iiY b-@ 咆k\8 MQr+cZRJTXi+39n[LaYY8 xp!OyȔ+[+bDYm"yWsz=1eT>սqEILS}UWrzwp H|&אe4OUOTxSbxLWv0XZ S:DBQVރxy$:u$_$#`ێ_s=_ T[ WT=wŴ΍R)],kFmy5Da(Ƙ zLѦZJ*:3L]͐2qT:{&DB{&` @`x~dfA1iOaOjtqq78 =JTSxmx7qV学IvC=<}8aʝ #qC!4P$.ea94@Pn ~l*~ڧD6E;&G(aV@+\=0O+=i k,K' y^jjShZs׫hrFӢ4$D)` O=w_('3|T0bp9i~ jBDӦo,"8~KfH{ġ,$̕ KzNct2˄8oy(Dг9p;J#Th9 Pp&y׊YennDZ >*qՙXQ9Ӈ")bDEB#YچR8.h4{IfIeDy.% KVj.a3bq$9{mqbZ>I>?`X7GKjS@Z\@-Խ)6}!Q,\/HԺTj)X9 fDA$cႇD14*YIM3٢=j'qt#a! 0' ~y!TolHʼ\Dwb*ǗAD<vCeXk,~VJ 4 G1 Wݲ"F{6e I],:(Oi*fky1x0YNmcb\v!-']bL^wVoeᖤ%I:W>$\- @s< hAbPYصc&+]] vU,>bſ~߱aqIOggSB﹦0NR7#$$ ""# %$$\eC0)M2a _$9dnop\e1Tl9VOh?)f:tz%5%\-$~(Oo;Gꮘy&71{~.8~@-S/_4FVQZrjhL‘ @ކ5ʧ*n! \#xY>LZ@a3 O^@C V0d*>&8gY{@ nA Q=O 2Cλcݒ_%,.m%V1ۖ[?+e̥c.7ɓqÿ)IxM>3okm8n^톆%[Sզ5A ~j*.3" {% (_+&\DQHr:3#WY \?-}i)>wi. |nCo/Kv~=wft0Ԛh3zPʳ DJJ'˜ x\5xv]idsc[bKWb}lOIcXsju5uuK?#Xd2'XV~8hcY 21  K,FtuSą?l2FR?֚}>nWwyS6{vz;|b_yJ5v !PT&@QyPe !f޵/eN–h1-ІkVa!`W@u"Wzkׯd7q\޹eL̆_*=F̍ʴZ br7B+ XPZ$K􄀧=YRnz:"68^cj>bDKY ˄Õej@4wE޻ERpEiJi2l:`F4fì?|=;ٝI׳8;vgݦ"Vb0H*@)?S1~`5/s$_֪~$k{ N"XI۾(J^ƁN@ "|>/pS\ :˯*#yfC39P |fݕԐ HoQ:Tezz׷qk]DYe_3y4,&#VPA$0D|);Ʊ܈gq GJD鎿5뱆}ӇEK.3j=M'cÑBiǸW4]<,zUιn˺|h^_5c`޶wKlO@ <,^q69mb%G;;^{om}Vry'|Q }C$Ibr;q'T÷J[w`ZFWk9 Pˉw7+Q#헬j,! \fE6 e #6K&_sBDMvEH.3H`ˁ!d[lĻ Q.`2 B:@)O/ҳ)dRWCU:=loRStlXqVUںYb) @C#owd o]UJO+I^^moʗȝ' 2=|zhsu|}h&.) G5^kVn4I0mt^fyXQi%2"G15]"u3nK8vn#T[רARprnoa*cHUD[*V#HA;0٭Ӎzm:QSTDYUԾy\\O6o:N/:濵Gtc=xXevmI?7Ο;i񻒉Tg{eExv>\ :m(Ikڜ-1 r,tX`0ȌzsYer1~+ঽC/s#</M>V ڙKŢe-,;1=?0=Wކn}bagkN]ʶ ?>U)9f(JO (hv-a.J ƭC.7>u@@xz@ E]x$ɫfvҹ})seۍh~YFDdCDE j!̱!oSZLzjv 3}&# FbfCn6~lgQsZqI w42szm%~6^2uF\/W&S M"6Sdzdݺp";dK5H2:?4ѣjzNR!jy=85Z˿zhvg=Nn(HVTrrG I״*iI `g2mvX0\gF |ļ$o$:|MttR4T xJJVL/23cx by͌)#mp2[#I>a:)=<}]G[D,Wn BF+.~6~e^5{.$E&NW#S\j7uڍpV*(89w×͝!\dzp^HDF==.s&6 |F߾py_'IT135 ᑉ$1/Q&mj( /c- !OggS@RC﹦0n.#!!!$!)&%"$"!%# %"'#~}~^6&<lPBJh|N0^)`gcALq>t_9){7OqEc/c&Zaz] .8_iq`xVt $im^WNkUr7#F#C U沬UK2׬+0*Э))^ZHai;%,3}F6O'%SLr[>/?p|鼣=ܕ4DNxon;Kx?v C=U?*4Hk-|8/ݒE~R-bDt*0u/;.qZbmvD@m ژ-L̈aw§r47ZNw8ii@,p[7@ؔ>%?4 5iƨ|֢%?ӹB`:Yi3~EgfOCopU͖juB8.wMs@Ŧ$d(HiRzwYbɕWЖw.q=Sb\"!QV농d8g}LYi+r3'ͬdTԲ L +,bsFSHw;?Myfj^J TWAt$ZTl zP<6JS LNӻ~VnfG.DׂxׇBA7;mQ\(/S\WaTg47p?tx($OFMj=t~]c6MɆgmPdK&j%R@O~ŕ;-gAT@k/ZW<׋W _'+K]v.=,-w5c;8(b=,ՎvpHK[GD4_X4PnqM/VFsX|Rȕ)p|D3r+V+PzY~N"ʈ3[Rkl6{xEtK0atr㹟ll5O3LjWzXW4lA|_vo\M$MazmgkRD%I$Ȩe+왤U#㮛G)J7Nrr![B<[_ Ijޙ\q#5f)wnez"[ ה5h,F1pb=BԚFLz&4jĺ~|vh;>{VV=H-|NǟG:\b c)~-[$ Q6Ty;iJ<]=zInIe*{Žg&BZ gY4KJA HA\ (^\vQ tyl *JQrE5 :\:X>?aiUWe7Zo% ..k4pQkCMNe; (#RJ¡`LY"Q&DONX,K֮= 0|dEAlsN7o^]{˯ryheHs)E9?Tέ<}}/:DwFg5 Ufg$&p 5^L7)A ATn"OGсRldrXfBBYTSv4Xk(Ϝ^Ynݡ\]+nxUKC TX?<pjj +ܰX<16rpH%M2GM6 %4b V]i`뼮xjC$DMST+s=Ds\NŤ)* DW5C؃6j*iIYnN5)yL] Jy<Nv zMcMLx'REyIUqc-$tOm_]z`㠄jH[?:8t{J6.(w7ix}.Μ'~7Z\9zfX'J> pM]^_U E; |e&  i"JDatq)_ wwp#WY81'cvt;LDD9d=JWUTo)ߧKթ u[(m~;E5t?m}! ޳Y&'\]~6~Gd3N x<7W-d WØi ;9$o RtUɝůdSn.+%dDx+VhĢ 2!V$!hӎF#d4yKR]d a(,Bb\r'ow|u3_Od >̩l.KA,|ʫ'sKς DRׯ]o`(b3 \BFā1<~8f~@0(J@pVxxB$OL@qok,u?FTC̯t>M/ϖ{<(V?f7'^R-Ym:-Ť:Ό8WB#v 1oMꫠI\[WkenV@E uA%AEXOggSC﹦0)7! !!!#"&&#!  &'$! %#$ ! "")'%<Ղk+g}y=0Qyme"dU,㗳 ӽd{80˜"\Uau[f?G~*3 ׏v/#GDWbU6vvT|v#Vμ4Fw' L1U5D|)6˒壈*DSYjMҊ֡k3u%sLUA4DaS2_㙢]\:"dUv]~òO@7u/h+ 3dg̱$íHn4S^Y<| 並ുXN:ʨFʣ}25pn~Nb@M^vEILEn2~K%ͥ:]6Yn\v>z G+S4E uhd)$ LY)Сewwr "ާ{nWzmL?TPP[j\K>ͮw:H٭\Tpp3,át8XNvBdo*Tsy|8pa,ڈM΄lϯfc\F{5/Ǝp} nIۃᖺ껺v+%zAQE!7[BeY~-.<^jBk"SDk ~МYOѲ,I!gh#wC K뤀S14J-H`UfY!* Xy Kx#Wz$GȖIީ)H#=nsx\WeŹ#%V%k)[ VNށ$ bu,n lkg磾Emr^ID4)7j|MsM<$gvo_O Ij^_C۔&-z0 (5o $_9~#hV԰\XW$T]WrmN_ƅ4CRϫV4uño.\WveǗ-xPHZc<ց\]"]-L{Yʿ*uH U%J\Ym3hEM|kZ\Y(t9@ysS0#++TWWV9uXtpV:IL[ۖSi>z_Ujk lc NK `N^urﱾD:64cncZͰr_ 4L@p?Z}jYNCye\|3:VIK'As[\_idiֱig0.[ d%xypAAe:Tŭzaz5>65/:rB'7 PTKxpG|3FR?v47\5~0xNGҼhf$Ʀ3!M?~|T_:ޥ`éoQh@ 0 \<D cI`kTDʈn\.U4fk() .M rѫxQtzQLGCzlyOp'bo CHཅi+Nd&ogyvHCe#"rN`E 4{f8Ez g>?E i6Xv3QD1&%Z]EGӣDw%ח#՗at $KJb.MPdx*D@67{p#*DS S> ,NG RYw"\[Y,+4͇njӃқn@M\[$k Ej~ zl0kf5#LUYܗEkOMK܎ŸVʛ ,SL{*j n,(*DTWY*HTZr1/U"zٽY:T_UP`׼ u0~atTaU1&8xڻ$Qou4옇Tf\Ƶv\cbB yVl, #EdӊLgy[c\Ԏ(8;w/|TEu`'ŒdH?tpS?b Fl]n%X;o;f 1 t!}0;r)$}l"ĝ nň1v_?zRDӡr4bDyENżl7ο}C4ȬQ,tl}4¦T`RmyZHxm1,hQk;ia ʤ^_1XhXbEUc0~6:F)H VP4*aO(CfefIDF/[㲧ډ+/|cH YF\ 8,$C!ԡk-#pK=+3bZaV(͑búyX& BU*1ց 8>> W͞(b<j4y'J!KB+, s2rr2;a;'D^oʡܙV^g%BhVqU%ՄUG(q$K9,?Uի,7MWX".cY*I /Z]W)uHO@l(:u1fp+ÇR+WĚQ}/I#;$$]PSWuKU3TIZ*!VHDhh( Qb#Dz ~O)V-6]o2k#aφT6F2tAuövΪnGڐlѶjPbYj8F=@c (+P6ዥ% P%E),=XX%{-XR~-@@챵  nDE7!&hpd 1XSOCRf-$TĠ p\LR|LI vnzP e-эoE8gw3sOh,kesiB7%wLcO:{ܹ~xPtseb~$xސ]KOHaOERbXk'/sۮYp?Secc '|.AkF*l_P2s^nLzzPJ"|OO1-A`T- \ߎ3[8V9/_%F}w_WVj0PT[ nn,CxhXT;T5L 5TSdտ=Bex_FCt8\[ңmyhfnGvLґ~q8 DaJ.5I R xCXCV̞>zkVtS$p\4%  ?B\8˕C)Gg3W,W8k_4z#b)~rUd䌨h0 \1櫢:,vS\.nix8n^^fѣ0$Lc!lsx)_kHe+ȝҎ]c=zx3ȹݮwC]2O\WlYgH\_sjal6'{bң<,xm)z䦢.D#%B5*F|(AU Yj?@F: hN>*?~~2:wXƎbk'juӷ?cdGN >::PPxfmE0aȌ`#e]jAGXOggSD﹦0% !!')!"!"'& F&R>b@xeĈw˃ύPDD){}y~vb$mp>%qB*}gUz*7u9BA Cd[|UAz)5BXMEkEnX"hT[QHs|y-1=ps _H }fmJM\J/%ԲwU2BԫX k(A7Q@ . è@co/hiNlxplkqv276J`dfOǼںm15J8nI܅W{1wok |fLR2BClIM_o)/Q.5_}E0g!{g%ڧҽIPXZc ځ C?[IMG%Oo'å34ͼ><||P %摸ɸk$$p}[g<1vP:,z_3vI%agSJXi9gh4~ mXKHA\LBO7WW:sdRL7>n-@x ӡ"b2qiBHƚOn<{ӷ畣Oqy4;5ݷ:kӼ.9nL+esV$ l3WϦkΟI>6|(:ttKN9n5QvWK+ٱfcpP,W ՐR |z|f yt%lGdXeG#QIbލr믿oJIz@ N"Pm4_I4{_Gѐ-ACCg-uMƈN-Me <`b3rK Y㉶pYU~|vWl&C!a`J'ێ'SG/gr3K#yu#t? 4n}*tS{bD۱r34Sݲ8M<Εd?f}ejyyۡJk[q&=Jb&ָ\ZuF޲^||e ӝʕRg>~v$1JdNKg =zӿ~c4$, {Ki` :iusS5FrTp@[>(>CMFoSLdrw47e<ƣCU4*e#n Ω7| )"FAnUMC@ (g9o콓h׹ !_e5KNwV]yS,fH g"ڶ^f&o$v%hgר榾c:t>ְ6Go;Jۨgf}tt[ A8Jb~EF9vK0 RpEapSVEK vGE%Muѱ̐مV l&I1[5W!!qJw{dޗrt_?5 1]zCWZ5Jzt$Q(*!FmOz0$kiɶ~v.A!xg  "| (UJH2q^c['!G)Km.>QӗB;x ak@NJGÚvz IIFH%m&r !Ivo0Ƙs Ҧkt24L;7;D$HQWmK^@?|h]F'|.pv)UB-5) c\S.F'GRNK=J~ aqqdqO1"PYyZTK;m~*3!r$ѕVdS.Sr%e fa@Jfz5T0G~6dPD|ii*N&;J)kEi\)aIhḫS!:S@ecR tFT*yZ< DR +k8v3P!BH>G)ՠ3/:ڦX㯔Wv:&҅"$J 5 >1!c5 tĮ ?H#/clQ4f#lGb]QHM R;>PѸaĸzޘ4Ě[lgt%S7$߈!⍥vȌ.\yW(Q^u%@0Jp +Y/]J0u&6';w=/o#fmY6#U|Lē- !* ;{,HKd7N"?Q:ו)o0 zjyP I7\TIDP!m^ OggS@uD﹦0:1""#$#" ,%%}z!!!#'%$~$""# #(#~kA"4-Si ;ɕ+RFOMx_f,޳ݫ ̌K5 ypUx__\(6 vܬ^u,Xk٧YI?VɇL;)dnF:l a6fԍ1jYƢP^"A0/͘!x.Pw TV?Uz!#Lv43BtKCWT;[>Qk@ƬalyfiLa{zπѐOmbOQݞQk] AeCa V2G^dP29˔!D<DIUu"k3 Ïuɦ$z!;:gww+lGwC Pi"6:AIɑͶf3*"+m*)}<'j\_ 1y.I_Gx\m] aB1"+]P,[xQ/Gu| L[A4ώ`Oýx"GRj5K,U Qy^9sV3ӿ-؛aEDSQV_u҆nQťP,Y#=dn0HC#kDzw"FHC(LY B\xEG`:; }@+CT,DWjSivh iuNH)EISG)s?_O:=UR( O9(y]ჽu7=:=Qzlc6K՚T؃տG_moqya TeY`'|KWqCNȯ)+׏&<5ґ 7b"-p+Ȉ!L&ę P$IMk0U,eNwCM>^mK::E}w'ErWG ـ4v%NnCvC`;P;v r爬2pj! VcG#Q;zO+nO1||;&kAr3u:T?8`Ҝ̏Zs:|nU!֢HAD:'Sp!X tƢCbKsתAzFIB$Zɓ0s?v51n̎*҈Lť+`q)"M4>`(l{ Q 'хtL39QsnU)goǔd$Z;dD%٨#Wr?"`J܅j䂌JIXsL@{jSptr^)S>ҌQ|p.0.nc.FbJCRgmP* i"`<5Q$([P],,bB}l6CAP\pUD4& e_9eN=.iZRˣ w>RHNJ"!*o2|EŮCbcYBCH . i,%(0 ^5IhPcQ;H:*.Fyɒ);˘'96w,bJ%G3̝%>qF# VJ![hXLM* %DhZrxIȄ)PJ$c@nhBt) ޭ.s)iҕFKtU >݈n]3i]&ds#;>6Ma:b9s( AK-E:1:vN/$Z>!`rf:CXѪX[V(ri ׅ+?(8P3֜7G6N\]n{{ n RH/gWbUA0p NZ|8F9>АHH(BP?؁>XZA[֩]!/t -AdDewA.zwpi'Qv{<~6Iire:nu{YR`"ޒ8`:ЏZ5V>ئs$ȨU\`Z;~-IAZ,S&D##( TWaSU!ÃنQtB0Odaa98fV,Ր9*#\W8iFܶ_ 7~\f=XMlf=x:iWlDD4/ۜ-chng5Hr': H @܂%ѰGĞ/Sm-+j{TY֜M(RL2v.]M[¥*><)vN Dhj'D @LD阆j%9M2lbܤ_--G fW>+ڪ `Dj Kr ^8GpMJJB֒{ّ |Ƶ,yCpzϞծ\sWg-l$"A"J$0g̮^q6Lu0-$[2y24  '@s%UI p!q!-b᳨ ! EEc.mL<1>'ϐ-VF"dA""1NC[ۄ$7ch8KlNӷz~u2S@Pi9pԘD& (K vQRhFAKh,e1: CKS );cMN<҅`+R&Ϥq*#8(@ `-Q<{4ʽ|v ".%WKԺ* $BH~žf $km]RV)=Qtbч@y,;9!23q6V.wm -QXy}8DzYo3BnjR5 HHY ~lmc!(K6;s*weS}Jѣha>>pa9C0]!'\xX @ WA"Bº:5 " Jf, -J/ZBmUh(vK&ʼEMc 7ȤE(3hjQI\x'"]$) Od o}/0 DV  [y]uՠYP"KT5U;FҐDWd Ն.c lɿ_9DZQ(DS+>3=n*,zbRV˸@T[=ïhssǪu@y?=GnH+n(Z4SGL|sXچoG@rC\H*,RJ6ՉO>`C6p8WdJeN2%%x]"qC;eYXD̮I&Mۡl>Qe2xuzu_8٦/ջZ+6:Ƴ/⧤_eZYٞ"y<@x,2 ]KOggS@D﹦0c4?.% &"!!"((!""!!#&!#!"!)&(^}A"xV<| :1}&PTJFFqyJ,b1,v M>%rH9%vRdŦV6 nL MQI3 iĕnqUGw1b֍gÔ/Ps6+¾NM5}Ԑ煄rBQh-l.wiy&:~cUa{%ʩnl:`!@1`dsb{m+H q~64u!DQ;y}|E ԝXg")|O>aM.vJ20.n^~;&ɎJhŴ?YNp/ກi$tf'vWtSo_yezJ[!R LCw۾UeVn"R???nw2ݺ>uY)SR""j}բl5`cɯu٪B[t.rz˖IH\@!I T˝ZED f1\KԘ'f%TJ0P!%TU*ģu xq4?oW8mb\WjWV!4 @iJu,l*9T[ii iK①RtJA U9A.cٸ 7y>% A~1dSVE'611^w&]h<+12ҊF@RKDYn=eQC![ XRPT cQm|o8[}D~>߄H?pwOMT4|NAVkahzl磫{A¼|g8:hN2â ܓDu~z(>qJ-E+ I ʂm(!-rxaVT2"XTaXA 8XZKATS(TYޜ{b<|'K'4I5j̍Lv d]ӭ 5֞m-luov}zARL[{.~`[:^Si gPLW*$*&9KBKJJ)֪RLU*WglIws8í#U˭L[YӖZ*R=65=fp#taH|F*ݤm 8`}{HeͯBqnK`~7B_Fhs-<'?z["B? J[ڵHAaSAWA{V[C~@!C:c{̮ϦiZnp(}#c#ӫԃ8zE3&ܪj[fo# YkrLDj/&wPqw sG -Z˧'% fÉ?1Hc;t?_f[JtsoINIZ`Gh@0hbv>x_m&KwRK&tZ#c;H K%"LB dX+dn(s  JNw>V DSUՒ@kImző~AMLWՆVwkyqǭ"CtDۉ3W1-*Lƒ?0 B4i4W)>|sْz^j»wS្ tcH~Pݍhb~ߌf1_le}WYvT;z}T|l~c+tp%˹o$`wBO%ESbT>M'H(iO*ϊ琳X,y\^yl#䪞/XT81@ {xGY KX)tBѡ鴍xCl\H} +ׁi4>n֭AV/XxZ| bN;)v!;`FNp,9lizxus[V»QbX Ԋ1ARԠ U@@xuK ^J=G"t*hN qM0,Zf󔫉}LC(S41F.a*NMHccӻǾ](@Y$XK$ABȱATRtE \vJiwpI&,*I>6%L݂TZUi)1Rtp`.H (N*lH2wi|n"ɉ xo_ֺ%(\ AW[ehXj, 9b^")" 8|6IfKEqq OggS2E﹦0.~!"!##!&(&# !!#&" #&#Si~&RauGM\jsڹ2`(Z|˜fE8{F.Բ;QgK_Hт0!kB _-(,aHIR/(ಀ*.=nu6s8)! p+Ic"H-(z4>N[ZƸF6g86Cx+Y&V˛%u9UK+|Ԏ/!f! P0Ӄ 0U g]"@#d-\`pR44Da*{4L99Cغ|,"x=ܢqV­_2ө.|6hsqt8Y>"5aM.$Hh^8ru;sec(:ݑW?{nrj<@rc0wyNt\/-?sȤt$׾iXrP9*akC+FVב8ZxEDZ{C8HI{_?QZz6? N #RCC;k7g]X9yÏ[0?m!m k -}i1{;Gbgѕ@}0ٌ U2eJPF;EaPq TW* jjG\  't fd@!x liO4CrRvOPl-lf:>@ه"s(T#+zuH(gMYB0+,ƽbm Fsq8CáV/(/#/}ZEz>pp~_xѸgN윶\1)]UvPe LIV%Y#QQ~QS\xc9>Dlu)@ ]v, +FHmy_+b Am7 Lx (>X&n"^cXح[iobt($j zsbnWZ3zLM]XnfK+7R5bPSE0O IpM*K;VJWŘS+lBhE iLT-?quBT`r^q(s뻜{4hWG/?λZ%zO瞳lQ4 D:J|kᮤ1 XWBm 6>7. ze)VS4WU^YjA֯1n%NMbvY\Ym2yb`)eںZ|kLWGN[`&w<&ɵOro,ADW +&ss҃=G|L%L\u"PDUL,rƒ/E|Ό!\UҸ+:u4|O~Ssv;Xq(LYS-2Q_uA 򵓾|V޸%\aö0 'ɊN}||-Tvo9 TzcnbEݘ #SunȲ,-23b=?=&BB9>М9iv:n+ ws{G?};sATs"}DT@'|V󙫃Z$#)2pLŦr_ܰr=&Pyz^.ތ4ap/;&5Bh FL. T̥f&r^\֧ z'PotӭITW + sVB>Wm7l$0DYtOIƇ&t{ZRzq_/Tat1bs秊ovC:U%+ApD(ZV*س9Nq?QΦ%3oYϗ6Hz\ݹ_?ͲøE_9}VԹfw- Эƌmf'~HV] Ǡ(8/jO\l禲-x9Ŝ]yY5/5g{owu}Β:R Je~,fQ@vX;xNw@+UU]MfQXZmDiх\ctޔǗتz_3S"vVtm7l"nzblA@jۥ*UʗF_(aOyzcuN&Kjuosڧ(E4֎X(˓xc~lI|f #d.PMlfm3̗̲rt4z+1ظ4rCz(kZrShun=zj:jŖg#bX'0<*S6&2G9[?!zn|dH{Ҍe~AAQ0.: N*Ԋ%~BDe6) ˯.vgx'ܶ|Ģ=$ܽ>bV+'`S<s;̌˘L%>:ij,2N!밭 65LÍ+V1]-O6W.QTzJBcrVk"{EA@n0!7a\y\\u[4_'f^4(!HݮQeeH+ s[A;n}Qטe5(q2]!Ȝm͍}fA Ѻ\~w^*V d8ĬlA.h13DaJ)~#K{‘̺ƸtX0WOg &7FcSw/ATZ|Φ~x6vj uD5ic>'}7B1RzWt>]Z)D\0ƀ@l(ړ-\'t!@C-<[4sz@qSr'4>HHfEIlH69ڛS~>WiJ RQ BlYhᤊkpl:Udg}iõqkO;}c嬬ʖՖ2+G*nr"sxGIOggS@E﹦0g2$ ! ! !%%"!  !&&&~ !! &&KS,_h\`~*2QR, dx)jMq5}鳹뙪.:%vu T.錀QG#рJXnwEa1BIbTCL8X`;^o^zv>M?6#]A:Cڋie8rRǵ9,c,[L_TO]ڐY>Ʈ6[#7k_ b - \[ -:i3(<9[Bw~ L]D.Mŧm$/ HyP*L[.:ekw0ϊ5~\I4[xT(qIS7z_H,CqD[L,JE{ߗWipZ]/PL_L ,#z1K>NZ8T]5WUA|_7a10|JОΥq~lK&UDӎ 7:o*)[E'%hʡ]+•*R{^f12Y! ;\?!Ft|mgSv6fnFptVzˑ4 Ѐt 0T\"^GUZ t JR*h(wT^ 7YtALLxg- wڹ>LҌ3Fc;|DL fFҒOh2De봣Q#%In͉cWڅeBc>}rÖtD!4ѥ6: A01LN~ڀ^uPF_O@\laB-0eZǀ!@ g$T@2V-,.n;rM2qSd8zx٥j%ARk@U' A'ph1+B+ .\trq,.(,i~ HP@7Wi ֛JU˘(5Ѱyrx0Wq%x2)7+ d] *ئ~@Z˾RLsn[?\iYs3`i`$B^dWX*r'z8XJ<Ƭᥙ Kؔ'RD5S>cC#;MۥQ;/;%&[O#I['ˉVC`,埧@U4Վ LV\놅e$ΛbA,6*/L)",R%\g]a60QO^c%rhdL|A 4Ӄ"P?#TVWIǍۖ,^*bˌmt>qK̜ƤU@%jxY j#8bB57\T3Fn7K&H-~Y0ФB(ս0Ʈvsc h‹^zސM$0 DD5BALSuڱ.>F1/ZG !ٿ%ĚL[Єx/:8$,RP8G'ʊ=0r=ɑPٴ' F,LO7rXc8@YƎ&p*)HE˦sJ;٥ ?9;4qP{"%`:XC;ЮW$np;/.5hMB(TWa%P\NSBlx6Tq%ӞgiL7'z!aO>sF;61k΃׷݉vpJ̍:S5}Rwe!-@v5xPʙ Of~Ga!RoT1ȅaE\ NHn{S)xNZ>&qcK2sljN2ph).?1YQO:C.ywG,eӿ*?a*)f.aX?= 7mlzS<Iq]*Ծ,XuĢ<7 Ǹ @Fjץ"g@J IKL)]ш~1.c!Nzϳ[c˦}ыOhRԴ#fH$ *mXA跴$ ð U@EE|ET ?Q~\# X9\rzL5'OE26}*C?5_=À  ‘]h0\Q?"QTX XnV%A,;E"P\&(k&H $n-;"R/,kʌǢ+`qiDFG"9H^]^s{o6L:q&D9\k}zf'>\fpp|~Nh:j޼DL^tӏY,i }8=dhw>q;FtEcbXK͉'U/+ed*@@BtHZhE=\)AFn /1 <`?AOjNrqؘ fl{GeObI"]ڌ2lG+k pSo{\UeT%^C"o`5nYU! fk@qkP oVDU'py'" ttMgRp|Q Qe+kx:dM\W)Ksin.^x iczL:VTe9,4$-4'1Em~>es_3o ,`F8G Pj*„r䏋ĵm~۱I~rNiN0^9EbfgG8ntNx52>+%&jpz;謆l1_C44@\Ko_p˾RZ FC^%a D;X0RKfxzX&ԳO4hqGXW7yE-{2X #+;VB\43F ZVkMYň"x<`.I\ҝ> K.b1 sE4nq]r#^LW,"tyHNwDD?ZF4o|!IyɽD\_DͲ W_tAan$$׶TgGin_dg݀> P-k]rEJDVK-z ^-  dd5|u=j=\؟fMtd:I5,Y+E* 0bsޟDh*MIH$Ŀ7rL_U^]0㈑Ã5j9_~g!ߋa=UJZ*`mQZ*IN.JWUkLJpOG B EfMDw({GlE!fh-N~},x%d,6炁S)cOm-uZf-=]! ղ#~#(EX+p{!jV*:Ԥpi #@t`߸;;*ϵX, ^ȼ1?NM:v滛ӌˮ0KqNAmiޔR&[%"cI0B(e #0A Q'W`QZTOHTW`]vI@# }g.x8SAБb|?I&;'K%e8qzInqW~^0*[A€:|- jRx Hmck` KL.kQZWpt4(߶EiI2Ok0qix v LT#@0m ?+L+𶻒6ZuŔ}b@BXII0V^ {^#@/8)633+d]zn^xq}qϚg-}|&Dg→AC^`RVx}VܼꪹQX(zz=%".M.uiD#%uBXl4ps+0KB:Hs0H:χY$3>Poú(&l+3"C<v =<;|أ " , 9J-)qmS.C ;2KG&o+M ӢmJl^M2L>5r7ۉ]Qd pj=#TjI(`j{Cs ׃fW9P;k.)}-"JnA"^pK&R8 +%E(W"BE:c͇oݱ)ؕb,!=W7}cn X{o,87>o&Ĩ >V {ߖT B Ta [.4ħ>4sn"R̥Ƌ0f P}RDWUl)=ǭ[6-VulETBGYo>zEI@p bTY㫭fEZEZo9,yx" kqmv0fUUu`SlW>nUSV#,WUDUc;<9g`*h,",ղ:4-޺v 2R?wvDYOMY^[#kZ#m/kWP%û W7 debYYp+8Wב~\ƨ뼌[0=Im\dZp`-UNGO|ίFzֵ2MnZ> ab'\LjH8), ֛do%%u[3Ia~m2郰ۖa2pDF u@$i#~6n>Gd|{Tdg L'.nWkԷNA*d]HkN {ݎ.:@ JW=MDULsNO?lk]Ѻ/IY bm#NC99ܝGPM̢[N/[EYB+t1Vrw9]#xII1F >әd}D +<8V)taȗZcEwzgU_G A ﻫ͹UT@4m)7Vm&tELyn;06x-PB t.nDXvpDY V`6NU_[J`ѲGP𹷓="sI"k8gϞ&D$a vyUuvjuMdHoԝoO4 +) 㐚W4Ѱ^dJk_-3;GbDM=Ux~"gPj\[F-.(.u+UTX#\arYP"'rm=8F/Sp^HKQTUtՕ<);)QF-CUp3ŪBپygi (4Wg._>Kǎpkׂ]뵎_E`MHL@iVRZVD]Z$y`~|),{E|g0APӊRg(dU c_]F|էl,]/{bh#ϯ#!!MF.ײuooܯKCf͚0=ݼmTJ}  DYee0!7G:=3 GLGIL[BvFHf>ճI.RtαͮyUi)٧ĂF^~ӝՍb$QUmVB=u[ e씤/LNNWM\af,bYWbzV^>L&\etWirtЂ9c+쌳XtԸ2n% `􂉤!3 cWz{juZ?G)ё\dGGơFDDr{)0P.@3[N*#ђf7p11ef#]hjFGªi-ϛFtzeAZAhո<YtvW^饬|&d)(f1݊R "C>3ր %1 I\K`(6bxl_Kh\ӨT~:e2''?2oЕUZ҂0VJbY) E iMCaö ׏ZNSG-z4BIuH1rH F6syC@~,=Sȸ <,?cD*/_{כq~$w4wz/2/VJҾ- Rb+IR,umj*T̔[ UUeXBdZu^1=Pc|1@p[*BsbO?s\1Emsf&-QT[0kM "{ԃNgF fVa)ώ. qyz1lK>Jq)?JBi*j`(~n)mRQ>abvZTїr:f8#Il]m&{%cs؝$׻1>Mqn XNg*ʾ'k=ؕǚjTXQ "eG*; ua3 n Z>L^NL ٩3:T:JSv:Mu,bdpE%ӻGykoyJ貲 @wV]UZ#@)T(+ }u⺡W! e\ q<)ުK:Eh91_V߾Ғ5sW6BTA?5,O#^w}5(ȧk}bN"F!ԡ߆EEJmMV=?84$"iUeA.D]UM]DI<4e;y5tpQ.TWSVYA='-I`tj`ϊw T_Y80x@lxe]nnW}$LWUԚӛjX`1dVh΢ b LSTRpNmܯ5'}:6G8,Uu-v22La/8=ؖRN7nujReGyC&-ajќ+8<na8EcA0߮)y/sTs+'Dj\%c棕и 'ֺEr-0X^z/FFɆ$W%O%'Bùv^jML*kJ9X^LSn$Om+8sIy:>mow]^F^|9<.{^saO|W.Zp'87#Xs 5 W+lqYJ'$`؈^xQFZxmpQzA>ªeQ[T2=N p }c$57@3T0"C~m""iãp6Vаh(VpIv\@@@VGMw:FF)1ؑX*+mzoGrCD\^C$pt-ub|_rAsw^IMƈߟ^<9)Dd ig(eno@v%Ƒi@>DHΛ [BFdWwCJG" O[BgMV;9k%1pIb5x56c BpXscv0X|&ӿQz;C"wC,bx)56AC5w_As\Ma<+X6k,ajg(56fpB!sj; f|K ĺO#8}>nߕ65QH5dDUpjT pn):kJXr~(<8;gu\<N4Wd15\zI^^k/v^Ϊ"<]]GN}NCśF :Us-0W1ZSJҫ}%X+=3J9Ǜ7S}Wھۺ}Ո>p)FAM{tu7@_:Orb30=O UwEZ)=khu:_Fݱ%&O+y4ޔ+XFA]"Ǣݘ^%ՇF4ҥI;}tmCun1_Azk\e#F;giܞozfzX-=311$Vu12vzn WAG\UTOggS@F﹦0̩Wµ'(([E h,H\NXR5"3Gz;.iR ۾­y5˫ce!Č0im66Աy2ebAcĸ> ƍSnױn8ݹvUL+_*WSjvIucvD+\Y (qFXK% ES\2 EǢ({v:xRV6MP K!֔YHCl2yѸc [֦/s5O8.ӽ:5rfuzRWG 8|MK 7Tτ\ fC[X!@7̢ IW_Q54y>?SuIdN%D$`#\gDTJ ak5dv=62}L_wj^Yf+@;X1h" /$W\0w!@kqQ/p7K<6"/퉯̪õ^& :prΕ'FPҔ5wjT]qv.eQ=|޶"@X |GTp:[erz`o@ [%2fIzγ;ב_=!NUnuN?iv Vi7y(ŚHy]| ~˅hP3o @H]@v 6} 8a?qYĻMn3Vh:Ќ腞ΐ*(0;]x$4SNǴl@31J Fó`J jɝDZwڦjn~҉qu:u=jt߱!oxS'+BB7R {KjGjו_4 F?eaE$G.AֳƱu/ f&TD&MJ{k4Zhxta?~7L5'c8x*NeL|SG1SS{'ֹbʍjNR|uÍ*e+JbI~ &`F+ƇoňIzX%T\a+Nθ^ GS(WT22 u<(oz?OA 5tyfg!`\T`%bnػfMTcQN}iJ~cI5{9O~r2=oF8Z$4sf,W RFS$yÿ V8 xb+Oฑ)(eL ֬IX5]h~BvjtuZI'aw)@yZ&>CϊHbgG6Cc`zV'Q|=~5Oy)qdשfNo |ꝵ>!r%.R@PD%c`#a9!qK*,*,I|f/]2oߌ3D:iY haHrKukxdu7;ŷ+b_;PSx16Rnf ^^/q9! iݮRsTDpKzcX ~RPޠVL*&4ÏJ|pBRͯ.[6fؑƽI~;^;|nc1TهtH^+%pǠ=l4i=1UC3ޛ8-n( [cM_>|t=JEQ0M8^ Si ۏ(EmqNI[fMӻwkW~umB5$z Uq( &t O"q7g6ڏtqg1PY|{(H(_4>3z?ͮ) @TK~L؁躓ip?D4OKl. wDS#vǾe_NJ[~cxɓETA o ؃STUR,].kt Vq3wPdzuCYV:vpp(+({67^9cSX8H9!o/; B:dq9Kע+2X| f$ A)Ӗ N^$sl\`s=S}QSg}JCX*/Yű7)JY\ʨnl1%I%wI5W7R?oL'٥n?ovJSiJ2\dג?tgy-,% B tc6~\C-G gՎ)ZQ=o,l`xB6ӶRH)RGIv+bc A€y"@&:Iyj\4~dn-~lOD?l߽ΧRPSwo/!alt{JUFht sL|Nb G 婻bkې.7nzCoBxet&^1I(T-qN{,huֲd)kx/|>[**Fh@??W/~_|Qy1wwE];KY*wjcO9 N4H&S-57)N% /ވeŴb0.XrcD\ʕ3T] @,b%So-YOggS@G﹦0W%!&#!!,'ns@i8J(p}*TBU+OiH0 Fl-J]:[/y$vIW-y(,XuDwz q~א/\f65*z9MjиkZu[:<:nw!qj{띍9}~k5fF.47w1~͞^H05}5+ ؕfD<6Dрڝ#<QueVMCB1?:1)ݕ r[=9?Wa1(jhoQJs#Pdx{^ >^P d7rjX!JvJO5XG^EV~}֓n[l!MLG6c*ˋt 5$Ҧ' `j8XåBX:R(yBh\#T_mv|=)m"p@34ۆX~ܯ#\0gĶ^PױR .J)ѩX?# ~Sܔs~Ę/Ѭb푻SC%I$-075\ zb`ٳE^($0!ݮz/ume4{Ӯ:?ljծ|6\q׳rvC,up_D%B5^ 6 ]}^9_cKZd1|Ϳ. 30VG ß'Go}ӈDs*7'6gwm 1kZxmm#pI'ލ<$o5YوJ6&g̶^A̅O #^^qy,LRťւP4:C3y 4,ki <O~uNz`뙡{uzv Lݮ\ʎ0JF]]y.%|*Oz/lt|w~ij.8ˤ>7O~sTm8+q;߮ !|!ފ_F;ʊsiqJk(H*sҜ'Fϰ{E_ZkLiz][o==x||Z;"c}ޮm΂CS2ӔtQWs^IܽNWJK7]n~ymؼósc7%ڱ>ec`Q˻[Ę=6罽 ܞױT׷LW7?Wwgu^_L?_7ţ [?}qP|̏lx^"m^g=i0-T h?Sjw%] 76FiM-Rop!Jx^Kn'yhvSR[ A,aO>/~͏;P9JO|{9TkHoT/hv'u7&Pco{vRc.ȃ֞~qtV?ɖٷhD@hCQU?1,pSӕgo+j*:4$~kw9kfd3#`DOU~7)<K1er=EUVJ7\`m xPlmfi=tS=L_[Ggx% :<_)GzNfwZ*T1UK[VֵI:ەKd[W@<_23rL:fj>b d]CXj!Hw")dkHRm)n1cZ-zܦ56;vhDո#](xq*VK7Vp\E^LKF:1M:OʰMW ES;4O'"dc;i?(ꘘq+HUiO,!CGr!H6*T(URdi-KX9g{GY ME!KDA[0TisKZ4up/Ae"޼_/w lz y^w?xIzmW]?޴)0@@k֑ٞ/)rb_RZZ:ܡĤ%P>bHVN9)\@7`)^C;q}dqwgZv|4^k>jwG篟m67A^qW"k#vQ*][[#E tHH#AC;pxi1kӳ[j. &u֠XND!+1yA dXU@5 0 h2i1Ou+ j5vB?Y2~ tB|;@##@@o9=JuڥbCowm )qeER5td 6--` ojS/ QN;djÐ#".i<6~ICNvHp1DN&%rt&pChf59< +]Gx 0ʺj`]iRBf2^Xf p\n%IY!t^'RRyvRv_96+g7:a>:c-Ih-6e,@B?EdQG2 5a]q E Ú(ۏbĕPH%NשIz@[7K*(OtZK о!wz>;qn۾Mr35>EU{lij)nDU`fOv`B@4EL(^iw9O"GmF^/ӇK_-_?q~zv_jN)E hJ &/ӆxi QIc:\q%{f1F Rs`TEtތޗ2/S BBМ?2?&<[]h5 QK iKݿtI2 qM|b/ &ռL[R:޸ "wP[lI(cњ'|^eGBf.AXuSJww dW?loݱy vݻj`.C #00XB,r!HE _|UP"VF]Y ċ ~<.8Lk\q84jpU~%KL`iSsڭ׉i 4厇S>x2eFho҂5MVanŝ~tW 3rj̑nG%$׭"?D0ʨFE>OggS@G﹦0zA5-UDMWץ~ xQQhvךک7n'}_Ny_-T=mE@۳ 3Y[X5V7a*nv oR s%{fUPD5L^XZif7.#oF!pW;|ttr5~vbxo^6NJ'+=TЖ;u3ʝtgi,j`:!0;r(I٢VRp3f 8촨矦Do4N:q)b(o黷[+etmq1 &v G?D ek`q20L]Aq gfˤcU{rB$e P^ƹ;<תYn.2=j'JHAZDbLp3?ns M/Ҙ늨\;N@ʄvj}glOw^Q*@#Au5V$xR>An)Cc&p2Ѡ` 4/Mbb@?3,sXa_-lvQ,ְA8B5O@JᢺppQqa}d(\>NV V$bH %Vn9Fcsc5)0Bɧ~_~.#q`~/P]c[kq`c#kg^22}Gwd+v8gINRlW3w~.t7)?yWFD+ t8D%ޫ;'~a{ȥt:WQ7 >anB)Dh\5@-qԡ^\Q!:Xf#_U?}|49CY{'>^A޶K6tђWnx]/rç}MFb} c I(@HzkƘ&nRQQipzɧmԺ/2R.urWCKuThBҸN<0_N?̝ɧoUo7v'L wc|66BrےpJ3#2DUjxYJƍf?"<.}]NP4.  gOuqgF~Ao8Inu7=FI{yGUpϒG d2M@ZסԳ20=3kfleF7e=ӁnMᲬI8%WpK,aOa^\nXd42 ౎!IrzX4?{ݷrdY]1/??yCY*I[@ w@Kp]Fjw|?MiCfI"s/:6dtA~\R8[vbb W5,^~.udR0]bb* ppiReH72뿋">6h4Q"`/Bڧ8^ Q:ZѦt y^3LW hohʨqPrw-e`EO44>lnmJYL𸕱v\$JO'^WgsOfǖױpY{ٞ;4>U).J;VtLZ"%vB.cMo?C<0|W.s8 d;7G"%>U͏B,)+TY҉Oԛ^s>\n/@Oa?« JkSXO;%H j}'f?x-Uvjf&H>2jpշ"@Z˒LdH |y_M嵪ėj;x9ǩ٭DKi!DX>Mb@W~jErq5$84R)QLr83h`{F(9۷=9wxB*1yʎR,#hLGo''3`vJD!j,R INn~]Fq؄;4zk~8Cg1bumɺ³ `&W3ͦ (njI33\"3SidODWae}+^n5tvNK@CK1 h\&%%y@#wM~/.ÑPXsdk(Z.V.ec]qgg^ni-Kh n^lj Ϗ3X8YXZ@g︵~`gޔY<.Ib:]~!:D|&YfZu w#u&oSC@~7BqA9qv"۱9Dž(ޓ!B vBD2DBn,Ќяp`*c)!k\ G؍j4lD'k(- H39.K=&o3`!CbnH!ğ]|fVrl̠M#ϥ(ש@ |E+v7*DCYsҾ i$,?*bW4}}5aH$4x2 Zd[yvUY~;}ν[m\OV\%LW" XÒHKMk4Kt|.iW{J &[:BM|6pZG? #[6_CV;bD,xڹ}PKS khVE.ц}- 0uR-`sa܍e(xќm"bp14CA3>a:D ҕ N OggS@G﹦02rڏ:Ԇ[ ;V'K鸮G\;LWGn<: FRE:+K"|ˁ(;#Fb@XfE'4>h7Pd}NRpϿ/9nz@}t庁GtB$WBj)`Z7!+iﺊFO*K"tAxbsshMς* ?~Qtˉ~kTXwynWKd8@ T8Nq:ti2abaXzOXiحNr+Pw6o(Sz!W2R()]kQ>fQ9)\O5v5F5i-8];O~Ccұ׵O:Zb/-{5-H@á^ѼN!5nk~{'+ܠxj{ z+WڊFH)U2kA@vڥ1w;nu 8>shVSJK~$;h_{u~{p_>³~9ֺgk\tcV}v92!h 8$'Y܏KHS@wPtk]e`7 [MMeƚ%+|7(+.5XY5~کk#q8b tUà h΅U˧Ө_0n|?h_,+LW<8&L%@q^Os|I|˽,ۥ{b㩏]aLm5Rc d\@t5w1p2ACxSsj)gweEoԴPh<]'YA>]A+e yZict4TQ>uO\ K?Åp:$rĐihp*VRttur^rҹ(wXl 4Z]S7u&CFT" Չ$ aYH*jp%&+w85+$0=FnўL_S4Yc[9?t^y\'I'4H$jxbSnVt9-۵-ZIu.Ca|YK߽O]5RL+siP~~սJ=.S᷼G <:7h0tx0hߟ^r :l^{+:lg4n% i!$)P5V*ML{S^ɡ7 Y0׮w7S'%3 v 4w#L:L)bc2k$keJc\N ,@?ْ9ӜvF#/w)Zu}wkW?-qs2v& !Xfs67gܨsx=kXG`uj*Qw8/5Ɗ6QX1䂵JL.Vmpy7Y;e =q3, Ysͫ)M\vpieun7xAYM-zQtwuK%I D:|F/{͝}- ܀M?wyjeŦ3Jmqxa/bWeRTFJ06\;)>n} &sZzyk#חg"ȫ`^?M%Tqs vZ %8mD6^4GF'+(SFě!sɣnP 1,zq zܷ9^}͆I@y:&Jy-xx-r/>U?w]>F->gkNf5q?ͤ[gF^ $ZcZs̠cŹ^I˫lGS\|_5FEWߩ 72Ա L7h( YGOGNQEߘ_WKAocЧujޚS1rWπenCp5b3(k{k5JrnLC5(^<^<<&;hCyKE'^du/3Wˇ~JƖ&s=pxz6ݽI:/jjܴw c[# }!n3m"ة4: I \iJcEfPoz(Gꪸ2Te4o+~l\I"/-q%~v*HF!pɱsChH28ķ ١G9K{+eOҬj{fs}6()|OjMf58c?=멨wz<Ż0[j$"aXսsLy/N$v<ʹ  DŽxNܯni"r5UTOc4 78|#i'r`&@epIJC}V:\)={X %v)WJ;4Ω74uݤ+Ӂ`_OggS@KH﹦0;-;ǹ `ԗPdөȡ+])ⰼR?pm v秲)Ǫ>C#L$䦝d ҭS!A!枆!IҐtPž3m(Е8^)qJl4u}heɟ'T-$#VMA!(HC.Xһ; -8ܫ2F 8-9׋ix}۩+<&k EڱNuwrE&E!d$v ǐgh:bK2vLwrxPwA(هXI';Fx0iAZ1d^xIL46w7sz>?~ܪHJ){g8UV@3+@n HvRY%+)7:Q᱑ʨ']{z ;|X1p vt.e1d@p-FR+߈d,KqfbW^vI>z(ôeD"|"Detk##`P%`z}1Bwo錃'jlʐ&1c]!SQv+H4Ղ:A,i%WR~+vf.@05Oha|vm.jm3_\lQW%}kUsNj{:MhLw$p0j| fCu:QQU}Jb~"21vlRS4]Sj`bRH8 ^Ra2@sO O)QvCMܖڹyc\%OtH{9(5, w> Uv"6 $BkBm -H#0*Z.F\Y$ .~\n5'9[S5VJqFT;4ۮYzyLygG囷Ԭ ꪪ}ه BDn`m8 pOt' %cѰY@9DE H$OxÚӓӁ1JM-d`j]dQɰ1iU>% F Os\txUkbof6;4Ɋz4pᤜ3.\~=x,4inP̧vMjZ^:UJ`sY)U^P?E)U_zàgPc-.}ZQ4xH{cCHH ܆`Y6Gp,׹N҇rԀgѻlΊН{ZDl3C$D9 ?@Nu"WMi z˭/ehBtNH_?M9Ԉkk  :S0i?H׭U2tl.0v9' [Izq\fl,.?qc-eq3DKB D{jo%Ԏ{_&[a ^-sX [j?̍%l%bGi#%i+mq;et?=]QvZFN .~5c^N ;}1A]+>F}C3RvH@Tn>lT39%$4Lp(g/9Jq/OO~6 0;:t9hOf`X&WRϋ:4r u*ҡ]=xnfݔm7f2|\6[,$*aPYt{:(TT~F$;8 Ɲ-7\\]cTZGKIૉuf|ɉ뉫wc?nrV;NSDUӓ&G\7P,[Z ^[Iq wR^ZJUėdTJiY~}go!ߓ0>xvc]Gs/9~rGI|sDo!VtHyۧ`Eq{[ҌqBѬ/Iʇ2:bӪ+ۆ} ; k~Ž`J<>[.n/E4cu趑]XkH\]W>-Z{{՛vFo|J_|"kIط.])C㛼~˸:N')[*$>X"4}5[`uhq7`W4OR!2gT)٥${1L,!*Uw?!\)Ln'dE ِ/UPZ+Qƍ.2Ѳb:˾vqx 12~өg|xv3@t0@&9" G( e,E_;rJn'ώNjk 'ҝCB47Sۊk"8_|nm-d6J1Al9=, |LOJt4.gk?UK/wIdm~~D@ @Lt~%x0t%BjEڐli}G-A I*j)=L %/EX#\6?0|]~Knn> ]r+KJx wT+8o~:M1{7LF!cf4w[V+%lՕy' `R&/w rwgt>Y>@0Ǭ4ǮB*QiQFlX/ıl]aZqe{%T>~2k}.]yF+OCO<<mq+tuCb7N)VZ`膇s5CJ!t4$/Q{uX( C)3h(#rߥq(0hb95](+RLx%i gn!%8,*AZ">\}i& v$b9 7bWT K/r5SO'/]G.:|v5} (@φV<ha !_ |_j˘鞗cdoVosԑGeދPxQniEknuiNC0^%m(kYg 6K/c(o&bC7<޷G#1a #6К:@hA{c$u P(.3 ͪ޾6N &^G+b5]*A'kIn H">s\^<^RK %)]Ly8HC2,:3+J3J:*Z@. @]GMBjԁ :] H j}V82cIBy&|0<THӋ+-e&^<>'0(^6kR?>r˴Pο2Z3qzݘ)nQ;؁h!7ѽ8V(sǠ>b(RKx] Jش~Bczwˊ![۹D!@"!,oge>;nbO$,2|8uqlhM*xt1̚.]6O |(*z8b(tI!NLd̩ NB6T_$Ufמ=w_ t+[j2 N*XW~+q)׶4§z(\iyGθe g~ 7,uUZ dX@thO5nf$(ǀ9TK9I@&# @u: 3n@ !u4K|Mke(OPXX \^\^Xe\C'k[Am:I IпM@^%OIFc{^;|NmP1s٤69,=v/.%4uM \>,񀐌 jc\{C𳈭y,Qk^)q&h/w%}S\iy[.bw8uub;wDm|<@ ċN7mFC||wIjOQVX;(t+ceQTj9K@Q Knq \r]S]%h v1שLJ&u^ l^ݷF:1}oBH]~=GiIșt5eky.f@І$ 2rbhu8K5b[ZۂVDp 1pa kݵ2Qx/9sr ZJ=2GVITK K͞n6ߕt~<7dV qxi\Ba 7]"<ԜNKCznS:ZBSƳ=g?JboGb94{WO4֍ռVwo. .fǑngwY=OP&~lGngc-.V- v% 98^\Չ *[-Q3VW\{nta[H}q9?-@Vf!E\\1 %eus"Jv/r;ח❘$v>"B^R*lCBaݳDf.v E}~\qEk7ePt(]+zUbN,ƋǗ*6 c7Q` ճa4+ۻV0 c[cS}S!{0r#jfv%_Oz%Z}}VfXiZ7(eUB,o x2{>%d`ܧZU)^w9WgTݎ3j S>qjc՗y]7n#IM7:> T0b=cRI> !!e^Rl,x_5JJ>Zh] aL@n G\E7qrzȥ=kVbX WR2/X͔Q)YtX6NYg_`U| 4InC t7~4rZBmYppmhxē5^u`˫uZ*F$ΣS= QhMT,1 h"*+SW z">=2ͺa,4䠂n1#pV$ 촶) $uVď/@wQT)ovlaWL[.5CȾ72L^{/rԊ[;C->ͩ;L`W=z5wرI뻇?]zcϿDKC%Qհ)me X%*6. :i2ͨD֝V[ _O5i8 sY>l^$ Nܚ'y&h *{3O O._8Ņ?yCcl}Dn%K\?s+Vwڦ5N^ko}?{]%sV<&lRoEPb! % KQ*lIFkIC ]+E7M4o?~gJVR׎+jf7Z!&ψp+恃Y; ?Pxsۤ4 d.n߭m~/P'߭{mQ*rZuŲªJnR Z@).sP|v_]tFNS|uL+:3/IHnp$6im]Aj0 Fwx ˠ DNЍ':C>i}Tލxű:z]Zk5(1kqY4H;P,ޣivF+֕nZ&6\ZNB>9&0Wpێ!vdKOw6eM Qz$#{@ܟ,By0"QH^LQ&W`wG2bjL")^zoq`̢͒z6Q텽V?&HIrO & ߚ^":= |,:BmrVZ0_^Nr= 7=KZ @8W;)'LF'ϑQfh^h3Ny6'$ pM=F',MEO@'Q#!5M0ֽL5x%)>vBcBB܂NHދr{i"XĢ;=- xc]5@vy~$6'q~b X-3] ~(hB9Aޗl\r# 8#Vv"X̙;]!dZ9ם" )P@V1!!L~m\4ȑ^^m%Nc.!M u.ė~Dٝ~i'[:}߿MNO* {ЂOX^ }bj;-&/e૵یw#"WZ{ Ln+!+ ?H^;wx7at2jfN®R,/ԙ{:۟ w:ez~iGw7>>:WYZPYķcRiH̭#ϑeύ9ޱ4__~kU_ݕ-R*1$*U{/Tw9 b֞LXcROggS@I﹦0l?k6՛;ctilҔ73/ +1JO{Ok .æJŽbmjVܒEbVR? qt(ZSf%$wKuW ´sBtk=8MFnLĂC >GEp͵^χU3x%) lF}Yխ%1/XHgm3Cq@ bҧ͆V Bp'L%iVyMֲ}jnNܻD <4:y}&U' >\~W;UC5O`C|l \sŕhF1ýUJj}z+v>턝WٍR#m4tz0. Rr:DRie.ʼn* Q#0DϤ*ŭ>\>KvU֐R;,|(8J-3ltmIVZ 䅚Σ]+v!i>Jٽ!-c e{M{w )ăii }9:c%̟ў\`4kI* "+Np RM@.t ojesk4QdOO7ۻJP\+u$ۢ$1j j%/S!_'0Fp-Zs ҿc&>3vYUԌcw `B$*u_Tʨ>+d_qw$ #pa5W b?} ::90s5OԔ!Bo We,/D*tR8H*˰:{ƼWv.r03+PViBPP.+FK+ ϯ;j] C1@WjR`!PVҨU=3jOeR#?aPno5kŒqӎF c~^@ȩ S'+[]*cy*yZ6굨K*!`T!q0==FkK>lq;vJ,܆GhO-SYvqι:W0|] d./Op/^ 0P%"H߸K}<%9 YcCHG>y:nIMyesgE|^ԑȕ9\I5 \aATNǠ^2".6g ʭn[E4@vWK~KkϦ|"آ[>z?%,JR%:FoBZ0)Dm@4# dFd:ҐB;r<1[I-mXw"*@a03>\c~h4%H^Q1jy?~].b8;xt=?>~yn#νZYDx"J"iľyDDdUJ S7nZnrb?%ŀ Ԇأm j `]iW #扅jו닂T8%LL ] ZI 4t%ůSqz'쯵"1n>խWڱ'{njAӀat"Z$ /^YsR_ұ 6"ﲅdEqU PGT G0~=R~AHJq1? qYl嘉85=GSC^]!9n!c}\ytIq`u+#73{n*xEGIˌX4׳*Raڬ5 ڴ0JDjdTb HCR4u/6_cmYG}Ǣg7j)Y)܋U'!,Jꈯ\^;N5Avs?E:.atq[EjYa~&ID/NW!gE:|lR[8 (q#? K=]}N@>aEmfYc_VaRB;+CC #+8;} [5ДqsI^ 谹/D>_PzEyl=Ư/b^o{hE~vC'i-a\ok=L5,Zpg^(ҕ$(7Fw5?THK>Qn]Bky'v&ۓ>Y9}aG..?;Jd`.v Э)<McfuZY`@xP.HI—J:GKpA}/g1V?]p1EDfs'L%4~[CoZU٧ۗ3eű7yye޾"6J4DLlbfsqt!''Z!v7 IkY(ij#D p ET>mq ~jd Og⯝u?fmE0~Y|ǩ]~ q(ݵcc|+3)?t~}("+M3~)R2)yӀYW4Rok!E, q!sۍqMM>~TE 'ǂ͂5uzܿQڪP`캏ZG/I݊(/'|m7K]IVg]gFYc!gRZ|ieNGVOEsPlJUSDYFVBBrMU\c43k5u@3¡񰸇kV,n̞>v'ߏ?=& uGW̯7li5pi5CIj"_R<,y%F־ߠlCW|~")↣0H3stB@*|>ƽ#V( EW:_Wϖᄟ2).mά߸R'ok?(W.>G'xD|K4Q:n|4ʱCy ˕B42\9]l=-`حRER"(~KYb!E{c2k!( dH"mrvO_޾[n\ʌч={zM(aR+m,`\ BibE&ZS,{@k+[+b E@26 n&Gx:i>\(Ͽ/hL!{,R<~<K踩rd]-,Iٰ`X$ jZV6C$Q)ǚu @Hb8'jgFRĠ3ik.|x>uQZ1e/|3Wb6ܑ6ZOggSI﹦0, -))&qt%#"%""#&%{##%#! ($%<>z.&ygL%dT?r곧F^u/Q{׿io[ }&XL_;ىj{v2|YH1wuywi<4L?ö[(۝m-ur 㺵jR<ډ`kl &</vUҲMm][|֖VTcH NPGI"j2ZHsv Q:tFd~/\V$}r }M,Rs H5(+"pź\^ك@:vl; _Ǻp+ڮ)NhӖ-S,F'&S e.6!3@әTUj<+p?Rd'= JYl6*=s3jls=( B$мroV*UXRU9Wq +g,KLJg<-BV>z{ɓu/>~:NkHbenR[zy8M0 ad.mB0ui`t:Xh.n8 bM0)RG\Ii,)Tw%SqSDLD <i7N6H>4w~Po%Q>1r x!8ֽU/رMs}-  ź%$-&IgOY!s؀Rp2#z%X7(QqQ(7 vR>:Ns=o]\6u\"]y{;$8 n"' Ԏ;f]8eF,)q؝3KR5E>&F%24\g#˜O"_w[m$ %Ek3ہJV&acM/&pݘ؃9x`e}*LT$1rDPBB̚#$20.<5D)3$!4*?Oն!@Gվ }@?ck.JPS.4rq(ZѪ(<&$b > vrilNjRK6xMljv6@q 4 t"KC*?ш?yvGVu NQ$=d"[P'y u(DU"$P1k%B^MrQc-X46M  QŠP\-&FmO3Q}mgy'F0,|/5|@kmP 6 \˪SrSeF[q̈ĸ( ⢮ZyKzucD/bZˋm8W*$zTPеҗp찃chOj(t%zP 8).EAKp}P" "~x({NfiYLw9M,|؄+y&LZ`\ieإBlx5XHHBQ  .dO0ԉPĢYY VBd H HV{5:-EЄs]ZZ_\p*iʮ_u%'Do_%S٢S%څ5oTnva}r\H_XiYTuE"QS $}T <8p@pˋe[+|z2q.@\ݖ)yћPMnP?dә\i`ڎj;FX 򹕍"\ߠOl{_._fxaF/ 4ɫL׆U5$>~Z nMߛk;WL@ _N]X0/ƝUەQV\h"̋z#i?!QkCCj\Y69\!gt0v7~ 'vlF\^n1˛z| j6o4;ap=ڊw XuA@/)!>s#H2)EJ&\?펉ާ..~t `$  $)7HJl}&Yk&_iNKaqXYvt2!wl!tS(~ktG* 1fx.zZ'!!vк~$xXyf/&$X*{? 잟m `ߠ( h{F`; sq _Zn.5!op uv.~p^Kx2! 39@j(aZWx%"k/Kߵ17(*@zim^iZ1 h6TX;BAp (j.^ 0hX^ rJ`Y_NZpS#r)=a} h,}?Ǥ8/`m߁~ź \ "B#bȵφ{l\/nSLY΢axӸEfJP!ty+aArOݯ~+Ý^/o^4&>6 y*9M<Eeq>L.zL/ɀV,єRe.֣JB!b/B'JDqT^ v4q@ay *32``uX'+^Ysѕ0.OggSI﹦0Oڝ+!" """*'%|zyv!"!#"$('kn)Oe`,@_|JR2>.X`HA H lc#H pOEΝ Aco D"D% PFkb>;v`*V4P[*ҁ =`וs2 gn.OO/ךİޭ DHd`hѝB0vu)x#e-'^nX (:6DK)c-G(`8=oTx K)D@^o׽GO @ ?@܊(Hp!֚uEXV'WcDB< Ҏ% >#3@7b0KNt&>AU÷o@j(QF_vyq w΂v?c DMFd`=F`-P*)~MRvfn@Q ֬]"N1IRp'ozG=^~Uk2Es1 ѧUږ 4%g;Wt@p40 [;).#/ԃI * 9]EPQѿFD!`L tkM[]vT0KL\٠םi0Dۃo"1k7J1T0յ3\mx{Z=x1*aeWkL׆^eh6թN[b>=Q TפJT<}?/="CAd3IDW׵Wy|G{my܏^8r&G$ DQ5qmp>ZRx]S;9pt*&t[Ρ*;}e RXϩp2:NS>Dl],+o$̒-dw46ZesۍH봦N q@SIe{V/Ŕ{αb*bLd俑7T/|(,Qw=٢_N@5 loXZoqG@}wDM\e^x *6̊<(j Fu|6lOxNzˡ,%؝3L1,J܀#$Jih.D!@)ZB DyΫyXkbX/_$չ, n p;P$$^n }E3(؋.xRj C|Hp5b)Qk F;a3m `!L4tB }'.nϨl@ԧT0 VDV;p H{.p{J Jٰ30.Ri UH1%J)tkp۽֖pA/@πq`p4 P]4һhg\t(W)t0$kvrGg-5[ 57<qQt$#vTR (  '5g^}޻}z M4%Jw! )@&+@mAk`6jDmG}7G G:0ĊQIGʰ>\)gV n-1/Η(ҟ"Qow\10<|e,BYHZ:@V5)F颚 a!î 0%"ƅrp{iF{#5GЂ`ǻr]Y/1Wn4%G@{|s~^(@4h3i=[ @4 ܀ꁳa+hx8aX.X?zkNrRe a=ʅs a-&:%&H h W FK9hY, pc|Z~&8#+.rZ¯llZ2?/ *^q(tDDcJG`y\߻?(E ,MHn&2@6.әkf-F)-wuKf%RӀh~+.x.:S@ ;'b$EO ROD7g3̎wz `E_k%i~hH^c 4-V ±B. QjCȽLU`(h0 G?fP0, aD>|a܊=Ӫ9 \Py\D>Q"lXwġ,?>:h7WyTUk_X/PGtIJȦbQ (jN0إxX~[!CR4m)`7HN+sJDi췁cwjf[v+SNπ8m]kYⒷ&CH@Ҏ1X:Kw\a^5kwn0^;N`4LXc BN//UOD6ڂ؛:egVFqjBjM"ha 6}pig|M.Ňc((BZ٥1,w*mB[~ vCg~][#f3> *MLucz~MEaFvT;h Nxn xh=biJi4c0o{f;Xt`sVƢ[R+ jG*X :H5xCӬ܎X"&8|lIb$JA:d `Sݰ%*z~NfeBHnHn0 oc6[g0~˪a YQIԷVOWt떆!hT5*MleV0X+d$^ \_O4M5Wvzh?1y'<4!-^SpRCڹ*+ Dxdt“axgRvKƄ#Wr#B16E^Qyw=5PLa ~tZΛ[@#W%^B{Ŷi 24'؎<67L`KgJ<w/p3ZMZ62*v6%H5x&a_"⟈"ŀ倍zʼ/@?;J Nk?aўȔ^d@  эFA!pA" vxy0LH^tJYд?pXEW!7[-~n7?|+g`fa/7i͏@;"Η$Ut뮗M>R"1G(|\J,Mc#) (֓GF$LSt 6wMcZUN[$TِSaC_Ã)%KmxPxTTLdÃ/=`X mo N5efI\ּ~0 le;QQCQ\i?A7KFB}&ui<^UhSŃKq+1Br5|].(Ti҈WN>ӛ67O]dפFq FS+-޽ۓeOt(OggS@cJ﹦0W+"z$$'"%%')($##'"*(l>m[q* ̒XTKwxSφ;eZ7`44w ɬISkH~3NNmijX+͐v%2}Ѣ >_zځ~["9X7UopD$>|fV-.n ɵhG.tU>S &(1$E}B"`O*!b@,/+}{-ܺ`U5kASm@9 2zD,Je ~ę;+NPQܔ2p;`Q>%:ALJa-mɿͿT[p}!"xQe ӱj&t'Qa@Mߢ%"ń! ud ^Kpǡ$Ϛ%r%m?p+6(ǂ(ZpУXQxKqiC  {`@-'6"HSB6ˮRTg]KnKInU>~;bѣ,KRzE̛2;a"R&FVrjsuWK~A0E|t@QU J^a3"FGug Ta: ATW(5c~;t ,O Ԏ^SQ.* Q2qiy8|_jZǯ"I%!?Zke3TeXtIG/0Ya"MnMKzdzMudVyC+kƶ(HNPWi Kܩis B(({b 6JUg-n_e@YI?iE*@A q^+qɦSkك&m.)-V"ԏO0R_a<1׷Ӷ{/6zEmG)PnܻȪ4DյqpxwꪤC( ױ}14s~5/=q/;qj>ޮvg,"U6 {B ^CZaY`7!|D fY+,O F竨|j$fO ˎy+yT 8Qk H99]@] 5šBqQ~|Àb%u;(LqB,ddERj͞XʣVM~CKPFR?%аtgV~t˔iqt%v"IR&]HƼb̳86}DkS*p5tEeebU^M,)+އZrA=GY6u$>^_Ըs%J0<ؼ t/K==wJ)Ė;p mJ*0o `= ɀ*߲7%]u8 ^M7<.'W#ʥgVPYriSP%\_\ ?n%(gRD#BM#iXy؞h~d;"h)F!g4*C+wA#+xFrK$D|sRADb s9z -@Σcm _w)~hYQ+tD$" FO` |=4יK3/YM(8QZH#%JL@*A;KcͭFٟ8So_L*_xM9x]J]g{%dXLՆi6柇۽k WHutU&MLDю{O i3_"F2UXb*MɧDmH@PWOtx_{級ڏ~ {ۿT i|@IӴ<)07?,d"u:\ނ<9H%eRݮtTX,yEѥ?XoU8~mky=ӚL%Yzkb\0 'fTLr=h:g:&^?DGXU 蜐$9i.R>!q}e|qUnQn)V~P@R9 NDu# (>kER} /snpnmR/zU{bJJ?6+#/s?QJ틳K`KX+4-;im>bL@@̬':Ye ʁ:N1owRGЙ " ~v4X5`N!.9O'BP'WƤOL@ _?V.u)gu*0e`HG9ty (.qo@Qy ^jhiJLim{riA0t;>4@WD)iGvLFFޏ)0<6{K+`(>*C.HŭDyJSe9"p͈F#(XC U&`QMH7/-qpU1QLb1]{6Ο)(ׇxY+L Ffn\nYqXQ]&zXsջA2 )W$7H#^ևT1 5>\Mb8dϽ &elѵq޷0v}W[,OX]쨃GB 0rDLKM9)b&{Y݀ABQ,UʸX}S\nebklNpknpNҒb;pA}Yካ蒈dGeף&o*DvWfCI;X"8/%汃D`$uџJeHºR邛B=3RpBQ9t9U#\OggSJ﹦0gcj2%!##$"((#~#!"#$!$'(#%!%"!(%%K mrz Moʩx~Wz|hLL@.-鬮 H*\߇n^b 'P*u}PI4VT*,I 8&#($">/V n}CczvGvDᏋn^/wͷ8`^hk9^T孓_K/EK jxƣGV'_߹R""Fӷ8ЎQD|BX$SIbz~SEQXߏuDxpQ6y_zҝfױ[9cCo:JTDI5 {യ^x7|ϱ֕|N>{ Rv,%7\05?-8_az%riƙ~.y6YLQYjdM?ZsK%ݴtIf/LWY*|땵kJ[ p8O=*Ƣd o)#}ËIeiH4Uo+"x^0"QBj4tӫM'F+KΉ4jGJ^r> 7jdy:"ZA$z@OeD%@0A{rI70¢1[:oF&+X\G>%GQov< ݭ^kl-rhSK#  PL`؍8Ϗ{]ih|'rqA.[vby;8Y*{84n yqQR +IrР Gtwx߯F#D1z "MdD8؂}{Ŷv#JT+fR?IHt D1w&0;$<փXR""JD[;[.CJ}c}*'g ,á.#vF Ge)!ZUS\*5Z~ԐoZG!|^XrN,Js%H){ `[ α0/yz^O'rۀ.Dupl @a5 fop ~nF۬ 3`@I ّIQy-%̡kPƎH"!VtN 'J˶"[96>Xr٪^uVQ?;MX:@qJmpcD91*[ttKQ,!bLz+(" 6̡Y 6tirJ]G[`'?gXwLc͉CQ"FI$Rk/Rl'ЁRDL n}PHg5b$TRh%` 0!^.r,tJ `-o3DM0V!RȕJ \ CP'"Z SM<vmQjtvWk0$07,hmo{EiN}ﯤµ2(>@6tR4$ JԢ鶛JSӅ82 3Tؽ̔`:h`@; lU(UH94B#J U.L@ru8S$ 2;JnOzڣYGTՠ4ݐ}b n;u%Т$TU,z_B_@>FA7YgլYcL8W?[ev{WJy\阺L>1~ݪNm8oSc \Sm{`-y-2\#t{}JI4lhWDVtoXFۑJ"dY_mЊ6 >rΤ uɋ13 {6v졃c'ڇtgfέrLDH5cЂ9 `?D|jrťtu18m"ӑRvDzyZR5YcGk_۟"4ΰ#O:@GfTqKb&g)SD >6ed_`YQkL;!":a?Pd.f zhT6c|Nɂ1W͵ AGX W ^0]"uj@_t$ЭHuozq8b둆 ?BV,1RΝj| Dw R{b4'ZQ`>'@ \)d&1]|ហTT @T~; qh*HE/Ѡt:k=@vD+Er~xv뻭Yߖbۜp4H/`=[]G !4 !ʭ8s+2j"EC'i-G.5"~6C nosC'2Up /6*lvEۏΒbW`@/b &+5 j=c>vP/a: AZXuB)V6p v5kfEe 5/:Ԣj`NOgdZSu}"FtvÚp* jN$wcRaRRӮW)lv&,ċ>F(P7ρjG.~Kf)UBRkȌ^eR|lѠ2`ic }ųKYw -NT% oVEnU6@F+_welVpchW!M6C(A$"m/O>;6rb"i0ڲGM[ P"JPl>ϒ 5Z^a3= [`(@o{Ѡ1 H9DrMA VQ#qe !UEba-t@% d_]xq>Z8LOdg֟xirT9!|!':A籘Půs  h;(`\1ucJkUMAQ}JG*nȉD5@(P DU5T^])42n޵azHڒuT6t?`mcu@J#W,17S;m'/W~7֐OjL ulG= y͞$+FלVT (ۋh}.[lF-X7~ێ#x< 5tT~%:4Êʫ)4~H 8T@:iz ӆa^cvF$ 6E7n.",VX\YZ=d4D+Qٌ pcP61aDODDZR?GN N­!FR MQ@Q_vyDpp;GZs"<KBw\ ,'"" I?f.ɓ8=M߭v* !PA @` ЈH z@a(t܂]B܀J,ۻvJ.$Q_Xڝu$@LcnU2t9 _V\$J4!No›>lmGU">:*o($YVGkh"b "Vc?qADK7pK{ i܈J17>\d +eYs"ǜ:KtǻX(&jDD(>O (izb"F t nRHM֚UhPyДX! |75А*lt@/Aڵ֚Yĸn^ ֤ ki@k)5=.)+JW@GN'c$AJACVdY_}_C8]%/?@?dn3 H9;n ЌRy`3"'~kx̬E3J6JG\4t9+xזΩ¦& k,dPzTgUs%8@Ұ9o.`5 n՘@XX\V? (B-+)u).56:6f Ұu5{qp_/?-c_qr|D""B s!..&+G艥G>{W QAowMaAVӿzx ``#n"Y2CH^ D%!<*wJO\IO(+vKoDOZzkaS 263M]T i6/ͱ@Z_4$WCjb DS?Ѵ#lM4㉚< pJ'4Qm 1+ɘ9OZqǷF%an*oOu L>+ۼ}  e~I-zeo&dLSǭY97o'l=5:dWa*H1`%%dũxqmک4v::ȖJ ntϘiO&gȣV>|++JqQ0F۰*2z84Õjj7)Nb]7;1;\'P}Iv ^9^}:UxJ!` A ^{ְNJ&9(أ·*C$㔦4?)S =1 i@U6?,hX>ɃL]V9׀Z[0="|f,\ "Ȃ+be.FZj6Ym5*q7+ 5!4*9fon~$6JO= O'~ۯ <a}&p  ` r kW7L!Cb<j_dyYEQ]~5,ژaoWv`˥uvIn8 h˘M{=6.Gx@.@#hGpٯ;aLtwfL;B+N^6zeFL/z-˓XxƇ8C>D .6S=aU5,:uM$@c`j"2`NpN \;u5rمroBwC LźyS\!2#)jx--jc"}JǾ}HB.j߼ҿ[VT}`4po_@* A8UGa"TtJ`|ޣUkiK0:I{bdd|L]]!}( /g t pOB b%q*m*&mS`E7(R&}Xe+.[^e룽Īܖ\"THԳ"9)XCM>ZYgB` {9ґ@mp@I[P 1bzmd@2.3T>T.~;vlC4*.d x!]y?R"""\X@6`.ykl_B!߿O P WJLPdBBx `@ UGa K.zM^ĉ8=C=6|kod#Q4Wڋv~d360YJw-0 ;Dڸ p/l ԁh?5kL< 1H@vTtI"q( -i< >>dˡ 8ަIC`AEѨ4O xY9᮹?9U~'qaoo?  t3(HS& 6s=Y}%A+QծƀcdHgQYnHԲ r3r2 NKM"~h/&]nv"`?$KoЛzE<K/P `\8kG\ǀCR.7 Gڪ8[n``Yr{NL%YRl|sc?Do+RHv0Wr:)n_+x%s:P{&VB"*.Z0r[#T|Z( ۽ܾ΄ E0rY5hɤa:ܚUhXU-1J>%\Ow2wژI~s=B+{p,&@_i:= nP@ !R0ވ:-SrxiUx5+Gv`:||K ^4 z#^|ixvP!0U-?5'.! nM=T#}k⺆!i\z_#+nQ z`hX `>L4#fM9pe; $,2F?Vƀ*#?EJawd|0wՍ` ǁ ?IdԐU[X=U˩RS@5闣@D&!]D$^zv֒nB :*L{qgL$g/d!")Y m6sPz7 *2 HID_I `\#ă䨁H`M% ! H |O rSs& AmCR0z:ysMӉifȇ/Nj?"fP4G€"cGTz4"CtW{hroM{t @GDUAF "k(!VGMDkZVjxo'S \֖C2WlHYGmn'x TsiG@3=vcdr|'Z2Md2;7,F:l 7Alsa|4/#w͇/>lfT "(%P[2\}2ij?s>~IFQT10\]Fr֡znPPX|n_, "<*T`d"yecOggS@K﹦06+~xs%%"%"$)+'|!$%#'%+)~w{bN휡ǒ[K(n>&{aEYPGHDA}UabXj` Nwnv-{ p? #.c>@p#x>)˰c:n)PY'\.>k` ~fi4?FsKJ:9M `vɞX2]B@$? M-#7m+^=_ d{<| ޽ rA-^K`WDM-~ 4<*H H#ł[{۩&Pz˅CW qPV.BrD(AWR%)mZdv7j: nBh@z AԃsQE(@\Qރӏ3X9,O! }e+}B^+Ҕ+d XN5L-|!9EH'uK `0,*ZOl6m_n} HPI0]=,$7jDOd>&[Y4RDDc*%qԖ}k0j7[€0@``5 hc 7ȁJ,Zflf>RRo!Zh%6"\=D:];{_o"M1#ڂ9Yw(;(v5A8XɷS0`صA@d Af﨟 Y/m.;TۆFۇ~^.V 0|7o9d(1us:PT׆tU5+/^ xJy}cqʫSFLQj"xg˷hϰ _>N^"l;\ζNWVp0?_Mg(|9*vw5eHr”[ff:{Lv@?"L΋+k2 E $"" Wv2]m;ϘX9wHd0?b!$H'JY/}LʥXHP6DYnr"[vtL nP{`Rtj1~03 '3B2'"" 0! JS:$#NYZyX)M . , cNw1|>h&d2ceA}bZfx>ild\PFz~Hٴu Xق\HS:wi+/Dw[ #`(ȷW `A̅ӾƬL%&do3P U4p ~.|FHZ@(K^Zk.~$tb xq' $^)(fQ^uop*Mq5R 3O_AMZʧ tmTM(\eO+n*tC˶c(5Su0Li@X9bH^9ky1*5Hkut!LjgSF{!i!ׁATNw )k{ "cqLu}A߮F>m5^ vlaCs'C9/pѠ&-34Z%tkߖW)FMT;ݺDa?@  4#vM,p,X :* Q彸x-aJ`g@p*CeC|m#A$1?gfN! MK_o~lwB^O$;x]Y!'q7-XQ%\ޥ +ƈ^q;:s>f\GAA":)Ǵ=iY͵Qz/Te?`kqIh@]1x@ dhqHTJ*iٲAS p 34ۈ$}BS_Z 6~/*֜U#iIu-;NJ@>X} Jh10`ܗlvQR ?@jWwps!aEPBEZ GDSqӵ?\zzmKI|WLLp69r6덉@ x޺{gLՠgWnMM{"&m8LLu\=i)ͿF"Nb Lن}m;\sU ^A蟰 BO 8?j}xtwAڽ[*Cu1:%曪iIAroA 5؍ )IfpM%f(6,i7>@“E?aM+n8: WHŀh3:&&]+kД0ά/DlwE<fBEƂ%)>MV#2䤽*x/JBO`G QJ)!ަ~a~z[NC20ZE/T+ *Nq`y :-'MjE~ DYYn^i2 V.c'C2y;*%锈1YGU'?XOzcusE 4br^h8u* ӑTHhSJQL;z =GL [}bHNj|~=5wZwy[.*M\ePѠ ȉxpPV)]m 7г*ӈZm10Wߐ)1S"^+ed?[}1zZ\ $lt*9!BD%z,_P-;jb]?!NW 7P <?X(vӜ",sc$ꄉ∀E!nbpoV^[N&rU8ž``տiPA"""AAIDD,cʄޭ~ŋ*@T(`RU^*ȅo7:s3($( Ǡ0 \)М_o) TD3UBO+2 IA) J":doL!'U@}gGqMw P> %6h ,RP YD@F#`@^OggSL﹦0|uP2#%$$!")*#""#$"$%*(# %"&*$%}jȶNY*rN8j4QġMCm"|jARDW'o=/\W⫫ Cσ78v!svHo:&XG!ó ssNZ c"T7fdVQbOa~O޻߇J|qtk7; KZH 7A>T,Hw kQ/b'!ܜ׃̀_@͜aL \~Kb̨Fpzgql16\&ʋ"VD#%J!VCoebԘ'.3ePW4탷O8[nK_<X{[H,VqB;B{>(^r.3y'I򃩉,}y6ZDsRpdRkwۻ1wr5iZNXVJDK2<Xjf%AA@E"Q T}",ޛ#9^:r0Lײ@kEɅhpj"(B?jvT`7V"ܟ@) 1xavp̶ſ5ps&R"aHh/#, n_4@(^EYܰ~o4.ayJ΢}v7REU ZԈ\ ]8"(hN/ tꮳ2yT[AQDYEcx%$U[.rMj |"A E<}z^kEO v4`~֢y6aZ w$J\8 vUn TOvE!F?AuwAVX_GO|@7ދr͠"IiM)4 .( F*KLbq;~  0H3pYlhL4 'qL9g.`p%AjDQ[le#)!`i4 F(ECpAv5U\7v6%vVk_Yǿ];qƾ m ] K\36G+)F;R+:$!PVXDr#"~9 JxZQ@b\"!-=4kd+ E߿z_k\N%N) &?՟~OaGcbMpDuD;HKD%=7 "ʲH!A T*8 + Dx૚<υH;([!uoD))lv6~/|]LDD*Z-$ ڋ~O:t_z$єkZS?b:&=$-gKL>63u OUѧvJ <Su5?\K=/=фw2e$vG,*Gx׵>#&bom<Cjѣ`=[ʾՒ_{DQ _Δ^u y|׫7ZFrЃ*$ZLRfڵaxtv?2ש/=9ۓъX\>^TJHH;,'\,_fBm lnOQJN-@9ZL@2\Fp:D>ᾩ^$TX˸4 H)+ra/r$Z8!vLIB`W"qJ Go˞SS)F[*B4MA0QtO =@*t,k#Vx=S#H_I]0:K6z@BX!HJx=)¡DD)ߵ+}ˋFk $Q" vPp %X B\oQK[QV7pJ eHY_)( A\ `TM&kI %, _ nvܿq~`=4NM|u@w1㒙XSXQ WLtq"^z?,=V Ua ޢoaEa̅Ylfj2lՠ]A~:mMJڕ[ckOJ'hV ; JsO]{9ƇYL8qE}9vG\iAzh\zF dj$2ZZ@ uFc2(<)31V~ UנSB*f`17`ؚ,.g-w4x~:QJ$^x9}>X҅i)yO(d}.@Z+F%xDl(^}/jt(U@ū6 l, pEt٨NȟW/< l9x}9S  KcKՏf-a(_$#,27 BV 9Ś$[=DH1R-E%*DIMtwFdvi0!}LD|S5F?0󻅆$Eq&HԺjr ~O.NB7߭\tA?%4|xAک4kbh ZO`R5r`@Q`m)ׄM keP]m4X [4nA3 &9Q9EŜZb!>!;ФnA8$ Q L>[)(?6p\-F_D ) %3a(xECE*ymc맮d_JAA_A)OggSL﹦0y,"!$" "(+%y"####$'(*NzGTt78/㲢9L"'"xq}Tn$<ϗ=z&__Gg z`DV> @!F9ʈX Ibj6 g11]f6d22AYc,D"Gm1œ A <̇#@9x?#_z:B@|De% ][%XC05rK\"1 &*W.~JJ#x5 !,R~!U*·,Uo?eGesJ'8KӴHݧmd(ǑkCcDUU5Pzg''Fq:ԔL ic-_90>]PtFʽxvl[LM3fRjzQTb>^~~̗w-NIHV$YL Iumn'FkpK[Y [B,ϱS5_|teDO6\-{+ Q9JlNwq>x%Vi}Qy{@ʕ7TU쪟^p>^}{sx63%FA!8]CV 3qX~9j:k\'s^`"eD`+ h7=Ћ;M?,3?vײ0$kmCxR/%@{QGB"yj5 |WPp[lJ'y2#;ѣ|0қEр E,W눶3{GϕV /iݞhf='MsG6usN3Oe~1 OpSKrϰU%'1E)p}eE?nJ9?住"zc3@T)ɫ/2yR,eX_D[SHH Jj!zX\1*;lʠ~gZǚӃ8^YQbQzPX$͑J0IS\9 -gn8X nd 4n#T7€'v(E$ lŤ. vಹ|f68p\߲+\ǒZpIBC'/ "0U>p;ph 8PD\G5H((P U5]!$5,Z]F+be2Y~ttb%cϺ͍;!)VOoӗC K `y ʾcw 5Mww?WD3 %2!BM|XL5$d hkУmd4W+Ņ7~%=M)dF}`@5;}r{G@bD^" !=j/(0̓ <Hb`HJ mcg Zg)Z"WqPSH4EDiy]8 33'1 uo;-`ʮBb@AECB e@./Ra= `ljR~ RBGP/,JCyDD=]Mz11EoV,Z% ΐ?H0]A6Ӵ`bP׈ HԂE(J#iU#V #H.AuD^;r u*;.zuf5'|cQO(xGѮ (z¼.߮BTW  {$7 7D.lJ(^"HKD5]+Fl艭0~04m;٘AS#î%&wg¸_q%礪N $8*z!6~I^J7rJ!$g$(:f|v?m$DnC(jmѢZJ>@+ɸPk/EJ:0%H~kae϶&8.b> ?!?5`=}6zy4w"}j"(Zt s츆9VC\ap2J8\[FJ1NLWc U9X  ^[.lOHD\M14]QR‚~ag?뙗w|TM i:H `0X >PxC.elɘD<ꠠeP xD TZaP> ^ld b`Z :4O) wC_E}R( BT}Kg/oAHK{rE֏.LIĚ^v 1(2Da-Tʍlp?e˸t'-K5$ on͜B5򮉲s"^ހmN hm5Dti(< Y JшຽW;PQsBG ˭ruct `{͜MɆTC!ή鰞8}Z~ۯk3}a`D];``@rBɂ рGZ?hyx0](`<EߊیF7  .x)aPLr{Z+Nޗ(d* RxϖtCT|V5' *qcDž~.?|u=j1nc\O4Czdyˆہ~㟵맿?|W}uXGBWH %Z| %-\"C 4[kVR2[j@}[4MiwsoVc*wz <@aav)FWs<̕ms]yYZ֥ӦdêߕYDЙ$5~3l|ܝqLאڋZq ljy7W0j~j*AD٭E\ɷ?{u܋b{sku(N?)U?_(aԬ`ʾT>'+v/3v rN6~VXoOpƃDwr`~+bMƛVόe/{-E"D;Awuu\K=hDE཈$UX W?.( *x0 䱝LC=un#H`TP#)@ &D*pOP6\>0?G+"DB"j)$ykt-ϥu87~znNS_! %@)@E`gTDCnY.}q".OggSL﹦0^F_,%"""#&*''!!#"!#,(~ "";TE 1 )WH4D :~;'_4ͱ_g;Qoo>HAXFsj;5 $ xOaj uI>6Iz<ܚWc,"+̣aQ"'JDDxÉFf<<2{ԟ@ҏN-|{ $VUj@P`DXSB=^_Cet b1O%YD3T6nrMԚ{V.zS $Z4Xն8_wpMJi6V6 L *g^~sMt}>-s-A9:[2qD,0ׅ\n-=HL%o$4XLd<C|8J$=[e{=5!a\#mDӆu5`u/U)B6>D+eKF '!gnŒQɽLG bPT*?M x_8/NNBvNM<Չ_?:-ul &%q?8-:ToFmJ *ڨ; /LaH,@wP`/>Dancm.30 at ]Nw>UWϻ "ڈ} _|@ c󓠿6UhGWUVJ{h2ݲKH3̤[UN;84E|""" ?9߉mW͍+;--At V(|~(Ec7etkN Tv{NvJioPpYTbF8U[k15.(]E E(<7b|H{KO]rț,tL-Xxhb o.@1s\{@C "}["Ԁ" gz˗gJ@@"@>K1,>5r>5RZɚzI4u mE? Đ t3=&*T4?`vxIN&7@.ڝfDt tta_±#GDtݑ3*LAHj,>\~NJsJfK;A{^b2¹0'"":tt現y=Q6," ܊ǀ1[):$F \jnƧ XF9a)G;vђYx~ڥtܦױF{N]\#Bɇ* (z6VD|LDDlPI ߐ~xwP?.#n3P IDu\ E#Ҥ1h+pC?e>;⡷ Χc[ػMǝ.8 \$HDX:gopXE2-ľg06 kA )vT7p vW*7CRR`%(" a;=VAxWǚ(MsV"CPAA H| d(㯾}H;t PI W enj 7 X8!SX]$\v ueԺNgӀg>>-ZzJn|}7t{o+ɹ!B =]T]F=g޶{vIUMڽĿ> U܂}$TuWpPn BeJDJEc`:Ӂh,Q1յ7.^9H`$ηL84674Oz#퍒~ITז5xe?rk,X_|[﷛jL@j{]7m<- >-_D7?O%4ĝ:A$8ؚ33_J.ZRL )<$%ILu͈;)[Dxfvg{l$Ilبؿ߿TX&Z6NI OTZ׎2ӭTSz*-!*l^۲CAOye[h(aSiGko6*azA!,Ǻua_$@!DA w<p tpOB6eYs< %ӗY {nx , h¡єeDħp ^q Ӓpto9+)lzhԔi]ә}+z"u!bnD }zkw0)lx$"^ɊD*?kP$n/`PkNbfl `ZpcLf i6R)=M#q\}Tg*5q[='pgQsBoS"ꯐZ U9\"Hj& qy+MHr kQ 6Dp*^+tN$e)v܈M-7b|L]h9Sc4g[1w /()Sֺ.JbMg89;J$5<  f,w>S6"_D+~b.iS\9CId`Vr,O%8giW翾μgz=Z=R @!4qI8@Ç]gD֊' Z)7$F_^GֈK x~kM{ ܚ;,b+-{Ҥf^f޽ k=e?>}&.T˒k*w .I q)뗑ÈRI`45R7QPԔF)iI/(7^̘,&`5ϢLA<gRqS >¹f$1 4B&h= I6/hI N@L '<hzeG?+ O7*kH2n0/е8nOq >_Ɖ@Nw}QSڶ@O__1uuCѦhL*jT"N1 F(y7lP J.VܡL*e" a:/|7| ++F6Mۃdy}Q8Q-w'3;wfXUonTW"zCgEI-y8UtdjdMX0$6XE>$Z(܄lR\T ڐVۿ>f~S$ L@4|x{,Uf}[%[Lՠj{Zg=01ITg]!>VZ<יUNxq B'DiȜE֯çZ[ ,Q{v@aWT}q7K{ؼ6d[,]k>*0+(Io;S7iZ;fm]$V{ְffk%I;$\PmEVrIGøܹH *a$#& ^C\$g8%$kz͝S+|cD-' )(-NS[%ݔ.D5ZӚD 7gAԠ& Xt^Kt˻ i95k:AĊ51$&XWr-@sWϾ5Ҏ^W=;@70(֟ RրLe$RÔ mc[KR!+H3mnZܜ%$w#.<79LEƠg\F~T_͎#vәB`@_ @@%hºc_͢ +#i1( 4 HebMFOp 밥1$ ジ,R7DD0QRғU WF]DY,+2}E"#"My`!vDUT kRyw~1$~prwq?G7{hfT տyyk2w4=d}g LF35N{t{My\o9Օs<-5X_yY<{)wKJDцӴ!o3}]=y-%eNqX]yL \חlzMc%b5_eԲc3,:1A?_'`ZGҠ~-zG_7C\@JF+uW:$mȤoTdڑ\T/k^0 2{{-ӻ ֬ET2;B2$rzB9n 5 ԍ ` W;łY:D >֛z`1Z-.~kl @/d hQ#1>n:^ 88I!>>݇mxe?Gؿ&kCaR0 P {@Gh cReT*hCp [Nf K1(FKTp OpבAG=^ ߢ.:Tc),x з]@ XqHGtFʊw5`2iwmաJP F]~[6H.&BK}FĈ"`Rz;`ydDD'(\r9ajW8UbRG0@7=r@F"#n.:Kux!.]IKCbW[L*E06V1pī?%dN@ kzs|4E fI s Q @?C3$BL`Pހdʆ\3~u nnOVGb lGv)2#DCe"Et{C:X=A1UWɑyMc{ʴ DDI40^ZTվ>]eðǔJD׾yS59?dxt6:*)RH4ͨ: W{7w`펃NTov7{+(TU UvB݊mRsLɹXAoV7}\YrY :.k..N;7"#[*:0nnp; P ڳ?_|>*m-0 꼙uIi2?i1U;jgJ@()' cM;A+Ա> K0Q #@ ܘ.@ֆ q\]uS? E[Rboo,,J/"@GӀsT[%`}1`yPXd Q7-.1 OnEd\e%hڇ9i ,<i arXJ1ϼA{}ظ'>/Yy;7C/(@`9t, V1 hH;$/ RAY|ܾVBƍ(~D")8MD)YcXMdv ʀ'J495b>4~|6傕;Q +\AE %`VzS,h ߃[1"T*)[]%@[DHA@`di,pIIY\" shm+~ )~ /I\ݾμTy_0 -`#r<"S:xhB."F=]Uz4J`æ!HL,-‡ҚܰsE~]WŲqDDȱSv8ڿ?3d-uN9>(*pV@—QLJFľ VPYn pAr. HF=OggSM﹦0,}!##"!$&))} !"#&#&''>;Gr(IPJ%{f!sA90jrTj:Bz^0k/qj%JWqW\W jF[%2!X)p%-4PvAD*v\lV.PdSqpDUEHDt`}NWz*K[$iT"a`l0 `bA%|AE)(  )\ݴ=bEK*F`IIuUA?'ݯrZd5?m\8P*bDD-5´f,3~ 'PG?܇6n? >hB@_q_p;X 4@TuXJOFpLBeA4؝h@6j{22mk TFib?^h=z@ݲl3T 皈\yWٲxdL6-)+e1Dq3E%(bȦވu*5.4OST< Lӫu<ާÍΥB,DӺ=Q5i> \}}KlCR )FdnCw …RbM$>B<,|:qJc` P~fLf'Xļ%1GLf#\p\](MQ:9X^MOz1iz~TzTZRQO^z_`M#nڧzKD qL./j%+%^$[tMAHn09n KX^HDD4p~+zDz/4LZ=jI}wӼWj D <^H 8`~"ގJ9I27o7dH-n0Iu\jNbLD#ZrdN)%G@/HLpFo(^-ԝ7eAoFW+7JkI I7_K|.nHdBMTa[BT@@bDl>K^ 0&ψx-p?%D?g-]'_>7 1'pHH/, 1 ()[A G4sgڄ|%JE>l>˒Ɇ;ӵ6 "|UD`ՓQlů.g V@e g12ъʚ60pg^aD4/k;g7++RTdCDlrL k8{ݑTiRF^ c/zKzkҊ-2V#_}"#@y1404Azy*R!(p 0X# ̚F5ROJsoB$[pYЂD b2`"jUl^9 p{nb VZS:\ ODD# oT| 6[7ǀ s`mPM&JkHK'p~6bXT@[d\"Ji $S0jl3A]>}eE2DDtNi4ڨ8#zT_Nk= 4@RaD07pXŊ$J>tQU #ALx*t~kֶFMZS^7JD Z1wpN /)-K֧,XO?S\ֺ']M}܏"D$ϳhvK u+{@2Ѿ(mDp50׆=a姈Nqa4=$NO̲yH5]3It\4I㙊״GSk`_Q e?*^TTQ4Mmm?f^[_Ӎ8n0yݖ\q<ѴXc'&,Xۙ 7mVRzfffZ .AZɚiE`4}C/ `1u(Yz ̎ddF n&KrHc۶9H@$-DT^N$!@]> /@r.d3-kn).JM`D [ 7Oش/SOŠM I{DDH ^U.~2p_ `} ({nG ֏? z VX<68Yd!f:R*vE-EԒ Qo"YQpڬ@\)Q8(m\cLI< 3XvSpC@AOggS:N﹦01&$!#"$+)'#$&"##.'}$#%!"$)'%^;n;ؒ#jM"vvaoYHL GZk&}B&KIc OO^OPTtf:)`![UtLRRfY|q)8TTɪ~|{@r5vk*,}'{<9a3"5UnNi4+e> 5 J݉5+D/HDi)3㡽op꿀ܳ*@ݿ!p@@*|+yEbHczPQcXIGLA %R {eixv0[Ę%|8zL"4,A?M4:_^i;dkpv9{q'OTG PX 6o~h8g ( ]mXbS>xTk È|![}ʐ{1ǖBl=\enb@Adz$J;MfĩS1hտ%`=+o-Х׾6,1AG01A銂eF+ 5xǬUV˂qćؿ ~+ js&{?x{փ%2VzV&@Akr HC| pBcXpx6 sa$B1ƌaHpq^Mr,_v2p12#s Xnɾ$Z.V8s28&LD/!Δwo+ 0?@(Lpj'聐@@FiXdxD{ϐ0!^ʕ$ӑMEՌlYxbKdNcE"葈h`Vx:?*GM'Mw2oф,@1A-U2uU.^VV`EڑE"MfG ~GQ9PViQ BXمSI$\PD Gt$a_~ޗqTtt>o?H]D.`ݩ @hr",@$F, P$b%[gix{ZK?9"uR Gĝ|^}=}|WH*k\LN"M>@U `0 xx!0QY=T#Ia1<ӎhk`qvJ_$<UVڻG6(uiW)X~yYBL ){O[ֶ,B&^9yϽ7<֏O>鹡hvq~FNK$et-1o|@Hnl3ӍY$\0.l~z&`㻞x;Q"=8*> "ODXܡ0 >Lcz~wMr]LJ^ u My\@kc΁  -HآяE40"Dqk6rK]1_!לؘea| o_fED(C/kH@[F\Z(;Z Q-~)[f! 8M}5'as/^A*T`:6cHh(0 ^k6b }2W {_/ })> NБ"Dt":ְN@R7ޓsSNy¼t>5-3_h9ԛQ4g^܃Hd)%-Hb9Ġz(5R|৐;l-z%C"Eez[R$w]x#T\v=ݼ\?q%xMy:,E&Y dTCO=vY9e8U%wJeZ[.nM_K%өr{{j^w7v&vDJJD`+?]d<C" {G@H=U@+5\1nNt@'RtaQҠMqh 0+%1V2t YG]"")(Yϊa _r^ǂDoغ>@Zy6, )h"F\Sb~ŠV;mgJlXP%W|lA`mA" QJ˳Mk෨ /yvzowYP(G҅t_RO-G# (Yxą8C鋟0)my<fY~X} -G[lـ$I""alFwcrsu>t˝ΌCeg?%ZE 6>z(?mT(+b G͉#=z(.&j|LՆӵQo }|-4G45h3cX{YKm1:L>d^FFL>i'wˋXKr21J7"4gq^9WыMs̥`DLנܨ[3;tuB2<pk],{.jɝކ %L^jN8p[g+8qshXT՘f:qh8yCf8xyWh?l TWS66S>X^m5%_wc{fE&OggSN﹦0+,z!%$&$"&'&}!!$$""(&({~Z+a4gG.2 ";FH"7|fY`45.1%Sj{̧/GEwvNw|ZٷUz{ hT4`Ν!4ېkG\%0qC!6r>EKHnl#ꅴ'侵k.0"8aN:@-X]+iM$?Q Χ}ON沍n$mwA@ @r` tPۂ/@qh%D !XoT:B K6nIF- Z\$] \ NS$DD>L;wԐ ^{(u@ Tۃ`t3>xQ>`E58E]$Jp #!:c"搆^KNrN$z-j{Ϭ$~6C.<7x8Edҟ&"zT_T]٥]_ܾY{|4@@w  \QPJq7 =\=L@6`%5"e *f5Pz¼ т|/Is`{.8 ELi" ̎fT{0B}n8Rp58?  *+ OV3k{H0ӛNR$P YŅX_r wƈ^|^@WvǑZ6 DEr@"ItJ4`{Spë8yT'.Տ(B%UZ=z@&W\~]E1b"׼^K.'qK7EC5 "50oӧ{ޭ\zp! U/Hǔ&7m jE$CPbVvZ _ _^ÿ%j;*dD _ ->SڃV.x7 T ya|e =%^g | XI/(P/F3p3|;tޔn'𞾦 @ z3Y 0psH "*B @V!5A*!jVZbF1-Z쌭% QO8LE!"-=:mČarVֵXpVUwf_m4TCSRt x+n`n;%$@ pX`U7Oi0tWmxM  TlΟ)W`V{T3[a5 LON:.?X=~rп44dTWFcGG;!4H62LنֽٞF6Ӿu!8ZI;D@MV 1_`]%~^ԎoLה?~H:N;I#M$tS5s_VBtpӆ!q\iD׵Fدу;|͙S{rS{hTLSZi*p>dY$j6q+1Ҧ\JFpӪS &Țd A}.+ŠHpe:%Z \gQOODt2nx4ThW~[|aw2xiR00H <ZA@N0fV! .ŊaZat[vp&Vaq h4nZ'{@P Hp`ܮu(x`eQ\@fA%,ڵ 2ǀdqDt]Y~ebynyrI1>9U0S_!c`"4NH-et}B;',ByHWnC"`=;nI+;ӈpaQDV*vt9P9`E6/R?3g.ٷe;?EwػaI'D*_\AvHps^h:<DD h;SV[ʓH Sk1 >}ApׄX-;n0Zj@baĈDcL@L󌛫<,-~/wrՐm՗4xO5q_Y[`U{3=_cFL ٧<`_Ϧ1Sc7+D|73?:_zKtlum&_XQmv*^M8EXa*=DIx(Xl\?@p%BMFӍ?iå\GAc63H.ў' $_dH˺}(@ M@lF Xn̲Eɖč웓z"2D-~+i4|d)M*msAQ~.l*O5V&睔lzd r hDk";"3GTD Thy^@Ȋ#dnӕSY1:|`s"L!aZ0pߖ<0JIe|w_kI(- =Ƿ"P@%w";{[Jj{~ʍ$xD}KŐly"k-Rl@)Y(S$A{ZA?++S"J@~:l=IK$+ր_K${ܗhW(ZSW@HP`"nԭmY Ɠ0܃)<X1ʀ_u ].j ~Kb)Qosĭ'S0Cͽcqbt|*eߜ\;^AoP:VTpHh`uN.^ T`o̔ulPay'foo>cI&% `-7 كɱtXᤸHYJ)hn ; zΣ`ƫVhon#]ɘfh@uWrʫQ& %n3=`+Bck^B/dϥx ;W&SQ #/jO}O_AXMG #9cXLŝS ,>9 %X,υ+G3㚶T2܄[^Di,0XHX{Qg1q e#ى0́:C] %W/w@p`&>CQP"F'ЦOQh U~1?cƁ}U*&6[).^;Ul@*95&.7ib|+F^) M pq_rޗ65бFjz@qAWdBƋ\( T\Jb?<в*1;*R׊DAprjfgܫ`z 2Ncp}a*ODDpL:_wbv%XO#h MPw) FlC %Ep7ݦ`!JM ]+7"UIuҽ1kud8ܚGWg-f9þYJ?Mz##b;Mg&8wvҮ p( @t8Y g%\_qrU(\C/6OugqG<5b] \H`*mH 趁@QBX=npIE1W a9hK8 䒛S^b+{6!`iaRlJK>I;$;F=z:ҳāhFhuth3-Hk ˺Lŷ PUfR^1]2;EC=:ţ =#r^T'oL?;[,:P]}='3[gL8*`|9xSʇP[֦ Ʋ&GidR0"jB1(X"*W1̼9EpSBJicYI'3TI;=o9tRFx> E"VnARx8`Qn1vs7z)#Etӑ'|Bap^[d`nV,:6\LfwPL/IW"%$ (ALe5bю&č🟎R*n/@,%]1 EpXT1$b,*A":q`Ś[l >9M8#cüFgq(c]ؠd 6Am"_o/AzϹ'p/p+\ii!¯Va0ox2 V L? XMhWTJ*pRu8bZvO骶[D(u㻑6D$[bW оn{KЏJ9r<"m ԀUyMS j5# w@@r/c)+n$m'dON1\f$G\H]ZҧDܰW_=Rp? =#0Ҧ3\Bl`uR"DT>]ZR#Uc ^DV6Nj~bkEitax%WĦYdZΕр7B.5鰑<)gm `MQI:`nD "T5Tj 7eCAn)Ee䑹CdH\\9E'#OggSO﹦01"#$%"#)&(}%"!$#&,'~#"#"#"('#kqHfbAzTdZL*Dc>l{ͺG?Ʊ]Fuv*3HTLkrMGp۱30<__\4Mt42ootUa}:g/q6y!I\λl`R;y_$)x'wQ^wOvFfB>OzNЌRb&#u ARKS N O>_/D;'XجOEʄDDD_ş9̾i_F8ekIV! ʶm! <Nn }[#U8Ћ$>!"rdR#]rc=C*ŏFJODhhldLO,G:Ő(@"W"!dJt/}$u}a8n (#_{ke@̌& } UF-Ị)`| ܔ dXx=`VUDq!|HFknbˠ؆ai/"v:Xptwae氪'"|ҟcҌid)t@ǦQAVa?4 {= X%KPxkjk<M37!KK~{`OEHV-{0͋Žb%?α /B1 7TPK!b€~@"~v  %0ݭ QFLVcDKYqh&`<d[X+ܟ`^Ðuf"XK ̹RƸ Q XUhdl] "l[Wwx[?݄x H\Z* Dj[AJhE0Ւ%J'(Wp{.z8dرok㶌l "htT8k6 [g˿k6xN3.UdEa.n5w16bK[V!.@@P"WeT@]ԝnC0Htru0B>cN>[9OggSO﹦0홷.|u!!$$!&$'|$###""(%'}#"#lvfY ^J_ {\,0WqA`1p?ƞ~v$tjczlu%b7$}Kb a K(ԴWFw|Rtz"":]Ό˺=82yeVN߷?QZUB*/~ 6Z}+_6)[1$p+ꄇ@t{K[7<,~nPy(.gnv@,D0P WJ$ WIswyPt4IO{rPkw61vil tMU]NGǃ*͙u{uufjd>i~|O[a4ӛ^1JfeL*!=~I& 󇾗gƋuvEo]O_{ww`1*’)!͖9)Mk \?+P09ghn;w~+ʳGpub0X#z_Z6 R'Q4ҬdG f]񁄌SظOr )=nO+06_>LWk8Ș4"rGrW<Ǯ[Xu z[ *J yae!퍰 h$g57WêGhD].n)N37]_fS ׉~Ş`R@.O{V5=4€5lBY-oa`G =Z$ "$dT.p2{D 1RqDhϵڟGMV$zķWsТqlH 7@O0A`@Ҕ@<B  =TcW.n= &'H`[` ~[.be4X#B=[]+OD!1ri}Ȼm(zkw p#*@߸v sIP9th<} 5{Ό2NwBP p{Jd`ayJΥ>;x LNǒce ˂AI+Ut@'p[g{ns} P/\!*e X9 L9ZÁXsvOT[cU!#$2npD0 p ,OơLsd;t˩tP`׊-vI~ 8n[![@롵bC)) P>;6ƑqVQXHʰ"(]#{J%Qͻ  4> 0mDrIn\"~ K߯/lN)%BM"Jm14c>^+DGGMK݅WQ/o@T_7` XQSBaYưHWˍ: QjeDFCA,3S5 EV_71QB>i:8$ICU ,p6?pt4}yܭ=5u.aDG"""B0keCIz,hKPV%#ȪA؟54<;p,u#"B;eH']wɎNjze%BzDD23K^bxH|@8Cu M| FT KMra+ ^kii`|Ņ鈚kn92ð[vtmF9(SFͯYB|_@U)D #,U9r?^ # ZАrwngwҰx"܀FkrY%+\MI?,:sED#0܇}Aٿ1nQ@cFOMA"B@I D@0[Դ(uňSˀ.{P݃TP^KpƲ;y;r,c*c9/%h nzۥMa@-c]a jAyЍ~ 9Ƃ_cQVv0`' .Q+b`ҚN~ nY0H% ~L5ӭ-=dC`~&'bD\g:.ͬ|: Y]oCzMBQY _QHѝ 6U;uĀ滑mcVeBXo+޺YhSJ0[E/B%taF"JFe/~U>:7KCtVhA$u#:+aPP %q#Erh;n X\\pWT  .hVVK-s{{&4!cXx1Y>%D@cF[lmI0]RJǎ5p$Qu )1. {t8"@ g@6H} \;3(V8tYK)8s u|sřsJ呈fac:hZꭵ\_]ݷdxujG@I`Ur@ZXBv\U @'ӗ{8 톅1X'G/mDh#pTՍg̗'oߵVZM(#jh#,M իkEOݭ?͹YQR ;ٔT _~s}}l&”ⷝ| OggSaP﹦0x@)""!'*(~~!#!%#$('&~<8U.~3⍜<[FO-4Mj,h߾8cn v7%D΀m[[m3 5>o*{YeWǔDQ[;<}3`iE+I?ǵW]LUYzOv<i> 4D{I/.#k|c2] DYKeYW HfrimF6q#qS\j\ :; D@ӘKlb &s+Z+speN?:.{|WA} <_5%JZ"Hm`T@:5S.mUN"B\H gƅŁyvxɔ͌ C 2 S0ȕ? Rr20L8sgoT~'tjrA1B@ )F  *`uѭIѧ0nsQV]  v% v+8wkfD47NH&s ^6HODH7hR)~??v a_;G X>5HZYO eθI۝,?ѱM$Hh,7 ]{%Y] [^b˘/3J=𲄴Tq.hv);n.wU(d n 7 Po;چu`lR)q|eDAm'A`kj)9& H$³>/;| LFkyS{ 'w.Xt< gί5} -xyK7ݸuq ,H10Z@dPr0e/atW}j3|D5`zFRe^n>,nq0dV:t(ł.pv +TӨz|O5wN5.x áz0Izn Rh"b:Tn֋3YΝ@J 0t@a,a>;f1jfhJši1Z>yuq 7dJ4槂̓rv$'轜OZ(+((ɰ"@K{Ս-#OG ~YX@%QTn"V2aJEL) 8|ha .p tR?$ V_[9O"::`cxfBFTr.n~"IFD\ pR21Tmh=!G*& qJ:k.774,hWJϝC8@w%Xp_0`X`-ǰE«2kK?:9Hʳ W >5dᑀX{i pˢ+qDDh_Zo[{+ˏk$ J`փVx98J*@` nqaBF@R $:Nx Z_ŞP: wFF cI'""J]I/ y3rj;O珯l=A"$`Y&7jnP.rhp{du*ÚB3FeR(ITɴ^`*6hMd&:}\7;>ҴAS[]I->?-[|ؔߋ[O;*t0gAAς = `ĺ~^nW]L~.'JX `.V4HG>hq]kG9-|,ߑ^jLgWϼvhO͌ '՞7.T) "SԻ+X0aCBƒFq-j9ު!gmqo1Hn ]cS˥+g bQ5`) +8~P񤌋 \O)хuuj =tn^&g*X_|VisNb2|`I@ S,$%Gj<0j:V"Ad\7wڸ %v*+^nfJÉhzڱb1Xn9rD".[ wa5:\HA?{b(=Ng|HcUF'bEe>5-[(AL,״)t|% MeIhF>\^YŤM 6G\,WyHqէ}[|RߝPUR2aFxa?RޑhˢFX ppIwѲ0nh *) JMG}~^6^ WMX8Dx >(V8x-z$ԱJ>:!T\(MF0#c> A@۠uZ$P? 1nD+ł*V:ܝ!"@+B^|ZQ&λIOXZ5GI*:| kɍsbHwJΝ1B^SMӹU$+hQQѲ` -(@%¨ p,]ZNnhTR(cpj6z `!`Mc</Bc"8:6{w;"R݉|+ cXL Q+In{,1&*@V(4ݏpW R=WDD"aELFh/qͤ3Y.n)>VRR\ِt%, D?(/=] !W/IuV)|yb-lFj<`iwMk3JjE$h!%'"^H C]́  ދvnJ.>G,A꘢) `$hD Z^/?4ڃ~|:o^Ŗݺ]vBs|y*5!z8\Vn!fu*D .pB pˀѩq@qҖ(~ (Kđ+F+XąEqNv2|( j-b1ɸ>~@ =Kc^ %TnPj)q 7!ɑjdY$$"[NnM{ah œ$t\G,J$SJ ~XGfĔW} p V@ 7|wUp\eid e]DVvC;H1RO!T;rO&.?M4ibdbvŅή9NO..SE&/F K B@@: HodNR7P2طC%) D2XP- [le9WKDMv04|, NdQS1>,+vRZtd)؇]rHB `V@!*t4\ut#Ap #n ' Jy!e %gyf4:nh4C5X¡9'#iI]3rxp% a: ^ 0IVz^*\uU;(%p2""8 *ŖOggSP﹦0Ĵ1"%"$&"*'&"""%",'}%####$%(% DKAx;bT`k8GJDK6,u)Iw'oI 1?B U#m_ם j'cF-n\EJ@$_@DDgB!h Tp TlI..lIa?k{ m/_5Bi+%JJb~~wY,""~yf@[)VPy! 2ʁ(<UN)e\_ /V%VRSHD$zU5׼yUh=֜~YTZW +z 44|oϾs>r_!^%,Lgyy]@LO{G=a L٠ޫښd򜟯Le$5+r$GKG˳3 'eu)G[w5ӌ~7r]_W*% (p>Vħcqt} [@V(hh*HQ(~ B+hۀLE.ca[NfMC#Yr!{zTEQ Y'll|%tt&& w`# 0 )V].rd?)8E~'g -Rh %`Z1]!Q-Z"(մhb $i- F$t7h"GI?c\|##=4".D;{I )@!f ?n<0w="O)B4?9"BꍰGXGE2J"ݸY~HʈHD4MƒwM!=O-s/W8D…T:b :a4+ڀt Hd&qƲc-b́j .^uDdU!=B(ʎkKF^4Mwqml(@$pAG^p^{%t%DЮKx{@DAl_@!N8BLpnDDb3)p fn+tڨƠS F {uFh1+#cO}W2FIFs¯Zk\\Dlu4z3 @ܴ6CPnP GLqY A.9OxH"" sT تԭTŋnr픙1T=ӎs>~><~VΡ,dML zGW/omx]*c_m.8%VՎ!waP TՐW689Zl#]4;o<t/08>@jc 7l?L4j,o~hiVP1=S{4d^+*2._Wm CkLO!"fLJlrϯ~#5 J)"X:/f;k|J6z}ueo!6nZRgP'0X\QPTOz8WlP'#0Viֺu+޻r%M_YڴK٫0]J!BQz2/ڣa(:%d+QoK{! r`pZi@ 4+k9[ pO0m`bed!]aW;rhϖX,@'o*|: yz:3Ȅ85kARu #JO7&@R}|5[4gI֤z k3wP"`Et)O1vu__-&%UkN3^ @UUD-rjز:@hqCo:N~"ZЅ6M@V^8 ra޾xF i71PpW,| U0@$*\*!*t f.j6GxvA(D4L~\^f~88;w,]~]8 "z7TI\lkJV@U&|$I\5]dzYT=_1[]I[0]kziK TSR""Npb;l켳-f|&sv¬]AC-H{ -w;U (u8KQBgTW*8<|k'C[66V}d+e_N/CG5@iADD$( p?' c㘳2O>|sj@n0Ї{*Q-1Av‚pC@"RF,(~KvnG$S_|)d'{|] [NP >~]ٕ"D Ihgn2GfE[(w"(+. t\tFi  9b ޠ_U>J eEGf6*b 3}P1e=K]0R+?&^FXI J"1 u^.q-R]f4.~aL} PU\\:3@DM$rn0> i*D IOMt۽ɕ "=}A<71DՎUFzE_z$g03?qC,Tk:ng[1F.}* sj^ TQ5^/Y P鰛&n7BMbBuz~LUY3HշcӴe^o# \Ya'joYKiK)Qu71Y&:FxJn.ɛ U,Kn.e5r92-?} o05q8%DcVYԖW`n+Ze,L."~ v|4ې0j̒w<"*(J> q ֬Fn n ,3GMƦNkVPzDD ^*:ˉ,拒#573èqt-obq e2{P'[;D $:d1 `֓O+v<r^5bI.r$z).XTpZ)W?MDjs_tdr8:,}-5x g_)1A%PL/# ih i֪1)Ay/&Wg]NS(Yy=i]׳=)ѭ{pge-M@!r.ʿW=YXH<p"$T)!H@NDӠu 1? I䑝v׹L+TՐ4ӓ_X=/Yᔯ74J$4׵ۭr0廰;zƲRYQ#Lk)g}-UL?~_q9BL Ȕ×kkm=Ht:?aL6<4c>uM{ӕtZ'kL* ( e') I%5Oc8}2l[>=Ld]r+rq έ_z* bH%5a07W&ccN[XJ<=!eG_.{ Z.tֶYw=7'vUҜ[Q3 1u?0*zFL ʚ"5hpH7[9Nv֫ 궋N)IXQ{rN Ȥ.=G qD Jx"<%:t_9 |=ƏfxעaKzXt7MR!0Y#H&zSw%o5pDDX9h+X\>+p(.-DlY#%/>YxhSwRO/.r%ϳ{b#BT@g*m` #ch׈;kPkvb Gbp`Vca3x+"S= }=[= $mPRcl}Rx+S8=OD-bͣp 53MVJ͒GRNPQ a^^+NrMb.#R( C}JN^K859@G'=9 `#r+P#:NiP7ȉ*@_]G!c)̧/0# ʅKNQ6YQskLr 4|_Zet"J467̞8&)wڣ7ﴞrl]#n }z 7@gT2R+!f6 Q eIӡsB (kf@QoY-*~kr@ҋl[WN2]T$,ƫ:%t3 HELK9> ۮğTY^bW U?1r;b"#w# 0DOxmT,Q:vtF!y-HfR1>% `)˔qwRk*Xl?=?S@)=\Y ^uP hx7|)Zw.7tuaIX\6*frCDB%ieAӫwqÞS*JS3J9_!p(@7zl im Wة%':ː2JI2RSTy0mˊLӾyL7/,1k+Dx~v~<"l㨦4Q&? WWctD>\yiN.̐fS?F͉]eٯ ~'AsІ4mDI=c:'aG+?-Ÿ\7 'yQLYKڣq4Fps)ƍh/gQ!:veSc\Y=YRj9CWNѱ.%Ʃމ%uiz:DI !.*TBVIS^LM4;+ HMEk~Z5 wʯcoz˦ã77Mo0e4T/R8Т{@p 5p`o\\LBQ6Ra!FktI\c%vh`YZu pq%R"JD[6~  0*څ"RSh_gw5h i5( P1촋~+ҷƔ~v5)e^ͪj"ӵq@iA?QTd?_VoR>_-nʅa7 @hdY=n W/6_fjb !F2腹XR^|z>@u,%K.ŽqԼ'JD}iuNB.@-/нw]: `~A@`+͈0>KaCqWrX'4+%8i!+h@t})+^&cB/w9eVDE-y:9rR كlj{BGAT?BA \Q$v@Q+8'I "ƫObMdi׈eVV"GFz/te2@c,UJRlBO\1DD4@,R װ*/?$@@$*_ FkyntO$C]Ԩ7Uȉ8&5kEetYݫeLLiQ:Ir{z,ih@wOFE :hf$\Q4\e{}Yv=MJ2~qŋIDDf7|?5p5fӁ:zxzS&%4QK^>LО<hGKFhqt4}UOggSQ﹦0`)%,%%xzy!!$! "'%'L@ڨּpW g:m),^ɫ94tqBvƍ_PJ?G=Ncfozr9 LWYlH짭Ett"0ϔTY#O~\ªWr󩯙)ߝȧ:*Pͅ!Zwq,EɈh"VzqAsrqx+R*1SvJXƌؿnLaxH9}T)@WIp=EmrJ$.8>L؍~U5$#l n [?0X1,$bHDP[αPOޛt )%&M h[oCǎ.,߀%zYO( FPюN`&vտ&tM(k+j-״nBBv%85e&.BW'$J P# h~_p߲ @* 1+ "=gzN`t)Y@2Ǐ܈U ĞJH]53ga>(+%+JR?`ߎeF=?({/Dԉggn4Rmc ;7)҅jE @[tO4Dm9c> P"B Dg*1ДtQ_>(sk `@gf`V1Hn Y >bV"e{IAL{Ds8Q ޕ"ca"B䴻p3ݛvՌ{gV/|? PǼx_sB(3,7Z?jeA&r@ kI #)O[#,^;NzX@ܞ @,YQ*ljhThrA{[ 0r5HwKS$nw% 2 Pp_6lEtO cD,3Z0`5>;b4LD)4_J]X*F %@u_ұ ŇI-.I:*dqW%]G]/wAEBI呅E@Y9и}( a/AUtx; $)eǏq7 !Cz U) "f nĮQ:vəU.B @g,Dxw0" >kEXk[@EQTLP*%+ZYJpMCC1ֲ)K8}ϟ$%5,l]cao>WP[m U:Y h[Ysɺ WvM\V< aP SW#@F ^-ܒ#k2^b-pC,`|~%"R&mSa}23aMnұڤXyX8 ]b׫-:D1Z<D:HL !x\qҘU( EMŘ!)V~knt,f'lh!R՟0 N?Y1KI>~Dy DF.`ZQ* 0`hiLCA]]]""dI BO!b[rYr%֔6߇`h ût\+O4% ^rFKx}fEgIVˆ]K0gLO'kcV.+Hы\LJgVDwTO B" 5N)%, pI&YRHi\vŏ?iKdOy6cnj }U%]>c?)c=Qj51D 1`ćba7JM7$َ!%cᾆE0~<V͡](`p1Yz(韈&[esXn٨wO~!%sIúmY(ݪ# 8ryV]Z 7{݇(LoT%\[Lqqg%f Ɠ V'Ą]k7jڷBàpx ƴ[pxe¤\!Nh<*q;,-־.j~ ]Ij>yQ>n.Vij* 72n22+@ӌ6ZAFh*0f (22MV[?LE돀^*hj -V@B;s2F*Hu 7XR`09 d5䵘KUla='pBU e3Y'lFι*cS<2@DF t5"{z a Y0d:Z`vq.\"ɁV)*#,!):JPPJV4VDD4](6fT /Z# {K:##92 C6.,=hW"谎Eps jyʬd3k,^RP'Uhc' >DOp" $5nEjtZdٜS?r?^,=uZkvX \Ր;\,/ENtB3pVmTӐh w͇sA}&J:#L ,(vɿ^\EGR+ueLנޠ9y̗udWj&콊~!وE;x&{4/.a&NDZƒֳ),?b/׫{qP - dk ;I$qoʊB*0w:6-#FI,3!س&(gp7prSCiM8=#""JUo:' *G@ً!, ʂ3 Atpe \7躋@်E$b,q(>*78"زKS7>ޜp=t/HD׺Rc2}1[}__ :PS7!p0iIFL@~ )"0" J7`wlQ(pf 9#W(mjd ˇ_~kbIɗ!LWv_M8߫RWgj\Q,ۙE8t,k?%SӯƕƔ z*ưteUC`XcTԠ[ 3@;1掩vr!DLQ~-I¾߸ɴfM*Rn[i@_7@S @잯' [>#b)[k Ԍֲ~[lԥGܖ=z* ^an` pW;A{k?Nq8X*~ <=m90n'@F`2lX;n`QG#dl!V):^+.rs8K䜐j !>&)A'$7S$DdQU\Ő{6/FN iB L"`)T#d9^$&|E;F%QQi@Q FDQfɅK 'zFC>9jnfs.~.G a n?ǴgedC*H؉2W" 5s$`=ڞ F)'UV{́rT0ì6pÀ&ܒ>1[~O|NDR<7=˻%/c!";@]:/2cXk(@$`@C301MUDt* W_]!@4.k Dƫ ;uOfP@LX%g]T͖t=^o U 1/Z-DoXxp{f9]h(DXe$ DHuh%H}TT,46DZ,n`aFUpGbŒ~KnBVVM2 [zb|Oα_E$HhBb/lw׭Ýȫ6 j`a4 ``|#kƉ*`5 Bp*DʑiMlʱyiA nj<] ࡁOU%N@ #V8@1($ 27jtMD(OPa6 Fj(ֈೋѿ!ᮟOs?A3w#?ܵNWq|RÇ9s4.H7ub;#e3P:H!`\ Xn"D::NYBz <qiKjmY|}}cǷǕفC)L$S5H.,xanJK852nm>XZq|"""ʧYUBE_$MqP^Iz*1-K,&t|[ֽF5x Tjzck7L}޻A CQY󺱈Rm:cLjFz)m>0l0B)9$!SY':mGm4bu;h>0v6"]ߩm[k@@p\hrA(IyS~tM7 b6E{ȶ^Qg *VGD)<,|j `'Yfƨ]ZDO{8‘j=vXj'A>1XD(*\O]þւpQ$+g|j|lNw|CzȬfR՘-DVVr? ~Tn@oySeStԓ 'VV#4ѹ#3hks1=zk5H^Dt9Vwq}ETB1C 0#}UA7J UHK;D+@v 5 1IхCIxnpJ2(S_t$Fe|>欔OD4wuNVrG&pb?Ϧ/GTG@D'.D7B VI VQܟUZ]7.ةSp}DVFF`Dˤ΁>; E9%/(EI魆.  -]]'B@LDhZ|^ :zb%?v5  m8V,ßG:)5^]I`+۠2< |ATc)\$baN_"5'd\v|D6THBLK=^W} 4IÃLv3K&4 TѾqynչuή}[SĨmPcJWn&SRw6\׶eG8 V?r_NċNVLQ=㛩$?R9s}_:NN?\dYRuo&u|e IS }ߔZF8f rњ8L⥒ p,ӀgsՉ"81=&m,]thb1S[/zX^@C@(MMOI{90'v&{ x@r> fbMk$agmp//ˁ̯,E#QJTUO_zo{[w!v @ `pq'(蟛RKޡHz V۱#GxD68D񯀌!f.ĸ4TV^z&"Z?O6Gǟ3n;8(muN@L"TPKP!݄Q]ҏA^h`ȸv, >F eq}</+C|J)K+gF|c~ ޻ΣM_4,{mPq3|ziL$r/@ROq)97[ TV X0{,"tɛƁH4Er*ŊBzzw;NVCzx߷7 &!mPwTR#'P'/W[-`cko" O7 D}jC|j J%OggSR﹦0P2{z""!$!"$)(#"#$&")$(y}####!&*(n6M35"IBPqBOݯ;lh5U3HaJjPO%ߩB,`c7!ɎQ6p4M(, ^i]zyL[s LqM&f# 1TH)W ZD[]Kl@,:{A6Z HN_@Z`]&|X="@, Êʁq9^l G8)hi6rE"ѣ b.GDH2%mx* =J o^(,`Q0@*p\HfKĜA{T~?uZb'` 0 Mċ>mdV:qEt zE6tz=T8HՋ%[vbè$.N̆)\ⰣPM.A5q=%:MXqBXz~6}/0a4Uw쪫%U=kL)iE.rO/1J'D7foY\{+~Kx b*Hkҁ7¥ta̫`h6W6o&n뉅;y ըUz*L>9R{XpT^XjE/j5HYDV5 ʀ 78!7>+ 5XWjPz'ӟйv Y-]w"xU>6 rxQђnAϲϲ RGK4*~_deoB:][f3/Z.9#QA>Si7F{?%"(z\Rz-P 5"U *wU"qpa8PCm(b(,((Xep^mhdRCpz{%e5Tta\Dtpz;;.5pO*JpJďH2n&0S v'U% WW0bA/{i zUј !p w4@YH5P U3Qź2A,VҞ6KZUC:P,P & cw&JʹJ ǠaXH.Z*j3.9xAP@i#eL#^[?5}2x8=Jvmk8tӓ;RO3 oWRY Z񌬀~Q$hWL%m)g!9eFY5>"Z.O>7,ME{YLMVx;q]o1ܛPID6ty/[<,dҪ%D\49V-^S~C(=b8Z͸ 4q䤚"c x׈xʨeC}T׍47b_{Ryd2S34O$y˃u#Buk3eGr6S,Qrp  -<6h LWbS֒zm7$v 5NbDT +8F1ڢÆu/#DI340,Õu(!k2tm~l4cDٓ\ps6+0 Vdmf([m r=ŵΑ7U,!`V~,řp\gcNbnI rP$Tۍ;6h} ]ǰ$4"1; `stgo Bk?I.sUPQFFfdI"i41\ҹZ -K!8 1EODpaِtxG v hC SՉPEv$_͊Ա _aY-ޤk,kbeb(0)~\ iƸxEm|<P$8+w8IoݛI8==Cxn^H*|^1 ~ n 2㺲-#U JGy6hc}hE-Z~ZAPGLwؠ.];үrkddS,}mg&us!藵>W;MN$, 4F ?ID7ĔTŇs0EQTKb Ld3qqkq.]f7+;o;}!2\٤hKۼzN@6$ctn%15Dx(ڙYN_y,1ٿcTאihqx{|ߨK?yQLِ+|14F2cTD@ptg>t@HK+$}jb(ԞN%dUίi8lr<~l)mhφwd[TA ;򺫖 e̋pS+c^z0%7LN!lCƌ[$ ^{Xjӷc۾{Ek!԰I0b"J Tgo~i{.զ鲌SlɩB!8T+}0[;,IR.g[; In7_ޛ*(zzd`>۩)ne׶nYqSeU  $ `|I`kOeڼ;1s Cit  IDH}f7 @$ 5@Fԩn {tA#UqshwZ@dFo+Bt]"j,""]  >5rbً8 Q?l>Js9}>?hV[Gfw= ח%$v-5LCen%DX=qVjO!!RȪR$SY$-[bMQOQ&*(Ӣ4'>DpF/Vpa}ohG0%rO!@ާw˟:@ pE>Zg5@jr9J =8%~[nVk2S[|<$8ʼnhPl ?3;Кnl6R`/0/k<|Jpu6FB rN9ocM֊eAOI”0P.kl;&g*c3.u2&1+ދmW"S4 lX":N] ^@IvO@ j8B/n@ib8- P~׎+*x"qR+ B?>HisNz ჱ~gkYA4zi{]v!G^ЧS[f1xˊ #Z0e /3tVN$P@gm0@4'7I0nBLDuUww+~P'<6,W5ru,TGPVYE\/u|6Z-{}>e*0n Tӵ~~jϟR^ADDib+ x{)\䊦xJ{t,3_Ho,dO6@hsK/e4=GiP4cwe9,6ҟN/( wmF'}~+gۆwu~oi;ģw-BJؽ5f\H]mqp<oQ A!` b+=uxع%߆**ՑDSL,3XrWY~`b $ =9NW0>&H8s.BqmX &A1KbwF)|V1jڝjmGjJ9ݥgl"56pY ^{ Xs{Z!+ >&cXyU0#m~N~_DU.X' i R bhyRmhm{@ ОSXZ)2^`GBOsWU5%AglkOHGOHe"*BQ&>lJg? gMKiJCF5?%훣/="Zu_9;C&HHDC/&o/k+iLN=YxdK"";SnwDTuEŢx> nk\' \",sUqg^ \I\߾H0ے;(%߹3Ү3Ve \{U= #^.tDvMqdQ JT`ݢ3V~D@CxA{{i֜Oی?\wT61]d_`z笐X;Z|^Bq@ DHL3$!)[ ށ` D.*L HRt7}9 7x`@1PWͬ( t{o>[p[(ٵǗiJ H@|(\D <+(_RBYeÀ n.IEzlRp6VXQcνܩVH7pu:F P"r2( IzZTk%i_ S~`dxՆ!ʹR9N[50:)rqb} VPp 2KAS_[ADFP}…:*D 1x3. 2 vIfI (EK}&MiD?:}h?MA ˴STxas4&s;j1iE yїH.t[q'I""hS `rEEٝ}]T샏8^H)0IK6Pw!bEXY@vJRZ\ِ50\o]]W &y_Ds`-;ZΜ)H!dzO]~qtV9 {+fQxHD0Ko?_Jot^Bcښ)#L m:|G_?ĬzmBpZi(Jf5 FD~[tI |tSHgp*‡ nhS(/ Oΰp`vTG |hZ0O>.xқpd{!#$tу$"hWM},V~kx3^ >R~8Z"QjDD)pw2i-t ȷu*gc4ނ ޿vj AIt A@}p_aE9($ NMQ@5A@ǐ:p14Xrk:ri-iM"cI TEmV dQKAID$Tf>;vh3iHKnlic&rHH&@b{?S&'AܟH*c @16-:OoaOVo=f Qc'E!F>+6HD3z Gk.zePqa/XQAbv4I Ǿ(Ks>JV>A`?M;MOr0@PNb5d"p8*D jʄeqYl$s9c̼dl37`hlֱG:}g+JC"(x͹wZ[Ӻ)x3r_ZS>O]>+}k* <"XkmN|jV-D. RhI$KOggS4S﹦0Y#!#%"+''%''&($% #!$%%%$! #!%%(($# !!#"(%$" "##!("$$ # "#*&"%'&!#% !$#)%#TۭɮCWCxkCm;%bé۸\L)?]mKF*6%\ӐQl_[0_?$ Ƙ?7e \i~׷6K:зL|]kJ TUhY50&Wd%d)+"(T`jp>wŧV֋qfSDttu?zgj鼾ohu"TYfJumja .c穔gC5֤V^d_YV^&؃4P>l<i7[0:qU0q:;eThCg (/n~em壻X̏/bo=t|<}EF,T]OdpvL1_"sDil#\Yi1įm#~('L]Y&29Y:JIj$'T_<[C0 Θ>dW$^Olaͣ 63gpnǼdz R T_Y5)t(eлEzOa/GL^[MZ_ٝ!Rգʾ?\u/:VK^=?(އVLW1nv%`{f/monzu;T[~E􍁥'͗,^c,eźmPU7d_aԕU҃Eltչa%kIP\$?U*?Ix0\/$Tdl͕M#w}r|ԣ J+fS5W翞X=H˭ffkշ_hGTW8V7h(_):t%Fd'a5LWDuh^ f򝈳ΒSMZ%Cda]Օ5=;e.jd[ )֯D."=؛ОQSVYMoQn&.d]59nűw ?l soys)DѠU m/2ڼ^~џDkiDW*FM:yN)$ˤpi\Wh5(?xL&!;+ uJ<]JVIa&Ѥupͣ}wYolkV=-T[d(D*W4 1I#d .D[U4P#|)e<5ĿaVBL\]=j/O[Cek7\]e ٕlo `v[R :XDD:tСPOi߹񲝖 w=L[YBQVA6yͼN]=UT]Shs3xnkhۍخl|8z&h/Eh?T$o%F$nyMUMy qzЯ2tEmV) ˍhL+nΗmPM-dôcfh9^`w{ e|fyM-w9>rD[ߎ\_EГE1X{s5˞٤9 e|͙FL]$Yq]@B#dwשLpRf .bLAqğټ|VC2UN?Fs3+Ғ.W^aUi K}шFWjsj=u4.0;}N#ץ)!k~;4q^Fyq:s2{d;&Vgy cgչo #_s>Ñpg'r|T]TpoS'I~'mi)5`8(Gb:H_gYtƇLYrQV&T-P ^\=~v2)O`\[i~ &]WjhS,o4FLIJDW2,:}{|>kMb+T2ĴDYtV }xvuim(#G {uS,"\](Ȕ/n\.P磖\8` T[Q*ċ%/_IŰ,TWiY~CzsarBFD%DBg <L0Oq^$")!#x{srRtʯUΏԍQT^gӕs;\*U\Bܪs[EŦo_@n߆RzсO+9-8A OggSS﹦0-'$'%(!(! !"$+&(${uy! %'DYi}[OGU3ɔFo-\\[犢Ɯ~}e=X ȍGxuyn/r,2"SO0|\M _d_waV*?Yq;oM=w[z2]>R]Ǖ͓YjELDȦ}ggtԶc!}5UI-LT**W  <.ơh1f{դW>IɟgP %$L*,pwOH P $;P,(FXWUhPDӄFe^u>rgiTek~0/8iAu덪\S^&Rg?5V1 aA87k\A+ ԏ0!f[݃YSL8ny䍈6UCfwc߾C5@Eum8L}oTeY H5Sg0 PX3iTi![fc݂% h\ t9ϥk⹠MWRGtŋr7Z[ _pv 7PXzݩя0=zu =+$>~y-D "^\6A/r@`]q.J4GVDk>t"woS!{ P dPLLal Zδ}Q…\n Ln!. 뫔d,,*YQ4~.G Crx`msa+xPFU2EJDGs]d6ab>?r_k_84<*hbDK]4u>1y!63;@ vB ZE;"2I5{vˉ  ץ԰4ғ;}\#/Ŋ0pбyPBDO7o Tb0aB+_J`Q5DꘇA7ԫ9QB듮յUC=CPg .~ID]./s JrU @$BxƒF_㧯_|G?k4 ^{ܧ~G;']^(~6҅RHw!/5=ӻ<#DFmjM7U;a*,ӟ6>j轎U$"Ud1pkI,e~Pa' az6iO:26JR@'yn٥}]^|Cyr^wN2R/wZ*BQM[v~@@ox@EUxË-R<۟ݬt0NzqGƧ=$VE;M<1*wӋ#@Ȯ=u=x:9~=W, R?%|bS(7\+rzt.& +C`x+$Z>yo!de_~DMɐ|TY*H4GO~`aOEx3J2JM"ATW31\[E{J{#ơR8KLSʑ4߼!n1* I~D07+)?p>G1I{ٳǑzgun}NF)S]_i̘<%˸l:l] \ +M١ޜXݘLLw~;{np8ϹzL$x1ȷNf 7=}wRgbalG qgYE\!UNaZUvyQ'pW_^1<5g"Q?f5t8raPGXlt#*%[kb*CxL d"^wϴ6#C0;x|9.%MvƑ]q󰅊vl.Pt !>(.-Wt[e!}Ly8ԅ=ZZ>ҧ>mi"kA;=ۚTntD[voe4'`:FfU,tJ 7YeLA/*\%f-k"jA>Tm5iF~. >(@rpΛJ]DXQs,J& =y1:n_5:Ct7Q| `FMPy0b H i]W > mM\޽?a4n%C$,%OggSS﹦0 #'#}^|nzr ^ R!fbfKگ3e S:n[2O|hbP7d)3"T34ԗzo>mosaEr㜯s.k )h.ArSV/JlcVTM6Ϻv Jف\n"FX9:l$9c[oQ` ,@& ڨryJM;U7`WRf7r,Ë= W-xdtCr>՗s 7IAȥňq4Jr%.+K^\cDA7LEbqp^ ?4O̸r7oky|t+NzbA?<ib 6wrM >ֶ)#K]&ɉE3c߉ OCܨtk CҮUZFqFMQ .4E!عcz]JZX%t7Bj8#o=\tӬ|XO>^> @ 6'Vc#|Ov.jݣml6텸j@W\5UylæM_#mv$X>~T~IO-;N_" _+{=m{c*CWեX 9DXph&I{{k*pCp}@2:X^ G\f.:6;y݅57Pk.Vkz8B*׺ )+O0dKX b%'QLD$zn[k81O^0&~N+,h pO ::-BR(.4@4B-G|Jf3 #h(FsHtSi2~XXSk"znZaoABv "<;ϻ(\{:l3486⋄/`z8tr9nRtl~l8r$<2yujJWY)TYuLµI乶n2.k<Әlx/7%7,L^\m>/wrط>h)udXEd[h+` |N S;-]&o~٭3d_ԬK5yo?{~]e.Q[  Xa ezLU*yhJK.&+v?m}ewH,gs:,h(+A5MDfƙCNOb4TZ'Sޞx≍kdu_*6 qEY !On¶M݄(N vP/1!2(QQ$: )SP@=SLfƣFT%F12,`TV>Lcu;"Kݒ=>8THJr&C@UWQQFZW%punU+6k'ktW)F1A팱M|(q\c@ ,=j#΅l%$FJҠ*O=v1BP? GuV2(PdEFFj'|nE!@esK+˩/{Q!a`v_BG$}"8f7xQ]_|ut}5 _%W{3j97O57k~Y(/tzuJ i}wVCx)6g<*l3ُcLN?8\CZ ~,L< -YwN51۽#ko[1gD1USyWƞqcǘ+y:keng _Ĕ :7{nd*oJ~kܦ~;MOߒ<ҊǞg9fgg',D5YjI5Ռ%aae(/UмϬA aNJdCw^&-pCB/bW 73&'9NJǸc-v6q0NG}o7 B>vj3@4*;b}1bk5኎R_64Oð/^pcȆ_l_׬%:f:w:[Ұ N A5*vRIL>+FѢbbh`󡦂)aL(B,WS9(4I3|abH$取1v1*S^fb H2kO⨾W tL l9?S텴?To\sw4< n)_^%z/v)@(QT|=)Ų8f0&|>//5Z," ֨ CWw#$$NlI 7 ,1i@v;jHth\x9PU֡᫘ 5ZY MYk8A!W WH[劾N4[m$7@>\˕oRZʨ`pa'~{cIA63>+֋RnK\ w~ю%:FM_lif~>///*M x5MF]*2}B71$? 2Ђ,QB&: :JR %`Qzŗ?ߡtO)ҙגKңm]MewTVLs"~ޥӖ|w5szy?gׄdr:ޅG*StDlu#vw$\>^L?Wrs"eQ7 O +B|d- Hh`kY?rjT;*t.Ewp|{h{.l$- v9\^6 R0yMO۠ v6]C dCu< uX2qϑT+r2ܫ(ʹ‘+hTDZU E"NI`HNaYj.u $Js4m)c/]2퐆\}jZHH:w8ƟF Qafʋ uyJ/6H%k8??6ěO?߭| $A8))i~/4jDbZ(idA'FKKi,gdoZA-oOژTJqwn )!ǡsP&uמ"YVe_y8ٱcŅa5-sIٱX+L,u%eX``'5& ٣pp-n]1Wtϓ|0=tU{v0ł\.GoA&9|p~u6UFP `KL_u7w_x9\ ٔm|qAW9 ƷR j bI!ZC>%f@crh]BOVGrٲTX*.LtΕכGMǣSYv@i]vS@G';ެl"0c)a:*3ZqC8T`o!Zs8~76tchqu4dRk7W_b OggS@[T﹦0E'&%&ҳN u$^d,y_f*ܶ^H7W:bKu![]G(d5Z_+a0Z5Ϳd7K?%(|e}W{Zdē:Chc+L_[;fFH%}1$G| =%Rw(Y ^]+ Bca|^#m+?8  o [;\v{3vFnSd!čY"Gj7[1uHidUfz:HLBͩա`鞵O{:cǥ1MrPT(F.iixģY^ͅYI7!M:sC+NR` c)trjd՟=~IƜ?WԋTGXO`oeF3nt5N__Nׯ }Y:Cz8նL`K/Mc65d9fGoH҇1#XR%ptK**><΁ћI>7\#UZqhmT/Ef@.||ŧǮ T/5TkJoT#g怕6!w[_4n#D$68]mUؗ~sn+A %.R5W%MANi\Æ{jP~vۢχtxONsTNGhZT$/<=_KVB@'Tݼne 2ЬRLČͽrzOׯ=:X\??kS&2!44;v᭎%3?A\p}H .T^qRn0߶ DOtAV@.hUj AMߛ^6E`:Ǐo޸Nuw~wnBgik߾j k=G*2`NYNuH@$ ȸi ,Дpz?En]M-vj]cE|9Ӫ@lۍ oqS/>AGV#ϑovr:Q_}ќRoxKl %;R4:#'M-r:" @8@دc|>%2?aSR[,}4 +JDAamp{ 38tsH:@Z׶^b_Fê@g䌆Xc;qp}7a/DH$(q@:| ^c]LׅCW'ES=*,tLGSz}'cÎY4b+XLi*yBhӵkvb'QOhn̋qt!Ɛj9F1cH&jR-wGSKNOŀ4%F?T-Xx?-e/dڶfgYt'U S:Ev55N5#+eu!"`:Uy]?;II1Y+\Y$$kUA%1H9r ~1FUnqz`2X|~iQv*eղ ƛ¢fvpYxm]tLG6+)w А=9<6*N?$ņvÒ|&\&Ԡ_2ȟΛ9uE!W#b( )~s]>|ށ7|] | 즮s!)A]H r]~FʔGQMit;p_au Ϛi 49O`O%`T_K}{9UeSV{7'C |wUH H_!DE.wF%}_9Mg/qجWk*8ҜC`YYޭYH9" ?Y.gַ_2R.b[᢫q_[wyN>Mzse?Vf'ȝ[Hrr dcޣsX!+veGhkY wNw!rY=bVvJ1>]NP_Vpcf?&: ֒R_r3uxż}=}+~k4!B|_=|z .XJ?3nŅO?3#:'k u2%v-9hGL8ıƋgc !x!M@];v wzStqUBh:f٣*#σc>iu=^!qm/vrG¨T$kbi ;oE5d>w4rpR"U(j$ ;RSYWp%o[r~'։mX͓ V= /9 Xd& ?^hm& [[J4 ¸FLm|:*WC Oue[ TK%Edąع ě 3jh!- .-Hǣ+8%݅8cS8=7܁8mWR4K*Kv ow׏Ud/#s,J) ?!el7n֛d~1bξ}!ˊjڞ0{}{ y&lBtlAkHR&9WkzJ^2:܋+zK'LOOO,8s_gC/AА =nQ A9`M_Ƽ׋nwg\ڐ8G_#z' q9:lW-Vp9)惨F1uL c)BϟuݑJ?e9Kt/%͹%v]P2(VhlN҄B!@`sIEȢt'&yuNu܊mr7lK.)&\F\I$؋ȯj5SdWCY~ީOk'Y: TVQ^w1LؓVH/=EndOggS@T﹦0]o"## #$!#&&' |dg"4Z!Z7DaE%W?4CBk['I2<{Eg̏-+f,>"0h4#gomla$>a x,ח[a4B/i!iiH㦆1B:ejP$ҀtR{T% !^\NƁ!hwŌ92gyɳVbwm \*fxLv2r>R`wҚqfӻl=ヲ~x1xmHKP ݺ\gD\_;=jke>1;IKѦ~b7Xkq~*es"^.ߚ/ "l/vVrBh`Is\p+S}ZPtN|9(Q8\49:/AK+ʥST.+q1I@ɯrkmO֪|w]{޽=j#1܏$"'A;rK6dqF*[Be` $ , PW 6ŝ^r͹-.'=w3l5lT"Nv!rNRۗnC(cUP2p΅lCxÆ+V+F2ZqUf)uKվ;QNGј.f"ru{ NCC׎% ( D]~f`6+# xKl8^ΣgۿԽ4jWPs\HoQbiG"0\o]k6J+xRo׻^QWnOxG18yd1Nn-ӓJ%aPf(܉K6@Iq[KAKĒsݿknIxO۹=KwH~Jd;0)+UU.aܹ!ZeW3Vq eQ>-KQ[8OhVT+]ٖT۩Y2Gkެٵ:HaFSG(CJxh6 Ԛ2~*w/VIsuC ]k1]w{!6r[e7:]kyȩcM; {~Zw,; ftYLkzmp\֘:PB5k]OnǬ4:D춫F`XR3 DJ9oۛ kz|1rm@"^1ZĂ0z+J|8¢2?&i$g_"h-R'3p;fXn-j)U$ 7d0KQ׺NS>A*\)EZgeGS+~vT9W0m Ù>NR|IU[jM5TKz”!-ӘR"q9v-?fI"]TT/DE_c!nZh )(1 (GPhCjpC(% G&& 2+܎!O2]+xB|> ʎXQ J6dc[u_&L@ުH$5=_.إgܧ,? }\  *,*+*T |b,V, j' mPP#G V ^1hRQt0yυi.EEM8C)TƏ:.O}vZ4L5ڮ -S"U7i@ @'|ag&.g*` D` <i 1 G D+lN&c_|."!AF烱$SN͜Ȓ8Z"ng pw9{J_D-Y9nT D 5*̀4Dpd.7" & (*\4xX\F HN>"~ :d )ARL^:5qE:Yo< ~Ӆ"`XV&T$`ܶE@^ґQx.RUE6C:%mCQpXQ#ᚏvΒmڣaeX@)`]*:x v30Q@VDDL ?pYT|U.+@[b\4E&U~H >O|(#301C"8szɈݮgI{Bg3e `P&':h/\}(PAaBe8#J*~+]<{!rǚ5|pPs+J3ӧ%OOs> ;pmw_坖e㋮u] {I&/ah5Axú&эBqYweL> .oB|RE$>uZBRZkEKP Z?>6^r@ӻ|f5mﰧ0ɨu86W8>(- w:^1Nkָ4۲ 㼾eĺZ\,_kd;֦*6*?jbqv (1e o9HB+T_?EOEyXdy=)r@iA|K!g+d;?SY^bB6aCýgL!VPsw bFgD1-n>|. b0%K:;s)=ifSȂMq9[@jrLTcOC^}6}Ȭ3bI nk9йNPA3XΎ3E HLhh1ѥ"A ^LNn8e0MC K T|, /exEdƇ+[#=Ib~E %yeʄ \pdI4\nύh7 [D#w'P,`EOggSU﹦0'>(&&%%"#%%)!#" $")&%(vf/Hy  Mq8f{CvŌ#:o::3]5Pn [eu'BjE]RYiMs7@Hq9-5(s ,%0mdy\*'W$S=ό ܲB @Zn^Szq܆u4UKK%GTGWN( iSօX>_p dFuGj48+gIdΠP!2W. LY1t=^3%"h"v_5Zd?g̰L6 'M19$t+zv^5nu1t|Ȉe9o[ 4VtSf'vئih'z~p@9G5;RUWCF?4KQ!qf^wsvsEpTĂ3kS<X`msΣT^~vZ'+k$2jur~4F!xe\++QRSN!D0[6;g_ iъI_.?ܚFҧ&rL/Sɼm?6(&!| H@6vK%wwjÏֆ Kn oT&fQw59[K$N+M -q ֆ!rWaeJ #5w!ɨD|nI=K8c%\0 O#yR`45jډx}7 tל#F"\5"]IЏld&9G߫XؖIQ/L{MfP+fkސyXs]ǣ[ROwTjݢ:/K .Ѡ:)~a`h$y'+N륻/\0}v2+vFhmA{3[#(k:J fU""Õ0 M81stx+x}mF|,lԥ-&VlxbA"~ۥZ^z jN!<%o*߰J fQ{]W}Nr<XʒUwR;CXk} 9 8Y\Ƣ˘6\~~x+z~voL}[7wܽP߆chh!޺ijsCޜpimUJUu 7,'ziA%@/s++hBYZgOe2سW_F݇/q:715 0:i;4r BxilԇݷjׇjmAqi}9j7C\C2k@"E˕ҵwKBo@]Xy%/@Vnd#^gwg/&/QFM67Q䚯*d"cyW*H& >q*G&+}Rv>w-u׷ObVF6Vji1n: CIHpC^ v+qq\HbI\ps[@~qu#c0C =9@ n~P 7itM]~n%zR&0Ѹ }ihR}׳5/a5)4iG(9nh s)8XԑJH\!5"+e_фZFkн-gX˵ER% Ep'Kjn$E9ޞkV<EMp]W٥vu_ͷH*ԄҴ7aVǏV5ф;@rX*5 ږk LD(*=YhZ-M^\p2v7Gz{.#鐙~q kvMqqPqz#Mljd(ۄ8ta?yV[ٝ''|ϙvtci skD8- h$lg4 E码=]뷜p3n VLƃ7#QU* !f1aWԷo:)׃)v ziT S~|r-`ck@.Sxzn5A}; .4Nc-7@m Z@!.G:3AOggS~U﹦0s=!"!)''&zx|y{vx!"!! !#%#! "!&$! "#%   ''%̞[`vEk#. \Rar!. _0H ' ng!k"Ց9|TY!Utq 2I$@'.]RT<4ѯFD{M$t]5p!qVG7Vɢ A^u,a]ETx0>֊"C ]K]/!Xjw sF~}LX8ݨ]Q@+`o t\ԈƸUErX.~B"CdY@\Qi*<>}d~09-2jLW"YV|.iƢI5ŘR4Q+}#$Qj(0\uTQmWm}*ۃ-e4T3gF] LU2Ǯ+Ns-H]^DXB59ڷv \]AfN^t ypzsXv󮜎D[% B[V$`& &euzoi!$\]zS**`>z܅=PkEcl^Wn(;3a+qWD![o IWzq&oxq} 9.v'/5Wx_c2ܓWjK $(@@<+`Ct!$"DI̮B$_2|>by$SHi9"e :i#$,6S)CCI1G2L5pʓ3GWl}E,rH 7X,.ެnb@{VVq$ NKd#M#5nZ~ޱj넫|bհn(;#C ]D!(\jtcpn5%P@Wb ,.E;6.J<"LHp%r@I2f(0+}${e:NzX)km}QЍf^e@IaͫS sQXǚRy,!<5>|v E+NGҋX,\ @K#Z?L$:ڔN)q_  Nd8Uao9yÝSz~|%L5i8t2b,CB= BX8+ֈF0BQ_dcny&oMmTQc2OSs`hb{9DpQEtal2>"PG]NL#_!*zT_Xx𺦁/ծT HTY`."@0a;E%V$I\R3'сE  ]TS̩J(`%ϖ>z27̕!gH\YBOUb&۵wKrn" ux!&7LU$JK>x5]Nƒ"BFumuϺ(]fH զ- AƬqoG5K*Sek_{0k*15WFVMۻ'55j-N8Wi-jUI h F%kڢHdV@n*ڮBgWovv=1R<[æVc8Ng|yc_ {UHuڻ f˿WO?gfyZvڤ]7Xi^PV|J${i''2 Y%$V7]~,vQ Ѹ`|.epG5Jo/ }VhvsԢ2~{^>;vϊ^r2u"j8&@r=y-TcH,S-_VlNT^2<֩QoG 2>q44j<*zrWxYm.j 3bt\_]>fvO-MIOl.{։%mGR>*:v|F"*OB3v:|>fa?r븍k4{xĈb;rosn،-\ n8Y4g BToʙ]+cQ^l6:+N']eogn#,rn=Ac4۴I{GMv>˨/ !L^Ȫ⯊9|}L{&w$~X‹e-(Q MQ:%#,~+e&rFj| td9GKt2:us{~T^%"EwJjKF#U)"e"4!hp>Ni5d#s ;C̿kAO a2vm*,OwD=ǾW$'<{c1_(nb@7 ulVq8=PlZ~wҊ*!К<wmfo0RC]W\{q^y>Dj'wBxٰӺԔP Ǘz!U_·7?.رmĹ^B(hv)ff4CG8Nj>qb FiA9#ã`8mp;ǘ><]jg=~\d׼'Idƣ!B*C:?YղBv/֕u /oz7lސKA zYJX<1ۋGڝҋ_sn>O>s6$my1iwXU ,c!5#6V_6@32ۻ^6KG%*_ye2iN܆×p\ԉץ$DRz7u`vRD$_P;rcLQ؞cc.ϋ )M2 :S3G&j[0_)5ҽI͎՟oq(*(ܘJ *ج`I0F ;:L_^*^+!u5P+ƴ @0V|TT8FLQb{0 V @LS4x6AX.^Jae%q!j>M. -T0Ø .Skv/2fIl2lR#Z#Z%q*PXYP6n}@R(TT(`"|P4iFGWi!n"Ӻgc3'<|J1~588Z-ON& |+ TzrLeP7ڴ(:TEG3.؂H BDʠdP`qY cэX&wD )f}[p'xKP#_, h#Mb8s"ɃMJ,7Gc@s0F.L0n$F9Vkj-{;|դiX.enjJ%D\TS[`% R*2=P`].LM(0u]ɑ(:(8c jBޜ?70- $M)fO) >ˢut^('jN:~l]o{r\xpba؎BefdUQ,@Tv `ؖu O1-+2Чz/O]~X#xK@GqQOggSKV﹦0B"(&(#"!!"&&|LMĿ|uB?nJ8IH)( s^Vlp6@ QBsZd] ?jp# U]AJa20P#77."D<&Aǎ6y<C ufvbnH8&o6r[$[s~Ϲ̷{EPfF3x3 @^La`0K G@P@P$ \*GBp#^ .4Y|`a4YshL\.ӨX7l) |`תsSeu/l E:|v 7s1ZI.|],BD#dY`vV8Jh/tD&F >m9x?˥\38/ү3l>޿V|:VfS[WP#mތnuD]J>&R.aQjO ݮ*Fy& NM?~ulD7 7GVMHRi2,Nyڧ{Ӈ~ZIJƓq+u`n<eZݶj,U|lN cV-RAdπ)mv+@#81(\~|t#A s !I"Ӣ4NԘ͸fz}sSXB\xqU27Ki ]Ԫ!kz]JuP۰S2 J!T Z@涗#e~aH)I vyrJP(vЦ.W >L~DXB|;ďU"s),ͥd#f6G!g8c}1,a*CHP@;0' 3#<%FSh0޸p@$ZA'6 GXq\+֢C:t36VqЃ7rT{JxPSUzO ARA0\Ӫn  a SQVY&<dil?CZjQo'%ӥ{9 DlJ*3c-P"1/2Xܦ~%J|2ɤ u'ZMRpO)"CtH"{q>=ұ 8? z<S^V"J%kDr꫟Wo@`Wr̷wR)+2#%`Ԛ_MK ($U@цŇ`^M2S #Y6\/ٖqͽi$^.w]ʰ;WWu?*R+?\hLN y|} SdMp,rg X)e7$MBټU8ud l1ڨt,緯)GV.PZqD>4A.wC!t}hdoZ=Hyu@x_0nhUs]jEIUq[ԏB$٨}hOBԐ>tznԯT븾Nl("CNzNF.gE6ǥdUK1uh# ւѝI @ls8mdҢ3ٺoov찊ōNv W6dڵ05R8c& |J]R24Y[i9eQ{nIy츾Ik##gXbtYtxx̅J 6!_lz\7xڂSsT/ JQ|l>_XOeJ%m }{SqtADp(!D:Zgk` @")PcԠkOU ᣬܙj0ʄPȮ63xQIf D%d[5HhN6wχ.xc^ԘaTY1˵ e957npvo DOM5fڌ?\^ҡX+5/F:*X LQQ47WHha jIQLSjʉn߮>,I#3 sa㗇m|9dwad` ϸ@HT4؞f(.p]@kPAeެ]Ik(τώZ";k|Q` t"B sSDvcz6kR[.MS+{J贀DvT!&)&-XNd Gݤz]I}0.r m;OggSV﹦06*&'#"# !()'&%$##(%)"!!"!&,)+!#%$(%(%ތ2p'i)(SZχG*:D]ҰiH~E:Ѭ)'1sY=}phKi|x}^@%Bq ~K`NKR8DS @n]zG D&PWbk# ^Lurh)hUQOR1i]8#RH."Rp?-\`cԌ{bݱ=o) n!(u~/=CP%p2X70ԭ]\Ci7va_]B6 6i ܴaкfj^AK905&?9:Aպ_\<P: ?D^w|/"IIw4<=Lya>QC>@ uRa @ړp5 'Ă %lr)x -|D`f]NpCp@Fϲ}I;o7ەLYzXycyѨ}c˩8Tݘ@|h=A{#iy6)9RG,YN{RsccSӍ jt_2{cRX[,5D8pBΡ ʟn?E8S~v2=ryV^5J8pO:dgE6eɎ~%~(X*󉣳zKΒ˧-:R7Ac" eJ NWHNTSW4قճ[/۱[D> $N[@,QCz E& $۝!)fO},kJ§ӌ }ϕ1|}x/esl)q\F5m't[Xsn[Q-߻iEٺ/$ !d( c #aAKpgv;N~$X =My4_/.z{ɟz9s$+J3<}z.m?dܴ_T%!V1oV!a$5` 0$J ƌ{WC k4~;*I ۱QalaT m߿.z|/su/{[sædL@,rڞbi\|wJbwsaL5(0D6ۣlȩNM27D٠Tm6e2~9Ohrz=?L tM>rurSV/ A&k>j,ոmEӎ1RjMn% rg?_ߝ\ЉetZ99}oMJ+jdYyΗw%Ήs0zNXXmν'{:m":D.C g8~7W̆9f?*yv:wyfMтieC"|'=~ lpԃw9r|_ 8\OWGދvr@7NnF0n/tFƃ 7?Ow!l?kB$eJIqrCJ34 ٪J\ZZ ^x[rMu)j;3ˑLRY!1$ڂĈߕCk8m p]slj'z_(]ßOu۱cE59$'8Z_NnuyMweEuN2i;fc)`wC!1{šo0DvW!`eTG}JB?\Saaz4dT4ؼr:B_X7Ѹ侎Dx[0W&X~O;qϺLck8 \rWu~srd+ik>% ߍ9\߁Wv؛`_ҷLj-ҾzwZLGC`1 YbB ӽdzENlvuVtl6;Nm,jOݜ #Fk/ձ;V/ K1WJ)!dB2r0!cL/kcNYp~u!=fIHא&`I Nf HjA8& t"5l$v XQD89k"v[r -Wwli|o}vTWJ>դxc>lWR{ЙIW/ 7Qǡ ">SP2e)(]VHB ~ T٩l KtS(nT|A&+Jn1]\pf^ކ S?Ց;ɍ3)];DdS7zp 0YsD4юxh}n>LXZҦT](-K8%4͆W5 V i,I4Na<ϸ:6a@p0v9ݞZ#Ƥۊ>DW)} jY,3_~W>yntGo CJ~ceTaLӗ  4 gٛ,<ָom\ct"l l?zS5ۚ~߼L_~2: 5&, `RȞSƗu>in94=\$%^tʉgFD!s (QZgaϙSG4"FSԛ沋B0h)N Y-RDtKQƬ"+H556L1ٗis9a:_?3_}$NgܹXUX xjZa;J4+`Um/C}O3wtX .^,K J/.m>P[GE(Ÿ3D7Mծ@:˥t7qX幠Ts($S/F}3$N;D7ǾÑmUI@{`ED)dQ4 WQ0%1vb{u~𝫛0%s]1&tggGqe8\_-]Uy6D$U$AC3qQgXcO~4:uR7cY+v>"5(E^i qOggS W﹦0~1. !""%(!##!" $($#$ '(%&y~DW)q}]<(%e!lcTֽDYѮ2rqA맜A~j߸JDDUf@L}J`rv PZOYwRNT_1ۗB?Ppdlϭ͢,"cjY0U %?5>wܞzHnZ/I-c"@:/"ѐtz)G&>hFwΝ3.f;qOjY9;rNjƩUc p9.ϗ:~,t:uTd]aq J82iy{' d[v%u}8eGPDm\]O5`q7?*tyH|gǻC,rn-mQG \߆[8Ԏ/"Bq1o?{$̪ Ư_cn:=! @\K[*0d_Ai'ye Ҽ}2n>TWs*}w*`3y,EvMb>4GߌkRۡwO]+!58h"\K^4uS|"su%kvǣdoO|V8Yix{=S \QE . D$i.F"x:aqȑj-VxR\yӌvf-^F^eҎ﷣TlD6?sLtttY:}+dK9H]|y]!g_<Ղ3ppV$ x:`s8KL ͨHxH@+Pc+QVjʥ(Dg0sun2;l[},{/2l0j/=3UƧ <To~vT݁nHf˟zsߔ7'n7ȇ4xk@RsvTŔVoġ2bj@ri%pAby8 cJNmu>u[5e-[E9n) #>GD0+һ-i`[%UEpw?N)5&+P<7#!L׳P=ц.*iwk}Y\ OGӽZp]^ K1`qw5RV9扴xP>Սp4_JJ7\ΒE2333Et6 Sqn28v3 hIc1t΁pa4ʪ^'=\s*kI}ѐ~OA|ݜ3jcsjohP_bc/#۩u*L$HʢIVZ.c!4^@Tt}QbPCu$0UGӌ[E \&  > FMĨ@jGiFEtvqT+D %^ X:Xӱ`C3"DwK|N< u?݋.63^u EԟMvV?)A@Z"@}~LNƁrӒvwThvA7,pD8`3ZO ¥6L<dCj-b)/bGPP S STwݶ>ҒWCn\G:cG(8Uo )&1j;a =5NY@/,TZ㶩9J;|gq#:1]gL'kiG~S 3֙B>.:mjy<`i-$fɅ( "ۭAbA\ǃM0 ;s, 7+6 X{ߎn:X/rNZ$7WcU=b"DŃ8 ;84-8$PEw50k% kFA fL4GHcayp>wO{1}G󆝥gJX睚Bbڲkl ֹˡ]9gƈ$$5ZXY  #$K3 .EHYv\ Q[{GȴWLbzL3Q1 q\Թ^J0GZ]#=$?RƓfޯ~'o\,^){DeČEZ܄J‚IJ~nLq|`Z,wA/<UܯXYU٧(j|vnJԾtze5JBx{`>C9ԹѳClv8}~=H|Dw= 2%ڵw)+2(ɬﳢ|0/P(|T2l.4 H V3sV.\( ajLk&t̀ !%=35>(^ARM0ot%m.֪ XCC޶ [ލݝǦZGbZ@+($U`C<ꦼ+=4cF쵏?/}t'SCmx6N 5^|RlEwLX8OggS@vW﹦0i=c*!  "($$w||ywxu#""!$!)$~|LU\ d 7WTJT*DSJ=#? }s7  [XT N1!EakuOH[M84laPDieSW -@(} >MΑ" QmP` :[\F@|/„}.ws R!)L>ı1ew tɸ{Mvrr/a =h@/P` <ADP" PU(\jp.L%RR< bcerrpxX\8,gi(~c^F?L9J\uI y$ l0pqYc$Dp($ T0`E\L.@<քp{Ln>]|lf >_{,W,- p<>/ő3ʈtFBWvW?'bY)O{}L&0,>-pfZ C!eX\X;2]mްp(hs:>K3)~K9'?1PhHmesP8pUᛋޜ8 K\j*2 X*Ųm92~5F D _azj] ;VAL 0!犞KNQzʌ >56,hb]Ŋ$4?+/\J{ W!UTEa=Elniq޲9ia \]+LDwA_h Dnz:r! Q"DH$R}0r6?bQA* eh=6؂0ֹ~HB3)r$7bhقeV V>Nؓ\ZWv D\?@D𹧏Vwk&NJOvپ0`T%}љD~~0֡3WO ۚ0„ 2l ڐUK:ae7@d_ '6(T= DUk?_u,4Sd .Hѽ+E]iC=>(TW#hEM $ӷV l[2ҳ:-d[Sf޵}hʝQK"k;@(xh$ GEiyWz^D&9E+>@oXH?cm)BCdƢ ]7TW@R  oKAx.z"+FM׃[C=84/e؋][#(*]8;r(ǐy};5>;e_Zg+tWƷvajNAz.鋮~frgSfꇑEBz6+aOggSW﹦055$ ! $('""&%"!%(%#"#!!)%)" !#&޻Sp(~5N >\*E$vS`zOMڳѤ'ߏ<;;8 4څ\Qw$VOhU{i3q*pc"ql+P2í%&<P};.쭘C.8ʴѐCnI\7ka/pSHt7~ĭ+gUQw:4o~"P5cLM SD]ZMcDY*ȹ A9uVZ( vnW;‹Is `K.h&kN?QLk'2[횼~F⧈%4=71^s &|Ϸ r*^b'L`ZP|%;=u k!ޤn,j<&DMX~1FKtzg??;}ߝ8rDYS>hp{ۼYNHc6NVJ[DUeKyePVD K?rհY:ehPFE  :)燉\K=3͹R1e&U78m9,|J~(Q9F 5IsWDg& 9/#OBr\:eϯ)JL.9V_S[ a!!RGkk,b= "<G+NPM-rM%7\@ͷ)XT~CHl~<4mg1p㾗SI;{}z[U#pr ځ9Nq.½]!>70}M`4ob( $͑fI_O)E XC"#C@`Ā WD$Eܬ#Z ^.x>R0#JG^E|%%Vi ?h0w8Wp&uz~  ( 8/' fXcYN9Cۣ݋W+?=Hc{imFgr% JrI#!Ze*K G fp'g' !i f/e V^cy @E\(Y#7+Jq<΀j!@[ruɴ\p7$6+߶{nOl8iPӛ4-TFY6y ME[Zw-sL$S?lsI YSsT u6GW(Zi|4D:Ɯ}s~I`^\_w:Q"١C"8;KЏuG].:Zq*+Y+rޜ_sB3 Ɔ LX(i؍F-N(dgfF< ߷j7]î_7bJ("4&@d GA7xIdi#2 .?e~lv=1) f em &+~77_4̏_4k -5>fE @ 8{P a+.l  V7< PT~,jt]>|G >`_6P3}ZJ1k`+e8QUNF]Y'%!v-,Uif{K~$lR+<%DؤwɑuP<:A ۶ O.L7ԥ@V@>Ym>Ֆ.;DkcU@R&_>/{|( |ժ],~.VLU(t grB~et( gp&DW˦Rvߌ">W9x+<]h `rU9~nQTkDI kن[ ˖.OA$q\6a*y+FQ.tȫoRO*- ;ϋ=۸as}~.Kn(gʆEٜh#~``$[KH5dQb9MKôeB~.\ŭJF=F#AM!k6h>NΌJta\LȎ'˪G˗uAĶ?8TD!X>pGh{A 8PWrx?I $oXfʐ(Ѹ#rPMU.;2&Pa%J*>_Ʊ\LVC5.89QUWi4-AW_U *4 <JzQ($ .;h/-2uY5%DQXe] xǂN_֙"BHc"TLWɟ-i柿š6M/9ֿ$ {?1cc\Yʈ/lw+pqĭN0#TQ"וAUUQūUm5,WVX9i"=cܮ=1U>l_(J8pskCnF^{izQ 01[H7hM(C~:_Y Qd#af?RJ#a۠=r$ʭȽ/F x(}bhS\XAQ,)E\5Q:ʒy1<ݍiAf庍pgeJrL 8HwP~Ŋ$n%@ȓB" w+0u1Q.T% jR̵ /FŹ _ikgM[<61wi2lbR CcA/KJn$U5(|"NH,YBB,T֛֩BFg$(񹌞CRpSΟG] 30}?0`8/  i4K1aN\/`YH?C p).* c 75n0FH,t ^,2$pJdW4S2d~YFEM+15D(5L[`UR}÷~m%fT/X\]*,vaQ:e#LY+#.k%1$rChP.')#PPv2/]av=j಻IaULRMƘbc^D}TjE)k)uo," F"N= ڏc*q0p)<~k@ ܂x Oqؕ.JHکed '6X\^KELb^ڱ0' U DxA*:qS ǸٗMGۨ)X"@5PUυ' q>.͡NIDwAX8<(*Ed.dg 3Sca0"A;ph:+L_*߱>sJ~ Ő/)7xJa^0 e#y5+K2N'I ๰tdԵ: )97+ fDŽIkl$Jt#2(toXph- e%ͬkmbQR<( VAsrPe&T* [+X |Qz@1H]_0ҝQOD,~Ln4c,,hj$SϮ1Rgo)2@V1g̜ge߽O I̽VCa١sU_m1*jb`ǴDDKj~\Ib ;.Pܔ Te`|pTP68"5rqcHzw.4Q B9P+c2;';X98J+~fR jI/#X]ەW?!`B/sRS8̢4A߬Ц/"TϤGJ4 H m6z_=[ii]}Tdy_㐖Q z~e*[4,:>AVt'J4Z@N0TuxjM9{PSkٙڋlㆾFQZl6_םGz¨ `,awM!\KbbuPk B%PZA%*{LOpg^Y:m).+Tz. #B=G=fN؋QhZĎG <ʭ=6ycnIB&Ժ{]UGpoH fLzx@ aјM1ax)s7[1vA{ŭxI̤b1R@Qa/) ʄT .<qi#0H4Vi8 QkC Wuu>LŃ՝Tvxdm"`v" vѰ#&Ósnf~*(>\R/0%ҷ˃X UGe1-YnD(Ȅ')y}3` L7[c(5}Ȝ\l4ޙ`RU/=mP)a0"b@EӭiMKBX=?&M;M+}vSn(ѝ_^vw-Ӄ91`C5ndU(`F]$4dynpK(/(d,. V4HE+Y4U3G={}=Mط'6 = TaJ.BNm˹q^]7?o5f3 v%QҐǟv)QWB#hY.82[[S"1ƗL!{X^| 7:1 co0dJ~ݔf86S` 8kDWr] @1h_*,\!,"5B.>d"!y$uTUQiJS@C6Ԉ$2'?7BvQ24بF}: L@&:8,= cXX ^T#Ѹ0)}@*'P]   ѻ xE1%(3^XXhGA\,ZAh_z`ME7Rÿl¨ wO5l#.J~fj0H*eMAސV~lxtV,P Am ,=AA@ABAE ?P#^/LBtѓD<ѪI`q6*  A1Fsw~\FӋSe;΃h (”0'C@ {!,b!p {N1]X` هEM T2=3XY_2AYĂSL*oEֺ["04v(t, ~= X-|7^QPTY+k9\|yb}>g;+! bjTUbjJ~z l0V_JQ#Cꅘ(LU(71߾&fg$g^FaČ(ALDU̫ O~mMCFOTW(|U![<4ӃЍ5* TY5 0| Br}jehJ %H #D[Ѩ ci?g-uy렺B1!&QI"DUB``cQ{OAd_in%4ǘ+#c:oJCzL1svcv zºVb([ne|vt~JrdwQKuH:J$ī:jZd|HSP1~~SD, qӃ,Y-eMO\C?,}xVAS P;=|fiBuQ^zVg{MPs<%rf8u=mF;=FAN-:(E{!*U jv`Ʌqr R.l.q9HI/Q}E=:8rLmѼݭ֒e;G0 dHD F[0n`JD@P$  AC eЁa4K"wJl\vD >Mڍ'KI@ug6l=)Fã qOi鈤J#8mbI", ∋0# " >e@ Щnا[{N$%F|N8*E&1a4] .cxVFcb Ua9^ Q`fJD:yTIt٢ ccU^XRPaADX d)H *ad'HtǞgO?xs^=!s|gEjL!_P>P*5!Tؑ "D@;"q>#Ct0(> NЃcX&gxnh)S[Ip}=` `2LSHj_#x*5["3 < Йl(*7y]\7qn7јn.AA>PM3];C@@v)CZRI Sx-]m'wf'QJ62F3xPs|ە8>Z$^QnXdIDO:̐jk4 h)hb$v  #"TOD5tb)M:~g[*%$MEO)rkqƃW2?k׈%*LM&JxwXǨqxNs?&LIf^۶4fLcudٸ؛OY}diq]_ PwJP Hx n6Z*ݽvTCZX#+XvL< @b)Bx0̫?:5IlCkK잸#KWwU:H9y{&ruT;uj5M=pÉ' iVcFDOFpdH ݻ+3 (Cx*+_$BTA;lBb1p,Fu],cWGJH4$?.vZʈy|:zs? ~rS9iѾ r1Ɲ7~5 v9o:PN2Q@ XREPJd%Fp98K6= e^D vRRfZA ׍Dixe)Q^c{fKdzm2vgJ!s4n~jI'?r}CϷݹo٩>!>ߌFC@usݡ Q|/kOH)\,j80ROggSY﹦0$0#! &#"#)$&$$! !&&###$$$*%'$u^^3h >7X?(b+)K0ysm=?Y<cr[`q.7U{lic} eAg|Xw/Ԯԑ:rSJJ0)D[>ݒh| ;sMNtL1]^e88133qK1~Y5ȴ!h @MMS$P&LG>-ӌ߄{`QW[2k$7‵& ,tԩc<AE.X\Dދ{Fϓe$I6EN+)>0p鳒 56׻U~Sǿۍ?^qVJVm~B| %3+B)Cׯch?eJ< p aEhB]3ǬF!4!VfP}:gH5:A@z *y-9A3splbY (%OJU$7q݈T^,'Tҝ7]Y%PWVDUA+ڏg ;gddMQUg1TDY7(%iIoO汕=W1!) 45F;{t˱\dJIqׁ=4h0F>|r>|4uq՘;4Tȥx2V0PcuC LKU]=/qƃ? 5\PAU&M`QGaM7(:R@T^̈SHI^>fl*\`N)+ȳɽefL.6? ܢϡ_j]I!v:C R`[A2{nz (ALkYjȿWtx} !f4n@d>Mpa.6 ɜ^i fPZtUO`6Фx4)MhaPP&bV;'g~Q* ?~.l/@Z$6 }mIPO#p=-@nI5oAWNإy7"|J )k^z[CDudWwađrV?9̓etw,s47Jc^~}ۛ^i*I{rGC}aU" $3@ɒzZUXٕ_ցp a4fV"~/}۹ZPl T[kZ~놥CZc'e([sn -DU}Ө1폇˾H!Sf=˕C4QӪvG@*-"dLWNS s,N=h:0,1TSg l*iP&d`NpI%^DU}Y#oC0CV1[c |ITWjԦh.H41ٵǩPk:qk)\Y\ Vn([ 6~G;O f;ʯT]t OMI8Z6eF]5L5fp7kڛrf+(N |g_ :[7y>Ubry>Xz` I{;u#4jC(VNOEDd6~vΘ]&g M[F$Jiz+]J0pvbg F6fa~;N2 YtX~#Du#@*_ 'DejgWz؝Ǜؚ_k[kMB_yEơ'nSj(d}%Q]Kt 8RAv; fe&#!"v/˶d-NbuTFں*(׊ qbѫ.XN6,xsug:Bb- @ڰr= Wd 7Ѐ18d1-p@cF(FG\ >9_:@WKMlc9aKs<'dMl?Lu4\bXҎ){Nc 5zQ?Dctq" A08=+-6H-k?p {jt@ R!TeX)]0͋T|kmS}.OCuơ+8{l. :Q<3"҃ Qx.<FYdKq \YQVk..Vat%2qgKC) >?Je]n~nӐ@TRII0M+Iw֘h鳣pEw(>,} M}J lh:Y2\]@  h.D DVdhZhTD!07*!OggS@sY﹦0.Pu- ## %'%" !!#(%! !"!&#&DY\銋i: {!, ($,#OՕfKnk1UJH4U).~4 "mRτavBTWJ||mMޚ_) P blD{D7*?R81@ n(9J]UD #p\+Rsx,$St W}\d>xk>.vU) ŨG8[GT9&vY?o丆 8g}=:oA.omp2 >>J몐(}U3"M b]1PEUՈ_ g$tB)+r|!:= / j!zs%dJ!kk 蕆 ];f8+E=J@*B$8=1:ca94YE >c RA,g^ZL v͵(e 'EEP9!%r!xq'DCR+"[$݃HF.@7@@]C(2"HR ߎ66`DEBS@] sN`r2 LEBkRBK[rHٟHYmc"'1ǻ[7q2kRK׼4͘ۑ9S}4ڡՄ_z)`ٽ5@2p  k-"0`9`]-4F <2YX94 ! dY^[x35}hWN)SoK՛bT?8z'KqCI$]LQ h Og^l3esUU[ALW) 67y4WJ3.ӓhD;mq]?фTYtC0t>dʴ4=pS]l.źDWCV[{*7^<ƗƩY~N9 wck g8qq~#ٮ9ŎJ?=TBXF r棫OcG#JdU]paFR =i_lm:*Ve.&+-)km-6ȏ@hգ|Mj*c⿰Fh h ~ C`fIAr,ĭVwʽMmv~%Ut0vsl-u[ECPhWR@@bIahg2$$?2D_s\+:0=cLR޵*(gO7}1xdRP|r~gC%^Ԑ&_-DbU:m6ޜcED_45C "ב㳕]f]C_T}t>ĸ{cT>^nm~DOhG"ĂۥkVhh[gŔgl\Cz|r} k}}3tЪͼ5=Ӧ xjK(Gqz&n$DR4k"/iѩ8 |.^iϱُX"v\Bde,gP3ݍgMPv3qd]V)LMf&pqU%䙫vu;}4:к̭!TdcJx#$ c$ٜ# ℛ,yɗVymf,2n(ΩJ.k$}pO^CUbꐔnk76C|=cbr hؾkɈώ>ĘF快t.0j$]-WP*ujG7J!J lދ &c1\$Ӿ4MܬILYNXttjWDכA{qv' iuv3ntSpV ~hדy֘qq'dƶ]&z68])R҈r˕ zQ7(~CbOGH@K]W;G/ks=x?D?iaz}e F-,a٥w$K~N {tdH&ZL(PQCPӳVf\xZ__oeVWHQqSN;Y/7Xl5k 8ҙ +6zx_!4@g.0/Vfo1k慺l{vL2RG\ j,K۩.?.J1P@] k m ;Է;؈XadmnFQ@Toޮ#H{N^ n~-aE!#%X 'r$mԡQ|eOݛx4{Jmox4dkQXA|]ǘZw/Cexs7szsm;lyYtog^K,R2D%2 Bӊqa5OggS@Y﹦0+#!! #+%&tz|$"$"$'$'{^n:̤CcFKԁ3iD91a>;OјA[x?_E IuHJ"-*sѶgِ0qQAp՜0f6L[f2э%;[(;+_LN1 MvÌ Ҋ+N*&LĤoɖ0b8Fġ->sNƐPH|p҄oSxԀj8МQ9v8HP4qC5ks -wѦHJĺ@BLuT)K&{ǎjP (bO 3K0Fwh$Pq @á_]֦i dJR~|*LAm(M߃FXa QqY\BLKwŋ2oVK.A&^va6w,)c|,5p¦r9Uw.XP[TǾQ8ZɭVE+Pg-C8aHMJ3+dRB={`R,G-8to7 .Uk3$5ε0%" |+ڗjJQ9. Kd> moJЩ|>p,,.^tr_5y /zL+u_ G,*U(ӹ=$6M-u{*IͅmGS\x"4-6ӳxzk(uR 1)Mf-f*vTϒ3t; _^xrqL o-cG; 3WWͮǺ|ꋕX'ֱ8C)CQks25W'vMDfVÐC9?cz!fV۩a8Xy$wPm]kU~( Mt}XI TYBWYlOch=\J{:K?LY(tDgnG'* W,\5 7Cz\[iK@+k2Gxp7woZ^5UdaY Oąԙy7el̦/Plei7{ѐI5GްҗUuڛAG`0 MX |XT]wF\3|ċHi12Ajz":Jiujen^O^_kp*g ;ڗJn܁ %#A JbG nX9.6Zp|c: GbHRnP~AAQP*>AP4Ft~<1 索+UĴ`Sv҉-S;ޔ5^L~+cm8g(R AѺd%c@G5 R'S*.DV@y^ދ2rU BsE *( &ZweӧHMW83DWP  @$dPQ 7r">L.USGɗMNd xŒidc>u=R/~v=S|f> ^ MHIB=@= ȪrȠ=DDDL&Q:Ǥ6FՃ4iZ0[O=Cǽ4܌q4:|a_C%#F#VAdmDYD @ VdaEd}pj,>,a՘&]7z֙JZMuU^D91  ԝ' 1NXdISMDe"ކ2yP @2UIjJ 7%tS(1˶R'U? l}S4O+n}Daȟ !)Dvzq`I-1uItar)C"Rv8Q^VZ:z4[UpP_#c!{9 ^1~dXɥ`(n A$.T~\]|J PpZ*SM$2rΎe$|TGц=[lO#kN#@fE_zY~kĨƠm F;RA t@&j p xMGiEԨיLFXY^/& AԇqLScUq n҆݊&qo>FI|ATO*t?6sofsIDդYG+t=T(^f';bT)<0 0F{K)t{(, \o?txk&S7Q=FD$)l?|M ؚ5hM(!lss~W2d]H~E ҦkG8F27lc"bQ EI.4c!q]ϞX[f>D ~89&@cqE!8K'8GBJ G#l۱\OJjvkY~0o &HjAcGL&\u8E-i|M{5v3au ld ެ.R^"J3w*:ϐDŽh7_NvԲwbmkӳ1u1(Ơ `R D @TLBKϠq"PaBq*!\xVm'+t.V,:1!r18oD:ݟM3.V բN0{\*_|J/h1!n,0A5 Y<&TlBh\+wO7sUsaRp8R-kgu m"ݘ%d/rbqC"8PU\xF;Xp!!T  ~#8[&tG-N=S(a]+acd@lxgKӟ{qq哝GoѰH*8"\1~\vw# AGK[Ǜ,FDr *evB@ ^Ter8vv 9ЦyDȫa.GcG ]i *"x;9 -6P7"8]]$  簯lІU\`X(v ,Ё]xd~_,`R W?U" `}ڇ5cXKy^@ƍ@*@(rJUB@$*d[hjVR߸,XAѥP] Ԁڗ2d_WX LF3yyX]I6#@vui>=~~:2S7W HwM0PˇD^aK@Vm$`'э*K%ZDy}WHÐZ`DWyGOaŝ{+ g{'Gupcvp߽QQ4 5c3+\{| %h ?(V67n.BtAD$PInOggS@=Z﹦0fo5"!! "$%#!$"# "*'| !!!!!&$%" !"!&%LS є6*1Iɮe?:Llk|ׇ+R"[|0g\ ɭJ#͚VQ)F~nC@Rֶf"qo8+ە»^دdtr%[oRy15PG)*4[ kH_RnQז.6UxK4 .VqI'z^L]M%˞c! TЌ^H` *}tkɆ@ G-XP]r]wQ$Rtm(1f3h#vI#m#9ǥop\_cT\P" ^P{Ò X  g$3iׅzse<^$&Hf[m*ݸ'BO-:3qqi\+EQ3iÇ"uǧ8֍YJߟiL6dU橱d\Lj0^p,aэn h)J֐uN۱ddsn[w)V>߬) X|}}S%!IձqXקȝ*Tqyf 3 u]%"KMp~ zɞV!t ŻMVV_u'/6 Gd?~~l&08c  x-ȸjVw<m~L@L=СmՇvB;|r=jZ6=I n1{,nп^`dtRE'h!c:gO/pJU'@-+OGOފ -跋O)\QRB@h׈!jIݠ }@:gy*@X:VP8-%tD4ƽii#`)}g4=H10#b]W"&W"{وU^^F˥{J~XN?_Hz[IW$w 0٠Zѯib4\i) AXo(zquN!g5hj6{E訂-4sz.,ttIaϥ;B3Jpd1kP0H)ԵP `p .7TK+!|i&}iM8VܭsxcaRӋ$SbY?qۋJ^>-NoV YTa( * V@qA$3.|.c# myfSpCGjTd\K6c1Fz>vם%slP3xHvѱp.`_hMx<1tS}+!$(3Huݓ%ed Xh\>  K! \aAXk0\?sp|[(-DW Bx4gȻ4̾륪$U*&*=<_ꋫ{a\Q"LUéhLʋӃMOvҠx_?uTC \WՕmnx[>q-W_L]}G~iOqk AĘ{N }N!7-b2 &'[>yN%L4]_O FD_=X!q` `(V .< k= 0"2'AB!U)g`E dE^bl )* v6-70\4UxJi^v9=ߨPqt %Y 8,A;b=9w'C R: }` pt !nV+Aʂ7\kZ0ȌeZzs%QK`rJ_vG`UO^!)LE XbH5N (  P{LD  E`Y`KEd_peZ'k_j/Ǜ# dYU6<>{x}?C!b8TWܠ se=,U 䎛*ð"DUëihY<_;^9?xC s \W܏+hnW\S%n^ 1d]jAh&?gxp{_ɝ뼈a1dkP\]aؕ ʏI@2{ToE*6!M Kn:Yl_ ëS1{l[TttN/]KsPtcknL$YJCg7{F&anoaOX& 9{;tʨR4:OSg}ϕWo=w)6, ƦVG)ucUe#|jҸbT 0a0!t\E*ESS}}:b%LY7 2B hauZTM_ .uFDG:soYZm<rԶ '{/p `@U!I FD1 \BX0DC,/$=H;>A bc$p"8 %NC ^7'JqlMk~FѝoFѻ2ftBBH^#J0 Fhc>(8Zp5 +ryԈ$h"%A O ϮJN!7J諷~|n%1QHpU7 \.xQ+¾)s!8C&Jԕ\5 *nt5O5݉bET) |"cAT[B-WL< fp5n2.X+J#&LW+irXqV}f(UWd[œ-_w Av}kR(qeDWUavN~w5o#N%)ɍBTY<Y*T];翚[xYT TU :] ~kO_f<=mj.Q\K\Y ~~c#g.k:Iq2la,o'h/G݌y{8Վ|e@UF);fn̎Y,LƔwZvPM Z?JYkGTFF"p*Yi9ibrk KYE,6e0- !uLyl<  AeE}HYq, ",,X҂DB-^*|@hPzI&'L hkǪc83±iס2Fc)!3VyA6D( 7 0m0pBi  kDW&@cS␨$P\UꊃwCe<BUYELU|D2@ QmmcmXiSBdCycI?v"k;v%͉Sm !"Qu #^ FVb-g(gia{;FWhma8پ |B "F,\Fz "U ܻ߻qݛ¾ǝ^W8t)a:PZnt7ց 3y IC T5$~DE|>$f< `|,*% Wb@vsMGM=n|%Áo..֛])谋JYjℌ03d\hr,_IêNsJjs|6b~ IFvt*p;Q{1O,QBe|[^;nFzu_<Z咀|LW!gbEQ`|1N 7꼦Rz'i4UƁMjIeN>S3ǨycCZqup8U՞=ZHYza'5k 嶻Ǐ[*gc:Oc5{K\/ƒt}Ax( +oBzvH֤9ttmj6͟ 47cǔWP!n(ՐWpݒR䮍k.dSOxwO?R$m?5#7g(j[(FAXQ3j=@3D#^ к3V.O-LoͼΌiŽcE|6֨|2@$YaˎcM< lq!2Lk|q}qځ:̬^{Yicf]~tm+JKjiVU7R46Ń՝Ad7J?P· -?fY*'efJhx7k ~d{?~fBM4$*? '#N#cqbxkk Jj7%5So4ӵג%P.nEOZ?OggS [﹦0h&'$&>LLF'!KXeL.\/S7uR񔫋Tfq,/|v R7~G,2'kmu~k>]ӽ,+"yyi̇ 1DtތyQH6x:_ܚAnz3c,L1\QXXQc2xRԴ@T;NDL_ ?Xelſ "zOug!dhR]R6*(YB Al0ºgӼH‘RHeKm^') 4ٶ ?gۛb3fV!^ACe~|tJ< EU|XPI^@n9G 3I‹yI_і4ss?9cKt~|s52OS)X| f#v,5mN'#Pc,~֘4K>Mo >NNjnK̯8b߈< *t L=zT%G`g Ft0Ny蹀GLm)]JE`uÞL fe3dy;_;:v*L0(P YM5B8X) cw^6* j zv0Bq?E/ ^[&J( }e xA0~eu+MikNFZ} E?*~v_V`cn ^ !l$0)_|X |֘5s}t&5qDt+_HLf7'_K-/\@bvL=qm@GF`Ј櫩پIH.Sֽr8~\UCWhڳͬ6@Q1F6&X;r1Vrgn/IvFi" R>>YB S@k U~;fBBr#@ҘC@G@G8ӧ0ب낥Td÷Tѹ#ߪ^ @Yn\t\5 X](G @bOr/|Gs L%;^?x@6RB.+6Tnvڧ8f ,xH#c 6GXIU>pC7t/lhd|֛ek2 -#`ROժ1U`N:xZ%ղRh[֝zTQh%JXV&0F;(e(@dR.Q-ycjx8zHWFR.Tc|J3S2OҼg #E35Y$1NjP°V 6$M؂qpxrnZ+iPȃN **,v|Cƣ|@/m'[]5J20+ʧ%='k+S+D, Ee4byV5 ? Y% z- tIA ;$|6lȾpCb A%q\ p#|ֲBIA{6,' TZSie BI()5d:}=`Ftc%fGvn鼧{|(P4Zx93B -z J pd6 _" V)$OX%Q pYT5r[6:A"LNWALNԣț4fZTxY 3Y)&{:6KH8) ˺}eԽTQ~~&P7XO)-"J t$QCeq#"~NA*q"~|N4,ޤ9&: M1;jaڄEцDh7],-& *@{qeHMeD\ 3S *Ԭ.!`ޜ^LӳK?7PwjhfX#R LGQtjt) NHE04^`{Lr; fK 3P55.XLDԀ!+>܉ʠE5\.BuMF|ț0hh %C"TLۜ?tYI3!b)#ۿ5QٜHi YQʓuTB.ҘJ,%E\Bp~%|HDIGX.B$>|N*l 7LeeO`"LCdX&}E|j0WO4bakĢ|3拧.fC̟^DĪh!Pɿ_(U3hm;rQmH ʒ-$3p8n T\\N}ĭE:=-KC#\?Q^wf9qHd<ˋ]]h d^(Q(ͤ8ʆGY(qCSt"9%a($ VVOggS@t[﹦0}0 !" &$!!$!!$)&# #!""&%$>msAbq3@>@υC2 yb6Nk$9ԗsNlyn4Q"VXI`LD 1*\-jagPȑB,,X"ebgt !,X|xԵH1Sq9RLDV!{像 =~ ʸ@ht* (mV,@jq TcH\V|w^ՊB F$.D0ֲm-T&+z:A cw.iJ :ŏ#7ql1"&ÌElL˦a;@*2Hw-@A&7sX "-^LU[jg5_PF{Vr G.h (@`S xt׶ A;P|`."vxTaը@77b@ˬ 2`߇'Mv*H ʅ?P55zOB {! $я9Uʜ'-+N+ +a`☽.D\)r+UAjx~e1}bEG$t64R)␬^r4ޘr:@܃\.\r·0%PPT2*++'/KπN3PY jnLWKջ;@v'1~+Ml Y.xT=9-(41hpߍjfr{,ٽ|4an#4QRdGP'rh5ZS5y~7؞&*sI˒ՒGoAwX︬ΓOxLq""Q,*hk)ؼljo' %O -L_qnu^_Y wʄ ,.i*^+\eX 6ҊR)ŵIa`-T g`%1hqc!;]^nd< `NvUHS;:6>xc9NJȬ eW " _zv.VVzۧ{ziɥ #D !a vW^}}T@ Cb/iNF"JNh7n~XOU[{=n;hG +c.fFa @os`a Y[{HlRu ~}V(FVe |+C8"uI(E/ՕОbM+k""Bmspj+ǧ< ĸiƛy*{-%@W "`- ZT@e ˥} u.!F"AԬTWt ς` dY=T^yϥXG %߉?Z-+ m]{"wQj DSWU"GWV-~^6W T ,QKbѴ3@sߏ=/Z6gȧxߩ]TDtm!9,I#r weK~B\ u δǓO~̯~Hnd5RWISLdW&*V{Ú]IR&ͩC'd]uko>]; YWET܄1b&L2QBMU_ihƴQf\qOGk8>T< ~”ts/WZuT&v 1ujD/Nz)v) Y)Y w __MφZ$pW Lޅr.5#m7 \.݉r)#:L1zd!d'"$bL gt^&?jAR!2L4H}ొX%4n9RaU1Cޜ.~)FzZ(#nz{}@:Hy&0"A RP&KI|(d%}Wi,hhZb݆,THΠ9b//(s#\[.!T]@.Ӹ8 ' w#(cqzݹjOp4IgN|`_'g4vQT/)+nG*6 _Tux/mg: / MhDDY)+Hs!`}\ wEqsd,+j ˫f;{X録G $Q㯬!_RnMvp$PV,O{U \}RN췫5F3ZQ TWa\u՜O8 O;t-S">p%DYAhkٽxP$r_+) I!D۝ռaXqh_`6*fYfB8!L[k О<_mw?Ļ/}\)8vr9o޸T_-:vKc;ϡq [{n+.ѨvzeaP!r ^íqu&('SͅVAYWHC| p  JB\;n&NKn"* *?Y$(~\ Sٿ}-t_O,bD .ԚJtkM29@U nBɶ!|ݗ> SSI2N 0pkr =]G@TnEfD(\$^-!l$8!:Zq5ZJ VE) ?QJ'`%6*p+y7=qWߐHp >۹`0d Ҳ+cMLW8bD>j>ȧo9**krh RVÑND#p*bjS/⋏]쬘FWrɦ?զ)VPpg8}U)ac(D*ޒg A:Fʹb@ ~6J>`Ёq7?p! ոH1 F"jY4z.c 1OggS[﹦0~{G"""!!)&&'"" #)&%&)!*&)%)&#!#'$)!!"!!!))w#"#$''$'"#"% &'%DDj~~}'SO?Jnj Tն?\s_k'D\Ƶjg9zd9!RT=:NOLՠcm^6@Mœ]5#51L>櫺qϼd{͜DvQHεթ Ӵ2rΒB^N:2S{SK>U\Y9j>'ƶN7-it1dMUd_KP=>W]:ܰ9d#?D_ C/m 9kOM}Tv}ۘx- 4eLFaL<wu{\5ˈ.{ITY,V(^פ hrbZ&DYtl(`0qR:m+}!d_Ry[,XWZ'"CIR*\]B_FTI[ TvGj|a[X 5߰wKHjDa܋{aOtc9ƋvpC Y\8 NvDSCYW JMEFHȱ_~~R|].  {utMkoogNy5Ldcɤ V$ذyKrT}hvoqJT_|ӹq4xRN}~1l[?@Eub\Ij$l{kLNd6r!Z /k:TОl>lLۖ].98b#4EK*dm <$ 'vO|演нOl.\s6=op=Z6ܳAks ͛Xlas9w9~^۹\YEUj}#x0jkIkڜwnD<6$|ҧT-zZd>qqk6LD6$AҼ$4rxC>~/:d6lHcZ_>%0@-keT>l/:@//S$7%D \{yxf"nb D$[k-xYc32Szug?fsYx[&ɕ#r_D065}gu{|uX?%WjLd? "S~>:G"D(uXasχ9pT}U>5*l=cwv(XiislW a!q͑4FmiekQS}/7+ȟX#ˑVS@Y$1"u0JK3XzcQR|$DП_O#e56[p,ŕ`(;wDdw֏ ݦ,7C_b mo ΐC k$ q{ݺ4#,(dY5T>d'|I8|$B"$"V%NW%\俟:yhzF0DR}Ysa۠eiJq Ӣ(f,0}rt ! d07䭙g6=:$+{KٷV?l~Ӧͪ E+D? ZǐX.>a-\b~#!!{F2 '>5Av+y*+|C]} <`y/j{JG p56vT8Gͩrt35ᘅ.ւ`c]i=j[n \!3 _ f,t'p7~I8+Qh ."clbZ[uz&0EXh4Z"J ۭPYox*/9a]Ϧӡ\5)PGua +p-t@fpt/ . q-cTW=T?Dd]`ͳʏT2zYTW}SU\~j}i/922pbXd[ 6G;W[|*Dx F2DUT?|i]$ypUdIJ_I1TWxyz#8w2!#\WXUm 9sDJ6d,\YH|tBhW{ sn֣~7]#vDa &AS];9pa<$Id/e{ fO޶~TD%2[Ene)~9ut-Mg7%詡3iH"1eL/7Zy6>g'/1vM%|@l/t/;^_oL|wNY~/o_cDav쓲H}Njl kr^S# TdzOIQ χlMU-OIn,V1|4 c16"aR,pRgJK`LԢ$K3fϾND)?ӐFl.O*n %y:z[e[zec%=LUIH( 0l^崌2w 2)޵)HSajB? r8aOE$t  ;Tj)Dpu4WQ!2LgpA9MNm2tz H'#@%VT$ݠ#cqkq+Cyui'`0LqEL>{/1OIv\w^?O#W-^%c3X'T2'%\m&SSӓ{s/w*^,WVRrswR[ÂwOzSoo+oÕdaE♷gW@~26:%׫)^?~䯎Edu?.-ʞO:]];סsXO:i~0 <*xϝWI6&_|)KR֠IiձbMMnGCOMnXEa T!YZ\ʪfArLZBZ><t@zRJp*JF/;NiLƒ v[zE6<\ s IH?n%~)(îvQ`h Vn* {_F셳hYo<n/.tcbO%{0U+Xp|Hӝ r3^(+UD^tZ "?tJPW!Kjpxkzq̰za:WgT͇\ "\),)Eɕ)?$#u})0Mf́`14g6OSSpg!V|֬>_o$ilX(owpltЏo: ޹FkYֻ8U#܅4z3;pk. \.}âu\ 4YZr+"##Farmw[Wr^Y(vMi1ˆ 7PbpA)ሽzS#o/lMW+NXV7~k[?=Ć!!L խw+ R-|NυiThR*D [ؑ.'d=݅~quw5VrƧɌC0k (|Ss̐$l;@o?G9jɴZ>|/4߅M4d;RX ½R>## ެ  >Kq(>"" G?Wiqa5POM7 ij gP1x 2Uo2ji$9cFetx3~++c?#=eHè)SC-s1H.n^~]Zi*CTE-`ͷ|QӬ<*ȟ [sae#UCѯ/`-$G/q)vao)Q F|_{9F2MSmݕxN/:e#QdJۆ![X6pMEX2o½E,}b@5 upiJ4) \^5[ǾL0\0I{䬰mň1DeWZ,WqHrzhH4]3^3 J`,R$5`ыd]Uj)_ޚ7°su<a?{?+RL}oRj i\A/̕WM8? NP*ܯ+4 *(nId{({ٗzo9E[u1E]/:Of^xbX1 zuxXre~<(_^689 I6_SF=vrE%׮_oI# X> e&YֆGvo8íNW75MVP-oW``aM:- n(QN c^va \1tfU408|D :ϰ ӽ\3*;UgݗLAv{Pc*6Nrʨ4i:pV::7oxfyw௱{-}߯lQ;֊aŬ4)b*4ދcr^ !Dx~!oAg?؅;OR7BȊ[C|Om$$ݞ}ϑֆbFojhHM9V(ݚFO>?fqwn5﯑͌1qTok=?q6-fZi= EGtL^;`dǗՒnEβR\ɟ>A-rꌁT[} scF{FA9D1]4adѝ9^fv)^AFfy AY`o`;[aͦni H*F=%VkQ@aviB(n?.XIOv1$"їN߫~ظ:IcV֡ը6w]Gnsй+nϻϾƛ^f&X"hNeq%}Sv̉8FѶ(7T \uK5eUw5w.W0pXB,XꣁN%Q1WP^o~?ܨ"H :"χ>g{T㋽BDY}&%qrXτ9Zgm+KjLk=&2(nZ)tY%ɪlg<ܱYd4>(PZtck糩5O&70dK 8811$q^oߔ&/o@Yo={9'_|c=^5UGkGHr{ uJd[[.&AGA;_[f!vʢ!4+sXV\iɛ=Yt'[YޖcV?+ :>*\/mGp4M:5]`'KydA9SD=Fk~n6| V*w156- LJ|Z A |@܁WW,hRzji ߬w+{0&h#y?7A8G}Dk v&548ƹ|ͧXCq-#2 do! bȰ#;.t ὂNtM=Pt}|hd2?iº/Z?z"9Ą4۪w2ή ﻫ6(ȇ='WiR'j@Ach.TV|}:uC EezeCENlYNl^OZ wTly ^@m4S×)TW~~ֱۙKw{O OplchVO͑R&k"M\"u=u|!v>(ql|$'2hXc*32LLO4QOiMv,|8]&Av\C'tNszKNL@!ܠ01~7NE7< P,w d nΑUlr֦/7h l봒!G,4R19׻݇R*5OnUaprP5k7@$R0hLh(#DXD>\,x(g*+tGa=X^,J6G)bӉ2CrTovȎΧ+8DzG~HP,* IB%PBOggS@\﹦0^"yw{t"!#! "#%&ã[0";oqa\hU႒?jv#XM\irq)%bhU zT)t[AcP9().J_-V\\@ʄʠrA1`!><^aS;wԚ>XS^89/("E@_HǏ32n0j{J7܌j6aZ|:DґyF-].?# $(P|b &~, s aA9-YAy۶ĕS|Te|fڒbUŎV4o'+Ll$D'?.,nS-@ǩ "X! 60H`@Ųc!bp̮B?CԼft5 -ؤ$*HXd@5oW)o\,C 6ʊc! PZ*aNX *;Fp)@F! $ I!@e@"\D~|Ƿ T֎1:QxsAQ\0+#x~rRIʎZqogOfxqQT*tɖr@vDt7 BAk^<b( Q|^ē.lga ܞ!t_M ֙H[VrPcTqLƸCZ1$2nX*}/0A4]}\u,uCF"Kbٽ 9~|q ּtK4Na+;r{psz8s>^w~(C5"`K 248C86 NdBod" Up#%H Ž>T(D^LnW+ e Prc5K`7JdہTxesQQ-'2d/.[EKE1DJ?HiW} &@ 40vԙ5zVt Qh {0XJ+^,A;Qa>öX,¾tU-mcoټՖ{.(DC= nIfRAH\ B8]~zS7pE7+7Ir SjDon{.ik˂6lmR4W1v>*=8.# @S5焒neKto߉p(+U ha@27 ;k qO;40_v$-砡6sT o: T+%pg fdHqt6HszN_+Y33hA|,P457< ^9>^5 5<%}WT =C͓x%_Tv.| UԆ0#ID0|a Kd%DAO!` < UU'5_wocj`HEDaҧ `4[ @9Շ~7Y"b::FTFeY3q~r?Jyֵ!eZDWajOr8_tW0i1]ӿ%4UO9мxx7zp^"LY| _~KNߍܼ2]gsLU8jU0_bA]KSz 9f*E$\WFd?B?juod`YH\YJIM#"ƒqS847}mبmx.\]:WH]$؃K/shFUDZ6Fk[ҩnF"`h%ݲ@xVG5{!ҩk'U{I$rf1W]WfvCm$a&>B)/@ԍISsOF?fMeXU:slK.Ìk'lhqn?l!(>n#c9W,|r8M^nE7`i~/aQ0<,"i\,cr10߆m msH+Rz7_Oe?3㮴v9Ɉg݆ߵ]]xVD򃰔=גչP&**u9R;5A&|fs:*.8zSwch?ULqjT uimΦĒ^̸_SG?<J7Bج+n=)ZWveƋfc1nnII1}u3aG4ƴ]4n\N#C (-gt@`IJ?N9ek»|5GBoIMn .GN3JIe8{1v'h6/ݔ#HX^wM?RYȖEnRtRRAVvvC)dZ~eN\ tJsȵkavL>â&;{xN6K*GjM  V) rέJ1bkeI1ߥzGl|͍ oڙ<-BHk޵[6CWKAMojġE=|z6HZE (ѳף#{Z䜆,2&%Eb jGQ>Tm8һ:x\{]z:Nim#o嵎.KY'_8C:UpCʑ V= 4պ .YӆI0k*Xq}<JՋz‚}ww=woiZ3DYc" \ԍ=E9 琑*rBb91$~g״=[F_PmE\)mr{LzIw0|DY<`ܵkGEsP?e> ^uB@7ZSVp=D\+ XR?{CzBsX3xz~3o>+p)±>ٰ`5QJ5d#^c!URӧՏY\>Q-ֽa'\("zF`p#zcDNo ҺDxXc2]\١#i,bJTeJ7_q߶~զ *ltH[)ra M-/g{Ax=lxrϚﶦmW1[ IOQICwj-co1+1t"Lm㰖L'n;z3dګc Rmv@9z8"{p2HgA .S,ƻIh Dp eЇ@9ؓ.A?wBu[P1z$*Feө, qCC€c,ڨ\u4! 84Ɔ?T#D (`A4鋁p5R* K}^$`PeYArAqAY%*}#sqlqh #]T PP<(טe e%]*D V\{>QQ&%H?B LgbM_Z++ N?%6M#˙˝zM~6H7 6b-`XEAܖ)E"`G%PbXy\Z,TU@+揭/rmڔo{ Z TWm 6guxspMOꈟZ믗@}\W@pϧlyXb ]gӆ5¼$pd'_Lb/EM2"4WVÃ8^BՎLl0jM\S\ʈ</ 3{>ÒEǰR5TWabu$T/B B*F35b8d[ 7wc `, rM&:gT[BSvvf\җݼ ?kt0ӽc=w+ Zg&P#G:_t`}µ)8ɕjˠ{4GR9']4>nnAt^ۇ&q}2M*0@ ;Uv~6d[zPLFq-qE8@ ^-B(E }\ ѾJpY(_-sqg0tDPrO!"ֳ,P4LEnx:8r~#eGHuhW~8# cR ;FB psɑ<7e8Lrr$T Z鑌_'e ɷ/BMP@qrX ((| w1BÊd@xADWu`EpAu.EicRPGn+̓ko?Ӎ&K sE4M1LUЩ HMաQ[N{oZ\ˍ%\UTh5}t48ǦaIY/)ä \_ חȘ6Ѳ c@7$SŦFkofeE1vD'"jZyq #5?{(EUʿbli}])41v=<76|xٺvMxi6s@ SsbB;1veߎ5Ws Vu|)8>r[PX70,X=7p^F.%I?F@"7SO8XXK.\CV+(KHM͡٧׊ &"/ 9S>LF.KF4`QB@#n~IU`'M4Ps2jID+D$ #(` >JGc(._'i%}-гDl *R!4SD/ٰysf&bA0R36Mm CHX8DDz2F%Pn@`*xIK>m',*D`Y\v1a>cs'ot 4͂YF.#rzm?_p{ny hL`h<4 -%@N^'hE7XdɑeC6 %`q9xn .!fbg"li570aCV i0:5e]գSDDk?B7coY&{44A@QMЅP5C9ŀCGq+l/ P"D`Ч2apTrp#~N5F?X }.( {Ce 4tǪQ2H|"lƽ١yKEGDk" %ɪqPm\@ h$za&hq@ Q肶V *\.%F}YB!XV/)u%9ZjBL?̤GS_$tћ^~|76 #A† NU:@ JT𔨸 4f`r5V\) "% $6% XB7~Pb&O ^U[EˤdR8$D(STbclqcBl;=m:hTI 7 I'@| ? vz$$Zhe0"[N&T fk}q$| G!7|y6KK(WLO1J1֣=}s wBN dA n. AJA5G&npI- O>ʥbEXyT] -N~:\M4ȁ޴Rl]F^ 8ú]{DJ̎R\MCT[6t#}E.bw,7YWdLUS3qfӵV({aF4\LY) nO-Pc$[{ \U'MY\ u:bݱU0D[=@VP˅[BrIԤUU.|_74y9僿PO&]:'\atCVGMi֮aD]7#/tk1o x~P^+&Ǐlsnád:=hy{~@KqNl6i/\*%PyYdSVnV%hTWIr3ёQ90=mőWV$`FJᆛ;3^L@0WKeK0h.¡Տ(GüF)jpl⭍͛K2ӑ-C/o4߯c*hUh%pаa7Y(Ss~󿡊FlR"VBeY\w#lۤc~ŰT^PHr륢@N{(x VuO?~ǵt>U{eGF cNGݲ<]Es<641d t" ] P( ˼W>XӢ9+ϫ@( +*k`pTbKT OggSK]﹦0+yn% " !! ($!#%!##+)UPQw+Ӌ`Xsɘ+V]âE(SwJu,a.m󵊈,V'`re")}"BL06`EI`qBEB$ mq`)JR\TYAT3E)`w uvXnBIT1Hn\[6PuЮ3n{ߥZ$$ZTYUTI6ߺbmy0,j$ҕKd[Uz0grDGn2+LY79:Y3 wSux8龮a)d]*nh>A0V zGWKT[ +ˆ4oXW8Z2qIJ7olybtc@6x8W&!X3IUtokofk!f.աC [T1 p|Dn%W?IH$'Ru\ Isű1kHb\'4ȬHV1ATnӇR0=:Ϸ/@}} ~:]`s}srߟڣW1ROZhD8 杽,KpLx?:84q2K7^c^ pχ1K(b%Fr:f7,}3HŋJHɷ 5CmJO}Mr7EqW#UYźQLq mf*` |>\D07A݌eZ›$\p(+ gH#eʶuYn\o6)tƃX(CiHّ4JǛɍ0A@ [Y%/ɼcԋD!*R寊%+y2׍[vq>ٕ=!mN{˵LtA'>Q'k2jnVlఊxOkv|9<]||mxʅ ]MPnZ<FK m( &@ԃ4% 4~*nd[[KrK{{/ih쓜w#E D[jQ_-ЋqmIj+a7ԺHdW/ܼ>|ZzIz:54oTY4+6/z?҃/"QD33N4W?X;^;{/u[ٹLYimܼ~e`:]خB!:բ6L[ک͕lu D}QWz){7ND_LFO[ ʊ!h9hG˺w{bI221n-_<{N-㓮YͻKu#LqU5:K=zUuLhX֮n,\)PSZ>kB}⒧̇v5yN8fDT({K)cQÝv$IDdžxN_sϛ~wה?"j4B|b[W!`vlxs^D|PN%)QZ hvN,:Ȣ9TB=}X?Uyq<69i ?i`"C{D;O=gbuVw$zkW^'fbcr^f90\n#C9w&UKΒY7>įk@p.JZRe'ͧlLȘ}m 9Ýci ]ݻfXr@/8UpRn'¾նnH) bP:2ݯ754J[ 7X^PٸT5]6XcY"Ec; kV7ACC ~BixG al]X0hRNXtb%!ټc 3X\b2Hilz.FAq٘>tr0~ѶA>?Oy}GGacWţلgKwF_je1!b)c&%:d̟/[)櫆*ڭO]%Rߥ󺑕Q/^o-3})> a}R jGPk =xYc,6^(^JܤNS\@:?GwLyikOv"Ŷ`όm6% 9h(h_7q}/Bgrubȝg{ӱsMwe4ǭ^U6IZ嘮ۍrU^P`)^~tw^ņ@Ze4P"?BWY #tu_G=b}|=Lk|#1&n2{sPJ!NԔ9nXSls:gw~ H/UҟDkzdl(x!y$iH%G՞@~ڍ ^&%\5|n3+G'nV{377u[y.'()ЙIցdZݹBϭc$.%G"Q9oov}OS Z(kV a6HRJ(\̵9Í[(!skΖBޚF3PPͿƤg#T h= iWy?(㯩25x\1-!j[[Cvm;:zJh_@Uڲ*JiUg@ o1*ɜiqҾ?'afG քN@흯FHO3kd1MKofǍ{6_I4Om{7bvlykۏQ_{^eMj5 By-V狋g(^  ]Nd^N19@ Cq8UpU%bQ=1 9] |Лt0^?qaB1~r[f9$e~jGͺ.4`HoIYD_-gNЊes᙭kShIÔ|\u1\A3#}a/Zֺ>Ŏ HʀN]@5vSWrp~TNp|6=fq%ί&^,5v#i<W㵛/6!ya:PV*njhR-WkPH:٧ٶm׿O78O̧Ԕֲ?+3Vm^N쉁cU6*O^ʬyi?Kn vbB­>T@&AYwڒ7QrR\܄k77BgS8htopn>'D ݮ\֘ζ1Lvp}VFJkvlɿa̜i_$UH53EHHac=,5^)PBc;uː!@5j(pWY[M'WoO^ηn|ry cd.@kbEz7V?b&_(am{y^?Rb6Uq(~i__ő?>]!M%63jghFgG6qV qpLPj )r! 8yrAy[ Nu l+޶mcLWTU\G c4Yc ]>$:>qv2_uo& \]˪Zw |;?vCO4k嚦~*:>ѐ/(E@h&F DCšMv"@L /ތ| 1;^437卻nsQ3ܲeRM"ҡMm"i/sr`@ F_WSal 6A9m҇錁TcaE\ "N&˗G (ȭ jRЄM2 Iia,t^7!향3n&iv{.CҗB(,J+iH2 bB$r 1i6clXl?^vf׭EZUTU2Mh > 2' t#7Bj)@ jɄ^_P`J!/9=Jؔ"֡u: gPf%D L)c<ӧh3+^(7KI i NTw!JVa zah Ђ7(@'Uk C0^Z)#:;N" c= _ 5(BPI)J)׼nay+m#.:[f\ Rmd4_l 2̖^.^s K\/X>(V`fL^fLq Q:xc ѓ:-r,>wl"2թ, D0($Icf/k_58Ii,(kZDs @x\ bM(Wu-@\tm$8>8Id[5N6k)o)#Ƌ[ %Tf.LU(d!5˥BzzuG)p!]d]*J9*CERϦyWTdW*0_n`67Q11wU\Y b|g)A.u&T ̫@\YeJ@(ӻw#5JX dWu)SK`<iE覾14,JCX@ V+5p DYa 4=_2C/ ¢ `<9FQD0m'@zA[@l V G@ T$/-0  Em jdE4AZ?wE)_6[J ps&S%F#O3 [B0i^fZ8IS܋H(tEA *~Hp\W߼g0 g]H+6CƤFM1!/x%Z8u4G"/Zte֮/ l]A'"o踆F`܋/qs`s,?60hi9˝ ]*(blmQ&wBش %*^D 8u#8/:١u)mvM5 Aq1@ּf2RI|g8˞[nخB%?胤 @l `]`)=&C^eǏ؍` (E? 3*#D?d.(L7elNJ,@;eR}ATY4&fC$YL wG>,KC{S@ޡ; QexT( O)(+M [!`H[é@R kε"%C.8ոJ0U(I(k[ {~_<`7E0)!(!@'y>6! f8;?lsv.^Hd?gwDPf@7Dv2,4H^S ʃ\cH=&MTWQnTy'gg}-qLkTI2CDQhB5+5gG@hEi._=b 6RUS)~~_|{}85[Q!lSLSaSzp0^W;=VӦeU(d4SO};{^YCz !/E4WӔM91@߼^mGܺ=$YTY!bER -?߮FAڷaT]*LY *~G%CT'L3Q¬Fzv7YB`~8yeI6o9'I4-mhZ2sWr_6SobPW瘦d@4^vKS.Tk2\#aVzlNw(Sf[7/ҋ*Dԭ)hG|V.(OggS^﹦0[p5~!!!#!!!(& """'#%$%$ #((#'"#&!)%+>}NUnQܤBx'A&if8&a\W⼇ȏӉLFTiXe6 =ke8!(P1yJeT)7(D<6!fW<Z#V5Tq]ՏwziYz}kx]"G5JܚGD$>ԟQPp4 QEȽ2'DG a)u`jA$Q\O~<6:A\.I.G +uBtawYϧLGF1РN(%[IX OlGƵ5>Uc{zӛ;>vۻ T>]y&P"D~v4!݈E\B;e(@m ,MA] -~)%A9y`z,,wwJ#Vml u]&m"eł {SC6}mV OPg'!6gnU f%h^ۥZW;v@B;q>vG~ ql UN:(P@J ~:#2Ωf[#Kf#+|o(S\Y]lGXk~]?ϹN?Phi" *+/qI*}Z BX7dԪTS n>|Zhyp)=_;HD~b{LUQj9o,/N/9c8+ԻnRqLœU rMm_IW.gj~"\US=\lhH衿y4˙)a) ,QBOT6̼ŕZ/?c dBG?^DSk9" z{Sk>;<)7lWN[-0`+~xSoz]fjt^&L]Y!:8)rm',LGį(T _svq}=mNOה2e^XL1qOM0Y,<9}Sؤ/OKM0B? [n =fsoYWC"́,,l.}F |NnM(5%L5&?B 2bmg{m[ܳ/[-DSpwolvzB' UJxB?_~".m:AA (%z7Vx.ͩ-NSL+ V6B\[έ370ٹ W]5hwdYӶ5Tlqv kֳGu\W3՞b=쬎UYFDS!dV-Goipv S'dE$fF4 97g'(Nu-"Tnuc_45zoƴbnK9'""sWvρt\/ $ 6 :ShT7iRС %,AQ$V=v6")gm0lcL<->Ϣ]c ^ >U}2tj'Q,f]i"J:{bHTjG/M@<oqOl{Qo` > |jrϔChQ?U@ ;YLAQw|1XD)P<)VX+#j@6+)p]!XȦ!0 ^x|bp[.dX{>_Mda;{po%|Z > ]δC!~ćV rޤN q@J8vɘL!ZH?,ŋ;.hNJ&Vzv۱yq_.C-A欶鿮3av!(ዳ-hAHnd/@/!>u:\ 6 +W11H!X>*M_fS,ZzDhuϳQ,L*k}!bjL;]uJ1R~z5`T OMn/ch5 lDUN4Ֆ]v3eKRVkMAL TU*r3j\a#of}̥JMdܖlvv?Ah0맲ssF->\[#hjm*; /voZ_fF|\[˫r(BCU/`*1) ӱԫk 0蘈 Er8zȰ\_.c\y.aZRimp426M}6*q1[9SP SЄKo# f[<|x4ʋI#|;XvQ!n7+:@[2 6Dzp:0?#}pfDwo" d**؁P/$Mӌ1~ Yu)CKw%qnmHx`c&?r|j;%/SZ 1}qll2ƥ2. >bYѠv[.f vќW0B``fgaj]ᄡg} ]9Y6J]/{M˛Χ.o/?S>f,45~܎R}\pf9qx9p!WzW?ۿ߂~:8*L>IHQV y|#z[WT% 9'c8YmD̑k܆Ix)#2Oe6Fd!0W6$ /]N$>Ӹ;*LmnasWmQEc1kmOJ+d{UXsϾ?97Supݰ jvOJddK =mF\=xNMs7_"d߶gpYŀ̧V9캛:}xDL"7QTiIfk|?8Yo}4}¾a<)4R4UR59Ǘ eN(OggSf^﹦03#"!""%&#"%$#%'&%!! !!!'$%$$$%($dU6>G@^>@)?n9nRd۰Qa:J`S?('-:]K{ZD$6<%=I;ƲvdL<5$|{ Z΅ s]n}$D仯kh{dsrzQ~-\ m xn n,!815DUElvjղH{'^fSF)9ONݷ_ l]Z;ng32x)DJM;J+ydni?` \$ͻ먧F@SS~hֲr(CGkJ¡^- `>#],y϶2=ԟOU0wR͈.S~1M52Lrn2?ņDcl#dH~zÀ]vEi PnqSnTBUC}vv"J>LXA)LaB&j&S^} aU^DQ9aTǽR.Q "wld6m!:w5b,@ (ώ_4|!gcH(,$T-c6$˦(~DT`e$޲1FCcЂ9>MEH!0AqHӂ"1R UuVzС[2에C_…˝&sfd|4l08DP p6p"\8l}FӌTpA$HM>|<}hk菐' 2yMvX~ yeB# N,u3rI9h\ #5BLtL_G"A)q&EII_ j ⳙ@| k4Xy%01$ TߖU8d*C/\/oN7e߮{?n,*\0Y8wi8{Yɗk7{Ne"T0M39XՌvPis$LM3rŃ,k:]r\kf'H\Ֆّ٬Kr?&u!|zjld2i<;bސvt>g u.S[.T[hf ğnZ݅X8nBOj؃@]χ R1Vf9 "nDu(#;?,E`E@ZǓ=ڥ r;;RIXۥ Q/,,)}= !m$5mgnooz_.IG҈BvJáy!&2g LOTUmq3T U~L׌0zⱮuԾ0ZCe$i L Kt)v E 6~I|%,J|>pӎ.>q 'ԺsV'祼QZށ 4B~h^J?* J^t}x6b խwi2|0vYYJ־E fT~LVe.z%1>o\oG ViH$DŽ֎nFߝu`21=f<U^W"ioBLO%(ھKM\6UH V9 uwӣ/ nYr`/R#iy\Uti~1?hg2_6:LinŹ`LY}Ֆ\{8~5st&3 FsTNU/֖/tIt JRudY?imΚ\2_Ui3(!UczdWΡ([۷m=g0DZՐ-E T]QѮ{E 8_M%Z5LWHu a<}Kkk|ywte.Kv`OOF4R$to7lmf: pn[| %pܭa\\ IHJW̙mz\RZ?8¾PuIL)y: 㡑[7ۧtZZN9GȈraF9'YkN፽8Ҳ\8~mkn[ae:^QX\:ܹO0$ޜklj(^Se| !2fh.,WvSHjDck8W5.h~t  Wq%eH*|>qs.O?R$@f9<+.B?8Slʦ ~_#y\ǮUQ'k }i%z@4,˓#a;Jd '?XH#[ m܀e_%B.1^>אIknq9e?!xkLv%{?Xn(E=Mr[#3WH3T2^INucϯF扨2^;Œ~NT V%M-ʀ +>‚rqCH*"+xBuF} 10a!dlk|Ʊag-@T?oOcvzdz thHok8_nyqfTאv`8>_~F ͤ%T_LLϴ>8zwcs$;tEM!l-_~$Dh`BD RvbT0nh?sW֜ntYc!T[ZӖPӴ}N)x%ɷ_fwo&\]7_:K؞~-\)=KZKFL0^9JY8?DVj?d]i,@謵d*@{mҥrץ /%h%_qP&݆@v:)o,#}g~^%sd?WrvxcKJYC~LE@mUKȗԑ"^ MY C=l}Zv՚b*YUFC$UvÁ1V4{+bINb:6XbY ,{ņ  $P\Eÿ·9r$oCdSei'FRRb`UI#z5a; {^e|ڮ_kZ6T9-o 5>wȈB;L]bj54Ra܍8,]5~+e@ p[7@=|b_= 4qq15#ң_ŭq~} cNwŘH3kmCل9,^p}M Gxm|ʶk^;ly1ssu6ί\k~zy$E=CRF"[YXA\Ir P 4VC1\FŨĢ]^[.&HrĤ ?n\N[[͝oJG*猐eG7Fws8:TWtw'F6?'ly=|Hns9dNYz>cnfT*]EK&OggS^﹦0V2"!!!# (''n?}8~ 5ꨏ,q8&D##:n:;oFZ/UbAT_uL  ^x VBzt]GMLysMgkhO?{_uin&RZB4-WHIQHsCZ}%:(%S48,J\hL5L+mZۥad,I$n{$϶)أ~MܘqZA$K&dCRAQME)k2:l}EW7Vg+ϩ2 nQZS*ެK D@Qc ~lkH(_&qXt$֜s0 $n$nQ:H8*,WZ %3qț4䈏L935F-ۛ931~bxNWnTXeò j`z+F7 C Zw5 $Pccݴ>;F>?ҵc퇴5[1Y 0ZԷjU~=1&:DrF5^w2<;dp'wBCh1'X!l`S*e_ )oPoҜVkccIf 7#*-wQ~06Hi 46͠87 LFCa-X@:JU0uny\enn؇=k)iXeGaڭ5-?{tHswkLq!)@KnEwi_Rvd1N{}SC̳1u8i En9,򅟻)*̅TB(B:쮔 +rE)[2,}x;&|.ũURebKds:8rAphO{D rHc= SJS^`S%HVߕy1PxCݞΧkm+.M!jx1j7vZ.ipUGQ uKoKn~ő\2[' \ДrjOi;",%]|A9s\G\bۇ&6sP|?58?`h}Ga]qU!JkW3: qF!'OC<~M!ŵ~e~MkUA՘5T랧%+t!]m.XK+ȕkנFE/1.hMSxQҟ=AC#{v(z9i4P=F7~M:nnu{6nu57Qilk|P 0F1UuUl l7  6PţXL1M#fO+W4dZü몒o^d/>x{.suu[lV!?_*HEG3n3XDyE$>tmH^6ht2=t ʔݻkö!PGh6=咦gE>,i.+I1(KaxnDW<yu}OV1ZT[p0kƃq"YS#>ATKT[ݕ5s{y K o*LwCR.D:W ix˼ۻ$DuVUpE d餯-;Wxm}e頔c$Dé$RTUS|"+~._ϒk.8?T X=8f֧_gKԿs(\*0>vB|ADd& qǪOTY嵕)"|s~ݸY?5Ndc$X>ضyM'rI 깨nOI)]Z|1;hCo-gboP\??!*Ĉ!JatRц{6%%겥hfm*g<.E)HZoa X-ID.#X1@2AADH JWI^XTڋx᤹SZ/п-<.i3``@@$ _\ v'0|p,2V,Ǟ1POIb26c8ԑu|XQЅd`B0" ", W{XeFMjl^^@k-b SK0)T2A]0IT *K ̡⹕!)ӟ C=F/&ͅe20$iHPYiX,uFtܔ,X?z>1$v eq \d0nY,L#Hv%uF ܛ)@]$ ?p4+~nc6t/nV d`IG$&n`o)F O}?9`Ōb-yޖut@%4 9X6ű^x˼BN-EE( ϓ` vف`I?ڱ@#9cAfGNV T$)z<:h,EL鳃yø(*7+qL!( Eip@|p 8JEUAIAq&@~nCe$cʡI n!k! iHH! 2YgA.'[]N#`lX-&J]pZܓc6D_ d_('bD|} &suTԱGG !(Ya0e 5 RލkM,nWn h(^@0^mL)H'l.I:QDMO XS"LC=&WKn w 7S )b$֊ҟC1jXXfa0:LI$i%v6|?+6 E -H$ R`"4Dܒ  nܬ ( 7/a]W5d\~<1{n &Cut.ɨ153cpdGc/"~w!baQVK^dH谱n65jwH7Hi+f;AX~&r)٣h=Py*\6qy?A=fʥM_&nP;{tu`EZ1[1OggS<_﹦0R],!!!"!"&#v "" #('zuy{xy>UN"t_sF^&e\.X)%g%X~s'Ɩ1ٸazl9}}]WE YȒtH@Tʁ&ʙ$ ,vv]ΌQMW+,2ᆺ_p8!NK8La= }Ab, x@`^|~G$ LHL8?CjF2"܅txm(z篟Yľyp  t ]@*XWTWOF-|<,7^Ls-Mp.L~V*i2 ( RDR'6n^Ga#n\~e,$bΧf"!"@ӗjHk`tX(AMladuA'~բm8c L-KjX"a$#@-{k{^XMnI:q,i˖F JvP B, gǢ2 ,ɂv`{.(Չ5kuJʭCG)aIJ .tj5~n*~\7d@ n8$q9@=)MS&s-(Ml \kv`Z5 9p{6$y]W;K68Bhm!{rզ<J<,)Mc;ȄhG*P!@oX/Rii ![]* T+j L+&D*W ~kn8ČR3t*~7vlp!H~x JCw9aEDD=wTXre!\^+hl Bw`"MH3@ h^1\lM{ Dkpvcˍ*`4 c0RoߎoVh }^>dr)!E@eKfxFdkm {uxV}2 ]-=4(.kF-pm`,*>>+ f4S$* rb:G~ekKÍJ\YeT|EW] GM}aXLS845I\g0ޞ tOaL*^DShT/nՆ@L; !PUdTY2IWWCxޡ7}שf{n^=/*P%4h{ukom5Hhf@׳ 5[ӈl4peT,.FƄ[;w:c',vT,4\,V&+QI7Y!&SµUxS3 |-   k J#,HWM:еD'dGф4GW@,N 4Iqa\Ɓڦ0uW˛YEWbF1CRWX*eKMT@%\^;!`v p) 1N^׷mP$jm_|c8f)3tgC"&A*Mpš*I5*wyIbYu)Hm^ƀDbzKslXaǓItO7};sƿpbO#s1 TՆũڑ|-?B(ݠi^{L$TQʱr 7z!SG] E\WUZYVM?( "4`]F'ЪI.Iid `7C7F0U zh@?H.l  P?}_`A$z | DjeBj߲4̤> D FĔ2lMtĸm0q*=J|[fNE@U <`#Y1D \KܒQ- M(5A"ue!F <~@[l6҃if2SBقsWnGw|plI}OKj Dl` <F¢r `(P&8XW8eߠ9Tc!r+( 7@ŝesuA"ߴ5I%~z ,aQx#ɄxZU:pxxRJ'Q1$"dDJpB1l) $,(NdQWK6.WRŒ]r 6G lmcO 8 9d<)a3m?! &yF*g-͠`ʵaBv7P>Q@. A{[ E2ҔDm4Pcڶ0?Q!ߏC==\woV)̐8&f6Rv4.AJmӶ@Y~)pPw pt PS9 ]bA߀*OggS@_﹦0`pu#8!#! "!!(%$!  %#$!! "$""p} ""!'$$TU%Bd"[yJJbiLQk[bj_~>ySm5z r߼!.TUeN?f_KzfR¢!k2LMRUJ<$ץR ZZTWrULdB CHODYP>kIvnT\_dU /55M>a;b3LKWQaNr"TX!?:.;'\D6SySFqaow3@WYsakXZ L(A AB$AsRR^笢IO_z3%kTV`^  G``@< X [ϖP@n+S{#Ay`' %9ʘ{.Xi2$$NLt*t9'zzuL[BQˢ6xfK'E}x QuTY\JL1|%p^b$\UiJZϧ4M7u+C\\W&6U֚R<ؗ՗{3i; \]dE>8,y-σߓi[XCG*d]\7';&5V;{$ǒo~d\et+`lʽPqC^s76Hǖz[]@Řނy D #QOLEnD9)A>4'|`JJv8c5Xw28$ j815RU3 ANX-sUI]*m*! 4UC%!b+X@;w 63zχE%((.R2;TGݓ*"?* (14z#cG#CeU}./6(h*~J qe.x ֆu||&[KӣU~(VtA4@@G0G]WXz*O@ hC*F`1\ &8Id=ݞ7 FH@;^}~H_ϗ4%DNb"B$y__mh b. !o$ aZ"NId؊7:B5\YAn.[DUF@b~š%qI\mITU"XՕ/U\wqLC?'89DUUL|,z>cagPJd[BFWFԷ]z|]-KrI\[BU8[fr$rq@L:DMװtLU0)=v;Z_)u]F27bAQD[JϕBL v}˧󿯓FĖ`O(d_. КfB8xpl5kٵ<|e(W&61M(|*:|)QVlN5 7m2b$GI9YX,&Yrl8ѩ&}5dK+aɭ607=t8Ѵ=*yP>奬 0p)r P@ B% ]H.0)\ ͲZ quDn48e]@@9.s1$A`t%~_nj!L]0K:3[bLc֕4*nJg  *P|A0,"^ߚ!$[N_$Ǥ%υ++ 1!Q˝ u(el;h6 «~hM pY`*p B&0v7;*K =Z#҅<'{FZ[{'{{w),@0)AHԕ `?{qvO>s$%~WW8zvv >%5@-[~T: u*\UյP4#d:RSH),\YB_n$r_ߺ\Pw[ض'ÐV\LU\ɩ}Ox,mp؛JV*!O-,){FX`ˑ&Ez_a9~>Oiiº%1aX2 k.,vBNC Xdbe!>ROi; tυmYzU(*DB )ROZL]vA~Okv*%zIUip*7)dP4ZO]8`\Gj^ȉK DpWOBoH@#OggS@`﹦0WS+{| !" !&&#!  (%>֑J'n1Lu@ .y1SqJI~ig^ hwϦb;9U.][P!10{] IK2iRWDb-b%%l|"By- I٢z@t1\ܠ nE?̈́L {þ#=:"2f̻6e>ɑ4}&IvQNϪl䬈by9ϯdc7DU_<:Hy'B$E5 h->z'A)~ltt@cԅ*3{B"!ꠉ .3-{67k̺tIv$ 4 0hq@#,{{57@NI3(Azz\iPb@(10z })%5ȝBu}f%$ΰJ 4^2^zY_'Kj|I`+ _8U?*RwwO#i`㷰pI( tqY!Id-FW^>vB!|gRj^f/O/3 v峉D1ګDz0CM Zb#av` P`G +97j `]V8Z&I Xn;R|^Lr*?"ˣ?FdeȈ}Ydc(+f$90`*!˘EKŇje `b}JeSxsVvCx${OD"hлZVeJȉ?p6yc}ac^".MF FY\ 0hGzw:d#L~X84'*Hz]7 >>5KO)N~,XJ2(e#w3:bڋ7-o~uʻ"tR*((hȨCrdL{g" ]JpK^O_.VG`(~LNހ%'iW+.\ S%.hDy{Bidɋ(EIYQK2 E2qMCu,ja~)er[?S,Q@ I3k'Rxk6ƁfAܱDE+wڛfD1KL\È2ro<e ѭb)16#73/gؤ+-@>h?nBU IҗPJ V;>(=^> Brh=H}KDAvId)zXj>O<0~I/Y}!:F֘*v.U( ܠ "8m ȧ)#Uˇl@W.@3J "aٟ_@0e şo @)SOR'йL:l*<^,3+چ6DY.Y-ܷvnj5=Fp&lg@=w,6@)%#}d!d+ct5QW驑`Z *WJ) Z1]zײZϓ]0]*d]lCgfA6kUZJB ^oK TW\JIpv39h$hvG*W$LUGP{]rZ&gΗŠ&DW9)M _r^JMnLW\JP]9y"!\~½!buTU\J Լm0}$k%źTYikiz\ęݸ=nkMFTaJ RS2_E?/}o`5Fm2TƩ#;M禀,% @s8`\4ZYfwv7&k}7R(7܅ 7#AFs25v=Ĕa'Zj UĊ2l`B0N)R}p4MWꝕPLlUƉYg}h|kTB2C E `p <` %zxެN%3xOmt!W:u՞5i@+qN5 $k& "$%̍KI&b7/_I؟?> :x(`)Η&rM-P1P\_@gk$Xxp>\v&BanmF:uI(K6$:\xnCHkPB0I$Bʐ_&6،~xOۋPtZ M@`7`8ĄsN K4 />F@5V28.t V ($$rՍQfCmXBLi֎6`=i_#$(2rœ~ uhѣ1/ 6 1HUe$c%}6}SՆT, _H5@`4``˲\҆5-ւD}#?\*-DެOK rzD,ءua7M '*)u0:fm0#',GCϸDQh2m1S\ǭ51ba<! < 4'%~l{3v;uD !@BuaRR83M( R"\TMd҉;3q.ϣN":a#qs& RR`epm_1'"{D@(IP R\x]Bb!j̽ Sȇ2ABMOFe&VwVJ ڠ%R$A22촗 pOϢS~% ȸN^U_H 9IY` : P1Xa@N'Px2 >jZˊ4QF#Ȳ O>2 &:P.!%,W YHr3,yʃvXC"#DU€eО/.vڽ*@˹*TYRu=~ԇP~ɋlMD)T,WF:t 7WW߆j p9`@`nwul|Bc>W$5xtV|ξjnmUOggS@x`﹦0f` 1{|y""" !#'#  %" *'"#! " &%#>u &vzipw:;k}6;O;KǾ͎&AhY&LF.iEXĕ@Lҋy| 8rQ@QEL1"'•"lSmba .)x 9pI"R$H}iÃ9-&tp<}vl^G[z@d@gJp ha0hC{!Bbt!@U# "^ J SVhwF`Yz-@r`j++N.U}jY!<:zUne%H u_iv._o t)b  ~@>rWP# 97xk+MOp;$9ڈ#wr^s 7m:߬R ;^FQ:0q 8,X?*r@bE؃M7"L^t8@CzW&` .„!E$9Y1nucjcYSF<R@-o@TTt ﰬo y@a>0C)&`BiEY\0?FJcA{_SqlՏ($!(!CKՕ]S)ûfTozAO[ (y.@b ޣ>X ~2AbAFpq+4SQ؅Eb!d/CbLIdBDSy5*T_䝅S NS5.*e4W)$C{3ø>=kudخ"Y#U4O`k*?߷Ez%tg RMrj(%4B^DYh@Ã1 ߹!Fw|p}a*T[*T[ \Ttjϔ"-qV7Lo3!RB,Ci( dݺ徟mws :ʬLO+2MTWԹm E!BF(ABѪ]edr;~?Xc۩ycA[k#*FF,]S %B$~XH\][=vxWekgBZ31F$lcJaYcyʔK8cTAqe`yi.w_TkNPÃnH>d62oDg`pX6 )QHdhL{{&"|g@W6 :8E卋cq=lxce\ Poz@~YfI.<,5֨a3OOEZ"Hޝ/:Z0jzcfs'8PӶ>RK1 1-  ,sQ`.0%oDUt^,^ F [0AX `<4?MOڞfoZribl^`:IG8"6b\ߧŅ*Y %ҥ6^bv(Aq!RFUULM$PzPӵTA4=K㸒OH)MhU#$EFÅE:SM۠yFvCBL^o9tV6}|\%LRj$4c^F_Ł1M],jP\Qu%3ot*:E\_>}<05Ԑ7'dÍc}äy޻UC: V?0ke s72_PHMTRkPs8HITn]"J{]X$ _ v]fXK&ѱ{͎ bm~7m3ρ,pgauuoބF/EgH_vDG+79`+Ë ~0ސ daez X`C?>uѪ~d[v lf({v߃Wo³gb"B:0z5PG0W{ܯO(v^86(VH #EI. ^_~1oiQ7tZ:RY=`äD&ڥc-ŷWw-@B[t)}RF.hyaf4b.6rcn8D!S15hByeb<[WP.ƂbIxى_fzu܇b,w.ȟ%BRq4}LU~} v[+ @Mr ؒ`V#n7I{V4]"٤ ar aA DYT}`UjN1qH.T׎uAj7VC/cPrZ.}eah5F\[m+ U޿I04İ;!y_bz]8ch.5Hu+{|sv/zBOXh]{ܺb^նe MGeHȡLz]̙& P.C [+b] .t4ʺ(Ot ާ.TpTP?^nuB= u0cj1j*7ՅSbEi$D]er}%e1^t74 ~Jپ:PPP@?,$rSIHH%r-$%nnM `y<ʑr3esM!Y]8%,RE1>)9wY1sy51PB a%TU@@k 1q^?v_ΐcxcȠb#\\ DFvu|52*SjL?Qd2㰮}G[VDO42w/*<44ϕ#\; v_'a7U#fAq6:9f4&jG+B_4S q@ `cqˬSuT[6j65Ml@j|J_N~ƢT[Ե4fύNgI^TLY}Ֆ \;y狾\!yRDSkv2gN(W BsLQXUӾVC945L׸=żE\Y@s}y@`̦\֛m}! \_ D} A/CQnޭ-VJ2B^ +r $y'dW >lOʵەku55O-%Wޙ]_WS"<U:^5ŧ(9b ȘU:q e;omA}4!:J|~u, /Z N[CAB ŧ_ψ tKq NmLc+.,!gU{(p(.s ¼,>cp|ݛg.z=y1IC&B1_BO>5o-) g&ɚc5m> n@!kt.rE`9$VOggS@`﹦0(0;!"!#')+%# %"*#)"#!"#,)(&##)'&(!## " %&#^=L$w=^̓u׫fA&,\1HlLHUr>!Y=qq<<WVS m B@@E{䁢&@@)jy$Wd%$PHh'ө UTt0z"VxZUZwj  LF2Ͼ[xk/Z-Ϻf"B||9}vMneg^q;6ZuGM%Xw+@(G5 Vq,yERĊ$踥/+oR{A=$b@L6]\AMYZUp/.J[ҘCQ-\ѾUĕ <;fՔLUM6?^{{/_d*HF^DD:P~R6nn6%bmIUhR)T ּ/?>J oM7vTۍ{e[6s0vxj[q*K˱z'{}ow"\=[prHA`XNGk-m@8ޏƽ#У@=TkQ4?FAO9&`P\:~(&V\'c7\o~9|2o7k:FA'{u>$/^p%*j4dֹ5|i[[GՙOޞGChdnHX2<6 h L@zh%Pj٧"CBȨ1z}n~SL>2\=[K-d6bdu*\wX8݅SLzRϩkS"~#da,H(*#RR%{Tvh$FUwMޔ.@gv=g34XNQBɓٶ8% $) :.ni@_WcHvJO.0V9ךô|šO"E}%ݘwVbZi9j4ɫoWMpE7IR[x5򽖔K_,RNfp7ؖL!Ih^G]*crex0ӕ6xX"p|$k41vTgRv! l#PݘhfZ^nӑN҄7͋8 8J#Th&0BUty9% *n@#D %72K%h.,# ~JbS0a@7"7MىtasC'i,=y DYT9 xB^M'Ƙ7ڭݜByM%1 57n>20Q~wyj#K(l\N#Iph:Y72]>]ڨR6yuRA} x5~%Qp4ًυ'VO_6.(NO+MO89KLobi"\dIXf]7k|mrladͳMz*7WXUb2> |X, Q~ fL6;$4^jbUsUjX sLi2֢'v7pl7k][oAZ !%h_A|6u!,:,Ǜy_cf(K*s\+9lbiɅU`&>TFB(eѨ]DKeX53@n'CKH*&He_~u\WFĺ\d_o7V\p˩e3cdS6ܘjϟaY-.L;PWXIP64`Zk /ܐKrFHhǼ T;"1Rn[V bLY37ۗWt%SaOT+DWSv;{wxde},EdUGW׺E3úB!$z|? pDY}4?)>e]ăT/2)5ƕX.Dd]LL7 kt=5lsg^So󐤱۰Tatl 6y"!†'R׹l ta(P7לO]QRR[7Y:_:JeN[GQ--Snrn{cMcmxl9z 6J9R+*eHwƸd(}fYa<>49{K40W vQZuqEBߌEӡrJg0[ M* yQD#APOjE_j5uCθ%c#׋xy2&Qٺ@R@ dQ̀!I/1t.&_ T/7= v&G Q&;\I| ~X8[~<.%Jvbv˳+4;"GaLJ;q{mi%-1'w<)slڷ~~p!جm4-=w#@@'YOtd%Nr&k4 -nYBc ldO5)B5B 9OggS=a﹦02&p*##!#'&&%|"!"" ! )%L:. t >Tf|S-\ۖ9x87ȔmZ8"Os \pS,xh~\Lyhh&ӒΫߺID䴣Aek VQyּv^?|pNiLWT%suIoIncD[ .(:~:v&㉛gǜL_ [P<8񦅥\G.:<67, (gG*^TlyH1ETJ<{|MU}xY/O&eAGF*mŰ4}א¶, QMUP0X.ֺo 0^<ֆS03A!h4iOULȩYDw?MnQ:ߥ2F\dt X" i m򶙟5dv:6CC?FNS&u(_Zւ(\0h~[CH!I`& _GPYǩg::gɥӬTwأ7\BD|. O:gOA2k.nm/NS2@ rLkѶjC65#;A,T F0"#>K%(Y+4pADDTAa<+"y{=/ n< M=Xh?] VNkxJ.%V͔.5#NʥpH7-KR`Vj(..8YF U6nU]+Lb~;WVۮeiKhHҘPKO\cdrJ:C>Sx5uf(1ӡݛwgF!qcPRz,ܡ^F^u nSF8&KR9?JRC`I2LxQ8oRݳCքuHgjB  k,iώ7~u8=&}۩)B5 ӱaՐi}zc]‚w>nseјķ|NɠBf낢9?HMO՛/6IOM%qYvYuᐲPdLt00a8b2|1L OͺSm>1UX)I.aq @#Zul${"iɼ@t$O\W|V)fZ4H⢉elo"C*oБn\A?^_dus|i _{>w|r'?ۯ6PЩ~SkU6/ߌNwW5#.j2!]C2'P[,aJۉD),Uh7=p#+GBhq1 ԋ7foNjGآݪWpTm7t)L?L HSy?Zi7iM[{ǑWׯp SJ"nJ[ WDͨX>-^QJh+ ijK'"2S7hamrr8a8mߌz)H'.h{mZzZRJ aK3؄1K`"-̖lb10m(j5B /m9PIaQXs] )q"eS ^rs-벣cݝ: RNm \ h%%Puܱ'95!qARKx]zmh/r{NR|T+6B`]XrJV ȊBR]Mk5i٤BЖ 2'^ѩP+b0>,r#\~T;u"ݞT+ ʰ4D D[NZ#^,A<HvgeQYn;ADFe{[_Moc5q UBnj? ?ʧkt6C S1+͑Exi,i \ A*n!`^l) RXu1M",^#*ª*HT+UX @IP h^/S:nTHd^2BN5pt,niUS_-qI!ԁp,n $vl<:̅ъ yDŽT,~BFlg?>H3pcb*|̡xxT0-Q6&#k \E*OZ!{WƖ_Z\eOZ :`ݛҨ]r(jA5sMno_v7NSw/pN+bE v wphުhAO^ ?)$>QF ؉OhכHiÜu;E)sZǖ>ԝ?Hժ9&tA/Qbɭ֣chh?Yj^Ŋ\UK&q@\wyW1l^ ]̡˺l3 B.DU助pÎ1؃k (=5R5DU(r6vo/bN( 4Qtj|V|iG,,U<OqAݓz}>~2|$TWе8Ԧ#>zk0ʞ &8 \4Nlᮚvѡ2z T>+,*J;Mn}4EL[QւLz3,jKw_WOî[[e/\[ .:A Hhz)ҵlJcdk̽: :SڤH 4\[,22 dߎag/"PS_s.dS~6,j1QRl8ݐֽI ~JSYY0'" nuwpbl:fYuo=JGFu4GS `eYj/I||xT6cw8~ڵcWKx#VA!i|o.0Rˠ2f@^\@> ^ \q0;e .=IZ@X2 #I٪L)uxD.=mQ?*xrp\ 7<d;a6ܐ* ( p"N)AFc6[D9.Lq1*KH!MG(vՠ^ P2f6sSC:Ti3F,I@~WBHw"07`(h@A0,Z (\ |@Ŷ2OggSa﹦0"*$ !!!!("$" !!*(wMd6Eݺ0 a` J @DL(d,bYmtK[ bOeGDNcWPj@D hW0JP~'hlA7e t(?}/-)%>dmVlc6LZ P\P:s* "$RIwlx4f6*Fm&"ܿE`30_6Xt 0 nY` vv.`N\,l%i='N5<ȇu q# gpeʀAQHAd5ƴ_A -²D)lIaxS2@tx0O~@@+uAf@?@KKZ~ 6Ad;0~e+ͦ֎NHfQJqrLS7GG{ Φ|a]$S_^]E~ѫR׉ٜFItR/ тf(4%r1LA@@j5Я.!::)]5?QFR-I9YNG*D/5Zw|.q1̕h$kY߸u0=鷼)_<چYWHVdn%P  o n@+Dȡ*K&؁'@LnV~8UiL|| ֥'RE"SR\ɧKpR#ox0ff~ *@/7$"I Zn$J F dRA2#2,^u2B4k ݤI/m &c)Hd$ƕ;ׇ~u=wy0ZRPD^Ih!G4 @0\JXr r /\Ve f*  ZA餒ﺂԼOYDp[S_ߗecdu-Ƕ Vg% f)lT  B@nC` 8nkbA6J'ASI0M,T0 ~u"*qh(D3@MJr|WMa%%\i#t ipMf4\jXXz!(zH@ dsnX#>0Ŋ@dA)\zW5uD1E;k@M{̂um3%R"Fr+И⏺|n?>< 8TV`tPehB` `(X+zD,0 VU.m!\;9RRUԂ‹ɤ ^0ZTcaV͗LJ_klKG`S2EDf 1t7u<ƍ# 0&;K"{pe+\@RiE=EH`~˅~%S`Ч]\WN`4%*oZ9;qR12%`{Jv DWH3>ck>[3uv*T.DQ"eDR;zOw0򲄨Hy.,SS8ܾDlO~K.U`BJJJLU|i 72/ެl<ڔAI|u*e(kv j{FEL|p}"|ˡOB"駑I{_+M}}z7}NgNꋷ)c~HdͿtR)Da 1*)y&.!^mn]܊X4$pOMyYS2c܉Co7(|~z5[7jO@Ӝ!m?f ;9Tbk _G(*Q.O* ,H<.CfA8dc\/ Ji+폛׮c.t(߿똝FQmm;kBT05V5oǔ0kx}>uW|5Z; {cN![rIg PTsX T.v^DJ rJD~nM5" sf4X ."\7x _lV2?~:L E{}|Z沰 Q?ݎALVH|:q_-@mH@ #'*,%+q v]B hE R|gSY-!tr ?ETWb J65)y^Ɗ a56p{G F4J9 ,RL|1tIbD7T F,*ĊTWS/<ߴw(BㄛlR TΈ6Ά% 4 f$\SPU3@>#;!c?%n P\ېëҨ]Ϻާz&)DOAd*\{w+vL6o5P,OOQD?+6%_BVJ31q'b`6 ㊧Z`lUk=UOL^|weE{2IYԆo)|>TYd =ї5,z[6k:j?{=r GJ!'5ѱĎ&z+a8!c]9#$#$Ip9<-ge/V:,HM0RDEev+x.XP^8@n˥$5 ]vEj1Ve9u ;IlfD~+њ @`tEm@aD+# j.C^ @,pwk 2> .MʦdnƉ초Y\#y-1jJ|d,a Fj"@X R%~<_\zҸ(qa *=Hcԃ6\ɃeGBT@>k =k9>|"RlJS\$D,m󙌘Iv:TB ګp?ˡ,P LÊUXQE\ ƀ +B~KЀ;p8t)9-JY<(];؈᥵DߞR6lZ.&@YXo P@0F ,A" 4* w bEH;f:TbPzT68Cw$DmVK2Ch~yv L/N DzuW FjC_X]{D ~"}KX( n 1p   tULS(ZZ;=h HȪ6:}ORC ӯ^,\S`Ub]L]}%7UiBcd[wuӹf/G]C4*W\YD)4×Ń; +v5PgRUd[u$KO;BP*\YgJa/׾ȧ.5a qDSJ P䷬Oة5eb+*ՊQDW* 1>]" ^oaM)ҶY'_^Խd_AEͽkuAiIYM-Bd_NX'[<ؗ0|vꕯu_k|.Usl{T @YV8pa8>cхPl'Hct\Y Go^5-e]S*}s|R(?_x׭o9?.{M0˂r+ ,w-3^7' |Ρ&qpLOIshS4\x,Mx".d@Mv)FBh:5[M(P4Uj~%L@r+RKxSځE,ђ8z]yц@? eAAP!DD"@jnclE ӆ_SռE7@Hn߁ii@ O D~L6&jCR`c xѣĸυi`)(!@$AH"X\6Nvtv>%`A4<P s : s \0I'|Tp}""^LNdvTwnܚv K(hBQ" ""zvYIS>礩'G>3nwyB݄3j7z `8a/ѭ Qʾ _$Š"\n&u+@ Jar.lG130(H%k=N͌WT]lmqd,i2K*TM`l*tN‚Dd@TTp".|SZ`O sAk&DH.elIчc,2fǤe]6ؒdi7A."hИ xЭP0/`0':q.(">`X9\n1Gl]%wHn]EE !E@’$NlLlbމ8qzA'@ -aq M@vn5t!AE ?P +ųDv0QzŦz;6~"í`>Ey2#,ʂ"($?vL=;kz_f4FճBAG@)83OkgUNPU(LWTE7US>qmѴ 6/7JͦD]Lu.B`>xmyXE2 %n򱬉]*]\_t* BXLy.b}Ł\Ie:Vrˤ8f'r糎b 2BY+Z,k 1wFNsmҾ}\mкb0c%PL TYЍveSlz`$-5Pb%ڃj@=|K0z Z8SB^)}>vaS&͞LECAcsmq(efh"A03҇S~X:֘`tY4Z!xC*( 8XC8w f?]+]N*B)4.xApyĊ4Ce "a:W\y/龤>GvJ\l~@xX ̊ACDItE\r\t/K?g"H m@g 9CW1GK8'b@'/X9 OggSb﹦06### )#TW\dJ%fLJE K݆%[,VdWh`_}n@$ 7QwlI\L_0.1 <8L|SZ T]B \[p8 nTD^ma;OJ\]BD]QrE#×[ΚG\WBTW@X? @] &ihJ$WSlc$b%r]m@r]^q T_ C/!?xk4 ñ&:5>׈:%4 t$^/sCR2F'dqqo9ɱ;Rfx:5Ojlg4Ғ?^ԕkdIDP3!w7R)5H$ WbT $StGBh^R-U^NDH*G e@ankH#'dDM܇Hx%'Û$j'Di7 D(.gJ+ϛ*Zi#,]nލg斂ѣ!!5W>P«# O`WaAeox8lo%h ,̫#tp(ѼVtg \TU[)'/ϿvWKˌI t7j*CjDw8hPwVYzU$SJ 7 {NHqp͘8n/}fw8n{T_.@|5sܘd@t W,{+¢ kD i9HZJ\7:~kB\2I c /@ [+-v Dtj:P,a\wƸ'9cmL{7\9OnIZ5FdMv̈zQ !ee@12y[9G(<";9g_734X0%8ޞbaNݠttyC; PT<`l̟R"rHG':rۦF_SeIxVLH݊G(9IĚY6]TF@A90 ` Fۂh":\b1hP?OD >Q|.EpJ$˥$t\Rd %K~*;OI2dnI<𔷌h!6^:(O)Y R&υ (EWш 1  l6Q"ѡ*kb4_^=;[T&ʄa%@%ee[YFu+1^I% Aɒ 䥶X} $g&血'Fx0K]Ũ[reuFjB@Y2@u 4CZ;~>"e G|cm*!HS\fځ2I=Ȧ~SeJ x>˒RrF֐@551vh'@l@֞),Y/@`>8[ ʠ[x)BnS" 5D06 .a(I?T]F$ 2) av̠Mu\0ҠD\dI%0xYF[^[zOH _V-a  zP5"AeBXc&Ia nD&B~.$Q'UCB$ەaJ!JΆ A'?:k@,BSS嗫`Ҳ!{֊K<ΫpYexA 5P6(P P^ՁۦgA#*ȥ`S@lqDa)hAqe>+ #,8!ħF$"'ĥ8@{aQ"S# uIGݴ2 lhG7F2bh4St 76Ԏj@u2ćk#,+_\2`XDpb`E"ۍFV=&a&bJ02ODDDi!{cô2'0){YyK^QCMN @Q7$Mbԥ9@ D% @ann."A$< AͲXQ Nxx!FYy_Hj`JȜQ:+la sO}~YGcѪdZ66R=-B.AP#B `n@-@ ӣGz`1yA@LBUT2 "%"Ӄ)uXԻmq+九EG Cz66 X- p tY"LErCe0;׫KdzxjV^==dw,")6$ @r! T(7P YI *e`^Dn%M*'CɐWۭ"L6S.f4M[S& }YgIBY'l?v+6wqa~{p'=b3PF7Yo@qK٬(| htBdPC7@$*$ d-L`Q̎5A7vI r^&i]TiSr S#vwmm;dⅴ]0 i‹uc*kM, AsmP<βwW:~%S2Nk^i|ZuɎ-e{ΫEi,Ltq~b[>jvlZ($B8A1NsD3|Lb%ʰ"SJ͢C\ᤩaXi0|mY͘]i-d<.J@V (gE*Rti*PhL L7Z.ܐX.d`>dO@x9H8n+&l<Ĉ&e,5cY55tT[Wf9@"3@P̠or.  <ƋPCl!E4#d0.&^ړ ""Y:=v ECiAKuO"6 `dKDӒ?];{v@1aSݟ82Z X͠@Ydqb.j@p#Go @&wn~|֑gm,~]ٍ< ,ޅ,Xc!CE03?ɤHh:fyݿ֣;Ƣ3J4j@0aNL!A$9S0nx+Fq(0RZqs!Z#`bkChefzTܢ;d ɒXHM8|3^I =U@\o (aYZu~ Ii#JqN G*Vl]\PpAURc!!^|!&,pM ?"f Q*GCZaB2_:'bs:v 1b".F P2@dq;ÒF*xPHA]Br*V\еPAeOggSb﹦0h3W+!)($%$$"'%!!#"'%&)í#!"޽Ot9~;M9- q4cct|;>fY8.`6t }JZ#>].7DRrޜnuH9]XW߱ q%kL[QWv`Ӷgo, E\[2)QZcx0$N۰{PTjJ#L[Ywiugn.jBW?H}]4rvD55~m\YwICN~2VSD )㾖:AU|PT"t)/{ou^l RjQ* ^ZAΰV .1FYzĤҠ% 1NRXmhbTflvXG|xcӧŻ1|'i_p;n #7p rlq?TgJdTEQ2J+/UV U1R?e`(Ș>땬vNPhZ w5\dTUahJt'h>"1@V}xivh=yx݁2hP¯kdu30,JV'g1<0A>@p, d >o5,>+43(? AOKM0n>%KhO=<{ʼ_v7(=_#h@k]A-n5b Vy@^7J-._ՃzmCAk@ \-?A2VЌ":X^?ͻiĘTَ'Wsc㰛 lCX!%=]mwS"c.Yzb&bj2B{`)$DyP6e1 2!4%;F(Cрb;Hпڰ lߺ+g#Ed&{-<lVnx\GzȘ᙮. ü+4YԸ8X 9=Uu0 ^wUwSxZ{.j|7r_9H 1^veٶתVތb 4,.lFJR<Mf&ǨLiȉeHc~\*rK(89v=U Blk0\ָqCq.r|g7F<zy<4˫vQ5o^ab4 cM5zo.׭^ v^rX Χg`Vҋۛ  ,2:tS/4fQ)0Nn‚ ҝSkwխc.&EMutXGN+;uS~s bcJ(B_1E~ŢQZeLGZ*S!>7VK~ucKxcy/5&klO^x~pLzJ$Jʆ_="<75>mq:mcO=ca͞ϥuL{-7c/&7zbxUnou,(,Tb~Qb\`Kp h.Hr ROC}ן&%۶L;Gc/qtQw҇ 1+QS~ ֛OY}."J6 L ~M[egKvտAnGDոn._R5X(+n@ ҵX5@I[\ְJa&F:Dj<oqyhlj:-aU*STL1IZUϘvf{f R=?@KO_S<}*; (@È#I o6'|)2}AEŸ%>m OnTTRPoʂ>Y5Tm\i*ey[Kތ ivspJLJRsfd2muH302ߔc ua ˾ T  F6" Oi(@݌^t)y.0Xת b:H9ȢK]Oϱq[)v+k Wz7%`,Z+Պ[99|@f6|t2~%"Y$r%$+Š\^uIYs|P M|^FmN$DdM3#;ScB#ڐ?v?9ٰ1kΔWPhK4[NqU5(VOdzVFB`\*;n0bij 8B|ڌ7pOďxTF8=#I$R6sRy}Q.aPXAļՖ j*TP7 nIjTC.t2IJHC[QFĥ(v8 L]w@!txSb>D3CdU)o@~mw?56U9LWa5L: N0Ux;*l=sXkIw,O*OU}+ #ۨݎ(׿ӃOT*= TYSV?vHeR]vNDs2O ~ll]í35)#ZBL;]Mz#da(P3͗-i$'.u:}:P/ @!p@}IGl~8|82}wsNŹ3Ly}벶|]? 6/9Ks5zc1߾vFh73@ɀI͗sgw[mHC^Vvb Be7]4o? {oxHw*r F A 3wYn"tmu֜_`zBDyϖ3| W *YtKn%eT6( (+EBR>o*'Z2ª[b~ T?I5=(e-恗@ЃF!V6hĥ[p?1`un[$cc8P>pR8|:$6;.-W36Ύ؉v1`ë+.<4g  |-c.¶pJ]N{sHXN~v+{Q"tv" QAnZ?1xl()H+lbH"K ȖyZmV"f:"uLuGFN[#H*Tݐ6xyAydY_ykܓ:lLONڨZ+giM~;8IeFL@(m~>/L$T٭SǧLS5|~|xɓXtQ˴c;\U>񨚴hΜ7|A-wkTˋF)5oLUhE旷: R8Ih߿kPVT] .0,J2I _(GBhL9#*=y>\]z%BaWKĿq8|e5.KАHp2::I@̑ 62љٵbqDiלi\Iqߴ{h,Pw'C,4皑`NS 2 +g ;pg'ݷC+J++ :\+rĵ# HT7#~)V|4Rc8ioRVj] vf2uGDB3,G*] Oniro69*wbSD| 倔o4(]9 \,n֠O$@c`T؊`c4HO`-+lФy8\\n0%ъ :kV`!b bgvDf̘fO@^,)'҂" dGt @"4za/@9~LѬ! z" %yIn(0F@5,!0bD$&9Tpl;Y·Ajl4@yt~S"X@{E(>,RPG|Z W$%ȉu\ؙ#"A F;lxe`*'1SeLOnjhxk7"U^[F=ZI?|-%0.Yb" KârQ\|]|-7F߳LE.#704Q" svl>L&D26l1:ifDieUbX+t=hXc#neJVk6:v-6hkQn%$Had3iݷ{$k1q'H`A#[I@+T@cIDR&\M >WK2 )+c(ⵔV9;n;V:a%tE0/R8|v2N#_ٱH`~q] ?}mϡ#1yw48&N#bNj6+IvZqwiM 3 P)p:h ?Ѣg)q\@" i=~ŬH8ݒ=Hry q c k5^h![wvf4" G?"f VC5OQ)P WQFQXhpWp@Q/D=wp@.hꀥpxSP6I(qfGȼ!7?af_Ɏဗf kl8X[ kv)Zu\Q߶MH# 2-k AcLyNO!t{I%,bU$z4F.?DV"[T[uۏrfXMLP?6UʺVuTOggSc﹦0h$ !!('$%$!" (&LY+˾2yY J!:8@N߂~I(Zǂrds$>bVf@E|.g/?]"m00*MM_2qS.ש2vm4:hqED+nTvt6MgA/1 -L,,Q@9h8K40/QL+J%? Duq|2 L^FT)MH9Na,)D0 6swD$~ ;/[o3-wZBmwРiUrJ1l)+#O[)rΰctuG$ `am8|:p;>ޓ F01C;k$IN~"sTwQ{DFg܁n Q23"AQ׿+Yv~h7l~>vuhd '=N;hWP[l>_ HT#ncR9Mpu @S +BB:6T[NxҼn ~;{p _;8%nDO3eS/_^i~`/"1p(nsr.P*M{Io/ByTݺ*kٳ~+PI/v+2-0J`$ 0#/wIX1Q"'$iܯ>j;K9;*w8go0.ۅ*bB$ fR!ZTl{ϕJ Am 1v,#ukan*{๊svLOW .+qE+²k~O*><6Z)x̌FX 4 mOSG/< 0HD&T2.(Bvѩr*"7{"|Ͷ-˂⁊n.5k[,>Ͱv53;yC368ƮȬ_0Ek0V6$/ 5g¸AX&[btqlkɈ#9ʔ%'B26b62<ʴ 9,(+Vzu)FnU ^+ SF),YDFbMERE$BQ涼T b')u9yZ&WBx*ؠ dln\Fn>!9qetl1.{:GUlv5ΦzηP]9i,ʘ:tϡ!P-j a1dVCr7F+QupEޜ.zMT<~\\Ң'?6Efp<:G"qQxN05uҥfj*8O,Sl4돧3foYS@4!vS8b=r_t#4[7c|O㔹9ctW>ͫDA%XJ"sM b dR*>cN}XuO63~NNR㺿Y{?2*s~B :NO7)@>?8\C^nC?T {YLIvմ!{]7LG[b7q'! Eׁ\ ^!&|^j$lnPʢ7eLq^O:'uwЅ<\aXeN/nG< bWG}aM#jgfX)ج;]]spbl!վWjqgktia?e7$zt% H 7#D*l1@) ssj;YmELXHw㪝N `v[tOmm~yM?Fw_88&)<>Γfor 5ͳǸʹq~5Ḽt\;J%aڮg$>P0R8 TH=[=[^m9۞}4o$v%t 2_!ljuI欔]Ë["Ќ!18xj fOf?ϛysL驷cRZ1rQn\چOYr]+w:qKvp\^nW'^(.l1bەp\ #JRGGpQxbüC |+F gn7HHI=Zׂ%2[N "ph41Ʉ RCXG=4IZBv,oC#7 J"7#^c|$'ݲfgv2$`Re)7Q9zMueINgp3DרHW\ HJ__arjحOaDGKę9G̙ˏ+.8E:ߥAWB*xn\JYC "kNRHsՃ%K AF紋B~o886M.-2[Km YZ7qhx{R(el$DI~'JO[A :ͣa' *a'' PTC3Ht1lPҮ$㇥(b*.+[HtmE;vBf7aiL0ut+H)Zt~t鋫B$IN_d5S6_/Ij  Tz*49DZ AI7nm_C)NunLtKBY%gJ\%)J4~ەL4BK):ME⺱TJ7Eȡ~S#؎3IhFN+ūӹS=`l I#ٜqTBMz)mq^Yc{ͦ/h!iVUnʙcj"Sr;>BPğ6T`<qXL6M7>;T?adקxu8~!:7nj؍+/AhPTvkZɺk*980(Hup5<0oϖl^Cz̻#;%v} R݅\ZGU%*eyH=QdqE=,I~ۍB@JAvPBXPx>85p6LI4,;cfJXї`o;f:ABM-mޜB_$ P 7 ca7s~@(:̽$Z&7HS] YR F1JOggS@d﹦0烱+'(% " #%&#z{}~{x!"""'$ª~;6!P\fL%#HsFKi'PtO3OO>)Lj"W <*؈NWX*@\N (B[qmuJSra^T%&tGGh¯RU^Y wA0]4:нaE3O$oLs_9,t^,]Y[,TD Dujn DafZ)3cw1ְSL4)uq#ލ`Eg+Z$W T @<L3׭ \By+_޽uե"eMacrũ=Jvw% &S\[^pDev1TK`a$AЏ殑o8;b$ñ軲hڱiFu AIYZň^Qk0 L_$h+kNԁj d8c(߂KD* $֒ n, rSNn(dc@#Z"*3lC Ǝ) i~(\3ɎND0k\t*Y^+/% Z?ėV/@j (4 2U`YpV+@t'֍a,^͞R] )I4›^/> F[#Hai0|A]YI $,X` ]!TTIZ0NUfGGGp#:88aF:͝߾sعm]V}XSKTq 8GGUՍJ vdP(OjbMn78p O&PL\+l[.<ɔLފfA\P~U8{#]|˜p}t2#sȣi!p;ր^Xd  Pf@Xƌxr/R+ )x!5 -ƨr X-;6 2/Jcňh ^ry*v@xyN#Nm&_M-a{~|OI! H LY-R m*n\Ħn^k9A 99IU}U"x)+^j\$n˷o5z%nOANHdՐʪʉnKZ^q oР"T4+v? "ͺ9˼ڄ % dۭLDJSmxPw6"=gRCyXY i 3\-׍(_./bo*֨A IL𓮮+B @#@b8P.ȑl:CIUUlcҴAE-+. ] 6n dT#"aNlG:bB^7>AE埰GډY+P>Rn&+BW/\P-X0JK h_~Lޜj)+I*O%кxj6n dH 1"ƜĮw֋YwJKAR!KK&CT&Vp##P/H> ֌Aw5 H >fT, S bcy~}ep5<88hlB~0/";e&SOӿ?Bk>Ih%'J`QM5 +B Y*L#^f:F7KƲΈJ2"wIW&6HMqDByeDI gcw,v_G1BN ]~t{Y8 C @9Їy.\7  VU^T7Vz lY,F?/l HI#"! w:;fJ,3(|!ɩ P. 3R$vT7@Udn i0ڕh_uǪyuN۲ .?.] 1 1"FDcjxNu ]LUri F ˌA  JbA0a%X: 5B8&_DQ3%adLâ%r| 'Kma4Ot*L`-5t]%T}%0 LQ(T%h>_ޕ#?x͉0ܓWSOPT#)4MF#@u#ml_ 1zOn7*~΃nL+UVH1q#0Tud W!LvU"N\vIhPi$s¶-7WbQ:]>awW~'Z}N簼zM 6 K;|( _lΤ̙~Y*^,?Qcoj!dվJ* 㙎#*w OggS@md﹦0+6;Q0#$!##" ''$$"  &(vw!  " &&Ln#2& K{(CdP/Tk&hoxg.#ca?ԴOPּiiҞo 7ـ&ۭYN8!سvY۷-[9XצVOnI,mv13\t3ևQ,+԰"F.TI$C6NdR|^/mҤԃ{&8).?%Ƞ+,eu^ }kk֜s9?Z)r|3P\?cz}9:M֍Fk`a/yYF&5vaaŸYe{êw8hPmʊt0jCJ4V~uNa<,ݥy,ߣZ,qy?ϙzL<=|+?_Dr&Xp~|̤AelSJᆹ\{6uG<&^gm|x8;'N(/vyйbs7%9% 릁<;hվҬ6rLTh3(h>/V*+.;aLVT?ʲVQo Q2 (&$!DJg " !<:4FzBٗdJitkG`OLGqd{io*\!+Fe;0(!8` ^8uPqrlj^hd)aq#+L2Rrrejz3[}q,k~ m3P1h#k@AkPہ+oHĬظ{:.Uq ?tҿ~ڷ˭11aYc\ CdXԩ,m@M0NJHHhlE>VycԦiA8p@Rj6y v&خh4w.C=(Awх)aEqH0ҥP&[ LU=)RCMZ6P*\[Nʾ`=`:}ZToC5]]\YE0db` fS~Ub\]7֗ȩ_X Yu;ƤT.TQ4H*VP.ᆕ\qRVkz$MJB*bRmy]8a9oJ(DUjʩ5O76 qSuݽ. \UadsU0Os} _'7VIU ;\_ RYXpV wՕ'0\[۰_|&vJjz^X2:Ew T#~"3Y\,bi`reJʒKNjic8SX0S{" ~$]5UL !"X'ۢW83x?<} :gXyI@$ hc`A|]Dd:$! ?ʈM_zt@2Ŀ %*`0&$tlHmfJ5͝p,{o,øK<+nc?T&Z@P >hvT7,!*v8,LGRdXy~neH\F%ύiP󣪅*i-LK)5gg9;<1}MT<,< rb$J2 D nnFH9P_Zxރ ^`M#t 7kNPa`s#Bg%BȌeu쩣^n[fl` ,xC\G컥nZzH>̩awh+uR5H'qJ6iEB~@B}TP,Zpȡ L]ë n}Nj}vOd7TIgjTS8q ɜ%qS.Pl3MF~8CU*@'F1ϥ\l4rcNCdOR P FM<(Z 4>ln^CJ zĸcՃs\ႢE(xO4 2xy=jK&M'Ά["c:*Xh`7 &b`=` ѝA $$+T]D5ѹ)H;o X0MOI=[`@q)[4f+̬)N'P G@'8<-.>X."p#_ &(( cbEnD@@D;6Dz5Nz)doJ.<U|jq:@J$HD^%o] kVw_'\\_6@2n ,P@AGinFKnBDX>VfCTY@te gǻO7-zA*,XEK = LW-W]ho>?\$6#{wSz bK,Ot6_i=K$ĠKLUb Qv}w}p! QtdY`Pˏ%}euvjq(4($eDS\( ciǿ<#\֦ǟAdDEd]fP?݂wJtĔ?-R/T[Ӗ0m};W(UOoM<&{f)%7k)-!A)|DDYuBL2e|{lQ5eضӳ^2qez|g fH/c.&U&B #jBcJ+k(/Š]Wvw+lR?QNl> ARvP..Ij0!tz*P@C.6|\æV8D$SW.=PRHB-.J"BdtD[OS=P2(KTD*-&Gp{Д"`ŋ Dhy|SI[)·SR)`raBP"$jmС!Ŵ$@hܪnE0Д [ΤlY ;o"K >o*ĝiID) ^|.1\BS))D{\Y@F t v]Dzp֠k Bd3!b4=?u^bIsN:i7Wvfy;u}ǰy$[ Ĥ[ ,!|\`gp0pJj|OGHpEL΁4Y԰$=!/$7)!ZÙp !JjVp?{[ ":M%Ä]*-) r#߈p#t@ j#4E|B!UZ"i%6iCDB1_4˿`(hita\=|$1&jJnظaoQ .eL@vXA(ȱS-C@G`q ڇ#;2VRo>^j+~fQm_zLJG`!fk:R闓"m:I:~[˽|voM]Bm$t[tnN]h0MB@3R"cq*  qa<n ô c^u VM [abB RV,&$&R( BEOO/MbӍ=kD# q( ȍcP Pd0m H8X#hw hS }DH.&On2VBOggSd﹦0-eK0$ %&$&|! ! &$#$ " #%{~|^6Lq p >O͍ D2.+n=,lԄ"F MWS,т:W .. 6Mm?C]'ǁ_@UPPZb[Pc7ay`:Շ} ?knla1jǵlKGcȍ_'Rݪ\S4% їW/KFpLWU 52_5Hy պ#VxԜXj8\8BV 5ZPERmTZTWOV8Ck)-5 sfe4"cIYrU){tUhem'NZߞoڽs:.-겫XSBgUP X|w97Y:QCȒ,nB0K60TA,s> PQi\]OD=^N|\,PBqq aA`).nLK@x>: , P* ZAuW-. UHI" v:pAx:݋~$9ÐI$!@"0-"X>в8hUp*@772Brő 5țUA ꁧI5; @,`m`pYNTW+ic{zhM}bHuV"X\Y<6_>my2xFJDQ†vU`*4^7'ڞ3(M *먆$L]"6}Omnƺj*DW8+RpE/U!w-W[2LY"  _H=؃1LŻ٢d½PJTWd*YN >KvgB77bDqI\_srX'b&5o;gޥAoX+ZKFR7cJ ax~NdNb\WZҏ8k])K)DƮfK$#i \k1^J2lo:~wq`(n>GuPltx) )hFu2"5Xbai~^"rBSX24c$9),݅XмBv _d?$UخA&("|eS6p@x4Tls&dsUm5lBǟV ,OuiasNMalٗQ%{`D%@^yP.(n74h31)B}k3N~+>vk#*%ƨo2ufY'ӵ>b+?|5SX,b$8 ?3 >{%1@@ cb*R򟦔ZL\ZՆۣ?w"ÐaՀCSx{~h>O50 H`D+$!EBr߮FU6IŵxB{^J ,YJfh,|9<ܛ%IrƸɻ>. $<_pj^\*A$kqn>Ύ6rO5=6/I*=yvo=8LM5;ܖ1ѺL=dnh~YjlӠ N 9FU;NGnDb؊S$\z\e8z0.`>h̜~DP[AP1RHأcq(Ӡ"q@"%ܨ\`-R`am d%TuϟQQT+4Ps Q0EF^\6t/hsYTqBu`0x\,gd,n/-'6K*sw=1uLKzIC3:^<XTcҐ6mc9k37^{ Y),_۞EZ"2["^\ i Rshph:ZЅ20QcK901`dmGm[J3e QQF DA$Bֈ 7$v>( KIv;uʗTg>V]% ddTZ LA2ȐYYJdyAbJK)'M*Mbx.ʵu>36;nt SiJ@pYX @xÊv4:}B@LIBn ($5H Ƙɽ,p@<NsaܠH4f1N 1#VŶq9yRrʺ1 /!"YQV(J{/τpsbH( D# I6NFdݎޔ 4"UV}!sJVBdp!6-n!Wx y1hBsU]R~j(S)u Qo7fUu+T4BD 6깂OggS@Ce﹦0P^%~|t&'$"% !!)#ۥZ:)$ _nNDHF-,<`6=Ylͣo}ލӳv b,fQw˵HD3 Y7TЛ!K&* [G[*# ܊@Xps> ޳_L% w+0e(a#,X9[|lu{?|1M+G!X,Kpm@J,*^ mP7fQ@A-b~ehg5+;zJQ(+YdRu5xH7K'nx;%dVEq%p )B!PWuP#cz?XqSto@^Afdj`J%F$"\vYZDt`a+ɲtd.vfݝ]1}3io2͓fcI6fPl"MYngQU@tMHVl&擽xu[q[(juq!*Ks>Ka-> -h@nn%#=< +5a2N)bJ#j¹LwB'k%.a_K殣hL)]]PWLfuExTVD\. ]~l6)4]cFDB7I-IB55liZ P$)#rR-MRugݺ{H"4*N<*͡kRS:sJ`X% f`SjXn~,VLӘ۵;'H#Dr43e`2 $Bas IƢdIfΤo?V *B`ṭ~. x<V& BXh@fD&9yЧKP 0~X&5"Dބi$7jSuƹS Aa$A451=\'~]ü&۪K NOL)GΛ0)V^9R7 ED\(qV!7G'R 7m9}p8TAHA^|kMhȹF%,/?IkYQ#]bZd`e$D D-Bx. ;,wt~k$eI$-("wr`A iDl4ayPpy|Α,n\.1fcPrIpq3=] ia֠HH$B #_~ot̐%ͷc_/y|) :Y`lJC` FN*25/~:D &D%;6gC:w: !_1*l皙G+s()0 R,=דCI{s}u̯KON 쏔}J!=H9 YR%ĤИ& N `A$$8wف_T[-Y<\y)6PJT[%J $e~hhlaՕ%@{|6`4جsx5֝E@m+f>2V OIVߞ?qg_ ɡRr(C}$Q,JZtX\=_,L͖veh٩c h ;$g/'DvG@#Dc3:?\|l1~7?ڨAg(G_t u6 C3V 9\ޜJE%?c]#D| @ ~Tp(X)GD6/գlTRjzv6&Ni>plFrtsizmI >K8 [?6;e*cV QJ9By䄺L M So7dwٲBE4X!@Òsj--ð ? '|jGs>o\K MΟK9^`rX*>LIgD/6Ē`@Lm,u{%QYP?B'@2dE`Q§G+6Pq@ L8vv\r~,K mF+2CzQT)UF !|0-lGx彯_=~y5jTeJ#? 8E@?$5 @T P/KCA37rD@ s'µ ~5BQk\װ!oflNJx 0EJ6 T!assLѼj>cX²@Cn䀫зԀ3Qe \zjm@ 4(݆DD9euQ$ }zKЛh:kj_WPqAUZ!t/^jP87C$S@Vr38-iL_M[+9L<] \YS5@|;)덤YjMTW8Ҥb?r-@[lws:HTѴ-tDU"طk\WqW|oM"j(\]=(Kcv^Sjx}}Nj2nlaN]=]*SKy(4V쎐vGG[6QFP!zTeNn5SsaZ=_mݮempdVz[6{|zQ4fGĂK._kȠ+KLo~ ߡkˣ*g&I*/UŁ{׍}wyr Y]]|0/8qʦ\}`ak9Ks͕P\M[J)OggSe﹦0!0""""#"!'&" !"!'(###!$(('%$"#~@ju+NA%(8tu`E~jMNtyݯJ4h,J[PR̐>gYwxR'1ZͻZ4m®47j RV=6]wՠ9u5j{k;rwyPϒƍ&2qukLbv,.  _U\~Tdn߰~ SO>>sxK}EyGě2˗Y^l9Mk>l]阺)sik |ݣZ>\rj%{Z]E!vk~IETI@:4!`qkKgSM9ȘŵX0U6sc̏=H_tX#/kC#ztWc+E7]׍/ RI *Ԇhc. s^~?mӗ_ggT)?ˑd]MUK?QVyRNA0H_֧ZÁJ\#[,)Ýb/x>NKPWcҁBbP~DjI %֎L09 G5^5Dz~FM#GGNV5=AXw:vǁШ~<9eRĤUO}# Cmi^~R[jv1n{C<~6g2Xo7_Ze|B9,g}]VeQPԄyYQq#6Q7 |diFCo"s/u8ZOGéH8IOU}D%hVab(z>%,v<+S3>orl/ sGo`V>)-Z15^-cS2l?V?kv~8T*K MC?E+vfQ?'sZ,k6HLrUJY{t3mq,}{?HIp &^^%>ߘbN?;(_n^j=>oNAP$ByA@~Vta6 fD߁54ߩXw~=`XG-sGt!EJZ+s^۬Mp/v<|W~D|Oz:3:lϑaWʑ:3[O?-% v⧜sai{P7Ps!Ƙג[T nh}xlhƪUM_DUYvUxM_`x'!#ӆR|*LD̩)~*/zo~ǰEhj \WMT&,_<_)*y/\DOÛϺch HzMBJ|jJޔX\STwغ\YY"*g@c@>^dA2v_)r(Y+jD=pl]SQkeB;6i0 ] (Mn9VuB\ĶE88mbH}⋰ycuT'N9AX}, ?>  |w7f`7b yBTqaGLYh{Hav8gL L^hdYN`Vh'WKH;1`wF7,+FDQ!nUՋ4ΩqK`j0p|Fof9 ,U#)?:ظVܞer9vLW=) 6bHPO_wc:0=ŭ+LW+|eoAhwey% ʯ׆T[k A2MXpp⺜Dꘅ۩+ Fl] `YnK/k45v:[׳ߏHwϤ{&Ҧa*l'bQ5[^p7/=ns:'C_v98,4-{e/ j*Iq#đjI;SrB4׾+'eWD- i_5X6 7k0D}vHG"oGC2H<T/ @'f"d$$H}S5_)?E$LPF7-UDAus 1ӣ-X_'Sy#LEs(3sTpfcBܳ]A!xHroF*4HMډ=;R`t+QeE#`!-x*oNyQlĐPUcrd R߭s%y`4>3O< @$moӧ')2@/!#QͺT[ne@'OBAcN(C"[f݈0%W6*`"/Ż.|~vʩ\(JsV0!vAszN;x<NP1b1j~*jD;0ʷeJ@A ,W|9nHus }]/8jI<5Gl21:S6f;1h[UʲaEBے{Y[N0[=ww$"Fb\sK{^gZ՘6KGp*%|Ik|ڝ1PŢ~ebII8ʂBVat´x\ېS86:|8TΧgotZt66|kWQԕ[mԯ)\0pU8dK h+Ԃe]2䭳}64OggSe﹦0_ 57"!)$'""!!"'&~#%# (%&)&! ! !%%Ù#%# !%$$Ty6V+{6sݮ=b&p+QL*madwY;݅26'T!p6_M_4"m痀GI"LDפGlh ^J8nc\U>jrHX*  %ݐdL٠+[{W.2=ޥ#Φ_ET,Y_.bMk[tn:uψ <ӎ{_ِep~L; ͝dT \!U6xyINsp])kWA \Wl2/[pcT׸g_fLWduhƵ\l\#:aZ/zF ڛnAYk^utc *s`\eT?9ߓlk畹Ѕ\?; v>}^wNkw^v,%2$id8Ƚ;C5IJ0n L <', !JG"*l;l V&_^=]ވ{ZD@ l`:~4qJ{AȐOSU#E"wNϾI e:‹EyZ틃ѠvډJLw䆩=f%;IpNtT%mseձbd:BuS tR9Q\\X?ֺ ެb1ՀϻXB(0y0j'@ZF"{$e{m&OGŒb5ةBzp'X Ф2 ݿ06^osA+GeENpjtpg";z9°k^ܴ#DG1<|Ip*+p$JDĨ$(Ꮓ_єs>:|t꼨֥=!}pb;D \;[q 6C*th$^l}ZA/keR@䲂,dlkx|N(Qt$0BEǃy/?[ci}!ĉv0/swBXѮDK#a:o9v3$WT19vxTшV1[I1V!41;QWל:ɸqr - >mJmm;#]TAJn8^60:1bb|.gRy4=.ϧ0x$:>G"@Sxkn- q, [Fޯi^(dC'_kDu~-p|q sέ'qr G# WСFԱDTɻ'u+dSܪ ^KAJ/ 5,eA»t(1WgoO]<%kߛWWN0^<# \ Ih?e M 69#l;/PnE?#qykgcfjk>ӝ'+FzcL!Q\V _3cILa^VVF""e~IV?. =~ iYq[^@ NK)Y f*LzoyW%{Kv$zTڏzDB$uy1eaFU|Pki9 p$#}'rZ%)^?Q*o2F:v5MGCY$IZ18nlŏ㹍-L5vSyO~8>.q_vR-$y]\˫|wd['*goiޟ@ä$te\Y3j_m]=xgqWmp\ \Y7qBjֻˢ] nN .LY?h"7σiWy}UV=A\W ھX { eJ(\Y*:vql=uooucZTcà H7W%ގvh5v m _,>Pv+aURD!Ĝ~!guEi_RqNhfnN<).4BНCo4&T yYbt b>fӝFۍҞ_XWgd9_ǢN=8yɬ7#Ǔɓd-%8'׷P'5x]'ORaK'R|LKVOf'`k8/$sv's$M1V.l15IYef.7A}Ġ G[д8T = )T%HqgFY]6TȒ @ %|ޚer0>ލ;;#gSY!?""yb܎FGM;W/c3Fv\Wyb֘ovMS" Im=&P$%T^mZ `4`I H`B5gO£9,VP@kYDktV b^: f:A?r>x2'֎bZ*M_<|${O*_w~\ܥP-qF]#|.P !I$=wdtf2@}!M;P2KfQ Q(+_ !l տڏïvx#˯pgm0]zRqN+ TߖS6 CV .B "O7*ruNecLLڼٹ0t˘R= N.oIcP!e ~JH&j!|HP\i F,Qaڥ&RrUQH$v Z%t}fo?8}׵&O1^e&Ɵ^q])m_up5K+h^j.>KMpesD(٦`]ɂ3\OggShf﹦0~ĦC,}.ISeX!>4*FU'"ri) 9qø={9CTAsi@ LãCJʾP]6]~ E2 +NPOwh{u%+P%m6"qX]X= i߮wE^oDd| |<_lz<Im޾sZ1@ b$U}1Ztj瞹:U>yX2Ċ A2pn%ctx.*߲?7gi~+f$;a^r"zzca܍(*_(*@@A4ܞukĶtN| 5vI<۾~A9i3λ>S~{cvs6KnnJ책ݬj)vl' 8U0LO 1G:>4-LNL>rf rUuXۥvO"l1y_xk}̷rE3CxzߦPN|.#[?.PpSu#,3#-!s1 bTl^SJ@v'ODD8jZfickI}~mr(2罆Ǩ_yt卲%ڇ~qzIQܢ77FZ{Y(_o '*C 0M %#>i?%k!4 癐}OUODP}g+ug^éudxi-Aŷ$Fd @ jk4%!k\*mjl5$ǖZ.I <Mp k@ev1X`DJrtsnu:ϯ'4Jlmk. tJs'.w(_)ͺ:ϟγ7/ڹs|m~oy=ӯV]ȹkWzijP[lEޛ-I@r հHDTTC?U%~}ge6:Ex "+iVzbݍ]aEJxYWхR"Z_ZydGDMn -"DhWwi>Q><S`@>J?4|zZB?_c +gHQa4;+j!`]$j;ml|A|l"2PzCmqV 8${ ksӔulhya D`GEFR%te,p1ȅJQ9:F#ZݖL\x8'|SP&>l}tdP[vBЇAl \5K%RM0Nwc#l?ou. *8zl~˩zF׹vhƛ]qڶ;7= ;Je]* u5<Q@DLE:V!ٰ,RTχѵ,sg9Í׻A`~W$`ӡiOJԨ|0U3d &_'fmﹾl`Σs]6n_+=F|r~*Ϡss'7?/iaBUTQ^C[% %yx&ip,>RA!5 3&,%k"XQT!N mIYt=5,v`:@mEԼp#qG_&8 a) ?+<+~|ֱ ϧqZӊϞEBd VP\"Uǩ@YCIC% eX:d&0qRl7fq]{HI燪 P:j d\>;L NlxwI ZH hu؂plN̠FĈn55u]. nMs [V lP diYRXQzY \ r{)MKRpV' 0  &|" -D*O \\K!K{c+V5^0BJqxQsLMbZ20,(aH)#B`{}{,r5%]ݦi n-ll `x'+ 3 y05_>X"+֞ c'5 e EI) i ۈGd4p-/'(O[=UX_4py,X9t*`X n]_ZGgt7& _ra0`P$2"aZN8 #Ȉbsܴm6~,3 P[Si9h ، D}`~`~B ƈN"!{ƺ0 c+6 "IDP(q9z34y.5ݥ¾lk:ʽq9ᖗsJ@cs'8K \l9M`ZyP=GQ~n.!R!>58݅?l;.le0A` H$4 ,jQea#,w=ދW0<4J~Ip(*$ *8((GP@:AȗvS5uܨGtr6M,@P& ! "I($Y)O5S>ə6y:{"Qp Z$Yw=k[lTlF3ۀ ;]x؂`YKځnM9Y5;Ї`9Ë% A BHIH S .`}#OKs IAKD E;qVh1(7@1ML<'@`"Kv,Q@\ݖ%(@A:RN J8MxB A(Ӈ$ɲuWmglv=InC/jR^ދ) J`wLE9XF6z4Sb%Ȉ,<;?(ދf+~i8dٲ ЗyZ)ɔd%u~C˱+?OM0@ZP4 WA`Ub72uCy )H?5@"^{iEAKqg{T$yjx)E2ED D$`!F=XWᶑaw&x(@_POH gal 0F*@Ўpjl@W #X",[6Ȭʠ_YALN=~ 8l0l@)&$Ew[ QjʂfpPc$ڄMZ0dZ)}@E,1 >>7OggSf﹦0J~;(&%}~!!##" *&{}~*f,A$pc *L8>]v]ЀP$ "7$x6=}^6v"`;9% AHj8T. i FΩ"̠D[ 0JpK`>;6?2 W?+6i2,f0~] 2L.OP:@ VWѯ@n -PM&L)C!F73H@:AV'P >~U[vl, E_j f}*-kJxԬH#RKbC-uCY׀~>؋NUx.6R *H J`Fi*de@ۗx8EF >;Xd6co4Ln~f/L2!]Eaaic Bho&㦭VdUjq/ļBROӗf'P 0H: &X#Dvx w[h0œp#*6FZȌڠ%\c~e.ws-B2I$B HCx eÁvqJc@Ɠ pN wn J7H0ȼ0%vvqc% 6f0gDM PfۥCJ`?6.ZV $&j{n4 Z_W }GY⷟n!l<g @,'u7 (pZBPa\ D;܌HX.LS8T/VY;髄B]E*DUiD6\ո_Y/S1Sm]5-DURvwW犝JQ9oYZLQK*X㴏FA`~8I٪$sRﯜ<'.(Q"4c\zp;*iVJn:$8bd4 Պ2@5;Tws@7qwipܓbXPF+ÀT"D^kjM}mXȿH?5"%Ui1ţnFҝiʽuUSc~Ȱ(\OP3T%Ft YO pET伞\$lX` " AzHM@Mui.HJ,gc\YK1OOkl|%1Zzف0&(zWyZRͷ F)_j%E\Ә03^uZɓqÔ 満8xARD/uŤEj %1Ogwvm ރdPcG7zw~미`eڋ*x 32X~6rGՐ*gdž*x_'\}HH)uiswj1Tp[n_),B`s@Ė]w9no +cE*Dە!h8-0s&d7x"<C"ǘHḇ!{P ]r)>UrܵHJ `h s/sx B + @$ZH(S6vMcV!ե~ݞs1A6%|-Ʋr(}ۿ"=a*3PB2ȉӖPPe@|_ˍIB - $"p ]dܥ*5!î/8\͸u=e :,*F`pLsֲZff^~L41h}=3C:[ | @+o8B$*&I]Lm@镤H%BX\8W}?!R}؈_^ͼŋUP$'(:kK<ٺOT_V0Ϳް=Y*LOͮk(޾>^\(B\QpTST i~ˡkJwk@uj[a TU(*n'@PR 9! DYڨh>Q>\IV[s֬%1*d@T(^jG``[ߧLJ݊ooJ\_1|#@o _'m~2ENTdPF_3(8NJ~i2QYdJ:b"JTHI:׺Tӟ d+ka#iIO;y-j:Gi҄ء[gGmܱ0RкPfs=1K$uFP jdA9s bnqO^ϻuZhE&!ToJZY^xSH "h)ѣ D`AKci˞i%`]őՖ(U1NRؑ&rۙZ>peܪ#'O0}٪iYw  DW8BĔ {637g "|soe *=9\' pZ1YcN'YdtqO.SnZ@ n|*@nGPс5.w%T#"ul]f')P`򄧡Y5 "$SDX;8\?ϊ{~(иC }4Be5~vTDYܡ T#ؗ ~Vx@B +pU4 Rm\p(EG$/Kl]- ~+ֻ`a( :u@.Z(b&ip䲲$MI݁W>jcJUE5ǫA 8\pZ ^5til3ݒ=zQ\PzƋCUH84 Mg4g@!^R-@1z|AչXm? {rR4IPӀ* -Ip^5x}rˑq?f$f8HC) <\2P܁{8=( *@sF2`aplr}6PS /<Pjۥк(ѬRY+`eD̖5u7e|F_>Dٗ^Kc;z Ūyu5<@_`~@AA8,f(O"` ŕ :3b bȍN ER>WT5lɼDy%'wɉE)c8iD<긯F5V./y(Q,FJ,n,Fe/o#bx! 7qjPH(DVЧN;lb\rSNKpCfd~I#6?;[^nVAJ2[_aé\ڹWVHYFuA^Uf%ۂ"H7y %pY?* ~k6Dh&!P"4)Q6~sj.ɓ7l_A[84R.X vtB.RbJ3_;#np8D9ЬZ.:舋e3 \WrIe0>6jR(?%"⻴jڣ! njh H3T6hPpی5_a >$E3#E{n!ƚQ-:"'iOggS^g﹦0 ~x}~x|ehÝݓ0*6`r*t"8CU"QgoFGo}w"l/{ ؒ6v?V7.V3Raw/+yfYwcZ"33*FEZ~b21 {uI1/'"D/|ݩ57}Sѷ1_3Xc_nE`d/H8pI'*n\.1 4_RCTޫIx-xX'm=`qV,s1Ę0HK #R7~>[:ˡqBJ@0iTԆ10,nb](2[<"6 @Lw(n鑿FZL@9J)`!5Kt=MR"Z~:a^O"广% @Ϭl]p6(3 ]Ah)>~r>K)1o!ImͩPp&;,a FgC+0 `Z~ۮS! Am}*j8HODX=_vN/l7xiZm! xv,?7Y?J+@%S`Zw$D?f b(%~^퓁9w<fl>O.̪juLEUbЋp 6M:ƘWlΉTtC8,2<@ &+&5G.&kT5*+*Gd~tõ`*_#Y;Ek2ITb8=92S Q^ӑOnL|uG:ߕBм! ػRCdE&TZFvJAkZ`ARA\4=kƥ B.>[bLGrs.hcéqլp"Q(Q`>_l ׆qӛh?+5 @YZ4` 5 O 7 G+X ъ `obfH:ܴ694 WdFxZl(YQHDDu{K$VUm rStB0~ H~ 50\P+R\yj1 "|˫q#[ᔽhIPGetSU5"b"""umwz̻#? VW_='*QNCcB 6*͡U!T=!.`%6Y7#+QM҄[Hޛ>b.b>x`%ψ(@®O++bc{WܮN s"ꊷ^?9 &su`,se%yBM*nފR@^H0t5jrcpkA4e*/?b""L|êQƒ9?_{Ҁ}m]1mCL'xYLjy1@ D */SjSqPJA2nLaJe^+NrkxDr ђSJqU%7}~`teC싷7D@Y*>oB (+zF@oDfXM+"u>($j>pdHGer 9XV7 ǻ*^E*Yr.BGDwA7i+3:k8iiakHQrrv  \yp=:?r`oъDdLlVvhAqI>ʕ^ IؼwTbŭJ>ޕG0q$ ߂q*}nBؾS lӚ 5^N)Teq1amdH%U=Bu*T9 km \@ {8$J'@~^l/N+[:V׻6n $mkԁG:KuzSX7A]Ԩf~ iEiMqu9@ P,إ{mͤ#nE.q_ p{8-r]Ym?3s߼ g? "%#0EL%Y>M߿nw#J{;\E!h.gD R-cQ[.21x:%37n]1CJD`nڻչ-`xұKSEE@_&PQ`C jZص,\#F"J?}`1&mA% # fi˄._M v>_yO {KF0xӻ[շU{ɡ[=mn 3 ]Zg+ .ȔƮKX- ˪ *Nt冁+]{R_| gBît8Mg{o%O7^C5I[zN+ Ѡ<KUJY\nU{A-ۊn 0kFJ89rJw6"Q?@dg,^eKo@*8)ZY G|B?T>(M};u%)5KT71Y)YA$;`lS,-⍑u.rTx%Qdqa7c9]NuI*` 6ŞZia ŜoXT'6ņ+ׇq o #4@Yʰ[~J DwqO5(S): a^{+p%_leҠas0Ϡnϵs>(gq>:Ki1kѿ|q=\h,H60cUX4AX~]|y;q EtuA~'e<%@-A0pa'A("#S_V,;[VTIc>+Nr(Ni-y-HgzbZq @afdܜŅo⼃{Z0i# \݀L=캯iP ,*Xj& kS Ucc5N?uuO7G)TRH1G[^K2PKn0/f@΅$ }رCgoIhugݽ׮)킱?QAꍮKAyFnvl{LXIR.Bimѭ^  ,f u/駉|6BZ?r=07Сšjz3X哯cڧ kj Soh>W$,agBFEIAQ@F>fۦ2 V ͧcO٠O d n#@^S)=\խu&_puwbR؁Bn=AJVKJA nvU}^W|KI@QDAyS@:. BAK1,ˁ[x,9'J4Ab߰>>P.fSP̎ ^R ,zȰ:v=BiHumѰ@+>3OV~k6^09l<_0n!E1U$(  .x%xp !C \BS2"zot~wn\M[?\JhZ۹7]1S5`I9: !87/7~;c3CJ/cQ=.ǭ5VSc7b r޿`K^6nǣD[)z9 jx-ͳ7~pp|hK;kEǧY!Uh@/`aT.-vכ ;]ȻzJ>8/%ꂅJl2`]t[bPl%zXUqJ|L^_4X̃ #\p{Z6lD ĝj <&k޺i%+>ϭm_ʈ뮽EDb+ZU"`<,R =|Ƒ >nLF/aI_"W ]Ze&Ղ3E{Fh 6CszSri[wK!(%>pfݪIAڿ!:cX0Xw\Mz kk35 Wɡxjbr8z1[?87q_44)6> +B; #]ChАϚ~ot\,zTHWb)+17Ӊ`ƥW6Y.Ha@un:=BKcY %z՝b"nC|k3oT'F"gmP`IxOgӮgDDϟ^-stUG N[-|8Skqظj'{L%ƘlȷwƛF`F]ޱ V>:?NٯH1RRP-eai MxN #xh"u"*OuO4ijpz qƄXmvu{;^V^YnŗJL ha@X<3Lt4-]J,k"+(.*ml }|4\?%J!>y"@dpQunfTI'9$'L'zP+`I*@ j/qĔouK^X#XDZ%(2 pIphjų9"c2H `L gO)~a)?N&fhޢЈ`)1n,vlALӃ9H0"AX^Gm()ֈ emkV #uG! 8EAPopՙJ~^̜&&mjKZ"/?'Fx#SgOq_Vq߫dޯ*Iș*ZTL&<ܮ/ܝX=cSlf ^n{yR1(|%zX TJkL sg9bh p1{ \z#in,p)̲7~V_Ja#"Y;F)@3F9<$e5b!Zm鑿XKQfyVCX,nSzn͵h!4{:bdP 38]o/4>'ǻ\$ b@u,K@nLG]_:Ŧ%u#$bHѕIԃվ5#[CRuF19xaJɊ ".J.l;'ڭ$ ?[8*IgDufԃm2FU $DDvVOֻ/e!Od Yn w_#e&GݮՉ:KR;& jD-z ` Ir `(&נ=I ,SƧ8+|h"">P4XI^=D}iD 6M@|Vڐ.n2r 115CSMN1҄ܐLb'h'7S5c"(W^=KQY/{DZ͜Oﺲ{_vR:_~W8>S*S 9~&㣽k|jB}3/RwgwhHBí5Qt@HQ= +_TM fP,&m|5.LO4`WW v9{Kz Rr׀WO|ׯz1^qVNK-K{\ݿw x5m0`j |mC?;)tX宜"Ebԋ9&c 4Y1L@' `kn^ )%J\cy ڎ>qI&7\>>Di JWfRJ xS"FlUR^){m5ӹKY+,A z˺ǧ+>ڑS>km03W>MR}Hv'Bwry_~>c#K'ƒc\d|^kIQk%Ee S#;[XS#jt5$=c˕0sl`P?MD^E잟LuWk31;&>5@SKf{]@t  pWMP҃&jCfPc-" h\ \7vh$?"ngˋ weW|锈3%VW}^e4Gyw~3"ⓛ)Ld^OX2:׶% "T\8F޵brdV͍1܄ hTR bÆΫݙqsE^Wtg=tϟ=x◳qGJppOٍg-"Wb\Dpa~ z@S5LggT)%""wp'q2p8=ۛ?87|hfpM_ȶcƪ~w)Uk.0( B5%֪i*D# kofڭH*$bbk=K[TCPQIS#FiJdGO]n6NrHx}XhW-vz!B^ɭ$^ n(7}}-j!VT jkQ F_7T*SˆVR*\qfb?t_y3òI>*{ +eV kf˶\nNfzshN1W~K,WtxA4| ઄Ҵ~E' ^ ⶤV\oç9EONx,UggMϯ[htio1G{`NZAX70({snoXEAydMHx.u%F*YPv+}//j8y쉤C><ov\O<=-K5zSok_[O(1sM{B>ydf~`(IuGIV NI})\ukAjF.Ǵ(j5\InO0t\9e\*ZHg?x?æ d(f5byrV :Zc<."ncKʬ;.܍ ![ׄ[k0sː-+RJ|䝅׼B ^`"OggSBh﹦0;a>=Ӗb63~` BO{r+~*ޢ 9}W/iBN54z0ա͒)Zinzk#Txu LPP+X">̲>ʭl 5 \OMi56ap: @k}}=wڶg||hzja]vݤns0zF g[/FlZ%[qڇ #@ !"z RCAwLhv^@ݚԖoGچ*?x{qnu6U=¨k7Ql3B c0c'#PZHdt_c48[b(5W -b:#!v %W:k.VU)6=ڋCs,"@ċ@՟~ӲjæCP?k6=ct ^UK7Xj|pZDkRD|{t(#5rUy? 08cBv [u.GJ744*hDLL}4R41RsE̍΍zy7UY%BXnPR H;@q^ʭrb{V[8'0ϿnVg"_~s,:-D+DĜCoViŔ1fެF% *`T3v,?Ik%{DSk(f\_`|LmHeth}i$>O @? x7]~˰~.A#svb}A 1xY|c" l+\eܺ)brC>u1TJ^PZ75(‵*c9? D˝%v--5^-h0i>j(P>(oja?-owbe.t.|[B5 5uӲol~*k}gk8|!SS5׺HXҍah.VA~BW~ 6'pʝh._=ۨ(:+^&л]7;ѶW{]pxx0b4ίhcOFX Ia_r3lౄ[k W` a1ˢc]#,+>IBEB#i" lΏn'.+7XWb4AJ!{Sf(Gy ~ʝ6d6Ĵr U\}H6^89U dNB`qg'ow}8+U?hhYHg@w vYB!'F*#:RF`-ajq 7|yutk4*!!l *,P+ mQKlO??cM?:ωRܛJ w:̧Kޝ&~Isp%Ӿq1Apk<^M-hW] pu[RzeҩL  G,`aU΂" q\^5`5 (|~_w(8`?{9TjsvxE:gx !JX5*yi+ T %t8ujWfB+v*SRF1YH k\TTTGEM%no*wP$F<`Jd][7Q׿4{}8Wo 1.K4z~j3^l-ӭb 0>bq3R|xg}j7b*o(ŧp!W#u`-"" -ӂ[5|^T}~O'"%{v?Fnrn>g?-XuZ&JEPJAF:Ih9̨J mp tx'c&@K0BP;ZDb D%ʝ=LprEV紨?%~-޾=O^}]ϟHtaI;DŽZo H-cWjs3Zvjrԍxdr7QE'0=\jDW`x$X.]-v&y(wVL@x Oî\'?|xuc4\w 9+5ִy_mZa9v{G=j|^G\;|zO,P*kD.>ʭ&*I^Ay>oFu kpQk7Im,g6ߜK).I @ dO]׸gjub;L)0!]vW'>6+țo>ReΧ:+lt?ue#_VnWv|IQ-*-H?C@CF Oz-[k؉3bulo!Bφ%gH VoIrVd}T1{H aFC-Ec8'VjY!Fӥ:;>r$2`Mf&kDK&^I2sOϽx|2v.~/3X֧c"(SN:h; jXQ; eeY&^"XWbB CAIdts+d/blO[: reشf+OggSh﹦0UWʝҥI-%pʝ=Tf#˻t;k|3Ie)NF_,F\{LFmSFJx`'r=5쿠 KJj5TVÚK1ޏTc AFMi7ed맄7-xZ(Qâ ɭɀ|^7.2xy7]))ҕ6q7/zw}F|YG8n( :@8 „8VLMbi,ӖO* kNq`e#rAt6^WZ qhWSwf9PlQT,h ɭz6"=oX4<.pybsyWV8zXV $9Rc w=#T{'Z0b-߆Z3SCN&ֽe\kbB" rM1 |&1LEtǨj>p[4qIQ1n9-^}=N/D/DZS+Dzy u s TQHI߈X$*p( ݊z%G]՘"A-5ZIh S(߉ >iWO>m]=oS/pwxV7:p&onv1 xV|3;uaM٩ulo_IɭSb|~`|?`/)׷{!OVBN}yO[܊%*6g+:{eњ]{zQ/FϬTοU+J Ζi,4=dLEԈk$ɭA|%B%7e>^>j:mv}S"Q-uyn$~훼pRCIՠӦvT-XZeH)>YNU q %ke5CH.1j5 R# S: ^2qICdW{ɇOA\a ЧRHH@~MŁ\#*7/*v&<O'uÏ{1kht ZBkG@6VWC4{hc!m"ftJ&ޮIYκYo6/z\Bx4ӬvhkSZie$-&9|Ycʙ0/ع?,=290 V4 `lsu:߰ &R'̤R{ng+SM7nS㏻r$%g;F,+b\mE*TA>(M_i#WWL6Ǎ0>5< 슫s75Y)֮_7]6*סֺ|D  X59h}v\R(6U@Tj;N}i359~afmpGo#g '/Ocg.?ւwؗO1u6dOI*?}_Jok&UԾ2JbrƹđH'd" R,)EYT D=[rܛU nQ.$ɭfC x>_4}D8}ܷ6T/%q>p5ΈG@"Ÿ9ku=AYYz.|J\j.ؾQseaz>UۛFܣB0~GۆS(m[ɤC0O?p4.WuzGYn*zv!)tpβC&aѨY:^'-3|lpCvn'&XFTxP ۺg#uZT$Dɝ5@$W4z>cbW9N$1j'.$t~p]D/c#R)闻/IOde ޺_8)5_F;]5UםG:xO2it BYsXB'CV .ɝ%@{ p/-\?hZl^xzh]!u;ϋZRp*rE~ֈb&dVFfd4KŒP;H͍Eޘy'J= -CwerxiIü@o7lD鍍EK422QVz3 EXvKc{Nw‹I-ur+7CJ%=]I]qV\,\DT]-YKU [L6nu ri}{{|ṫիypg3rZN=GLB0pnT\ԙ$NpBȸz hZo=)\0b#aR?7`:zҖQRUU$ɝ5Enωa|h\%%Ek#'2av[bvίyO `.liip이VJ(51/·6kmU]CH* rnˏA+x༫t[:J@OggS"i﹦0CMZ2:J-聋pv Q.?.^+ݘ#H'{:[ju: prŊ4J pQN{ԖJQAݎu"1f'z(W  M-g_${  ϫxe闳nz zzfXcʛ݆;r$VG_|T\<8O}snկ:G0ʊN)v~SP QCZ8HDɝ5%{ r Oǩ9 AH׬ߧKғc)sSYX:ꊎ0j|fIk[Z럥Fcwav7LJqb# >kJj#ϟ/6޼8o/'h])֧/4=UL]w n q4@Z[F떈U5p?uTEɾQK+;wgCoXw ȭd19>"`1\We 0?=s솗߱4=t~uhV?_0q'RR {VSވkjZb~׳ezʦӠ j^XY”Z:Eس]׭iv 0\$>M4ܹBaL*ً/o<0tNF 7 תsNۊk 3[#a}Zĉ/gDqfafzm[k 2UpP>Uyu 7}rl& B~-d.J" &1<(`O?u$hxx=xϢ|Z^\w8-WTzLy{#5RS8oa>S 1qR0vU"*BpM64 DrgzMk'ũB? w~_OX}ڽw1 s/"RSްڋ/v>= jnm_Wzt4ϱVJ \ 4LaY#Jt/^ a~Myމݸi? (-xxê?){54kyRzH*yCG#6i--5.L{C(ڱsѨPwg!2\bfVmWkWzƐdâ[P~ȍo'0ɝ#MtӍJOӻ_ι2۲^q]Tۘ)2BVI=nD$_m7i h=vcޯ vIxH JHqMBݦqMB >=A#wtr&ҧpsHin-K] a?ь7JA 8t&zS:~r!ƍkz<tCJo:6#RnLo]z<8uVJKɌv Wݡa[_Z^ɝ%7g+F3  #!hn*{G~&p0{U~&έM%sem M!;鳹Dk7/5-t,MjJĐUo:x~(7컮<>ɝ% #sHnѿ+*G"99sr;~г*kfՃO] 6V uq%ib\9E#~y*<7΃ة[JV`:1N r8:,{>@nBH@~r[ xLx ^4m|$EdO~[6=q轻hzunԊI*{c115G``O~詫L,>CQZѱrG}F=^ ~ȍHV#g >4NV(&.RP4N]dO. U ~=6 m{N0_>fKftXk(*m^ZN qF~ mcۮn]/t`O'̱Kr\.?ДJlWAִ;g VA<T #YfNno^R{tPByxm'6z] jP˨: ɽ3oGh~`mc*"gkteo{+DH}K:vBKeu?vzËys0Yn,#PSeM95OtK'VMˠ 0Y@;JS* V>| oi/L9䮕nZ=6DR!U%%p&.O9[EBȝ-O7,r{$sWO &ϜC5`/eY-Z xuuW5} xU#"@ZuN-?D0+=j`.bzC7e_M0DnP;X@c~6ZSZ?Ƕx-MGgӺڞl)GH﫚+KnvŘ)VAqKo0uϐDɝ-,An2fArJq ^5G"ht$3S֏]5N2AsG_4ucD ?\+.(/{_!,/w˴6ٵlq[T\D -tI̛܀<5 gl^ ۑaXx>Xϼ+UT=L:`뀗֬3eHO$_ǤL-n -Ծݵ^b\P^70==#|(3PRBeIe% MYWޜ^wh>&@6#W{#Uy5ŷ9ڏ#ɷқً(}b+nFRbbK-pA~5t%w[ /*/7Hڽs-_ڱs?7k\- ;-]!{';?-|3C\Ur,MPTGvHD3 1$ca'XT3; lrFW(žz"x_<y}1Σ^!.x~5qRp 3v W#*菐FOH]2Ff&)M]cZe镦D)ƭt](ȝ-tgU`G+tE T+>WMxK<ʏy8nR?~mAt3dpHKfB9tZKX蟀`넘#~Ry#X \Ǖun1ƨv1D(^]%d!h3XOGn0qv.ԤK;[؛fj}搷Z mMӫANJQ΄W70:oC&?ݍ1JfxErBD>ӌhH^'gf\1zy7pʩ/B4">ukXwVߴ$-ٽoivQݺ/kv_8FofʼnCn³6\#*ڤ~Og>W}wP:eD{{VuAA֚Ap0ʹGxUws?y ~v& BrCh'ʱI#{c:>O Be ,Ti`aȝ->FF(ߑLFـӮ0~~w6>0R&3[ݻOIZ!rPIő\w A;{kpjZkb_z5 HK,/AR$B~ȝ#t dk?⁼hf(ծk0`@ӯѫ{5#3I7x# o;H]|؞kvIgge7b.jyΫcB@(P "ȝ#72܉>M ʩ+("l9xá#[h^٤yp{ WOXٲ«J% ئ5Gy劏!;r/5jBL)\I7N`JDD*.^ȝ=ޔbE?к۽; ~+"ϵDc r[{$ } :un$,y@@VDo=q{O0",|Xrrk ",2FR\$~ms&4C^q]x>J7 m݌z1ݾš1jj X' KU|(5I 7c[xLh{3w)گD7l*nz`>dSFgچagca^tCOD%C*sX=-'Ǿ1XD4l Uǟ~%7`G^A(7w.8f_myRZ/Zd7TaW\ `?{/|'q>?pj̅ơ? t2*f\)L0wCv`< z;ku qdMƼ*-1`c.Z6Fc,#VЋ+ \qPCHzjN]*5H^+H63 aqaӉۇI2$5]j|*C%~@s!0#p_ j$pۛˣfQFB EdPKB]nK$ eSF ]y#`kßܙ4Eu ?&V'X{Va]I6}[6A{Ά~ǨQ6@y֨!$u亏20Q1"٪] ^oPk@]+څ[!؀K|P (88_Di}路i[JnDd|h9 uODOd},Us'qN65`+$o+:Wf2kX,[ bLUE$Pmcfc=ΠFR|*Cʉ;jV@XV7 Kh왲yEsɘHt du4n]hCrt#S)XDdm`6*# An5T =xgV)tom+_cXujG*7@NU"DDȝ;!CSmxU~!C܏ұxpXgBiD 6;\0eԶ]߅e(8"wī5ΧUKX@VD"LsA+(Q6Pm -D8S$‹4[O<_鄖׏6_C"`+Jsnڨ򔨃w`uӪ1֎aq= mXB6[C`X99`F=3+` WƊtD?4M\|[or,7JDh[w Ӆ%;BHO}F1HI_AjOK0(4|w-tbep A">=3m ʶ"wMh"t/YWNؖ>Ux.:}Up{ۿvA6].,2%Bt_}*B` %;>x)֒6$B! ^m66]3L6/jɨrU@}ex]" \P` cgJ_ ^eRfaցXV7$_c]a  ]; (a1ܥx<scLH|>{Fh[>o?ݯj.ñ7زEao?L>8c^C"й|[H<ϲMZ@dI?PpD0(ȝ#f2 63&ey #OCLP2@pvym#ґwrn5ަ{q+I鋌GFBMO-SnRY{kzQB"B%OggS"j﹦0 j"|}~xxwzy}kpzw|twtww{|wsqwzswn]H&2ȝ3i fܩkBZl1z\8+σu/aZ5 &(%F"e!y *D,>ȝݳ.iܣ<]8xN'B"i1&}OH,^/zEz{V{.f[ H\{V *J˰rI,)՘;t^C°P>3 7sn`WX ؀۝e>M\Ms+zsY=vҦߜ#Jdb j{?<$?B&" !6;Ǩ! dF "^]S0?nuVqƋ,9{b%+^?닟}ɇ {pPȭ]ݾ p3.!cE㦦kǪyIb (>ȝѩ #wo3-"1Iu/,W'B$v] vkT|P;huN_V I0hZ4HT<:7<:)a  H0@-i" w]Kus>NN@z::KIɴ1h@/ٷhoIFfBƛUmy©;riaY!a`<w ,$$(^ȝ3z+i<"a)'Nh?UU&.KFUF/zO%=vV2!+HQMUE!JFR-RDT` jE[vOހ?=%""$V*K/opDž?{zsGu *M&|zb|e_Ł?T2VYu+%E>]c6r Ar, <<""k|+m| T N ޒ%('sBj]0.*PbAmؙcECPf*=j`Ŷƞ>".7 vok[hE1G WAa=gxF[ 3M^\7c.b  * >]=b 6rgqv剽j 4K'$D"r8]{]{ԣ*eo5_CfHi@7 U{ CZmU 'npSt'[]ipPנ D$.>s&<9g&{d] 9\~{^#܈Oέƿ|cwϿ$7)-mdx۵b!ulbcX ! % PA]mD6eog$Le*՟??裠6Cz]Ew^Fr=;*5XBzqt"tVƨ+}M&#āD@ ǝͽ3Y22xW^V҈Hs_P_ |\.;#,~E}oSWPB5+omشkxA{+V8gRXP$ Ƚ[h qyva`ofϫ|$D$DAaI ~E7ٻaۓ٭/3*t]JQcA/ݯ ԕ?obi2^~/axsD *]4M{ܫD0;L!"kvyNDH{\GO`}M?O!&s)> ]8j"т2KzG֑tJ/iQ"a!~k&C & 78U"!!p7|S \p5*{%mma/ h5JϒOv>㮖aq !BA^]=Y mlv29}C󄄄L_dzK?:.t1jS׷į8.h0Iaw]uE[5{ǹE`ZFoJyVv{W217Տ,>W.>,k pJVe?_D@w8("WpE,*@ǽ38.l`;[Ttf vo==iB""`khxa0/Fȝ3 (׍]8xZfH+Rىo<ģ~7lKwsYZ"U-RȀ _Zo1:q kT TUPJ>=>0BYSiW|i(?&B" |%Jx s`9˶WUPOeԌ}e2fM&4/X뎷ݕpUQ5`XDDP $>]mṶ{]A?lk뱠>"HD8 i6&I֯:ƻwA:wNBH=*"m;GqZ* JI0^=j [{eb3諱f z9%$$:qx?S': '`06xguџ6]9akW4s~"-%]u3@/,&mxΠsx5!rW.>g}M:UB?HNpCHkM}xIW2mqFohbQյ2EuQ]54gl#IpV&D$"஽xLjUC[7cfZ#ʠVK.˄[b(twaZnGeJ$lp ]4hq)@`1BP=%+{o#6*^Wpr^?&B"BeO[ӏָ]_xX߭ H[ j+|!,Y IL ħ(BKLewlp-!!n g|W_zWKAIfpܖNVӅ@qP P aH OggSj﹦0 +[%zt|ynlusqvpyslujr|tolkx{mkrkjnnslrngjݖml {|7xm^b_!!!5:WOW_U YW7XpVv>Qg@-o^GSrMi,u)#P\, X ^]2u6=sώaCvMUN7\;YS/|_U^zFz 譕^vd0[^MQE $D ݶAVg.ilEɽX8'$"S،>o~bn=W?/uU{Mu~1{GH!?8Ɗ?@߹܏zu?7nA*%W;b B8P#.d1`^:aUrHHH]7+ kVyW*^:"?'# el.|[QET.0`*X D>=iKaE =^~ H6Cu>0*!{S+V%q){\bj+| ? 6B%=JHusX5UD䟚~J(B\H>$HX,TXD^Ƚ6!w Pp]%aG$$">p2k`ز:ߝ%"vVpC. dn[۱ l GX,"a )=efmAn_egv˩v5ꄄQrn?U7RMQ(!jrE% 62 3kTX?jK>=u$NV揻[/ fq]SRsuBB$"f]t -~>:TتfQn`˝ Ca4W,٤QT WUX YJXȽ.l#~,ٔA۸3\'iucDD$Fa}4߾uڋ۫֝&}y?}TiUJ\A 1nY.Qe = q/X'2G-9-Kwċ4)M]5ݿE;;=mTB⮇A &bn}XP"^0p `$ Ƚ. @ w06)- ٙTL`_Lv&ڙܛ]{aX1}ۀpDYFJTH* ~}.]mb[OCI- ׫"glnH ~4d>=0Fmpr ;lx*>{ Oq{<በ !"^Ƚs]4"wI~a/ p:>ÏD?mu9^S@7DevK4'ȓv-d~(KhiEaa`$` ,EWfSv^q]|5!"!vGi>Bh/zꌆ+0ҏqtmx)ɾ!23g@]M<ڡR0aHV=6~ |lA8FΕ ~3o{v"n1ZlTy]dfz~;rdztdBd]DPjU ] "=6`K=7%ۥFLΤ]/s'藝շ"i8=DKd A ==뿯PJ mncYraA `Kq@1^}4@K *0#o(jL@uEtp's}w3kGY@`HP0G%Ԉ r'h$LK80W)"1nܵv>7*ztfIS,dnj).QBb^}b 3㨆B؅ ȹ:!"~uzCܚ:*;ŭâk`jUPh8]c` ,wv㥵2!]  ,ȽcEV@}E~Nx{8sb$BBD\Nďo\{uIg}frmD6-2!`l[F&:՚^Éug]4@^}N&lܽ^69$۬"LTBR #!$1Jby>=֛!i ցᬾϟo z&-P ~H˧\$ZE%bH=3.[-q:' >wC8JDHD3M ϴZ}{D/.; Zv{.Kg0H!cflRcS1%C  ˂=m؅A>Q[ٶe/H >{8rbB"B|o}|qf߳$?~)4 D_T+|@ ^Ƚ{[~,q d^ "$@pqDGn>a5,hLЍ'gP_^MÜinȄÅҡȀ W@Ţ^ȽYcx<< ؀Uơx y?K#pճWEn!vI,:❵BQAM-i@@d!>Ƚa6,G>;DH g<ĥۭ?sٵ?fẄ́j>iQ>m=.k* .,}ydSr$lE5$~$D"X̷r ux 9 .<@w|S $xE(,$Ƚ/V2Ƚ'ɰUyW5W  p=@F3 G>`fE^005}ҨY_4lAt $ >ȽMã^U 8~,;B//_ؕHHX.N>]=^~|dwKkgoMhg`f1jPCk+ĤTP`$, J,`^X滼\mZ8Wy0rHHH޿t[5f3\/U{m:` ;5*$C1)ň+R`P}G+P}c3 b+>v59T]a"BBp=v;B&Lotn~.Dpj&KFl0fnK_D^ "0}i6bfJ'ڪxn[_!@gOfٽW^?D 0C}v5eBzK b+@P}e0`sݎNx^|D"$tD^sxNho}]3ڎA`^)r+B"Bo-7vK݈z8O4죄w{N^+ c]hE52 s.|@DB^Ƚp'͑ y#L.TTN E⧈Qx2\n=tzAHp-)B4*TTzBD$xb3ngl ?mU"n'BGdWnb(}H{"~lv8}u](a ƙ>s=" _l~QND>p{{0}:NȬH޹o ={xnOH *^O܂Er^Sݨjb9OO.'{l˓=ߟƪ(8@Iq %Ry:C̕# R*pED",~}M?a8 |(*/^e5H6j>>n^/./"yg>.q+3d.P,.~!YMҐJ@ hAAŸV slo0_V7n^v8:ϑ*ޚ&òʺV=4b Pi;V0M~}{aWv =WBq @ \HPN4]aݫvl<{ڽ螈qZ?k|xWِ肑 ~wBy8>0*>%UeH|=<M{k.h;D(D=VEQYb^ iBgr| #:!@{-ln+`V({w_x$RH.=i :t 'tI IX \T~(onQt܀@uUVղi: 耬instead-3.5.2+dfsg/games/tutorial/instead.png000066400000000000000000000643621467622671600212170ustar00rootroot00000000000000PNG  IHDRCFVGzTXtRaw profile type exifxڭ3 pw-YOitUw9 I_7ҬZ=r=^{}r }(VgӾ/3 ^_nd_vFy7E`|k^ yNl܈.<'xRH1F/S"I__CHȟ=+?_T?p>w/Ŀ>y}_O~ΏnsF~'cuY𺽯Η9w헟|C$-77ss<3{R= 7&_1-қx7KxqInO?^| &/?!2| ( fc-f r ??ހ`B"TB B F~7r 79Jr,\l,6E"JA2Fl(RJ-XeTs-V~[ifaɲ̜u=8^{{i>kG˔>~fK[q 8)9 PQ9rNS|tE(9;(cd0 ?s%o.)oGRȜSC=o,ːPA;-Pݮ-Mr\= :9S=nzJ jué\q(6].}!&~ ty bsaZ}NC ?evJi1V=2!]q{[ZfsV<^1LSXYFpjy)IJLϘF'M6KLg<<ɇUAQܭr 7*5 ^SjmKl= J O|u>{5"{J)qǥ'FD[1]b.n@`PGjfB]6GK"&F\HvB9@qR^$v:^DĥNy@W1MC@#G3v9`u϶Zag/RZuS#eBMar~'߅ >DŽ4(Zv#āW66 ,胵*T $j@Z;0އ=ݮ_ ڻDm W?0#'F8(FnTFx"@[@ R9;a<`(Dg ;N L91yzaS•HBN*јa€Zd9QU7ryEBК}=9:L/]Rkep4FGڔ5<1 ~DBVZ 8xDdfD6ߥ8HLɖ&Xr J(#[&RRmN!-CˑИP <uEd'9Z$6PTWtk{@h>\BizrWt$-'٠ (( v]#&~ i*AuD :w 1}fX3; 7b6B͈ EkC V Q~F#DDPʨnwR'Rj!~U2Zv,(2G-ȌQ K]~FaJ `(ژ;m~VJqh5 6ŁhpBd t)@hsU"ޮ*NLJ|%j Azӱ@(QӔRdz S`KTa/ F!F3Y OChx@G& M H"Lyka,D eZZIzyq\%4YYm_(!::Сld~푯dG_i"P+ňH^/.'c`ZrvBI/ =!3<.vZ@ h22TnX`BYzDEj!FϤ,khxtWt=v&tvΡ'Z$16p-*B]V ~U+ "妘:DVњSE`:~n:zT͕R@_t2Qt$-SC,oVM"e$#ؐ{+q i_)pD;Hq;sH&vt>vM␁U J&vH x]T+мwdbE:n^1l-h@6 2O^*d\HERo4̛/h:v{T9>(VFd(?ZHax=RkG#-| :ſ歶t49N=Z>@|Dj KITSZ:-rU_AJńƘ 0 &FA蝎:B O5\9ٵFNT i@rL m[+BI 8ѦK;iW+A/chG,F+H `BާĖ=]6#+Ƀ^YęO;^⁻!9>@B70%Vfmjj'1HJzh_k(Эc!ʊZR~ JV3Q< ěHT$ˢ䜄yb[n,@X 'Yj_ʄz2r/j*0cgӖC-L l`O2pTrzܒ ` MdRXn#ZG^ 8hfujC(|Ԓ" }@SG`Ƞ;y@wK@#@b}:FaAhPhXieUsB$l"(Ъ56dôPHu/3z7M(M6 /+2@j-OMv ''p;cI;TDԪ Boפ!\B0i!X|$hP-חWӗ~>?bZ4 jUK㦼:Ғ jQ;B'RV*ir>sLWT5wQ] Ck"BZJ0L>{jx1zHoI(|C~/WJU @i>54{! -4 ˅Dj @GyFpDO ǭIrj"p%sB68Z%Wt_oZɔ& +NNB'W-q=jŎH7.8uЕ (m~A*BC4-=X2`H=\Gi'mQ"ix\;ڑC}XDS'S *vyA'ÆR(:jѫA^h ؔsX4EG")Vy' Di,cҊ&D(ąML98i<Kz̝ZB]$GvC4@58սXʖ/iŸ/aA˴A.i܌/?xSų)QR_. [Ǧv3m9ѐ"P0#+bBҵ[[]Uâ["4$!5;̩? -{{Q`vQZcF%D6OS+CE6qKb綾1!q)隙(N>];J[8Z5l3 {y܇7Y&[w~P^C={.ZY Am;rg|8̬"ɣf0}`V۸Tt< ⯳#yIf- |$LS3uKU^P]`} mX"2d=HWuh ݥ,޹2=A*DZU$}\2T*s:y!:1vj=* >]R(wL{h/\;1Td`F%t4Q,pj3&iaKrP#Fu3޹&!h0s<<)&6#C Ub<t$$-4qM$Tc3g=ixߢr_^)d# ̤#~Ch@Ng4SjG;*@DX ~ ﭕU_wb}gL]dѼFPZ5TƍpX<;"o:Pc.F!x(?$T9dx鴴א0aSU"b$3^F2I@0<F2 5d0!.d=f;P&dlUmՂCI::-bkQ,Rz:kQ:\J{e'KT8"ң*(,|@Yuh7!, iKJ,42ɡ\`Qd( rXKtt]ZcEӈ m8%0ƓADK.w8x4^K#jװjqL,4{ π¹x0ΡW%@hm`tqN I!a"Mu"5(ƀ2 ŤHlJp\%K5 HjAKe2ڐ4͢jV`DYr sLȓcZ3!|JsD Y}Z[޴ߡwGo\ڪ"H-z) pD ៝%d!ztxE bpG0U#U&&pMM'(WÁ^ٗIDY8-NAEcA; ր}מ$+АOi|.nMgΩmCG'ħNsG{''iCCPICC profilex}=H@_["-V):Yq*BZu0 4$).kŪ "%/)=Ff8jN&lnU"a L}NS_.γ9JdO eaoOoZ:}+I 9A$~~12yP`YPcQ?yZ= Cyme4HbK!@F eT`!NF4' +;bKGD pHYs >FtIME IDATx]w|T~BEB (RU+MHR=ԧQPOAQ@,Hi1@ BH#KHv7n޽e3gΜsfP^=EQ%b<˲bdq"<WoVTf@,h)at+$0  ,Kψ@`F$B,C;VWC˵aa0 !GYeY'˲.N.BӲL{_r}DzJJR(?,dadB@4x&~=.dԩTF rʨ\2bbb4;wJMMϜ9c1iiiH4ma^a& Ø,ܤG5B X fܲ;aaOYڡ9a8Bg!zBާp:Y &!DBlQy Ty_m!cY`Y0aTUi(kDQ$Iڵ ,8xYxrIF^M6$X]p}VZYx<,˿} "^MK.LӄeYeY8,^yQ7l؀?iIR~fΜ)]ίeYyR\ÇI$w%n[F HZZZ"u95MgϞ-Z\RѤIBaYصkצMkGŶmx BH4j =PPsss1{l^lFj֬ ,6l`+d"  EqdRRP^8mڴ ,EQ,EQ,KE!i$IVZS_Nf͚ݻ7Zl_ީSРAоE%Te}ݴ, u={v,B ayٝ;wr^{mЗNI&a",,ruAap]w޹sgGvۣiӦa#3g_ݴ,럄7K;Ҿڒrr={vРAOCTp sn+MU8P(Mk֬!$}V6e)Sh Ø.+vt:eyYQ(?0 r裏 r8].:۽]Xeu]>B1tOBPϞ=l-w1F`qӹeYҲ !믄y τĠrƌD#r~>}zH5x*"P-Ɗ:0?>za~TTIe+u$Iz mF8S]eMqœX8;w.ԭy衇T]W­QӴ)㥥 tJ;v@4 \y0E믿_ΆlB, p<[C*BA{"55g0Ѭ{6C>;vX^/vSUU-}>_3gر1wܐ/n^ZfYv8 T:iCđP%bߏ~eaDa8=zիW/; X̀24{^Q3ϟlo&d^xQ|>Pޔ!!$ԩS*Ubu˲9R VZSN*˲O\eHʸN] =vXߒ%KBмysxA PKkMv+,~ӦM㯻,z$̔2t8ׯH_ͼ-r222-P@3g4jy>5Le#gO?a߾}eYgXW-u]as9x\ƊB2i UUvhTBxؿ(,J d,Cc <ȼ{ذa4MKC x(_kjjGݻw+6E"O}r2˲K)h`/CUUx=z( VQ$QaYH-Yj`0LD:iϚ5Kٳ"OW1q][nݩi'w9111kfϞr TUKӴX[TOqԨQ ?:t %HBgӳ?u +ʐ.\{UCM@fͰrJ_Vf*UO_=p8nDeglRRҔk׾xͽ%''}NNNk˓ )0gϞzݺu| gqĈa%}fL6M! cƌq A :t?O_ޙ.Z(vȑ4mt6N0ѥFJ˃e%7e-[e~Me8I&F۶maYvލG 8>@E]tJb˲Y999!!..iV.(!MU;Νk,\0,Kk׮1c23C)2~ʔ) :,eݻw+l߾yQLKq#o!;;;;ip v?R C1 㑧zFlE$,XUU;8E\h:D8<ȑ#1rHǶm۰`GVX(w xe&oeSӧw(Jd^@͚5QV-hnː-˰;Z?wɒ%DӴ9E+ذaæts!6!:sEvٯw}E97o 6H^{퍒$Ф%bcc_Hcƌ?|(-V (N6w\i,/|0 t[6G; aGfYvd6m&Mpiرcطo7,裏Fv5Z^z^peP111! cõ؊i"mSEk3fXXOժUŋ%F}5U]k$''O2eʙ6mh:9x`,Deg#&u&ipB8]םBH۶m:j(c0M eH) ԰a .DQ @r.ᜟ~IHII !1 CFuMy Y )4tnr*E={rʰ\f͚aܹqsNFrR^nnnyٳަM?o_>/ZP3d> ;(d󛿚M8eß71DEίpbŊIJ,D~w>${4( ,Y:'9- 84z_ J2 v?~\4մ0l7MgyؿXSny~cDX0MrFFƀ%K|g%&&V.\3gΔ(8h J*U2j[ۧ 4Rp8="˲, =zg~駪A鏏]we 0-XXPԡ:mp*il$qR(C zj)XR@= b=*.[G&qRJ]W];v4iRBӦM}}u<gyuЭ[7iѢE !FKS008JMMͷ ! ڹ_~L@־ 0LA-RvvqFzA2dvځS beEQj4j(ٳ'3R3L0x<6%K$Q ]ɓ'OڵknS'P;!;^=g̙Omr=0?tPaÆ~ї9ڵ .[5\c$%%ӈھSGaԯ_ VߦM J=)a/:"QRUo7daC=2553MۨeKMNݺu~t5}aÆ,y+o իW<\cBWff>*ԩ:uUlС Dp~Mmڴ![Ϋ( Z0xEwy?Cd,˘7ot:{sJa ?z 0@ J[z(J5++o KO5iБ3B(oƐke#}(iJO9۷o/H:|09"XXxj5SxE̓[ooܸ1ߥK/T^4hР&Bq', x6g4i$.h<+_ zD.pλv‚ Jӈ_x1X8 0@OS벲 @ƫzKǎ¬Y>,tHeapiǏ??7n-Z`ڴi zB|UВ$-SNeav"n;w xu]Jjs>(m5MKӧO>ӦM9r{JS(uرJ|Afp,haQM415k&%/[5%p-lrY} 1IDAT|45jK, +IB׮]1~xBi4!9yduС!Ԉ28q >pYկ EQ|k׮VLL g&N8G'R(\ts=zCXڵiӦ /A9BX>aGȘUΰh02nܸRz-tZ%<B\.z 3A2,$''hIJcSJ-IR؏5Ms`߾}lʕ$I?Fb$߷oxԩ0`hY֣*G/_|CeY lUرn:ݻ5Md.a:}>7uT* QXX@pjVf͚E޿;]M<}F'VӴO=T/ZC!uԱZj˲`MQ"[$I/_rUVWU,-8{g)Çcʔ)i82 NJh%F娪zǷ~.YK$BXtI,ö<[?~o x6ZBܫW/4h ? ,ׯ_l/׫&1WX 8!Ir/+h:eY^u]v- .`ܸqeY3,ld+`"N3 BWJ"/<eGu]`֬Yf8KG@J*|,ÎM6ՋRJ| $i'Lf[L!aZ\yR[6m<,xuiP_ (`.2]QZAylZR{4GO<g׬R?5(3ʑXIz뭎p>}4.\h*hY%d!(C(+D;ڷo, 8.'$I۳gOV$Xlٲ3 c~Y9oZ=x}'ȲU ItyL6MbY><ƌ:uMWʐeI"%AP`iӞ}Y-C(i߿?Ӷm۪(nPDHyBBBվ}oq@6;8BY42_Fz-hYV֭[4Mdggep2'{<ڸq#A8`Wv)K>}XMnЬ4/0S9ַoߚ3f+UtMǰaժvB eY+O]fp8M[QeFm`˲ǫlCݯZMk֬]_|QlܸqCIv0̫$u{ŋ={>E$).4,4!0P :BhFL-;@wN4hߡCLMӾ[dYN wR :ud8uՌ81ڋe-[ b k˗cF^^d6ZۢFS, L~0 !_XոI&b@aԫWe :z׿:̜93hRuO_>owy̙3 67,S͒$}(r^zITe{di k/ƍP!9`MmdGSJԴZjL @q:FC@lGqA說j;j$IehFMyĈǔݲ3a$%%ջIχ.ر?kfن5k֔B9B@ 916~h0L;You5!Dҥp5RSSG;vPL|a}l nA %. 5RRSS?4mgO^NL7j*S *)))t]hCMz8qb端`ʔ)BQ8f^(WXc,Az+}݇,ˇ|>|,  Q-0Yt)Ou4{X4@=Ax}PFZ?]ߥ2r.RBheFM|bZZZO0z~˲D$]ep˅&M-[Zhڵkg!5Hy!Cw.7p4BUեϲl򫐾gZxy-4m Uq\wbb"l3//aEamV>EQ\ѢE YfBBB7n Q UgΜg}oڴy~8).UUBXx_Aqv ŋ1{l$;;A;.ۊL ?aiZ O<@zz:&O$''<{A0y0h R_w}w?^(ΝðaGX~}z >9M6aݺu'O Xian[W lꗯ9uO>}:Wgg,UU5ʈYZ5;tۗ ddd`֬YѣGŋqq t-w `(oի҈#luhzf,{icccÇK}'zoh;vDQl,˲)bZgwɲoqeU2 jZ0}t?Wڵk7())),' !?|Ql({M7U0aB]ב p8t:!IRVeae˖?3 M^p$DLT\w0²f\r r-}Ÿ8ԪU jʯ0/^ddd`۶mؾ}1 |=q[G!s[dffb?KX,ˋTU߬Y3owv111!"##^k׾䝂իWW& |bx#̛*2NzRJ%!;;_|6nܸLQJ3#IvAZ6LJ%':4luc<#\BBg"55IIIXnYUUknz-˅J*E%˩Spkn9_GyDի8.cž}k.cŋEAVi6 \Sǃl ]MqykEfƍa_~`a( ׮]k׎&3M?pUʕn)Ԋop(8qcs̹uj:u(J¾tAW ++ {ի}GA`6EA<#''GAy,2y($mn%8n˲²lH9i4 a@ӴrΞ=N֭[. ǎ8˗uvWbԬY͛7ϧȑ#e{{qC 6lLλ?s_>N>}Y]h`rrrldgg#++ɔTiѷJ9I˨MyPyˠJTq^txlX3[Kmr* R(O:ͪRh t/;T nK88b D' 9/JL2}ouSTnoQ7&*ģhOqGR *wR wԛR!ޣf* RB?Cˌ+~nsC4h:p<`$BM [Z׿igLy|@{iPKV7*z8-xǶ0G'?m}Wx tW)oA^_k"UKe52U/*{Jz>=K\D fR%x)ڧB*$^TL\z6q2uSE;j ]%4]˴NI)nڮJ[[9+hG T7~h};̵C߻o@~˰ P=a.@VϨ. ?n mJ6a.Ϯӽ2 Q2t/nkL j`.ͱ `Ԣ5 Ry2 mTi(6X=ӀXnX-+oSdI-/` |AE}e&Jk~/ ٯ4>OU/kŗa]Qp,pRWH6ɋ6C*{\zmT[R.]^NGpgJn=P1E800 gv:` i^ _^şvetjsq-itjHZgW…tiBt4Ls\/ ԝDI.[{ !LH8Rih&[TQx"0,2l_NHRk Cj Ia4 Q1)MQ&R: <:"0PKS׻FB*6(KkR]d([< {[}|qai8+ħ/PwDuBS=+:(_mm1 46{Oie-,,~:r6/p]\{\c2 B 57B˕mۆ(;j om[!t0a$=tL d4mUp  s(ɱ;obO>!xPwfʈGV:|gѪ\iv @ӺRn'P ɴ?dS2{t?yPTc4f֖v;|Jm{hxELtt}Z6 bzjE2- umOKc )03Ɔ.DJh_Aˉ/ е F; udjUVyv* E-VI5/% Ez _Ƨkl3?;Z7VQRP?㮏?h)F҃e ^ό?{Ɠ]i6]аRLTY?yQiu#PqgSQa i`Gϐ͡H?\vQϨΧ gP"-q4ך*vt}TfS7Q K]jٝ1x[R+l]tCB@J&gkrKq4:ZQ%^ى&TPŕD]iTANi| iO+r;TƟ3I64w3 ʣv`>zﯨHe>h] | &a LI\Zۻ%8h4L1CTlUoue}+N(D5`8v+hxA/Jf~W֡x]G0 , \7[kIENDB`instead-3.5.2+dfsg/games/tutorial/it.png000066400000000000000000000006441467622671600201750ustar00rootroot00000000000000PNG  IHDR ngAMA7tEXtSoftwareAdobe ImageReadyqe<6IDATxbd10ax*RU baPZ RIJJbb e&ba`?￿@Po QVh@ TFW @` 5 B1bbzh￿%(@ f F ߿T @Wa` @JCv > @c?ܒ o BFFF8PR)#(AlY8@ 8.VwQrIENDB`instead-3.5.2+dfsg/games/tutorial/main-de.lua000066400000000000000000000000601467622671600210600ustar00rootroot00000000000000LANG='de' include 'tutorial' fmt.quotes = false instead-3.5.2+dfsg/games/tutorial/main-en.lua000066400000000000000000000000601467622671600210720ustar00rootroot00000000000000LANG='en' include 'tutorial' fmt.quotes = false instead-3.5.2+dfsg/games/tutorial/main-es.lua000066400000000000000000000000601467622671600210770ustar00rootroot00000000000000LANG='es' include 'tutorial' fmt.quotes = false instead-3.5.2+dfsg/games/tutorial/main-fr.lua000066400000000000000000000000601467622671600210770ustar00rootroot00000000000000LANG='fr' include 'tutorial' fmt.quotes = false instead-3.5.2+dfsg/games/tutorial/main-it.lua000066400000000000000000000000601467622671600211040ustar00rootroot00000000000000LANG='it' include 'tutorial' fmt.quotes = false instead-3.5.2+dfsg/games/tutorial/main-nl.lua000066400000000000000000000000601467622671600211010ustar00rootroot00000000000000LANG='nl' include 'tutorial' fmt.quotes = false instead-3.5.2+dfsg/games/tutorial/main-pt.lua000066400000000000000000000000601467622671600211130ustar00rootroot00000000000000LANG='pt' include 'tutorial' fmt.quotes = false instead-3.5.2+dfsg/games/tutorial/main-ru.lua000066400000000000000000000000551467622671600211220ustar00rootroot00000000000000LANG='ru' include 'tutorial' fmt.para = true instead-3.5.2+dfsg/games/tutorial/main-uk.lua000066400000000000000000000000551467622671600211130ustar00rootroot00000000000000LANG='uk' include 'tutorial' fmt.para = true instead-3.5.2+dfsg/games/tutorial/main3.lua000066400000000000000000000024571467622671600205710ustar00rootroot00000000000000-- $Name:Tutorial$ -- $Name(ru):Обучение$ -- $Name(uk):Навчання$ -- $Name(de):Einführung$ -- $Name(es):Tutorial$ -- $Name(fr):Tutoriel$ -- $Name(it):Tutorial$ -- $Name(pt):Tutorial$ -- $Name(nl):Snelstart Training$ require 'fmt' local tut_lang = { ru = 'Язык', en = 'Language', ua = 'Мова', it = 'Lingua', es = 'Idioma', pt = 'Linguagem', fr = 'Langue', de = 'Sprache', nl = 'Taal', } local tut_title = { ru = 'Обучение', en = 'Tutorial', ua = 'Навчання', it = 'Tutorial', es = 'Tutorial', pt = 'Tutorial', fr = 'Tutoriel', de = 'Einführung', nl = 'Snelstart Training', } if not LANG or not tut_lang[LANG] then LANG = "en" end tut_lang = tut_lang[LANG] tut_title = tut_title[LANG] xact.load = function(w) gamefile('main-'..w..'.lua', true) end room { nam = 'main'; title = tut_title; pic = 'instead.png'; decor = fmt.c ( fmt.b(tut_lang)..'^^'.. [[{$fmt img|gb.png} {@ load en|English}^ {$fmt img|ru.png} {@ load ru|Русский}^ {$fmt img|uk.png} {@ load uk|Українська}^ {$fmt img|es.png} {@ load es|Español}^ {$fmt img|br.png} {@ load pt|Português}^ {$fmt img|it.png} {@ load it|Italiano}^ {$fmt img|fr.png} {@ load fr|Français}^ {$fmt img|de.png} {@ load de|Deutsch}^ {$fmt img|nl.png} {@ load nl|Nederlands}]] ); } instead-3.5.2+dfsg/games/tutorial/nl.png000066400000000000000000000007051467622671600201700ustar00rootroot00000000000000PNG  IHDR ngAMA7tEXtSoftwareAdobe ImageReadyqe<WIDATxbπPX@`U 5/w9~LO)V*<'ρJ@~$(+  XD 3T j Ə??< AT40Ved@+o>Ƞ_^kן $߿ <{;g óOzH߯@u5@H?p20 _ uœ#@?`@hc`FDB2kgIENDB`instead-3.5.2+dfsg/games/tutorial/ru.png000066400000000000000000000006441467622671600202070ustar00rootroot00000000000000PNG  IHDR ngAMA7tEXtSoftwareAdobe ImageReadyqe<6IDATxb?BAX )̀l#/ dj?6 ==gd䌿 d@$$XX XoH7?_Iyy?|4D/ THRH\) @@,5|HӟD efE ?phU=L0HJ倢 `g1 H W*M  ?e8aIENDB`instead-3.5.2+dfsg/games/tutorial/tutorial.lua000066400000000000000000002165341467622671600214300ustar00rootroot00000000000000require "snd" require "fmt" obj { nam = '$'; act = function(s, w) return w end; } fmt.dash = true function L(t) return t[LANG] or t.en end game.act = L { ru = 'Не получается.', de = 'Das können Sie nicht.', en = "You can't.", es = 'No puedes hacer eso.', fr = 'Vous ne pouvez pas.', it = 'Non puoi.', nl = 'Dat kan niet.', pt = 'Isso não é permitido.', uk = 'Не виходить.', } game.inv = L { ru = 'Гм.. Не то..', de = 'Hmm … Falsch …', en = "Hmm... Wrong...", es = "Hmm... Nop...", fr = "Hmm… Mauvais…", it = "Hmm... Sbagliato...", nl = "Hmm... Verkeerd...", pt = "Hmm... Não...", uk = "Гм.. Не те..", } game.use = L { ru = 'Не сработает...', de = 'Das wird nicht funktionieren.', en = "Won't work...", es = 'No pasa nada...', fr = 'Ne fonctionne pas…', it = 'Non funziona...', nl = 'Dat werkt niet...', pt = 'Não funciona...', uk = 'Не спрацює...', } game.pic = 'instead.png' snd.music 'instead.ogg' xact.walk = walk room { nam = 'main'; disp = L{ ru = 'Обучение', en = 'Tutorial', de = 'Einführung', es = 'Tutorial', fr = 'Tutoriel', it = 'Tutorial', nl = 'Snelstart Training', pt = 'Tutorial', uk = 'Навчання', }; dsc = L{ ru = [[{$fmt c|Добро пожаловать в режим обучения INSTEAD.}^^ Игра состоит из сцен. Каждая сцена игры имеет описание, состоящее из статической и динамической части. Динамическая часть включает объекты, персонажей и т.д. С динамической частью игрок может взаимодействовать с помощью мыши, нажимая на подсвеченные ссылки.^^ Данная сцена называется "Обучение" и сейчас Вы читаете статическую часть её описания. Единственным объектом сцены является объект "Дальше", который Вы видите внизу текста. Итак, для продолжения обучения Вы можете нажать на "Дальше".^^ {@ walk r1|Дальше}]], en = [[ {$fmt c|Welcome to INSTEAD tutorial mode.}^^ The game consists of scenes. Each game scene has a description, consisting of static and dynamic parts. Dynamic part includes objects, characters, etc. A player can interact with the dynamic part by clicking mouse on the highlighted links.^^ The current scene is called "Tutorial" and you are reading the static part of its description. The only object in this scene is the "Next" object, which you can see below the text. Thus, to continue learning you can click "Next".^^ {@ walk r1|Next}]], de = [[{$fmt c|Willkommen in der INSTEAD-Einführung.}^^ Das Spiel besteht aus Szenen. Jede Spielszene hat eine Beschreibung, welche wiederum aus statischen und dynamischen Teilen besteht. Die dynamischen Teile beeinhalten Objekte, Figuren, usw. Ein Spieler kann mit dem dynamischen Teil interagieren, indem er mit der Maus auf die hervorgehobenen Links klickt.^^ Die aktuelle Szene wird »Einführung« genannt und Sie lesen den statischen Teil ihrer Beschreibung. Das einzige Objekt in dieser Szene ist das »Weiter«-Objekt, welches Sie unter dem Text sehen können. Um mit dem Lernen fortzufahren, können Sie auf »Weiter« klicken.^^ {@ walk r1|Weiter}]], es = [[{$fmt c|Bienvenido al tutorial de INSTEAD.}^^ En INSTEAD un juego se divide en "escenas". Cada escena tiene una descripción, conformada por secciones estáticas y dinámicas. Las secciones estáticas pueden incluir objetos, personajes, etc. Como jugador puedes interactuar con las partes dinámicas al hacer click en los links resaltados.^^ La escena actual se llama "Tutorial" y tu estás leyendo la sección estática de su descripción. El único objeto en esta escena es el objeto "Siguiente", que puedes ver más abajo. Esto es: para seguir aprendiendo haz click en "Siguiente".^^ {@ walk r1|Siguiente}]], fr = [[{$fmt c|Bienvenue dans le tutoriel de INSTEAD.}^^ Le jeu se compose de scènes. Chaque scène de jeu a une description, constituée de parties statiques et dynamiques. La partie dynamique comprend des objets, des personnages, etc. Un joueur peut interagir avec la partie dynamique en cliquant avec la souris sur les liens en surbrillance.^^ La scène actuelle est appelée « Tutoriel » et vous êtes en train de lire la partie statique de sa description. Le seul objet dans cette scène est l'objet « Suivant », que vous pouvez voir ci-dessous. Ainsi, pour continuer à apprendre, cliquez sur « Suivant ».^^ {@ walk r1|Suivant}]], it = [[{$fmt c|Benvenuto in questa guida introduttiva ad INSTEAD.}^^ Il gioco consiste di scene. Ogni scena del gioco ha una descrizione, formata da parti statiche e dinamiche. Le parti dinamiche includono oggetti, personaggi, etc... Il giocatore può interagire con la parte dinamica cliccando con il mouse sui link evidenziati.^^ La scena corrente è chiamata "Tutorial" e state leggendo la parte statica della sua descrizione. L'unico oggetto di questa scena è l'oggetto "Avanti", che potete vedere sotto il testo. Così, per continuare questa guida basta fare click su "Avanti".^^ {@ walk r1|Avanti}]], nl = [[{$fmt c|Welkom bij de INSTEAD snelstart training.}^^ Het spel bestaat uit scènes. Elke scène heeft een beschrijving. Een beschrijving bestaat uit vaste en dynamische gedeeltes. Dynamische gedeeltes zijn bijvoorbeeld objecten of personages. Een speler kan de dynamische gedeeltes beïnvloeden door op de gemarkeerde te klikken.^^ De huidige scène heet "Snelstart Training" waarvan je op dit moment het statische gedeelte van de omschrijving aan het lezen ben. Het enige object in deze scène is het "Volgende" object. Die kun je onder deze tekst vinden. Om de rest van de training te lezen, moet je op "Volgende" klikken..^^ {@ walk r1|Volgende}]], pt = [[{$fmt c|Bem-vindo ao tutorial do INSTEAD.}^^ Cada jogo consiste de cenas. Cada cena do jogo tem uma descrição, com partes estáticas e dinâmicas. Partes dinâmicas incluem objetos, personagens, etc. Um jogador pode interagir com a parte dinâmica clicando com o mouse nos links realçados.^^ A cena corrente é chamada de "Tutorial" e você está lendo a parte estática da sua descrição. O único objeto nesta cena é o objeto "Próxima", que você pode ver abaixo do texto. Então, para continuar aprendendo você pode clicar "Próxima".^^ {@ walk r1|Próxima}]], uk = [[{$fmt c|Вітаємо в режимі навчання INSTEAD.}^^ Гра складається зі сцен. Кожна сцена гри має опис, що складається зі статичної та динамічної частини. Динамічна частина включає об'єкти, персонажі й т.і. З динамічною частиною гравець може взаємодіяти за допомогою миші, нажимаючи на підсвічені посилання.^^ Дана сцена має назву "Навчання" і зараз Ви читаєте статичну частину її опису. Єдиним об'єктом сцени є об'єкт "Далі", котрий Ви бачите внизу тексту. Отже, для продовження навчання Ви можете натиснути на "Далі".^^ {@ walk r1|Далі}]], } } obj { nam = 'paper'; disp = L { ru = 'бумага', en = 'paper', de = 'Papier', es = 'papel', fr = 'papier', it = 'foglio', nl = 'papier', pt = 'papel', uk = 'папір', }; dsc = L { ru = 'Первое, что Вы замечаете в комнате -- {листок бумаги}.', en = 'The first thing you notice in the room is a {sheet of paper}.', de = 'Das Erste, was Sie im Raum bemerken, ist ein {Blatt Papier}.', es = 'Lo primero que ves en la habitación es un {pedazo de papel}.', fr = 'La première chose que vous remarquez dans la pièce est une {feuille de papier}.', it = 'La prima cosa che potete notare nella stanza è un {foglio di carta}.', nl = 'Het eerste dat in deze ruimte opvalt, is een {blad papier}.', pt = 'A primeira coisa que você vê no local é uma {folha de papel}.', uk = 'Перше, що Ви помічаєте в кімнаті -- {аркуш паперу}.', }; tak = L { ru = 'Вы взяли бумагу.', en = 'You take the paper.', de = 'Sie nehmen das Papier.', es = 'Coges el papel.', fr = 'Vous prenez le papier.', it = 'Prendi il foglio.', nl = 'Je pakt het blad papier.', pt = 'Você pega o papel.', uk = 'Ви взяли папір.', }; seen = false; haswriting = false; inv = function(s) if here()^'r2' then s.seen = true end if not s.haswriting then p (L { ru = 'Чистый лист клетчатой бумаги. Похоже, его вырвали из тетради.', en = 'A blank sheet of squared paper. Probably torn out of the copy-book.', de = 'Ein leeres Blatt kariertes Papier. Vermutlich wurde aus einem Schreibblock ausgerissen.', es = 'Una hoja blanca y cuadrada. Probablemente arrancada de un libro.', fr = 'Une feuille de papier quadrillé. Probablement arrachée d’un livre.', it = 'Un foglio di carta bianca a quadretti. Probabilmente strappato da un quaderno.', nl = 'Een blanco blad gelinieerd papier. Waarschijnlijk uit een notitieboekje gescheurd.', pt = 'Uma folha branca e quadrada de papel. Provavelmente rasgada de um livro.', uk = 'Чистий аркуш картатого паперу. Схоже, його вирвали з зошита.', }) return end p (L { ru = 'Лист клетчатой бумаги, на котором написано Ваше имя.', en = 'A sheet of squared paper with your name on it.', de = 'Ein Blatt kariertes Papier, auf dem Ihr Name geschrieben steht.', es = 'Una hoja cuadrada de papel con tu nombre escrito en ella.', fr = 'Une feuille de papier quadrillé avec votre nom.', it = 'Un foglio a quadretti con il tuo nome scritto sopra.', nl = 'Een blad gelinieerd papier waarop jouw naam geschreven staat.', pt = 'Uma folha quadrada de papel com seu nome nela.', uk = 'Аркуш картатого паперу, на якому написано Ваше ім`я.', }) end; used = function(s, w) if w^'pencil' and here()^'r4' then s.haswriting = true p (L { ru = 'Вы пишете на листке своё имя.', en = 'You write your name on the paper.', de = 'Sie schreiben Ihren Namen auf das Papier.', es = 'Escribes tu nombre en el papel.', fr = 'Vous écrivez votre nom sur le papier.', it = 'Scrivi il tuo nome sul foglio.', nl = 'Je schrijft je naam op het papier.', pt = 'Você escreve o seu nome no papel.', uk = 'Ви пишите на аркуші своє ім`я.', }) return end return false end } obj { nam = 'pencil'; disp = L { ru = 'карандаш', en = 'pencil', de = 'Stift', es = 'lápiz', fr = 'crayon', it = 'matita', nl = 'potlood', pt = 'lápis', uk = 'олівець', }; dsc = L { ru = 'На полу лежит {карандаш}.', en = 'There is a {pencil} on the floor.', de = 'Dort liegt ein {Stift} auf dem Boden.', es = 'Hay un {lápiz} en el piso.', fr = 'Il y a un {crayon} sur le sol.', it = "C'è anche una {matita} sul pavimento.", nl = 'Er ligt een {potlood} op de grond.', pt = 'Há um {lápis} no chão.', uk = 'На підлозі лежить {олівець}.', }; tak = L { ru = 'Вы подобрали карандаш.', en = 'You pick the pencil.', de = 'Sie nehmen den Stift.', es = 'Coges el lápiz.', fr = 'Vous prenez le crayon.', it = 'Raccogli la matita.', nl = 'Je pakt het potlood op.', pt = 'Você pega o lápis.', uk = 'Ви підібрали олівець.', }; seen = false; inv = function(s) if here() ^ 'r2' then s.seen = true end p (L { ru = 'Обычный деревянный карандаш.', en = 'An ordinary wooden pencil.', de = 'Ein gewöhnlicher Stift.', es = 'Un lápiz común de madera.', fr = 'Un crayon ordinaire, en bois.', it = 'Una normale matita di legno.', nl = 'Een heel normaal houten potlood.', pt = 'Um simples lápis de madeira.', uk = 'Звичайний дерев`яний олівець.', }) end } room { nam = 'r1'; disp = L { ru = 'Урок 1', en = 'Lesson 1', de = '1. Lektion', es = 'Lección 1', fr = 'Leçon nº 1', it = 'Lezione 1', nl = 'Les 1', pt = 'Lição 1', uk = 'Урок 1', }; enter = function(s) lifeon(s) end; life = function(s) if not have 'paper' or not have 'pencil' then return end lifeoff(s) enable '#cont' end; dsc = L { ru = [[Урок 1. Взаимодействие с объектами^^ Продолжим урок. Сейчас Вы находитесь в комнате. Возьмите оба предмета, которые Вы видите. Напомним, что для этого Вы можете просто использовать мышь. Если Вам удобнее пользоваться клавиатурой -- можно выбрать нужный предмет с помощью клавиш со стрелками и нажать "Ввод" для взаимодействия с ним.]], en = [[Lesson 1. Interacting with objects^^ Let's continue the lesson. You are inside a room. Take both objects that you see. You can just click on them with mouse. If you prefer keyboard, you can pick an object with arrow keys and press "Enter" to interact with it.]], de = [[1. Lektion: Interaktion mit Objekten^^ Lassen Sie uns mit der Lektion fortfahren. Sie befinden sich in einem Raum. Nehmen Sie beide Objekte, die Sie sehen. Sie können sie einfach mit der Maus anklicken. Falls Sie die Tastatur bevorzugen, können Sie ein Objekt mit den Pfeiltasten auswählen und [Eingabe] drücken, um mit ihm zu interagieren.]], es = [[Lección 1. Interactuar con objetos^^ Continuemos con el tutorial. Estás en una habitación. Coge los dos objetos que ves aquí. Para ello, puedes clickear sobre ellos con el ratón o -si lo prefieres- usar las flechas de tu teclado para posicionarte y el "Enter" para interactuar.]], fr = [[Leçon nº 1. Interagir avec les objets^^ Continuons la leçon. Vous êtes à l'intérieur d'une pièce. Prenez les deux objets que vous y voyez. Vous pouvez simplement cliquer dessus avec la souris, ou, si vous préférez le clavier, vous pouvez choisir un objet avec les touches fléchées et appuyer sur « Entrée » pour interagir avec lui.]], it = [[Lezione 1. Interagire con gli oggetti^^ Continuiamo la nostra guida. Siete dentro una stanza e potete vedere due oggetti presenti. Per prenderli fate semplicemente click su di essi con il mouse o, se preferite usare la tastiera, potete raccogliere un oggetto usando i tasti freccia e premendo quindi "Invio" per interagire con essi.]], nl = [[Les 1. Werken met objecten^^ We gaan verder met de training. Je bent in een ruimte. Pak beide objecten die je ziet. Je kunt er simpelweg op klikken met de muis. Gebruik je liever het toetsenbord, gebruik dan de pijltjes toetsen om het object te selecteren, en druk op "Enter" om het op te pakken.]], pt = [[Lição 1. Interagindo com objetos^^ Continuando com a lição. Você está num local. Pegue os objetos que você vê. Basta clicar neles com o mouse. Se preferir o teclado, você pode apontar para um objeto com as setas direcionais e pressionar "Enter" para interagir com ele.]], uk = [[Урок 1. Взаємодія з об`єктами^^ Продовжимо урок. Зараз Ви знаходитесь в кімнаті. Візьміть обидва предмети, котрі Ви бачите. Нагадаємо, що для цього Ви можете просто використовувати мишу. Якщо Вам зручніше використовувати клавіатуру -- можна обрати потрібний предмет за допомогою клавіш зі стрілками и натиснути "Введення" для взаємодії з ними.]], }; }:with { 'paper', 'pencil', obj { nam = '#cont'; dsc = L { ru = [[Отлично!^Вы скорее всего заметили, что статическая часть описания сцены исчезла, уступив место описанию предметов, которые Вы взяли. Чтобы снова посмотреть полное описание сцены, можно нажать на её название, отображаемое в верхней части окна -- "Урок 1". Кроме того, можно нажать клавишу F5 на клавиатуре, результат будет таким же.^^ {Дальше}]], en = [[Excellent!^You've probably noticed that the static part of the scene description disappeared, replaced by the descriptions of the objects you've taken. To see the full scene description again either click on the scene name at the top — "Lesson 1" or press F5. The result is the same.^^ {Next}]], de = [[Ausgezeichnet!^ Sie haben vermutlich bemerkt, dass der statische Teil der Szenenbeschreibung verschwunden ist und durch die Beschreibungen der Objekte, die Sie genommen haben, ersetzt wurde. Um die vollständige Szenenbeschreibung wieder zu sehen, klicken Sie entweder auf den Szenennamen – »1. Lektion« – oben oder drücken Sie F5. Das Ergebnis wird identisch sein.^^ {Weiter}]], es = [[Genial!^ Te abrás dado cuenta que la parte estática de la descripción ya no está; reemplazada por las descripciones de los objetos que cogiste. Para ver nuevamente la descricpión completa de esta escena puedes clickear en el nombre arriba (Lección 1) o pulsar F5. Es lo mismo.^^ {Siguiente}]], fr = [[Excellent !^Vous avez probablement remarqué que la partie statique de la description de la scène a disparu, remplacée par les descriptions des objets que vous avez pris. Pour voir à nouveau la description complète de la scène, cliquez sur le nom de la scène au sommet – « Leçon nº 1 » – ou appuyez sur F5. Le résultat est le même.^^ {Suivant}]], it = [[Eccellente!^Avrete probabilmente notato che la parte statica della descrizione della scena è scomparsa, rimpiazzata dalla descrizione degli oggetti che avete preso. Per vedere di nuovo la descrizione completa della scena potete fare click sul nome della scena in alto — "Lezione 1" o premere F5. Il risultato è lo stesso.^^ {Next}]], nl = [[Fantastisch!^Je hebt waarschijnlijk gemerkt dat het statische gedeelte van de scène beschrijving verdwenen is. Het werd vervangen met de omschrijving van de objecten die je gepakt hebt. Als je de volledige omschrijving nogmaals wilt lezen, klik je danwel op de naam van de scène bovenin (dus op "Les 1"), of je drukt op F5. Beide geeft hetzelfde resultaat.^^ {Volgende}]], pt = [[Excelente!^Você provavelmente notou que a parte estática da descrição da cena desapareceu, substituída pelas descrições dos objetos que você pegou. Para ver a descrição completa da cena novamente clique no seu nome no alto da da página — "Lição 1" ou tecle F5. O resultado é o mesmo.^^ {Próxima}]], uk = [[Відмінно!^Ви, швидше за все помітили, що статична частина опису сцени зникла, поступившись місцем опису предметів, котрі Ви взяли. Щоб знову подивитись повний опис сцени, можна нажати на її назву, відображену у верхній частині вікна -- "Урок 1". Окрім того, можна нажати клавішу F5 на клавіатурі, результат буде такий само.^^ {Далі}]], }; act = function() walk 'r2' end; }:disable(); } room { nam = 'r2'; disp = L { ru = 'Урок 2', en = 'Lesson 2', de = '2. Lektion', es = 'Lección 2', fr = 'Leçon nº 2', it = 'Lezione 2', nl = 'Les 2', pt = 'Lição 2', uk = 'Урок 2', }; enter = function(s) lifeon(s) end; life = function(s) if not _'paper'.seen or not _'pencil'.seen then return end lifeoff(s) enable '#cont' end, dsc = L { ru = [[Урок 2. Использование инвентаря - Часть I^^ Теперь у Вас появились предметы, которые можно использовать или изучать. Для этого предназначен инвентарь. Вы можете посмотреть на любой предмет инвентаря дважды щелкнув мышью по этому предмету. То же самое можно сделать с помощью клавиатуры: нажмите "Tab", чтобы переключиться на панель инвентаря, выберите нужный предмет и дважды нажмите "Ввод". Чтобы вернуться назад к описанию сцены, нажмите "Tab" еще раз.^^ Итак, посмотрите на бумагу. Затем, повторите эту операцию с карандашом.]], en = [[Lesson 2. Using the inventory — Part I^^ Now you've got objects that you can examine or use. That's what the inventory is for. To look at any object double click on it. Or you can switch the cursor to the inventory with "Tab", choose an object and press "enter" twice. To return the cursor to the scene description, press "Tab" again.^^ So, look at the paper. Then do the same with the pencil.]], de = [[2. Lektion: Benutzung des Inventars – 1. Teil^^ Nun haben Sie Objekte, die Sie untersuchen oder benutzen können. Dafür ist das Inventar da. Um ein beliebiges Objekt zu betrachten, doppelklicken Sie darauf. Alternativ können Sie zum Inventar mit [Tab] wechseln, und ein Objekt auswählen, indem Sie zwei mal die Eingabetaste drücken. Um den Zeiger zurück zur Szenenbeschreibung zu bewegen, drücken Sie erneut [Tab].^^ Sehen Sie sich das Papier an. Dann tun Sie dasselbe mit dem Stift.]], es = [[Lección 2. Usando el inventario — Parte I^^ Ahora tienes en tu poder objetos que puedes examinar o usar. Eso es tu inventario. Para examinar un objeto haz doble click en él. O puedes manejar el cursor con la tecla "Tab", elegir un objeto y presionar Enter dos veces. Para volver el cursor a la descripción de la escena, presiona nuevamente "Tab".^^ Ok, examina el papel. Y haz lo propio con el lápiz.]], fr = [[Leçon nº 2. Utiliser l'inventaire — Partie I^^ Vous avez maintenant des objets que vous pouvez examiner ou utiliser. L'inventaire est fait pour cela. Pour regarder un objet, double-cliquez dessus. Ou alors, vous pouvez faire passer le curseur dans l'inventaire avec « Tab », y choisir un objet et appuyer sur « Entrée » deux fois. Pour ramener le curseur à la description de la scène, appuyez sur « Tab » à nouveau.^^ Regardez maintenant le papier. Faites ensuite la même chose avec le crayon.]], it = [[Lezione 2. Usare l'inventario — Parte I^^ Ora avete nel vostro inventario due oggetti che potete esaminare od usare. Per esaminare un qualsiasi oggetto fate doppio click su di esso oppure potete posizionare il cursore nell'inventario con il tasto "Tab", scegliete l'oggetto e premete "invio" due volte. Per tornare con il cursore alla descrizione della scena premete di nuovo "Tab"^^ Ora, osservate il foglio, e quindi fate lo stesso con la matita.]], nl = [[Les 2. Het gebruik van de inventaris — Deel I^^ Je hebt nu objecten die je kunt onderzoeken of gebruiken. Daarvoor is het inventarisscherm. Om een object te bekijken, klik je er twee keer op. Of je kan met de "Tab" toets naar het inventarisscherm schakelen en vervolgens het betreffende object kiezen met de pijltjestoetsen, en dan twee keer op "Enter" drukken. Om terug te gaan naar het gedeelte omschrijving kun je daarna weer op "Tab" drukken.^^ Dus, bekijk nu het papier, en bekijk daarna ook het potlood.]], pt = [[Lição 2. Usando o inventário — Parte I^^ Agora você tem objetos para examinar ou usar. O inventário é para isso. Para examinar algum objeto dê duplo clique nele. Ou você pode mover o cursor para o inventário com a tecla "Tab", escolha um objeto e tecle "enter" duas vezes. Para levar o cursor de volta para a descrição da cena, tecle "Tab" novamente.^^ Então, examine o lápis. Faça o mesmo com o papel.]], uk = [[Урок 2. Використання інвентарю - Частина I^^ Тепер у Вас з'явилися предмети, котрі можно використовувати чи вивчати. Для цього призначений інвентар. Ви можете подивитися на будь-який предмет інвентарю двічи клацнувши мишею по цьому предмету. Те ж саме можна зробити за допомогою клавіатури: нажміть "Tab", щоб перемкнутися на панель інвентарю, оберіть потрібний предмет і двічі нажміть "Введення". Щоб повернутися назад до опису сцени, нажмить "Tab" ще раз.^^ Отже, подивіться на папір. Потім, повторіть цю операцію з олівцем.]], }; }:with { obj { nam = '#cont'; dsc = L { ru = "Хорошо!^^{Дальше}", en = "Good!^^{Next}", de = "Gut!^^{Weiter}", es = "Bien!^^{Siguiente}", fr = "Bien !^^{Suivant}", it = "Bene!^^{Avanti}", nl = "Goed!^^{Volgende}", pt = "Muito Bem!^^{Próxima}", uk = "Гарно!^^{Далі}", }; act = function() walk 'r3' end; }:disable(); } obj { nam = 'apple'; disp = L { ru = 'яблоко', en = 'apple', de = 'Apfel', es = 'manzana', fr = 'pomme', it = 'mela', nl = 'appel', pt = 'maçã', uk = 'яблуко', }; dsc = L { ru = 'На столе лежит {яблоко}.', en = "There's an {apple} on the table.", de = 'Auf dem Tisch liegt ein {Apfel}.', es = 'Hay una {manzana} sobre la mesa.', fr = 'Il y a une {pomme} sur le bureau.', it = "C'è una {mela} sul tavolo.", nl = 'Er ligt een {appel} op de tafel.', pt = 'Há uma {maçã} na mesa.', uk = 'На столі лежить {яблуко}.', }; tak = L { ru = 'Вы взяли яблоко со стола.', en = "You take an apple from the table.", de = 'Sie nehmen sich einen Apfel vom Tisch.', es = 'Coges la manzana de la mesa.', fr = 'Vous prenez la pomme sur le bureau.', it = 'Prendi la mela dal tavolo.', nl = 'Je pakt de appel van de tafel.', pt = 'Você pega a maçã da mesa.', uk = 'Ви взяли яблуко зі столу.', }; knife = false; inv = function(s) if here() ^ 'r4' then remove(s) p (L { ru = "Вы съедаете яблоко.", en = "You eat the apple.", de = 'Sie essen den Apfel.', es = 'Te comes la manzana.', fr = 'Vous mangez la pomme.', it = 'Mangi la mela.', nl = 'Je eet de appel op.', pt = 'Você comeu a maçã.', uk = 'Вы з`їдаєте яблуко.', }) return end p (L { ru = "Выглядит аппетитно.", en = "Looks appetizing.", de = 'Sieht appetitlich aus.', es = 'Luce apetecible.', fr = 'Elle est appétissante.', it = 'Sembra appetitosa.', nl = 'Ziet er smakelijk uit.', pt = 'Hum, apetitosa.', uk = 'Виглядає апетитно.', }) end } obj { nam = 'desk'; disp = L { ru = 'стол', en = 'desk', de = 'Schreibtisch', es = 'escritorio', fr = 'bureau', it = 'scrivania', nl = 'bureau', pt = 'escrivaninha', uk = 'стіл', }, dsc = L { ru = 'На этом уроке вы видите деревянный {письменный стол}.', en = 'In this lesson you see a wooden {desk}.', de = 'In dieser Lektion sehen Sie einen hölzernen {Schreibtisch}.', es = 'Aquí ves un {escritorio} de madera.', fr = 'Dans cette leçon, vous voyez un {bureau} en bois.', it = 'Puoi vedere una {scrivania} di legno.', nl = 'In deze ruimte zie je een houten {bureau}.', pt = 'Você vê aqui uma {escrivaninha} de madeira.', uk = 'В цьому уроці ви бачите дерев`яний {письмовий стіл}.', }, haswriting = false; seen = false; act = function(s) if s.haswriting then s.seen = true; p (L { ru = 'Большой дубовый письменный стол. На столешнице видна мелкая надпись карандашом: "Lorem Ipsum".', en = [[Large oaken desk. There's a pencil inscription on its top: "Lorem Ipsum".]], de = 'Ein großer Schreibtisch aus Eichenholz. Auf seiner Oberfläche steht mit einem Bleistift geschrieben: »Lorem Ipsum«.', es = 'Un gran escritorio de roble. Hay algo escrito en él: "Lorem Ipsum".', fr = 'Un grand bureau en chêne. Il y a dessus une inscription au crayon : « Lorem Ipsum ».', it = [[Una larga scrivania di legno. C'è un'iscrizione sul piano: "Lorem Ipsum".]], nl = 'Een groot eiken bureau. Er is met potlood op geschreven: "Lorem Ipsum".', pt = 'Uma grande escrivaninha de carvalho. Há uma inscrição a lápis no seu topo: "Lorem Ipsum".', uk = 'Великий дубовий письмовий стіл. На стільниці видно дрібний напис олівцем: "Lorem Ipsum".', }) return end p (L { ru = "Большой дубовый письменный стол.", en = "Large oaken desk.", de = 'Ein großer Schreibtisch aus Eichenholz.', es = 'Un gran escritorio de roble.', fr = 'Un grand bureau en chêne.', it = 'Una larga scrivania in legno.', nl = 'Een groot eiken bureau.', pt = 'Uma grande escrivaninha de carvalho.', uk = 'Великий дубовий письмовий стіл.', }) end; used = function(s, w) if w ^ 'pencil' and not s.haswriting then s.haswriting = true p (L { ru = "Вы пишете на столешнице несколько букв.", en = "You write several letters on the desk.", de = 'Sie schreiben einige Buchstaben auf den Tisch.', es = 'Garabateas unas palabras sobre el escritorio.', fr = 'Vous griffonnez plusieurs lettres sur le bureau.', it = 'Scrivi alcune lettere sulla scrivania.', nl = 'Je schrijft enkele letters op het bureau.', pt = 'Você escreve várias letras na escrivaninha.', uk = 'Ви пишете на столешні декілька літер.', }) return end return false end; }:with { 'apple' } room { nam = 'r3'; disp = L { ru = 'Урок 3', en = 'Lesson 3', de = '3. Lektion', es = 'Lección 3', fr = 'Leçon nº 3', it = 'Lezione 3', nl = 'Les 3', pt = 'Lição 3', uk = 'Урок 3', }; enter = function(s) lifeon(s) end; life = function(s) if not _'desk'.seen or not have 'apple' then return end lifeoff(s) enable '#cont' end; dsc = L { ru = [[Урок 3. Использование инвентаря - Часть II^^ Вы можете действовать предметами инвентаря на другие предметы сцены или инвентаря. В этой комнате вы увидите стол. Попробуйте воздействовать карандашом на стол.^^ Для этого нажмите мышью на карандаш, а затем на стол. То же самое можно сделать с помощью клавиатуры: используя клавиши "Tab", "Ввод" и "стрелки".^^ Затем посмотрите на стол. И не забудьте взять яблоко, оно нам пригодится в следующем уроке.]], en = [[Lesson 3. Using the inventory — Part II^^ You can act with inventory objects on other objects of the scene or inventory. In this room you'll see a desk. Try using pencil on it.^^ To do that click mouse on the pencil, then click on the desk. Or you can do the same with "Tab", "enter" and arrows.^^ Then look at the table. And don't forget to take the apple, you'll need it in the next lesson.]], de = [[3. Lektion: Benutzung des Inventars – 2. Teil^^ Sie können mit Inventar- oder anderen Objekten der Szene oder des Inventars interagieren. In diesem Raum sehen Sie einen Schreibtisch. Versuchen Sie, den Stift auf ihn anzuwenden.^^ Um das zu tun, klicken Sie mit der Maus auf den Stift, dann klicken Sie auf den Tisch. Alternativ können Sie dasselbe mit [Tab], [Eingabe] und den Pfeiltasten tun.^^ Dann sehen Sie sich den Tisch an. Und vergessen Sie nicht, den Apfel zu nehmen, Sie werden ihn in der nächsten Lektion benötigen.]], es = [[Lección 3. Usando el inventario — Parte II^^ Puedes combinar una acción con un objeto de tu inventario y un objeto de la escena o del mismo inventario. En esta habitación verás un escritorio. Prueba usar el lápiz con él.^^ Para ello, haz click sobre el lápiz, y entonces click sobre el escritorio. O puedes conseguir lo mismo con "Tab", "Enter" y las flechas de tu teclado.^^ A continuación, examina el escritorio. Y no te olvides de coger la manzana. La necesitarás para la próxima lección.]], fr = [[Leçon nº 3. Utiliser l'inventaire — Partie II^^ Vous pouvez faire agir les objets de l'inventaire sur d'autres objets de la scène ou de l'inventaire. Dans cette salle, vous verrez un bureau. Essayez d'utiliser un crayon sur lui.^^ Pour ce faire, cliquez avec la souris sur le crayon, puis cliquez sur le bureau. Ou alors, vous pouvez faire la même chose au clavier avec « Tab », « Entrée » et les flèches.^^ Il suffit ensuite de regarder le bureau pour voir le résultat. Et n'oubliez pas de prendre la pomme, vous en aurez besoin dans la prochaine leçon.]], it = [[Lezione 3. Usare l'inventario — Parte II^^ Potete agire con oggetti dell'inventario su altri oggeti della scena o dell'inventario stesso. In questa locazione potete vedere una scrivania. Provate ad usare la matita su di essa.^^ Per farlo fate click con il mouse sulla matita, e quindi sulla scrivania. Oppure usate la tastiera con i tasti "Tab", "invio" e le frecce.^^ Ora guardate il tavolo e non scordatevi di prendere la mela, ne avrete bisogno per la prossima dimostrazione.]], nl = [[Les 3. Het gebruik van de inventaris — Deel II^^ Objecten in de inventaris kun je ook gebruiken in combinatie met andere objecten. Die andere objecten kunnen zich ook in de inventaris bevinden, maar kunnen ook objecten uit de scène beschrijving zijn. In de huidige ruimte bevind zich een bureau. Probeer het potlood daarop te gebruiken.^^ Om dat te doen, klik je eerst op het potlood, vervolgens op het bureau. Dat kan natuurlijk ook met het toetsenbord met behulp van de "Tab", "Enter" en pijltjestoetsen.^^ Kijk vervolgens naar de tafel. En pak tenslotte ook de appel op, die heb je nodig in de volgende les.]], pt = [[Lição 3. Usando o inventário — Parte II^^ Você pode usar objetos do inventário para afetar outros objetos da cena ou do inventário. Neste local você vê uma escrivaninha. Tente usar o lápis nela.^^ Para isso clique com o mouse no lápis, então clique na escrivaninha. Ou você pode fazer o mesmo com "Tab", "enter" e as setas do teclado.^^ Então examine a mesa. E não esqueça de pegar a maçã, você precisará dela na próxima lição.]], uk = [[Урок 3. Використання інвентаря - Частина II^^ Ви можете задіяти предмети інвентарю на інші предмети сцени чи інвентарю. В цій комнаті ви бачите стіл. Спробуйте задіяти олівець на стіл.^^ Для цього клацніть мишей на олівець, а потім на стіл. Те ж саме можна зробити за допомогою клавіатури: використовуючи клавіши "Tab", "Введення" й "стрілки".^^ Потім подивіться на стіл. І не забудьте взяти яблуко, воно нам знадобиться в наступному уроці.]], }; }:with { 'desk'; obj { nam = '#cont'; dsc = L { ru = "{$|^^}{Дальше}", en = "{$|^^}{Next}", de = "{$|^^}{Weiter}", es = "{$|^^}{Siguiente}", fr = "{$|^^}{Suivant}", it = "{$|^^}{Avanti}", nl = "{$|^^}{Volgende}", pt = "{$|^^}{Próxima}", uk = "{$|^^}{Далі}", }; act = function() walk 'r4' end; }:disable(); } room { nam = 'r4'; disp = L { ru = 'Урок 4', en = 'Lesson 4', de = '4. Lektion', es = 'Lección 4', fr = 'Leçon nº 4', it = 'Lezione 4', nl = 'Les 4', pt = 'Lição 4', uk = 'Урок 4', }; enter = function(s) _'apple'.knife = false lifeon(s) end; life = function(s) if not _'paper'.haswriting or have 'apple' then return end lifeoff(s) enable '#cont' end; dsc = L { ru = [[Урок 4. Использование инвентаря - Часть III^^ Хорошо, теперь изучим еще несколько действий с предметами.^^ Во-первых, напишите что-нибудь на бумаге. Для этого нажмите мышью на карандаш, а затем на бумагу. После этого вы можете посмотреть на бумагу, чтобы увидеть вашу запись.^^ Во-вторых, съешьте яблоко, которое Вы взяли со стола в предыдущей комнате. Для этого дважды щелкните по яблоку в инвентаре.^^ Все описанные действия можно выполнить с помощью клавиатуры так же, как показано в предыдущем уроке.]], en = [[Lesson 4. Using the inventory — Part III^^ Good, now let's learn several more actions with objects.^^ First, write something on the paper. Click pencil, then paper. Then you can look at the paper to see your writing.^^ Second, eat an apple, you've taken in the previous room. Double click on it.^^ All those actions can be done with keyboard as described previously.]], de = [[4. Lektion: Benutzung des Inventars – 3. Teil^^ Gut, nun lassen Sie uns einige weitere Aktionen mit Objekten lernen.^^ Erstens: Schreiben Sie etwas auf das Papier. Klicken Sie den Stift, dann das Papier an. Dann können Sie sich das Papier ansehen, um sich Ihr Schreiben anzusehen. Zweitens: Essen Sie den Apfel, den Sie vom vorherigen Raum genommen haben. Doppelklicken Sie ihn.^^ All diese Aktionen können mit der Tastatur durchgeführt werden, wie zuvor beschrieben.]], es = [[Lección 4. Usando el inventario — Parte III^^ Bien, ahora veamos un par de acciones más sobre objetos.^^ Primero, escribir algo en el papel. Haz click en el lápiz y luego en el papel. Y entonces examina el papel para ver lo que haz escrito.^^ Segundo, cómete la manzana que cogiste en la escena anterior. Haz doble click en ella.^^ Todas estas acciones también pueden ejecutarse con tu teclado, como ya se ha descrito.]], fr = [[Leçon nº 4. Utiliser l’inventaire — Partie III^^ Bon, maintenant, nous allons étudier plusieurs autres actions sur les objets.^^ Tout d’abord, écrivez quelque chose sur le papier. Cliquez sur le crayon, puis sur le papier. Vous pourrez ensuite regarder le document pour voir le résultat.^^ Deuxièmement, mangez la pomme que vous avez prise dans la salle précédente. Double-cliquez sur elle.^^ Toutes ces actions peuvent être faites avec le clavier comme décrit précédemment.]], it = [[Lezione 4. Usare l'inventario — Parte III^^ Bene, ora vediamo qualche altra azione con gli oggetti.^^ Come prima cosa, scrivete qualcosa sul foglio. Fate click sulla matita e quindi sul foglio. Ora potete osservare il foglio e controllare cosa avete scritto.^^ Come secondo passo, mangiate la mela, l'avete presa nella precedente locazione. Per farlo fate doppio click su di essa.^^ Tutte queste azioni possono essere eseguite anche con la tastiera come già descritto in precedenza.]], nl = [[Les 4. Het gebruik van de inventaris — Deel III^^ We gaan nu verdere acties met objecten leren.^^ Om te beginnen schrijf je iets op het papier. Klik daarvoor op het potlood, daarna op het papier. Kijk vervolgens op het papier om het resultaat te bekijken.^^ Eet tenslotte de appel op die je meegenomen hebt uit de vorige ruimte. Klik hiervoor twee maal op de appel.^^ Natuurlijk kan bovenstaande ook weer met het toetsenbord gedaan worden.]], pt = [[Lição 4. Usando o inventário — Parte III^^ Bom, agora vamos aprender diversas outras ações com objetos.^^ Primeiro, escreva algo no papel. Clique no lápis, depois no papel. Então você pode examinar o papel para ver os seus escritos.^^ Segundo, coma a maçã que você pegou no local anterior. Dê duplo clique nela.^^ Todas estas ações podem ser realizadas com o teclado, conforme descrito antes.]], uk = [[Урок 4. Використання інвентарю - Частина III^^ Гаразд, тепер вивчимо ще декілька дій з предметами.^^ По-перше, напішить що-небудь на папері. Для цього нажміть мишею на олівець, а потім на папір. Після цього ви можете подивитись на папір, щоб побачити ваш запис.^^ По-друге, з'їште яблуко, котре Ви взяли зі столу в попередній кімнаті. Для цього двічи клацніть по яблуку в інвентарі.^^ Всі описані дії можна виконати за допомогою клавіатури так само, як показано в попередньому уроці.]], }; }:with { obj { nam = '#cont'; dsc = L { ru = "Хорошо.^^{Дальше}", en = "Good.^^{Next}", de = "Gut.^^{Weiter}", es = "Bien!^^{Siguiente}", fr = "Bien.^^{Suivant}", it = "Bene.^^{Avanti}", nl = "Goed.^^{Volgende}", pt = "Muito bem.^^{Próxima}", uk = "Гаразд.^^{Далі}", }; act = function() walk 'r5' end; }:disable(); } room { nam = 'r5'; disp = L { ru = 'Урок 5', en = 'Lesson 5', de = '5. Lektion', es = 'Lección 5', fr = 'Leçon nº 5', it = 'Lezione 5', nl = 'Les 5', pt = 'Lição 5', uk = 'Урок 5', }; onexit = function(s, t) if t ^ 'r6' then return end p (L { ru = "Этот урок мы уже прошли.^ Пожалуйста, перейдите на урок 6.", en = "We've already finished this lesson.^ Go to lesson 6, please.", de = 'Wir haben diese Lektion bereits fertiggestellt.^ Bitte gehen Sie zur 6. Lektion.', es = 'Ya hemos terminado esta lección.^ Ve a la lección 6, por favor.', fr = 'Nous avons déjà terminé cette leçon…^ En avant pour la leçon nº 6, s’il vous plaît.', it = 'Abbiamo già terminato questa parte della guida. Proseguiamo alla prossima, per favore.', nl = 'Die les is al afgerond.^ Ga naar les 6, aub.', pt = 'Já terminamos esta lição.^ Favor seguir para a lição 6.', uk = 'Цей урок ми вже пройшли.^ Будь ласка, перейдіть на урок 6.', }) return false end; dsc = L { ru = [[Урок 5. Перемещение - Часть I^^ Теперь изучим переходы между комнатами. В этой комнате Вы видите пять дополнительных ссылок с номерами уроков. Перейдите на урок 6. ^^ Для этого нажмите мышью на соответствующую ссылку. Вы также можете воспользоваться клавиатурой -- выберите нужную ссылку с помощью клавиш со стрелками и нажмите "Ввод" для перехода.]], en = [[Lesson 5. Moving — Part I^^ Now we'll study the passages between rooms. In this room you see five links with lesson numbers. Go to lesson 6.^^ Click on the appropriate link or use keyboard — pick the link with arrows and press "Enter".]], de = [[5. Lektion: Fortbewegung – 1. Teil^^ Nun werden wir die Fortbewegung zwischen Räumen erlernen. In diesem Raum sehen Sie fünf Links mit Lektionsnummern. Gehen Sie in die 6. Lektion.^^ Klicken Sie auf den passenden Link oder benutzen Sie die Tastatur – wählen Sie den Link mit den Pfeiltasten aus und drücken Sie [Eingabe].]], es = [[Lección 5. Moviéndose — Parte I^^ Ahora analizaremos el movimiento entre localidades. En esta habitación puedes ver 5 links con los nombres de las lecciones. Ve a la lección 6.^^ Haz click en el link correspondiente o usa el teclado (ubica el cursor con las flechas y presiona "Enter").]], fr = [[Leçon nº 5. En mouvement — Partie I^^ Maintenant, nous allons étudier les déplacements entre les pièces. Dans cette salle, vous voyez cinq liens pointant vers les autres leçons. Allez à la leçon nº 6.^^ Cliquez sur le lien approprié ou utilisez le clavier — sélectionnez le lien a l’aide des flèches et appuyez ensuite sur « Entrée ».]], it = [[Lezione 5. Movimenti — Parte I^^ Ora vedremo i passaggi tra una locazione e l'altra. In questa stanza potete vedere cinque link che portano verso le lezioni numerate. Andate alla 6.^^ Fate click sul giusto link o usate la tastera - selezionate il link con le frecce e premete "Invio".]], nl = [[Les 5. Verplaatsen — Deel I^^ We bestuderen nu hoe je je verplaatst naar een andere ruimte. In deze ruimte zie je vijf links met naar verschillende lessen. Ga naar les 6.^^ Klik op de betreffende les met de muis, of gebruik het toetsenbord. (Gebruik de pijltjestoetsen om de juiste les te selecteren, en druk dan op "Enter".]], pt = [[Lição 5. Movendo-se — Parte I^^ Agora vamos estudar as passagens entre os locais. Neste local você vê cinco links com números de lições. Vá para a lição 6.^^ Clique no link apropriado ou use o teclado — selecione o link com as setas e tecle "Enter".]], uk = [[Урок 5. Переміщення - Частина I^^ Тепер вивчимо переходи між кімнатами. В цій кімнаті Ви бачите п'ять допоміжних посилань з номерами уроків. Перейдіть на урок 6. ^^ Для цього натисніть мишею на відповідне посилання. Ви також можете використати клавіатуру -- виберіть потрібне посилання за допомогою клавіш зі стрілками та нажміть "Введення" для переходу.]], }; way = { 'r1', 'r2', 'r3', 'r4', 'r6'}, } room { nam = 'r6'; disp = L { ru = 'Урок 6', en = 'Lesson 6', de = '6. Lektion', es = 'Lección 6', fr = 'Leçon nº 6', it = 'Lezione 6', nl = 'Les 6', pt = 'Lição 6', uk = 'Урок 6', }; onexit = function(s, t) if t ^ 'theend' then return end p (L { ru = "Этот урок мы уже прошли.^ Пожалуйста, перейдите на последний урок.", en = "We've already finished this lesson..^ Go to the last lesson, please.", de = 'Wir haben diese Lektion bereits fertiggestellt.^ Bitte gehen Sie zur letzen Lektion.', es = 'Ya hemos terminado esta lección.^ Ve a la última lección, por favor.', fr = 'Nous avons déjà terminé cette leçon…^ En avant pour la dernière leçon, s’il vous plaît.', it = 'Abbiamo già terminato questa lezione.^ Proseguiamo verso la 6, per favore.', nl = 'Die les is al afgerond.^ Ga naar de laatste les aub.', pt = 'Já terminamos esta lição..^ Favor seguir para a última lição.', uk = 'Цей урок ми вже пройшли.^ Будь ласка, перейдіть на останній урок.', }) return false end; dsc = L { ru = [[Урок 6. Перемещение - Часть II^^ Теперь перейдите на последний урок.]], en = [[Lesson 6. Moving - Part II^^ Now go to the last lesson.]], de = [[6. Lektion: Fortbewegung – 2. Teil^^ Nun gehen Sie zur letzten Lektion.]], es = [[Lección 6. Moviéndose - Parte II^^ Ahora ve a la última lección.]], fr = [[Leçon nº 6. En mouvement — Partie II^^ Rendez-vous à la dernière leçon.]], it = [[Lezione 6. Movimenti - Parte II^^ Ora passiamo all'ultimo step di questa guida.]], nl = [[Les 6. Verplaatsen — Deel II^^ Verplaats jezelf nu naar de laatste les.]], pt = [[Lição 6. Movendo-se - Parte II^^ Agora vá para a última lição.]], uk = [[Урок 6. Переміщення - Частина II^^ Тепер перейдіть на останній урок.]], }; way = { 'r1', 'r2', 'r3', 'r4', 'r5', 'theend'} } room { nam = 'theend'; disp = L { ru = 'Последний урок', en = 'Last lesson', de = 'Letzte Lektion', es = 'Ultima lección', fr = 'Dernière leçon', it = 'Gran Finale', nl = 'Laatste les', pt = 'Última lição', uk = 'Останній урок', }; dsc = L { ru = [[Вы можете выбирать игру, сохранять и загружать её состояние и выполнять другие действия с помощью меню. Для вызова меню нажмите клавишу "Esc" или нажмите мышью на символ меню (справа снизу).^^ Теперь Вы готовы к игре. Удачи!!!^^ Игры для INSTEAD можно скачать здесь: {$fmt u|https://instead-hub.github.io}^^ В обучении использован трек "Instead game-engine" от svenzzon.]], en = [[With the help of the menu you can choose a game, save or load the state, or do other things. To open the menu press "Esc" or click the menu icon at the bottom right.^^ Now you are ready to play. Good luck!!!^^ Download games for INSTEAD here: {$fmt u|http://instead-games.sourceforge.net}^^ The tutorial uses the track "Instead game-engine" from svenzzon.]], de = [[Mithilfe des Menüs können Sie ein Spiel starten, den Spielstand speichern oder laden, oder andere Dinge tun. Um das Menü zu öffnen, drücken Sie [Esc] oder klicken sie das Menüsymbol unten rechts an.^^ Nun sind Sie bereit zum Spielen. Viel Glück!^^ Laden Sie sich Spiele für INSTEAD von dort herunter: {$fmt u|http://instead-games.sourceforge.net}^^ Die Einführung benutzt die Musik »Instead game-engine« von svenzzon.]], es = [[Mediante el menú flotante, puedes elegir un juego, salvar o cargar un juego, y un par de cosas más. Para abrirlo presiona "Esc" o haz click en el icono de menú abajo a la derecha.^^ Ahora ya estás listo para jugar. Buena suerte!!!^^ Descarga nuevos juegos para INSTEAD aquí: {$fmt u|http://instead-games.sourceforge.net}^^ Este tutorial usa el tema "Instead game-engine" de svenzzon.]], fr = [[À l’aide du menu, vous pouvez choisir un jeu, sauvegarder ou charger une partie, ou faire d'autres choses encore. Pour ouvrir le menu, appuyez sur « Esc » ou cliquez sur l'icône de menu en bas à droite (avec le thème par défaut).^^ Maintenant, vous êtes prêt à jouer. Bonne chance !!!^^ Téléchargez des jeux pour INSTEAD ici : {$fmt u|http://instead-games.sourceforge.net}^^ Le tutoriel utilise « INSTEAD game-engine » de svenzzon comme thème musical.]], it = [[Con l'aiuto del menu potete scegliere un gioco, salvare o caricare una partita, oltre a svariate altre cose. Per aprire il menu premete "Esc" o fate click sull'icona di menu in basso a destra.^^ Ora siete pronti a giocare. Buona Fortuna!!!^^ Scaricate i giochi per INSTEAD qui: {$fmt u|http://instead-games.sourceforge.net}^^ Il tutorial si avvale del brano musicale "Instead game-engine" di svenzzon.]], nl = [[In het menu kun je onder andere een ander spel kiezen. Je kunt ook de huidige stand opslaan of weer laden. Om het menu te openen, toets "Esc" of klik met de muis op het hamburger icoon rechts onderin.^^ Je bent nu klaar om te spelen. Veel plezier!!!^^ Download spellen voor INSTEAD hier: {$fmt u|http://instead-games.sourceforge.net}^^ De achtergrondmuziek in deze training is van svenzzon en heet "Instead game-engine".]], pt = [[Com a ajuda do menu você pode escolher um jogo, salvar ou carregar o seu estado, ou fazer outras coisas. Para abrir o menu tecle "Esc" ou clique no ícone do menu à direita no fundo da página.^^ Agora você está pronto para jogar. Boa sorte!!!^^ Baixe jogos aqui: {$fmt u|http://instead-games.sourceforge.net}^^ O tutorial usa o tema "Instead game-engine" de svenzzon.]], uk = [[Ви можете вибирати гру, зберігати та завантажувати її стан і виконувати інші дії за допомогою меню. Для виклику меню натисніть клавішу "Esc" або натисніть мишею на символ меню (справа знизу).^^ Тепер Ви готові до гри. Хай щастить!!!^^ Ігри для INSTEAD можно завантажити тут: {$fmt u|https://instead-hub.github.io}^^ Для навчання використан трек "Instead game-engine" вiд svenzzon.]], }; decor = L { ru = 'Посмотреть {@ walk help|список клавиш}.', en = 'See {@ walk help|list of keyboard shortcuts}.', de = 'Siehe {@ walk help|Liste der Tastenkürzel}.', es = 'Ver {@ walk help|lista de atajos de teclado}.', fr = 'Voir la {@ walk help|liste des raccourcis clavier}.', it = 'Vedi {@ walk help|lista delle scorciatoie da tastiera}.', nl = 'Zie ook de {@ walk help|lijst met sneltoetsen}.', pt = 'Ver {@ walk help|lista de atalhos de teclado}.', uk = 'Подивитись {@ walk help|список клавіш}.', } } room { nam = 'help'; disp = L { ru = 'Список клавиш', en = 'Keyboard shortcuts', de = 'Tastenkürzel', es = 'Atajos de Teclado', fr = 'Raccourcis clavier', it = 'Scorciatoie da tastiera', nl = 'Sneltoetsen', pt = 'Atalhos de teclado', uk = 'Список клавіш', }; dsc = L { ru = [[ Esc - Вызов меню;^ Alt+Q - Выход;^ Alt+Enter - Полноэкранный/оконный режим;^ F5 - Обновление сцены;^ Пробел/Backspace - Прокрутка описания сцены;^ Tab/Shift+Tab - Переключение между активными зонами;^ PgUp/PgDn - Прокрутка активной зоны;^ Стрелки влево/вправо - Выбор ссылок в активной зоне;^ F2 - Сохранение игры;^ F3 - Загрузка игры;^ F8 - Быстрое сохранение игры;^ F9 - Быстрая загрузка игры.^^ Клавиши, поведение которых зависит от выбранного режима клавиатуры (см. Меню -> Настройки -> Режим клавиатуры):^^ Стрелки вверх/вниз:^  - В режиме "Прокрутка": прокрутка активной зоны;^  - В режиме "Ссылки": выбор ссылок в активной зоне;^  - В режиме "Умный": одновременно выбор ссылок и прокрутка активной зоны.^^ Стрелки вверх/вниз + Shift или Alt:^  - В режиме "Прокрутка": выбор ссылок в активной зоне;^  - В режиме "Ссылки": прокрутка активной зоны;^  - В режиме "Умный": прокрутка активной зоны. ]], en = [[ Esc - Menu.^ Alt+Q - Exit.^ Alt+Enter - Full screen/window.^ F5 - Refresh the scene.^ Space/Backspace - Scroll the scene description.^ Tab/Shift+Tab - Switch between active zones.^ PgUp/PgDn - Scroll the active zone.^ Arrows left/right - Choose links in the active zone.^ F2 - Save game.^ F3 - Load game.^ F8 - Quick save.^ F9 - Quick load.^^ Shortcuts, that depend on the chosen keyboard mode (see Menu -> Settings -> Keyboard mode):^^ Arrows up/down:^  - "Scroll" mode: scroll active zone.^  - "Links" mode: choose links in the active zone.^  - "Smart" mode: both choose links and scroll active zone.^^ Arrows up/down + Shift or Alt:^  - "Scroll" mode: choose links in the active zone.^  - "Links" mode: scroll active zone.^  - "Smart" mode: scroll active zone. ]], de = [[ [Esc] – Menü.^ [Alt]+[Q] – Beenden.^ [Alt]+[Enter] – Vollbild/Fenster.^ [F5] – Szene neu laden.^ [Leertaste]/[Rücktaste] – Szenenbeschreibung scrollen.^ [Tab]/[Umschalt]+[Tab] – Zwischen aktiven Zonen wechseln.^ [Bild auf]/[Bild ab] – In der aktiven Zone scrollen.^ [Links]/[Rechts] – Links in der aktiven Zone auswählen.^ [F2] – Spiel speichern.^ [F3] – Spiel laden.^ [F8] – Schnellspeichern.^ [F9] – Schnellladen.^^ Tastenkürzel, die vom ausgewählten Tastaturmodus abhängen (siehe Menü -> Einstellungen -> Tastaturmodus):^^ [Hoch]/[Runter]:^  – Scrollmodus: In der aktiven Zone scrollen.^  – Linksmodus: Links in der aktiven Zone auswählen.^  – Intelligenter Modus: Sowohl Links auswählen als auch scrollen.^^ [Hoch]/[Runter] + [Umschalt] oder [Alt]:^  – Schrollmodus: Links in der aktiven Zone auswählen.^  – Linksmodus: In der aktiven Zone scrollen.^  – Intelligenter Modus: In der aktiven Zone scrollen. ]], es = [[ Esc - Menú.^ Alt+Q - Salir.^ Alt+Enter - Pantalla Completa/Ventana.^ F5 - Actualizar escena.^ Espacio/Backspace - Desplazar la descripción de la escena.^ Tab/Shift+Tab - Cambiar entres zonas activas.^ PgUp/PgDn - Desplazar el contenido de la zona activa.^ Teclas izqu/derecha - Elegir links en la zona activa.^ F2 - Salvar juego.^ F3 - Cargar juego.^ F8 - Salvado Express.^ F9 - Carga Express.^^ Atajos que dependen del modo de teclado elegido (ver Menú->Opciones->Modo Teclado):^^ Flechas arriba/abajo:^  - Modo "Scroll": hace scroll de zona activa.^  - Modo "Links": elige los links en la zona activa.^  - Modo "Smart": combina las dos anteriores.^^ Flechas arriba/abajo + Shift o Alt:^  - Modo "Scroll": elige los links en la zona activa.^  - Modo "Links": hace scroll de zona activa.^  - Modo "Smart": hace scroll de zona activa. ]], fr = [[ Esc – Menu^ Alt+Q – Quitter^ Alt+Entrée – Plein écran/Fenêtre^ F5 – Rafraîchir la scène^ Espace/Effacement arrière – Faire défiler la description de la scène^ Tab/Maj+Tab – Basculer entre les zones actives^ PgUp/PgDn – Faire défiler les zones actives^ Flèches gauche/droite – Sélection des liens dans la zone active^ F2 – Sauvegarder la partie^ F3 – Charger une partie^ F8 – Sauvegarde rapide^ F9 – Chargement rapide^^ Les raccourcis dépendent du mode de clavier choisi^ (cf. Menu → Réglages → [Autres] → Mode clavier) :^^ Flèches haut/bas :^ - mode « Scroll » : défilement zone active.^ - mode « Links » : sélection des liens dans la zone active.^ - mode « Smart » : à la fois sélection des liens et défilement dans la zone active.^^ Flèches haut/bas + Shift ou Alt :^ - mode « Scroll » : sélection des liens dans la zone active.^ - mode « Links » : défilement dans la zone active.^ - mode « Smart » : défilement dans la zone active. ]], it = [[ Esc - Menu.^ Alt+Q - Esci.^ Alt+Enter - Schermo intero/finestra.^ F5 - Ristampa la descrizione completa della scena.^ Space/Backspace - Scorri la descrizione della scena.^ Tab/Shift+Tab - Passa da una zona attiva all'altra.^ PgUp/PgDn - Scorri la zona attiva.^ Freccia sinistra/destra - Scegli i link nella zona attiva.^ F2 - Salva la partita.^ F3 - Carica la partita.^ F8 - Salvataggio veloce.^ F9 - Caricamento veloce.^^ Le scorciatoie sono attive se si sceglie la modalità tastiera nelle impostazioni (vedi Menu -> Impostazioni -> Keyboard mode):^^ Frecce su/giù:^  - "Scroll" mode: scorre la zona attiva.^  - "Links" mode: sceglie i link nella zona attiva.^  - "Smart" mode: sceglie i link e scorre la zona attiva.^^ Frecce su/giù + Shift o Alt:^  - "Scroll" mode: sceglie i link nella zona attiva.^  - "Links" mode: scorre la zona attiva.^  - "Smart" mode: scorre la zona attiva. ]], nl = [[ Esc - Menu.^ Alt+Q - Afsluiten.^ Alt+Enter - Volledig scherm/venster.^ F5 - Ververs de scène.^ Spatie/Backspace - Scroll door de scène beschrijving.^ Tab/Shift+Tab - Schakel tussen de beschrijving en inventaris zone.^ PgUp/PgDn - Scroll de tekst van de actieve zone.^ Pijltjes rechts/links - Kies objecten in de actieve zone.^ F2 - Het spel opslaan.^ F3 - Een opgeslagen spel laden.^ F8 - Snel opslaan.^ F9 - Snel laden.^^ Sneltoetsen die afhankelijk zijn van de pijltjestoetsen mode (zie Menu -> Instellingen -> Overig -> Pijltjestoetsen):^^ Functie pijltje omhoog/omlaag:^  - in "Scroll" mode: scroll de tekst van de actieve zone.^  - in "Object" mode: kies objecten in het zichtbare gedeelte van de actieve zone.^  - in "Intelligente" mode: zowel scrollen als objecten kiezen in de actieve zone.^^ Functie pijltje omhoog/omlaag met Shift of Alt:^  - in "Scroll" mode: kies objecten in het zichtbare gedeelte van de actieve zone.^  - in "Object" mode: scroll de tekst van de actieve zone.^  - in "Intelligente" mode: scroll de tekst van de actieve zone. ]], pt = [[ Esc - Menu.^ Alt+Q - Sair.^ Alt+Enter - Tela cheia/janela.^ F5 - Atualizar cena.^ Space/Backspace - Rolar descrição da cena.^ Tab/Shift+Tab - Alternar áreas ativas.^ PgUp/PgDn - Rolar área ativa.^ Arrows left/right - Selecionar links na área ativa.^ F2 - Salvar jogo.^ F3 - Carregar jogo.^ F8 - Salvar rápido.^ F9 - Carregar rápido.^^ Atalhos que dependem do modo de teclado escolhido (Ver Menu -> Opções -> Modo de teclado):^^ Setas acima/abaixo:^  - Modo "Scroll": rolar área ativa.^  - Modo "Links": selecionar links na área ativa.^  - Modo "Smart": selecionar links e rolar área ativa.^^ Setas acima/abaixo + Shift ou Alt:^  - Modo "Scroll": selecionar links na área ativa.^  - Modo "Links": rolar área ativa.^  - Modo "Smart": rolar área ativa. ]], uk = [[ Esc - Виклик меню;^ Alt+Q - Вихід;^ Alt+Enter - Повноекранний/віконний режим;^ F5 - Оновлення сцени;^ Пробел/Backspace - Прокрутка опису сцени;^ Tab/Shift+Tab - Переключення між активними зонами;^ PgUp/PgDn - Прокрутка активної зони;^ Стрілки вліво/вправо - Вибір посиланнь в активній зоні;^ F2 - Збереження гри;^ F3 - Завантаження гри;^ F8 - Швидке збереження гри;^ F9 - Швидке завантаження гри.^^ Клавіши, поведінка яких залежить від обраного режиму клавіатури (див. Меню -> Налаштування -> Режим клавіатури):^^ Стрілки вгору/вниз:^  - В режимі "Прокрутка": прокрутка активної зони;^  - В режимі "Посилання": вибір посиланнь в активній зоні;^  - В режимі "Розумний": одночасний вибір посиланнь та прокрутка активної зони.^^ Стрілки вгору/вниз + Shift або Alt:^  - В режимі "Прокрутка": вибір посиланнь в активній зоні;^  - В режимі "Посилання": прокрутка активної зони;^  - В режимі "Розумний": прокрутка активної зони. ]], }; decor = L { ru = 'Посмотреть {@ walk help2|параметры командной строки}.', en = 'See {@ walk help2|command line parameters}.', de = 'Siehe {@ walk help2|Kommandozeilenparameter}.', es = 'Ver {@ walk help2|parámetros línea de comandos}.', fr = 'Voir les {@ walk help2|paramètres de la ligne de commande}.', it = 'Vedi {@ walk help2|parametri della linea di comando}.', nl = 'Zie {@ walk help2|commandoregel parameters}.', pt = 'Ver {@ walk help2|parâmetros de linha de comando}.', uk = 'Подивитись {@ walk help2|параметри командного рядка}.', }; } room { nam = 'help2'; disp = L { ru = 'Параметры командной строки', en = 'Command line parameters', de = 'Kommandozeilenparameter', es = 'Parámetros línea de comandos', fr = 'Paramètres de la ligne de commande', it = 'Parametri della linea di comando', nl = 'Commandoregel parameters', pt = 'parâmetros de linha de comando', uk = 'Параметри командного рядка', }; dsc = L { ru = [[ -nosound - запуск без звука;^ -debug - отладочный режим для разработчика игр;^ -theme <тема> - выбор темы;^ -game <игра> - выбор игры;^ -themespath <путь> - дополнительный путь к темам;^ -gamespath <путь> - дополнительный путь к играм;^ -window - оконный режим;^ -fullscreen - полноэкранный режим;^ -noautosave - отключить автосохранение/автозагрузку;^ -encode [encoded.lua] - закодировать исходный текст lua (используйте doencfile для загрузки такого файла);^ -mode [ШИРИНАxВЫСОТА] - установить разрешение. ]], en = [[ -nosound - launch without sound;^ -debug - debug mode for game developers;^ -theme - pick a theme;^ -game - pick a game;^ -themespath - additional path to themes;^ -gamespath - additional path to games;^ -window - windowed mode;^ -fullscreen - fullscreen mode;^ -noautosave - disable autosave/autoload option;^ -encode [encoded.lua] - encode lua source code (use doencfile from lua to load it);^ -mode [WxH] - use WxH resolution. ]], de = [[ -nosound – Ohne Ton starten;^ -debug – Debugmodus für Spielentwickler;^ -theme – Ein Thema auswählen;^ -game – Ein Spiel auswählen;^ -themespath – Zusätzlicher Pfad für Themen;^ -gamespath – zusätzlicher Pfad für Spiele;^ -window – Fenstermodus;^ -fullscreen – Vollbildmodus;^ -noautosave – Automatisches Speichern/Laden deaktivieren;^ -encode [kodiert.lua] – Lua-Quellcode kodieren (benutzen Sie doencfile aus Lua, um es zu laden);^ -mode [BxH] – Auflösung von B×H benutzen. ]], es = [[ -nosound - lanza sin sonido;^ -debug - modo debug para desarrolladores;^ -theme - elige un tema;^ -game - elige un juego;^ -themespath - ruta adicional para los temas;^ -gamespath - ruta adicional para los juegos;^ -window - modo ventana;^ -fullscreen - pantalla completa;^ -noautosave - deshabilita opción autosalvar/autocargar;^ -encode [encoded.lua] - encode del código fuente lua (usar doencfile desde lua para cargarlo);^ -mode [WxH] - usa resolusion WxH. ]], fr = [[ -nosound – lancement sans son^ -debug – mode debugage pour les développeurs^ -theme – choisir un thème^ -game – choisir un jeu^ -themespath – chemin supplémentaire pour les thèmes^ -gamespath – chemin supplémentaire pour les jeux^ -window – mode fenêtré^ -fullscreen – mode plein écran^ -noautosave – désactiver les options de sauvegarde auto./chargement auto.^ -encode [encoded.lua] – encoder code source lua (utilisation doencfile de lua pour charger)^ -mode [WxH] – utiliser la résolution WxH (LxH). ]], it = [[ -nosound - lancia il gioco senza suono;^ -debug - modalità di debug per sviluppatori di giochi;^ -theme - scegli un tema;^ -game - scegli un gioco;^ -themespath - percorsi addizionali per i temi;^ -gamespath - percorsi addizionali per i giochi;^ -window - modalità finestra;^ -fullscreen - modalità a tutto schermo;^ -noautosave - disabilita l'opzione di autosalvataggio/autocaricamento;^ -encode [encoded.lua] - comprime il codice sorgente di lua (usate doencfile da lua per caricarlo);^ -mode [WxH] - usa la risoluzione WxH. ]], nl = [[ -nosound - start zonder geluid;^ -debug - debug mode voor ontwikkelaars van spellen;^ -theme - kies een skin/thema;^ -game - kies een spel;^ -themespath - extra folder met skins/thema's;^ -gamespath - extra folder met spellen;^ -window - gebruik een venster;^ -fullscreen - gebruik het volledige scherm;^ -noautosave - schakel het automatisch opslaan en laden uit;^ -encode [encoded.lua] - encodeer lua source code (gebruik "doencfile" in lua om het te laden);^ -mode [WxH] - gebruik de schermresolutie WxH. ]], pt = [[ -nosound - executar sem som;^ -debug - modo de depuração para desenvolvedores de jogos;^ -theme - escolha um tema;^ -game - escolha um jogo;^ -themespath - endereço adicional para temas;^ -gamespath - endereço adicional para jogos;^ -window - modo de janela;^ -fullscreen - modo de tela cheia;^ -noautosave - desabilitar opções de salvar/carregar automaticamente;^ -encode [codificado.lua] - codificar código-fonte Lua (usar doencfile de Lua para carregá-lo);^ -mode [WxH] - usar resolução WxH. ]], uk = [[ -nosound - запуск без звуку;^ -debug - режим налагоджування для розробників ігр;^ -theme <тема> - вибір теми;^ -game <гра> - вибір гри;^ -themespath <шлях> - додатковий шлях до тем;^ -gamespath <шлях> - додатковий шлях до ігр;^ -window - віконний режим;^ -fullscreen - повноекранний режим;^ -noautosave - відключити автозбереження/автозагрузку;^ -encode [encoded.lua] - закодувати вихідний текст lua (використовуйте doencfile для загрузки такого файла);^ -mode [ШИРИНАxВИСОТА] - встановити роздільну здатність екрану. ]] }; decor = L { ru = 'Посмотреть {@ walk help|список клавиш}.', en = 'See {@ walk help|list of keyboard shortcuts}.', de = 'Siehe {@ walk help|Liste der Tastenkürzel}.', es = 'Ver {@ walk help|lista de atajos de teclado}.', fr = 'Voir la {@ walk help|liste des raccourcis clavier}.', it = 'Vedi {@ walk help|lista delle scorciatorie da tastiera}.', nl = 'Zie ook de {@ walk help|lijst met sneltoetsen}.', pt = 'Ver {@ walk help|lista de atalhos de teclado}.', uk = 'Подивитись {@ walk help|список клавіш}.', }; } instead-3.5.2+dfsg/games/tutorial/uk.png000066400000000000000000000006761467622671600202050ustar00rootroot00000000000000PNG  IHDR ngAMA7tEXtSoftwareAdobe ImageReadyqe<PIDATxbdh1 ?(# rr1Pz(* jd!7nG3K,TCœ~KG00T??߿ !~!@lTd6H+ks X. l$P*  rJSߟ wHʖbc:@20?/WdbRz@C, HTE( @ P6  @uJDA:#B?bz@I8`@pAHnGIENDB`instead-3.5.2+dfsg/icon/000077500000000000000000000000001467622671600150405ustar00rootroot00000000000000instead-3.5.2+dfsg/icon/CMakeLists.txt000066400000000000000000000010421467622671600175750ustar00rootroot00000000000000SET(ICON_FILES sdl_instead.png sdl_instead.ico sdl_instead.svg ) IF(WIN32) SET(PLATFORM_ICON_FILE sdl_instead_1x32.png) ELSE(WIN32) SET(PLATFORM_ICON_FILE sdl_instead_1.png) ENDIF(WIN32) IF(SYSTEMWIDE) INSTALL(FILES ${ICON_FILES} DESTINATION ${ICONDIR}) INSTALL(FILES ${PLATFORM_ICON_FILE} DESTINATION ${ICONDIR} RENAME sdl_instead_1.png) ELSEIF(STANDALONE) INSTALL(FILES ${ICON_FILES} DESTINATION ${STANDALONEDIR}/icon) INSTALL(FILES ${PLATFORM_ICON_FILE} DESTINATION ${STANDALONEDIR}/icon RENAME sdl_instead_1.png) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/icon/Makefile000066400000000000000000000007761467622671600165120ustar00rootroot00000000000000include ../Rules.make include ../config.make clean: all: install: $(INSTALLD) $(DESTDIR)$(ICONPATH) $(INSTALL) sdl_instead.png $(DESTDIR)$(ICONPATH) ifeq ($(WINDOWS), yes) $(INSTALL) sdl_instead_1x32.png $(DESTDIR)$(ICONPATH)/sdl_instead_1.png else $(INSTALL) sdl_instead_1.png $(DESTDIR)$(ICONPATH) endif $(INSTALL) sdl_instead.ico $(DESTDIR)$(ICONPATH) uninstall: $(RM) $(DESTDIR)$(ICONPATH)/sdl_instead.png $(RM) $(DESTDIR)$(ICONPATH)/sdl_instead_1.png $(RM) $(DESTDIR)$(ICONPATH)/sdl_instead.ico instead-3.5.2+dfsg/icon/book16x16.ico000066400000000000000000000021761467622671600172020ustar00rootroot00000000000000 h(  % awh}+ËڌM,=F߃rBcx\XmxBIZcRgs:6GS .VvWMmE"3;U0?GV2KX iĵ&+.@f}1:4hܭ% A`pz^|m\nwo??instead-3.5.2+dfsg/icon/instead-s60.svg000066400000000000000000000206461467622671600176260ustar00rootroot00000000000000 image/svg+xml instead-3.5.2+dfsg/icon/sdl_instead.ico000066400000000000000000000637261467622671600200430ustar00rootroot0000000000000000f  h)00 %-  R hnc(0`͟~knlhyyyШfʷwsZuso͎{ʷy}ue߻sxjھ~h´ݸ׿ȼo{r Āզž߹׬У˨αӺŹurpl '+Ƥ}ò߽ٯҢʚŔÜƢʬϵԿƺ~ezws+1 bc~ymʿڳӦ̛ƕÝƧ̱һǶj}ܓș&+$+#'{{{rǸ֪ΜƕӠߩܦÖâɭϷw~tbwww;> 4:KQ39ZQH̭ϟǔõ١ۢۢڢڡןӼħ˱ѽоt|l chdibf$'cʖ֜לל֛֛֚՚ՙϕηȮθԺŸf|tgvw#(hl&*?PcɐӗӖӕӕҕєѓѓѓВБɍưĪ̵ѵŽwVqme<@ݚܚۂ uIcm͏АϐΏΏΎΎ΍͌̌̌̋̊ˊˉņx|~~ȰίuV~zsnoӴ⑔%*mY{ַˊˊˊʉʉʈʇɇɆȆȅȅDŽDŽǃƃƂƁ|uyyz}ĪȬnsk^>Aik&Ze~DžDŽƃłŁŁĀ~}}}|{{zzsp~suux¤sytB\g"1Ppr}}|{zwvvuttvvvwwv{ÀăĂÁ|wqޯjfvknor{ivu{wЫpxwtqpܯmӨhХfҧfХe̢cѥd٬hݮj߰jq‚˔ΚϛΚ͙̗ɔ⾋̫~رwԨhW~Xi{fijl]mkurmrpmڬhУb̠`Ɯ]WUUTQSW˜Zʥoۺǘ˛͜ΜΛ̙ɖӳ[PNDzf`SHxT`xbf]khdkkhܫdե`ȚZSQOKIH|FzEM^pxĪҵ۽Ƙ̜̜z z'#U[MIsS{Ms?{qOe}amjʺݩ`ktثjʞ^—YSMNMbXCiZ@VoMOWTs[lgku{ֹĘ>9 o/1k.1f#M DII>AjLMB|sd򴬠q—[ΫzìpZ_\l[xfmafb{hdYhRYYVXThkth\~"[9Wn(,J,-O?c~5Vq@("3UF2wX.whR~pD\sXavvdcXdgbT[ZVVQ{Tdkzcq[`UTr 46p.3Ne;Xo#';Y>bx5,%3CJ;bzfzrnekV8oyڑߌށzŅOWXg^PSly.B`pw~ n->a3;S/1HPzlemb@bu`NqiҘߌߋމs`#3[]_i@AdSypNtrtrpomfOY`Ͽumpz}]Q;tiUoxxgw݊ވr > E&4UACXII`26DWywvmfponcPV򘧮vxmprmwFbueYjr}Ɗއ]rl14@4:G$,=_{yU}qnpn[fw黾hzϻtY7b=@DC܊ވ};HU&.=v|~}rgmqarpWrꧧ物Ǣitzdijzߌߋށ!-C$.<:JTNbm~ndefytrbPywǒϪ藻Ή}ޢ勱fszz|asђߍߋށЃcjtyxɁ|dt|gvtX\q䄑Ԯ郕҆㒿ߕioߋmMam{ʅ܃܂w`~Vpfyxqz}߀Љo}ߎ_vCWb^ujv}t܂܀}|yvWz㞯ֲꁜㄛ扫ɝ㍹p̈́̐qk~Ђ؃܁zn~p܎ն늟滼ϩ璷ˆɓܝ䀢nzwЏpun|Ԕ帻쏡ް׫菪唹Υft禰ٛv𵺼얪˟ӭ鐰xz|ס凧n␿u~|ٸɇ싢q|耚mvzxmӇȘ⋷xq͟hii}qtуrү瘽got~u|lǤ}燩qstw}Ӡ䒼ӗۀk뢿rz،z덞ۙjopݵ゗syȖvkqtҬt۟sӔ߁|zpx|~wٛګڰ}Xvyꎢ\pz횾{~uz猟~ā犚ҫ̝ܲ( @䵲}{m}ⴲͼž}}韡ڨ¬?DWZϲӻ٭вԾѷQUdfجМħ̳й|۵Y] -1ǽРȕТȠ£ɱѿ©v HNHMljmƿȔŻ؟ٟ؟םҿɶѻȼ{>A:@uyux9B’іԗӗҖҕєʏƸDZůu~t~Þtw7L|zŊ΍̍̌̋̊ʉʉʈɇƅĮ~~îqehmpK`~ÄDžƄƃƂŁŁāĀ~}|y}vyoRnyײvzxv߳q޳pݱoݱnqrv~ņNJƉązݱpk~lnxm݄~رrqmըfϣc\ZXXɝ]ϥh⼇ɖ͛Λ˘῏vfn^cW^j|e`|z۾wljӤ`ƙYPNtG|JtHvOfqβė~*) h61KmZMlEzWpuhͼȡkЧnå{ltZj`pslmurouqyekg\mu`V'k+5]/8^+Ce?SE9h?跰x[qSyzytxoka{zp_ZY\ z).k>QmQ|EfQ;IPAdzyp~̏֒ߑߊۆqg?Z{d m5@pTyOrmnl`Uvħ܁|wlu`}wz̃?Z1EoPJh~yoxtniV𢲺ƛڡvvcI^ed~j4AP_lygipf~ﲺҙ͈y|ߌmB[pLamo{h~ss[j졯ө哤Ţ啼ҐƏņȒ߈wz_{|ȁullts{Ɨš֠ٻɛӠᘽљ֙Șw[wn}vĂـ~ywzΚ敱޶Ǡڒϔ֌~Šy~|uĨ깾靶Ѧ⌟۝wʈ̑ɛ̷͟뜷Û䖵{͓̑؆Ȑv‘rx{發πだ𤶾צ睽˲頺Ɵ˝şԦ剧~Ζṣ̌䈘⯹۩狭ڕȌ~ȍלsʻ畹͈˻ƌԙȎ̭Մn˜埼ʖsŕǺб( ڶڨιķ).̵­Ƿҳ"'_cv֛՚ÔŦszyʈɇȅDŽł˴}sݰnХf͢c٬jʑō}iskͺجlhYx\u_~f{30y*2]XHB{atq^jr w.=}Sz\LoՊtrCWrTqrÒlyԠϙ܋mfvszΠëϙǝАɸp|}φüѪֳʍքǎ؞ؓӣڒѹǝɡՙӒᆪӝǣɦ؋ПûAAAAAAAAAAAAAAAA(0`  2 ibS9 pR5 /0)k\ʷul]AmT=)  2A8(sʷtVK6{`K6$  ,+*)  D`T=pUK8~\F2! ]~IkB2 % FugM´ȼjD=/rXC0 T5&I/* fižŹh!jV@- 7aI89>9,xyòƺrW$ gR=* 42h^JC3ʿǶseLcN9& \6~l%fG$+ vh^GĽӠߩܦÖu`T=_J6$ 64:KQ39PG=񽷛õ١ۢۢڢڡןӼnWJ5y\G3" 1<chdibf$'c֜לל֛֛֚՚ՙϕη_F:(wZD/a#(hl&*?PcɐӗӖӕӕҕєѓѓѓВБɍưŽoL(!jS9!'/3 uIcm͏АϐΏΏΎΎ΍͌̌̌̋̊ˊˉņx|~~ydA(!V5  O%*mY{ַˊˊˊʉʉʈʇɇɆȆȅȅDŽDŽǃƃƂƁ|uyyz}mA6$D#  &-5>Aik&Ze~DžDŽƃłŁŁĀ~}}}|{{zzsp~suuxOWQL' `~}B\g"1Ppr}}|{zwvvuttvvvwwv{ÀăĂÁ|wqޯjfvknor{CTRO) Wtp{wЫpxwtqpܯmӨhХfҧfХe̢cѥd٬hݮj߰jq‚˔ΚϛΚ͙̗ɔ⾋̫~رwԨhW~Xi{fijl5IFM(OjfurmrpmڬhУb̠`Ɯ]WUUTQSW˜Zʥoۺǘ˛͜ΜΛ̙ɖӳ[PNDzf`SHxT`xbf1C@H$ gcLdkkhܫdե`ȚZSQOKIH|FzEM^pxĪҵ۽Ƙ̜̜z z'#U[MIsS{Ms?{qOe}1@<; p@{ݩ`ktثjʞ^—YSMNMbXCiZ@VoMOWTs[lgku{ֹĘ>9 o/1k.1f#M DII>AjLMBC7!)  P=!muA—[ΫzìpZ_\l[xfmafb{hdYhRYYVXThkth\~"[9Wn(,J,-O?c~5Vq@("3UF2wX.J5 @   BaH%e6\sXavvdcXdgbT[ZVVQ{Tdkzcq[`UTr 46p.3Ne;Xo#';Y>bx5,%3CJ;bzH'CTjuE?3X@oyzOWXg^PSly.B`pw~ n->a3;S/1HPzlemb@bu`=d}mK+ 0Tm{s`#3[]_i@AdSypNtrtrpomf$-vX7  7DELalĞ|TpANR]Q;tiUoxxgwr > E&4UACXII`26DWywvmfponXPV&q"  [r~Yq~|ufJ7$iwS"pI8O[~nbKGMutrbKu&MUVnzc>',x\{M!).=4BIxy dyѲNbmpR>0>FQjxdC$  $6oۨYkt}-8>lae՞q$/6: ).Bc_r|!$k\pzze{ب &05&+B(;D>[iD_lYwš:EKK/(oˬu?R[ % D`n!(*qV=+!"").U~`zF#/KX9oyq#,1l\ND?AK%-2~s?PX&?JW:^n+2R/DOwO`h2;@#& &*5?DUfoǀ-9?M!*/v&*0 Jr~quk3GtQ~GSvƐtTJ[cYnx' gw+0Wsўpuݵum~* Q9WfD^k1@Hh'+Xp#DQWi[lu ;Ua2Tw YnyRfpM |8??( @ %%%  `n`F?6' R0   [l̻¼b&"]9"UUUUUU 6_;(%D=/«k)%`9"UUUnO"2OF6ukV {P/ %%% ~BN YxbkdPS0  L?Ip  {rZкǼТȠySJ7iE' Zi HNHMgfhƿŻ؟ٟ؟םҿȼyJB2 nH(%%%%%%  :@uyux9B’іԗӗҖҕєʏƸ~pV0'V7  +Zpstw7L|zŊ΍̍̌̋̊ʉʉʈɇƅĮ~~wlR)#0UUU 8FJ~mpK`~ÄDžƄƃƂŁŁāĀ~}|y}vyhnc=UUU((6Wx|Rnyײvzxv߳q޳pݱoݱnqrv~ņNJƉązݱpk~lnxSonBUUU$#5j٢~رrqmըfϣc\ZXXɝ]ϥh⼇ɖ͛Λ˘῏vfn^cW^j|eDb`>'"0YljӤ`ƙYPNtG|JtHvOfqβė~*) h61KmZMlEzWNTE,hO,zUЧnå{ltZj`pslmurouqyekg\mu`V'k+5]/8^+Ce?SE9}]26( 1$c}jL~gHyzytxoka{zp_ZY\ z).k>QmQ|EfQ;IP=bwi3 ,o]km㉴qg?Z{d m5@pTyOrmnl`8[qi>%%%1>Ef'17wri3CJD=/whN}vz?Z1EoPJh~ynP|XndM|3@PdoTlzc M. fZB$oZ>^ed~j4AP_lyAat ZWap/J\`"  )16rBRZmܠ;LU!j [)5;qmB[p7M[b{2IWc[_sV4Re UUU QclOcmYz\xρrpJi{tj.DQFd+5;Xbx !#= À??(   TTT***'}t`i`N ]@V!VZZZ# _cu֛՚Ô/)3 35^szyʈɇȅDŽł˴jn`%TTT?VV}sݰnХf͢c٬jʑō}is]+SC)d֨fhYx\u_~f{30y*2]XHBaU9ZZZ -rrg샥q^jr w.=}Sz\Dg}Q L`k{!"_R>rrCWrTqh0K[i(@O"*.OWmxXqasRGBbKGD pHYs B(xtIME'tEXtCommentCreated with GIMPW IDATxw|ӶhUV˽ɽǝbcSC:@(C SI`L w6m5KJݙcfwG,{~4Y><<?GO`Plܶ$k l?C=yX℉pЖ(Iҁ|xP k>F[ Ur}_yphjh푳N$*ST}Y#9%` 0?Co#$?}SNthʧ(HsF$k(S'$ ?r^weI֘8v piVF* ot2^MU>YSr#*2s'fO_e")ҷOQ(vpXJN5_ȡ? A9NdE 53S%IR 0vDEL$YAU+Wx<5onʡ)lLM~& F) g]絗KϟU\7wO J+kl+Mš߾|KSqg>V@Vm3(K=M=MVL=ObS{o:nl;Xi,M@o(5`;:N0«obО/!"Ir Kޝk£Ͻ+71cڨ{[Z;ᗁ@ ։B!|iE_jNQ|zg>{>r,<|<10la~~;Kγ⃀AHK`m+_7VNLn0aw.|$cAv:2A=nrN CriQ·ǢƟ(0Ag 4)J$v b*wf;e%A6|d55G0-oJ/t:F L?NJnVj8 V`;vcS^Yg! ~J ~ O^@U/V+ڦ~yx ٗdVg8#Q]SlGAM0JTފ 1mOb&qg»۞1 q3_ed7jDl (lۻ=pĠB+S/sg.}ƦVXnF)s9*PNzcnj],aνs#DpƴQٷ^}}{0o)=Tu2fӈr zeܒ~9}鋑zé\D঻^`oi @1^^Tԓ3Oj;4E +q:5N4]lVbV.}QY>[f^5}feRɹcUhYjuZzɊ ˈ]Q?(*zzʚt` ډۢ6Qz$IwƎХXzۋVlQIV.$+J8 oЁ=ʞ×AnN&-x_3s0f)ښ&kk޶5]s鳎߇S1%!X{de-GKOSN8FMU7S/ ud-|\W53#;37N ?hX.!43yjdI:ߵ'w;c%+0*Mgkݵu{ToMZ Bj=dPi!/Fo}GEY', Ktbfe[7;?'pT d޲= }B !-%iCһG,!KPUSƭ.$N9>$ԧ_~z0zI:[QZ1ORAP7#)1Շn9G3ZJL+h0P9'9,;P'J㧌 TOQt:^]*>/5HHvޡ.~NR6??X` 2uیmعl/ϜکB0SEcb;a?zO^,+𛭭ъ-%;PFȲ >\괹M&1qnAvf*ޤՊ !Y&6Pyun3n';3hܫ Q R6!+Xkvϑ?t &E v8~A'?z%dgw;_jk) &mXqǝq/=qR&}+r.xs9v6A'fQtJ( >=tR]{5_][Gyeu=ޜIeqc _{ǃ/j:`Knx.,^>׻:ʇZ>$$N(qbl1@nGQbH*'c%ʝXc&2RG !!BLy󃯟?w>˧KRQU$)kFK!R Sv "૕WZuxHo(-tν/VȒ^`;cE>[;vA]J - q)-363gx,'{~p_(Q,hh'.xg$95o*N:sv/滝ecP g?4mm^{o5K@d[_E;)]źnQf~PQ+~Ab/8c*6o e'pbRBܵIs9:-łΈ iItD)C9oKoWeDkN?eAqp vUTI#{1id7}Ki &Xv20t}-Vዒ1c5PUHj.1UQxo,$0]eL }GeYbԑ u۾!@_?q㟺 e`.k#JپPFc66\@\z{-Dߗo)Iqfz9 _˩vv] ͭ^{} 8釽3ѭ[P~Vdz=097'=oDI?:SƄ_q;i(mi3thoiwFK@k[%7RQU'ŀ> Sx!xEKؼVGYc=P^aˎ:eJLz֔Cx/Y `xC?U[|ք.H"SeQ8*0>I/EI}F-QcзgAFRz;Gιn>zuײaG aėc<eƽ cK -]lQ5[Zr7JQɠxu瞃͇kĄJgN$DD|ᨡ}r˜ !cq b}3>~|֯gSj"Oְ~ W|{0Hз8sa"_SRv٘1KL֣ȫ_ٴp.,@,6zd!Db=n<\\U\?.3{`BػshtWBؔLQ^:͝)Ǎ.I=sy 9;xmt#k޾S=qkwC+;gBuDE jNU +@XJ`G ; 33$EU$\C{W, c:c:\MS8e3tZ "t<&x_r׵SUy #zgtBPq:p/ѷ. Pl..>cQ}젲K˦ī6O,=Rr#:IDs\tY@&w9qiSq;>vv%EysteSFˁ*X(|>lPcras.Eq~zLjIq~}wy^eMKT۲|vq y<7k>r+Vx܎.?aGʲBGmDJ+V=0}҈󟿋PΛ.ͺV>y쉓nDn3g-xw?zcxbpepSY59Fk+˿ɢT },km pxvGoln>\b^[%aB)#5ӌFSd*-;+4+1Uk쫚\F X\0bH{C8j7h;Xj1{p~E|ݸs`eq:5/OqF{khޏԤWʴ;Qv^!1>7-K7:w֨N\u?Xk EGȈs9J^{j3O9'M)atIzeЍܔ.ś" v2B@nWk@όn/f!Kۡ*M-," .\Mhu?q阋9SSoe薿s nCKͷґk/wً\#?c_>=$Fkjn_>VׄOsЦjmð; ħ7U9d >!a9ָ '>m`ʻ2sVm t/ 6EIs9't_{N9[w[EuhҲ̎@߃Ni,N2{o֩5p`SQY̜4"+-ӅLMm5bLfK%]&.ێ*HCZ+rDY*5%)ϼ>5ʭGꚸgEk1 }nXfZɲÝW4⑨ M6m++gYqA~J$'Hw߱aJ3$P8܊Umʄ-i)INfxr IDATƦʗZ<ݘK6XpڹŬ qB~Nw^Ԯnap@YVe+@ҙ S0 uI &/AdoJ~|oqՅH/w!+6ld!( zSǸ8O7ȣ-D2lw]Z֔]ZeG㕖{-VqΠo )[J{#Ͽò߭^B(-OҀLYs'O)8R"0`+k h1Py 8熹-=7!g}Izߏ$ZWJT:=g7 3 Uh 5pn֩B54Rj 8=FBR3^N[:n/=zS;-ݽ'^z^yyx\qB_[')F,⑘KLp*Cg2MS$So"fwظKt.?gubѥyu[sɓ(;\Miy9e2lH.17>}h1NbS,qC 3S% /a jQ-Pr vFw]-ڛ=Mа{¼뷟KwJY)Zr_ hJ0֡U&|I `0#EeD" Pv7/Cx9<3x8eZ U|1 Ëرo?{J0ڊhmq.lǾ5&w;c(Iq qmWV.9ϻxQ\ |d=5wP68͙H}*gyqj2C\u(?f,ISJ ?e/aSs }s1LޓT{?0f NP C!ش};S'拧p UJYMSHwr>y㎡3:r \EeY1{l& 1;mo%ɉ|CrJM6݇ͬ\6殮Տ+^#ђ2М.< F;dbfOQ}T9۹ט?8DH}?2YэAiev%?N&G˒wӿ(܌vb[xo[,ZKܻ1H-﷧[ыG}m" /- [}s[5<?;RVYKeu=ջik vvighX:ô4ȁdPQKlB  É4 !%PJǡ24텨A_nhs9UYC e ]ٺ +w?1hJEMBA $)*=zݢӿ燎}dG buQы!!͉8lkfo} 8k}l*ڱʫY~g?i $| ;ߚUni*' 73"`PkcvOuJ\Mxe^ˬ7[yVqlt!#!nrg z 鞛MLM6kG8窇SZjuۢ\g46ew/zMyϹw9ӕLыx ؾ=dJ`JX{U͚۸Y6=LFy;6o?w= !l8.lZcE:Eߞ'x+/˩Ϲs `0:*sYSe9aMc_^_HacPn^x-z#/ Wl1WԖD!udڭ*bV Qɦ|1}1G|VDVjd꽴yzfw .`Z Iw'Υ:,)1_vdLЪ0YA0d2rP4M}UM,;yTo7qy@]2 OR2s{}p/xv$rh)~Δ$\9:E:Hpi'|0c{0X7?WfKM#HklUhiwQ9ְX=sr>66, xj465fH9O"!'HEVƞ;ݏ_b %DT`!<|fҩF|3VmMf%7?vj-pAҳ @vaONF[ g ٚe"q*uׁ%o8Fv>@Ak uV6qr$SOBѲkrz?l o7qCÿw֗&Xu/z 1oc(lP,1I JdLFq<9S4Tvͤ$ki㾧гP*Jy;Ίow(2"9g1~xϰ\a'K6T0IG%8yZI\9)4Ւ[dH!hC&Lc㩯o]G@+ R{flGֈK|[777"@46R'to\w,߸ЂB[[Xl'Ǐ+f`-?+Io*CA3g^Ccs6[cp /l:m^XX Rt̻l_h7ļ>$#SHq[Ⴁc: u<4#5p!М.N0 +qpܬ}VmŸa=ÿԈOJ!5;L=!(-~TC70 6 oyy$7A0oq'+&IȖ+>'}v0_ onE  4gA񠑴ϕP &P\4Ϊlmjmy;/Z )_U±' u}ʈ 0T8A35R2ܮ%l.7/M^Y)AO.^w'b 0PN|6g'\cy}1A|b2OfMctF .|ūv0pTȲ(hFs\S.ohv!e8%3HvRȚ|:X^AT~k6odrp(2_lY@Ud>^6g$ zkiU523| GcgIJEANQ_Z j&z!٦5 E5_8ӅrpݤmkB~_zw/Mό BqNd&:I1 `´$!+4eEEV5́9PNT͉9ZW")n)NK.TMD,oFE (+DB )ͥP/+Ԧ'iTBrQpkTPBRY\,uJׂƊ}4WM',~l%tIF2,G~=0K0 MCkʙ_4 IIԴJx]2,bHji(쭬BX9NgjN7=GL/[-2$[!*L7(;v;N`@O#FZsq$O B⒒V1Pi0T|m.Ij'հC+@|VP<(NFXѱ@U ]F(20L% #,I,.CXnaCur tÖ *@ [%]E .B*HY_QUT4DU4KdsȪyLRB72-HZ$ )-'_HQ,Y8^Ke;Ob`-0&Bx/uy=Q{ "#3'ɺ>Rh H,j rս h 3#6ҡ׎?VǸ|_SRJ4;a2V,# Ca((̻~2B@Ba! dNH a !d޸Z_+('-_ozN'%"P<`M~.Y$YFFBH${ }P ߴ"pVYAPDb &dwf>uq#'9ղ:4 Cq`h  taI#+#x/(mX@q DQ];IObV,M)!,W c.HfMW Z Z^@2G xTM3]9P5fl,ɦٷ ,o[I=xj{盥y GUW[8A}Eh2yMT~N0hk.z&&3ȲHaU68f KYIJ[-mm$%7lqߺ0Lo _PUEDb1A ]P=$)+BfD$˄+HˠJ44d{;\a?2$f>Gn?uBd~ٟ")d H#K80p$,ǀ3L ewc#7.OA=' Ԫ8]8h9RIJpHu$'Qh3XѼ;MSQөѳ@%zk$?d@BFXq9 Iü8C1[ [do A3`4H#$I-b R@d+ݪ^ `$OYMD(e  K߄-d G:UCIM|c'?gVꧾzC55}àCd:"˲5L7d(B4XK(.P(W_f*,lHf/+հY0 3`TAahBBۊF)xk, 2P YPL.H@[Fd"B%%㼩2!pe34Եh1Tt́Sb\[A 1ыD2/aYv_RC' -[w{8<>NW~(9jB6]A8ѿ C Bݪ!*E2aX1 kʖWѻR+e wI6Auץ䒈SySRlUJ2-Ch ]$c(* &/ hfp*:@+#U4Vj`W)yY2IIްBAnH'C˟өX\.-ީm/62arrRp:*TI:[hi"G?܉)ߍi9L6V\`F8(XKaRE5g~V#AVoPfM­JT b QeB@G/K%mA !̘Bsk+߇V=$&&l =x$Yu ՜v kut !4a˖m橧>Vrmg3xp%.;ʿb $V.GfO(́RC>FLcȑ\_d)"|۰]&X9> 6U˼*V vV hp\c2嫫l/r; i^܇I2iEm$ HO<>'&i𙯅o~3@bWlS7>.)bF-G0@vΝhX)[Z؃6ok ZiQðVnj-˲@F!aV૯lFNzH?P')э, ~ɪahYPՐ8ea-CcO<=8Q3SP\nfVVi8P%,˸\Nzj$G(5Y<8oYkN밠B M;a+="Y D,TQ;k{; Zk+Gf9l8׃bJ%fx乹2hFT?nc-`1GVqGf23罁+%oבȟI߳ﭠ[n9 ˁde%Wώ)@j@xCœ!"z[Dn84|xGn1'PEgTi/ii|?dDrrSN4ͅᎱw.Pn泭|2k6XM#VQ e!NzHauכw0@2G"W/zmZϖt3$*$'HVVS py<8q`% +m ȶtHiozK}Q$Z9r`u6[AI.z9z=NsxYV4'j V\hG t 4jZX/& edﺥW'rޘcQxTm駓ԯ?"@}\fÇSz%d#٩Fݤ)&8p'$Ƙ\GG8\xDf|G!wTΔ&đC{ݳڕ >y* ʍy 9u8\6%pSMs#I~#!=uȎe`77 pLg4&<ZbRGl^4s.΅ϵ-q "}t|բtFDNloQ_u$80i\.Gw- a,G+Y8ӋOIgGyT ԣ*l?WRˈ1vF,g0bR s服7DIDAT= àmi&%g⽩WtFgQ˗EtPq^⛿(tu4;m xS)EynB:wװ\@RV>ۿ^ĒPz_v %\:9 ؞yf:*<>x퐿fvCH+HJN[am4TQsh/)+''Í㊝nCB5n#QȲF uo-H-t>{*|e41'+55d "j9vב-A.x N\7wC߲kGm di-+#0~tᅄ-u~'ģ*M$?}S_UN8uB 2m&,)BuaVmٙMZbj ٳ5Bznߺ_,,@]waYg ` @Q`Suf}\NzHöu67kojniuE)h8\A=(u?q|'10aC(3o7 aDAj0d_FE'/w*&@[?;$H5kE kBM,/#Vt"xŻJ/e#v2 nkkQ>v@ 7o/xC <תVpkd!)ā3Rz5đ't1rj ')+2{sb 4}H u襼lW.{^|T|7s{Ym@6)弐"/[<&rdQM2?Q-U~ϿMA ,Yedg;f¹Z 6'%)B_naѲq'&gf&':PO;f )/+ 'e,j[/sE`px-k.,ϱM) 6 m  2Y 0THC AFIb\|wn /wWB$#sTUNp ZOE服oJJj 0Fx , 5ɩ 1%>@?(q45C٢z}yN?W`l:Pfİ$+`so ˀ/rc" A46 8]?3O6lxQU9Ah&A"*k`"{F-gr,lƗ7Je9^u8Np#D1 U/-VU|h?/oc/H<1iLR S`|"dKxal=yX 0"v_[ 8΅u *A$kŰ'@qQ3܍۝gёcHtTC=(TRv=r/G>#%Yкvw覓z)tߊb]]"sQ>Qxb`k5?άlXU"qβ*Na|-4L|( ^w2bċ`%>QA$"virKQ^ɱ<*J3ɠA̛n6 #K& z#h^;\sߒ'f|B c`sAN݊5O4Rյ8Jt620j\DWhR^=#ΑXmʏҼ "I ':z9B,QQS ~ɮ& wꉜ W30iht>b?حWӰK U05}QTgor^qy2Ţ\rt'͡mܚwMlv:=Qt(ںs>ɃojJ}?>˯n} *.Z{qo?k;I0T'ct|KBCY_}3jG9(,7Hlбh(2ZDѥXUEzwq\}bӭױoכHx}=o?x:u&Erb0{@!C/z?A\S 1 7,?ʟ>*R4J_k#jBDQ $AƱb 0F{l ֬20<ޯN1ӺU8^t]ǦueRĘrH$kHfvi/BðCf휚8.6wv୪g'l\.1ıv n (1c\oe'=?iTwfm2 r BHík0qN8!G׋ܱ/KhT[ΫZS{smӳszzZ pzd$0|ĝ@p019ž~ W-btWvPUU=7c&˰VQf_W33fX;8 IZ>]7#~{6"69ʲ" H'a~Щ)˪)]XKtf7Y~_Oaw%9HEX?j "@֥ˎC yck.^m~ ΪR^\ : $=, շ#Ѩ̗M~UTE:N'[`frS_kXOWkۍf4AJg H;ndY{wR^wÎ2KgI5mtV YX >)`$99u↫Qۛ6т3M,[A8.ADQo=G:QVSOyi?rpF<{;l0,Hh8S"!γK_ n|)BCL4q7jX\apxq2䤬OY%A>%;tN|ߎPS8逷%q :6NU<^En~ Atzk (4 H,\Layva܆"lx3WS8j }3M3Btcx['DyrOuGqBdI?>Mdfh;W-2D S J? vt}ׯ'h}=[dplE3oHaSB4)cf@y)n&L3I3u-;7G2T 6@MNgR<6d-LJc f/kzcS-T image/svg+xml instead-3.5.2+dfsg/icon/sdl_instead_1.png000066400000000000000000000423671467622671600202730ustar00rootroot00000000000000PNG  IHDR>asRGBbKGD pHYs B(xtIME1iTXtCommentCreated with GIMPd.e IDATxwl{r~T]{X555ƒb,]cEAD#pzmcbk_3<<?-=]ӶG7r_rā&AN|\!IN,?&;t2驉xX]Q=ej!'} 's E HKJRT`1vBAng:>qk~h3& IRd̟$ `6瞼]~(ZjJ?`r3\!Lǜ}ǑP-Uctq~see/͊b1'|[AZm(af%>ցj3Ehv>aX$ty(V{ }W!AZR|y4rcK(jw_~y& jO?Zw&j)4">?NJ7PMfzrZy9{,\Ln!]΁ Yy}^_)C(*xX?0nW|)FyEJ7ߋ_}\!?9\TuUӸ#.6N͵c~#[EC }G}:dYS$NMsa3nY M&~AQT}}9N.dl^?{ !(K?E᾿/-{C xxzO[VS~ܥXm!t@:~x>l?ސF؍0i"' ߞ{y"= ` >Bn`gy5nLJ#.Avf*ٙ)f1}vKUm~{z8rj'`[q~AiZ[ݸU+guWKj= H^ױbfϚ)LvFr^k_$@\M~/HNm/-SL#WqG}hw+ )1mNרʹJ8̣9p>ϸa$̔yicx'.ɴ y~7NۭCEM+v {W>k\!OgLj/p"Hɋq#AӘ;6.=E9D7 f{5U'1YCQ#^ r!*媛egy^G|oׅ]| M0 |/ع'o]taV2 xbo,Ȗnb*fSo`[YBH_W|P ;x'>z댗>x]e(/zGWW/23spI{Sҝ{ץʇkF愉|iI"!%]ݽ\v?xTd8T&/03{jd _J/9͕ˎ?c_K%`F?l7bˏ Vp,2!.blRZB%pI:J8%.*zX6Y XoQ~ڍ3s"5hx|Mtu{ gGyDzf~q韨mNb6'+M絻IrwvusY7ug(͐|;1/r/@}v,Lw ^vzŏ11dƔCCN9BZ;bźou3mIrc7P2 .4sl?]4@~?d%3chc>翿o~RI ?˔ :’6?-CO͝o|UU(_͗ L:3s /.$@МYc {>,ۍ$'% 9@b@?YQg?+K>~Is(.bP]oPÌ |g7ӥċ? \=UON,YZ|%Y__GJFcAlP]^\ׁ3 p)7 0cbd^XSϿܯ^}M}.xퟫ&j Puwd\Ng?^JXtu8yx vȧ$)}7.aw_z2BsblV Y}Ofz/ϕk6COB>1s+yii1gf ͘)l⡧ͩHvR1+W[ewZ{6Pr$&HIvq`>dn_z|^πuJW+*5Xj=N;=>aQӿi].^1/{C.WM}oĤ#_u꧱M'jCLX[g@͊5Xn}͆ od9M)jNjJ$Y, eU5|74V_9Y)}@>WJ}|Mc~ғ #c#7,>?} 6o[#x~j V-9v>h|˸|>4UJG]׍*鯯txSHzz<86'gb~:g[LZr|O=j|Sj*1-k *aM˳4ӮYYF-aHP?B>q)IrWMgʬĨĊsϜKFQRJTE !tKUiQdk` .!OjπjٝMzJB 3=&)*pOI>~Z??mot̨\UnϰF[gr*l.cN:J MHL/>x1v+pjwM"IspI̝]ʸooU **+K Mͱr tT\x#9hH&^Y55[xv?4l賕l.-:,cgY5"cWkx_GS\}I2..&R/_}*ƌ𚤄k/>C8l{dLFUִy𥠪>eۮ1CsQYY4;8S7Gɷ:_yjQcLN6L+C|O7gp%+aM_ui.57cg\& lHX9=tʯ>ZYxz+1E}rR|Hv )5ln?[;9=UKz?YWZ# 0-JQTz}<9D+Ϛ3k鰻wϖo' HB} Vm(Ί00ڪjB|HvFѫi ;kڸO~ݱLIaŪMD:8|au( +7.t`}x60p|~N*o=~ 6-gͦOcK^{O^Wo~y> M3J/i5d:OxoW`q93s¯z(9I>q_.p>ZAI6)%n7_vT̵(HpDZ,% T7uPV>mVΘwn漓BG\4Fv7SΘ>NoY5h{Vx;~<#}F`~jr2pحX(*$\Koy?45z)o#-tnVn7 ̛3HZRܠ=x?ЃgMV}k9Ow|#2QF'Kgyi5c2\,hhcPj%E5wssFIq׹n͢ilZmJ_`k6+9؃wʘ⹪CN3TJr_#9)Cg)~)<.?>}v(7|,Nc߿*nxa4 = v| {L0X&i]RQ]/&,UMESUz4 t-_\4^4UjVz|.x )z{ǭ`~|kd[rr샊[=S¾%OCUhz J?^7,ne: ]^GKF@]7^ ;BZR(Gˇth=:2s_zɟJLtTen*纋S%;VGIƍ.-Eq58lbltt{zHrRJtkAKVeHGcnp鍏Q|Rr,'JavQ,?&+">`=z٤$,]qP3L𣅤A~i9  bdWuޯJO˹2Dd =?4J||qOMJkųp5).$ՠxV>u5 aU?iW< \<§6q1d9xYd2RW?m{hQ}p-.Ϸ'{cW>yU,^VOD^N7>eMU=)G; &(IWJ/-͍|`>keʯNrP:Wn7ȱHً2)Ac[>rc7EU$n'|r' Z창=*9`rPɗ/!,|&3S/PW7D@bTjp;;$iL˲R1|^+p|p$}??-+OCJ۴?5Ҳ]+, 3%Gwo/X&~d1o#O:p )D(En`^QV4ZM08@ۉG0ͭ~-x r cjWԷrCŪ?zT'Ҵ-ҽb9 q 1KK9idtx?peirH%srC7yVACF{%7>p k4򅷖#Wc?T[w^ARF. >yr.c 3s^Ʌ~d_ܶfd$kxrsfz^liB߇{dcē Z4HMN}.=&z{>\y7th)f%6@ ^#6-kV5'p s7>\ |K޹jY/:CJnb7d:>0rV,p黭ZQ$;>M/Zث.Vʫ=T-B"yu^YLPŢ~'}_Ԏ\}g3 OkcbA(*هXg"?i+9055 3!XWegg  0ˎu`r^ =L0{_Jwh?:Y5t=H="[/]Ͻ~Jl\-u̝={n83bd N7u~۩l$/#"xfata 5v5# IDATf"̼"NJ6~9\4+G*#Bv&ˆ:+%z ƎAǃCEvA:;9big%Rĕ">Ƃ%[/ň)sڼ %X*(Kfyp.&YqjlӻHIs꯮hdy+/뭨*u)̚ZVoeZ[3}{HI$[IE)¤aTO_ٰbo/aD[`8%toXՉV8h蠤8TWLw| =ɹytpVYȌ#ɈxW2URk|9~ !l a,Y܉`o|6fN) WB3np gpף`)$b,BA BHi($}Dg~{ٱB$V"y;bUT_tN m$®Ⱚ*BؒEixzݼŲ̀ɳ|+o,z3[lFRl[|Xd|JEFyV;׃EzIRɉMHi>_fJ\v3C*^!WێݕNJ `Ԥ|\yAzЬV 0 2r(24/}>N>0q!KX?4=}kvXBۢTK9!ǃm8lW!>[m).F:FZ1'Ջ* vҲfP8a:^] -w 'YUJ_Fj{fɨ&}~dɍl{=|^tn( {/9`7H+9h:H bt{dw1~,\i]PeMj cLJ0L`ڜ=ͤ19|z'GiPBj4jC:Hu%yj1w_duc 9"*_KLv.5|z/&5/EL$%_sbVO*#jcEs{ y8s(9pJ,1"m|zK2ro:2.>1GèJExȏEquqtx>O7 Yb{)EB3+çb._\|.,}-xsR2¿1-DI 4`Oz=:xBU(UEU54ݎnMO4!G6@n{/$cbX׍M2#A2di.:ؗKMd{jBW+%{.5b7FGO# cE#@^~L>*EC"$&Hx}:]n/={tzp=Б/aDF+_>rq3xOH~ EgC Ów\í*\w~uB) S PMCU͗P](~VV݁bY(*vPeLI[#aJcjk!%tyWZJFJ,5U& ځ98ǐ9GGK=n%/b'a'KpHi uTCa|>.Hχ{>?º2د]MgCxy08Ʀ4m_KIp%R=Xf U9"0/0@H,ˮ)" WEi4 bCXP5s[ELBAbEX%qm`N]% q S˷!@0 }>^n|n7@NKfjq +txł"%FKk'=-ێ /@Jnf&㛦fzI=!4V CaSv$0ĐCm4P$)ӄ*](t>]zg-~+;`O@ L+ B A$_|#eΡ ů|2b,6ٞ>XǐjjV,6;jݰmh`U< d'G\ MSzuTE$-5FJk$d* "L`D@Ec3t/Mn~{§.ɀY"L :/8 +T4BTua*?tWc5p '/0D^4K(ӬlGϤ"?6$4B#4Z64Mۛm#ŷSAUU1(!&!Q3W2jQhV{pDT׺@ z|CӂZ@o?*CPv~7 {l<>iy}^:{u=͎Ow;=-u$1%d;AxR|X,?#eY(Hh;H#!(H]`lC0̋3TCU2Г~7uoU@(Jp|=h FJ[$U5BQ$6\[BP?4g(ΈiEq8#FbǘU7 UJ<t6*2Ź̘0Uo^v2ׯUt1lY-rJJ k`C`H-`Ň1 K}Ұ  ?00Xem(U= M$5 fpX@xi!+B ĸ)3I3:bPӈ% Z^z bŦ0|^zښj%޳11deYIHp!ДRe/nL@P>!!Iv/ٸ $כҴ /Ð!RݟCQZ\PAp+E4?r](.jWeWq1 .hmK"h \P0TL|AǠ+j`Su|^[-޵rr2NWPċCHhlb/'>Z#++ < g׷RIj I!ݍ߇VwTX)+nA0$K߇WT"rT#Ep䠈Th 4Ek84]XU"!$R)0 t<<=^pR6*s!tw4ZSm c-;5HHH^3eVVc3Eؒ%xwzxe\Lddif1eI3sB(~=$?aA`EQ bcen`n]-ΣCEE#`gٰ -Tw^8Wa.R b?0 5@xX "Lkumd´\XTŨK*6ҵ KQb /LKe=7'2W'%SJ{;xTW7ߝnEU22i377Wf?xBiR̵{JEp"? &d-Yk!U"b`T;1OJk.<7QIbbÈ˗G?T0c j8=G P?o?|`[&5϶QmOݽKO"vG|7KH1 YUBw-aK'.)5~_+)~h 0r )߰~+u ej>b`%K s ϘI۪d j**pE|t+gl+mNzA1VY! -#M?C[} M;ob<;<>0> |>\ҝt2ISHs.^lvlXޟ((xlpS **ۓ\3& 6FXHVʻ9XWr?04t0A"G'{iobjd%f "yJ1.n`Wu oY\8wGfv݉%l5t# nb )7\}{usˆaQj:k iIv 4(.;|.e ]ƊȖR]Zp:c{Cj}D΂a>/mʛDrN!3|>?J3׳~G x3YBk(]^_(r3)CY*oiNFh,vHJ>|AP݆@Cd(ef\aZB^p>2/JORdF$$ٿc?{! y)\:^K 鈣]zo/+*Y“瞅6V /MI`1 LL|][*ZAq crxOX@0hnbm䥃WBDE7kHò- lnGAQ+{va@w LMp3/ϮX3ҭ500F1IX E HS"F(*Y)tsvk#cxR2~aF"w2 Igk ;FN~$&K FW%(tw{XYZLeE<~i7ð7̔pXn+:V}ﺵXpO֕d8 &`umgTvA_Ex0 _D&11e)Jog;Y#}ME|e&:[i(~;K(^sEGB(:kհڋ%)TnǎMetʓk ΀Wu0oL)) څ_%zK 4s:yOWcs0蓨ز֗3{Ӂ|M&<FHAP\B|m9[wQOJڍgZiE{vLN򐒒௪P~^2ҵz )]=Ȅl&T37.cv95hP) ހ.ne<DŽдζk9ƀZs~͙NmvK9hT |0]:Z>̢ dKՆh,f=%j B`>@ ]7)|GtFyy|s_~`7锴Ab+P|N) [ISǚ ][M.hm .'OG^m- &{IGljOVR4VWR_KG)9d; uP#mH{0-m,RGyE$g÷yoiXsB7|n oM\}3'*m]9cHICJ=B*"/ 0࡬ OYcjoEmBVL 9YfV h'ttvUi5[[5 He˪exغo,J! r|98p.IZhܹYg'#чѥ6'@ jjl#MVz<1QOT7CkA%*nVmdSABF>i9yԖ;g>,kGynXlfEE2ǍOfRe}L.FD|5EF4pR$#^ Xu=8RG[HW{/}30SAa HM.Wf"}U Mlz2Ffckla ¥B_+=偪Hj yP 6fuy+"W3~?8!ﶆ͈ qjbW *K7U0wJ.gRD_u x b"wTֲb{#z6IDATLE8Y#[wK?[j'Rc>pN >9đ9 W0?1>7 aTQ!#$IY]!uۡ &de'h.s= ~5B^dRy㻘3e$6vgv!}!hmoPI-"%3]gB!?d|/n/˽!#F^xL>d[7tq܌"H $>|!?tvutc4$e5^&-|YGKLБ5z4MU𛛨ߵOvN'̴D2TP͗ߔ\Rs0'x֏!lrҤ\xϳtҴsGMLe|a6BH? _}k=׫2hM4McMIAt?~Pk6/QQ]͙03zgrt>(ig>ڵ(r.Zڅت́(i)DdAEBآX.qRf)eLý-a6'sN<;ӘɎnFe9(oɝ;e-M,SR B$}~nqJf\+]@kdNfLj9vmAU=K]sk ض$;5h/B#݈/}nR(`~*_P\.v񠷋W 1_¯-NΣ 7b[}xz*7GQG]= ҫIqTZpGd!.wJ Gp]3jyIENDB`instead-3.5.2+dfsg/icon/sdl_instead_1x32.png000066400000000000000000000032051467622671600206140ustar00rootroot00000000000000PNG  IHDR DsRGBPLTEDd)s -#$V.7J$.C'(zR,":Wf,M4/g/0$ U63@=20?OH>/g=(ZA,V@DFGH[D6q><.Ohz@AWL҅R C7W-tn!H/uShϮ=~ǟ[$9N|>-MAY~Mqg/@ !X<IENDB`instead-3.5.2+dfsg/lang/000077500000000000000000000000001467622671600150315ustar00rootroot00000000000000instead-3.5.2+dfsg/lang/CMakeLists.txt000066400000000000000000000003231467622671600175670ustar00rootroot00000000000000IF(SYSTEMWIDE) FILE(GLOB FILES "*.ini") INSTALL(FILES ${FILES} DESTINATION ${LANGDIR}) ELSEIF(STANDALONE) FILE(GLOB FILES "*.ini") INSTALL(FILES ${FILES} DESTINATION ${STANDALONEDIR}/lang) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/lang/Makefile000066400000000000000000000003351467622671600164720ustar00rootroot00000000000000include ../Rules.make include ../config.make clean: all: install: $(INSTALLD) $(DESTDIR)$(LANGPATH) for f in *.ini; do \ $(INSTALL) $$f $(DESTDIR)$(LANGPATH)/$$f;\ done uninstall: $(RM) -rf $(DESTDIR)$(LANGPATH) instead-3.5.2+dfsg/lang/cs.ini000066400000000000000000000061771467622671600161520ustar00rootroot00000000000000;$Name:Česky$ UNKNOWN_ERROR = Neznámá chyba. ERROR_MENU = Chyba při nahrávání hry:\n\ '%s'\n\ \n\ Ok WARNING_MENU = Chyba při nahrávání hry:\n\ '%s'\n\ \n\ Ok SAVE_SLOT_EMPTY = prázdný SELECT_LOAD_MENU = Nahraj hru\n\n AUTOSAVE_SLOT = Autosave BROKEN_SLOT = rozbitý SELECT_SAVE_MENU = Ulož hru\n\n MAIN_MENU = \ Pokračuj ve hře\n\ Vyber hru\n\ Vyber vzhled\n\ Restartuj hru\n\ Nahraj hru\n\ Ulož hru\n\ Autoři\n\ Nastavení\n\ Konec ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Naprogramoval Peter Kosyh, 2009-2023\n\ \n\ Web:\n\ https://instead-hub.github.io\n\ \n\ Zpět BACK_MENU = Zpět ON = On OFF = Off SELECT_GAME_MENU = Výběr hry\n\n SELECT_THEME_MENU = Výběr vzhledu\n\n KBD_MODE_LINKS = Links KBD_MODE_SMART = Smart KBD_MODE_SCROLL = Scroll FROM_THEME = Vzhled SETTINGS_SND_MENU = \ [Grafika][Zvuk][Ostatní]\n\ \n\ Hlasitost: <<< %d%% >>>\n\ \n\ Kvalita: << %dHz >>\n\ \n\ Hudba: %s\n\ \n\ Zvuk klikání: %s\n\ \n\ Použij SETTINGS_GFX_MENU = \ [Grafika][Zvuk][Ostatní]\n\ \n\ Rezlišení: <<%s>>\n\ Celá obrazovka: %s / HQ: %s\n\ Zvětšení písma: <<%d%%>>\n\ Zarovnání textu: <<%s>>\n\ Zvýraznění odkazů: %s\n\ Fading effect: %s\n\ Vzhledy dle hry: %s\n\ \n\ Použij SETTINGS_OTH_MENU = \ [Grafika][Zvuk][Ostatní]\n\ \n\ Scrolling mode: %s\n\ Mouse filter: %s\n\ Keyboard mode: %s\n\ \n\ Jazyk: <<%s>>\n\ \n\ Аutosave: %s\n\ \n\ Použij OWN_THEME_MENU = \ Warning!!!\n\ \n\ Current game has a custom theme.\n\ Changes will be ignored.\n\ \n\ You can disable custom themes\n\ in settings menu.\n\ \n\ Ok CUSTOM_THEME_MENU = \ Warning!!!\n\ \n\ This game has a custom theme, but custom themes are disabled. \ The game may look differently from the author's design.\n\ \n\ You can enable custom theme support in settings menu.\n\ \n\ Ok QUIT_MENU = \ Opravdu skončit?\n\ \n\ Ano | Ne SAVED_MENU = \ Hra uložena.\n\ \n\ Ok NOGAMES_MENU = \ Nenalezena žádná hra! \n\ Prosím, vložte hry do složky \n'%s' NOTHEMES_MENU = \ Nenalezen žádný vzhled!\n\ Prosím, vložte vzhled do složky:\n'%s' CANCEL_MENU = Storno DISABLED_SAVE_MENU = \ Hra zakázala ukládání.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Odstranit hru?\n\ %s\n\ \n\ Ano | Ne WAIT_MENU = \ Čekejte... instead-3.5.2+dfsg/lang/de.ini000066400000000000000000000066311467622671600161300ustar00rootroot00000000000000;$Name:Deutsch$ UNKNOWN_ERROR = Unbekannter Fehler. ERROR_MENU = Fehler beim Laden des folgenden Spiels:\n\ »%s«\n\ \n\ OK WARNING_MENU = Fehler beim Verarbeiten des folgenden Spiels:\n\ »%s«\n\ \n\ Ok SAVE_SLOT_EMPTY = leer SELECT_LOAD_MENU = Spiel laden\n\n AUTOSAVE_SLOT = automatischer Spielstand BROKEN_SLOT = Fehler SELECT_SAVE_MENU = Spiel speichern\n\n MAIN_MENU = \ Spiel fortsetzen\n\ Spiel auswählen\n\ Thema auswählen\n\ Spiel neustarten\n\ Spiel laden\n\ Spiel speichern\n\ Über\n\ Einstellungen\n\ Beenden ABOUT_MENU = \ INSTEAD – %s\n\ \n\ Programmiert von Peter Kosyh, 2009–2023\n\ \n\ Homepage:\n\ https://instead-hub.github.io\n\ \n\ Zurück BACK_MENU = Zurück ON = Ein OFF = Aus SELECT_GAME_MENU = Spiel auswählen\n\n SELECT_THEME_MENU = Thema auswählen\n\n KBD_MODE_LINKS = Links KBD_MODE_SMART = Intelligent KBD_MODE_SCROLL = Scrollen FROM_THEME = Themenvorgabe SETTINGS_SND_MENU = \ [Grafik][Ton][Sonstiges]\n\ \n\ Lautstärke: <<< %d%% >>>\n\ \n\ Qualität: << %d Hz >>\n\ \n\ Musik: %s\n\ \n\ Klickgeräusch: %s\n\ \n\ Anwenden SETTINGS_GFX_MENU = \ [Grafik][Ton][Sonstiges]\n\ \n\ Bildschirmauflösung: <<%s>>\n\ Vollbild: %s / HQ: %s\n\ Schriftskalierung: <<%d%%>>\n\ Blocksatz: <<%s>>\n\ Links hervorheben: %s\n\ Verblassungseffekt: %s\n\ Spielthemen zulassen: %s\n\ \n\ Anwenden SETTINGS_OTH_MENU = \ [Grafik][Ton][Sonstiges]\n\ \n\ Scrollmodus: %s\n\ Mausfilter: %s\n\ Tastaturmodus: %s\n\ \n\ Sprache: <<%s>>\n\ \n\ Automatisch speichern: %s\n\ \n\ Anwenden OWN_THEME_MENU = \ Achtung!\n\ \n\ Das aktuelle Spiel hat eine eigene Thema.\n\ Die Änderungen werden ignoriert.\n\ \n\ Sie können benutzerdefinierte Themen\n\ im Einstellungsmenü deaktivieren.\n\ \n\ OK CUSTOM_THEME_MENU = \ Achtung!\n\ \n\ Dieses Spiel hat ein eigenes Thema, aber eigene Themen\ sind deaktiviert. Das Spiel könnte anders aussehen, als vom Autor \ vorgesehen\n\ \n\ Sie können die Unterstützung für eigene Themenim \ Einstellungsmenü aktivieren.\n\ \n\ OK QUIT_MENU = \ Wirklich beenden?\n\ \n\ Ja | Nein SAVED_MENU = \ Aktuellen Spielstand gespeichert!\n\ \n\ OK NOGAMES_MENU = \ Keine Spiele gefunden. \n\ Bitte legen Sie ein Spiel im Verzeichnis »%s« ab. NOTHEMES_MENU = \ Keine Themen gefunden.\n\ Bitte legen Sie ein Thema im Verzeichnis »%s« ab. CANCEL_MENU = Abbrechen DISABLED_SAVE_MENU = \ Das Speichern wird vom Spiel unterbunden.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Dieses Spiel entfernen?\n\ %s\n\ \n\ Ja | Nein WAIT_MENU = \ Bitte warten … instead-3.5.2+dfsg/lang/en.ini000066400000000000000000000061161467622671600161400ustar00rootroot00000000000000;$Name:English$ UNKNOWN_ERROR = Unknown error. ERROR_MENU = Error while loading game:\n\ '%s'\n\ \n\ Ok WARNING_MENU = Error while processing game:\n\ '%s'\n\ \n\ Ok SAVE_SLOT_EMPTY = empty SELECT_LOAD_MENU = Load game\n\n AUTOSAVE_SLOT = Autosave BROKEN_SLOT = error SELECT_SAVE_MENU = Save game\n\n MAIN_MENU = \ Resume game\n\ Select game\n\ Select theme\n\ Restart game\n\ Load game\n\ Save game\n\ About\n\ Settings\n\ Quit ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Written by Peter Kosyh, 2009-2023\n\ \n\ Homepage:\n\ https://instead-hub.github.io\n\ \n\ Back BACK_MENU = Back ON = On OFF = Off SELECT_GAME_MENU = Select game to play\n\n SELECT_THEME_MENU = Select theme\n\n KBD_MODE_LINKS = Links KBD_MODE_SMART = Smart KBD_MODE_SCROLL = Scroll FROM_THEME = Theme SETTINGS_SND_MENU = \ [Graphics][Sound][Other]\n\ \n\ Volume: <<< %d%% >>>\n\ \n\ Quality: << %dHz >>\n\ \n\ Music: %s\n\ \n\ Click sound: %s\n\ \n\ Apply SETTINGS_GFX_MENU = \ [Graphics][Sound][Other]\n\ \n\ Resolution: <<%s>>\n\ Full screen: %s / HQ: %s\n\ Font scaling: <<%d%%>>\n\ Justify text: <<%s>>\n\ Links highlighting: %s\n\ Fading effect: %s\n\ Custom game themes: %s\n\ \n\ Apply SETTINGS_OTH_MENU = \ [Graphics][Sound][Other]\n\ \n\ Scrolling mode: %s\n\ Mouse filter: %s\n\ Keyboard mode: %s\n\ \n\ Language: <<%s>>\n\ \n\ Аutosave: %s\n\ \n\ Apply OWN_THEME_MENU = \ Warning!!!\n\ \n\ Current game has a custom theme.\n\ Changes will be ignored.\n\ \n\ You can disable custom themes\n\ in settings menu.\n\ \n\ Ok CUSTOM_THEME_MENU = \ Warning!!!\n\ \n\ This game has a custom theme, but custom themes are disabled. \ The game may look differently from the author's design.\n\ \n\ You can enable custom theme support in settings menu.\n\ \n\ Ok QUIT_MENU = \ Really quit?\n\ \n\ Yes | No SAVED_MENU = \ Current Game saved!\n\ \n\ Ok NOGAMES_MENU = \ No games found. \n\ Please, put any game in the directory \n'%s' NOTHEMES_MENU = \ No themes found.\n\ Please, put any theme in the directory:\n'%s' CANCEL_MENU = Cancel DISABLED_SAVE_MENU = \ Saving is disabled by game.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Remove the game?\n\ %s\n\ \n\ Yes | No WAIT_MENU = \ Please wait... instead-3.5.2+dfsg/lang/es.ini000066400000000000000000000064731467622671600161530ustar00rootroot00000000000000;$Name:Español$ UNKNOWN_ERROR = Error desconocido. ERROR_MENU = Error al cargar el juego:\n\ '%s'\n\ \n\ Ok WARNING_MENU = Error al procesar el juego:\n\ '%s'\n\ \n\ Ok SAVE_SLOT_EMPTY = vacío SELECT_LOAD_MENU = Cargar juego\n\n AUTOSAVE_SLOT = Autoguardar BROKEN_SLOT = error SELECT_SAVE_MENU = Guardar juego\n\n MAIN_MENU = \ Continuar juego\n\ Elegir juego\n\ Elegir tema\n\ Reiniciar juego\n\ Cargar juego\n\ Guardar juego\n\ Acerca de\n\ Opciones\n\ Salir ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Escrito por Peter Kosyh, 2009-2023\n\ \n\ Web:\n\ https://instead-hub.github.io\n\ \n\ Atrás BACK_MENU = Atrás ON = On OFF = Off SELECT_GAME_MENU = Elegir juego\n\n SELECT_THEME_MENU = Elegir tema\n\n KBD_MODE_LINKS = Links KBD_MODE_SMART = Smart KBD_MODE_SCROLL = Scroll FROM_THEME = Tema SETTINGS_SND_MENU = \ [Gráficos][Sonido][Otros]\n\ \n\ Volumen: <<< %d%% >>>\n\ \n\ Calidad: << %dHz >>\n\ \n\ Música: %s\n\ \n\ Sonido Click: %s\n\ \n\ Aceptar SETTINGS_GFX_MENU = \ [Gráficos][Sonido][Otros]\n\ \n\ Resolución: <<%s>>\n\ Pantalla Completa: %s / HQ: %s\n\ Escala de Fuente: <<%d%%>>\n\ Justificar el texto: <<%s>>\n\ Resaltar Links: %s\n\ Efecto de atenuación: %s\n\ Temas específicos del juego: %s\n\ \n\ Aceptar SETTINGS_OTH_MENU = \ [Gráficos][Sonido][Otros]\n\ \n\ Modo Scrolling: %s\n\ Filtrar Mouse: %s\n\ Modo Teclado: %s\n\ \n\ Idioma: <<%s>>\n\ \n\ AutoGuardar: %s\n\ \n\ Aceptar OWN_THEME_MENU = \ Atención!!\n\ \n\ El juego actual tienen un tema específico.\n\ Los cambios se descartarán\n\ \n\ No puedes deshabilitar los temas específicos\n\ en el menú de opciones.\n\ \n\ Ok CUSTOM_THEME_MENU = \ Atención!!\n\ \n\ Este juego requiere un tema específico, pero los temas específicos están deshabilitados. \ Este juego puede no tener el aspecto original diseñado por su autor.\n\ \n\ Puedes habilitar el soporte de temas específicos desde el menú de opciones.\n\ \n\ Ok QUIT_MENU = \ ¿Realmente quieres salir?\n\ \n\ Sí | No SAVED_MENU = \ Juego guardado!\n\ \n\ Ok NOGAMES_MENU = \ No se encontraron juegos. \n\ Por favor, copia algún juego en la carpeta \n'%s' NOTHEMES_MENU = \ No existen temas.\n\ Por favor, copia algún tema en la carpeta :\n'%s' CANCEL_MENU = Cancelar DISABLED_SAVE_MENU = \ Guardar está deshabilitado desde el juego.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ ¿Quitar el juego?\n\ %s\n\ \n\ Yes | No WAIT_MENU = \ Espere por favor... instead-3.5.2+dfsg/lang/fr.ini000066400000000000000000000067251467622671600161530ustar00rootroot00000000000000;$Name:Français$ UNKNOWN_ERROR = Erreur inconnue. ERROR_MENU = Erreur lors du chargement du jeu :\n\ '%s'\n\ \n\ OK WARNING_MENU = Erreur lors du traitement du jeu:\n\ '%s'\n\ \n\ OK SAVE_SLOT_EMPTY = vide SELECT_LOAD_MENU = Chargement d’une partie\n\n AUTOSAVE_SLOT = Sauvegarde automatique BROKEN_SLOT = erreur SELECT_SAVE_MENU = Sauvegarde de la partie\n\n MAIN_MENU = \ Reprendre la partie\n\ Sélection d’un jeu\n\ Sélection d’un thème\n\ Redémarrer le jeu\n\ Charger une partie\n\ Sauvegarder la partie\n\ À propos\n\ Réglages\n\ Quitter ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Écrit par Peter Kosyh, 2009-2023\n\ \n\ Page web :\n\ https://instead-hub.github.io\n\ \n\ Retour BACK_MENU = Retour ON = Oui OFF = Non SELECT_GAME_MENU = Sélectionnez un jeu\n\n SELECT_THEME_MENU = Sélectionnez un thème\n\n KBD_MODE_LINKS = Links KBD_MODE_SMART = Smart KBD_MODE_SCROLL = Scroll FROM_THEME = Thème SETTINGS_SND_MENU = \ [Graphiques][Son][Autres]\n\ \n\ Volume : <<< %d%% >>>\n\ \n\ Qualité : << %dHz >>\n\ \n\ Musique : %s\n\ \n\ Déclics clavier : %s\n\ \n\ Appliquer SETTINGS_GFX_MENU = \ [Graphiques][Son][Autres]\n\ \n\ Résolution : <<%s>>\n\ Plein écran : %s / HQ: %s\n\ Mise à l’échelle de la police : <<%d%%>>\n\ Justification du texte : <<%s>>\n\ Liens soulignés : %s\n\ Effet de dégradés : %s\n\ Thème de jeu personnalisé : %s\n\ \n\ Appliquer SETTINGS_OTH_MENU = \ [Graphiques][Son][Autres]\n\ \n\ Mode de défilement : %s\n\ Filtre souris : %s\n\ Mode clavier : %s\n\ \n\ Langue : <<%s>>\n\ \n\ Sauvegarde automatique : %s\n\ \n\ Appliquer OWN_THEME_MENU = \ Attention !!!\n\ \n\ Le jeu actuel a un thème personnalisé.\n\ Les changements seront ignorés.\n\ \n\ Vous pouvez désactiver des thèmes personnalisés\n\ dans le menu de configuration.\n\ \n\ OK CUSTOM_THEME_MENU = \ Attention !!!\n\ \n\ Ce jeu a un thème personnalisé, mais il a été désactivé.\n\ Le jeu peut différer de celui prévu par l’auteur.\n\ \n\ Vous pouvez activer le support du thème personnalisé dans le menu de configuration.\n\ \n\ OK QUIT_MENU = \ Vraiment quitter?\n\ \n\ Oui | Non SAVED_MENU = \ Partie sauvegardée !\n\ \n\ OK NOGAMES_MENU = \ Jeu non trouvé.\n\ S’il vous plaît, mettez un jeu dans le répertoire.\n'%s' NOTHEMES_MENU = \ Thème non trouvé.\n\ S’il vous plaît, mettez un thème dans le répertoire.\n'%s' CANCEL_MENU = Annuler DISABLED_SAVE_MENU = \ Sauvegarde désactivée par le jeu.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Supprimer le jeu ?\n\ %s\n\ \n\ Oui | Non WAIT_MENU = \ Merci d'attendre… instead-3.5.2+dfsg/lang/it.ini000066400000000000000000000066301467622671600161530ustar00rootroot00000000000000;$Name:Italiano$ UNKNOWN_ERROR = Errore sconosciuto. ERROR_MENU = Errore nel caricamento del gioco:\n\ '%s'\n\ \n\ Ok WARNING_MENU = Errore durante l'avvio del gioco:\n\ '%s'\n\ \n\ Ok SAVE_SLOT_EMPTY = vuoto SELECT_LOAD_MENU = Carica una partita\n\n AUTOSAVE_SLOT = Autosalvataggio BROKEN_SLOT = errore SELECT_SAVE_MENU = Salvare la partita\n\n MAIN_MENU = \ Torna al gioco\n\ Seleziona una partita\n\ Seleziona un tema\n\ Ricomincia\n\ Carica\n\ Salva\n\ Informazioni\n\ Impostazioni\n\ Esci ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Scritto da Peter Kosyh, 2009-2010\n\ \n\ Homepage:\n\ https://instead-hub.github.io\n\ \n\ Indietro BACK_MENU = Indietro ON = On OFF = Off SELECT_GAME_MENU = Scegli un gioco\n\n SELECT_THEME_MENU = Scegli un tema\n\n KBD_MODE_LINKS = Links KBD_MODE_SMART = Smart KBD_MODE_SCROLL = Scroll FROM_THEME = Tema SETTINGS_SND_MENU = \ [Grafica][Sound][Altri]\n\ \n\ Volume: <<< %d%% >>>\n\ \n\ Qualità: << %dHz >>\n\ \n\ Musica: %s\n\ \n\ Suono Click: %s\n\ \n\ Applica SETTINGS_GFX_MENU = \ [Grafica][Sound][Altri]\n\ \n\ Risoluzione: <<%s>>\n\ Schermo intero: %s / HQ: %s\n\ Dimensione dei Caratteri: <<%d%%>>\n\ Giustificare il testo: <<%s>>\n\ Evidenziazione dei Links: %s\n\ Effetto dissolvenza: %s\n\ Tema personalizzato del gioco: %s\n\ \n\ Applica SETTINGS_OTH_MENU = \ [Grafica][Sound][Altri]\n\ \n\ Modalità di Scorrimento: %s\n\ Filtro Mouse: %s\n\ Modalità Tastiera: %s\n\ \n\ Lingua: <<%s>>\n\ \n\ Аutosalvataggio: %s\n\ \n\ Applica OWN_THEME_MENU = \ Attenzione!!!\n\ \n\ Il gioco attuale ha un tema personalizzato.\n\ I Cambiamenti saranno ignorati.\n\ \n\ Puoi disabilitare i temi personalizzati\n\ nel menu delle impostazioni.\n\ \n\ Ok CUSTOM_THEME_MENU = \ Attenzione!!!\n\ \n\ Questo gioco ha un tema personalizzato, ma i temi personalizzati sono disabilitati. \ Il gioco può apparire differente dalle intenzioni dell'autore.\n\ \n\ Puoi abilitare il supporto dei temi personalizzati nel menu delle impostazioni.\n\ \n\ Ok QUIT_MENU = \ Vuoi davvero uscire?\n\ \n\ Si | No SAVED_MENU = \ La partita è stata salvata!\n\ \n\ Ok NOGAMES_MENU = \ Non è stata trovato alcun gioco. \n\ Per favore, inserisci un gioco nella cartella \n'%s' NOTHEMES_MENU = \ Non è stato trovato alcun tema.\n\ Per favore, inserite un tema nella cartella:\n'%s' CANCEL_MENU = Cancella DISABLED_SAVE_MENU = \ I salvataggi sono disabilitati dal gioco.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Rimuovere il gioco?\n\ %s\n\ \n\ Si | No WAIT_MENU = \ Attendere prego... instead-3.5.2+dfsg/lang/nl.ini000066400000000000000000000064521467622671600161520ustar00rootroot00000000000000;$Name:Nederlands$ UNKNOWN_ERROR = Onbekende fout. ERROR_MENU = Fout tijdens het laden van het spel:\n\ '%s'\n\ \n\ Ok WARNING_MENU = Fout tijdens het uitvoeren van het spel:\n\ '%s'\n\ \n\ Ok SAVE_SLOT_EMPTY = leeg SELECT_LOAD_MENU = Spel laden\n\n AUTOSAVE_SLOT = Automatisch opgeslagen spel BROKEN_SLOT = fout SELECT_SAVE_MENU = Spel opslaan\n\n MAIN_MENU = \ Terug\n\ Selecteer spel\n\ Kies skin\n\ Herstart huidig spel\n\ Opgeslagen spel laden\n\ Spel opslaan\n\ Over\n\ Instellingen\n\ Afsluiten ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Geschreven door Peter Kosyh, 2009-2023\n\ \n\ Homepage:\n\ https://instead-hub.github.io\n\ \n\ Terug BACK_MENU = Terug ON = Aan OFF = Uit SELECT_GAME_MENU = Kies het spel\n\n SELECT_THEME_MENU = Kies een skin\n\n KBD_MODE_LINKS = Objecten KBD_MODE_SMART = Intelligent KBD_MODE_SCROLL = Scrollen FROM_THEME = Skin SETTINGS_SND_MENU = \ [Beeld][Geluid][Overig]\n\ \n\ Volume: <<< %d%% >>>\n\ \n\ Kwaliteit: << %dHz >>\n\ \n\ Muziek: %s\n\ \n\ Klik geluid: %s\n\ \n\ Toepassen SETTINGS_GFX_MENU = \ [Beeld][Geluid][Overig]\n\ \n\ Resolutie: <<%s>>\n\ Volledig scherm: %s / HQ: %s\n\ Tekst vergroten: <<%d%%>>\n\ Tekst uitlijnen: <<%s>>\n\ Links markeren: %s\n\ Vervagen: %s\n\ Geïntegreerde skins: %s\n\ \n\ Toepassen SETTINGS_OTH_MENU = \ [Beeld][Geluid][Overig]\n\ \n\ Scrollen: %s\n\ Muis filter: %s\n\ Pijltjestoetsen: %s\n\ \n\ Taal: <<%s>>\n\ \n\ Аutomatisch opslaan: %s\n\ \n\ Toepassen OWN_THEME_MENU = \ Waarschuwing!!!\n\ \n\ Het huidige spel heeft een geïntegreerde skin.\n\ Veranderingen worden genegeerd.\n\ \n\ U kunt geïntegreerde skins uitschakelen\n\ in de instellingen.\n\ \n\ Ok CUSTOM_THEME_MENU = \ Waarschuwing!!!\n\ \n\ Het huidige spel heeft een geïntegreerde skin, maar geïntegreerde skin's zijn uitgeschakeld. \ Dit spel kan anders lijken dan de auteur bedoeld had.\n\ \n\ U kunt geïntegreerde skin's inschakelen in de instellingen.\n\ \n\ Ok QUIT_MENU = \ Wilt u dit programma echt afsluiten?\n\ \n\ Ja | Nee SAVED_MENU = \ Huidig spel opgeslagen!\n\ \n\ Ok NOGAMES_MENU = \ Geen spellen gevonden. \n\ Plaats spellen in de folder:\n'%s' NOTHEMES_MENU = \ Geen skins gevonden.\n\ Plaats skins in de folder:\n'%s' CANCEL_MENU = Afbreken DISABLED_SAVE_MENU = \ Opslaan is uitgeschakeld in dit spel.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Verwijder het spel?\n\ %s\n\ \n\ Ja | Nee WAIT_MENU = \ Even geduld aub... instead-3.5.2+dfsg/lang/pt.ini000066400000000000000000000062261467622671600161630ustar00rootroot00000000000000;$Name:Português$ UNKNOWN_ERROR = Erro desconhecido. ERROR_MENU = Erro ao carregar o jogo:\n\ '%s'\n\ \n\ Ok WARNING_MENU = Erro ao processar o jogo:\n\ '%s'\n\ \n\ Ok SAVE_SLOT_EMPTY = vazio SELECT_LOAD_MENU = Carregar jogo\n\n AUTOSAVE_SLOT = Auto-salvar BROKEN_SLOT = erro SELECT_SAVE_MENU = Salvar jogo\n\n MAIN_MENU = \ Continuar jogo\n\ Escolher jogo\n\ Escolher tema\n\ Reiniciar jogo\n\ Carregar jogo\n\ Salvar jogo\n\ Sobre\n\ Opções\n\ Sair ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Escrito por Peter Kosyh, 2009-2023\n\ \n\ Web:\n\ https://instead-hub.github.io\n\ \n\ Voltar BACK_MENU = Voltar ON = On OFF = Off SELECT_GAME_MENU = Escolher jogo\n\n SELECT_THEME_MENU = Escolher tema\n\n KBD_MODE_LINKS = Links KBD_MODE_SMART = Smart KBD_MODE_SCROLL = Scroll FROM_THEME = Theme SETTINGS_SND_MENU = \ [Gráficos][Som][Outros]\n\ \n\ Volume: <<< %d%% >>>\n\ \n\ Qualidade: << %dHz >>\n\ \n\ Música: %s\n\ \n\ Som de click: %s\n\ \n\ Aplicar SETTINGS_GFX_MENU = \ [Gráficos][Som][Outros]\n\ \n\ Resolução: <<%s>>\n\ Tela cheia: %s / HQ: %s\n\ Fonte: <<%d%%>>\n\ Justificar: <<%s>>\n\ Realçar links: %s\n\ Atenuação: %s\n\ Temas do jogo: %s\n\ \n\ Aplicar SETTINGS_OTH_MENU = \ [Gráficos][Som][Outros]\n\ \n\ Modo de rolagem: %s\n\ Filtro de Mouse: %s\n\ Modo de teclado: %s\n\ \n\ Língua: <<%s>>\n\ \n\ Аuto-salvar: %s\n\ \n\ Aplicar OWN_THEME_MENU = \ Atenção!!!\n\ \n\ O jogo atual tem um tema personalizado.\n\ Alterações serão ignoradas.\n\ \n\ Você pode desabilitar temas personalizados\n\ no menu de opções.\n\ \n\ Ok CUSTOM_THEME_MENU = \ Atenção!!!\n\ \n\ Há um tema para este jogo, mas temas personalizados estão desabilitados. \ O jogo pode parecer diferente do projeto do autor.\n\ \n\ Você pode habilitar suporte a temas personalizados no menu de opções.\n\ \n\ Ok QUIT_MENU = \ Sair mesmo?\n\ \n\ Sim | Não SAVED_MENU = \ Jogo salvo!\n\ \n\ Ok NOGAMES_MENU = \ Nenhum jogo encontrado. \n\ Favor colocar um jogo na pasta \n'%s' NOTHEMES_MENU = \ Nenhum tema encontrado.\n\ Favor colocar um tema na pasta:\n'%s' CANCEL_MENU = Cancelar DISABLED_SAVE_MENU = \ Salvar desabilitado.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Remover o jogo?\n\ %s\n\ \n\ Sim | Não WAIT_MENU = \ Favor aguardar... instead-3.5.2+dfsg/lang/ru.ini000066400000000000000000000106741467622671600161700ustar00rootroot00000000000000;$Name:Русский$ UNKNOWN_ERROR = Неизвестная ошибка. ERROR_MENU = Во время инициализации игры произошла ошибка:\n\ '%s'\n\ \n\ Да WARNING_MENU = Во время работы игры произошла ошибка:\n\ '%s'\n\ \n\ Да SAVE_SLOT_EMPTY = пусто SELECT_LOAD_MENU = Загрузите игру\n\n AUTOSAVE_SLOT = Автосохранение BROKEN_SLOT = ошибка SELECT_SAVE_MENU = Сохраните игру\n\n MAIN_MENU = \ Продолжить игру\n\ Выбор игры\n\ Выбор темы\n\ Начать заново\n\ Загрузить игру\n\ Сохранить игру\n\ Информация\n\ Настройки\n\ Выход ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Интерпретатор простых\n\ текстовых приключений:\n\ Косых П.А. 2009-2023\n\ \n\ Сайт проекта:\n\ https://instead-hub.github.io\n\ \n\ Назад BACK_MENU = Назад ON = Да OFF = Нет KBD_MODE_LINKS = Ссылки KBD_MODE_SMART = Умный KBD_MODE_SCROLL = Прокрутка FROM_THEME = Тема SETTINGS_SND_MENU = \ [Графика][Звук][Другое]\n\ \n\ Громкость: <<< %d%% >>>\n\ \n\ Качество: << %dГц >>\n\ \n\ Музыка: %s\n\ \n\ Звук щелчка: %s\n\ \n\ Применить SETTINGS_GFX_MENU = \ [Графика][Звук][Другое]\n\ \n\ Размер окна: <<%s>>\n\ Полный экран: %s / HQ: %s\n\ Масштаб шрифта: <<%d%%>>\n\ Текст по ширине: <<%s>>\n\ Подсветка ссылок: %s\n\ Эффект перехода: %s\n\ Собственные темы игр: %s\n\ \n\ Применить SETTINGS_OTH_MENU = \ [Графика][Звук][Другое]\n\ \n\ Режим прокрутки: %s\n\ Фильтр мышки: %s\n\ Режим клавиатуры: %s\n\ \n\ Язык: <<%s>>\n\ \n\ Автосохранение: %s\n\ \n\ Применить CUSTOM_THEME_MENU = \ Внимание!!!\n\ \n\ Игра содержит собственную тему, но поддержка собственных тем отключена в настройках. \ Игра может выглядеть не так, как задумывал ее автор.\n\ \n\ Вы можете разрешить возможность переопределения тем в настройках.\n\ \n\ Да OWN_THEME_MENU = \ Внимание!!!\n\ \n\ Выбранная игра переопределяет тему. Изменения не вступят в силу.\n\ \n\ Вы можете запретить возможность переопределения тем в настройках.\n\ \n\ Да QUIT_MENU = \ На самом деле выйти?\n\ \n\ Да | Нет SELECT_GAME_MENU = Выбор игры\n\n SELECT_THEME_MENU = Выбор темы\n\n SAVED_MENU = \ Игра сохранена!\n\ \n\ Да NOGAMES_MENU = \ Не найдена ни одна игра.\n\ Пожалуйста, скопируйте хотя бы одну игру в каталог:\n'%s' NOTHEMES_MENU = \ Не найдена ни одна тема.\n\ Пожалуйста, скопируйте хотя бы одну тему в каталог:\n'%s'\n CANCEL_MENU = Отмена DISABLED_SAVE_MENU = \ Сохранение запрещено игрой.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Удалить игру?\n\ %s\n\ \n\ Да | Нет WAIT_MENU = \ Пожалуйста, подождите... instead-3.5.2+dfsg/lang/uk.ini000066400000000000000000000106551467622671600161600ustar00rootroot00000000000000;$Name:Українська$ UNKNOWN_ERROR = Невідома помилка. ERROR_MENU = Під час ініціалізації гри сталася помилка:\n\ '%s'\n\ \n\ Так WARNING_MENU = Під час роботи гри сталася помилка:\n\ '%s'\n\ \n\ Так SAVE_SLOT_EMPTY = порожньо SELECT_LOAD_MENU = Завантажте гру\n\n AUTOSAVE_SLOT = Автозбереження BROKEN_SLOT = помилка SELECT_SAVE_MENU = Збережіть гру\n\n MAIN_MENU = \ Продовжити гру\n\ Вибір гри\n\ Вибір теми\n\ Розпочати заново\n\ Завантажити гру\n\ Зберегти гру\n\ Інформація\n\ Налаштування\n\ Вихід ABOUT_MENU = \ INSTEAD - %s\n\ \n\ Інтерпретатор простих\n\ текстових пригод:\n\ Косих П.О. 2009-2023\n\ \n\ Сайт проєкту:\n\ https://instead-hub.github.io\n\ \n\ Назад BACK_MENU = Назад ON = Так OFF = Ні KBD_MODE_LINKS = Посилання KBD_MODE_SMART = Розумний KBD_MODE_SCROLL = Прокручування FROM_THEME = Тема SETTINGS_SND_MENU = \ [Графіка][Звук][Інше]\n\ \n\ Гучність: <<< %d%% >>>\n\ \n\ Якість: << %dГц >>\n\ \n\ Музика: %s\n\ \n\ Звук клацання: %s\n\ \n\ Застосувати SETTINGS_GFX_MENU = \ [Графіка][Звук][Інше]\n\ \n\ Розмір вікна: <<%s>>\n\ Повний екран: %s / HQ: %s\n\ Масштаб шрифту: <<%d%%>>\n\ Текст по ширині: <<%s>>\n\ Підсвічування посиланнь: %s\n\ Ефект загасання: %s\n\ Власні теми ігор: %s\n\ \n\ Застосувати SETTINGS_OTH_MENU = \ [Графіка][Звук][Інше]\n\ \n\ Режим прокручування: %s\n\ Фільтр миші: %s\n\ Режим клавіатури: %s\n\ \n\ Мова: <<%s>>\n\ \n\ Автозбереження: %s\n\ \n\ Застосувати CUSTOM_THEME_MENU = \ Увага!!!\n\ \n\ Гра містить власну тему, але підтримка власних тем відключена в налаштуваннях. \ Гра може виглядати не так, як задумував її автор.\n\ \n\ Ви можете дозволити можливість перевизначення тем в налаштуваннях.\n\ \n\ Так OWN_THEME_MENU = \ Увага!!!\n\ \n\ Вибрана гра перевизначає тему. Зміни не вступлять у силу.\n\ \n\ Ви можете заборонити можливість перевизначення тем у налаштуваннях.\n\ \n\ Так QUIT_MENU = \ Справді вийти?\n\ \n\ Так | Ні SELECT_GAME_MENU = Вибір гри\n\n SELECT_THEME_MENU = Вибір теми\n\n SAVED_MENU = \ Гра збережена!\n\ \n\ Так NOGAMES_MENU = \ Не знайдено жодної гри.\n\ Будь ласка, скопіюйте хоча б одну гру до каталогу:\n'%s' NOTHEMES_MENU = \ Не знайдено жодної теми.\n\ Будь ласка, скопіюйте хоча б одну тему до каталогу:\n'%s'\n CANCEL_MENU = Скасування DISABLED_SAVE_MENU = \ Збереження заборонене грою.\n BROWSE_MENU = \ [...] REMOVE_MENU = \ Видалити гру?\n\ %s\n\ \n\ Так | Ні WAIT_MENU = \ Будь ласка, зачекайте... instead-3.5.2+dfsg/sdl-instead000077700000000000000000000000001467622671600211562src/sdl-insteadustar00rootroot00000000000000instead-3.5.2+dfsg/src/000077500000000000000000000000001467622671600146775ustar00rootroot00000000000000instead-3.5.2+dfsg/src/CMakeLists.txt000066400000000000000000000113221467622671600174360ustar00rootroot00000000000000# sources SET(INSTEAD_SRCS SDL_gif.c SDL_gfxBlitFunc.c SDL_rotozoom.c config.c game.c graphics.c input.c noise1234.c ioapi.c main.c menu.c sound.c themes.c unpack.c unzip.c utils.c instead_bits.c instead_sprites.c instead_timer.c instead_sound.c instead_paths.c instead/instead.c instead/util.c instead/list.c instead/cache.c instead/idf.c instead/tinymt32.c instead/lfs.c ) # platform-specific sources IF(APPLE) SET(INSTEAD_SRCS ${INSTEAD_SRCS} macosx.m) ADD_DEFINITIONS(-Dunix) ELSEIF(WIN32) SET(INSTEAD_SRCS ${INSTEAD_SRCS} windows.c iowin32.c) ELSEIF(UNIX) SET(INSTEAD_SRCS ${INSTEAD_SRCS} unix.c) ADD_DEFINITIONS(-Dunix) ELSE(APPLE) MESSAGE(FATAL_ERROR "Your platform is not supported yet, sorry") ENDIF(APPLE) # flags ADD_DEFINITIONS( -DVERSION=\"${INSTEAD_VERSION}\" -D_USE_UNPACK -Wall -D_USE_SDL ) INCLUDE(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG(-Wextra WEXTRA_FLAG_SUPPORTED) CHECK_CXX_COMPILER_FLAG(-Wno-unused-parameter WNO_UNUSED_PARAMETER_FLAG_SUPPORTED) IF(WEXTRA_FLAG_SUPPORTED) ADD_DEFINITIONS(-Wextra) ENDIF(WEXTRA_FLAG_SUPPORTED) IF(WNO_UNUSED_PARAMETER_FLAG_SUPPORTED) ADD_DEFINITIONS(-Wno-unused-parameter) ENDIF(WNO_UNUSED_PARAMETER_FLAG_SUPPORTED) IF(APPIMAGE) ADD_DEFINITIONS(-DAPPIMAGE) ENDIF(APPIMAGE) IF(SYSTEMWIDE) if(APPIMAGE) ADD_DEFINITIONS( -DLANG_PATH=\"usr/${LANGDIR}/\" -DSTEAD_PATH=\"usr/${STEADDIR}/\" -DGAMES_PATH=\"usr/${GAMESDIR}/\" -DTHEMES_PATH=\"usr/${THEMESDIR}/\" -DICON_PATH=\"usr/${ICONDIR}/\" ) ELSE(APPIMAGE) # Systemwide installation, global data paths ADD_DEFINITIONS( -DLANG_PATH=\"${CMAKE_INSTALL_PREFIX}/${LANGDIR}/\" -DSTEAD_PATH=\"${CMAKE_INSTALL_PREFIX}/${STEADDIR}/\" -DGAMES_PATH=\"${CMAKE_INSTALL_PREFIX}/${GAMESDIR}/\" -DTHEMES_PATH=\"${CMAKE_INSTALL_PREFIX}/${THEMESDIR}/\" -DICON_PATH=\"${CMAKE_INSTALL_PREFIX}/${ICONDIR}/\" ) ENDIF(APPIMAGE) ELSEIF(STANDALONE) # Standalone installation, local data paths ADD_DEFINITIONS( -DLANG_PATH=\"lang/\" -DSTEAD_PATH=\"stead/\" -DGAMES_PATH=\"games/\" -DTHEMES_PATH=\"themes/\" -DICON_PATH=\"icon/\" -D_LOCAL_APPDATA ) ELSE(SYSTEMWIDE) # Neither, data paths point to source tree ADD_DEFINITIONS( -DLANG_PATH=\"${CMAKE_SOURCE_DIR}/lang/\" -DSTEAD_PATH=\"${CMAKE_SOURCE_DIR}/stead/\" -DGAMES_PATH=\"${CMAKE_SOURCE_DIR}/games/\" -DTHEMES_PATH=\"${CMAKE_SOURCE_DIR}/themes/\" -DICON_PATH=\"${CMAKE_SOURCE_DIR}/icon/\" ) ENDIF(SYSTEMWIDE) # depends IF(WITH_LUAJIT) FIND_PACKAGE(LuaJIT REQUIRED) ELSE(WITH_LUAJIT) FIND_PACKAGE(Lua51 REQUIRED) ENDif(WITH_LUAJIT) FIND_PACKAGE(ZLIB REQUIRED) FIND_LIBRARY(MATH_LIBRARY m) INCLUDE_DIRECTORIES( ${ZLIB_INCLUDE_DIRS} ${LUA_INCLUDE_DIR} ) SET(INSTEAD_LIBS ${ZLIB_LIBRARIES} ${LUA_LIBRARIES} ${MATH_LIBRARY} ) IF(APPLE) SET(INSTEAD_LIBS ${INSTEAD_LIBS} "-framework AppKit") ENDIF(APPLE) FIND_PACKAGE(SDL2 REQUIRED) FIND_PACKAGE(SDL2_mixer REQUIRED) FIND_PACKAGE(SDL2_image REQUIRED) FIND_PACKAGE(SDL2_ttf REQUIRED) INCLUDE_DIRECTORIES( ${SDL2_INCLUDE_DIR} ${SDL2MIXER_INCLUDE_DIR} ${SDL2IMAGE_INCLUDE_DIR} ${SDL2TTF_INCLUDE_DIR} ) LIST(APPEND INSTEAD_LIBS ${SDL2_LIBRARY} ${SDL2MIXER_LIBRARY} ${SDL2IMAGE_LIBRARY} ${SDL2TTF_LIBRARY} ) IF(WITH_ICONV) FIND_PACKAGE(Iconv REQUIRED) ADD_DEFINITIONS(-D_HAVE_ICONV) INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR}) SET(INSTEAD_LIBS ${INSTEAD_LIBS} ${ICONV_LIBRARY}) ENDIF(WITH_ICONV) IF(WITH_GTK2) FIND_PACKAGE(GTK2 REQUIRED) ADD_DEFINITIONS(-D_USE_GTK -D_USE_BROWSE ${GTK2_DEFINITIONS}) INCLUDE_DIRECTORIES(${GTK2_INCLUDE_DIRS}) SET(INSTEAD_LIBS ${INSTEAD_LIBS} ${GTK2_LIBRARIES}) ELSEIF(WITH_GTK3) FIND_PACKAGE(GTK3 REQUIRED) ADD_DEFINITIONS(-D_USE_GTK -D_USE_BROWSE) INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS}) SET(INSTEAD_LIBS ${INSTEAD_LIBS} ${GTK3_LIBRARIES}) ENDIF(WITH_GTK2) IF(WITH_HARFBUZZ) FIND_PACKAGE(HarfBuzz REQUIRED) ADD_DEFINITIONS(-D_USE_HARFBUZZ ${HARFBUZZ_DEFINITIONS}) INCLUDE_DIRECTORIES(${HARFBUZZ_INCLUDE_DIR}) SET(INSTEAD_LIBS ${INSTEAD_LIBS} ${HARFBUZZ_LIBRARY}) FIND_PACKAGE(PkgConfig REQUIRED) ENDIF(WITH_HARFBUZZ) IF(WITH_HARFBUZZ AND NOT WITH_GTK3) FIND_PACKAGE(GLIB REQUIRED) ADD_DEFINITIONS(${GLIB_DEFINITIONS}) INCLUDE_DIRECTORIES(${GLIB_INCLUDE_DIRS}) SET(INSTEAD_LIBS ${INSTEAD_LIBS} ${GLIB_LIBRARIES}) FIND_PACKAGE(PkgConfig REQUIRED) ENDIF(WITH_HARFBUZZ AND NOT WITH_GTK3) # targets ADD_EXECUTABLE(sdl-instead ${INSTEAD_SRCS}) TARGET_LINK_LIBRARIES(sdl-instead ${INSTEAD_LIBS}) # install INCLUDE(InstallSymlink) IF(SYSTEMWIDE) INSTALL(TARGETS sdl-instead DESTINATION ${BINDIR}) INSTALL_SYMLINK(sdl-instead instead${CMAKE_EXECUTABLE_SUFFIX} ${BINDIR}) ELSEIF(STANDALONE) INSTALL(TARGETS sdl-instead DESTINATION ${STANDALONEDIR}) INSTALL_SYMLINK(sdl-instead instead${CMAKE_EXECUTABLE_SUFFIX} ${STANDALONEDIR}) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/src/Makefile000066400000000000000000000031341467622671600163400ustar00rootroot00000000000000include ../Rules.make include ../config.make CFLAGS += $(SDL_CFLAGS) $(LUA_CFLAGS) $(ZLIB_CFLAGS) $(EXTRA_CFLAGS) -D_USE_SDL -DLANG_PATH=\"${LANGPATH}/\" -DSTEAD_PATH=\"${STEADPATH}/\" -DGAMES_PATH=\"${GAMESPATH}/\" -DTHEMES_PATH=\"${THEMESPATH}/\" -DVERSION=\"$(VERSION)\" -DICON_PATH=\"${ICONPATH}/\" LDFLAGS += $(SDL_LFLAGS) $(LUA_LFLAGS) $(ZLIB_LFLAGS) $(EXTRA_LDFLAGS) INSTEAD_SRC := instead/instead.c instead/util.c instead/list.c instead/cache.c instead/idf.c instead/tinymt32.c instead/lfs.c INSTEAD_H := instead/cache.h instead/system.h instead/instead.h instead/list.h instead/util.h instead/tinymt32.h instead/idf.h SRC := graphics.c input.c game.c main.c \ instead_bits.c instead_sprites.c instead_timer.c instead_sound.c instead_paths.c noise1234.c \ sound.c SDL_rotozoom.c SDL_gfxBlitFunc.c SDL_gif.c config.c themes.c menu.c \ utils.c unzip.c ioapi.c unpack.c $(PLATFORM) $(INSTEAD_SRC) H := config.h externals.h game.h graphics.h input.h internals.h ioapi.h iowin32.h \ menu.h SDL_rotozoom.h SDL_gif.h SDL_gfxBlitFunc.h sound.h themes.h unzip.h $(INSTEAD_H) OBJ := $(patsubst %.c, %.o, $(SRC)) $(ADDOBJ) all: sdl-instead$(EXE) $(OBJ): %.o : %.c $(H) $(CC) -c $(<) $(I) $(CFLAGS) $(CPPFLAGS) -o $(@) sdl-instead$(EXE): $(OBJ) $(RESOURCES) $(CC) $(CFLAGS) $(^) $(LDFLAGS) -o $(@) install: $(INSTALLD) $(DESTDIR)$(BIN) $(INSTALLB) sdl-instead$(EXE) $(DESTDIR)$(BIN)/sdl-instead$(EXE) $(LN) sdl-instead$(EXE) $(DESTDIR)$(BIN)/instead$(EXE) uninstall: $(RM) $(DESTDIR)$(BIN)/sdl-instead$(EXE) $(RM) $(DESTDIR)$(BIN)/instead$(EXE) clean: $(RM) -f *.o instead/*.o sdl-instead$(EXE) instead-3.5.2+dfsg/src/SDL_gfxBlitFunc.c000066400000000000000000000307701467622671600177670ustar00rootroot00000000000000/* SDL_gfxBlitFunc.c: custom blitters Copyright (C) 2001-2012 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #include "SDL_gfxBlitFunc.h" /*! \brief Alpha adjustment table for custom blitter. The table provides values for a modified, non-linear transfer function which maintain brightness. */ const unsigned int GFX_ALPHA_ADJUST_ARRAY[256] = { 0, /* 0 */ 15, /* 1 */ 22, /* 2 */ 27, /* 3 */ 31, /* 4 */ 35, /* 5 */ 39, /* 6 */ 42, /* 7 */ 45, /* 8 */ 47, /* 9 */ 50, /* 10 */ 52, /* 11 */ 55, /* 12 */ 57, /* 13 */ 59, /* 14 */ 61, /* 15 */ 63, /* 16 */ 65, /* 17 */ 67, /* 18 */ 69, /* 19 */ 71, /* 20 */ 73, /* 21 */ 74, /* 22 */ 76, /* 23 */ 78, /* 24 */ 79, /* 25 */ 81, /* 26 */ 82, /* 27 */ 84, /* 28 */ 85, /* 29 */ 87, /* 30 */ 88, /* 31 */ 90, /* 32 */ 91, /* 33 */ 93, /* 34 */ 94, /* 35 */ 95, /* 36 */ 97, /* 37 */ 98, /* 38 */ 99, /* 39 */ 100, /* 40 */ 102, /* 41 */ 103, /* 42 */ 104, /* 43 */ 105, /* 44 */ 107, /* 45 */ 108, /* 46 */ 109, /* 47 */ 110, /* 48 */ 111, /* 49 */ 112, /* 50 */ 114, /* 51 */ 115, /* 52 */ 116, /* 53 */ 117, /* 54 */ 118, /* 55 */ 119, /* 56 */ 120, /* 57 */ 121, /* 58 */ 122, /* 59 */ 123, /* 60 */ 124, /* 61 */ 125, /* 62 */ 126, /* 63 */ 127, /* 64 */ 128, /* 65 */ 129, /* 66 */ 130, /* 67 */ 131, /* 68 */ 132, /* 69 */ 133, /* 70 */ 134, /* 71 */ 135, /* 72 */ 136, /* 73 */ 137, /* 74 */ 138, /* 75 */ 139, /* 76 */ 140, /* 77 */ 141, /* 78 */ 141, /* 79 */ 142, /* 80 */ 143, /* 81 */ 144, /* 82 */ 145, /* 83 */ 146, /* 84 */ 147, /* 85 */ 148, /* 86 */ 148, /* 87 */ 149, /* 88 */ 150, /* 89 */ 151, /* 90 */ 152, /* 91 */ 153, /* 92 */ 153, /* 93 */ 154, /* 94 */ 155, /* 95 */ 156, /* 96 */ 157, /* 97 */ 158, /* 98 */ 158, /* 99 */ 159, /* 100 */ 160, /* 101 */ 161, /* 102 */ 162, /* 103 */ 162, /* 104 */ 163, /* 105 */ 164, /* 106 */ 165, /* 107 */ 165, /* 108 */ 166, /* 109 */ 167, /* 110 */ 168, /* 111 */ 168, /* 112 */ 169, /* 113 */ 170, /* 114 */ 171, /* 115 */ 171, /* 116 */ 172, /* 117 */ 173, /* 118 */ 174, /* 119 */ 174, /* 120 */ 175, /* 121 */ 176, /* 122 */ 177, /* 123 */ 177, /* 124 */ 178, /* 125 */ 179, /* 126 */ 179, /* 127 */ 180, /* 128 */ 181, /* 129 */ 182, /* 130 */ 182, /* 131 */ 183, /* 132 */ 184, /* 133 */ 184, /* 134 */ 185, /* 135 */ 186, /* 136 */ 186, /* 137 */ 187, /* 138 */ 188, /* 139 */ 188, /* 140 */ 189, /* 141 */ 190, /* 142 */ 190, /* 143 */ 191, /* 144 */ 192, /* 145 */ 192, /* 146 */ 193, /* 147 */ 194, /* 148 */ 194, /* 149 */ 195, /* 150 */ 196, /* 151 */ 196, /* 152 */ 197, /* 153 */ 198, /* 154 */ 198, /* 155 */ 199, /* 156 */ 200, /* 157 */ 200, /* 158 */ 201, /* 159 */ 201, /* 160 */ 202, /* 161 */ 203, /* 162 */ 203, /* 163 */ 204, /* 164 */ 205, /* 165 */ 205, /* 166 */ 206, /* 167 */ 206, /* 168 */ 207, /* 169 */ 208, /* 170 */ 208, /* 171 */ 209, /* 172 */ 210, /* 173 */ 210, /* 174 */ 211, /* 175 */ 211, /* 176 */ 212, /* 177 */ 213, /* 178 */ 213, /* 179 */ 214, /* 180 */ 214, /* 181 */ 215, /* 182 */ 216, /* 183 */ 216, /* 184 */ 217, /* 185 */ 217, /* 186 */ 218, /* 187 */ 218, /* 188 */ 219, /* 189 */ 220, /* 190 */ 220, /* 191 */ 221, /* 192 */ 221, /* 193 */ 222, /* 194 */ 222, /* 195 */ 223, /* 196 */ 224, /* 197 */ 224, /* 198 */ 225, /* 199 */ 225, /* 200 */ 226, /* 201 */ 226, /* 202 */ 227, /* 203 */ 228, /* 204 */ 228, /* 205 */ 229, /* 206 */ 229, /* 207 */ 230, /* 208 */ 230, /* 209 */ 231, /* 210 */ 231, /* 211 */ 232, /* 212 */ 233, /* 213 */ 233, /* 214 */ 234, /* 215 */ 234, /* 216 */ 235, /* 217 */ 235, /* 218 */ 236, /* 219 */ 236, /* 220 */ 237, /* 221 */ 237, /* 222 */ 238, /* 223 */ 238, /* 224 */ 239, /* 225 */ 240, /* 226 */ 240, /* 227 */ 241, /* 228 */ 241, /* 229 */ 242, /* 230 */ 242, /* 231 */ 243, /* 232 */ 243, /* 233 */ 244, /* 234 */ 244, /* 235 */ 245, /* 236 */ 245, /* 237 */ 246, /* 238 */ 246, /* 239 */ 247, /* 240 */ 247, /* 241 */ 248, /* 242 */ 248, /* 243 */ 249, /* 244 */ 249, /* 245 */ 250, /* 246 */ 250, /* 247 */ 251, /* 248 */ 251, /* 249 */ 252, /* 250 */ 252, /* 251 */ 253, /* 252 */ 253, /* 253 */ 254, /* 254 */ 255 /* 255 */ }; /*! \brief Internal blitter using adjusted destination alpha during RGBA->RGBA blits. Performs the blit based on the 'info' structure and applies the transfer function to the destination 'a' values. \param info The blit info to use. */ void _SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo * info) { int width = info->d_width; int height = info->d_height; Uint8 *src = info->s_pixels; int srcskip = info->s_skip; Uint8 *dst = info->d_pixels; int dstskip = info->d_skip; SDL_PixelFormat *srcfmt = info->src; SDL_PixelFormat *dstfmt = info->dst; Uint8 srcbpp = srcfmt->BytesPerPixel; Uint8 dstbpp = dstfmt->BytesPerPixel; while (height--) { GFX_DUFFS_LOOP4( { Uint32 pixel; unsigned sR; unsigned sG; unsigned sB; unsigned sA; unsigned dR; unsigned dG; unsigned dB; unsigned dA; unsigned sAA; GFX_DISASSEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA); GFX_DISASSEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); sAA=GFX_ALPHA_ADJUST_ARRAY[sA & 255]; GFX_ALPHA_BLEND(sR, sG, sB, sAA, dR, dG, dB); dA |= sAA; GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); src += srcbpp; dst += dstbpp; }, width); src += srcskip; dst += dstskip; } } /*! \brief Internal blitter setup wrapper for RGBA->RGBA blits. Sets up the blitter info based on the 'src' and 'dst' surfaces and rectangles. \param src The source surface. \param srcrect The source rectangle. \param dst The destination surface. \param dstrect The destination rectangle. \returns Returns 1 if blit was performed, 0 otherwise. */ int _SDL_gfxBlitRGBACall(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { /* * Set up source and destination buffer pointers, then blit */ if (srcrect->w && srcrect->h) { SDL_gfxBlitInfo info; /* * Set up the blit information */ info.s_pixels = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel; info.s_width = srcrect->w; info.s_height = srcrect->h; info.s_skip = (int)(src->pitch - info.s_width * src->format->BytesPerPixel); info.d_pixels = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel; info.d_width = dstrect->w; info.d_height = dstrect->h; info.d_skip = (int)(dst->pitch - info.d_width * dst->format->BytesPerPixel); info.aux_data = NULL; info.src = src->format; info.table = NULL; info.dst = dst->format; /* * Run the actual software blitter */ _SDL_gfxBlitBlitterRGBA(&info); return 1; } return (0); } /*! \brief Blitter for RGBA->RGBA blits with alpha adjustment. Verifies the input 'src' and 'dst' surfaces and rectangles and performs blit. The destination clip rectangle is honored. \param src The source surface. \param srcrect The source rectangle. \param dst The destination surface. \param dstrect The destination rectangle. \returns Returns 1 if blit was performed, 0 otherwise, or -1 if an error occured. */ int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { SDL_Rect sr, dr; int srcx, srcy, w, h; /* * Make sure the surfaces aren't locked */ if (!src || !dst) { SDL_SetError("SDL_UpperBlit: passed a NULL surface"); return (-1); } if ((src->locked) || (dst->locked)) { SDL_SetError("Surfaces must not be locked during blit"); return (-1); } /* * If the destination rectangle is NULL, use the entire dest surface */ if (dstrect == NULL) { dr.x = dr.y = 0; dr.w = dst->w; dr.h = dst->h; } else { dr = *dstrect; } /* * Clip the source rectangle to the source surface */ if (srcrect) { int maxw, maxh; srcx = srcrect->x; w = srcrect->w; if (srcx < 0) { w += srcx; dr.x -= srcx; srcx = 0; } maxw = src->w - srcx; if (maxw < w) w = maxw; srcy = srcrect->y; h = srcrect->h; if (srcy < 0) { h += srcy; dr.y -= srcy; srcy = 0; } maxh = src->h - srcy; if (maxh < h) h = maxh; } else { srcx = srcy = 0; w = src->w; h = src->h; } /* * Clip the destination rectangle against the clip rectangle */ { SDL_Rect *clip = &dst->clip_rect; int dx, dy; dx = clip->x - dr.x; if (dx > 0) { w -= dx; dr.x += dx; srcx += dx; } dx = dr.x + w - clip->x - clip->w; if (dx > 0) w -= dx; dy = clip->y - dr.y; if (dy > 0) { h -= dy; dr.y += dy; srcy += dy; } dy = dr.y + h - clip->y - clip->h; if (dy > 0) h -= dy; } if (w > 0 && h > 0) { sr.x = srcx; sr.y = srcy; sr.w = dr.w = w; sr.h = dr.h = h; return (_SDL_gfxBlitRGBACall(src, &sr, dst, &dr)); } return 0; } /*! \brief Sets the alpha channel in a 32 bit surface. Helper function that sets the alpha channel in a 32 bit surface to a constant value. Only 32 bit surfaces can be used with this function. \param src Pointer to the target surface to change. \param a The alpha value to set. \return Returns 1 if alpha was changed, -1 otherwise. */ int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN const int alpha_offset = 0; #else const int alpha_offset = 3; #endif int i, j, row_skip; Uint8 *pixels; /* Check if we have a 32bit surface */ if ( (src==NULL) || (src->format==NULL) || (src->format->BytesPerPixel!=4) ) { SDL_SetError("SDL_gfxSetAlpha: Invalid input surface."); return -1; } /* * Lock the surface */ if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { return (-1); } } /* Process */ pixels = (Uint8 *)src->pixels; row_skip = (src->pitch - (4*src->w)); pixels += alpha_offset; for ( i=0; ih; i++ ) { for ( j=0; jw; j++ ) { *pixels = a; pixels += 4; } pixels += row_skip; } /* * Unlock surface */ if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } return 1; } /*! \brief Multiply the alpha channel in a 32bit surface. Helper function that multiplies the alpha channel in a 32 bit surface with a constant value. The final alpha is always scaled to the range 0-255 (i.e. the factor is a/256). Only 32 bit surfaces can be used with this function. \param src Pointer to the target surface to change. \param a The alpha value to multiply with. When a is 255, this function is a NoOp. \return Returns 1 if alpha was changed, 0 otherwise. Returns -1 if input surface is invalid. */ int SDL_gfxMultiplyAlpha(SDL_Surface *src, Uint8 a) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN const int alpha_offset = 0; #else const int alpha_offset = 3; #endif int i, j, row_skip; Uint8 *pixels; /* Check if we have a 32bit surface */ if ( (src==NULL) || (src->format==NULL) || (src->format->BytesPerPixel!=4) ) { SDL_SetError("SDL_gfxMultiplyAlpha: Invalid input surface."); return -1; } /* Check if multiplication is needed */ if (a==255) { return 0; } /* * Lock the surface */ if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { return (-1); } } /* Process */ pixels = (Uint8 *)src->pixels; row_skip = (src->pitch - (4*src->w)); pixels += alpha_offset; for ( i=0; ih; i++ ) { for ( j=0; jw; j++ ) { *pixels = (Uint8)(((int)(*pixels)*a)>>8); pixels += 4; } pixels += row_skip; } /* * Unlock surface */ if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } return 1; } instead-3.5.2+dfsg/src/SDL_gfxBlitFunc.h000066400000000000000000000107161467622671600177720ustar00rootroot00000000000000/* SDL_gfxBlitFunc.h: custom blitters Copyright (C) 2001-2012 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #ifndef _SDL_gfxBlitFunc_h #define _SDL_gfxBlitFunc_h /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif #include #include #include #include extern const unsigned int GFX_ALPHA_ADJUST_ARRAY[256]; /* ---- Function Prototypes */ #ifdef _MSC_VER # if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT) # define SDL_GFXBLITFUNC_SCOPE __declspec(dllexport) # else # ifdef LIBSDL_GFX_DLL_IMPORT # define SDL_GFXBLITFUNC_SCOPE __declspec(dllimport) # endif # endif #endif #ifndef SDL_GFXBLITFUNC_SCOPE # define SDL_GFXBLITFUNC_SCOPE extern #endif SDL_GFXBLITFUNC_SCOPE int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect); SDL_GFXBLITFUNC_SCOPE int SDL_gfxSetAlpha(SDL_Surface * src, Uint8 a); SDL_GFXBLITFUNC_SCOPE int SDL_gfxMultiplyAlpha(SDL_Surface * src, Uint8 a); /* -------- Macros */ /* Define SDL macros locally as a substitute for an #include "SDL_blit.h", */ /* which doesn't work since the include file doesn't get installed. */ /*! \brief The structure passed to the low level blit functions. */ typedef struct { Uint8 *s_pixels; int s_width; int s_height; int s_skip; Uint8 *d_pixels; int d_width; int d_height; int d_skip; void *aux_data; SDL_PixelFormat *src; Uint8 *table; SDL_PixelFormat *dst; } SDL_gfxBlitInfo; /*! \brief Unwrap RGBA values from a pixel using mask, shift and loss for surface. */ #define GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a) \ { \ r = ((pixel&fmt->Rmask)>>fmt->Rshift)<Rloss; \ g = ((pixel&fmt->Gmask)>>fmt->Gshift)<Gloss; \ b = ((pixel&fmt->Bmask)>>fmt->Bshift)<Bloss; \ a = ((pixel&fmt->Amask)>>fmt->Ashift)<Aloss; \ } /*! \brief Disassemble buffer pointer into a pixel and separate RGBA values. */ #define GFX_DISASSEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a) \ do { \ pixel = *((Uint32 *)(buf)); \ GFX_RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \ pixel &= ~fmt->Amask; \ } while(0) /*! \brief Wrap a pixel from RGBA values using mask, shift and loss for surface. */ #define GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a) \ { \ pixel = ((r>>fmt->Rloss)<Rshift)| \ ((g>>fmt->Gloss)<Gshift)| \ ((b>>fmt->Bloss)<Bshift)| \ ((a<Aloss)<Ashift); \ } /*! \brief Assemble pixel into buffer pointer from separate RGBA values. */ #define GFX_ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ { \ Uint32 pixel; \ \ GFX_PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ *((Uint32 *)(buf)) = pixel; \ } /*! \brief Blend the RGB values of two pixels based on a source alpha value. */ #define GFX_ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ do { \ dR = (((sR-dR)*(A))/255)+dR; \ dG = (((sG-dG)*(A))/255)+dG; \ dB = (((sB-dB)*(A))/255)+dB; \ } while(0) /*! \brief 4-times unrolled DUFFs loop. This is a very useful loop for optimizing blitters. */ #define GFX_DUFFS_LOOP4(pixel_copy_increment, width) \ { int n = (width+3)/4; \ switch (width & 3) { \ case 0: do { pixel_copy_increment; /* fall through */ \ case 3: pixel_copy_increment; /* fall through */ \ case 2: pixel_copy_increment; /* fall through */ \ case 1: pixel_copy_increment; \ } while ( --n > 0 ); \ } \ } /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif #endif /* _SDL_gfxBlitFunc_h */ instead-3.5.2+dfsg/src/SDL_gif.c000066400000000000000000000552161467622671600163230ustar00rootroot00000000000000/* Code adopted from SDL2_image library, Licensed under zlib */ /* SDL_image: An example image loading library for use with SDL Copyright (C) 1997-2020 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* This is a GIF image file loading framework */ #include #include /* Code from here to end of file has been adapted from XPaint: */ /* +-------------------------------------------------------------------+ */ /* | Copyright 1990, 1991, 1993 David Koblas. | */ /* | Copyright 1996 Torsten Martinsen. | */ /* | Permission to use, copy, modify, and distribute this software | */ /* | and its documentation for any purpose and without fee is hereby | */ /* | granted, provided that the above copyright notice appear in all | */ /* | copies and that both that copyright notice and this permission | */ /* | notice appear in supporting documentation. This software is | */ /* | provided "as is" without express or implied warranty. | */ /* +-------------------------------------------------------------------+ */ /* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */ /* Changes to work with SDL: Include SDL header file Use SDL_Surface rather than xpaint Image structure Define SDL versions of RWSetMsg(), ImageNewCmap() and ImageSetCmap() */ #include #include "SDL_gif.h" #include "instead/instead.h" extern idf_t game_idf; void FreeAnimation(Animation_t *anim) { if (anim) { if (anim->frames) { int i; for (i = 0; i < anim->count; ++i) { if (anim->frames[i]) { SDL_FreeSurface(anim->frames[i]); } } SDL_free(anim->frames); } if (anim->delays) { SDL_free(anim->delays); } SDL_free(anim); } } #define Image SDL_Surface #define RWSetMsg IMG_SetError #define ImageNewCmap(w, h, s) SDL_CreateRGBSurface(SDL_SWSURFACE,w,h,8,0,0,0,0) #define ImageSetCmap(s, i, R, G, B) do { \ s->format->palette->colors[i].r = R; \ s->format->palette->colors[i].g = G; \ s->format->palette->colors[i].b = B; \ } while (0) /* * * * * */ #define GIF_DISPOSE_NA 0 /* No disposal specified */ #define GIF_DISPOSE_NONE 1 /* Do not dispose */ #define GIF_DISPOSE_RESTORE_BACKGROUND 2 /* Restore to background */ #define GIF_DISPOSE_RESTORE_PREVIOUS 3 /* Restore to previous */ #define MAXCOLORMAPSIZE 256 #define TRUE 1 #define FALSE 0 #define CM_RED 0 #define CM_GREEN 1 #define CM_BLUE 2 #define MAX_LWZ_BITS 12 #define INTERLACE 0x40 #define LOCALCOLORMAP 0x80 #define BitSet(byte, bit) (((byte) & (bit)) == (bit)) #define ReadOK(file,buffer,len) SDL_RWread(file, buffer, len, 1) #define LM_to_uint(a,b) (((b)<<8)|(a)) typedef struct { Image *image; int x, y; int disposal; int delay; } GIF_Frame_t; typedef struct { int count; int loop; GIF_Frame_t *frames; } GIF_Anim_t; typedef struct { struct { unsigned int Width; unsigned int Height; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned int BitPixel; unsigned int ColorResolution; unsigned int Background; unsigned int AspectRatio; int GrayScale; } GifScreen; struct { int transparent; int delayTime; int inputFlag; int disposal; } Gif89; unsigned char buf[280]; int curbit, lastbit, done, last_byte; int fresh; int code_size, set_code_size; int max_code, max_code_size; int firstcode, oldcode; int clear_code, end_code; int table[2][(1 << MAX_LWZ_BITS)]; int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp; int ZeroDataBlock; int loop; } State_t; static int ReadColorMap(SDL_RWops * src, int number, unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag); static int DoExtension(SDL_RWops * src, int label, State_t * state); static int GetDataBlock(SDL_RWops * src, unsigned char *buf, State_t * state); static int GetCode(SDL_RWops * src, int code_size, int flag, State_t * state); static int LWZReadByte(SDL_RWops * src, int flag, int input_code_size, State_t * state); static Image *ReadImage(SDL_RWops * src, int len, int height, int, unsigned char cmap[3][MAXCOLORMAPSIZE], int gray, int interlace, int ignore, State_t * state); static SDL_bool NormalizeFrames(GIF_Frame_t *frames, int count) { SDL_Surface *image; int i; int lastDispose = GIF_DISPOSE_RESTORE_BACKGROUND; int iRestore = 0; Uint32 fill; SDL_Rect rect; if (SDL_GetColorKey(frames[0].image, NULL) == 0) { image = SDL_ConvertSurfaceFormat(frames[0].image, SDL_PIXELFORMAT_ARGB8888, 0); } else { image = SDL_ConvertSurfaceFormat(frames[0].image, SDL_PIXELFORMAT_RGB888, 0); } if (!image) { return SDL_FALSE; } fill = SDL_MapRGBA(image->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT); rect.x = 0; rect.y = 0; rect.w = image->w; rect.h = image->h; for (i = 0; i < count; ++i) { switch (lastDispose) { case GIF_DISPOSE_RESTORE_BACKGROUND: SDL_FillRect(image, &rect, fill); break; case GIF_DISPOSE_RESTORE_PREVIOUS: SDL_BlitSurface(frames[iRestore].image, &rect, image, &rect); break; default: break; } if (frames[i].disposal != GIF_DISPOSE_RESTORE_PREVIOUS) { iRestore = i; } rect.x = (Sint16)frames[i].x; rect.y = (Sint16)frames[i].y; rect.w = frames[i].image->w; rect.h = frames[i].image->h; SDL_BlitSurface(frames[i].image, NULL, image, &rect); SDL_FreeSurface(frames[i].image); frames[i].image = SDL_ConvertSurface(image, image->format, image->flags); if (!frames[i].image) { return SDL_FALSE; } lastDispose = frames[i].disposal; } SDL_FreeSurface( image ); return SDL_TRUE; } static GIF_Anim_t * IMG_LoadGIF_RW_Internal(SDL_RWops *src, SDL_bool load_anim) { unsigned char buf[16]; unsigned char c; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; int grayScale; int useGlobalColormap; int bitPixel; char version[4]; Image *image = NULL; GIF_Anim_t *anim; GIF_Frame_t *frames, *frame; State_t state; state.ZeroDataBlock = FALSE; state.fresh = FALSE; state.last_byte = 0; state.loop = 1; if (src == NULL) { return NULL; } anim = (GIF_Anim_t *)SDL_calloc(1, sizeof(*anim)); if (!anim) { SDL_OutOfMemory(); return NULL; } if (!ReadOK(src, buf, 6)) { RWSetMsg("error reading magic number"); goto done; } if (SDL_strncmp((char *) buf, "GIF", 3) != 0) { RWSetMsg("not a GIF file"); goto done; } SDL_memcpy(version, (char *) buf + 3, 3); version[3] = '\0'; if ((SDL_strcmp(version, "87a") != 0) && (SDL_strcmp(version, "89a") != 0)) { RWSetMsg("bad version number, not '87a' or '89a'"); goto done; } state.Gif89.transparent = -1; state.Gif89.delayTime = -1; state.Gif89.inputFlag = -1; state.Gif89.disposal = GIF_DISPOSE_NA; if (!ReadOK(src, buf, 7)) { RWSetMsg("failed to read screen descriptor"); goto done; } state.GifScreen.Width = LM_to_uint(buf[0], buf[1]); state.GifScreen.Height = LM_to_uint(buf[2], buf[3]); state.GifScreen.BitPixel = 2 << (buf[4] & 0x07); state.GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); state.GifScreen.Background = buf[5]; state.GifScreen.AspectRatio = buf[6]; if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ if (ReadColorMap(src, state.GifScreen.BitPixel, state.GifScreen.ColorMap, &state.GifScreen.GrayScale)) { RWSetMsg("error reading global colormap"); goto done; } } for ( ; ; ) { if (!ReadOK(src, &c, 1)) { RWSetMsg("EOF / read error on image data"); goto done; } if (c == ';') { /* GIF terminator */ goto done; } if (c == '!') { /* Extension */ if (!ReadOK(src, &c, 1)) { RWSetMsg("EOF / read error on extention function code"); goto done; } DoExtension(src, c, &state); continue; } if (c != ',') { /* Not a valid start character */ continue; } if (!ReadOK(src, buf, 9)) { RWSetMsg("couldn't read left/top/width/height"); goto done; } useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP); bitPixel = 1 << ((buf[8] & 0x07) + 1); if (!useGlobalColormap) { if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) { RWSetMsg("error reading local colormap"); goto done; } image = ReadImage(src, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), bitPixel, localColorMap, grayScale, BitSet(buf[8], INTERLACE), 0, &state); } else { image = ReadImage(src, LM_to_uint(buf[4], buf[5]), LM_to_uint(buf[6], buf[7]), state.GifScreen.BitPixel, state.GifScreen.ColorMap, state.GifScreen.GrayScale, BitSet(buf[8], INTERLACE), 0, &state); } if (image) { if (state.Gif89.transparent >= 0) { SDL_SetColorKey(image, SDL_TRUE, state.Gif89.transparent); } frames = (GIF_Frame_t *)SDL_realloc(anim->frames, (anim->count + 1) * sizeof(*anim->frames)); if (!frames) { SDL_OutOfMemory(); goto done; } ++anim->count; anim->frames = frames; frame = &anim->frames[anim->count - 1]; frame->image = image; frame->x = LM_to_uint(buf[0], buf[1]); frame->y = LM_to_uint(buf[2], buf[3]); frame->disposal = state.Gif89.disposal; if (state.Gif89.delayTime < 2) { frame->delay = 100; /* Default animation delay, matching browsers and Qt */ } else { frame->delay = state.Gif89.delayTime * 10; } if (!load_anim) { /* We only need one frame, we're done */ goto done; } } } done: if (anim->count > 1) { /* Normalize the frames */ if (!NormalizeFrames(anim->frames, anim->count)) { int i; for (i = 0; i < anim->count; ++i) { SDL_FreeSurface(anim->frames[i].image); } anim->count = 0; } } if (anim->count == 0) { SDL_free(anim->frames); SDL_free(anim); return NULL; } anim->loop = state.loop; return anim; } static int ReadColorMap(SDL_RWops *src, int number, unsigned char buffer[3][MAXCOLORMAPSIZE], int *gray) { int i; unsigned char rgb[3]; int flag; flag = TRUE; for (i = 0; i < number; ++i) { if (!ReadOK(src, rgb, sizeof(rgb))) { RWSetMsg("bad colormap"); return 1; } buffer[CM_RED][i] = rgb[0]; buffer[CM_GREEN][i] = rgb[1]; buffer[CM_BLUE][i] = rgb[2]; flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]); } #if 0 if (flag) *gray = (number == 2) ? PBM_TYPE : PGM_TYPE; else *gray = PPM_TYPE; #else *gray = 0; #endif return FALSE; } static int DoExtension(SDL_RWops *src, int label, State_t * state) { unsigned char buf[256]; switch (label) { case 0x01: /* Plain Text Extension */ break; case 0xff: /* Application Extension */ if (GetDataBlock(src, buf, state ) != 11) break; if (strncmp((char*)buf, "NETSCAPE2.0", 11)) break; if (GetDataBlock(src, buf, state) != 3) break; if (buf[0] != 1) break; state->loop = (unsigned int)buf[1] | (((unsigned int)buf[2]) << 8); break; break; case 0xfe: /* Comment Extension */ while (GetDataBlock(src, buf, state) > 0) ; return FALSE; case 0xf9: /* Graphic Control Extension */ (void) GetDataBlock(src, buf, state); state->Gif89.disposal = (buf[0] >> 2) & 0x7; state->Gif89.inputFlag = (buf[0] >> 1) & 0x1; state->Gif89.delayTime = LM_to_uint(buf[1], buf[2]); if ((buf[0] & 0x1) != 0) state->Gif89.transparent = buf[3]; while (GetDataBlock(src, buf, state) > 0) ; return FALSE; default: break; } while (GetDataBlock(src, buf, state) > 0) ; return FALSE; } static int GetDataBlock(SDL_RWops *src, unsigned char *buf, State_t * state) { unsigned char count; if (!ReadOK(src, &count, 1)) { /* pm_message("error in getting DataBlock size" ); */ return -1; } state->ZeroDataBlock = count == 0; if ((count != 0) && (!ReadOK(src, buf, count))) { /* pm_message("error in reading DataBlock" ); */ return -1; } return count; } static int GetCode(SDL_RWops *src, int code_size, int flag, State_t * state) { int i, j, ret; unsigned char count; if (flag) { state->curbit = 0; state->lastbit = 0; state->done = FALSE; return 0; } if ((state->curbit + code_size) >= state->lastbit) { if (state->done) { if (state->curbit >= state->lastbit) RWSetMsg("ran off the end of my bits"); return -1; } state->buf[0] = state->buf[state->last_byte - 2]; state->buf[1] = state->buf[state->last_byte - 1]; if ((ret = GetDataBlock(src, &state->buf[2], state)) > 0) count = (unsigned char) ret; else { count = 0; state->done = TRUE; } state->last_byte = 2 + count; state->curbit = (state->curbit - state->lastbit) + 16; state->lastbit = (2 + count) * 8; } ret = 0; for (i = state->curbit, j = 0; j < code_size; ++i, ++j) ret |= ((state->buf[i / 8] & (1 << (i % 8))) != 0) << j; state->curbit += code_size; return ret; } static int LWZReadByte(SDL_RWops *src, int flag, int input_code_size, State_t * state) { int code, incode; register int i; /* Fixed buffer overflow found by Michael Skladnikiewicz */ if (input_code_size > MAX_LWZ_BITS) return -1; if (flag) { state->set_code_size = input_code_size; state->code_size = state->set_code_size + 1; state->clear_code = 1 << state->set_code_size; state->end_code = state->clear_code + 1; state->max_code_size = 2 * state->clear_code; state->max_code = state->clear_code + 2; GetCode(src, 0, TRUE, state); state->fresh = TRUE; for (i = 0; i < state->clear_code; ++i) { state->table[0][i] = 0; state->table[1][i] = i; } state->table[1][0] = 0; for (; i < (1 << MAX_LWZ_BITS); ++i) state->table[0][i] = 0; state->sp = state->stack; return 0; } else if (state->fresh) { state->fresh = FALSE; do { state->firstcode = state->oldcode = GetCode(src, state->code_size, FALSE, state); } while (state->firstcode == state->clear_code); return state->firstcode; } if (state->sp > state->stack) return *--state->sp; while ((code = GetCode(src, state->code_size, FALSE, state)) >= 0) { if (code == state->clear_code) { for (i = 0; i < state->clear_code; ++i) { state->table[0][i] = 0; state->table[1][i] = i; } for (; i < (1 << MAX_LWZ_BITS); ++i) state->table[0][i] = state->table[1][i] = 0; state->code_size = state->set_code_size + 1; state->max_code_size = 2 * state->clear_code; state->max_code = state->clear_code + 2; state->sp = state->stack; state->firstcode = state->oldcode = GetCode(src, state->code_size, FALSE, state); return state->firstcode; } else if (code == state->end_code) { int count; unsigned char buf[260]; if (state->ZeroDataBlock) return -2; while ((count = GetDataBlock(src, buf, state)) > 0) ; if (count != 0) { /* * pm_message("missing EOD in data stream (common occurence)"); */ } return -2; } incode = code; if (code >= state->max_code) { *state->sp++ = state->firstcode; code = state->oldcode; } while (code >= state->clear_code) { /* Guard against buffer overruns */ if (code < 0 || code >= (1 << MAX_LWZ_BITS)) { RWSetMsg("invalid LWZ data"); return -3; } *state->sp++ = state->table[1][code]; if (code == state->table[0][code]) { RWSetMsg("circular table entry BIG ERROR"); return -3; } code = state->table[0][code]; } /* Guard against buffer overruns */ if (code < 0 || code >= (1 << MAX_LWZ_BITS)) { RWSetMsg("invalid LWZ data"); return -4; } *state->sp++ = state->firstcode = state->table[1][code]; if ((code = state->max_code) < (1 << MAX_LWZ_BITS)) { state->table[0][code] = state->oldcode; state->table[1][code] = state->firstcode; ++state->max_code; if ((state->max_code >= state->max_code_size) && (state->max_code_size < (1 << MAX_LWZ_BITS))) { state->max_code_size *= 2; ++state->code_size; } } state->oldcode = incode; if (state->sp > state->stack) return *--state->sp; } return code; } static Image * ReadImage(SDL_RWops * src, int len, int height, int cmapSize, unsigned char cmap[3][MAXCOLORMAPSIZE], int gray, int interlace, int ignore, State_t * state) { Image *image; unsigned char c; int i, v; int xpos = 0, ypos = 0, pass = 0; (void) gray; /* unused */ /* ** Initialize the compression routines */ if (!ReadOK(src, &c, 1)) { RWSetMsg("EOF / read error on image data"); return NULL; } if (LWZReadByte(src, TRUE, c, state) < 0) { RWSetMsg("error reading image"); return NULL; } /* ** If this is an "uninteresting picture" ignore it. */ if (ignore) { while (LWZReadByte(src, FALSE, c, state) >= 0) ; return NULL; } image = ImageNewCmap(len, height, cmapSize); for (i = 0; i < cmapSize; i++) ImageSetCmap(image, i, cmap[CM_RED][i], cmap[CM_GREEN][i], cmap[CM_BLUE][i]); while ((v = LWZReadByte(src, FALSE, c, state)) >= 0) { ((Uint8 *)image->pixels)[xpos + ypos * image->pitch] = (Uint8)v; ++xpos; if (xpos == len) { xpos = 0; if (interlace) { switch (pass) { case 0: case 1: ypos += 8; break; case 2: ypos += 4; break; case 3: ypos += 2; break; } if (ypos >= height) { ++pass; switch (pass) { case 1: ypos = 4; break; case 2: ypos = 2; break; case 3: ypos = 1; break; default: goto fini; } } } else { ++ypos; } } if (ypos >= height) break; } fini: return image; } /* Load a GIF type animation from an SDL datasource */ static Animation_t *LoadGIFAnimation_RW(SDL_RWops *src) { GIF_Anim_t *internal = IMG_LoadGIF_RW_Internal(src, SDL_TRUE); if (internal) { Animation_t *anim = (Animation_t *)SDL_malloc(sizeof(*anim)); if (anim) { anim->w = internal->frames[0].image->w; anim->h = internal->frames[0].image->h; anim->count = internal->count; anim->loop = internal->loop; anim->frames = (SDL_Surface **)SDL_calloc(anim->count, sizeof(*anim->frames)); anim->delays = (int *)SDL_calloc(anim->count, sizeof(*anim->delays)); if (anim->frames && anim->delays) { int i; for (i = 0; i < anim->count; ++i) { anim->frames[i] = internal->frames[i].image; anim->delays[i] = internal->frames[i].delay; } } else { FreeAnimation(anim); anim = NULL; } } if (!anim) { SDL_OutOfMemory(); } SDL_free(internal->frames); SDL_free(internal); return anim; } return NULL; } Animation_t *GIF_LoadAnim(const char* file) { Animation_t *anim; SDL_RWops* src = RWFromIdf(instead_idf(), file); if (!src) return NULL; anim = LoadGIFAnimation_RW(src); SDL_RWclose(src); if (!anim) return NULL; if (anim->count <=1) { FreeAnimation(anim); return NULL; } return anim; } instead-3.5.2+dfsg/src/SDL_gif.h000066400000000000000000000025651467622671600163270ustar00rootroot00000000000000#ifndef _SDL_AGIF_H #define _SDL_AGIF_H /* Code adopted from SDL2_image library, Licensed under zlib */ /* SDL_image: An example image loading library for use with SDL Copyright (C) 1997-2020 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* This is a GIF image file loading framework */ #include typedef struct { int w, h; int count; int loop; SDL_Surface **frames; int *delays; } Animation_t; extern DECLSPEC Animation_t *GIF_LoadAnim(const char* file); extern DECLSPEC void FreeAnimation(Animation_t *anim); #endif /* _SDL_AGIF_H */ instead-3.5.2+dfsg/src/SDL_rotozoom.c000066400000000000000000001212561467622671600174440ustar00rootroot00000000000000/* SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces Copyright (C) 2012 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #ifdef WIN32 #include #endif #include #include #include "SDL_rotozoom.h" /* ---- Internally used structures */ /*! \brief A 32 bit RGBA pixel. */ typedef struct tColorRGBA { Uint8 r; Uint8 g; Uint8 b; Uint8 a; } tColorRGBA; /*! \brief A 8bit Y/palette pixel. */ typedef struct tColorY { Uint8 y; } tColorY; /*! \brief Returns maximum of two numbers a and b. */ #define MAX(a,b) (((a) > (b)) ? (a) : (b)) /*! \brief Number of guard rows added to destination surfaces. This is a simple but effective workaround for observed issues. These rows allocate extra memory and are then hidden from the surface. Rows are added to the end of destination surfaces when they are allocated. This catches any potential overflows which seem to happen with just the right src image dimensions and scale/rotation and can lead to a situation where the program can segfault. */ #define GUARD_ROWS (2) /*! \brief Lower limit of absolute zoom factor or rotation degrees. */ #define VALUE_LIMIT 0.001 /*! \brief Returns colorkey info for a surface */ Uint32 _colorkey(SDL_Surface *src) { Uint32 key = 0; SDL_GetColorKey(src, &key); return key; } /*! \brief Internal 32 bit integer-factor averaging Shrinker. Shrinks 32 bit RGBA/ABGR 'src' surface to 'dst' surface. Averages color and alpha values values of src pixels to calculate dst pixels. Assumes src and dst surfaces are of 32 bit depth. Assumes dst surface was allocated with the correct dimensions. \param src The surface to shrink (input). \param dst The shrunken surface (output). \param factorx The horizontal shrinking ratio. \param factory The vertical shrinking ratio. \return 0 for success or -1 for error. */ int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) { int x, y, dx, dy, dgap, ra, ga, ba, aa; int n_average; tColorRGBA *sp, *osp, *oosp; tColorRGBA *dp; /* * Averaging integer shrink */ /* Precalculate division factor */ n_average = factorx*factory; /* * Scan destination */ sp = (tColorRGBA *) src->pixels; dp = (tColorRGBA *) dst->pixels; dgap = dst->pitch - dst->w * 4; for (y = 0; y < dst->h; y++) { osp=sp; for (x = 0; x < dst->w; x++) { /* Trace out source box and accumulate */ oosp=sp; ra=ga=ba=aa=0; for (dy=0; dy < factory; dy++) { for (dx=0; dx < factorx; dx++) { ra += sp->r; ga += sp->g; ba += sp->b; aa += sp->a; sp++; } /* src dx loop */ sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); /* next y */ } /* src dy loop */ /* next box-x */ sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx); /* Store result in destination */ dp->r = ra/n_average; dp->g = ga/n_average; dp->b = ba/n_average; dp->a = aa/n_average; /* * Advance destination pointer */ dp++; } /* dst x loop */ /* next box-y */ sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory); /* * Advance destination pointers */ dp = (tColorRGBA *) ((Uint8 *) dp + dgap); } /* dst y loop */ return (0); } /*! \brief Internal 8 bit integer-factor averaging shrinker. Shrinks 8bit Y 'src' surface to 'dst' surface. Averages color (brightness) values values of src pixels to calculate dst pixels. Assumes src and dst surfaces are of 8 bit depth. Assumes dst surface was allocated with the correct dimensions. \param src The surface to shrink (input). \param dst The shrunken surface (output). \param factorx The horizontal shrinking ratio. \param factory The vertical shrinking ratio. \return 0 for success or -1 for error. */ int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory) { int x, y, dx, dy, dgap, a; int n_average; Uint8 *sp, *osp, *oosp; Uint8 *dp; /* * Averaging integer shrink */ /* Precalculate division factor */ n_average = factorx*factory; /* * Scan destination */ sp = (Uint8 *) src->pixels; dp = (Uint8 *) dst->pixels; dgap = dst->pitch - dst->w; for (y = 0; y < dst->h; y++) { osp=sp; for (x = 0; x < dst->w; x++) { /* Trace out source box and accumulate */ oosp=sp; a=0; for (dy=0; dy < factory; dy++) { for (dx=0; dx < factorx; dx++) { a += (*sp); /* next x */ sp++; } /* end src dx loop */ /* next y */ sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx)); } /* end src dy loop */ /* next box-x */ sp = (Uint8 *)((Uint8*)oosp + factorx); /* Store result in destination */ *dp = a/n_average; /* * Advance destination pointer */ dp++; } /* end dst x loop */ /* next box-y */ sp = (Uint8 *)((Uint8*)osp + src->pitch*factory); /* * Advance destination pointers */ dp = (Uint8 *)((Uint8 *)dp + dgap); } /* end dst y loop */ return (0); } int _greatestCommonDivisor(int n1, int n2) { //Using Euclid's algorithm int r = 1; while (n2 > 0) { r = n2; n2 = n1 % n2; n1 = r; } return r; } /*! \brief Internal 32 bit Zoomer with optional anti-aliasing by bilinear interpolation. Zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface. Assumes src and dst surfaces are of 32 bit depth. Assumes dst surface was allocated with the correct dimensions. \param src The surface to zoom (input). \param dst The zoomed surface (output). \param flipx Flag indicating if the image should be horizontally flipped. \param flipy Flag indicating if the image should be vertically flipped. \param smooth Antialiasing flag; set to SMOOTHING_ON to enable. \return 0 for success or -1 for error. */ int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth) { int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy; /* * Variables for applying scale factors * dx, dy -- deltas to apply each fx, fy pixels * mx, my -- Multiplier for source pixels (see below) * fx, fy -- Multiplier for target pixels * nxd, nyd -- next pixel to apply delta on */ int dx = 0, dy = 0, mx = 1, my = 1, fx = 0, fy = 0, nxd = 0, nyd = 0; tColorRGBA *c00, *c01, *c10, *c11; tColorRGBA *sp, *csp, *dp; int spixelgap, spixelw, spixelh, dgap, t1, t2; /* * Allocate memory for row/column increments */ if ((sax = (int *) malloc((dst->w + 1) * sizeof(int))) == NULL) { return (-1); } if ((say = (int *) malloc((dst->h + 1) * sizeof(int))) == NULL) { free(sax); return (-1); } /* * Precalculate row increments */ spixelw = (src->w - 1); spixelh = (src->h - 1); if (smooth) { sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1)); sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1)); if (dst->w > src->w) { mx = _greatestCommonDivisor(dst->w - 1, spixelw); fx = (dst->w - 1) / mx; mx = spixelw / mx; } if (dst->h > src->h) { my = _greatestCommonDivisor(dst->h - 1, spixelh); fy = (dst->h - 1) / my; my = spixelh / my; } } else { sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w)); sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h)); if (dst->w > src->w) { mx = _greatestCommonDivisor(dst->w, src->w); fx = dst->w / mx; mx = src->w / mx; } if (dst->h > src->h) { my = _greatestCommonDivisor(dst->h, src->h); fy = dst->h / my; my = src->h / my; } } if (dst->w > src->w) { nxd = fx; dx = 65536 * mx - sx * fx; } if (dst->h > src->h) { nyd = fy; dy = 65536 * my - sy * fy; } /* Maximum scaled source size */ ssx = (src->w << 16) - 1; ssy = (src->h << 16) - 1; /* Precalculate horizontal row increments */ csx = 0; csax = sax; for (x = 0; x <= dst->w; x++) { *csax = csx; csax++; if (x + 1 == nxd) { csx += dx; nxd += fx; } csx += sx; /* Guard from overflows */ if (csx > ssx) { csx = ssx; } } /* Precalculate vertical row increments */ csy = 0; csay = say; for (y = 0; y <= dst->h; y++) { *csay = csy; csay++; if (y + 1 == nyd) { csy += dy; nyd += fy; } csy += sy; /* Guard from overflows */ if (csy > ssy) { csy = ssy; } } sp = (tColorRGBA *) src->pixels; dp = (tColorRGBA *) dst->pixels; dgap = dst->pitch - dst->w * 4; spixelgap = src->pitch/4; if (flipx) sp += spixelw; if (flipy) sp += (spixelgap * spixelh); /* * Switch between interpolating and non-interpolating code */ if (smooth) { /* * Interpolating Zoom */ csay = say; for (y = 0; y < dst->h; y++) { csp = sp; csax = sax; for (x = 0; x < dst->w; x++) { /* * Setup color source pointers */ ex = (*csax & 0xffff); ey = (*csay & 0xffff); cx = (*csax >> 16); cy = (*csay >> 16); sstepx = cx < spixelw; sstepy = cy < spixelh; c00 = sp; c01 = sp; c10 = sp; if (sstepy) { if (flipy) { c10 -= spixelgap; } else { c10 += spixelgap; } } c11 = c10; if (sstepx) { if (flipx) { c01--; c11--; } else { c01++; c11++; } } /* * Draw and interpolate colors */ t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; dp->r = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; dp->g = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; dp->b = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; dp->a = (((t2 - t1) * ey) >> 16) + t1; /* * Advance source pointer x */ salast = csax; csax++; sstep = (*csax >> 16) - (*salast >> 16); if (flipx) { sp -= sstep; } else { sp += sstep; } /* * Advance destination pointer x */ dp++; } /* * Advance source pointer y */ salast = csay; csay++; sstep = (*csay >> 16) - (*salast >> 16); sstep *= spixelgap; if (flipy) { sp = csp - sstep; } else { sp = csp + sstep; } /* * Advance destination pointer y */ dp = (tColorRGBA *) ((Uint8 *) dp + dgap); } } else { /* * Non-Interpolating Zoom */ csay = say; for (y = 0; y < dst->h; y++) { csp = sp; csax = sax; for (x = 0; x < dst->w; x++) { /* * Draw */ *dp = *sp; /* * Advance source pointer x */ salast = csax; csax++; sstep = (*csax >> 16) - (*salast >> 16); if (flipx) sstep = -sstep; sp += sstep; /* * Advance destination pointer x */ dp++; } /* * Advance source pointer y */ salast = csay; csay++; sstep = (*csay >> 16) - (*salast >> 16); sstep *= spixelgap; if (flipy) sstep = -sstep; sp = csp + sstep; /* * Advance destination pointer y */ dp = (tColorRGBA *) ((Uint8 *) dp + dgap); } } /* * Remove temp arrays */ free(sax); free(say); return (0); } /*! \brief Internal 8 bit Zoomer without smoothing. Zooms 8bit palette/Y 'src' surface to 'dst' surface. Assumes src and dst surfaces are of 8 bit depth. Assumes dst surface was allocated with the correct dimensions. \param src The surface to zoom (input). \param dst The zoomed surface (output). \param flipx Flag indicating if the image should be horizontally flipped. \param flipy Flag indicating if the image should be vertically flipped. \return 0 for success or -1 for error. */ int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy) { int x, y; Uint32 *sax, *say, *csax, *csay; int csx, csy; Uint8 *sp, *dp, *csp; int dgap; /* * Allocate memory for row increments */ if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) { return (-1); } if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) { free(sax); return (-1); } /* * Pointer setup */ sp = csp = (Uint8 *) src->pixels; dp = (Uint8 *) dst->pixels; dgap = dst->pitch - dst->w; if (flipx) csp += (src->w-1); if (flipy) csp = ( (Uint8*)csp + src->pitch*(src->h-1) ); /* * Precalculate row increments */ csx = 0; csax = sax; for (x = 0; x < dst->w; x++) { csx += src->w; *csax = 0; while (csx >= dst->w) { csx -= dst->w; (*csax)++; } (*csax) = (*csax) * (flipx ? -1 : 1); csax++; } csy = 0; csay = say; for (y = 0; y < dst->h; y++) { csy += src->h; *csay = 0; while (csy >= dst->h) { csy -= dst->h; (*csay)++; } (*csay) = (*csay) * (flipy ? -1 : 1); csay++; } /* * Draw */ csay = say; for (y = 0; y < dst->h; y++) { csax = sax; sp = csp; for (x = 0; x < dst->w; x++) { /* * Draw */ *dp = *sp; /* * Advance source pointers */ sp += (*csax); csax++; /* * Advance destination pointer */ dp++; } /* * Advance source pointer (for row) */ csp += ((*csay) * src->pitch); csay++; /* * Advance destination pointers */ dp += dgap; } /* * Remove temp arrays */ free(sax); free(say); return (0); } /*! \brief Internal 32 bit rotozoomer with optional anti-aliasing. Rotates and zooms 32 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control parameters by scanning the destination surface and applying optionally anti-aliasing by bilinear interpolation. Assumes src and dst surfaces are of 32 bit depth. Assumes dst surface was allocated with the correct dimensions. \param src Source surface. \param dst Destination surface. \param cx Horizontal center coordinate. \param cy Vertical center coordinate. \param isin Integer version of sine of angle. \param icos Integer version of cosine of angle. \param flipx Flag indicating horizontal mirroring should be applied. \param flipy Flag indicating vertical mirroring should be applied. \param smooth Flag indicating anti-aliasing should be used. */ void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth) { int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh; tColorRGBA c00, c01, c10, c11, cswap; tColorRGBA *pc, *sp; int gap; /* * Variable setup */ xd = ((src->w - dst->w) << 15); yd = ((src->h - dst->h) << 15); ax = (cx << 16) - (icos * cx); ay = (cy << 16) - (isin * cx); sw = src->w - 1; sh = src->h - 1; pc = (tColorRGBA*) dst->pixels; gap = dst->pitch - dst->w * 4; /* * Switch between interpolating and non-interpolating code */ if (smooth) { for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (sdx >> 16); dy = (sdy >> 16); if (flipx) dx = sw - dx; if (flipy) dy = sh - dy; if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) { sp = (tColorRGBA *)src->pixels;; sp += ((src->pitch/4) * dy); sp += dx; c00 = *sp; sp += 1; c01 = *sp; sp += (src->pitch/4); c11 = *sp; sp -= 1; c10 = *sp; if (flipx) { cswap = c00; c00=c01; c01=cswap; cswap = c10; c10=c11; c11=cswap; } if (flipy) { cswap = c00; c00=c10; c10=cswap; cswap = c01; c01=c11; c11=cswap; } /* * Interpolate colors */ ex = (sdx & 0xffff); ey = (sdy & 0xffff); t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; pc->r = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; pc->g = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; pc->b = (((t2 - t1) * ey) >> 16) + t1; t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; pc->a = (((t2 - t1) * ey) >> 16) + t1; } sdx += icos; sdy += isin; pc++; } pc = (tColorRGBA *) ((Uint8 *) pc + gap); } } else { for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (short) (sdx >> 16); dy = (short) (sdy >> 16); if (flipx) dx = (src->w-1)-dx; if (flipy) dy = (src->h-1)-dy; if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy); sp += dx; *pc = *sp; } sdx += icos; sdy += isin; pc++; } pc = (tColorRGBA *) ((Uint8 *) pc + gap); } } } /*! \brief Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing. Rotates and zooms 8 bit RGBA/ABGR 'src' surface to 'dst' surface based on the control parameters by scanning the destination surface. Assumes src and dst surfaces are of 8 bit depth. Assumes dst surface was allocated with the correct dimensions. \param src Source surface. \param dst Destination surface. \param cx Horizontal center coordinate. \param cy Vertical center coordinate. \param isin Integer version of sine of angle. \param icos Integer version of cosine of angle. \param flipx Flag indicating horizontal mirroring should be applied. \param flipy Flag indicating vertical mirroring should be applied. */ void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy) { int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay; tColorY *pc, *sp; int gap; /* * Variable setup */ xd = ((src->w - dst->w) << 15); yd = ((src->h - dst->h) << 15); ax = (cx << 16) - (icos * cx); ay = (cy << 16) - (isin * cx); pc = (tColorY*) dst->pixels; gap = dst->pitch - dst->w; /* * Clear surface to colorkey */ memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h); /* * Iterate through destination surface */ for (y = 0; y < dst->h; y++) { dy = cy - y; sdx = (ax + (isin * dy)) + xd; sdy = (ay - (icos * dy)) + yd; for (x = 0; x < dst->w; x++) { dx = (short) (sdx >> 16); dy = (short) (sdy >> 16); if (flipx) dx = (src->w-1)-dx; if (flipy) dy = (src->h-1)-dy; if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) { sp = (tColorY *) (src->pixels); sp += (src->pitch * dy + dx); *pc = *sp; } sdx += icos; sdy += isin; pc++; } pc += gap; } } /*! \brief Rotates a 8/16/24/32 bit surface in increments of 90 degrees. Specialized 90 degree rotator which rotates a 'src' surface in 90 degree increments clockwise returning a new surface. Faster than rotozoomer since no scanning or interpolation takes place. Input surface must be 8/16/24/32 bit. (code contributed by J. Schiller, improved by C. Allport and A. Schiffler) \param src Source surface to rotate. \param numClockwiseTurns Number of clockwise 90 degree turns to apply to the source. \returns The new, rotated surface; or NULL for surfaces with incorrect input format. */ SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns) { int row, col, newWidth, newHeight; int bpp; SDL_Surface* dst; Uint8* srcBuf; Uint8* dstBuf; /* Has to be a valid surface pointer and be a 8/16/24/32-bit surface */ if (!src || !src->format || !(src->format->BitsPerPixel == 8) || (src->format->BitsPerPixel == 16) || (src->format->BitsPerPixel == 24) || (src->format->BitsPerPixel == 32)) { return NULL; } /* normalize numClockwiseTurns */ while(numClockwiseTurns < 0) { numClockwiseTurns += 4; } numClockwiseTurns = (numClockwiseTurns % 4); /* if it's even, our new width will be the same as the source surface */ newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w); newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h); dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); if(!dst) { return NULL; } if (SDL_MUSTLOCK(src)) { SDL_LockSurface(src); } if (SDL_MUSTLOCK(dst)) { SDL_LockSurface(dst); } /* Calculate byte-per-pixel */ bpp = src->format->BitsPerPixel / 8; switch(numClockwiseTurns) { case 0: /* Make a copy of the surface */ { /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface since it does not preserve alpha. */ if (src->pitch == dst->pitch) { /* If the pitch is the same for both surfaces, the memory can be copied all at once. */ memcpy(dst->pixels, src->pixels, (src->h * src->pitch)); } else { /* If the pitch differs, copy each row separately */ srcBuf = (Uint8*)(src->pixels); dstBuf = (Uint8*)(dst->pixels); for (row = 0; row < src->h; row++) { memcpy(dstBuf, srcBuf, dst->w * bpp); srcBuf += src->pitch; dstBuf += dst->pitch; } /* end for(col) */ } /* end for(row) */ } break; /* rotate clockwise */ case 1: /* rotated 90 degrees clockwise */ { for (row = 0; row < src->h; ++row) { srcBuf = (Uint8*)(src->pixels) + (row * src->pitch); dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp; for (col = 0; col < src->w; ++col) { memcpy (dstBuf, srcBuf, bpp); srcBuf += bpp; dstBuf += dst->pitch; } } } break; case 2: /* rotated 180 degrees clockwise */ { for (row = 0; row < src->h; ++row) { srcBuf = (Uint8*)(src->pixels) + (row * src->pitch); dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp; for (col = 0; col < src->w; ++col) { memcpy (dstBuf, srcBuf, bpp); srcBuf += bpp; dstBuf -= bpp; } } } break; case 3: /* rotated 270 degrees clockwise */ { for (row = 0; row < src->h; ++row) { srcBuf = (Uint8*)(src->pixels) + (row * src->pitch); dstBuf = (Uint8*)(dst->pixels) + row + ((dst->h - 1) * dst->pitch); for (col = 0; col < src->w; ++col) { *dstBuf = *srcBuf; srcBuf += bpp; dstBuf -= dst->pitch; } } } break; } /* end switch */ if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } if (SDL_MUSTLOCK(dst)) { SDL_UnlockSurface(dst); } return dst; } /*! \brief Internal target surface sizing function for rotozooms with trig result return. \param width The source surface width. \param height The source surface height. \param angle The angle to rotate in degrees. \param zoomx The horizontal scaling factor. \param zoomy The vertical scaling factor. \param dstwidth The calculated width of the destination surface. \param dstheight The calculated height of the destination surface. \param canglezoom The sine of the angle adjusted by the zoom factor. \param sanglezoom The cosine of the angle adjusted by the zoom factor. */ void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight, double *canglezoom, double *sanglezoom) { double x, y, cx, cy, sx, sy; double radangle; int dstwidthhalf, dstheighthalf; /* * Determine destination width and height by rotating a centered source box */ radangle = angle * (M_PI / 180.0); *sanglezoom = sin(radangle); *canglezoom = cos(radangle); *sanglezoom *= zoomx; *canglezoom *= zoomx; x = (double)(width / 2); y = (double)(height / 2); cx = *canglezoom * x; cy = *canglezoom * y; sx = *sanglezoom * x; sy = *sanglezoom * y; dstwidthhalf = MAX((int) ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1); dstheighthalf = MAX((int) ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1); *dstwidth = 2 * dstwidthhalf; *dstheight = 2 * dstheighthalf; } /*! \brief Returns the size of the resulting target surface for a rotozoomSurfaceXY() call. \param width The source surface width. \param height The source surface height. \param angle The angle to rotate in degrees. \param zoomx The horizontal scaling factor. \param zoomy The vertical scaling factor. \param dstwidth The calculated width of the rotozoomed destination surface. \param dstheight The calculated height of the rotozoomed destination surface. */ void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight) { double dummy_sanglezoom, dummy_canglezoom; _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); } /*! \brief Returns the size of the resulting target surface for a rotozoomSurface() call. \param width The source surface width. \param height The source surface height. \param angle The angle to rotate in degrees. \param zoom The scaling factor. \param dstwidth The calculated width of the rotozoomed destination surface. \param dstheight The calculated height of the rotozoomed destination surface. */ void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight) { double dummy_sanglezoom, dummy_canglezoom; _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom); } /*! \brief Rotates and zooms a surface and optional anti-aliasing. Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'angle' is the rotation in degrees and 'zoom' a scaling factor. If 'smooth' is set then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. \param src The surface to rotozoom. \param angle The angle to rotate in degrees. \param zoom The scaling factor. \param smooth Antialiasing flag; set to SMOOTHING_ON to enable. \return The new rotozoomed surface. */ SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth) { return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth); } /*! \brief Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-aliasing. Rotates and zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'angle' is the rotation in degrees, 'zoomx and 'zoomy' scaling factors. If 'smooth' is set then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. \param src The surface to rotozoom. \param angle The angle to rotate in degrees. \param zoomx The horizontal scaling factor. \param zoomy The vertical scaling factor. \param smooth Antialiasing flag; set to SMOOTHING_ON to enable. \return The new rotozoomed surface. */ SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth) { SDL_Surface *rz_src; SDL_Surface *rz_dst; double zoominv; double sanglezoom, canglezoom, sanglezoominv, canglezoominv; int dstwidthhalf, dstwidth, dstheighthalf, dstheight; int is32bit; int i, src_converted; int flipx,flipy; /* * Sanity check */ if (src == NULL) { return (NULL); } /* * Determine if source surface is 32bit or 8bit */ is32bit = (src->format->BitsPerPixel == 32); if ((is32bit) || (src->format->BitsPerPixel == 8)) { /* * Use source surface 'as is' */ rz_src = src; src_converted = 0; } else { /* * New source surface is 32bit with a defined RGBA ordering */ rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 #else 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff #endif ); SDL_BlitSurface(src, NULL, rz_src, NULL); src_converted = 1; is32bit = 1; } /* * Sanity check zoom factor */ flipx = (zoomx<0.0); if (flipx) zoomx=-zoomx; flipy = (zoomy<0.0); if (flipy) zoomy=-zoomy; if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT; if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT; zoominv = 65536.0 / (zoomx * zoomx); /* * Check if we have a rotozoom or just a zoom */ if (fabs(angle) > VALUE_LIMIT) { /* * Angle!=0: full rotozoom */ /* * ----------------------- */ /* Determine target size */ _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom); /* * Calculate target factors from sin/cos and zoom */ sanglezoominv = sanglezoom; canglezoominv = canglezoom; sanglezoominv *= zoominv; canglezoominv *= zoominv; /* Calculate half size */ dstwidthhalf = dstwidth / 2; dstheighthalf = dstheight / 2; /* * Alloc space to completely contain the rotated surface */ rz_dst = NULL; if (is32bit) { /* * Target surface is 32bit with source RGBA/ABGR ordering */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); } else { /* * Target surface is 8bit */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); } /* Check target */ if (rz_dst == NULL) return NULL; /* Adjust for guard rows */ rz_dst->h = dstheight; /* * Lock source surface */ if (SDL_MUSTLOCK(rz_src)) { SDL_LockSurface(rz_src); } /* * Check which kind of surface we have */ if (is32bit) { /* * Call the 32bit transformation routine to do the rotation (using alpha) */ _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf, (int) (sanglezoominv), (int) (canglezoominv), flipx, flipy, smooth); } else { /* * Copy palette and colorkey info */ for (i = 0; i < rz_src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; } rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; /* * Call the 8bit transformation routine to do the rotation */ transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf, (int) (sanglezoominv), (int) (canglezoominv), flipx, flipy); } /* * Unlock source surface */ if (SDL_MUSTLOCK(rz_src)) { SDL_UnlockSurface(rz_src); } } else { /* * Angle=0: Just a zoom */ /* * -------------------- */ /* * Calculate target size */ zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); /* * Alloc space to completely contain the zoomed surface */ rz_dst = NULL; if (is32bit) { /* * Target surface is 32bit with source RGBA/ABGR ordering */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); } else { /* * Target surface is 8bit */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); } /* Check target */ if (rz_dst == NULL) return NULL; /* Adjust for guard rows */ rz_dst->h = dstheight; /* * Lock source surface */ if (SDL_MUSTLOCK(rz_src)) { SDL_LockSurface(rz_src); } /* * Check which kind of surface we have */ if (is32bit) { /* * Call the 32bit transformation routine to do the zooming (using alpha) */ _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); } else { /* * Copy palette and colorkey info */ for (i = 0; i < rz_src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; } rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; /* * Call the 8bit transformation routine to do the zooming */ _zoomSurfaceY(rz_src, rz_dst, flipx, flipy); } /* * Unlock source surface */ if (SDL_MUSTLOCK(rz_src)) { SDL_UnlockSurface(rz_src); } } /* * Cleanup temp surface */ if (src_converted) { SDL_FreeSurface(rz_src); } /* * Return destination surface */ return (rz_dst); } /*! \brief Calculates the size of the target surface for a zoomSurface() call. The minimum size of the target surface is 1. The input factors can be positive or negative. \param width The width of the source surface to zoom. \param height The height of the source surface to zoom. \param zoomx The horizontal zoom factor. \param zoomy The vertical zoom factor. \param dstwidth Pointer to an integer to store the calculated width of the zoomed target surface. \param dstheight Pointer to an integer to store the calculated height of the zoomed target surface. */ void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight) { /* * Make zoom factors positive */ int flipx, flipy; flipx = (zoomx<0.0); if (flipx) zoomx = -zoomx; flipy = (zoomy<0.0); if (flipy) zoomy = -zoomy; /* * Sanity check zoom factors */ if (zoomx < VALUE_LIMIT) { zoomx = VALUE_LIMIT; } if (zoomy < VALUE_LIMIT) { zoomy = VALUE_LIMIT; } /* * Calculate target size */ *dstwidth = (int) floor(((double) width * zoomx) + 0.5); *dstheight = (int) floor(((double) height * zoomy) + 0.5); if (*dstwidth < 1) { *dstwidth = 1; } if (*dstheight < 1) { *dstheight = 1; } } /*! \brief Zoom a surface by independent horizontal and vertical factors with optional smoothing. Zooms a 32bit or 8bit 'src' surface to newly created 'dst' surface. 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is on then the destination 32bit surface is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. If zoom factors are negative, the image is flipped on the axes. \param src The surface to zoom. \param zoomx The horizontal zoom factor. \param zoomy The vertical zoom factor. \param smooth Antialiasing flag; set to SMOOTHING_ON to enable. \return The new, zoomed surface. */ SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth) { SDL_Surface *rz_src; SDL_Surface *rz_dst; int dstwidth, dstheight; int is32bit; int i, src_converted; int flipx, flipy; /* * Sanity check */ if (src == NULL) return (NULL); /* * Determine if source surface is 32bit or 8bit */ is32bit = (src->format->BitsPerPixel == 32); if ((is32bit) || (src->format->BitsPerPixel == 8)) { /* * Use source surface 'as is' */ rz_src = src; src_converted = 0; } else { /* * New source surface is 32bit with a defined RGBA ordering */ rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 #else 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff #endif ); if (rz_src == NULL) { return NULL; } SDL_BlitSurface(src, NULL, rz_src, NULL); src_converted = 1; is32bit = 1; } flipx = (zoomx<0.0); if (flipx) zoomx = -zoomx; flipy = (zoomy<0.0); if (flipy) zoomy = -zoomy; /* Get size if target */ zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight); /* * Alloc space to completely contain the zoomed surface */ rz_dst = NULL; if (is32bit) { /* * Target surface is 32bit with source RGBA/ABGR ordering */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); } else { /* * Target surface is 8bit */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); } /* Check target */ if (rz_dst == NULL) { /* * Cleanup temp surface */ if (src_converted) { SDL_FreeSurface(rz_src); } return NULL; } /* Adjust for guard rows */ rz_dst->h = dstheight; /* * Lock source surface */ if (SDL_MUSTLOCK(rz_src)) { SDL_LockSurface(rz_src); } /* * Check which kind of surface we have */ if (is32bit) { /* * Call the 32bit transformation routine to do the zooming (using alpha) */ _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth); } else { /* * Copy palette and colorkey info */ for (i = 0; i < rz_src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; } rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; /* * Call the 8bit transformation routine to do the zooming */ _zoomSurfaceY(rz_src, rz_dst, flipx, flipy); } /* * Unlock source surface */ if (SDL_MUSTLOCK(rz_src)) { SDL_UnlockSurface(rz_src); } /* * Cleanup temp surface */ if (src_converted) { SDL_FreeSurface(rz_src); } /* * Return destination surface */ return (rz_dst); } /*! \brief Shrink a surface by an integer ratio using averaging. Shrinks a 32bit or 8bit 'src' surface to a newly created 'dst' surface. 'factorx' and 'factory' are the shrinking ratios (i.e. 2=1/2 the size, 3=1/3 the size, etc.) The destination surface is antialiased by averaging the source box RGBA or Y information. If the surface is not 8bit or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly. The input surface is not modified. The output surface is newly allocated. \param src The surface to shrink. \param factorx The horizontal shrinking ratio. \param factory The vertical shrinking ratio. \return The new, shrunken surface. */ /*@null@*/ SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory) { int result; SDL_Surface *rz_src; SDL_Surface *rz_dst = NULL; int dstwidth, dstheight; int is32bit; int i, src_converted = 0; int haveError = 0; /* * Sanity check */ if (src == NULL) { return (NULL); } /* * Determine if source surface is 32bit or 8bit */ is32bit = (src->format->BitsPerPixel == 32); if ((is32bit) || (src->format->BitsPerPixel == 8)) { /* * Use source surface 'as is' */ rz_src = src; src_converted = 0; } else { /* * New source surface is 32bit with a defined RGBA ordering */ rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 #else 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff #endif ); if (rz_src==NULL) { haveError = 1; goto exitShrinkSurface; } SDL_BlitSurface(src, NULL, rz_src, NULL); src_converted = 1; is32bit = 1; } /* * Lock the surface */ if (SDL_MUSTLOCK(rz_src)) { if (SDL_LockSurface(rz_src) < 0) { haveError = 1; goto exitShrinkSurface; } } /* Get size for target */ dstwidth=rz_src->w/factorx; while (dstwidth*factorx>rz_src->w) { dstwidth--; } dstheight=rz_src->h/factory; while (dstheight*factory>rz_src->h) { dstheight--; } /* * Alloc space to completely contain the shrunken surface * (with added guard rows) */ if (is32bit==1) { /* * Target surface is 32bit with source RGBA/ABGR ordering */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask); } else { /* * Target surface is 8bit */ rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0); } /* Check target */ if (rz_dst == NULL) { haveError = 1; goto exitShrinkSurface; } /* Adjust for guard rows */ rz_dst->h = dstheight; /* * Check which kind of surface we have */ if (is32bit==1) { /* * Call the 32bit transformation routine to do the shrinking (using alpha) */ result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory); if ((result!=0) || (rz_dst==NULL)) { haveError = 1; goto exitShrinkSurface; } } else { /* * Copy palette and colorkey info */ for (i = 0; i < rz_src->format->palette->ncolors; i++) { rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i]; } rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors; /* * Call the 8bit transformation routine to do the shrinking */ result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory); if (result!=0) { haveError = 1; goto exitShrinkSurface; } } exitShrinkSurface: if (rz_src!=NULL) { /* * Unlock source surface */ if (SDL_MUSTLOCK(rz_src)) { SDL_UnlockSurface(rz_src); } /* * Cleanup temp surface */ if (src_converted==1) { SDL_FreeSurface(rz_src); } } /* Check error state; maybe need to cleanup destination */ if (haveError==1) { if (rz_dst!=NULL) { SDL_FreeSurface(rz_dst); } rz_dst=NULL; } /* * Return destination surface */ return (rz_dst); } instead-3.5.2+dfsg/src/SDL_rotozoom.h000066400000000000000000000056701467622671600174520ustar00rootroot00000000000000/* SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces Copyright (C) 2001-2012 Andreas Schiffler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Andreas Schiffler -- aschiffler at ferzkopp dot net */ #ifndef _SDL2_rotozoom_h #define _SDL2_rotozoom_h #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif #include "SDL.h" /* ---- Defines */ /*! \brief Disable anti-aliasing (no smoothing). */ #define SMOOTHING_OFF 0 /*! \brief Enable anti-aliasing (smoothing). */ #define SMOOTHING_ON 1 /* ---- Function Prototypes */ #ifdef _MSC_VER # if defined(DLL_EXPORT) && !defined(LIBSDL2_GFX_DLL_IMPORT) # define SDL2_ROTOZOOM_SCOPE __declspec(dllexport) # else # ifdef LIBSDL2_GFX_DLL_IMPORT # define SDL2_ROTOZOOM_SCOPE __declspec(dllimport) # endif # endif #endif #ifndef SDL2_ROTOZOOM_SCOPE # define SDL2_ROTOZOOM_SCOPE extern #endif /* Rotozoom functions */ SDL2_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth); SDL2_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurfaceXY (SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth); SDL2_ROTOZOOM_SCOPE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight); SDL2_ROTOZOOM_SCOPE void rotozoomSurfaceSizeXY (int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight); /* Zooming functions */ SDL2_ROTOZOOM_SCOPE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth); SDL2_ROTOZOOM_SCOPE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight); /* Shrinking functions */ SDL2_ROTOZOOM_SCOPE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory); /* Specialized rotation functions */ SDL2_ROTOZOOM_SCOPE SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns); /* Ends C function definitions when using C++ */ #ifdef __cplusplus } #endif #endif /* _SDL2_rotozoom_h */ instead-3.5.2+dfsg/src/android.h000066400000000000000000000011651467622671600164730ustar00rootroot00000000000000#include #ifndef SDL_JAVA_PACKAGE_PATH #error You have to define SDL_JAVA_PACKAGE_PATH to your package path with dots replaced with underscores, for example "com_example_SanAngeles" #endif #define JAVA_EXPORT_NAME2(name,package) Java_##package##_##name #define JAVA_EXPORT_NAME1(name,package) JAVA_EXPORT_NAME2(name,package) #define JAVA_EXPORT_NAME(name) JAVA_EXPORT_NAME1(name,SDL_JAVA_PACKAGE_PATH) extern void JNICALL JAVA_EXPORT_NAME(SDLActivity_nativeSave)(JNIEnv *env, jobject obj) { cfg_save(); } extern void JNICALL JAVA_EXPORT_NAME(SDLActivity_nativeStop)(JNIEnv *env, jobject obj) { game_done(0); exit(0); } instead-3.5.2+dfsg/src/config.c000066400000000000000000000106461467622671600163170ustar00rootroot00000000000000/* * Copyright 2009-2022 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" #if defined(IOS) || defined(SAILFISHOS) || defined(ANDROID) || defined(WINRT) int opt_fsize = 5; #else int opt_fsize = 0; #endif #if defined(IOS) || defined(ANDROID) || defined(SAILFISHOS) || defined(WINRT) int opt_fs = 1; int opt_owntheme = 1; int opt_hl = 0; #else int opt_fs = 0; int opt_owntheme = 1; int opt_hl = 1; #endif int opt_fading = 1; int opt_hz = 44100; int opt_vol = 127; int opt_motion = 1; int opt_click = 1; int opt_music = 1; int opt_autosave = 1; int opt_filter = 1; int opt_kbd = KBD_SMART; int opt_justify = 0; int opt_vsync = -1; int opt_debug = -1; int opt_resizable = -1; int opt_hires = 1; char *opt_game = NULL; char *opt_theme = NULL; char *opt_lang = NULL; int opt_mode[2] = {-1, -1}; int parse_mode(const char *v, void *data) { int w, h; char *eptr; int *p = ((int *)data); w = strtol(v, &eptr, 10); if (!w || (eptr == v) || (*eptr != 'x')) return -1; eptr ++; h = strtol(eptr, &eptr, 10); if (!h || (*eptr)) return -1; p[0] = w; p[1] = h; return 0; } static struct parser cfg_parser[] = { { "hz", parse_int, &opt_hz, 0 }, { "fs", parse_int, &opt_fs, 0 }, { "vol", parse_int, &opt_vol, 0 }, { "hl", parse_int, &opt_hl, 0 }, { "game", parse_string, &opt_game, 0 }, { "theme", parse_string, &opt_theme, 0 }, { "autosave", parse_int, &opt_autosave, 0 }, { "motion", parse_int, &opt_motion, 0 }, { "click", parse_int, &opt_click, 0 }, { "music", parse_int, &opt_music, 0 }, { "fscale", parse_int, &opt_fsize, 0 }, { "filter", parse_int, &opt_filter, 0 }, { "owntheme", parse_int, &opt_owntheme, 0 }, { "lang", parse_string, &opt_lang, 0 }, { "kbd", parse_int, &opt_kbd, 0 }, { "mode", parse_mode, opt_mode, 0 }, { "justify", parse_int, &opt_justify, 0 }, { "fading", parse_int, &opt_fading, 0 }, { "vsync", parse_int, &opt_vsync, 0 }, { "debug", parse_int, &opt_debug, 0 }, { "resizable", parse_int, &opt_resizable, 0 }, { "hires", parse_int, &opt_hires, 0 }, { NULL, NULL, NULL, 0 }, }; void cfg_init(void) { #if defined(IOS) ios_cfg_init(); #endif } static int cfg_parse(const char *path) { return parse_ini(path, cfg_parser); } int cfg_load(void) { char *p = game_cfg_path(); if (!p) return -1; if (access(p, R_OK)) return 0; return cfg_parse(p); } extern int noowntheme_sw; int cfg_save(void) { int save_owntheme = (opt_owntheme == 2)?0:((noowntheme_sw)?1:opt_owntheme); int save_autosave = (opt_autosave == 2)?1:opt_autosave; FILE *fp; char *p = game_cfg_path(); if (!p) return -1; fp = fopen(p, "w"); if (!fp) return -1; fprintf(fp, "fs = %d\nhl = %d\nhz = %d\nvol = %d\nautosave = %d\n\ game = %s\nfscale = %d\nmotion = %d\n\ click = %d\nmusic = %d\ntheme = %s\n\ filter = %d\nowntheme = %d\nlang = %s\nkbd = %d\nmode = %dx%d\njustify = %d\nfading = %d\nhires = %d\n", opt_fs, opt_hl, opt_hz, opt_vol, save_autosave, curgame_dir?curgame_dir:"", opt_fsize, opt_motion, opt_click, opt_music, curtheme_dir[THEME_GLOBAL]?curtheme_dir[THEME_GLOBAL]:DEFAULT_THEME, opt_filter, save_owntheme, opt_lang, opt_kbd, opt_mode[0], opt_mode[1], opt_justify, opt_fading, opt_hires); if (opt_vsync != -1) fprintf(fp, "vsync = %d\n", opt_vsync); if (opt_debug != -1) fprintf(fp, "debug = %d\n", opt_debug); if (opt_resizable != -1) fprintf(fp, "resizable = %d\n", opt_resizable); fclose(fp); data_sync(); return 0; } instead-3.5.2+dfsg/src/config.h000066400000000000000000000041231467622671600163150ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh * * 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. * */ #ifndef __CONFIG_H_INCLUDED #define __CONFIG_H_INCLUDED #define FONT_SZ(v) (SCALABLE_FONT?((v) * (1.0f + ((0.1f * opt_fsize)))):(v)) #define KBD_SMART 0 #define KBD_NORMAL 1 #define KBD_INVERSE 2 #define KBD_MAX 3 #define JUST_THEME 0 #define JUST_NO 1 #define JUST_YES 2 #define JUST_MAX 3 extern char *appdata_sw; extern int chunksize_sw; extern int opt_fading; extern int opt_fsize; extern int opt_fs; extern int opt_owntheme; extern int opt_hl; extern int opt_hz; extern int opt_vol; extern int opt_motion; extern int opt_click; extern int opt_music; extern int opt_autosave; extern int opt_filter; extern int opt_kbd; extern int opt_justify; extern int opt_vsync; extern int opt_debug; extern int opt_resizable; extern int opt_hires; extern int opt_mode[2]; extern char *opt_game; extern char *opt_theme; extern char *opt_lang; extern void cfg_init(void); extern int cfg_load(void); extern int cfg_save(void); extern int parse_mode(const char *v, void *data); #endif instead-3.5.2+dfsg/src/externals.h000066400000000000000000000001571467622671600170600ustar00rootroot00000000000000#include "instead/system.h" #ifdef __EMSCRIPTEN__ #include "emscripten.h" #include "emscripten/html5.h" #endif instead-3.5.2+dfsg/src/game.c000066400000000000000000002321101467622671600157530ustar00rootroot00000000000000/* * Copyright 2009-2022 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" #define MOTION_TIME (timer_counter - click_time >= 200 / HZ) int game_running = 1; char game_cwd[PATH_MAX]; char *curgame_dir = NULL; int game_grab_events = 0; int game_wait_use = 1; int game_own_theme = 0; int game_theme_changed = 0; unsigned int mouse_filter_delay = 400; static int need_restart = 0; static int game_pic_w = 0; static int game_pic_h = 0; static char *last_pict = NULL; static char *last_title = NULL; static char *last_cmd = NULL; void game_cursor(int on); extern void instead_render_callback(void); extern int instead_render_callback_dirty(int reset); void game_flip(void) { instead_render_callback(); gfx_flip(); } static void _game_update(int x, int y, int w, int h) { if (instead_render_callback_dirty(-1) == 1) return; gfx_update(x, y, w, h); } static void game_update(int x, int y, int w, int h) { if (instead_render_callback_dirty(-1) == 1) return; game_cursor(CURSOR_DRAW); gfx_update(x, y, w, h); } void game_res_err_msg(const char *filename, int alert) { static const char preambule[] = "Can't load: "; char *msg; unsigned int s; if (!filename || (!*filename && !alert)) return; if (alert && curgame_dir) { s = sizeof(preambule) + strlen(filename) + 2; msg = malloc(s); if (msg) { snprintf(msg, s, "%s\"%s\"", preambule, filename); instead_err_msg(msg); free(msg); } } fprintf(stderr, "%s%s\n", preambule, filename); } int is_game(const char *path, const char *n) { int rc = 0; char *p; char *pp; if (!n) return 0; if (!strcmp("..", n) || !strcmp(".", n)) return 0; p = getfilepath(path, n); if (!p) return 0; if (idf_magic(p)) { free(p); return 1; } /* new api? */ pp = getfilepath(p, INSTEAD_MAIN3); if (!pp) goto out; if (!access(pp, R_OK)) rc = 3; free(pp); if (rc) /* got one! */ goto out; /* classic one? */ pp = getfilepath(p, INSTEAD_MAIN); if (!pp) goto out; if (!access(pp, R_OK)) rc = 2; free(pp); if (rc) goto out; out: free(p); return rc; } struct game *games = NULL; int games_nr = 0; static void game_release(void); struct game *game_lookup(const char *name) { int i; if (!name || !*name) { if (games_nr == 1 && name) return &games[0]; return NULL; } for (i = 0; iname); return g->name; } else { gfx_set_title(NULL); return NULL; } } static int game_cfg_load(void); int game_select(const char *name) { int rc = -1; struct game *g; // FREE(last_cmd); // game_stop_mus(500); g = game_lookup(name); if ((!name || !*name) && !g) { game_use_theme(); return game_theme_init(); } if (g) { char *oldgame = curgame_dir; curgame_dir = g->dir; instead_done(); instead_set_debug(debug_sw); instead_set_standalone(standalone_sw); if (instead_init(g->path)) { curgame_dir = oldgame; goto err; } themes_lookup_idf(instead_idf(), "themes/", THEME_GAME); if (idf_only(instead_idf(), -1) != 1) themes_lookup(dirpath("themes"), THEME_GAME); game_cfg_load(); game_use_theme(); if (game_theme_init()) { curgame_dir = oldgame; goto err; } instead_set_lang(opt_lang); if ((rc = instead_load(NULL))) { curgame_dir = oldgame; goto err; } } else { game_use_theme(); game_theme_init(); rc = 0; } err: game_reset_name(); return rc; } int game_tag_valid(const char *p) { while (p && *p) { p += strcspn(p, "<"); if (gfx_get_token(p, NULL, NULL, NULL)) return 0; if (*p == '<') p ++; } return 1; } static char *game_tag(const char *path, const char *d_name, const char *tag) { char *l = NULL; char *p; if (idf_magic(path)) { idf_t idf = idf_init(path); if (idf) { l = lookup_lang_tag_idf(idf, INSTEAD_MAIN3, tag, "--", opt_lang); if (!l) l = lookup_lang_tag_idf(idf, INSTEAD_MAIN, tag, "--", opt_lang); idf_done(idf); } if (l) goto ok; goto err; } /* stead3 */ p = getfilepath(path, INSTEAD_MAIN3); if (!p) goto err; l = lookup_lang_tag(p, tag, "--", opt_lang); free(p); if (l) goto ok; /* stead2 */ p = getfilepath(path, INSTEAD_MAIN); if (!p) goto err; l = lookup_lang_tag(p, tag, "--", opt_lang); free(p); if (!l) goto err; ok: if (!game_tag_valid(l)) { /* avoid dangerous tags */ free(l); return NULL; } return l; err: return NULL; } static char *game_name(const char *path, const char *d_name) { char *p = game_tag(path, d_name, "Name"); if (!p) return strdup(d_name); trunc_lines(p, 0); return p; } static char *game_info(const char *path, const char *d_name) { char *p = game_tag(path, d_name, "Info"); if (!p) return p; trunc_lines(p, 4); return p; } static char *game_author(const char *path, const char *d_name) { char *p = game_tag(path, d_name, "Author"); trunc_lines(p, 0); return p; } static char *game_version(const char *path, const char *d_name) { char *p = game_tag(path, d_name, "Version"); trunc_lines(p, 0); return p; } static char *game_direction(const char *path, const char *d_name) { char *p = game_tag(path, d_name, "Direction"); if (!p) return strdup(d_name); trunc_lines(p, 0); return p; } #if 0 static char *game_api(const char *path, const char *d_name) { char *p = game_tag(path, d_name, "API"); trunc_lines(p, 0); if (!p) return strdup("stead2"); return p; } #endif static void game_info_free(struct game *g) { FREE(g->name); FREE(g->info); FREE(g->author); FREE(g->version); FREE(g->direction); /* FREE(g->api); */ } static void game_free(struct game *g) { FREE(g->path); FREE(g->dir); game_info_free(g); } static void game_info_fill(struct game *g) { g->name = game_name(dirpath(g->path), g->dir); g->info = game_info(dirpath(g->path), g->dir); g->author = game_author(dirpath(g->path), g->dir); g->version = game_version(dirpath(g->path), g->dir); g->direction = game_direction(dirpath(g->path), g->dir); /* g->api = game_api(dirpath(g->path), g->dir); */ } static void game_fill(struct game *g, const char *p, const char *dir) { g->path = strdup(p); g->dir = strdup(dir); game_info_fill(g); } int games_rename(void) { int i; char cwd[PATH_MAX]; getdir(cwd, sizeof(cwd)); setdir(game_cwd); for (i = 0; i < games_nr; i++) { game_info_free(&games[i]); game_info_fill(&games[i]); } setdir(cwd); return 0; } static int cmp_game(const void *p1, const void *p2) { const struct game *g1 = (const struct game*)p1; const struct game *g2 = (const struct game*)p2; int g1_s = !!strncmp(g1->path, GAMES_PATH, strlen(GAMES_PATH)); int g2_s = !!strncmp(g2->path, GAMES_PATH, strlen(GAMES_PATH)); if (g1_s != g2_s) return g1_s - g2_s; return strcmp(g1->name, g2->name); } static void games_sort() { if (!games) return; qsort(games, games_nr, sizeof(struct game), cmp_game); } static int games_add(const char *path, const char *dir) { char *p; if (!is_game(path, dir)) return -1; p = getfilepath(path, dir); if (!p) return -1; if (!idf_magic(p)) { strcat(p, "/"); games[games_nr].idf = 0; } else games[games_nr].idf = 1; game_fill(&games[games_nr], p, dir); free(p); games_nr ++; return 0; } int games_replace(const char *path, const char *dir) { int rc; char *p; struct game *g; struct game *new_games; if (!is_game(path, dir)) return -1; g = game_lookup(dir); if (g) { if (g->idf) p = getfilepath(path, dir); else p = getpath(path, dir); if (!p) return -1; game_free(g); game_fill(g, p, dir); free(p); games_sort(); return 0; } new_games = realloc(games, sizeof(struct game) * (1 + games_nr)); if (!new_games) return -1; games = new_games; rc = games_add(path, dir); if (!rc) games_sort(); return rc; } int games_lookup(const char *path) { int n = 0, i = 0; DIR *d; struct dirent *de; struct game *new_games; if (!path) return 0; d = opendir(path); if (!d) return -1; while ((de = readdir(d))) { /*if (de->d_type != DT_DIR) continue;*/ if (game_lookup(de->d_name)) continue; if (!is_game(path, de->d_name)) continue; n ++; } if (!n) goto out; closedir(d); d = opendir(path); if (!d) return -1; new_games = realloc(games, sizeof(struct game) * (n + games_nr)); if (!new_games) { closedir(d); return -1; } games = new_games; while ((de = readdir(d)) && i < n) { /*if (de->d_type != DT_DIR) continue;*/ if (game_lookup(de->d_name)) continue; if (games_add(path, de->d_name)) continue; i ++; } out: closedir(d); games_sort(); return 0; } int games_remove(int gtr) { int rc; struct game *new_games; rc = remove_dir(games[gtr].path); free(games[gtr].name); free(games[gtr].dir); free(games[gtr].path); games_nr --; memmove(&games[gtr], &games[gtr + 1], (games_nr - gtr) * sizeof(struct game)); new_games = realloc(games, games_nr * sizeof(struct game)); if (new_games) /* failure to shrink otherwise, and it's non-fatal */ games = new_games; return rc; } static int motion_mode = 0; static int motion_id = 0; static int motion_y = 0; static int mx, my; static img_t menubg = NULL; static img_t menu = NULL; static int menu_shown = 0; static int browse_dialog = 0; int game_cmd(char *cmd, int click); void game_clear(int x, int y, int w, int h) { game_cursor(CURSOR_CLEAR); if (game_theme.bg) gfx_draw_bg(game_theme.bg, x, y, w, h); else gfx_clear(x, y, w, h); if (menu_shown) { int xx = x - mx; int yy = y - my; gfx_copy_from(menubg, xx, yy, w, h, NULL, x, y); gfx_draw_from(menu, xx, yy, w, h, NULL, x, y); } } void game_clear_all(void) { if (DIRECT_MODE) gfx_img_fill(gfx_screen(NULL), 0, 0, game_theme.w, game_theme.h, gfx_col(game_theme.brdcol.r, game_theme.brdcol.g, game_theme.brdcol.b)); else game_clear(0, 0, game_theme.w, game_theme.h); } void game_clear(int x, int y, int w, int h); struct el { int id; int x; int y; int mx; int my; /* coordinates */ int type; int drawn; /* int clone; */ union { layout_t lay; textbox_t box; img_t img; void *p; } p; }; enum { elt_box, elt_layout, elt_image, }; enum { el_menu = 1, el_title, el_ways, el_inv, el_scene, el_sup, el_sdown, /* el_sslide, */ el_iup, el_idown, /* el_islide, */ el_spic, el_menu_button, el_max, }; static struct el objs[el_max]; static void el_set(int i, int t, int x, int y, void *p) { objs[i].id = i; objs[i].x = x; objs[i].y = y; objs[i].p.p = p; objs[i].type = t; objs[i].drawn = 0; /* objs[i].clone = 0; */ } static void el_zero(int num) { memset(&objs[num], 0, sizeof(struct el)); } static struct el *el(int num) { return &objs[num]; } static textbox_t el_box(int num) { return objs[num].p.box; } static layout_t el_layout(int num) { return objs[num].p.lay; } static img_t el_img(int num) { return objs[num].p.img; } char *game_menu_gen(void); void game_menu(int nr) { mouse_reset(1); cur_menu = nr; game_menu_box(1, game_menu_gen()); } int game_error(void) { game_done(1); if (game_init(NULL)) { fprintf(stderr,"Fatal error! Can't init anything!!!\n"); exit(1); } game_menu(menu_error); return 0; } static void el_draw(int n); int window_sw = 0; int fullscreen_sw = 0; int hires_sw = -1; int game_load(int nr) { char *s; s = game_save_path(0, nr); if (s && !access(s, R_OK)) { char cmd[PATH_MAX]; char sav[PATH_MAX]; strcpy(sav, s); snprintf(cmd, sizeof(cmd) - 1, "load %s", s); game_cmd(cmd, GAME_CMD_FILE); if (nr == -1) unlink(sav); return 0; } return -1; } int game_saves_enabled(void) { int rc; instead_lock(); instead_function("instead.isEnableSave", NULL); rc = instead_bretval(0); instead_clear(); instead_unlock(); return rc; } int game_autosave_enabled(void) { int rc; instead_lock(); instead_function("instead.isEnableAutosave", NULL); rc = instead_bretval(0); instead_clear(); instead_unlock(); return rc; } int game_save(int nr) { char *s = game_save_path(1, nr); char cmd[PATH_MAX]; char *p; int rc; if (!s) return -1; if (nr == -1 || nr == 0) { struct instead_args args_1[] = { { .val = "-1", .type = INSTEAD_NUM }, { .val = NULL, } }; struct instead_args args_0[] = { { .val = "0", .type = INSTEAD_NUM }, { .val = NULL, } }; if (nr == -1) { instead_lock(); instead_function("instead.autosave", args_1); /* enable saving for -1 */ } else if (!game_autosave_enabled()) return 0; /* nothing todo */ else { instead_lock(); instead_function("instead.autosave", args_0); /* enable saving for 0 */ } instead_clear(); instead_unlock(); } snprintf(cmd, sizeof(cmd) - 1, "save %s", s); instead_lock(); p = instead_file_cmd(cmd, &rc); instead_unlock(); if (p) free(p); if (rc || (!p && instead_err())) { game_menu(menu_warning); return -1; } data_sync(); return 0; } static int inv_enabled(void) { return (game_theme.inv_mode != INV_MODE_DISABLED); } int game_apply_theme(void) { int align = game_theme.win_align; layout_t lay = NULL; textbox_t box = NULL; struct game *g = game_lookup(curgame_dir); int rtl = 0; if (g && g->direction) { if (!strcmp(g->direction, "rtl")) rtl = 1; else if (!strcmp(g->direction, "auto")) rtl = -1; } gfx_bg(game_theme.xoff, game_theme.yoff, game_theme.w - 2*game_theme.xoff, game_theme.h - 2*game_theme.yoff, game_theme.bgcol, game_theme.brdcol); if (!DIRECT_MODE) game_clear_all(); gfx_flip(); if (opt_justify == JUST_NO && align == ALIGN_JUSTIFY) align = ALIGN_LEFT; else if (opt_justify == JUST_YES && align == ALIGN_LEFT) align = ALIGN_JUSTIFY; if (!el_box(el_scene)) { lay = txt_layout(game_theme.font, align, game_theme.win_w, game_theme.win_h); if (!lay) return -1; box = txt_box(game_theme.win_w, game_theme.win_h); if (!box) return -1; txt_layout_color(lay, game_theme.fgcol); txt_layout_link_color(lay, game_theme.lcol); /* txt_layout_link_style(lay, 4); */ txt_layout_active_color(lay, game_theme.acol); txt_layout_font_height(lay, game_theme.font_height); txt_layout_rtl(lay, rtl); txt_box_set(box, lay); el_set(el_scene, elt_box, game_theme.win_x, 0, box); } if (inv_enabled()) { if (!el_box(el_inv)) { lay = txt_layout(game_theme.inv_font, INV_ALIGN(game_theme.inv_mode), game_theme.inv_w, game_theme.inv_h); if (!lay) return -1; txt_layout_color(lay, game_theme.icol); txt_layout_link_color(lay, game_theme.ilcol); txt_layout_active_color(lay, game_theme.iacol); txt_layout_font_height(lay, game_theme.inv_font_height); txt_layout_rtl(lay, rtl); box = txt_box(game_theme.inv_w, game_theme.inv_h); if (!box) return -1; txt_box_set(box, lay); el_set(el_inv, elt_box, game_theme.inv_x, game_theme.inv_y, box); } } else el_set(el_inv, elt_box, game_theme.inv_x, game_theme.inv_y, NULL); if (!el_layout(el_title)) { lay = txt_layout(game_theme.font, ALIGN_CENTER, game_theme.win_w, 0); if (!lay) return -1; txt_layout_color(lay, game_theme.fgcol); txt_layout_link_color(lay, game_theme.lcol); txt_layout_active_color(lay, game_theme.acol); txt_layout_font_height(lay, game_theme.font_height); txt_layout_rtl(lay, rtl); el_set(el_title, elt_layout, game_theme.win_x, game_theme.win_y, lay); } if (!el_layout(el_ways)) { lay = txt_layout(game_theme.font, ALIGN_CENTER, game_theme.win_w, 0); if (!lay) return -1; txt_layout_color(lay, game_theme.fgcol); txt_layout_link_color(lay, game_theme.lcol); txt_layout_active_color(lay, game_theme.acol); txt_layout_font_height(lay, game_theme.font_height); txt_layout_rtl(lay, rtl); el_set(el_ways, elt_layout, game_theme.win_x, 0, lay); } el_set(el_sdown, elt_image, 0, 0, game_theme.a_down); el_set(el_sup, elt_image, 0, 0, game_theme.a_up); el_set(el_idown, elt_image, 0, 0, game_theme.inv_a_down); el_set(el_iup, elt_image, 0, 0, game_theme.inv_a_up); el_set(el_spic, elt_image, game_theme.win_x, game_theme.win_y, NULL); el_set(el_menu, elt_layout, 0, 0, NULL); el_set(el_menu_button, elt_image, game_theme.menu_button_x, game_theme.menu_button_y, game_theme.menu_button); gfx_set_icon(game_theme.icon); if (!DIRECT_MODE) { el_draw(el_menu_button); } return 0; } int game_restart(void) { char *og = curgame_dir; game_save(-1); game_done(0); if (game_init(og)) { game_error(); return 0; } return 0; } unsigned long timer_counter = 0; gtimer_t timer_han = NULL_TIMER; static int gfx_commit_event = 0; static void _game_gfx_commit(void *data) { gfx_commit_event = 0; gfx_commit(); } void game_gfx_commit(int sync) { if (gfx_fading()) /* to avoid flickering */ return; if (gfx_pending()) { if (sync) { _game_gfx_commit(NULL); } else { if (!gfx_commit_event) { gfx_commit_event ++; push_user_event(_game_gfx_commit, NULL); } } } } static int game_render_callback_redraw(void); static void anim_do(void *data) { void *v; img_t img; if (browse_dialog || menu_shown || gfx_fading() || minimized()) return; game_cursor(CURSOR_CLEAR); if (gfx_frame_anim(el_img(el_spic))) { /* scene */ game_render_callback_redraw(); gfx_update_anim(el_img(el_spic), game_update); } game_cursor(CURSOR_CLEAR); for (v = NULL; (img = txt_layout_images(txt_box_layout(el_box(el_scene)), &v)); ) { /* scene */ game_cursor(CURSOR_CLEAR); if ((img != el_img(el_spic)) && gfx_frame_anim(img)) { game_render_callback_redraw(); gfx_update_anim(img, game_update); } } game_cursor(CURSOR_CLEAR); for (v = NULL; (img = txt_layout_images(txt_box_layout(el_box(el_inv)), &v)); ) { /* inv */ game_cursor(CURSOR_CLEAR); if (gfx_frame_anim(img)) { game_render_callback_redraw(); gfx_update_anim(img, game_update); } } game_cursor(CURSOR_CLEAR); for (v = NULL; (img = txt_layout_images(el_layout(el_title), &v)); ) { /* title */ game_cursor(CURSOR_CLEAR); if (gfx_frame_anim(img)) { game_render_callback_redraw(); gfx_update_anim(img, game_update); } } game_cursor(CURSOR_CLEAR); for (v = NULL; (img = txt_layout_images(el_layout(el_ways), &v)); ) { /* ways */ game_cursor(CURSOR_CLEAR); if (gfx_frame_anim(img)) { game_render_callback_redraw(); gfx_update_anim(img, game_update); } } game_cursor(CURSOR_ON); game_flip(); game_gfx_commit(0); } int counter_fn(int interval, void *p) { timer_counter ++; #ifdef SAILFISHOS /* idle response sometimes */ if ((timer_counter % 25) == 0) { push_user_event(NULL, NULL); } #endif if (gfx_is_drawn_anims() && !DIRECT_MODE) push_user_event(anim_do, NULL); return interval; } static int parse_curtheme(const char *v, void *data) { char **p = ((char **)data); struct theme *theme; theme = theme_lookup(v, THEME_GAME); if (theme) *p = theme->dir; else *p = NULL; return 0; } static struct parser cmd_game_parser[] = { { "theme", parse_curtheme, &curtheme_dir[THEME_GAME], 0 }, }; static int game_cfg_load(void) { char *p = getfilepath(dirname(game_save_path(1, 0)), "config.ini"); curtheme_dir[THEME_GAME] = NULL; if (!p) return -1; parse_ini(p, cmd_game_parser); free(p); return 0; } int game_cfg_save(void) { FILE *fp; char *p; if (!curgame_dir) return 0; if (!curtheme_dir[THEME_GAME]) /* nothing todo */ return 0; p = getfilepath(dirname(game_save_path(1, 0)), "config.ini"); if (!p) return -1; fp = fopen(p, "wb"); if (fp) { if (curtheme_dir[THEME_GAME]) { fprintf(fp, "theme = %s\n", curtheme_dir[THEME_GAME]); } fclose(fp); } free(p); return 0; } int game_use_theme(void) { int rc = 0; game_theme_changed = 0; game_own_theme = 0; memset(objs, 0, sizeof(struct el) * el_max); if (game_default_theme()) { fprintf(stderr, "Can't load default theme.\n"); return -1; } if (themes_count(THEME_GAME) > 0) { /* new scheme with own themes? */ game_own_theme = 2; if (opt_owntheme) { fprintf(stderr, "Using own themes directory...\n"); if (curtheme_dir[THEME_GAME] && strlowcmp(DEFAULT_THEME, curtheme_dir[THEME_GAME])) { rc = game_theme_load(curtheme_dir[THEME_GAME], THEME_GAME); } else curtheme_dir[THEME_GAME] = DEFAULT_THEME; return rc; } } else if (curgame_dir && (!idf_access(instead_idf(), THEME_FILE) || !access(dirpath(THEME_FILE), R_OK))) { game_own_theme = 1; if (opt_owntheme) { fprintf(stderr, "Using own theme file...\n"); theme_relative = 1; rc = theme_load(THEME_FILE); theme_relative = 0; return rc; } } if (curtheme_dir[THEME_GLOBAL] && strlowcmp(DEFAULT_THEME, curtheme_dir[THEME_GLOBAL])) { rc = game_theme_load(curtheme_dir[THEME_GLOBAL], THEME_GLOBAL); } return rc; } int game_init(const char *name) { getdir(game_cwd, sizeof(game_cwd)); unix_path(game_cwd); if (game_select(name)) return -1; if (game_theme_optimize()) return -1; if (game_apply_theme()) { game_theme_select(DEFAULT_THEME); return -1; } timer_han = gfx_add_timer(HZ, counter_fn, NULL); if (!curgame_dir) { game_menu(menu_games); } else { if (!game_load(-1)) /* tmp save */ goto out; if ((opt_autosave & 1) && !game_load(0)) /* autosave */ goto out; game_cmd("look", 0); custom_theme_warn(); if (opt_autosave) game_save(0); } out: return 0; } static void game_release(void) { input_uevents(); /* all callbacks */ if (last_pict) free(last_pict); if (last_title) free(last_title); if (last_cmd) free(last_cmd); last_pict = last_title = last_cmd = NULL; // game_stop_mus(500); // sounds_free(); } void game_release_theme(int force) { int i; mouse_reset(1); game_cursor(CURSOR_OFF); if (el_img(el_spic)) { gfx_free_image(el_img(el_spic)); el_zero(el_spic); if (GFX_MODE(game_theme.gfx_mode) == GFX_MODE_EMBEDDED) txt_layout_add_img(txt_box_layout(el_box(el_scene)), "scene", NULL); } for (i = 0; i < el_max; i++) { struct el *o; if (!force) { switch (i) { case el_title: case el_ways: case el_scene: if (!(game_theme.changed & CHANGED_WIN)) continue; break; case el_inv: if (!(game_theme.changed & CHANGED_INV)) continue; break; default: break; } } o = el(i); if (o->type == elt_layout && o->p.p) { txt_layout_free(o->p.lay); } else if (o->type == elt_box && o->p.p) { txt_layout_free(txt_box_layout(o->p.box)); txt_box_free(o->p.box); } el_zero(i); } if (menu) gfx_free_image(menu); if (menubg) gfx_free_image(menubg); menu = menubg = NULL; _game_update(0, 0, game_theme.w, game_theme.h); } static int game_event(const char *ev); void game_done(int err) { if (!err && curgame_dir) { game_event("quit"); if (opt_autosave) game_save(0); game_cfg_save(); } gfx_del_timer(timer_han); timer_han = NULL_TIMER; if (menu_shown) menu_toggle(-1); game_release(); /* here all lost user callback are */ game_release_theme(1); game_theme_free(); themes_drop(THEME_GAME); input_clear(); instead_done(); curgame_dir = NULL; game_own_theme = 0; need_restart = 0; } static void el_size(int i, int *w, int *h) { int type; type = el(i)->type; if (type == elt_layout) txt_layout_size(el_layout(i), w, h); else if (type == elt_box) txt_box_size(el_box(i), w, h); else if (type == elt_image) { if (w) *w = gfx_img_w(el_img(i)); if (h) *h = gfx_img_h(el_img(i)); } else { /* impossible type */ if (w) *w = 0; if (h) *h = 0; } } #define el_clear(n) _el_clear(n, game_clear) #define el_clear_nobg(n) _el_clear(n, NULL) static int _el_clear(int n, clear_fn clear) { void *v; img_t img; int x, y, w, h; struct el *o; o = el(n); if (!o || !o->drawn) return 0; x = o->x; y = o->y; el_size(n, &w, &h); o->drawn = 0; if (clear) clear(x, y, w, h); if (o->type == elt_box) { for (v = NULL; (img = txt_layout_images(txt_box_layout(el_box(n)), &v)); ) gfx_dispose_anim(img); } else if (o->type == elt_layout) { for (v = NULL; (img = txt_layout_images(el_layout(n), &v)); ) gfx_dispose_anim(img); } else if (o->type == elt_image) gfx_dispose_anim(el_img(n)); return 1; } static void el_update(int n) { int x, y, w, h; struct el *o; o = el(n); /* if (!o->drawn) return; */ x = o->x; y = o->y; el_size(n, &w, &h); game_update(x, y, w, h); return; } static void el_clip(int n) { int x, y, w, h; struct el *o; o = el(n); x = o->x; y = o->y; el_size(n, &w, &h); gfx_clip(x, y, w, h); return; } int box_isscroll_up(int n) { if (el(n)->type != elt_box) return -1; if (txt_box_off(el_box(n))) return 0; return -1; } int box_isscroll_down(int n) { int off; int h, hh; if (el(n)->type != elt_box) return -1; el_size(n, NULL, &h); txt_box_real_size(el_box(n), NULL, &hh); off = txt_box_off(el_box(n)); if (hh - off > h) return 0; return -1; } void box_update_scrollbar(int n) { struct el *elup = NULL; struct el *eldown = NULL; /* struct el *elslide; */ int x1, y1; int x2, y2; int off; int w, h, hh; if (n == el_scene) { elup = el(el_sup); eldown = el(el_sdown); x1 = game_theme.a_up_x; y1 = game_theme.a_up_y; x2 = game_theme.a_down_x; y2 = game_theme.a_down_y; /* elslide = el(el_sslide); */ } else if (n == el_inv) { elup = el(el_iup); eldown = el(el_idown); x1 = game_theme.inv_a_up_x; y1 = game_theme.inv_a_up_y; x2 = game_theme.inv_a_down_x; y2 = game_theme.inv_a_down_y; /* elslide = el(el_islide); */ } else /* impossible case */ return; if (!elup || !eldown) return; /* if (x1 == -1 || y1 == -1 || x2 == -1 || y2 == -1) */ el_size(n, &w, &h); if (x1 == -1) x1 = el(n)->x + w + game_theme.pad; if (y1 == -1) y1 = el(n)->y; if (x2 == -1) x2 = x1; if (y2 == -1) y2 = y1 + h - gfx_img_h(game_theme.a_down); txt_box_real_size(el_box(n), NULL, &hh); off = txt_box_off(el_box(n)); if (el_clear(elup->id)) { if (elup->x != x1 || elup->y != y1) el_update(elup->id); } if (el_clear(eldown->id)) { if (eldown->x != x2 || eldown->y != y2) el_update(eldown->id); } elup->x = x1; elup->y = y1; eldown->x = x2; eldown->y = y2; el_clear(elup->id); el_clear(eldown->id); if (hh - off > h) el_draw(eldown->id); if (off) el_draw(elup->id); el_update(elup->id); el_update(eldown->id); } /* Decides what to draw */ void el_draw(int n) { int x, y; struct el *o; o = el(n); x = o->x; y = o->y; if (!o->p.p) return; game_gfx_clip(); game_cursor(CURSOR_CLEAR); if (o->type == elt_image) gfx_draw(o->p.img, x, y); else if (o->type == elt_layout) txt_layout_draw(o->p.lay, x, y); else if (o->type == elt_box) { txt_box_draw(o->p.box, x, y); box_update_scrollbar(o->id); } o->drawn = 1; game_gfx_noclip(); return; } img_t game_pict_scale(img_t img, int ww, int hh) { img_t img2 = img; int w, h, www, hhh; float scale1, scale2, scale = 1.0f; game_pic_w = gfx_img_w(img); game_pic_h = gfx_img_h(img); if (!cache_have(gfx_image_cache(), img)) { game_pic_w = (int)((float)game_pic_w / (float)game_theme.scale); game_pic_h = (int)((float)game_pic_h / (float)game_theme.scale); return img; /* do not scale sprites! */ } if (game_theme.img_scale * game_theme.scale > 1.0f) scale = game_theme.img_scale * game_theme.scale; w = gfx_img_w(img) * scale; h = gfx_img_h(img) * scale; if (ww == -1) ww = w; if (hh == -1) hh = h; if (w <= ww && h <= hh) { theme_img_scale(&img); return img; } www = ww; hhh = hh; while (scale * (float)w > ww || scale * (float)h > hh) { scale1 = (float)(www - 2) / (float)(w); scale2 = (float)(hhh - 2) / (float)(h); scale = (scale1 1.0f) scale *= (game_theme.img_scale * game_theme.scale); img2 = gfx_scale(img, scale, scale, SCALABLE_THEME_SMOOTH); gfx_free_image(img); return img2; } int game_menu_box_wh(const char *txt, int *w, int *h) { layout_t lay; int b = game_theme.border_w; int pad = game_theme.pad; lay = txt_layout(game_theme.menu_font, ALIGN_CENTER, game_theme.w - 2 * (b + pad), 0); txt_layout_set(lay, (char*)txt); txt_layout_real_size(lay, w, h); txt_layout_free(lay); return 0; } int game_menu_box_width(int show, const char *txt, int width) { /* img_t menu; */ int w, h, mw, mh; int x, y; int b = game_theme.border_w; int pad = game_theme.pad; layout_t lay = NULL; el(el_menu)->drawn = 0; if (el_layout(el_menu)) { _txt_layout_free(el_layout(el_menu)); lay = el_layout(el_menu); } if (menubg) { game_cursor(CURSOR_CLEAR); gfx_copy(menubg, mx, my); gfx_free_image(menubg); menubg = NULL; } if (menu) { gfx_free_image(menu); menu = NULL; } if (!DIRECT_MODE) { el_clear(el_menu_button); if (!show) el_draw(el_menu_button); } if (!show) { menu_shown = 0; game_cursor(CURSOR_DRAW); gfx_flip(); return 0; } instead_render_callback(); menu_shown = 1; if (!lay) { lay = txt_layout(game_theme.menu_font, ALIGN_CENTER, game_theme.w - 2 * (b + pad), 0); txt_layout_color(lay, game_theme.menu_fg); txt_layout_link_color(lay, game_theme.menu_link); txt_layout_active_color(lay, game_theme.menu_alink); txt_layout_font_height(lay, game_theme.menu_font_height); } else txt_layout_set_size(lay, game_theme.w - 2 * (b + pad), 0); txt_layout_set(lay, (char*)txt); txt_layout_real_size(lay, &w, &h); if (width) w = width; txt_layout_set_size(lay, w, h); txt_layout_set(lay, (char*)txt); menu = gfx_new(w + (b + pad)*2, h + (b + pad)*2); gfx_img_fill(menu, 0, 0, w + (b + pad)*2, h + (b + pad)*2, game_theme.border_col); gfx_img_fill(menu, b, b, w + pad*2, h + pad*2, game_theme.menu_bg); gfx_set_alpha(menu, game_theme.menu_alpha); x = (game_theme.w - w)/2; y = (game_theme.h - h)/2; mx = x - b - pad; my = y - b - pad; mw = w + (b + pad) * 2; mh = h + (b + pad) * 2; game_cursor(CURSOR_CLEAR); menubg = gfx_grab_screen(mx, my, mw, mh); gfx_draw(menu, mx, my); el_set(el_menu, elt_layout, /*game_theme.win_x*/ x, y, lay); el_draw(el_menu); game_cursor(CURSOR_DRAW); gfx_flip(); return 0; } int game_menu_box(int show, const char *txt) { int w = 0, rc; if (show && cur_menu != menu_wait) gfx_cancel_change_screen(); if (show) game_event("pause"); if (cur_menu == menu_games) { /* hack a bit :( */ w = games_menu_maxw(); game_menu_gen(); } else if (cur_menu == menu_themes) { w = themes_menu_maxw(); game_menu_gen(); } rc = game_menu_box_width(show, txt, w); if (!show) { game_event("resume"); } #ifdef __EMSCRIPTEN__ if (!show) cfg_save(); #endif return rc; } int check_new_place(char *title) { int rc = 0; if (!title && !last_title) return 0; if (!title && last_title) { rc = 1; } else if (!last_title || strcmp(title, last_title)) { rc = 1; } if (last_title) { free(last_title); } last_title = title; return rc; } int check_new_pict(char *pict) { int rc = 0; if (!pict && !last_pict) return 0; if (!pict && last_pict) { rc = 1; } else if (!last_pict || strcmp(pict, last_pict)) { rc = 1; } if (last_pict) { free(last_pict); } last_pict = pict; return rc; } static int check_fading(int *new_scene) { int rc; int st; instead_lock(); instead_function("instead.get_fading", NULL); rc = instead_bretval(0); st = instead_iretval(1); if (st < 0) st = 0; else if (st > 255) st = 255; instead_clear(); instead_unlock(); if (new_scene) *new_scene = rc; return st; } static void game_autosave(void) { int b,r; if (!curgame_dir) return; instead_lock(); instead_function("instead.get_autosave", NULL); b = instead_bretval(0); r = instead_iretval(1); instead_clear(); instead_unlock(); if (b) { r = r % MAX_SAVE_SLOTS; game_save(r); /* instead_eval("game.autosave = false;"); instead_clear();*/ } } static void game_instead_restart(void) { int b; if (!curgame_dir) return; instead_lock(); instead_function("instead.get_restart", NULL); b = instead_bretval(0); instead_clear(); instead_unlock(); need_restart = b; } static void game_instead_menu(void) { char *menu; if (!curgame_dir) return; instead_lock(); instead_function("instead.get_menu", NULL); menu = instead_retval(0); instead_clear(); instead_unlock(); if (!menu) return; if (!strcmp(menu, "save")) menu_toggle(menu_save); else if (!strcmp(menu, "load")) menu_toggle(menu_load); else if (!strcmp(menu, "quit") || !strcmp(menu, "exit")) menu_toggle(menu_askquit); else if (!strcmp(menu, "themes")) menu_toggle(menu_themes); else if (!strcmp(menu, "settings")) menu_toggle(menu_settings); else if (!strcmp(menu, "main")) menu_toggle(menu_main); else menu_toggle(-1); free(menu); } static char *get_inv(void) { char *ni; struct instead_args args[] = { { .val = NULL, .type = INSTEAD_BOOL }, { .val = NULL, }, }; args[0].val = (INV_MODE(game_theme.inv_mode) == INV_MODE_HORIZ)?"true":"false"; instead_lock(); instead_function("instead.get_inv", args); ni = instead_retval(0); instead_clear(); instead_unlock(); return ni; } static int find_diff_pos(const char *p1, const char *p2) { int pos = 0; if (!p1 || !p2) return -1; while ((*p1 == *p2) && *p1) { p1 ++; p2 ++; pos ++; } if (!*p1) return -1; return pos; } static void scroll_to_diff(const char *cmdstr, int cur_off, int new_scene) { int off = 0; int pos = 0; int h = 0; int hh = 0; off = txt_layout_anchor(txt_box_layout(el_box(el_scene)), &hh); /* tag? */ if (off == -1) { if (new_scene) return; /* nothing to do */ pos = find_diff_pos(cmdstr, last_cmd); if (pos != -1) off = txt_layout_pos2off(txt_box_layout(el_box(el_scene)), pos, &hh); if (off == -1) off = cur_off; } el_size(el_scene, NULL, &h); if (game_theme.win_scroll_mode == 2 && (cur_off <= off && cur_off + h >= off + hh)) { /* do not scroll */ off = cur_off; } txt_box_scroll(el_box(el_scene), off); } static void scroll_to_last(void) { int w, h; txt_layout_size(txt_box_layout(el_box(el_scene)), &w, &h); txt_box_scroll(el_box(el_scene), h); } int game_highlight(int x, int y, int on); int game_pict_modify(img_t p) { static int modify = 0; int last = modify; game_bg_modify(p); if (p && ((el_img(el_spic) == p) || p == gfx_screen(NULL))) modify = 1; else if (!p) /* use NULL to reset modify flag */ modify = 0; return last; } int game_bg_modify(img_t p) { static int modify = 0; int last = modify; if (p && p == game_theme.bg) modify = 1; else if (!p) /* use NULL to reset modify flag */ modify = 0; return last; } static void game_pict_clip(void) { int x, y, w, h; if (GFX_MODE(game_theme.gfx_mode) == GFX_MODE_EMBEDDED) { el_clip(el_scene); return; } if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_FLOAT) { x = game_theme.win_x; y = game_theme.win_y; w = game_theme.win_w; h = game_theme.win_h; } else { x = game_theme.gfx_x; y = game_theme.gfx_y; w = game_theme.max_scene_w; h = game_theme.max_scene_h; } gfx_clip(x, y, w, h); } void game_gfx_clip(void) { if (game_theme.bg) { gfx_img_clip(game_theme.bg, game_theme.xoff, game_theme.yoff, game_theme.w - 2 * game_theme.xoff, game_theme.h - 2 * game_theme.yoff); } gfx_clip(game_theme.xoff, game_theme.yoff, game_theme.w - 2 * game_theme.xoff, game_theme.h - 2 * game_theme.yoff); } void game_gfx_noclip(void) { if (game_theme.bg) { gfx_img_noclip(game_theme.bg); } gfx_noclip(); } static void game_redraw_pic(void) { int x, y, ox, oy; if (game_pict_coord(&x, &y, NULL, NULL)) return; game_pict_clip(); ox = el(el_spic)->x; oy = el(el_spic)->y; el(el_spic)->x = x; el(el_spic)->y = y; el_clear(el_spic); el_draw(el_spic); gfx_noclip(); el_update(el_spic); el(el_spic)->x = ox; el(el_spic)->y = oy; } static xref_t hl_xref = NULL; static struct el *hl_el = NULL; static struct { img_t offscreen; int flags; int m_restore; } fade_ctx; static void after_click(int flags, int m_restore) { if (DIRECT_MODE) return; #if 1 { int x, y; if (!(flags & GAME_CMD_NOHL) && (!m_restore || mouse_restore())) { gfx_cursor(&x, &y); game_highlight(x, y, 1); /* highlight new scene, to avoid flickering */ } } #endif } extern void instead_ready(void); static void after_cmd(void) { game_autosave(); game_instead_restart(); game_instead_menu(); game_gfx_commit(0); } static void after_fading(void *aux) { gfx_start_anim(el_img(el_spic)); gfx_free_image(fade_ctx.offscreen); game_render_callback_redraw(); after_click(fade_ctx.flags, fade_ctx.m_restore); after_cmd(); game_cursor(CURSOR_DRAW); game_flip(); } void game_redraw_all(void) { if (menu_shown || DIRECT_MODE) return; game_clear_all(); el_draw(el_title); el_draw(el_ways); if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_EMBEDDED) el_draw(el_spic); el_draw(el_scene); if (inv_enabled()) el_draw(el_inv); el_draw(el_menu_button); game_update(0, 0, game_theme.w, game_theme.h); } static int game_render_callback_redraw(void) { if (instead_render_callback_dirty(0) == -1) { instead_render_callback_dirty(1); /* disable updates */ game_redraw_all(); return 1; } return 0; } int game_cmd(char *cmd, int flags) { int old_off; int fading = 0; int new_pict = 0; int new_place = 0; int redraw_pict = 0; int title_h = 0, ways_h = 0, pict_h = 0; char buf[1024]; char *cmdstr = NULL; char *invstr = NULL; char *waystr = NULL; char *title = NULL; char *pict = NULL; img_t oldscreen = NULL; int dd = (DIRECT_MODE); int rc = 0; int new_scene = 0; int m_restore = 0; int win_spacing; if (menu_shown) return -1; /* if (dd) */ game_cursor(CURSOR_CLEAR); instead_lock(); if (flags & GAME_CMD_FILE) /* file command */ cmdstr = instead_file_cmd(cmd, &rc); else cmdstr = instead_cmd(cmd, &rc); instead_unlock(); instead_ready(); if (opt_click && (flags & GAME_CMD_CLICK) && !rc) sound_play_click(); if (DIRECT_MODE) { if (cmdstr) free(cmdstr); if (game_theme_changed) { /* cursor change only? */ img_t offscreen = gfx_new(game_theme.w, game_theme.h); if (!offscreen) goto fatal; oldscreen = gfx_screen(offscreen); gfx_copy(oldscreen, 0, 0); if ((rc = game_theme_update())) goto out; offscreen = gfx_screen(oldscreen); gfx_change_screen(offscreen, 1, NULL, NULL); gfx_free_image(offscreen); } if (game_pict_modify(NULL)) goto out; return rc; } else if (dd) { /* disable direct mode on the fly */ game_theme_changed = 1; /* force redraw */ game_cursor(CURSOR_DRAW); } if (!cmdstr) { game_render_callback_redraw(); if (game_bg_modify(NULL)) { game_redraw_all(); } else if (game_pict_modify(NULL)) /* redraw pic only */ game_redraw_pic(); if (!rc) { if (hl_el == el(el_inv)) { m_restore = !(flags & GAME_CMD_CLICK); mouse_reset(0); } goto inv; /* hackish? ok, yes it is... */ } if (instead_render_callback_dirty(-1) == 1) { game_cursor(CURSOR_DRAW); game_flip(); } goto err; /* really nothing to do */ } if (game_bg_modify(NULL)) game_theme_changed = 1; /* force redraw */ m_restore = !(flags & GAME_CMD_CLICK); mouse_reset(0); /* redraw all, so, reset mouse */ fading = check_fading(&new_scene); instead_lock(); instead_function("instead.get_title", NULL); title = instead_retval(0); instead_clear(); instead_unlock(); new_place = check_new_place(title); instead_lock(); instead_function("instead.get_picture", NULL); pict = instead_retval(0); instead_clear(); instead_unlock(); unix_path(pict); new_pict = check_new_pict(pict); if (game_theme_changed && !fading) fading = 1; /* one frame at least */ if (fading) { /* take old screen */ img_t offscreen; game_cursor(CURSOR_CLEAR); offscreen = gfx_new(game_theme.w, game_theme.h); if (!offscreen) goto fatal; oldscreen = gfx_screen(offscreen); gfx_copy(oldscreen, 0, 0); } game_render_callback_redraw(); if (game_theme_changed) { if ((rc = game_theme_update())) goto out; new_place = 1; if (pict) new_pict = 1; } if (new_place) el_clear(el_title); win_spacing = game_theme.font_size * game_theme.font_height / 2; if (title && *title) { snprintf(buf, sizeof(buf), "%s", title); txt_layout_set(el_layout(el_title), buf); txt_layout_size(el_layout(el_title), NULL, &title_h); title_h += win_spacing; } else txt_layout_set(el_layout(el_title), NULL); if (new_pict || fading || game_pict_modify(NULL) || (new_place && (GFX_MODE(game_theme.gfx_mode) == GFX_MODE_FIXED))) { redraw_pict = 1; } game_pict_clip(); if (redraw_pict) { if (el_img(el_spic)) { if (GFX_MODE(game_theme.gfx_mode) == GFX_MODE_EMBEDDED) el_clear_nobg(el_spic); else el_clear(el_spic); if (new_pict) { gfx_free_image(el_img(el_spic)); el(el_spic)->p.p = NULL; if (GFX_MODE(game_theme.gfx_mode) == GFX_MODE_EMBEDDED) /* clear embedded gfx */ txt_layout_add_img(txt_box_layout(el_box(el_scene)), "scene", NULL); } } } if (pict) { int w, h, x; img_t img; if (new_pict) { img = gfx_load_image(pict); if (!img) game_res_err_msg(pict, debug_sw); if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_FLOAT) img = game_pict_scale(img, game_theme.win_w, game_theme.max_scene_h); else img = game_pict_scale(img, game_theme.max_scene_w, game_theme.max_scene_h); } else img = el_img(el_spic); if (img) { w = gfx_img_w(img); h = gfx_img_h(img); if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_FLOAT) { x = (game_theme.win_w - w)/2 + game_theme.win_x; if (redraw_pict) el_set(el_spic, elt_image, x, game_theme.win_y + title_h, img); } else { int xx, yy; if (GFX_ALIGN(game_theme.gfx_mode) & ALIGN_TOP) yy = 0; else if (GFX_ALIGN(game_theme.gfx_mode) & ALIGN_BOTTOM) yy = game_theme.max_scene_h - h; else yy = (game_theme.max_scene_h - h)/2; if (GFX_ALIGN(game_theme.gfx_mode) & ALIGN_LEFT) xx = 0; else if (GFX_ALIGN(game_theme.gfx_mode) & ALIGN_RIGHT) xx = game_theme.max_scene_w - w; else xx = (game_theme.max_scene_w - w)/2; x = xx + game_theme.gfx_x; if (redraw_pict) el_set(el_spic, elt_image, x, game_theme.gfx_y + yy, img); } pict_h = h; } } gfx_noclip(); /* clear area */ el_clear(el_ways); el_clear(el_scene); instead_lock(); instead_function("instead.get_ways", NULL); waystr = instead_retval(0); instead_clear(); instead_unlock(); if (waystr) { int l = strlen(waystr); if (l && waystr[l - 1] == '\n') waystr[l - 1] = 0; } if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_EMBEDDED) { txt_layout_set(el_layout(el_ways), waystr); txt_layout_size(el_layout(el_ways), NULL, &ways_h); if ((ways_h == 0 || WAYS_BOTTOM) && pict_h != 0) pict_h += win_spacing; } old_off = txt_box_off(el_box(el_scene)); if (GFX_MODE(game_theme.gfx_mode) == GFX_MODE_EMBEDDED) { char *p; pict_h = 0; /* to fake code bellow */ txt_box_resize(el_box(el_scene), game_theme.win_w, game_theme.win_h - title_h - ways_h - pict_h); txt_layout_set(txt_box_layout(el_box(el_scene)), ""); /* hack, to null layout, but not images */ if (el_img(el_spic)) { txt_layout_add_img(txt_box_layout(el_box(el_scene)),"scene", el_img(el_spic)); txt_layout_add(txt_box_layout(el_box(el_scene)), "\n"); } p = malloc(strlen(cmdstr) + ((waystr)?strlen(waystr):0) + 16); if (p) { *p = 0; if (!WAYS_BOTTOM && waystr && *waystr) { strcpy(p, waystr); strcat(p, "\n"); } else if (el_img(el_spic)) strcat(p, "\n"); strcat(p, cmdstr); if (WAYS_BOTTOM && waystr) { strcat(p, "\n"); strcat(p, waystr); } free(cmdstr); cmdstr = p; } else { /* paranoia? Yes... */ txt_layout_add(txt_box_layout(el_box(el_scene)), waystr); txt_layout_add(txt_box_layout(el_box(el_scene)), "\n"); /* small hack */ } txt_layout_add(txt_box_layout(el_box(el_scene)), cmdstr); txt_box_set(el_box(el_scene), txt_box_layout(el_box(el_scene))); } else { if (GFX_MODE(game_theme.gfx_mode) == GFX_MODE_FLOAT) pict_h = 0; txt_box_resize(el_box(el_scene), game_theme.win_w, game_theme.win_h - title_h - ways_h - pict_h); txt_layout_set(txt_box_layout(el_box(el_scene)), cmdstr); txt_box_set(el_box(el_scene), txt_box_layout(el_box(el_scene))); } if (WAYS_BOTTOM) el(el_ways)->y = game_theme.win_h - ways_h + game_theme.win_y; else el(el_ways)->y = el(el_title)->y + title_h + pict_h; if (waystr) free(waystr); if (WAYS_BOTTOM) el(el_scene)->y = el(el_title)->y + title_h + pict_h; else el(el_scene)->y = el(el_ways)->y + ways_h; /* game_clear(game_theme.win_x, game_theme.win_y + pict_h + title_h, game_theme.win_w, game_theme.win_h - pict_h - title_h); */ /* draw title and ways */ if (new_place) el_draw(el_title); if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_EMBEDDED) { el_draw(el_ways); if (redraw_pict) { game_pict_clip(); el_draw(el_spic); gfx_noclip(); } } if (game_theme.win_scroll_mode == 1 || game_theme.win_scroll_mode == 2) { scroll_to_diff(cmdstr, old_off, new_scene); } else if (game_theme.win_scroll_mode == 3) { scroll_to_last(); } FREE(last_cmd); last_cmd = cmdstr; el_draw(el_scene); inv: if (inv_enabled()) { int off; invstr = get_inv(); off = txt_box_off(el_box(el_inv)); txt_layout_set(txt_box_layout(el_box(el_inv)), invstr); txt_box_set(el_box(el_inv), txt_box_layout(el_box(el_inv))); txt_box_scroll(el_box(el_inv), off); if (invstr) free(invstr); el_clear(el_inv); el_draw(el_inv); } if (fading) { img_t offscreen; game_cursor(CURSOR_OFF); gfx_stop_anim(el_img(el_spic)); instead_render_callback(); offscreen = gfx_screen(oldscreen); fade_ctx.offscreen = offscreen; fade_ctx.flags = flags; fade_ctx.m_restore = m_restore; gfx_change_screen(offscreen, fading, after_fading, offscreen); return 0; } after_click(flags, m_restore); out: game_cursor(CURSOR_DRAW); game_flip(); /* input_clear(); */ err: after_cmd(); return rc; fatal: fprintf(stderr, "Fatal error! (can't alloc offscreen)\n"); exit(1); } /* void game_update(int x, int y, int w, int h) { game_cursor(CURSOR_DRAW); gfx_update(x, y, w, h); }*/ void game_xref_update(xref_t xref, int x, int y) { if (instead_render_callback_dirty(-1) == -1) return; game_cursor(CURSOR_CLEAR); xref_update(xref, x, y, game_clear, game_update); } xref_t use_xref = NULL; int disable_use(void) { if (use_xref) { xref_set_active(use_xref, 0); if (xref_layout(use_xref) == txt_box_layout(el_box(el_inv))) game_xref_update(use_xref, el(el_inv)->x, el(el_inv)->y); else game_xref_update(use_xref, el(el_scene)->x, el(el_scene)->y); use_xref = NULL; return 1; } return 0; } void enable_use(xref_t xref) { use_xref = xref; xref_set_active(xref, 1); if (xref_layout(use_xref) == txt_box_layout(el_box(el_inv))) game_xref_update(use_xref, el(el_inv)->x, el(el_inv)->y); else game_xref_update(use_xref, el(el_scene)->x, el(el_scene)->y); } struct el *look_obj(int x, int y) { int i; for (i = 0; i < el_max; i++) { int w, h; if (el(i)->drawn && el(i)->id == el_menu) { return el(i); } if (x < el(i)->x || y < el(i)->y || !el(i)->drawn) continue; el_size(i, &w, &h); if (x >= el(i)->x && y >= el(i)->y && x < el(i)->x + w && y < el(i)->y + h) return el(i); } return NULL; } static xref_t get_nearest_xref(int i, int mx, int my); xref_t look_xref(int x, int y, struct el **elem) { struct el *o; int type; xref_t xref = NULL; o = look_obj(x, y); if (elem) *elem = o; if (!o) return NULL; type = o->type; if (type == elt_layout) xref = txt_layout_xref(o->p.lay, x - o->x, y - o->y); else if (type == elt_box) xref = txt_box_xref(o->p.box, x - o->x, y - o->y); #if defined(ANDROID) || defined(IOS) || defined(SAILFISHOS) || defined(WINRT) if (!xref) { int xc, yc, r; xref = get_nearest_xref(o->id, x, y); if (!xref) return NULL; r = fnt_height(txt_layout_font(xref_layout(xref))) * 2; /* radius is here */ if (!xref_position(xref, &xc, &yc)) { if (o->type == elt_box && yc) yc -= txt_box_off(el_box(o->id)); xc += o->x; yc += o->y; if (((x - xc)*(x - xc) + (y - yc)*(y - yc)) < (r * r)) return xref; } return NULL; } #endif return xref; } static char click_xref[1024]; static struct el *click_el = NULL; static unsigned long click_time = 0; static int click_x = -1; static int click_y = -1; int menu_visible(void) { if (menu_shown) return cur_menu; return 0; } int game_freezed(void) { return browse_dialog || menu_shown || gfx_fading() || minimized(); } int game_paused(void) { return game_freezed() || (use_xref && game_wait_use) || instead_busy(); } void menu_update(struct el *elem) { gfx_copy(menubg, mx, my); gfx_draw(menu, mx, my); txt_layout_draw(elem->p.lay, elem->x, elem->y); gfx_update(mx, my, gfx_img_w(menu), gfx_img_h(menu)); /* gfx_fill(x, y, w, h, game_theme.menu_bg); */ } int game_highlight(int x, int y, int on) { struct el *elem = NULL; xref_t xref = NULL; if (on == 1) { xref = look_xref(x, y, &elem); if (xref && opt_hl && !xref_get_active(xref)) { xref_set_active(xref, 1); game_xref_update(xref, elem->x, elem->y); } } if (hl_xref != xref && hl_el) { if (hl_xref != use_xref && xref_get_active(hl_xref)) { xref_set_active(hl_xref, 0); game_xref_update(hl_xref, hl_el->x, hl_el->y); } } hl_xref = xref; hl_el = elem; return 0; } void mouse_reset(int hl) { if (hl && (menu_shown || !DIRECT_MODE)) { game_highlight(-1, -1, 0); } else hl_xref = hl_el = NULL; disable_use(); motion_mode = 0; click_el = NULL; click_xref[0] = 0; } void menu_toggle(int menu) { int on = menu_shown; mouse_reset(1); on ^= 1; if (!on) cur_menu = menu_main; else if (menu != -1) cur_menu = menu; top_menu = cur_menu; game_menu_box(on, game_menu_gen()); menu_shown = on; } static int scroll_pup(int id) { int hh; if (box_isscroll_up(id)) return -1; el_size(el_scene, NULL, &hh); txt_box_scroll(el_box(id), -hh); el_clear(id); el_draw(id); el_update(id); return 0; } static int scroll_pdown(int id) { int hh; if (box_isscroll_down(id)) return -1; el_size(el_scene, NULL, &hh); txt_box_scroll(el_box(id), hh); el_clear(id); el_draw(id); el_update(id); return 0; } int mouse_filter(int filter) { static unsigned long old_counter = 0; if (!opt_filter || !mouse_filter_delay) return 0; if (filter && (old_counter - timer_counter <= (mouse_filter_delay / HZ))) /* 400 ms */ return -1; old_counter = timer_counter; return 0; } /* action: 0 - first click,1 - second, -1 - restore */ int game_click(int x, int y, int action, int filter) { int menu_mode = 0; int use_mode = 0; int go_mode = 0; struct el *elem = NULL; char buf[1024]; xref_t xref = NULL; char *xref_txt = NULL; xref_t new_xref = NULL; struct el *new_elem = NULL; int was_motion = (motion_mode == 2); if (!action) { click_x = x; click_y = y; motion_y = y; click_time = timer_counter; } else if (action == 1) { click_x = -1; click_y = -1; } if (action) motion_mode = 0; if (action == 1) { char *link; new_xref = look_xref(x, y, &new_elem); link = (new_xref)?xref_get_text(new_xref):""; if (new_elem != click_el || strcmp(link, click_xref)) { click_el = NULL; new_xref = NULL; new_elem = NULL; if (click_xref[0]) { click_xref[0] = 0; return 0; /* just filtered */ } } } if (action == 1) { xref = new_xref; elem = new_elem; click_xref[0] = 0; click_el = NULL; } else { /* just press */ xref = look_xref(x, y, &elem); click_xref[0] = 0; if (xref) { xref_set_active(xref, 1); game_xref_update(xref, elem->x, elem->y); } else if (elem && elem->type == elt_box && opt_motion && (!box_isscroll_up(elem->id) || !box_isscroll_down(elem->id))) { motion_mode = 1; motion_id = elem->id; return 0; } if (xref) { snprintf(click_xref, sizeof(click_xref), "%s", xref_get_text(xref)); click_xref[sizeof(click_xref) - 1] = 0; } click_el = elem; return 0; } /* now look only second press */ if (!xref) { if (elem) { if (elem->id == el_menu_button) { menu_toggle(-1); } else if (elem->id == el_sdown) { scroll_pdown(el_scene); } else if (elem->id == el_sup) { scroll_pup(el_scene); } else if (elem->id == el_idown) { scroll_pdown(el_inv); } else if (elem->id == el_iup) { scroll_pup(el_inv); } else disable_use(); /* el_update(el_inv); */ motion_mode = 0; } else if (!(was_motion && MOTION_TIME)) { disable_use(); /* el_update(el_inv); gfx_flip(); */ } return 0; } /* second xref */ if (elem->id == el_menu) { /* xref_set_active(xref, 0); txt_layout_update_links(elem->p.lay, elem->x, elem->y, game_clear); */ if (game_menu_act(xref_get_text(xref))) { return -1; } /* game_menu_box(menu_shown, game_menu_gen()); gfx_flip(); */ return 1; } xref_txt = xref_get_text(xref); if (!strncmp("act ", xref_get_text(xref), 4)) { menu_mode = 1; xref_txt += 4; } else if (!strncmp("use ", xref_get_text(xref), 4)) { use_mode = 1; xref_txt += 4; } else if (!strncmp("go ", xref_get_text(xref), 3)) { go_mode = 1; /* xref_txt += 3; */ } else if (!strncmp("obj/act ", xref_get_text(xref), 8)) { if (!use_xref) xref_txt += 4; /* act */ else xref_txt += 8; /* obj */ } else if (elem->id == el_inv) { use_mode = 1; } if (!use_xref) { if (use_mode) { enable_use(xref); /* el_update(el_inv); */ return 0; } if (menu_mode) { if (elem->id == el_inv) snprintf(buf, sizeof(buf), "use %s", xref_txt); else snprintf(buf, sizeof(buf), "act %s", xref_txt); } else snprintf(buf, sizeof(buf), "%s", xref_txt); if (mouse_filter(filter)) return 0; buf[sizeof(buf) - 1] = 0; game_cmd(buf, GAME_CMD_CLICK); return 1; } if (menu_mode || go_mode || elem->id == el_title) return 0; if (use_xref == xref) snprintf(buf,sizeof(buf), "use %s", xref_txt); else { if (!strncmp("use ", xref_get_text(use_xref), 4)) /* already use */ snprintf(buf,sizeof(buf), "%s,%s", xref_get_text(use_xref), xref_txt); else snprintf(buf,sizeof(buf), "use %s,%s", xref_get_text(use_xref), xref_txt); } if (mouse_filter(filter)) return 0; disable_use(); buf[sizeof(buf) - 1] = 0; game_cmd(buf, GAME_CMD_CLICK); return 1; } int mouse_restore(void) { if (click_x == -1 || click_y == -1) return -1; game_click(click_x, click_y, -1, 0); return 0; } int game_cursor_show = 1; void game_cursor(int on) { static img_t grab = NULL; static img_t cur = NULL; static int xc = 0, yc = 0, w = 0, h = 0; /*, w, h; */ int xx, yy, ww, hh; gfx_getclip(&xx, &yy, &ww, &hh); gfx_noclip(); if (on == CURSOR_OFF) cur = NULL; if (grab) { gfx_copy(grab, xc, yc); gfx_free_image(grab); grab = NULL; } if (on == CURSOR_OFF) { _game_update(xc, yc, w, h); goto out; } if (on == CURSOR_CLEAR) goto out; if (on != CURSOR_DRAW) cur = (use_xref) ? game_theme.use:game_theme.cursor; if (!cur) goto out; do { int ox = xc; int oy = yc; int ow = w; int oh = h; if (on != CURSOR_DRAW) { gfx_cursor(&xc, &yc); xc -= game_theme.cur_x; yc -= game_theme.cur_y; } w = gfx_img_w(cur); h = gfx_img_h(cur); grab = gfx_grab_screen(xc, yc, w, h); if (!nocursor_sw && mouse_focus() && (game_cursor_show || menu_shown)) gfx_draw(cur, xc, yc); if (on != CURSOR_DRAW) { _game_update(xc, yc, w, h); _game_update(ox, oy, ow, oh); } } while (0); out: gfx_clip(xx, yy, ww, hh); return; } static void scroll_up(int id, int count) { /* int i; */ if (box_isscroll_up(id)) return; txt_box_scroll(el_box(id), -(FONT_SZ(game_theme.font_size)) * count); el_clear(id); el_draw(id); el_update(id); } static void scroll_down(int id, int count) { /* int i; */ if (box_isscroll_down(id)) return; txt_box_scroll(el_box(id), (FONT_SZ(game_theme.font_size)) * count); el_clear(id); el_draw(id); el_update(id); } static int scroll_possible(int id, int off) { if (!off || (off > 0 && box_isscroll_down(id)) || (off < 0 && box_isscroll_up(id))) return -1; return 0; } static void scroll_motion(int id, int off) { if (scroll_possible(id, off)) return; game_highlight(-1, -1, 0); txt_box_scroll(el_box(id), off); el_clear(id); el_draw(id); el_update(id); } static int sel_el = 0; static void frame_next(void) { if (sel_el == el_scene && !inv_enabled()) sel_el = el_inv; switch(sel_el) { default: case 0: sel_el = el_scene; break; case el_ways: sel_el = el_scene; break; case el_scene: sel_el = el_inv; break; case el_inv: if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_EMBEDDED && txt_layout_xrefs(el_layout(el_ways))) sel_el = el_ways; else sel_el = el_scene; break; } } static void frame_prev(void) { switch(sel_el) { default: case 0: sel_el = el_inv; break; case el_title: sel_el = el_inv; break; case el_ways: sel_el = el_inv; break; case el_scene: if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_EMBEDDED && txt_layout_xrefs(el_layout(el_ways))) sel_el = el_ways; else sel_el = el_inv; break; case el_inv: sel_el = el_scene; break; } if (sel_el == el_inv && !inv_enabled()) sel_el = el_scene; } static int select_ref(int prev, int last); static xref_t get_xref(int i, int last); static void xref_jump(xref_t xref, struct el* elem); static void select_frame(int prev) { struct el *elem = NULL; int x, y, w, h; gfx_cursor(&x, &y); elem = look_obj(x, y); if (elem) sel_el = elem->id; el(sel_el)->mx = x; el(sel_el)->my = y; if (menu_shown) { sel_el = el_menu; } else { /* int old_sel; if (!sel_el) frame_next(); old_sel = sel_el; do { */ if (prev) { frame_prev(); } else { frame_next(); } /* } while (!get_xref(sel_el, 0) && sel_el != old_sel); */ } el_size(sel_el, &w, &h); x = el(sel_el)->mx; y = el(sel_el)->my; if (x < el(sel_el)->x || y < el(sel_el)->y || x > el(sel_el)->x + w || y > el(sel_el)->y + h) { x = el(sel_el)->x + w / 2; y = el(sel_el)->y + h / 2; } gfx_warp_cursor(x, y); if (!look_xref(x, y, &elem) && elem) { xref_t xref = get_nearest_xref(elem->id, x, y); xref_jump(xref, elem); } } static int xref_rel_position(xref_t xref, struct el *elem, int *x, int *y) { int rc = xref_position(xref, x, y); if (!rc && elem->type == elt_box && y) { *y -= txt_box_off(el_box(elem->id)); } return rc; } static int xref_visible(xref_t xref, struct el *elem) { int x, y, w, h; if (!elem || !xref) return -1; if (xref_rel_position(xref, elem, &x, &y)) return -1; el_size(elem->id, &w, &h); if (y < 0 || y >= h) return -1; return 0; } static xref_t get_nearest_xref(int i, int mx, int my) { xref_t xref = NULL; xref_t min_xref = NULL; int min_disp = game_theme.h * game_theme.h + game_theme.w * game_theme.w; if (!i) return NULL; for (xref = get_xref(i, 0); !xref_visible(xref, el(i)); xref = xref_next(xref)) { int x, y, disp; if (xref_rel_position(xref, el(i), &x, &y)) continue; disp = (x + el(i)->x - mx) * (x + el(i)->x - mx) + (y + el(i)->y - my) * (y + el(i)->y - my); if (disp < min_disp) { min_disp = disp; min_xref = xref; } } return min_xref; } static xref_t get_xref(int i, int last) { xref_t xref = NULL; int type; type = el(i)->type; if (type == elt_layout) { xref = txt_layout_xrefs(el_layout(i)); while (last && xref && xref_next(xref)) xref = xref_next(xref); } else if (type == elt_box) { xref = txt_box_xrefs(el_box(i)); while (!last && xref && !xref_visible(xref_prev(xref), el(i))) /* try find visible one */ xref = xref_prev(xref); while (last && xref && !xref_visible(xref_next(xref), el(i))) xref = xref_next(xref); } return xref; } static void xref_jump(xref_t xref, struct el* elem) { int x, y; if (!elem || !xref || xref_visible(xref, elem) || xref_rel_position(xref, elem, &x, &y)) return; gfx_warp_cursor(elem->x + x, elem->y + y); } static int select_ref(int prev, int last) { int x, y; struct el *elem = NULL; xref_t xref = NULL; gfx_cursor(&x, &y); xref = look_xref(x, y, &elem); if (!elem) { if (!sel_el) select_frame(0); elem = el(sel_el); } if (last) { if (!(xref = get_xref(elem->id, !prev))) return -1; } else if (xref) { if (prev) { do { xref = xref_prev(xref); } while (xref && xref_valid(xref)); if (!xref || xref_visible(xref, elem)) { if (!box_isscroll_up(elem->id) || !box_isscroll_down(elem->id)) return -1; else xref = get_xref(elem->id, 1); } } else { do { xref = xref_next(xref); } while (xref && xref_valid(xref)); if (!xref || xref_visible(xref, elem)) { if (!box_isscroll_down(elem->id) || !box_isscroll_up(elem->id)) return -1; else xref = get_xref(elem->id, 0); } } } if (!xref) xref = get_nearest_xref(elem->id, x, y); if (!xref) return -1; xref_jump(xref, elem); return 0; } static void game_scroll_up(int count) { int xm, ym; struct el *o; gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { scroll_up(o->id, count); } } static void game_scroll_down(int count) { int xm, ym; struct el *o; gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { scroll_down(o->id, count); } } static int game_scroll_pup(void) { int xm, ym; struct el *o; gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { return scroll_pup(o->id); } return -1; } static int game_scroll_pdown(void) { int xm, ym; struct el *o; gfx_cursor(&xm, &ym); o = look_obj(xm, ym); if (o && (o->id == el_scene || o->id == el_inv)) { return scroll_pdown(o->id); } return -1; } static int is_key(struct inp_event *ev, const char *name) { return strcmp(ev->sym, name); } int game_pict_coord(int *x, int *y, int *w, int *h) { img_t img; int ww, hh; int xx, yy; word_t word; img = el_img(el_spic); if (!img) return -1; if (GFX_MODE(game_theme.gfx_mode) != GFX_MODE_EMBEDDED) { xx = el(el_spic)->x; yy = el(el_spic)->y; ww = gfx_img_w(img); hh = gfx_img_h(img); goto out; } el_size(el_scene, &ww, &hh); for (word = NULL; (word = txt_layout_words(txt_box_layout(el_box(el_scene)), word)); ) { /* scene */ if (word_image(word) != img) { word = NULL; /* first word is always pic */ break; /* continue; */ } word_geom(word, &xx, &yy, &ww, &hh); yy -= txt_box_off(el_box(el_scene)); xx += el(el_scene)->x; yy += el(el_scene)->y; break; } if (!word) return -1; out: if (x) *x = xx; if (y) *y = yy; if (w) *w = ww; if (h) *h = hh; return 0; } static int game_pic_click(int x, int y, int *ox, int *oy) { int xx, yy, ww, hh; if (game_pict_coord(&xx, &yy, &ww, &hh)) return -1; if (x >= xx && y >= yy && x < (xx + ww) && y < (yy + hh)) { *ox = x - xx; *oy = y - yy; if (ww) *ox = (int)((float)(*ox) * (float)game_pic_w / (float)ww); else *ox = 0; if (hh) *oy = (int)((float)(*oy) * (float)game_pic_h / (float)hh); else *oy = 0; return 0; } return -1; } static int game_bg_click(int mb, int x, int y, int *ox, int *oy) { struct el *o = NULL; struct game_theme *t = &game_theme; int bg = 1; if (x < t->xoff || y < t->yoff || x >= (t->w - t->xoff) || y >= (t->h - t->yoff)) bg = 0; else o = look_obj(x, y); *ox = (int)((float)(x - t->xoff) / (float)t->scale); *oy = (int)((float)(y - t->yoff) / (float)t->scale); if (!game_grab_events && ((o && (o->id == el_sup || o->id == el_sdown || o->id == el_iup || o->id == el_idown || o->id == el_menu_button)) || look_xref(x, y, NULL))) return -1; /* ask Odyssey for that ;) */ if (bg || mb == EV_CODE_FINGER) /* fingers area may be larger */ return 0; return -1; } static int game_event(const char *ev) { char *p; int rc; struct instead_args args[8]; if (!curgame_dir) return -1; if (game_paused()) return -1; args[0].val = "event"; args[0].type = INSTEAD_STR; args[1].val = ev; args[1].type = INSTEAD_STR; args[2].val = NULL; instead_lock(); if (instead_function("iface:input", args)) { instead_clear(); instead_unlock(); return -1; } p = instead_retval(0); instead_clear(); instead_unlock(); if (!p) return -1; rc = game_cmd(p, GAME_CMD_NOHL); free(p); return (rc)?-1:0; } static int game_input(int down, const char *key, int x, int y, int mb) { char *p; struct instead_args args[8]; int rc = 0; char tx[16]; char ty[16]; char tpx[16]; char tpy[16]; char tmb[16]; if (game_paused()) return -1; if (mb == EV_CODE_KBD) { const char *k; args[0].val = "kbd"; args[0].type = INSTEAD_STR; args[1].val = (down)?"true":"false"; args[1].type = INSTEAD_BOOL; k = (key) ? key:"unknown"; args[2].val = (char*)k; args[2].type = INSTEAD_STR; args[3].val = NULL; } else if (mb == EV_CODE_TEXT) { const char *k; args[0].val = "text"; args[0].type = INSTEAD_STR; k = (key) ? key:""; args[1].val = (char*)k; args[1].type = INSTEAD_STR; args[2].val = NULL; } else if (mb == EV_CODE_WHEEL) { if (!game_grab_events) return -1; args[0].val = "wheel"; args[0].type = INSTEAD_STR; snprintf(tx, sizeof(tx), "%d", x); snprintf(ty, sizeof(ty), "%d", y); args[1].val = tx; args[1].type = INSTEAD_NUM; args[2].val = ty; args[2].type = INSTEAD_NUM; args[3].val = NULL; } else { const char *k; int px = -1; int py = -1; game_pic_click(x, y, &px, &py); /* got picture coord */ if (game_bg_click(mb, x, y, &x, &y)) { /* no click on bg */ return -1; } snprintf(tx, sizeof(tx), "%d", x); snprintf(ty, sizeof(ty), "%d", y); snprintf(tmb, sizeof(tmb), "%d", mb); if (mb == EV_CODE_FINGER) { args[0].val = "finger"; args[0].type = INSTEAD_STR; } else { args[0].val = "mouse"; args[0].type = INSTEAD_STR; } args[1].val = (down)?"true":"false"; args[1].type = INSTEAD_BOOL; if (mb == EV_CODE_FINGER) { k = (key)?key:"unknown"; args[2].val = k; args[2].type = INSTEAD_STR; } else { args[2].val = tmb; args[2].type = INSTEAD_NUM; } args[3].val = tx; args[3].type = INSTEAD_NUM; args[4].val = ty; args[4].type = INSTEAD_NUM; args[5].val = NULL; if (px != -1) { snprintf(tpx, sizeof(tpx), "%d", px); snprintf(tpy, sizeof(tpy), "%d", py); args[5].val = tpx; args[5].type = INSTEAD_NUM; args[6].val = tpy; args[6].type = INSTEAD_NUM; args[7].val = NULL; } } instead_lock(); if (instead_function("iface:input", args)) { instead_clear(); instead_unlock(); return -1; } p = instead_retval(0); instead_clear(); instead_unlock(); if (!p) { return -1; } rc = game_cmd(p, (mb >= 0 || mb == EV_CODE_FINGER)?GAME_CMD_CLICK:0); free(p); return (rc)?-1:0; } extern char zip_game_dirname[]; extern int unpack(const char *zipfilename, const char *dirname); #ifdef _USE_BROWSE int game_from_disk(void) { int i = 0; char *g, *p, *b, *d; char dir[PATH_MAX]; char base[PATH_MAX]; if (opt_fs) { int old_menu = (menu_shown) ? cur_menu: -1; opt_fs ^= 1; game_restart(); if (old_menu != -1) game_menu(old_menu); } mouse_cursor(1); game_cursor(CURSOR_OFF); browse_dialog = 1; getdir(dir, sizeof(dir)); #ifdef LC_MESSAGES setlocale(LC_MESSAGES, ""); #endif g = p = open_file_dialog(); #ifdef LC_MESSAGES setlocale(LC_MESSAGES, "C"); #endif setdir(dir); /* dir can be changed */ browse_dialog = 0; game_cursor(CURSOR_ON); mouse_cursor(0); gfx_flip(); if (!p) return -1; game_done(0); strcpy(dir, p); strcpy(base, p); d = dir; b = base; i = strlen(d); if (i && d[i - 1] != '/') { /* file */ if (!idf_magic(d)) { d = dirname(d); strcpy(b, d); } } d = dirname(d); b = basename(b); #ifdef _USE_UNPACK p = games_sw ? games_sw:game_local_games_path(1); fprintf(stderr,"Trying to install: %s\n", g); if (!unpack(g, p)) { if (!zip_game_dirname[0]) goto err; if (games_replace(p, zip_game_dirname)) goto clean; p = zip_game_dirname; } else if (zip_game_dirname[0]) { /* error, needs to clean */ goto clean; #else if (0) { #endif } else if (games_replace(d, b)) { goto err; } else p = b; if (game_init(p)) { game_error(); } return 0; #ifdef _USE_UNPACK clean: p = getpath(p, zip_game_dirname); fprintf(stderr, "Cleaning: '%s'...\n", p); remove_dir(p); free(p); err: game_error(); return -1; #endif } #endif static int game_input_events(struct inp_event *ev) { if (!curgame_dir) return 0; if (ev->type == KEY_DOWN || ev->type == KEY_UP) { #if defined(ANDROID) || defined(IOS) || defined(WINRT) if (!is_key(ev, "f12") && !menu_shown) /* f12 is keyboard toggle */ return 0; #endif if (!game_input((ev->type == KEY_DOWN), ev->sym, -1, -1, EV_CODE_KBD)) return 1; } else if (ev->type == FINGER_DOWN || ev->type == FINGER_UP) { if (!game_input((ev->type == FINGER_DOWN), ev->sym, ev->x, ev->y, EV_CODE_FINGER)) return 1; } else if (ev->type == MOUSE_DOWN || ev->type == MOUSE_UP) { if (!game_input((ev->type == MOUSE_DOWN), "mouse", ev->x, ev->y, ev->code)) return 1; } else if (ev->type == MOUSE_WHEEL_DOWN) { if (!game_input(1, "wheel", 0, ev->count, EV_CODE_WHEEL)) return 1; } else if (ev->type == MOUSE_WHEEL_UP) { if (!game_input(1, "wheel", 0, -ev->count, EV_CODE_WHEEL)) return 1; } else if (ev->type == KEY_TEXT) { if (!game_input(1, ev->sym, -1, -1, EV_CODE_TEXT)) return 1; } return 0; } static int alt_pressed = 0; static int shift_pressed = 0; static int control_pressed = 0; static int kbd_modifiers(struct inp_event *ev) { if (ev->type != KEY_DOWN && ev->type != KEY_UP) return 0; if (!is_key(ev, "left alt") || !is_key(ev, "right alt")) { alt_pressed = (ev->type == KEY_DOWN); return 1; } else if (!is_key(ev, "left shift") || !is_key(ev, "right shift")) { shift_pressed = (ev->type == KEY_DOWN); return 1; } else if (!is_key(ev, "left ctrl") || !is_key(ev, "right ctrl")) { control_pressed = (ev->type == KEY_DOWN); return 1; } return 0; } static int is_key_back(struct inp_event *ev) { if (!is_key(ev, "escape") #ifdef ANDROID || ev->code == 118 #endif ) return 0; return -1; } static int kbd_instead(struct inp_event *ev, int *x, int *y) { if (ev->type != KEY_DOWN) return 0; if (!is_key_back(ev)) { if (use_xref) disable_use(); else menu_toggle(-1); } else if (!is_key(ev, "f1")) { if (!menu_shown) menu_toggle(-1); } else if (!is_key(ev, "f2") && curgame_dir) { game_menu(menu_save); } else if (!is_key(ev, "f3") && curgame_dir) { game_menu(menu_load); } else if (!is_key(ev, "f8") && curgame_dir && !menu_shown) { if (game_saves_enabled()) game_save(9); } else if (!is_key(ev, "f9") && curgame_dir && !menu_shown) { if (game_saves_enabled()) { if (!access(game_save_path(0, 9), R_OK)) { if (!game_reset()) game_load(9); } } #if defined(ANDROID) || defined(IOS) || defined(WINRT) } else if (!is_key(ev, "f12") && curgame_dir && !menu_shown) { input_text(!(input_text(-1) > 0)); #endif } else if (!is_key(ev, "f5") && curgame_dir && !menu_shown) { mouse_reset(1); game_cmd("look", 0); } else if ((alt_pressed || control_pressed) && !is_key(ev, "r") && curgame_dir && !menu_shown && debug_sw) { mouse_reset(1); game_menu_act("/new"); shift_pressed = alt_pressed = control_pressed = 0; } else if (!is_key(ev, "f10") #ifdef ANDROID || ev->code == 270 #endif ) { #ifdef ANDROID return -1; #else game_menu(menu_askquit); #endif } else if ((alt_pressed | control_pressed) && (!is_key(ev, "q") || !is_key(ev, "f4"))) { game_running = 0; return -1; } else if (alt_pressed && (!is_key(ev, "enter") || !is_key(ev, "return"))) { int old_menu = (menu_shown) ? cur_menu: -1; shift_pressed = alt_pressed = control_pressed = 0; opt_fs ^= 1; game_restart(); if (old_menu != -1) game_menu(old_menu); } else if (!is_key(ev, "f4") && !alt_pressed && !standalone_sw) { #ifdef _USE_UNPACK #ifdef _USE_BROWSE mouse_reset(1); if (!game_from_disk()) { shift_pressed = alt_pressed = control_pressed = 0; } #endif #endif } else if (DIRECT_MODE && !menu_shown) { ; /* nothing todo */ } else if (!alt_pressed && (!is_key(ev, "return") || !is_key(ev, "enter") )) { gfx_cursor(x, y); game_highlight(-1, -1, 0); /* reset */ game_click(*x, *y, 0, 0); game_highlight(*x, *y, 1); /* hl on/off */ game_highlight(*x, *y, 0); if (game_click(*x, *y, 1, 0) == -1) { game_running = 0; return -1; } } else if (!is_key(ev, "tab")) { select_frame(shift_pressed); } else if (!is_key(ev, "up") || !is_key(ev, "down") || !is_key(ev, "[8]") || !is_key(ev, "[2]")) { int lm; int prev = !is_key(ev, "up") || !is_key(ev, "[8]"); if (opt_kbd == KBD_INVERSE) lm = (alt_pressed || shift_pressed); else lm = (!alt_pressed && !shift_pressed); if (menu_shown || lm) { if (select_ref(prev, 0)) { if (opt_kbd == KBD_SMART) { (prev)?game_scroll_up(1):game_scroll_down(1); select_ref(prev, 1); } else select_ref(prev, 1); } } else (prev)?game_scroll_up(1):game_scroll_down(1); } else if (!is_key(ev, "page up") || !is_key(ev, "[9]") || !is_key(ev, "page down") || !is_key(ev, "[3]")) { int lm; int prev = !is_key(ev, "page up") || !is_key(ev, "[9]"); if (opt_kbd == KBD_INVERSE) lm = (alt_pressed || shift_pressed); else lm = (!alt_pressed && !shift_pressed); if (menu_shown || lm) { if (select_ref(prev, 0) || select_ref(prev, 1)) { if (opt_kbd == KBD_SMART) { int s = (prev)?game_scroll_pup():game_scroll_pdown(); if (!s) select_ref(!prev, 1); } else select_ref(prev, 0); } } else { if (prev) game_scroll_pup(); else game_scroll_pdown(); } } else if (!is_key(ev, "left") || !is_key(ev, "[4]")) { select_ref(1, 0); } else if (!is_key(ev, "right") || !is_key(ev, "[6]")) { select_ref(0, 0); } else if (!is_key(ev, "backspace") && !menu_shown) { scroll_pup(el_scene); } else if (!is_key(ev, "space") && !menu_shown) { scroll_pdown(el_scene); } else return 0; return 1; } static int mouse_instead(struct inp_event *ev, int *x, int *y) { if (ev->type == MOUSE_DOWN) { if (ev->code != 1) disable_use(); else { game_highlight(-1, -1, 0); game_click(ev->x, ev->y, 0, 1); *x = ev->x; *y = ev->y; } } else if (ev->type == MOUSE_UP && ev->code == 1) { game_highlight(-1, -1, 0); if (game_click(ev->x, ev->y, 1, 1) == -1) return -1; } else if (ev->type == MOUSE_WHEEL_UP && !menu_shown) { game_scroll_up(ev->count); } else if (ev->type == MOUSE_WHEEL_DOWN && !menu_shown) { game_scroll_down(ev->count); } else if (ev->type == MOUSE_MOTION) { if (opt_motion && !motion_mode && click_el && MOTION_TIME && !scroll_possible(click_el->id, click_y - ev->y)) { motion_id = click_el->id; motion_y = click_y; motion_mode = 1; click_el = NULL; click_xref[0] = 0; } if (motion_mode) { motion_mode = 2; scroll_motion(motion_id, motion_y - ev->y); motion_y = ev->y; } /* game_highlight(ev.x, ev.y, 1); */ } return 0; } static __inline int game_cycle(void) { static int x = 0, y = 0, rc; struct inp_event ev; ev.x = -1; /* game_cursor(CURSOR_CLEAR); */ /* release bg */ if (((rc = input(&ev, 1)) == AGAIN) && !need_restart) { game_gfx_commit(1); return rc; } if (!rc || gfx_fading()) /* just skip */ return 0; if (rc == -1) {/* close */ goto out; } else if (game_input_events(&ev)) { /* kbd, mouse and touch -> pass in game */ ; /* all is done in game_input */ } else if (kbd_modifiers(&ev)) { /* ctrl, alt, shift */ ; /* got modifiers */ } else if ((rc = kbd_instead(&ev, &x, &y))) { /* ui keys */ if (rc < 0) goto out; } else if (DIRECT_MODE && !menu_shown) { ; /* nothing todo */ } else if ((rc = mouse_instead(&ev, &x, &y)) < 0) { /* ui mouse */ goto out; } if (gfx_fading()) /* just fading */ return 0; game_render_callback_redraw(); if (need_restart) { need_restart = 0; game_menu_act("/new"); } if ((!DIRECT_MODE || menu_shown)) { if (click_xref[0]) { game_highlight(x, y, 1); } else if (!motion_mode) { int x, y; gfx_cursor(&x, &y); game_highlight(x, y, 1); } } game_cursor(CURSOR_ON); if (instead_err()) { game_menu(menu_warning); } rc = 0; out: game_flip(); game_gfx_commit(rc < 0); if (rc < 0) game_render_callback_redraw(); return rc; } #ifdef __EMSCRIPTEN__ const char *em_beforeunload(int eventType, const void *reserved, void *userData) { if (curgame_dir) { game_event("quit"); if (opt_autosave) game_save(0); game_cfg_save(); } return NULL; } static void game_void_cycle(void) { int rc; while ((rc = game_cycle()) == AGAIN); if (rc < 0) { cfg_save(); if (curgame_dir) game_done(0); gfx_clear(0, 0, game_theme.w, game_theme.h); gfx_flip(); gfx_commit(); emscripten_cancel_main_loop(); emscripten_force_exit(1); } } #endif int game_loop(void) { #ifdef __EMSCRIPTEN__ emscripten_set_beforeunload_callback(NULL, em_beforeunload); emscripten_set_main_loop(game_void_cycle, 0, 0); return -1; #else while (game_running) { if (game_cycle() < 0) { break; } } #endif return 0; } extern int instead_bits_init(void); extern int instead_timer_init(void); extern int instead_sprites_init(void); extern int instead_sound_init(void); extern int instead_paths_init(void); int game_instead_extensions(void) { instead_bits_init(); instead_timer_init(); instead_sprites_init(); instead_sound_init(); instead_paths_init(); return 0; } instead-3.5.2+dfsg/src/game.h000066400000000000000000000115761467622671600157730ustar00rootroot00000000000000/* * Copyright 2009-2018 Peter Kosyh * * 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. * */ #ifndef __GAME_H__ #define __GAME_H__ #include #include "utils.h" #define SND_CHANNELS MIX_CHANNELS #ifndef GAMES_PATH #define GAMES_PATH "./games" #endif #define HZ 100 extern int game_grab_events; extern int game_wait_use; extern int game_running; extern int game_theme_changed; extern int nosound_sw; extern int debug_sw; extern int fullscreen_sw; extern int hires_sw; extern int window_sw; extern int nopause_sw; extern int nocursor_sw; extern int game_own_theme; /* current game has own theme */ extern char *games_sw; extern char game_cwd[PATH_MAX]; /* current game cwd */ extern char *curgame_dir; extern int vsync_sw; extern int resizable_sw; extern int scale_sw; extern int standalone_sw; extern char *render_sw; extern int dpi_sw; extern char *appdir(void); extern void game_clear(int x, int y, int w, int h); extern void game_clear_all(void); extern void game_redraw_all(void); extern char *game_local_games_path(int cr); extern char *game_local_themes_path(void); extern char *game_tmp_path(void); extern int game_theme_select(const char *name); extern int game_init(const char *game); extern void game_flip(void); extern int game_loop(void); extern void game_done(int err); extern char *game_reset_name(void); extern int game_load_theme(const char *path); extern int game_apply_theme(void); extern int game_use_theme(void); extern void game_release_theme(int force); extern int game_reset(void); extern int game_cfg_save(void); extern void game_music_player(void); extern void game_stop_mus(int ms); extern int game_change_vol(int d, int val); extern int game_change_hz(int hz); extern int games_lookup(const char *path); extern struct game *game_lookup(const char *name); extern int is_game(const char *games, const char *name); extern int games_remove(int nr); extern int games_replace(const char *path, const char *dir); extern int games_rename(void); extern void game_res_err_msg(const char *s, int alert); extern int game_error(void); extern int game_restart(void); extern int game_select(const char *name); extern void game_gfx_clip(void); extern void game_gfx_noclip(void); #define GAME_CMD_CLICK 1 #define GAME_CMD_FILE 2 #define GAME_CMD_NOHL 4 extern int game_cmd(char *cmd, int flags); extern void game_menu(int nr); /* select and show menu */ extern int game_menu_box(int show, const char *txt); /* show menu */ extern int game_menu_box_wh(const char *txt, int *w, int *h); extern int game_menu_box_width(int show, const char *txt, int width); extern void mouse_reset(int hl); extern int mouse_restore(void); extern int game_load(int nr); extern int game_save(int nr); extern int game_saves_enabled(void); extern char *game_cfg_path(void); extern char *game_save_path(int rc, int nr); extern char *game_locale(void); extern int game_freezed(void); extern int game_paused(void); extern char *open_file_dialog(void); extern int game_from_disk(void); extern int game_pict_modify(img_t p); extern int game_bg_modify(img_t p); extern int game_pict_coord(int *x, int *y, int *w, int *h); extern void menu_toggle(int menu); extern int menu_visible(void); extern void game_channel_finished(int channel); extern void sound_play_click(void); extern void *sound_get(const char *fname); extern void sound_put(void *sn); extern int game_tag_valid(const char *p); void game_gfx_commit(int sync); #define CURSOR_CLEAR -1 #define CURSOR_OFF 0 #define CURSOR_ON 1 #define CURSOR_DRAW 2 extern void game_cursor(int on); /* must be called with -1 before gfx change and 1 after, 2 - not update */ extern int game_cursor_show; struct game { char *path; char *name; char *author; char *version; char *info; char *dir; char *direction; /* char *api; */ int idf; }; extern struct game *games; extern int games_nr; extern unsigned long timer_counter; #endif instead-3.5.2+dfsg/src/graphics.c000066400000000000000000003414771467622671600166630ustar00rootroot00000000000000/* * Copyright 2009-2023 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" #include #include #include #ifdef _USE_HARFBUZZ #include #include #endif #include #include "SDL_rotozoom.h" #include "SDL_gfxBlitFunc.h" #include "SDL_gif.h" #define IMG_ANIM 1 struct _img_t { SDL_Surface *s; /* SDL_Texture *t; */ int flags; void *aux; }; #define Surf(p) (((p)?(((img_t)(p))->s):NULL)) #ifndef SDL_malloc #define SDL_malloc malloc #endif #ifndef SDL_free #define SDL_free free #endif static img_t screen = NULL; static cache_t images = NULL; static struct { const char *name; unsigned long val; } cnames[] = { {"aliceblue", 0xf0f8ff}, {"antiquewhite", 0xfaebd7}, {"aqua", 0x00ffff}, {"aquamarine", 0x7fffd4}, {"azure", 0xf0ffff}, {"beige", 0xf5f5dc}, {"bisque", 0xffe4c4}, {"black", 0x000000}, {"blanchedalmond", 0xffebcd}, {"blue", 0x0000ff}, {"blueviolet", 0x8a2be2}, {"brown", 0xa52a2a}, {"burlywood", 0xdeb887}, {"cadetblue", 0x5f9ea0}, {"chartreuse", 0x7fff00}, {"chocolate", 0xd2691e}, {"coral", 0xff7f50}, {"cornflowerblue", 0x6495ed}, {"cornsilk", 0xfff8dc}, {"crimson", 0xdc143c}, {"cyan", 0x00ffff}, {"darkblue", 0x00008b}, {"darkcyan", 0x008b8b}, {"darkgoldenrod", 0xb8860b}, {"darkgray", 0xa9a9a9}, {"darkgrey", 0xa9a9a9}, {"darkgreen", 0x006400}, {"darkkhaki", 0xbdb76b}, {"darkmagenta", 0x8b008b}, {"darkolivegreen", 0x556b2f}, {"darkorange", 0xff8c00}, {"darkorchid", 0x9932cc}, {"darkred", 0x8b0000}, {"darksalmon", 0xe9967a}, {"darkseagreen", 0x8fbc8f}, {"darkslateblue", 0x483d8b}, {"darkslategray", 0x2f4f4f}, {"darkslategrey", 0x2f4f4f}, {"darkturquoise", 0x00ced1}, {"darkviolet", 0x9400d3}, {"deeppink", 0xff1493}, {"deepskyblue", 0x00bfff}, {"dimgray", 0x696969}, {"dimgrey", 0x696969}, {"dodgerblue", 0x1e90ff}, {"feldspar", 0xd19275}, {"firebrick", 0xb22222}, {"floralwhite", 0xfffaf0}, {"forestgreen", 0x228b22}, {"fuchsia", 0xff00ff}, {"gainsboro", 0xdcdcdc}, {"ghostwhite", 0xf8f8ff}, {"gold", 0xffd700}, {"goldenrod", 0xdaa520}, {"gray", 0x808080}, {"grey", 0x808080}, {"green", 0x008000}, {"greenyellow", 0xadff2f}, {"honeydew", 0xf0fff0}, {"hotpink", 0xff69b4}, {"indianred", 0xcd5c5c}, {"indigo", 0x4b0082}, {"ivory", 0xfffff0}, {"khaki", 0xf0e68c}, {"lavender", 0xe6e6fa}, {"lavenderblush", 0xfff0f5}, {"lawngreen", 0x7cfc00}, {"lemonchiffon", 0xfffacd}, {"lightblue", 0xadd8e6}, {"lightcoral", 0xf08080}, {"lightcyan", 0xe0ffff}, {"lightgoldenrodyellow", 0xfafad2}, {"lightgray", 0xd3d3d3}, {"lightgrey", 0xd3d3d3}, {"lightgreen", 0x90ee90}, {"lightpink", 0xffb6c1}, {"lightsalmon", 0xffa07a}, {"lightseagreen", 0x20b2aa}, {"lightskyblue", 0x87cefa}, {"lightslateblue", 0x8470ff}, {"lightslategray", 0x778899}, {"lightslategrey", 0x778899}, {"lightsteelblue", 0xb0c4de}, {"lightyellow", 0xffffe0}, {"lime", 0x00ff00}, {"limegreen", 0x32cd32}, {"linen", 0xfaf0e6}, {"magenta", 0xff00ff}, {"maroon", 0x800000}, {"mediumaquamarine", 0x66cdaa}, {"mediumblue", 0x0000cd}, {"mediumorchid", 0xba55d3}, {"mediumpurple", 0x9370d8}, {"mediumseagreen", 0x3cb371}, {"mediumslateblue", 0x7b68ee}, {"mediumspringgreen", 0x00fa9a}, {"mediumturquoise", 0x48d1cc}, {"mediumvioletred", 0xc71585}, {"midnightblue", 0x191970}, {"mintcream", 0xf5fffa}, {"mistyrose", 0xffe4e1}, {"moccasin", 0xffe4b5}, {"navajowhite", 0xffdead}, {"navy", 0x000080}, {"oldlace", 0xfdf5e6}, {"olive", 0x808000}, {"olivedrab", 0x6b8e23}, {"orange", 0xffa500}, {"orangered", 0xff4500}, {"orchid", 0xda70d6}, {"palegoldenrod", 0xeee8aa}, {"palegreen", 0x98fb98}, {"paleturquoise", 0xafeeee}, {"palevioletred", 0xd87093}, {"papayawhip", 0xffefd5}, {"peachpuff", 0xffdab9}, {"peru", 0xcd853f}, {"pink", 0xffc0cb}, {"plum", 0xdda0dd}, {"powderblue", 0xb0e0e6}, {"purple", 0x800080}, {"red", 0xff0000}, {"rosybrown", 0xbc8f8f}, {"royalblue", 0x4169e1}, {"saddlebrown", 0x8b4513}, {"salmon", 0xfa8072}, {"sandybrown", 0xf4a460}, {"seagreen", 0x2e8b57}, {"seashell", 0xfff5ee}, {"sienna", 0xa0522d}, {"silver", 0xc0c0c0}, {"skyblue", 0x87ceeb}, {"slateblue", 0x6a5acd}, {"slategray", 0x708090}, {"slategrey", 0x708090}, {"snow", 0xfffafa}, {"springgreen", 0x00ff7f}, {"steelblue", 0x4682b4}, {"tan", 0xd2b48c}, {"teal", 0x008080}, {"thistle", 0xd8bfd8}, {"tomato", 0xff6347}, {"turquoise", 0x40e0d0}, {"violet", 0xee82ee}, {"violetred", 0xd02090}, {"wheat", 0xf5deb3}, {"white", 0xffffff}, {"whitesmoke", 0xf5f5f5}, {"yellow", 0xffff00}, {"yellowgreen", 0x9acd32}, {NULL, 0x0}, }; color_t gfx_col(int r, int g, int b) { color_t col; col.r = r; col.g = g; col.b = b; col.a = 0; return col; } int gfx_parse_color ( const char *spec, color_t *def) { int n, i; int r, g, b; char c; if (!spec) return -1; spec += strspn(spec, " \t"); n = strlen (spec); if (*spec == '#') { /* * RGB */ spec++; n--; if (n != 3 && n != 6 && n != 9 && n != 12) return -1; n /= 3; g = b = 0; do { r = g; g = b; b = 0; for (i = n; --i >= 0; ) { c = *spec++; b <<= 4; if (c >= '0' && c <= '9') b |= c - '0'; else if (c >= 'A' && c <= 'F') b |= c - ('A' - 10); else if (c >= 'a' && c <= 'f') b |= c - ('a' - 10); else return (0); } } while (*spec != '\0'); if (def) { def->r = r; def->g = g; def->b = b; } return 0; } for (i=0; cnames[i].name; i++) { if (!strcmp(cnames[i].name, spec)) { if (def) { def->r = (cnames[i].val & 0xff0000) >> 16; def->g = (cnames[i].val & 0x00ff00) >> 8; def->b = (cnames[i].val & 0x0000ff); } return 0; } } return -1; } struct _anim_t; struct anspawn { SDL_Rect clip; img_t bg; int x; int y; }; #define ANSPAWN_BLOCK 8 struct _anim_t { struct _anim_t *next; struct _anim_t *prev; int cur_frame; int nr_frames; int loop; int drawn; int active; unsigned long delay; int spawn_nr; struct anspawn *spawn; Animation_t *anim; }; typedef struct _anim_t *anim_t; static int anim_spawn(anim_t ag, int x, int y, int w, int h) { int nr; SDL_Rect clip; SDL_GetClipRect(Surf(screen), &clip); /* gfx_free_image(ag->bg); */ if (!ag->spawn && !(ag->spawn = malloc(ANSPAWN_BLOCK * sizeof(struct anspawn)))) return -1; nr = ag->spawn_nr + 1; if (!(nr % ANSPAWN_BLOCK)) { /* grow */ void *p = realloc(ag->spawn, ANSPAWN_BLOCK * sizeof(struct anspawn) * ((nr / ANSPAWN_BLOCK) + 1)); if (!p) return -1; ag->spawn = p; } ag->spawn[ag->spawn_nr].x = x; ag->spawn[ag->spawn_nr].y = y; ag->spawn[ag->spawn_nr].clip = clip; ag->spawn[ag->spawn_nr].bg = gfx_grab_screen(x, y, w, h); ag->spawn_nr = nr; return 0; } static anim_t anim_list = NULL; static int anim_drawn_nr = 0; static anim_t anim_find(anim_t g) { anim_t p; for (p = anim_list; p; p = p->next) { if (p == g) return p; } return NULL; } static void anim_disposal(anim_t g) { SDL_Rect dest; SDL_Rect clip; int i = 0; SDL_Surface *img = NULL; dest.x = 0; dest.y = 0; dest.w = g->anim->w; dest.h = g->anim->h; SDL_GetClipRect(Surf(screen), &clip); for (i = 0; i < g->spawn_nr; i++) { SDL_Rect dst; SDL_SetClipRect(Surf(screen), &g->spawn[i].clip); dst = dest; dst.x += g->spawn[i].x; dst.y += g->spawn[i].y; img = Surf(g->spawn[i].bg); if (img) { dst.w = img->w; dst.h = img->h; /* draw bg */ SDL_BlitSurface(img, NULL, Surf(screen), &dst); } } SDL_SetClipRect(Surf(screen), &clip); } static void anim_frame(anim_t g) { int i; SDL_Rect dest; SDL_Rect clip; SDL_Surface *frame; frame = g->anim->frames[g->cur_frame]; SDL_GetClipRect(Surf(screen), &clip); dest.w = g->anim->w; dest.h = g->anim->h; for (i = 0; i < g->spawn_nr; i++) { dest.x = g->spawn[i].x; dest.y = g->spawn[i].y; SDL_SetClipRect(Surf(screen), &g->spawn[i].clip); SDL_BlitSurface(frame, NULL, Surf(screen), &dest); } if (!g->active) /* initial draw */ g->delay = timer_counter; SDL_SetClipRect(Surf(screen), &clip); } static anim_t is_anim(img_t img) { if (img && (img->flags & IMG_ANIM)) return (anim_t)(img->aux); return NULL; } static anim_t anim_add(anim_t g) { anim_t p; p = anim_find(g); if (p) return p; if (!anim_list) { anim_list = g; g->next = NULL; g->prev = NULL; return g; } for (p = anim_list; p && p->next; p = p->next); p->next = g; g->next = NULL; g->prev = p; return g; } static anim_t anim_del(anim_t g) { if (g->prev == NULL) anim_list = g->next; else g->prev->next = g->next; if (g->next) g->next->prev = g->prev; return g; } static void anim_free_spawn(anim_t g) { int i; for (i = 0; i < g->spawn_nr; i++) gfx_free_image(g->spawn[i].bg); if (g->spawn) { free(g->spawn); g->spawn = NULL; g->spawn_nr = 0; } } static void anim_free(anim_t g) { FreeAnimation(g->anim); anim_free_spawn(g); free(g); } static void gfx_free_img(img_t p) { if (!p) return; SDL_FreeSurface(Surf(p)); /* todo texture */ SDL_free(p); } void gfx_free_image(img_t p) { anim_t ag; if (!p) return; if (!cache_forget(images, p)) return; /* cached sprite */ if ((ag = is_anim(p))) { if (ag->drawn) anim_drawn_nr --; anim_del(ag); anim_free(ag); return; } gfx_free_img(p); } void gfx_cache_free_image(void *p) { gfx_free_image((img_t)p); } int gfx_img_w(img_t pixmap) { if (!pixmap) return 0; return Surf(pixmap)->w; } int gfx_img_h(img_t pixmap) { if (!pixmap) return 0; return Surf(pixmap)->h; } void gfx_getclip(int *x, int *y, int *w, int *h) { SDL_Rect clip; if (!screen) return; SDL_GetClipRect(Surf(screen), &clip); if (x) *x = clip.x; if (y) *y = clip.y; if (w) *w = clip.w; if (h) *h = clip.h; } void gfx_img_noclip(img_t img) { SDL_SetClipRect(Surf(img), NULL); } void gfx_noclip(void) { gfx_img_noclip(screen); } void gfx_img_clip(img_t img, int x, int y, int w, int h) { SDL_Rect src; src.x = x; src.y = y; src.w = w; src.h = h; SDL_SetClipRect(Surf(img), &src); } void gfx_clip(int x, int y, int w, int h) { gfx_img_clip(screen, x, y, w, h); } #define GFX_IMG(v) gfx_new_img(v, 0, NULL, 0) #define GFX_IMG_REL(v) gfx_new_img(v, 0, NULL, 1) static img_t gfx_new_img(SDL_Surface *s, int fl, void *data, int release) { img_t i; if (!s) return NULL; i = SDL_malloc(sizeof(struct _img_t)); if (i) { i->s = s; /* i->t = NULL; */ i->flags = fl; i->aux = data; } else if (release && s) { SDL_FreeSurface(s); } return i; } img_t gfx_new_rgba(int w, int h) { SDL_Surface *dst; Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif dst = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, rmask, gmask, bmask, amask); if (dst) SDL_SetSurfaceBlendMode(dst, SDL_BLENDMODE_BLEND); if (dst) return GFX_IMG_REL(dst); return NULL; } img_t gfx_dup(img_t src) { SDL_Surface *dst; if (!src) return NULL; dst = SDL_ConvertSurface(Surf(src), Surf(src)->format, Surf(src)->flags); if (!dst) return NULL; return GFX_IMG_REL(dst); } img_t gfx_new_from(int w, int h, unsigned char *pixels) { SDL_Surface *dst; Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif dst = SDL_CreateRGBSurfaceFrom(pixels, w, h, 32, w * 4, rmask, gmask, bmask, amask); if (dst) SDL_SetSurfaceBlendMode(dst, SDL_BLENDMODE_BLEND); if (dst) return GFX_IMG_REL(dst); return NULL; } img_t gfx_new(int w, int h) { SDL_Surface *dst; if (!screen) { return gfx_new_rgba(w, h); } else { dst = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, Surf(screen)->format->BitsPerPixel, Surf(screen)->format->Rmask, Surf(screen)->format->Gmask, Surf(screen)->format->Bmask, Surf(screen)->format->Amask); } if (dst) SDL_SetSurfaceBlendMode(dst, SDL_BLENDMODE_NONE); if (dst) return GFX_IMG_REL(dst); return NULL; } void gfx_img_fill(img_t img, int x, int y, int w, int h, color_t col) { SDL_Rect dest; if (!img) return; dest.x = x; dest.y = y; dest.w = w; dest.h = h; SDL_FillRect(Surf(img), &dest, SDL_MapRGB((Surf(img))->format, col.r, col.g, col.b)); } void gfx_fill(int x, int y, int w, int h, color_t col) { gfx_img_fill(screen, x, y, w, h, col); } img_t gfx_screen(img_t nscreen) { img_t img; if (nscreen) { img = screen; screen = nscreen; return img; } return screen; } img_t gfx_grab_screen(int x, int y, int w, int h) { SDL_Rect dst, src; SDL_Surface *s; int a; img_t img; if (!screen) return NULL; s = SDL_CreateRGBSurface(Surf(screen)->flags, w, h, Surf(screen)->format->BitsPerPixel, Surf(screen)->format->Rmask, Surf(screen)->format->Gmask, Surf(screen)->format->Bmask, Surf(screen)->format->Amask); if (!s) return NULL; src.x = x; src.y = y; src.w = w; src.h = h; dst.x = 0; dst.y = 0; dst.w = w; dst.h = h; /* SDL_SetSurfaceBlendMode(screen, SDL_BLENDMODE_NONE); SDL_SetSurfaceBlendMode(img, SDL_BLENDMODE_NONE); */ a = gfx_unset_alpha(screen); SDL_BlitSurface(Surf(screen), &src, s, &dst); gfx_set_alpha(screen, a); img = GFX_IMG_REL(s); if (!img) return NULL; gfx_unset_alpha(img); return img; } static SDL_RendererInfo SDL_VideoRendererInfo; SDL_Surface *SDL_DisplayFormat(SDL_Surface * surface) { SDL_PixelFormat *format; SDL_Surface *converted; if (!screen) { fprintf(stderr, "No video mode has been set.\n"); return NULL; } format = Surf(screen)->format; converted = SDL_ConvertSurface(surface, format, 0); return converted; } SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface * surface) { SDL_Surface *converted; converted = SDL_DisplayFormat(surface); if (converted) SDL_SetSurfaceBlendMode(converted, SDL_BLENDMODE_BLEND); return converted; } img_t gfx_display_alpha(img_t src) { SDL_Surface* res; if (!src) return NULL; if (!screen) return src; if (is_anim(src)) /* already optimized */ return src; if (Surf(screen)->format == Surf(src)->format) { /* fast path! */ SDL_SetSurfaceBlendMode(Surf(src), SDL_BLENDMODE_BLEND); return src; } res = SDL_DisplayFormatAlpha(Surf(src)); if (!res) return src; gfx_free_image(src); return GFX_IMG_REL(res); } int gfx_get_pixel(img_t src, int x, int y, color_t *color) { Uint8 r, g, b, a; Uint32 col = 0; Uint8 *ptr; int bpp; SDL_Surface *img = Surf(src); if (!img) return -1; if (x >= img->w || y >= img->h || x < 0 || y < 0) return -1; if (SDL_LockSurface(img)) return -1; if (img->format) bpp = img->format->BytesPerPixel; else bpp = 1; /* hack? */ ptr = (Uint8*)img->pixels; ptr += img->pitch * y; ptr += x * bpp; memcpy(&col, ptr, bpp); SDL_UnlockSurface(img); if (color) SDL_GetRGBA(col, img->format, &r, &g, &b, &a); if (color) { color->r = r; color->g = g; color->b = b; color->a = a; } return 0; } int gfx_set_pixel(img_t src, int x, int y, color_t color) { int bpp; Uint32 col; Uint8 *ptr; SDL_Surface *img = Surf(src); if (!img) return -1; if (x >= img->w || y >= img->h || x < 0 || y < 0) return -1; if (SDL_LockSurface(img)) return -1; if (img->format) bpp = img->format->BytesPerPixel; else bpp = 1; /* hack? */ ptr = (Uint8*)img->pixels; ptr += img->pitch * y; ptr += x * bpp; col = SDL_MapRGBA(img->format, color.r, color.g, color.b, color.a); memcpy(ptr, &col, bpp); SDL_UnlockSurface(img); return 0; } void gfx_put_pixels(img_t src) { SDL_Surface *img = Surf(src); SDL_UnlockSurface(img); return; } unsigned char *gfx_get_pixels(img_t src) { Uint8 *ptr; SDL_Surface *img = Surf(src); if (!img) return NULL; if (SDL_LockSurface(img)) return NULL; ptr = (unsigned char*)img->pixels; return ptr; } img_t gfx_alpha_img(img_t src, int alpha) { Uint8 *ptr; Uint32 col; int size; int bpp; img_t img = NULL; if (!src) return NULL; if (screen) { SDL_Surface *s = SDL_DisplayFormatAlpha(Surf(src)); if (s) img = GFX_IMG_REL(s); } else img = gfx_new(Surf(src)->w, Surf(src)->h); if (!img) return NULL; if (Surf(img)->format) bpp = Surf(img)->format->BytesPerPixel; else bpp = 1; gfx_set_alpha(img, SDL_ALPHA_OPAQUE); if (SDL_LockSurface(Surf(img)) == 0) { int w = Surf(img)->w; ptr = (Uint8*)(Surf(img)->pixels); size = Surf(img)->w * Surf(img)->h; while (size --) { Uint8 r, g, b, a; memcpy(&col, ptr, bpp); SDL_GetRGBA(col, Surf(img)->format, &r, &g, &b, &a); col = SDL_MapRGBA(Surf(img)->format, r, g, b, a * alpha / SDL_ALPHA_OPAQUE); memcpy(ptr, &col, bpp); ptr += bpp; w --; if (!w) { w = Surf(img)->w; ptr += Surf(img)->pitch; ptr -= w * bpp; } } SDL_UnlockSurface(Surf(img)); } return img; } void gfx_set_colorkey(img_t src, color_t col) { Uint32 c; SDL_Surface *s = Surf(src); if (!s) return; c = SDL_MapRGB(s->format, col.r, col.g, col.b); SDL_SetColorKey(s, SDL_TRUE, c); /* gfx_unset_alpha(src); */ } void gfx_unset_colorkey(img_t src) { SDL_SetColorKey(Surf(src), SDL_FALSE, 0); /* gfx_set_alpha(src, SDL_ALPHA_OPAQUE); */ } void gfx_set_alpha(img_t src, int alpha) { if (alpha < 0) return; /* if (Surf(src)->format->Amask) alpha = SDL_ALPHA_OPAQUE; */ SDL_SetSurfaceAlphaMod(Surf(src), alpha); /* SDL_SetSurfaceBlendMode((SDL_Surface *)src, SDL_BLENDMODE_NONE); else */ SDL_SetSurfaceBlendMode(Surf(src), SDL_BLENDMODE_BLEND); } int gfx_unset_alpha(img_t src) { int alpha = -1; SDL_BlendMode blendMode; Uint8 sdl_alpha = SDL_ALPHA_OPAQUE; alpha = SDL_GetSurfaceBlendMode(Surf(src), &blendMode); if (blendMode == SDL_BLENDMODE_BLEND) { SDL_GetSurfaceAlphaMod(Surf(src), &sdl_alpha); alpha = sdl_alpha; } SDL_SetSurfaceAlphaMod(Surf(src), SDL_ALPHA_OPAQUE); SDL_SetSurfaceBlendMode(Surf(src), SDL_BLENDMODE_NONE); return alpha; } img_t gfx_combine(img_t src, img_t dst) { img_t new; SDL_Surface *s; s = SDL_DisplayFormatAlpha(Surf(dst)); if (!s) return NULL; new = GFX_IMG_REL(s); if (new) SDL_BlitSurface(Surf(src), NULL, Surf(new), NULL); return new; } static img_t img_pad(char *fname) { int l,r,t,b, rc; img_t img, img2; SDL_Rect to; char *p = fname; p += strcspn(p, ","); if (*p != ',') return NULL; p ++; rc = sscanf(fname, "%d %d %d %d,", &t, &r, &b, &l); if (rc == 1) { r = b = l = t; } else if (rc == 2) { b = t; l = r; } else if (rc == 3) { l = r; } else if (rc == 4) { ; } else return NULL; img = gfx_load_image(p); if (!img) return NULL; img2 = gfx_new(gfx_img_w(img) + l + r, gfx_img_h(img) + t + b); if (!img2) { gfx_free_image(img); return NULL; } else { img_t img = gfx_alpha_img(img2, 0); if (img) { gfx_free_image(img2); img2 = img; } } to.x = l; to.y = t; SDL_gfxBlitRGBA(Surf(img), NULL, Surf(img2), &to); gfx_free_image(img); return img2; } static img_t _gfx_load_combined_image(char *filename); /* blank:WxH */ static img_t _gfx_load_special_image(char *f, int combined) { int alpha = 0; int blank = 0; char *filename; img_t img, img2; char *pc = NULL, *pt = NULL; int wh[2] = { 0, 0 }; if (!f) return NULL; if (!(f = filename = strdup(f))) return NULL; if (!strncmp(filename, "blank:", 6)) { filename += 6; blank = 1; } else if (!strncmp(filename, "spr:", 4) && !combined) { /* filename += 4; */ img2 = cache_get(images, filename); /* fprintf(stderr, "get:%s %p\n", filename, img2); */ goto out; } else if (!strncmp(filename, "box:", 4)) { filename += 4; alpha = SDL_ALPHA_OPAQUE; } else if (!strncmp(filename, "pad:", 4)) { filename += 4; img2 = img_pad(filename); goto out; } else if (!strncmp(filename, "comb:", 5)) { filename += 5; img2 = _gfx_load_combined_image(filename); goto out; } else goto err; if (strchr(filename, ';')) goto err; /* combined */ if (blank) goto skip; pc = filename + strcspn(filename, ","); if (*pc == ',') { *pc = 0; pc ++; pt = pc + strcspn(pc, ","); if (*pt == ',') { *pt = 0; pt ++; } else pt = NULL; } else pc = NULL; skip: if (parse_mode(filename, wh)) goto err; if (wh[0] <= 0 || wh[1] <= 0) goto err; img = gfx_new(wh[0], wh[1]); if (!img) goto err; if (pc) { color_t col = { .r = 255, .g = 255, .b = 255 }; gfx_parse_color(pc, &col); gfx_img_fill(img, 0, 0, wh[0], wh[1], col); } if (pt) alpha = atoi(pt); img2 = gfx_alpha_img(img, alpha); gfx_free_image(img); out: free(f); return img2; err: free(f); return NULL; } cache_t gfx_image_cache(void) { return images; } static anim_t anim_new(Animation_t *anim) { anim_t ag = malloc(sizeof(struct _anim_t)); if (!ag) return NULL; memset(ag, 0, sizeof(struct _anim_t)); ag->anim = anim; ag->nr_frames = anim->count; ag->loop = anim->loop; return ag; } static anim_t anim_clone(anim_t ag) { int i; anim_t nag = malloc(sizeof(struct _anim_t)); if (!nag) return NULL; memcpy(nag, ag, sizeof(struct _anim_t)); nag->cur_frame = 0; nag->drawn = 0; nag->active = 0; nag->delay = 0; nag->spawn_nr = 0; nag->spawn = NULL; nag->anim = malloc(sizeof(Animation_t)); if (!nag->anim) goto err; memcpy(nag->anim, ag->anim, sizeof(Animation_t)); nag->anim->delays = malloc(sizeof(int) * nag->nr_frames); nag->anim->frames = malloc(sizeof(SDL_Surface *) * nag->nr_frames); if (!nag->anim->delays || !nag->anim->frames) goto err; for (i = 0; i < nag->nr_frames; i ++) { nag->anim->frames[i] = ag->anim->frames[i]; nag->anim->delays[i] = ag->anim->delays[i]; } return nag; err: if (nag->anim) { if (nag->anim->delays) free(nag->anim->delays); if (nag->anim->frames) free(nag->anim->frames); free(nag->anim); } free(nag); return NULL; } static img_t _gfx_load_image(char *filename, int combined) { SDL_RWops *rw; img_t img; Animation_t *anim = NULL; filename = strip(filename); img = _gfx_load_special_image(filename, combined); if (img) return img; if (strstr(filename,".gif") || strstr(filename,".GIF")) /* only agif now */ anim = GIF_LoadAnim(filename); if (anim) { /* animation logic */ anim_t ag = anim_new(anim); if (!ag) return NULL; anim_add(ag); img = gfx_new_img(ag->anim->frames[0], IMG_ANIM, ag, 0); if (!img) { anim_del(ag); anim_free(ag); } return img; } rw = RWFromIdf(instead_idf(), filename); if (!rw || !(img = GFX_IMG_REL(IMG_Load_RW(rw, 1)))) return NULL; if (Surf(img)->format->BitsPerPixel == 32) { /* hack for 32 bit BMP :( */ SDL_RWops *rwop; rwop = RWFromIdf(instead_idf(), filename); if (rwop) { if (IMG_isBMP(rwop)) /* SDL_SetAlpha(img, 0, SDL_ALPHA_OPAQUE); */ gfx_unset_alpha(img); SDL_RWclose(rwop); } } img = gfx_display_alpha(img); return img; } /* x.png;a.png@1,2;b.png@3,4 */ static img_t _gfx_load_combined_image(char *filename) { char *str; char *p, *ep; img_t base = NULL, img = NULL; p = str = strdup(filename); if (!str) return NULL; ep = p + strcspn(p, ";"); if (*ep != ';') goto err; /* first image is a base image */ *ep = 0; base = _gfx_load_image(strip(p), 1); if (!base) goto err; p = ep + 1; while (*p) { int x = 0, y = 0, c = 0; SDL_Rect to; ep = p + strcspn(p, ";@"); if (*ep == '@') { *ep = 0; ep ++; if (*ep == 'c') { c = 1; ep ++; } sscanf(ep, "%d,%d", &x, &y); ep += strcspn(ep, ";"); if (*ep) ep ++; } else if (*ep == ';') { *ep = 0; ep ++; } else if (*ep) { goto err; } img = _gfx_load_image(strip(p), 1); if (!img) goto err; to.x = x; to.y = y; if (c) { to.x -= gfx_img_w(img) / 2; to.y -= gfx_img_h(img) / 2; } to.w = to.h = 0; SDL_gfxBlitRGBA(Surf(img), NULL, Surf(base), &to); gfx_free_image(img); p = ep; } free(str); return base; err: gfx_free_image(base); free(str); return NULL; } img_t gfx_load_image(char *filename) { img_t img = NULL; if (!filename) return NULL; /* if (!access(filename, R_OK)) */ img = _gfx_load_image(filename, 0); if (!img) img = _gfx_load_combined_image(filename); return img; } void gfx_draw_bg(img_t p, int x, int y, int width, int height) { int a; SDL_Surface *pixbuf = Surf(p); SDL_Rect dest, src; if (!p) return; src.x = x; src.y = y; src.w = width; src.h = height; dest.x = x; dest.y = y; dest.w = width; dest.h = height; a = gfx_unset_alpha(p); SDL_BlitSurface(pixbuf, &src, Surf(screen), &dest); gfx_set_alpha(p, a); } void gfx_draw_from_alpha(img_t s, int x, int y, int w, int h, img_t d, int xx, int yy, int alpha) { SDL_BlendMode blendMode; Uint8 sdl_alpha = SDL_ALPHA_OPAQUE; SDL_GetSurfaceBlendMode(Surf(s), &blendMode); SDL_GetSurfaceAlphaMod(Surf(s), &sdl_alpha); SDL_SetSurfaceAlphaMod(Surf(s), alpha); SDL_SetSurfaceBlendMode(Surf(s), SDL_BLENDMODE_BLEND); gfx_draw_from(s, x, y, w, h, d, xx, yy); SDL_SetSurfaceBlendMode(Surf(s), blendMode); SDL_SetSurfaceAlphaMod(Surf(s), sdl_alpha); } void gfx_draw_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy) { SDL_Surface *pixbuf = Surf(p); SDL_Surface *scr = Surf(to); SDL_Rect dest, src; if (!p) return; if (!scr) scr = Surf(screen); src.x = x; src.y = y; src.w = width; src.h = height; dest.x = xx; dest.y = yy; dest.w = width; dest.h = height; SDL_BlitSurface(pixbuf, &src, scr, &dest); } void gfx_compose_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy) { SDL_Surface *pixbuf = Surf(p); SDL_Surface *scr = Surf(to); SDL_Rect dest, src; if (!scr) scr = Surf(screen); src.x = x; src.y = y; src.w = width; src.h = height; dest.x = xx; dest.y = yy; dest.w = width; dest.h = height; SDL_gfxBlitRGBA(pixbuf, &src, scr, &dest); } void gfx_copy(img_t p, int x, int y) { int a; SDL_Surface *pixbuf = Surf(p); SDL_Rect dest; if (!p) return; dest.x = x; dest.y = y; dest.w = pixbuf->w; dest.h = pixbuf->h; a = gfx_unset_alpha(p); SDL_BlitSurface(pixbuf, NULL, Surf(screen), &dest); gfx_set_alpha(p, a); } void gfx_copy_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy) { int a; SDL_Surface *pixbuf = Surf(p); SDL_Surface *scr = Surf(to); SDL_Rect dest, src; if (!p) return; if (!scr) scr = Surf(screen); src.x = x; src.y = y; src.w = width; src.h = height; dest.x = xx; dest.y = yy; dest.w = width; dest.h = height; a = gfx_unset_alpha(p); SDL_BlitSurface(pixbuf, &src, scr, &dest); gfx_set_alpha(p, a); } void gfx_draw(img_t p, int x, int y) { anim_t ag; SDL_Surface *pixbuf = Surf(p); SDL_Rect dest; if (!p) return; dest.x = x; dest.y = y; dest.w = pixbuf->w; dest.h = pixbuf->h; if (!DIRECT_MODE) /* no anim in direct mode */ ag = is_anim(p); else ag = NULL; if (ag) { anim_spawn(ag, x, y, dest.w, dest.h); if (!ag->drawn) anim_drawn_nr ++; anim_frame(ag); ag->drawn = 1; ag->active = 1; return; } SDL_BlitSurface(pixbuf, NULL, Surf(screen), &dest); } void gfx_stop_anim(img_t p) { anim_t ag; ag = is_anim(p); if (ag) ag->active = 0; } void gfx_dispose_anim(img_t p) { anim_t ag; ag = is_anim(p); if (ag) { if (ag->drawn) anim_drawn_nr --; ag->drawn = 0; anim_free_spawn(ag); } } void gfx_start_anim(img_t p) { anim_t ag; ag = is_anim(p); if (ag) ag->active = 1; } int gfx_frame_anim(img_t img) { anim_t ag; ag = is_anim(img); if (!ag) return 0; if (!ag->drawn || !ag->active) return 0; if (ag->loop == -1) return 0; if ((int)(timer_counter - ag->delay) < (ag->anim->delays[ag->cur_frame] / HZ)) return 0; if (ag->cur_frame != ag->nr_frames - 1 || ag->loop > 1 || !ag->loop) anim_disposal(ag); ag->cur_frame ++; if (ag->cur_frame >= ag->nr_frames) { if (!ag->loop || ag->loop > 1) ag->cur_frame = 0; else ag->cur_frame --; /* last one */ if (ag->loop) { ag->loop --; if (!ag->loop) ag->loop = -1; /* disabled */ } } if (ag->loop != -1) { anim_frame(ag); ag->delay = timer_counter; } return 1; } int gfx_is_drawn_anims(void) { return anim_drawn_nr; } void gfx_update_anim(img_t img, update_fn update) { int i = 0; anim_t ag; ag = is_anim(img); if (!ag) return; if (!ag->drawn || !ag->active) return; for (i = 0; i < ag->spawn_nr; i++) { update(ag->spawn[i].x, ag->spawn[i].y, gfx_img_w(img), gfx_img_h(img)); } } void gfx_draw_wh(img_t p, int x, int y, int w, int h) { SDL_Surface *pixbuf = Surf(p); SDL_Rect dest, src; src.x = 0; src.y = 0; src.w = w; src.h = h; dest.x = x; dest.y = y; dest.w = w; dest.h = h; SDL_BlitSurface(pixbuf, &src, Surf(screen), &dest); } static SDL_Color bgcol = { .r = 0, .g = 0, .b = 0 }; static SDL_Color brdcol = { .r = 0, .g = 0, .b = 0 }; static SDL_Rect brd = { .x = 0, .y = 0, .w = -1, .h = -1 }; void gfx_bg(int x, int y, int w, int h, color_t col, color_t bcol) { brd.x = x; brd.y = y; brd.w = w; brd.h = h; bgcol.r = col.r; bgcol.g = col.g; bgcol.b = col.b; brdcol.r = bcol.r; brdcol.g = bcol.g; brdcol.b = bcol.b; } void gfx_clear(int x, int y, int w, int h) { int dx, dy; SDL_Rect dest; SDL_Surface *s = Surf(screen); if (!s) return; dest.x = x; dest.y = y; dest.w = w; dest.h = h; if (x < brd.x || y < brd.y || x + w >= brd.x + brd.w || y + h >= brd.y + brd.h) { SDL_FillRect(s, &dest, SDL_MapRGB(s->format, brdcol.r, brdcol.g, brdcol.b)); dx = brd.x - x; dy = brd.y - y; if (dx > 0) { dest.x += dx; dest.w -= dx; } if (dy > 0) { dest.y += dy; dest.h -= dy; } dx = (brd.x + brd.w) - (dest.x + dest.w); dy = (brd.y + brd.h) - (dest.y + dest.h); if (dx < 0) dest.w += dx; if (dy < 0) dest.h += dy; if (dest.w > 0 && dest.h > 0) SDL_FillRect(s, &dest, SDL_MapRGB(s->format, bgcol.r, bgcol.g, bgcol.b)); } else SDL_FillRect(s, &dest, SDL_MapRGB(s->format, bgcol.r, bgcol.g, bgcol.b)); } int gfx_width = -1; int gfx_height = -1; int gfx_fs = -1; static SDL_Rect** vid_modes = NULL; static SDL_Rect m640x480 = { .w = 640, .h = 480 }; static SDL_Rect m800x480 = { .w = 800, .h = 480 }; static SDL_Rect m800x600 = { .w = 800, .h = 600 }; static SDL_Rect m1024x768 = { .w = 1024, .h = 768 }; static SDL_Rect m1280x800 = { .w = 1280, .h = 800 }; static SDL_Rect* std_modes[] = { &m640x480, &m800x480, &m800x600, &m1024x768, &m1280x800, NULL }; static int SDL_CurrentDisplay = 0; static void SelectVideoDisplay() { const char *variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_DISPLAY"); if ( !variable ) { variable = SDL_getenv("SDL_VIDEO_FULLSCREEN_HEAD"); } if ( variable ) { SDL_CurrentDisplay = SDL_atoi(variable); } } static SDL_Rect **SDL_ListModes(const SDL_PixelFormat * format, Uint32 flags) { SDL_DisplayMode disp_mode; int i, nmodes; SDL_Rect **modes; SDL_Rect **new_modes; Uint32 Rmask, Gmask, Bmask, Amask; int bpp; SelectVideoDisplay(); SDL_GetDesktopDisplayMode(SDL_CurrentDisplay, &disp_mode); SDL_PixelFormatEnumToMasks(disp_mode.format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); if (format) bpp = format->BitsPerPixel; nmodes = 0; modes = NULL; for (i = 0; i < SDL_GetNumDisplayModes(SDL_CurrentDisplay); ++i) { SDL_DisplayMode mode; if (SDL_GetDisplayMode(SDL_CurrentDisplay, i, &mode) < 0) continue; if (!mode.w || !mode.h) { continue; } /* fprintf(stderr, "Mode: %d %d %d %d\n", bpp, SDL_BITSPERPIXEL(mode.format), mode.w, mode.h); */ if ((unsigned int)bpp < SDL_BITSPERPIXEL(mode.format)) { continue; } if (mode.w > disp_mode.w || mode.h > disp_mode.h) { /* skip large modes */ if (mode.w > disp_mode.h || mode.h > disp_mode.w) /* landscape ? */ continue; } if (nmodes > 0 && modes[nmodes - 1]->w == mode.w && modes[nmodes - 1]->h == mode.h) { continue; } new_modes = SDL_realloc(modes, (nmodes + 2) * sizeof(*modes)); if (!new_modes) goto out; modes = new_modes; modes[nmodes] = (SDL_Rect *) SDL_malloc(sizeof(SDL_Rect)); if (!modes[nmodes]) goto out; modes[nmodes]->x = 0; modes[nmodes]->y = 0; modes[nmodes]->w = mode.w; modes[nmodes]->h = mode.h; ++nmodes; } if (!modes) /* no modes found */ return (SDL_Rect **) (-1); if (modes) { modes[nmodes] = NULL; } return modes; out: for (i = 0; i < nmodes; i++) SDL_free(modes[i]); SDL_free(modes); return NULL; } extern char *modes_sw; static int gfx_parse_modes(void) { const char *p = modes_sw; int nr = 0; int mode[2]; int i = 0; if (!modes_sw) return 0; while (*p) { p += strcspn(p, ","); if (*p) p ++; nr ++; } if (!nr) return 0; vid_modes = SDL_malloc(sizeof(SDL_Rect *) * (nr + 1)); /* array of pointers */ if (!vid_modes) return 0; p = modes_sw; nr = 0; while (*p) { char m[64]; SDL_Rect *r; size_t s; s = strcspn(p, ","); memset(m, 0, sizeof(m)); memcpy(m, p, (s > sizeof(m))? sizeof(m): s); m[sizeof(m) - 1] = 0; if (parse_mode(m, &mode)) break; r = SDL_malloc(sizeof(SDL_Rect)); if (!r) goto err; vid_modes[nr ++] = r; r->w = mode[0]; r->h = mode[1]; fprintf(stderr, "Available mode: %dx%d\n", r->w, r->h); p += strcspn(p, ","); if (*p) p ++; } vid_modes[nr] = NULL; return nr; err: for (i = 0; i < nr; i++) { SDL_free(vid_modes[i]); } SDL_free(vid_modes); vid_modes = NULL; return 0; } int gfx_modes(void) { int i = 0; SDL_Rect** modes; if ((i = gfx_parse_modes())) return i; modes = SDL_ListModes(NULL, 0); if (modes == (SDL_Rect**)0)/* no modes */ return 0; if (modes == (SDL_Rect**)-1) { vid_modes = std_modes; return 5; } for (i = 0; modes[i]; ++i); vid_modes = modes; return i; } int gfx_get_mode(int n, int *w, int *h) { if (!vid_modes) gfx_modes(); if (!vid_modes || !vid_modes[n]) return -1; if (w) *w = vid_modes[n]->w; if (h) *h = vid_modes[n]->h; return 0; } int gfx_prev_mode(int *w, int *h) { int ww, hh, i = 0; if (!w || !h) return -1; while ((*w != -1 && *h != -1) && !gfx_get_mode(i, &ww, &hh)) { if (ww == *w && hh == *h) break; i ++; } if (*w == -1 || *h == -1) i = gfx_modes(); if (!i) return -1; i --; if (gfx_get_mode(i, &ww, &hh)) return -1; *w = ww; *h = hh; return 0; } int gfx_next_mode(int *w, int *h) { int ww, hh, i = 0; if (!w || !h) return -1; while ((*w != -1 && *h != -1) && !gfx_get_mode(i, &ww, &hh)) { i ++; if (ww == *w && hh == *h) break; } if (gfx_get_mode(i, &ww, &hh)) return -1; *w = ww; *h = hh; return 0; } #if defined(ANDROID) || defined(IOS) static int current_gfx_w = - 1; static int current_gfx_h = - 1; #endif #if defined(ANDROID) extern void get_screen_size(int *w, int *h); #endif int gfx_get_max_mode(int *w, int *h, int o) { int ww = 0, hh = 0; int i = 0; SDL_DisplayMode desktop_mode; #if defined(ANDROID) if (o == MODE_ANY) { get_screen_size(w, h); return 0; } #elif defined(IOS) if (o == MODE_ANY && current_gfx_w != -1) { *w = current_gfx_w; *h = current_gfx_h; return 0; } #endif #ifdef _USE_SWROTATE if (!SDL_GetDesktopDisplayMode(SDL_CurrentDisplay, &desktop_mode)) { if ((o == MODE_H && desktop_mode.w < desktop_mode.h) || (o == MODE_V && desktop_mode.w > desktop_mode.h)) { *w = desktop_mode.h; *h = desktop_mode.w; } else { *w = desktop_mode.w; *h = desktop_mode.h; } return 0; } #endif if (o == MODE_ANY && !SDL_GetDesktopDisplayMode(SDL_CurrentDisplay, &desktop_mode)) { *w = desktop_mode.w; *h = desktop_mode.h; return 0; } *w = 0; *h = 0; if (!vid_modes) gfx_modes(); if (!vid_modes) return -1; while (!gfx_get_mode(i, &ww, &hh)) { if ((ww * hh >= (*w) * (*h))) { if (o == MODE_ANY || (o == MODE_H && ww >= hh) || (o == MODE_V && hh > ww)) { *w = ww; *h = hh; } } i ++; } if (*w == 0 || *h == 0) /* no suitable mode */ return -1; return 0; } int gfx_check_mode(int w, int h) { #if defined(IOS) || defined(ANDROID) return 0; #else int ww = 0, hh = 0; int i = 0; if (!vid_modes) gfx_modes(); if (!vid_modes) return -1; while (!gfx_get_mode(i, &ww, &hh)) { if (ww == w && hh == h) return 0; i ++; } return -1; #endif } static SDL_Surface *icon = NULL; extern int software_sw; extern int glhack_sw; #ifdef _USE_SWROTATE static int gfx_flip_rotate = 0; #endif SDL_Window *SDL_VideoWindow = NULL; static SDL_Texture *SDL_VideoTexture = NULL; static SDL_Surface *SDL_VideoSurface = NULL; static SDL_Renderer *Renderer = NULL; static void GetEnvironmentWindowPosition(int w, int h, int *x, int *y) { const char *window = SDL_getenv("SDL_VIDEO_WINDOW_POS"); const char *center = SDL_getenv("SDL_VIDEO_CENTERED"); if (window) { if (SDL_sscanf(window, "%d,%d", x, y) == 2) { return; } if (SDL_strcmp(window, "center") == 0) { center = window; } } if (center) { SDL_DisplayMode mode; SDL_GetDesktopDisplayMode(SDL_CurrentDisplay, &mode); *x = (mode.w - w) / 2; *y = (mode.h - h) / 2; } } static SDL_Surface *CreateVideoSurface(SDL_Texture * texture) { SDL_Surface *surface; Uint32 format; int w, h; int bpp; Uint32 Rmask, Gmask, Bmask, Amask; /* void *pixels; int pitch; */ if (SDL_QueryTexture(texture, &format, NULL, &w, &h) < 0) { return NULL; } if (!SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { fprintf(stderr, "Unknown texture format.\n"); return NULL; } surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask); SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE); return surface; } static int mouse_x = -1; static int mouse_y = -1; static int mouse_watcher(void *userdata, SDL_Event *event) { #ifdef _USE_SWROTATE if (gfx_flip_rotate) { switch (event->type) { case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: mouse_y = gfx_height - event->button.x; mouse_x = event->button.y; event->button.x = mouse_x; event->button.y = mouse_y; break; case SDL_MOUSEMOTION: mouse_y = gfx_height - event->motion.x; mouse_x = event->motion.y; event->motion.x = mouse_x; event->motion.y = mouse_y; break; case SDL_FINGERMOTION: case SDL_FINGERUP: case SDL_FINGERDOWN: #ifdef SAILFISHOS /* sailfish has broken touch events */ mouse_x = event->tfinger.y; mouse_y = gfx_height - event->tfinger.x; #endif break; default: break; } return 0; } #endif switch (event->type) { case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: mouse_x = event->button.x; mouse_y = event->button.y; break; case SDL_MOUSEMOTION: mouse_x = event->motion.x; mouse_y = event->motion.y; break; default: break; } return 0; } void gfx_real_size(int *ww, int *hh) { int w, h; SDL_GetWindowSize(SDL_VideoWindow, &w, &h); if (ww) *ww = w; if (hh) *hh = h; } void gfx_finger_pos_scale(float x, float y, int *ox, int *oy, int norm) { int xx = 0, yy = 0; #ifndef SAILFISHOS int w, h; float sx, sy; SDL_Rect rect; if (!norm) { /* do not normalize? */ w = gfx_width; h = gfx_height; sx = 1.0f; sy = 1.0f; rect.x = 0; rect.y = 0; } else { SDL_GetWindowSize(SDL_VideoWindow, &w, &h); SDL_RenderGetViewport(Renderer, &rect); SDL_RenderGetScale(Renderer, &sx, &sy); } if (sx != 0) { x = x * w; xx = x / sx - rect.x; } if (sy != 0) { y = y * h; yy = y / sy - rect.y; } #else xx = (int)x; /* broken touch in SFOS */ yy = (int)y; #endif #ifdef _USE_SWROTATE if (gfx_flip_rotate) { if (ox) *ox = yy; if (oy) *oy = gfx_height - xx; } else { #endif if (ox) *ox = xx; if (oy) *oy = yy; #ifdef _USE_SWROTATE } #endif } #ifdef _USE_SWROTATE void rotate_landscape(void) { SDL_DisplayMode desktop_mode; SDL_GetDesktopDisplayMode(SDL_CurrentDisplay, &desktop_mode); gfx_flip_rotate = (desktop_mode.w < desktop_mode.h); #ifdef SAILFISHOS SDL_SetHint(SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION, "landscape"); #endif } void rotate_portrait(void) { SDL_DisplayMode desktop_mode; SDL_GetDesktopDisplayMode(SDL_CurrentDisplay, &desktop_mode); gfx_flip_rotate = (desktop_mode.w > desktop_mode.h); #ifdef SAILFISHOS SDL_SetHint(SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION, "portrait"); #endif } void unlock_rotation(void) { gfx_flip_rotate = 0; #ifdef SAILFISHOS SDL_SetHint(SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION, "primary"); #endif } #endif int gfx_set_mode(int w, int h, int fs) { int i; int vsync = SDL_RENDERER_PRESENTVSYNC; int window_x = SDL_WINDOWPOS_UNDEFINED; int window_y = SDL_WINDOWPOS_UNDEFINED; int win_w; int win_h; int sw_fallback = 0; int max_mode_w = 0; int max_mode_h = 0; SDL_DisplayMode desktop_mode; char title[4096]; char *t; strcpy(title, "INSTEAD - " ); strcat(title, VERSION ); win_w = w * scale_sw; win_h = h * scale_sw; gfx_get_max_mode(&max_mode_w, &max_mode_h, MODE_ANY); /* get current window size */ #if defined(IOS) || defined(ANDROID) || defined(SAILFISHOS) || defined(WINRT) fs = 1; /* always fs for mobiles */ #endif if (fs && !software_sw) { win_w = max_mode_w; win_h = max_mode_h; } if (gfx_width == w && gfx_height == h && gfx_fs == fs) { game_reset_name(); #if defined(ANDROID) if (SDL_VideoWindow) /* see gfx_set_mode call from input.c */ #else if (SDL_VideoWindow && !fs) #endif SDL_SetWindowSize(SDL_VideoWindow, win_w, win_h); goto done; /* already done */ } SelectVideoDisplay(); SDL_GetDesktopDisplayMode(SDL_CurrentDisplay, &desktop_mode); if (vid_modes && vid_modes != std_modes) { for (i = 0; vid_modes[i]; i++) SDL_free(vid_modes[i]); SDL_free(vid_modes); } vid_modes = NULL; if (screen) gfx_free_image(screen); /* if (SDL_VideoTexture) SDL_DestroyTexture(SDL_VideoTexture); */ if (Renderer) SDL_DestroyRenderer(Renderer); screen = NULL; Renderer = NULL; SDL_VideoTexture = NULL; if (SDL_VideoWindow) { SDL_GetWindowPosition(SDL_VideoWindow, &window_x, &window_y); SDL_DestroyWindow(SDL_VideoWindow); SDL_VideoWindow = NULL; if ((gfx_fs == 1 && !fs) || (window_x == 0 || window_y == 0)) { /* return from fullscreen */ window_x = SDL_WINDOWPOS_CENTERED; window_y = SDL_WINDOWPOS_CENTERED; } } else GetEnvironmentWindowPosition(win_w, win_h, &window_x, &window_y); if (desktop_mode.w <= win_w || fs) window_x = 0; if (desktop_mode.h <= win_h || fs) window_y = 0; t = game_reset_name(); if (!t) t = title; if (glhack_sw) { fprintf(stderr, "glhack: %d\n", glhack_sw); /* fix for hackish samsung devices */ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, (glhack_sw / 100) % 10); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, (glhack_sw / 10) % 10); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, glhack_sw % 10); } #if defined(IOS) || defined(ANDROID) || defined(SAILFISHOS) || defined(WINRT) SDL_VideoWindow = SDL_CreateWindow(t, window_x, window_y, win_w, win_h, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE #if defined(ANDROID) | SDL_WINDOW_FULLSCREEN_DESKTOP #endif ); if (!SDL_VideoWindow) { fprintf(stderr, "Fallback to software window.\n"); SDL_VideoWindow = SDL_CreateWindow(t, window_x, window_y, win_w, win_h, SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE); } #else if (!software_sw) /* try to using scale */ SDL_VideoWindow = SDL_CreateWindow(t, window_x, window_y, win_w, win_h, SDL_WINDOW_SHOWN | ((fs)?SDL_WINDOW_FULLSCREEN:(resizable_sw?SDL_WINDOW_RESIZABLE:0)) | SDL_WINDOW_OPENGL); if (!SDL_VideoWindow) { /* try simple window */ fprintf(stderr, "Fallback to software window.\n"); win_w = w; win_h = h; SDL_VideoWindow = SDL_CreateWindow(t, window_x, window_y, win_w, win_h, SDL_WINDOW_SHOWN | ((fs)?SDL_WINDOW_FULLSCREEN:0)); } #endif if (SDL_VideoWindow == NULL) { fprintf(stderr, "Unable to create %dx%d window: %s\n", win_w, win_h, SDL_GetError()); return -1; } if (icon) SDL_SetWindowIcon(SDL_VideoWindow, icon); if (SDL_SetWindowDisplayMode(SDL_VideoWindow, (fs)?NULL:&desktop_mode) < 0) { fprintf(stderr, "Unable to set display mode: %s\n", SDL_GetError()); /* return -1; */ } if (!vsync_sw) vsync = 0; retry: if (software_sw || (!(Renderer = SDL_CreateRenderer(SDL_VideoWindow, -1, SDL_RENDERER_ACCELERATED | vsync | SDL_RENDERER_TARGETTEXTURE)) && !(Renderer = SDL_CreateRenderer(SDL_VideoWindow, -1, SDL_RENDERER_ACCELERATED)))) { fprintf(stderr, "Fallback to software renderer.\n"); sw_fallback = 1; if (!(Renderer = SDL_CreateRenderer(SDL_VideoWindow, -1, SDL_RENDERER_SOFTWARE))) { fprintf(stderr, "Unable to create renderer: %s\n", SDL_GetError()); return -1; } } SDL_GetRendererInfo(Renderer, &SDL_VideoRendererInfo); SDL_VideoTexture = SDL_CreateTexture(Renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h); if (!SDL_VideoTexture) { fprintf(stderr, "Unable to create texture: %s\n", SDL_GetError()); if (!sw_fallback) { /* one more chance */ SDL_DestroyRenderer(Renderer); software_sw = 1; goto retry; } return -1; } SDL_VideoSurface = CreateVideoSurface(SDL_VideoTexture); if (!SDL_VideoSurface) { fprintf(stderr, "Unable to create screen surface: %s\n", SDL_GetError()); return -1; } /* Set a default screen palette */ #if 0 if (SDL_VideoSurface->format->palette) { /* SDL_VideoSurface->flags |= SDL_HWPALETTE; SDL_DitherColors(SDL_VideoSurface->format->palette->colors, SDL_VideoSurface->format->BitsPerPixel); SDL_AddPaletteWatch(SDL_VideoSurface->format->palette, SDL_VideoPaletteChanged, SDL_VideoSurface); */ SDL_SetPaletteColors(SDL_VideoSurface->format->palette, SDL_VideoSurface->format->palette->colors, 0, SDL_VideoSurface->format->palette->ncolors); } #endif if (!nocursor_sw) SDL_ShowCursor(SDL_DISABLE); gfx_fs = fs; gfx_width = w; gfx_height = h; screen = GFX_IMG_REL(SDL_VideoSurface); if (!screen) { fprintf(stderr, "Can't alloc screen!\n"); return -1; } #ifdef _USE_SWROTATE if (gfx_flip_rotate) SDL_RenderSetLogicalSize(Renderer, h, w); else #endif SDL_RenderSetLogicalSize(Renderer, w, h); SDL_DelEventWatch(mouse_watcher, NULL); SDL_AddEventWatch(mouse_watcher, NULL); fprintf(stderr, "Video mode: %dx%d@%dbpp (%s)\n", Surf(screen)->w, Surf(screen)->h, Surf(screen)->format->BitsPerPixel, SDL_VideoRendererInfo.name); done: SDL_SetRenderDrawBlendMode(Renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255); SDL_RenderClear(Renderer); SDL_RenderPresent(Renderer); SDL_FillRect(SDL_VideoSurface, NULL, SDL_MapRGB(SDL_VideoSurface->format, 0, 0, 0)); return 0; } int gfx_video_init(void) { if (TTF_Init()) { fprintf(stderr, "Can't init TTF subsystem.\n"); return -1; } #ifndef ICON_PATH #define ICON_PATH "./icon" #endif icon = IMG_Load( ICON_PATH"/sdl_instead_1.png" ); return 0; } static int queue_x1 = -1; static int queue_y1 = -1; static int queue_x2 = -1; static int queue_y2 = -1; static int queue_dirty = 0; static SDL_Texture *cursor = NULL; static int cursor_xc = 0; static int cursor_yc = 0; static int cursor_w; static int cursor_h; static int cursor_on = 1; void gfx_set_cursor(img_t cur, int xc, int yc) { if (cursor) SDL_DestroyTexture(cursor); if (!cur) { cursor = NULL; cursor_w = 0; cursor_h = 0; return; } cursor = SDL_CreateTextureFromSurface(Renderer, Surf(cur)); if (!cursor) return; cursor_w = gfx_img_w(cur); cursor_h = gfx_img_h(cur); cursor_xc = xc; cursor_yc = yc; SDL_SetTextureBlendMode(cursor, SDL_BLENDMODE_BLEND); } void gfx_show_cursor(int on) { cursor_on = on; } static void gfx_render_copy(SDL_Texture *texture, SDL_Rect *dst, int clear) { #ifdef _USE_SWROTATE SDL_Rect r2; SDL_Point r; int w, h; if (gfx_flip_rotate) { if (clear) SDL_RenderClear(Renderer); SDL_QueryTexture(texture, NULL, NULL, &w, &h); r2.x = 0; r2.y = -h; r2.w = w; r2.h = h; r.x = 0; r.y = h; SDL_RenderCopyEx(Renderer, texture, NULL, &r2, 90, &r, 0); return; } #endif if (SDL_VideoRendererInfo.flags & SDL_RENDERER_ACCELERATED) { if (clear) SDL_RenderClear(Renderer); SDL_RenderCopy(Renderer, texture, NULL, NULL); } else SDL_RenderCopy(Renderer, texture, dst, dst); } static void gfx_render_cursor(void) { int cursor_x = 0; int cursor_y = 0; SDL_Rect rect; #ifdef _USE_SWROTATE SDL_Point r; #endif if (!cursor_on || !mouse_focus() || nocursor_sw) return; gfx_cursor(&cursor_x, &cursor_y); #ifdef _USE_SWROTATE if (gfx_flip_rotate) { int tmp = cursor_x; cursor_x = gfx_height - cursor_y; cursor_y = tmp; r.x = cursor_xc; r.y = cursor_yc; } #endif cursor_x -= cursor_xc; cursor_y -= cursor_yc; rect.x = cursor_x; rect.y = cursor_y; rect.w = cursor_w; /* - 1; */ /* SDL 2.0 hack? */ rect.h = cursor_h; /* - 1; */ #ifdef _USE_SWROTATE if (gfx_flip_rotate) SDL_RenderCopyEx(Renderer, cursor, NULL, &rect, 90, &r, 0); else #endif SDL_RenderCopy(Renderer, cursor, NULL, &rect); } static void SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h); int SDL_Flip(SDL_Surface * screen) { SDL_Rect rect; int pitch, psize; unsigned char *pixels; if (!screen) return 0; pitch = screen->pitch; psize = screen->format->BytesPerPixel; pixels = screen->pixels; if (queue_dirty) { rect.x = queue_x1; rect.y = queue_y1; rect.w = queue_x2 - queue_x1; rect.h = queue_y2 - queue_y1; pixels += pitch * queue_y1 + queue_x1 * psize; SDL_UpdateTexture(SDL_VideoTexture, &rect, pixels, pitch); gfx_render_copy(SDL_VideoTexture, &rect, 1); SDL_RenderPresent(Renderer); } queue_x1 = queue_y1 = queue_x2 = queue_y2 = -1; queue_dirty = 0; return 0; } static void SDL_UpdateRect(SDL_Surface * screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) { if (queue_x1 < 0 || x < queue_x1) queue_x1 = x; if (queue_y1 < 0 || y < queue_y1) queue_y1 = y; if ((Sint32)(x + w) > queue_x2) queue_x2 = (Sint32)(x + w); if ((Sint32)(y + h) > queue_y2) queue_y2 = (Sint32)(y + h); queue_dirty = 1; } void gfx_flip(void) { queue_x1 = queue_y1 = 0; queue_x2 = gfx_width; queue_y2 = gfx_height; queue_dirty = 1; } void gfx_resize(int w, int h) { #if defined(ANDROID) || defined(IOS) current_gfx_w = w; current_gfx_h = h; #endif } void gfx_commit(void) { SDL_Flip(Surf(screen)); } void gfx_update(int x, int y, int w, int h) { if (x < 0) { w += x; x = 0; } if (y < 0) { h += y; y = 0; } if (w < 0 || h < 0) return; if (x >= gfx_width || y >= gfx_height) return; if (x + w > gfx_width) { w = gfx_width - x; } if (y + h > gfx_height) { h = gfx_height - y; } SDL_UpdateRect(Surf(screen), x, y, w, h); } void gfx_video_done(void) { if (icon) SDL_FreeSurface(icon); screen = NULL; TTF_Quit(); } img_t gfx_scale(img_t src, float xscale, float yscale, int smooth) { anim_t ag; if ((ag = is_anim(src))) { int i; int err = 0; img_t img = NULL; anim_t ag2; ag2 = anim_clone(ag); if (!ag2) return NULL; for (i = 0; i < ag->nr_frames; i ++) { SDL_Surface *s; s = (err) ? NULL : zoomSurface(ag->anim->frames[i], xscale, yscale, 1); if (!s) { err ++; ag2->anim->frames[i] = NULL; continue; } ag2->anim->frames[i] = s; } if (err) { anim_free(ag2); return NULL; } anim_add(ag2); /* scaled anim added */ img = gfx_new_img(ag2->anim->frames[0], IMG_ANIM, ag2, 0); if (!img) { anim_del(ag2); anim_free(ag2); } return img; } return GFX_IMG_REL(zoomSurface(Surf(src), xscale, yscale, smooth)); } img_t gfx_rotate(img_t src, float angle, int smooth) { anim_t ag; if ((ag = is_anim(src))) { int i; int err = 0; img_t img = NULL; anim_t ag2; ag2 = anim_clone(ag); if (!ag2) return NULL; for (i = 0; i < ag->nr_frames; i ++) { SDL_Surface *s; s = (err) ? NULL : rotozoomSurface(ag->anim->frames[i], angle, 1.0f, smooth); if (!s) { err ++; ag2->anim->frames[i] = NULL; continue; } ag2->anim->frames[i] = s; } if (err) { anim_free(ag2); return NULL; } anim_add(ag2); /* rotated anim added */ img = gfx_new_img(ag2->anim->frames[0], IMG_ANIM, ag2, 0); if (!img) { anim_del(ag2); anim_free(ag2); } return img; } return GFX_IMG_REL(rotozoomSurface(Surf(src), angle, 1.0f, smooth)); } #define FN_REG 0 #define FN_BOLD 1 #define FN_ITALIC 2 #define FN_ITALICBOLD 3 #define FN_MAX 4 struct fnt { TTF_Font *fn; TTF_Font *fonts[FN_MAX]; int style; }; /* prefix{regular,italic, bold, bolditalic}.ttf */ static int parse_fn(const char *f, char *files[]) { int e; int nr = 0; int elen; const char *ep = f; const char *s = f; int pref = strcspn(f, "{"); if (!f[pref]) goto no; f += pref + 1; ep = f; ep += strcspn(f, "}"); if (!*ep) goto no; ep ++; elen = strlen(ep); while (1) { f += strspn(f, " \t"); e = strcspn(f, ",}"); if (!e) { /* empty subst */ files[nr] = NULL; goto skip; } files[nr] = malloc(e + pref + elen + 1); if (!files[nr]) break; if (pref) memcpy(files[nr], s, pref); if (e) memcpy(files[nr] + pref, f, e); if (elen) memcpy(files[nr] + pref + e, ep, elen); *(files[nr] + pref + e + elen) = 0; skip: nr ++; if (!f[e] || f[e] == '}') break; f += e + 1; if (nr >=4) break; } return nr; no: files[0] = strdup(s); return (files[0])?1:0; } extern int hinting_sw; fnt_t fnt_load(const char *fname, int size) { TTF_Font *fn; struct fnt *h; int i, n = 0; char *files[4] = { NULL, NULL, NULL, NULL }; h = malloc(sizeof(struct fnt)); if (!h) return NULL; h->fonts[0] = h->fonts[1] = h->fonts[2] = h->fonts[3] = NULL; n = parse_fn(fname, files); if (!n) goto err; for (i = 0; i < n; i++) { fn = NULL; if (!is_empty(files[i])) { SDL_RWops *rw = RWFromIdf(instead_idf(), files[i]); if (!rw || !(fn = TTF_OpenFontRW(rw, 1, size))) { fprintf(stderr, "Can not load font: '%s'\n", files[i]); } } if (!fn && i == 0) /* no regular */ goto err; #ifdef TTF_HINTING_LIGHT if (fn) { switch (hinting_sw) { case 0: TTF_SetFontHinting(fn, TTF_HINTING_NORMAL); break; case 1: TTF_SetFontHinting(fn, TTF_HINTING_LIGHT); break; case 2: TTF_SetFontHinting(fn, TTF_HINTING_MONO); break; case 3: TTF_SetFontHinting(fn, TTF_HINTING_NONE); break; default: break; } } #endif h->fonts[i] = fn; } h->fn = h->fonts[FN_REG]; for (i = 0; i < n; i++) free(files[i]); return (fnt_t) h; err: for (i = 0; i < n; i++) free(files[i]); fnt_free(h); return NULL; } void fnt_style(fnt_t fn, int style) { struct fnt *h = (struct fnt*)fn; if (!h) return; h->style = style; if ((style & TTF_STYLE_BOLD) && (style & TTF_STYLE_ITALIC)) { if (h->fonts[FN_ITALICBOLD]) { h->fn = h->fonts[FN_ITALICBOLD]; style &= ~TTF_STYLE_BOLD; style &= ~TTF_STYLE_ITALIC; } else h->fn = h->fonts[FN_REG]; } else if ((style & TTF_STYLE_BOLD)) { if (h->fonts[FN_BOLD]) { h->fn = h->fonts[FN_BOLD]; style &= ~TTF_STYLE_BOLD; } else h->fn = h->fonts[FN_REG]; } else if ((style & TTF_STYLE_ITALIC)) { if (h->fonts[FN_ITALIC]) { h->fn = h->fonts[FN_ITALIC]; style &= ~TTF_STYLE_ITALIC; } else h->fn = h->fonts[FN_REG]; } else { h->fn = h->fonts[FN_REG]; } TTF_SetFontStyle((TTF_Font *)h->fn, style); } img_t fnt_render(fnt_t fn, const char *p, color_t col) { SDL_Color scol = { .r = col.r, .g = col.g, .b = col.b }; struct fnt *h = (struct fnt*)fn; if (!h) return NULL; return GFX_IMG_REL(TTF_RenderUTF8_Blended((TTF_Font *)h->fn, p, scol)); } int fnt_height(fnt_t fn) { struct fnt *h = (struct fnt*)fn; if (!fn) return 0; return TTF_FontHeight((TTF_Font *)(h->fonts[FN_REG])); } void fnt_free(fnt_t fnt) { int i; struct fnt *h = (struct fnt*)fnt; if (!fnt) return; for (i = 0; i < FN_MAX; i++) { if (h->fonts[i]) TTF_CloseFont((TTF_Font *)h->fonts[i]); } free(h); } void txt_draw(fnt_t fnt, const char *txt, int x, int y, color_t col) { img_t s = fnt_render(fnt, txt, col); if (!s) return; gfx_draw(s, x, y); } #if 0 int txt_width(fnt_t fnt, const char *txt) { const char *p = txt; int c = 0; int w = 0; Uint16 u = 0; struct fnt *f = (struct fnt*)fnt; if (!f) return 0; while (*p) { if (!c) { if (! (*p & 0x80)) { /* ascii */ c = 1; u = *p & 0x7f; } else { if ((*p & 0xe0) == 0xc0) { c = 2; u = *p & 0x1f; } else if ((*p & 0xf0) == 0xe0) { c = 3; u = *p & 0xf; } else if ((*p & 0xf8) == 0xf0) { c = 4; u = *p & 0x3; } else { c = 1; u = *p & 0x7f; /* fallback */ } } } else { if ((*p & 0xc0) != 0x80) { c = 1; u = *p & 0x7f; /* fallback */ } else { u <<= 6; u |= *p & 0x3f; } } c --; if (!c) { int adv = 0; TTF_GlyphMetrics(f->fn, u, NULL, NULL, NULL, NULL, &adv); w += adv; } p ++; } return w; } #endif void txt_size(fnt_t fnt, const char *txt, int *w, int *h) { int ww, hh; struct fnt *f = (struct fnt*)fnt; TTF_SizeUTF8((TTF_Font *)f->fn, txt, &ww, &hh); if (w) *w = ww; if (h) *h = hh; } struct word; struct line; struct xref; struct word { int style; int x; int w; int unbrake; int valign; int img_align; /* Direction and Script (Language) of the word */ int rtl; int script; /* See HarfBuzz hb_script_t */ int isalpha; /* Whether this word contains alphabets */ char *word; img_t img; struct word *next; /* in line */ struct word *prev; /* in line */ struct line *line; struct xref *xref; img_t prerend; img_t hlprerend; }; img_t word_image(word_t v) { struct word *w = (struct word*)v; if (!w) return NULL; return w->img; } #ifdef _USE_HARFBUZZ static int hb_dir(int rtl) { return rtl ? HB_DIRECTION_RTL:HB_DIRECTION_LTR; } #endif /* This function detects and configures direction, script and type of a word. */ static void word_detect_rtl(struct word *w, int mode) { #ifdef _USE_HARFBUZZ const char *str = w->word; int rc; unsigned long sym = 0; if (mode == 0) /* force ltr mode */ return; /* Find the first alphanumeric utf8 character for a meaningful direction or use direction of the first character. */ while ((rc = get_utf8(str, &sym))) { if (g_unichar_isalpha(sym)) break; str += rc; } /* Is this made of alphabets? */ w->isalpha = g_unichar_isalpha(sym); if (mode == 1) { /* force rtl */ w->rtl = 1; w->script = HB_SCRIPT_COMMON; return; } switch(g_unichar_get_script(sym)) { case G_UNICODE_SCRIPT_HEBREW: w->rtl = !g_unichar_isdigit(sym); w->script = HB_SCRIPT_HEBREW; /* Fall through */ case G_UNICODE_SCRIPT_ARABIC: w->rtl = !g_unichar_isdigit(sym); w->script = HB_SCRIPT_ARABIC; break; default: w->rtl = 0; w->script = HB_SCRIPT_COMMON; } #endif } struct word *word_new(const char *str) { struct word *w; w = malloc(sizeof(struct word)); if (!w) return NULL; w->word = strdup(str); w->next = NULL; w->x = 0; w->w = 0; w->valign = 0; w->line = NULL; w->xref = NULL; w->style = 0; w->img = NULL; w->img_align = 0; w->unbrake = 0; w->prerend = NULL; w->hlprerend = NULL; w->rtl = 0; w->script = 0; w->isalpha = 0; return w; } struct line { int x; int y; int h; int w; int num; int align; int pos; int tabx; int al_tabx; int taby; int al_taby; /* Each line could be RTL or LTR regardless of its script */ int rtl; struct word *words; struct line *next; struct line *prev; struct layout *layout; }; static int vertical_align(struct word *w, int *hh); static int word_pos_x(struct word *word); int word_geom(word_t v, int *x, int *y, int *w, int *h) { int xx, yy, ww, hh; struct line *line; struct word *word = (struct word*)v; if (!word || !word->line) return -1; line = word->line; xx = word_pos_x(word); ww = word->w; yy = line->y; yy += vertical_align(v, &hh); if (x) *x = xx; if (y) *y = yy; if (w) *w = ww; if (h) *h = hh; return 0; } struct line *line_new(void) { struct line *l; l = malloc(sizeof(struct line)); if (!l) return NULL; l->words = NULL; l->next = NULL; l->prev = NULL; l->x = 0; l->w = 0; l->y = 0; l->h = 0; l->num = 0; l->tabx = -1; l->al_tabx = ALIGN_LEFT; l->taby = -1; l->al_taby = ALIGN_BOTTOM; l->layout = NULL; l->align = 0; l->pos = 0; l->rtl = 0; return l; } int line_empty(struct line *line) { struct word *w; w = line->words; while (w) { if (w->img_align) { w = w->next; continue; } return 0; } return 1; } static int line_margin(struct line *line) { struct word *w; w = line->words; while (w) { if (w->img_align) return 1; w = w->next; } return 0; } static struct word *next_word(struct word *w) { while (w->next && w->next->img_align) /* skip margins */ w = w->next; return w->next; } void line_justify(struct line *line, int width) { int x = 0; int last_margin = 0; int last_unbrake = 0; struct word *w; int sp, spm, lw = 0; int lnum = 0; if (!line || line->num <= 1 /*|| width <= line->w*/) return; w = line->words; while (w) { lw += w->w; if (last_margin && w->unbrake) w->unbrake = last_unbrake; if (!w->unbrake && !w->img_align) lnum ++; if (!last_margin && w->img_align) last_unbrake = w->unbrake; last_margin = w->img_align; w = w->next; } if (lnum <=1 ) return; w = line->words; sp = (width - lw) / (lnum - 1); spm = (width - lw) % (lnum - 1); while (w) { if (!w->img_align) { w->x = x; if (next_word(w) && next_word(w)->unbrake) x += w->w; else { x += w->w + sp + ((spm)?1:0); if (spm) spm --; } } w = w->next; } } void line_right(struct line *line, int width) { struct word *w; int sp; if (!line || line->num == 0) return; sp = width - line->w; w = line->words; while (w) { if (!w->img_align) { w->x += sp; } w = w->next; } } void line_center(struct line *line, int width) { struct word *w; int sp; if (!line || line->num == 0) return; sp = (width - line->w)/2; w = line->words; while (w) { if (!w->img_align) { w->x += sp; } w = w->next; } } void line_align(struct line *line, int width, int style, int nl) { if (style == ALIGN_JUSTIFY) { if (nl) return; line_justify(line, width); return; } if (style == ALIGN_CENTER) { line_center(line, width); return; } if (style == ALIGN_LEFT) return; if (style == ALIGN_RIGHT) { line_right(line, width); return; } } void word_free(struct word *word); void line_free(struct line *line) { struct word *w; if (!line) return; w = line->words; while (w) { struct word *ow = w; w = w->next; word_free(ow); } free(line); } void line_add_word(struct line *l, struct word *word) { struct word *w = l->words; l->num ++; word->line = l; if (!l->words) { l->words = word; word->prev = word; /* This is the first word in this line. Let's use its direction for the line too. Ideally, something like fribidi should be used for mixing directions however. */ l->rtl = word->rtl; return; } w = w->prev; w->next = word; word->prev = w; l->words->prev = word; return; } struct image; struct image { struct image *next; char *name; img_t image; int free_it; }; struct image *image_new(const char *name, img_t img) { struct image *g = malloc(sizeof(struct image)); if (!g) return NULL; g->image = img; g->name = strdup(name); g->next = NULL; g->free_it = 0; return g; } void image_free(struct image *image) { if (!image) return; if (image->name) free(image->name); if (image->free_it) gfx_free_image(image->image); free(image); } struct textbox; #define ALIGN_NEST 16 struct margin; struct margin { struct margin *next; int w; int h; int y; int align; struct word *word; }; struct margin *margin_new(void) { struct margin *m = malloc(sizeof(struct margin)); if (!m) return NULL; m->w = m->h = m->align = 0; m->next = NULL; return m; } void margin_free(struct margin *m) { if (m) free(m); } struct layout { fnt_t fn; float fn_height; color_t col; color_t lcol; color_t acol; struct image *images; struct xref *xrefs; struct line *lines; struct line *anchor; struct textbox *box; struct margin *margin; int w; int h; int align; int valign; int saved_align[ALIGN_NEST]; int saved_valign[ALIGN_NEST]; int acnt; int vcnt; int style; int rtl; int scnt[4]; int lstyle; cache_t img_cache; cache_t prerend_cache; cache_t hlprerend_cache; }; struct xref { struct xref *next; struct xref *prev; struct word **words; struct layout *layout; char *link; int num; int active; }; struct textbox { struct layout *lay; struct line *line; int off; int w; int h; }; void word_free(struct word *word) { if (!word) return; /* if (word->img) gfx_free_image(word->img); */ if (word->word) free(word->word); if (word->prerend) { cache_forget(word->line->layout->prerend_cache, word->prerend); /* SDL_FreeSurface(word->prerend); */ } if (word->hlprerend) { cache_forget(word->line->layout->hlprerend_cache, word->hlprerend); /* SDL_FreeSurface(word->hlprerend); */ } word->hlprerend = word->prerend = NULL; free(word); } struct xref *xref_new(char *link) { struct xref *p; p = malloc(sizeof(struct xref)); if (!p) return NULL; if (link) p->link = strdup(link); else p->link = NULL; p->num = 0; p->layout = NULL; p->next = NULL; p->prev = NULL; p->active = 0; p->words = NULL; return p; } int xref_add_word(struct xref *xref, struct word *word) { struct word **new_words; new_words = realloc(xref->words, (xref->num + 1) * sizeof(struct word*)); if (!new_words) return -1; xref->words = new_words; xref->words[xref->num ++] = word; word->xref = xref; return 0; } void xref_free(struct xref *xref) { if (xref->link) free(xref->link); if (xref->words) free(xref->words); free(xref); } void layout_add_line(struct layout *layout, struct line *line) { struct line *l = layout->lines; line->layout = layout; if (!l) { layout->lines = line; line->prev = line; return; } l = l->prev; l->next = line; line->prev = l; layout->lines->prev = line; return; } void layout_add_margin(struct layout *layout, struct margin *margin) { struct margin *m = layout->margin; if (!m) { layout->margin = margin; return; } while (m->next) m = m->next; m->next = margin; return; } #if 1 static int layout_skip_margin(struct layout *layout, int y) { struct margin *m = layout->margin; int my = y; if (!m) return y; while (m) { if (m->y + m->h > my) my = m->y + m->h; m = m->next; } if (y < my) y = my; return y; } #endif static void margin_rebase(struct layout *layout) { struct margin *m = layout->margin; if (!m) return; while (m) { m->y = m->word->line->y; m = m->next; } } static int layout_find_margin(struct layout *layout, int y, int *w) { struct margin *m = layout->margin; int xpos = 0; int rpos = layout->w; if (!m) { if (w) *w = layout->w; return 0; } while (m) { if (y >= m->y && y < m->y + m->h) { if (m->align == ALIGN_LEFT) xpos = (xpos < m->w)?m->w:xpos; else rpos = (rpos > layout->w - m->w)?layout->w - m->w:rpos; } m = m->next; } if (w) *w = rpos - xpos; return xpos; } struct image *_layout_lookup_image(struct layout *layout, const char *name) { struct image *g; for (g = layout->images; g; g = g->next) { if (!strcmp(g->name, name)) return g; } return NULL; } img_t txt_layout_images(layout_t lay, void **v) { struct image **g = (struct image **)v; struct layout *layout = (struct layout *)lay; if (!layout) return NULL; if (!*v) *v = layout->images; else *v = (*g)->next; if (!*v) return NULL; return (*g)->image; } textbox_t txt_layout_box(layout_t lay) { struct layout *layout = (struct layout *)lay; return layout->box; } void layout_add_image(struct layout *layout, struct image *image) { struct image *g = layout->images; if (!g) { layout->images = image; return; } while (g->next) g = g->next; g->next = image; return; } img_t layout_lookup_image(struct layout *layout, char *name) { struct image *g = _layout_lookup_image(layout, name); return (g)?g->image: NULL; } void layout_add_xref(struct layout *layout, struct xref *xref) { struct xref *x = layout->xrefs; xref->layout = layout; if (!x) { layout->xrefs = xref; xref->prev = xref; return; } x = x->prev; x->next = xref; xref->prev = x; layout->xrefs->prev = xref; return; } static void sdl_surface_free(void *p) { gfx_free_img((img_t)p); } struct layout *layout_new(fnt_t fn, int w, int h) { struct layout *l; l = malloc(sizeof(struct layout)); if (!l) return NULL; l->lines = NULL; l->anchor = NULL; l->images = NULL; l->w = w; l->h = h; l->fn = fn; l->fn_height = 1.0f; l->align = ALIGN_JUSTIFY; l->valign = 0; l->style = 0; l->lstyle = 0; l->rtl = 0; l->xrefs = NULL; l->margin = NULL; l->col = gfx_col(0, 0, 0); l->lcol = gfx_col(0, 0, 255); l->acol = gfx_col(255, 0, 0); l->box = NULL; l->img_cache = cache_init(0, gfx_cache_free_image); l->prerend_cache = cache_init(0, sdl_surface_free); l->hlprerend_cache = cache_init(0, sdl_surface_free); memset(l->scnt, 0, sizeof(l->scnt)); memset(l->saved_align, 0, sizeof(l->saved_align)); memset(l->saved_valign, 0, sizeof(l->saved_valign)); l->acnt = 0; l->vcnt = 0; return l; } void txt_layout_size(layout_t lay, int *w, int *h) { struct layout *layout = (struct layout *)lay; if (!lay) return; if (w) *w = layout->w; if (h) *h = layout->h; } void txt_layout_set_size(layout_t lay, int w, int h) { struct layout *layout = (struct layout *)lay; if (!lay) return; layout->w = w; layout->h = h; } int txt_layout_add_img(layout_t lay, const char *name, img_t img) { struct layout *layout = (struct layout *)lay; struct image *image; image = _layout_lookup_image(layout, name); if (image) { /* overwrite */ image->image = img; return 0; } image = image_new(name, img); if (!image) return -1; layout_add_image(layout, image); return 0; } void _txt_layout_free(layout_t lay) { struct layout *layout = (struct layout *)lay; struct line *l; struct image *g; struct xref *x; struct margin *m; if (!layout) return; l = layout->lines; while (l) { struct line *ol = l; l = l->next; line_free(ol); } x = layout->xrefs; while (x) { struct xref *ox = x; x = x->next; xref_free(ox); } m = layout->margin; while (m) { struct margin *om = m; m = m->next; margin_free(om); } g = layout->images; while (g) { struct image *og = g; g = g->next; if (!cache_have(layout->img_cache, og->image)) og->free_it = 0; /* do not free from cache */ cache_forget(layout->img_cache, og->image); image_free(og); } layout->images = NULL; layout->xrefs = NULL; layout->lines = NULL; layout->anchor = NULL; layout->margin = NULL; memset(layout->scnt, 0, sizeof(layout->scnt)); memset(layout->saved_align, 0, sizeof(layout->saved_align)); memset(layout->saved_valign, 0, sizeof(layout->saved_valign)); layout->acnt = 0; layout->vcnt = 0; } word_t txt_layout_words_ex(layout_t lay, struct line *line, word_t v, int off, int height) { struct layout *layout = (struct layout*)lay; struct word *w = (struct word*)v; if (!lay) return NULL; if (!w) { if (!line) line = layout->lines; if (!line) return NULL; w = line->words; } else { line = w->line; w = w->next; } for (; (!w || (line->y + line->h) < off) && line->next; line = line->next, w = line->words); if ((line->y + line->h) < off) w = NULL; else if (height >= 0 && line->y - off > height) w = NULL; return w; } word_t txt_layout_words(layout_t lay, word_t v) { return txt_layout_words_ex(lay, NULL, v, 0, -1); } void txt_layout_free(layout_t lay) { struct layout *layout = (struct layout *)lay; _txt_layout_free(lay); if (lay) { cache_free(layout->img_cache); cache_free(layout->prerend_cache); cache_free(layout->hlprerend_cache); layout->img_cache = NULL; layout->prerend_cache = NULL; layout->hlprerend_cache = NULL; free(lay); } } #define TOKEN_NONE 0x000 #define TOKEN_A 0x001 #define TOKEN_B 0x002 #define TOKEN_I 0x004 #define TOKEN_U 0x008 #define TOKEN_S 0x010 #define TOKEN_C 0x020 #define TOKEN_R 0x040 #define TOKEN_J 0x080 #define TOKEN_L 0x100 #define TOKEN_T 0x200 #define TOKEN_D 0x400 #define TOKEN_M 0x800 #define TOKEN_X 0x1000 #define TOKEN_Y 0x2000 #define TOKEN_CLOSE 0x4000 #define TOKEN(x) (x & 0x3fff) int gfx_get_token(const char *ptr, char **eptr, char **val, int *sp) { int y_token = 0; char *ep, *p; int closing = 0; if (eptr) *eptr = NULL; p = (char*)ptr; ptr += strspn(ptr, " \t"); if (sp) { *sp = 0; if (p != ptr) *sp = 1; } if (val) *val = NULL; if (!*ptr) return 0; if (*ptr != '<') return 0; ptr ++; if (*ptr == '/') { closing = 1; if (!ptr[1] || ptr[2] != '>') return 0; ptr ++; } switch (*ptr) { case 'y': y_token = 1; /* Fall through */ case 'x': if (ptr[1] != ':') return 0; ptr += 2; ep = find_in_esc(ptr, "\\>"); if (*ep != '>') return 0; if (val) { p = malloc(ep - ptr + 1); if (!p) return 0; memcpy(p, ptr, ep - ptr); p[ep - ptr] = 0; *val = p; } if (eptr) *eptr = ep + 1; return (y_token)?TOKEN_Y:TOKEN_X; case 'a': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_A | TOKEN_CLOSE; } if (ptr[1] != ':') { return 0; } ptr += 2; /* ep = (char*)ptr + strcspn(ptr, ">"); */ ep = find_in_esc(ptr, "\\>"); if (!ep || *ep != '>') { return 0; } if (val) { p = malloc(ep - ptr + 1); if (!p) return 0; memcpy(p, ptr, ep - ptr); p[ep - ptr] = 0; parse_esc_string(p, val); if (*val) free(p); else *val = p; } if (eptr) *eptr = ep + 1; return TOKEN_A; case 'b': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_B | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_B; } break; case 'i': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_I | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_I; } break; case 's': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_S | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_S; } break; case 't': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_T | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_T; } break; case 'd': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_D | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_D; } break; case 'm': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_M | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_M; } break; case 'u': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_U | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_U; } break; case 'c': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_C | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_C; } break; case 'r': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_R | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_R; } break; case 'j': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_J | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_J; } break; case 'l': if (closing) { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_L | TOKEN_CLOSE; } if (ptr[1] == '>') { if (eptr) *eptr = (char*)ptr + 2; return TOKEN_L; } break; } return 0; } static int is_delim(int c) { switch(c) { case '.': case ',': case ':': case '!': case '+': case '-': case '?': case '/': return 1; } return 0; } static int process_word_token(const char *p, char **eptr, char ch) { char *ep; if (eptr) *eptr = (char*)p; if (!p) return 0; if (p[0] != '<' || p[1] != ch || p[2] != ':') return 0; p += 3; ep = find_in_esc(p, "\\>"); if (*ep != '>') return 0; if (eptr) *eptr = ep + 1; return (ep - p + 1); } static int word_img(const char *p, char **eptr) { return process_word_token(p, eptr, 'g'); } static int word_token(const char *p, char **eptr) { return process_word_token(p, eptr, 'w'); } static int lookup_cjk(const char *ptr, int limit) { unsigned long sym; int off = 0, rc; while ((rc = get_utf8(ptr, &sym))) { if (is_cjk(sym)) return off; off += rc; ptr += rc; if (off >= limit) break; } return off; } static int cjk_here(const char *ptr) { unsigned long sym; int rc; rc = get_utf8(ptr, &sym); if (is_cjk(sym)) return rc; return 0; } static const char *lookup_token_or_sp(const char *ptr) { char *eptr; const char *p = ptr; while (*p) { int cjk, rc; rc = strcspn(p, " .,:!+-?/<\t\n"); cjk = lookup_cjk(p, rc); if (p[cjk] && cjk < rc) { /* cjk symbol found! */ rc = cjk; if (!rc) rc += get_utf8(p, NULL); } p += rc; if (*p != '<' ) { while (is_delim(*p)) p ++; /* if (is_delim(*p)) p ++; */ return p; } if (!gfx_get_token(p, &eptr, NULL, NULL)) { if (word_img(p, &eptr)) { if (p == ptr) /* first one */ p = eptr; return p; } else if (word_token(p, &eptr)) { if (p == ptr) /* first one */ p = eptr; return p; } p ++; continue; } return p; } return ptr; } #define BREAK_NONE 0 #define BREAK_SPACE 1 static char *get_word(const char *ptr, char **eptr, int *sp) { const char *ep; char *o; size_t sz; *eptr = NULL; o = (char*)ptr; ptr += strspn(ptr, " \t"); if (sp) { *sp = BREAK_NONE; if (o != ptr) *sp = BREAK_SPACE; } if (!*ptr) return NULL; ep = lookup_token_or_sp(ptr); /* ep += strcspn(ep, " \t\n"); */ sz = ep - ptr; o = malloc(sz + 1); memcpy(o, ptr, sz); o[sz] = 0; sz = word_img(ptr, eptr); if (sz) return o; sz = word_token(ptr, eptr); if (sz) return o; *eptr = (char*)ep; return o; } void layout_debug(struct layout *layout) { struct line *line; struct word *word; line = layout->lines; while (line) { printf("%d of %d)", line->y, line->num); word = line->words; while (word) { printf("%d)%s ", word->x, word->word); word = word->next; } printf("\n"); line = line->next; } } void txt_layout_color(layout_t lay, color_t fg) { struct layout *layout = (struct layout*)lay; if (!lay) return; layout->col = fg; } void txt_layout_rtl(layout_t lay, int rtl) { struct layout *layout = (struct layout*)lay; if (!lay) return; layout->rtl = rtl; } void txt_layout_font_height(layout_t lay, float height) { struct layout *layout = (struct layout*)lay; if (!lay) return; layout->fn_height = height; } void txt_layout_link_color(layout_t lay, color_t link) { struct layout *layout = (struct layout*)lay; if (!lay) return; layout->lcol = link; } void txt_layout_active_color(layout_t lay, color_t link) { struct layout *layout = (struct layout*)lay; if (!lay) return; layout->acol = link; } void txt_layout_link_style(layout_t lay, int style) { struct layout *layout = (struct layout*)lay; if (!lay) return; layout->lstyle = style; } static char *word_cache_string(struct word *w, Uint32 style) { char *p; int len = 0; len = (w->word)?strlen(w->word):0; len += 16; p = malloc(len); if (!p) return NULL; snprintf(p, len, "%s-%08x", (w->word)?w->word:"", style); return p; } static void word_render(struct layout *layout, struct word *word, int x, int y) { char *wc = NULL; img_t s; img_t prerend = NULL; img_t hlprerend = NULL; color_t fgcol = { .r = layout->col.r, .g = layout->col.g, .b = layout->col.b }; color_t lcol = { .r = layout->lcol.r, .g = layout->lcol.g, .b = layout->lcol.b }; color_t acol = { .r = layout->acol.r, .g = layout->acol.g, .b = layout->acol.b }; Uint32 style; if (!word->xref) { style = (fgcol.r << 24) + (fgcol.g << 16) + (fgcol.b << 8); } else if (word->xref->active) { style = (acol.r << 24) + (acol.g << 16) + (acol.b << 8); } else { style = (lcol.r << 24) + (lcol.g << 16) + (lcol.b << 8); } if (word->xref && !word->style) { fnt_style(layout->fn, layout->lstyle); wc = word_cache_string(word, layout->lstyle | style); } else { fnt_style(layout->fn, word->style); wc = word_cache_string(word, word->style | style); } if (!wc) return; #ifdef _USE_HARFBUZZ /* Set the language and script for SDL_ttf */ TTF_SetDirection(hb_dir(word->rtl)); TTF_SetScript(word->script); #endif if (!word->xref) { if (!word->prerend) { prerend = cache_get(layout->prerend_cache, wc); if (!prerend) { word->prerend = fnt_render(layout->fn, word->word, fgcol); word->prerend = gfx_display_alpha(word->prerend); cache_add(layout->prerend_cache, wc, word->prerend); } else { word->prerend = prerend; } } s = word->prerend; } else if (word->xref->active) { if (!word->hlprerend) { hlprerend = cache_get(layout->hlprerend_cache, wc); if (!hlprerend) { word->hlprerend = fnt_render(layout->fn, word->word, acol); word->hlprerend = gfx_display_alpha(word->hlprerend); cache_add(layout->hlprerend_cache, wc, word->hlprerend); } else { word->hlprerend = hlprerend; } } s = word->hlprerend; } else { if (!word->prerend) { prerend = cache_get(layout->prerend_cache, wc); if (!prerend) { word->prerend = fnt_render(layout->fn, word->word, lcol); word->prerend = gfx_display_alpha(word->prerend); cache_add(layout->prerend_cache, wc, word->prerend); } else { word->prerend = prerend; } } s = word->prerend; } free(wc); #ifdef _USE_HARFBUZZ /* Drop to defaults */ TTF_SetDirection(HB_DIRECTION_LTR); TTF_SetScript(HB_SCRIPT_COMMON); #endif if (!s) return; gfx_draw(s, x, y); } fnt_t txt_layout_font(layout_t lay) { struct layout *layout = lay; if (!lay) return NULL; return layout->fn; } static int vertical_align(struct word *w, int *hh) { int h; struct line *line = w->line; struct layout *layout = line->layout; if (w->img) h = gfx_img_h(w->img); else h = fnt_height(layout->fn); if (hh) *hh = h; if (w->img && w->img_align) return 0; if (w->valign == ALIGN_TOP) return 0; else if (w->valign == ALIGN_BOTTOM) return line->h - h; return (line->h - h) / 2; } /* relative position in line */ static int line_pos(struct line *line, int x) { if (!line->rtl) return x; return line->layout->w - line->x - x; } /* absolute position of word */ static int word_pos_x(struct word *word) { struct line *line = word->line; struct layout *layout = line->layout; if (word->img && word->img_align) { if (line->rtl) return layout->w - word->x - gfx_img_w(word->img); return word->x; } if (!line->rtl) /* fast path */ return line->x + word->x; if (word->img) return layout->w - line->x - word->x - gfx_img_w(word->img); return layout->w - line->x - word->x - word->w; } static void word_image_render(struct word *word, int x, int y, clear_fn clear, update_fn update) { struct line *line = word->line; struct layout *layout = line->layout; int yy; int posx = word_pos_x(word); if (clear && !word->xref) return; yy = vertical_align(word, NULL); if (clear) { if (word->img) { clear(x + posx, y + line->y + yy, gfx_img_w(word->img), gfx_img_h(word->img)); } else clear(x + posx, y + line->y/* + yy*/, word->w, line->h); } if (word->img) { /* We have an image to draw */ gfx_draw(word->img, x + posx, y + line->y + yy); if (update) update(x + posx, y + line->y + yy, gfx_img_w(word->img), gfx_img_h(word->img)); } else { word_render(layout, word, x + posx, y + yy + line->y); if (update) update(x + posx, y + line->y + yy, word->w, line->h); } } void xref_update(xref_t pxref, int x, int y, clear_fn clear, update_fn update) { int i; struct xref *xref = (struct xref*)pxref; struct layout *layout; struct word *word; if (!xref) return; layout = xref->layout; if (layout->box) { gfx_clip(x, y, layout->box->w, layout->box->h); y -= (layout->box)->off; } for (i = 0; i < xref->num; i ++) { word = xref->words[i]; if (!word->img_align) word_image_render(word, x, y, clear, update); } gfx_noclip(); } /* Draws everything */ void txt_layout_draw_ex(layout_t lay, struct line *line, int x, int y, int off, int height, clear_fn clear) { void *v; img_t img; struct layout *layout = (struct layout*)lay; struct margin *margin; struct word *word; /* line = layout->lines; gfx_clip(x, y, layout->w, layout->h); */ if (!lay) return; for (v = NULL; (img = txt_layout_images(lay, &v)); ) gfx_dispose_anim(img); for (margin = layout->margin; margin; margin = margin->next) { if (margin->y + margin->h < off) continue; if (margin->y - off > height) continue; word_image_render(margin->word, x, y, clear, NULL); } if (!line) line = layout->lines; for (; line; line= line->next) { if ((line->y + line->h) < off) continue; if (line->y - off > height) break; for (word = line->words; word; word = word->next ) { if (!word->img_align) word_image_render(word, x, y, clear, NULL); } } cache_shrink(layout->prerend_cache); cache_shrink(layout->hlprerend_cache); cache_shrink(layout->img_cache); /* gfx_noclip(); */ } void txt_layout_draw(layout_t lay, int x, int y) { struct layout *layout = (struct layout*)lay; txt_layout_draw_ex(lay, NULL, x, y, 0, layout->h, 0); } textbox_t txt_box(int w, int h) { struct textbox *box; box = malloc(sizeof(struct textbox)); if (!box) return NULL; box->lay = NULL; /* (struct layout*)lay; */ box->w = w; box->h = h; box->off = 0; box->line = NULL; /* (box->lay)->lines; */ return box; } void txt_box_norm(textbox_t tbox) { struct textbox *box = (struct textbox *)tbox; struct line *line; int off; if (!tbox || !box->lay) return; off = box->off; box->line = box->lay->lines; for (line = box->line; line; line = line->next) { if (off < line->h) break; off -= line->h; box->line = line; } } layout_t txt_box_layout(textbox_t tbox) { struct textbox *box = (struct textbox *)tbox; if (!box) return NULL; return box->lay; } void txt_box_set(textbox_t tbox, layout_t lay) { struct textbox *box = (struct textbox *)tbox; if (!box) return; box->lay = (struct layout*)lay; box->off = 0; if (lay) box->lay->box = box; txt_box_norm(tbox); } void txt_box_resize(textbox_t tbox, int w, int h) { struct textbox *box = (struct textbox *)tbox; if (!tbox) return; if (w < 0) w = 0; if (h < 0) h = 0; box->w = w; box->h = h; txt_box_norm(tbox); } void txt_box_size(textbox_t tbox, int *w, int *h) { struct textbox *box = (struct textbox *)tbox; if (!tbox) return; if (w) *w = box->w; if (h) *h = box->h; } void txt_box_scroll_next(textbox_t tbox, int disp) { int off, h; struct textbox *box = (struct textbox *)tbox; struct line *line; if (!tbox) return; line = box->line; if (!line) return; txt_box_real_size(box, NULL, &h); if (h - box->off < box->h) return; off = h - box->off - box->h; if (disp > off) disp = off; off = box->off - line->y; /* offset from cur line */ off += disp; /* needed offset */ while (line->next && off >= line->next->y - line->y) { off -= (line->next->y - line->y); line = line->next; } box->line = line; box->off = line->y + off; } void txt_box_scroll_prev(textbox_t tbox, int disp) { int off; struct textbox *box = (struct textbox *)tbox; struct line *line; struct layout *l; if (!tbox) return; l = box->lay; line = box->line; if (!line) return; off = box->off - line->y; /* offset from cur line */ off -= disp; /* offset from current line */ while (line != l->lines && off < 0) { line = line->prev; off += (line->next->y - line->y); } box->line = line; box->off = line->y + off; if (box->off <0) box->off = 0; } void txt_box_scroll(textbox_t tbox, int disp) { if (!tbox) return; if (disp >0) { txt_box_scroll_next(tbox, disp); return; } else if (disp <0) { txt_box_scroll_prev(tbox, -disp); return; } } void txt_box_next_line(textbox_t tbox) { struct textbox *box = (struct textbox *)tbox; struct line *line; if (!box || !box->lay) return; line = box->line; if (!line) return; /* txt_box_norm(tbox); */ if (box->lay->h - box->off < box->h) return; line = line->next; if (line) { box->off = line->y; box->line = line; } } void txt_box_prev_line(textbox_t tbox) { struct textbox *box = (struct textbox *)tbox; struct line *line; struct layout *l; if (!box || !box->lay) return; l = box->lay; line = box->line; if (!line) return; if (line != l->lines) { line = line->prev; box->line = line; box->off = line->y; } else box->off = 0; } int txt_box_off(textbox_t tbox) { struct textbox *box = (struct textbox *)tbox; if (!box) return -1; return box->off; } void txt_box_next(textbox_t tbox) { struct textbox *box = (struct textbox *)tbox; struct line *line; if (!tbox) return; line = box->line; if (!line) return; for (; line; line = line->next) { if ((line->y + line->h - box->off) >= box->h) break; } if (line) { box->off += (line->y - box->off); box->line = line; } } void txt_box_prev(textbox_t tbox) { struct textbox *box = (struct textbox *)tbox; struct layout *lay; struct line *line; if (!tbox) return; lay = box->lay; if (!lay) return; line = box->line; if (!line) return; for (; line != lay->lines; line = line->prev) { if ((box->off - line->y) >= box->h) break; } if (line == lay->lines) { box->off = 0; box->line = lay->lines; return; } box->off = line->y; box->line = line; } xref_t txt_box_xrefs(textbox_t tbox) { struct textbox *box = (struct textbox*)tbox; struct xref *xref = NULL; struct word *word = NULL; struct line *line; if (!tbox) return NULL; for (line = box->line; line; line = line->next) { if (line->y < box->off) continue; /* too high */ if (line->y + line->h > box->h + box->off) break; /* bottom */ for (word = line->words; word; word = word->next) { xref = word->xref; if (!xref || word->img_align) continue; return xref; } } return xref; } xref_t txt_box_xref(textbox_t tbox, int x, int y) { struct textbox *box = (struct textbox*)tbox; struct xref *xref = NULL; struct word *word = NULL; struct line *line; if (!tbox) return NULL; y += box->off; if (x < 0) return NULL; if (y < 0) return NULL; if (x >= box->w) return NULL; /* Process each word in each line */ for (line = box->line; line; line = line->next) { int hh, yy, lx; if (y < line->y) break; if (y > line->y + line->h) continue; lx = line_pos(line, x); for (word = line->words; word; word = word->next) { yy = vertical_align(word, &hh); if (y < line->y + yy || y > line->y + yy + hh) continue; if (lx < line->x + word->x) continue; xref = word->xref; /* Go back. Found nothing. */ if (!xref) continue; if (lx < line->x + word->x + word->w) break; if (word->next && word->next->xref == xref && lx < line->x + word->next->x + word->next->w) { yy = vertical_align(word->next, &hh); if (y < line->y + yy || y > line->y + yy + hh) continue; break; } } } if (word && xref) { /* We found a highlighted word. */ return xref; } return NULL; } void txt_box_free(textbox_t tbox) { if (!tbox) return; free(tbox); } img_t txt_box_render(textbox_t tbox) { img_t old_screen; img_t dst; struct textbox *box = (struct textbox *)tbox; if (!tbox) return NULL; dst = gfx_new(box->w, box->h); if (!dst) return NULL; old_screen = screen; screen = dst; gfx_clear(0, 0, box->w, box->h); /* gfx_clip(0, 0, box->w, box->h); printf("line: %d\n", box->line->y); */ txt_layout_draw_ex(box->lay, box->line, 0, - box->off, box->off, box->h, NULL); /* gfx_noclip(); */ screen = old_screen; return dst; } /* Draws game content */ void txt_box_draw(textbox_t tbox, int x, int y) { struct textbox *box = (struct textbox *)tbox; if (!tbox) return; gfx_clip(x, y, box->w, box->h); /* printf("line: %d\n", box->line->y); */ txt_layout_draw_ex(box->lay, box->line, x, y - box->off, box->off, box->h, NULL); gfx_noclip(); } void txt_box_update_links(textbox_t tbox, int x, int y, clear_fn clear) { struct textbox *box = (struct textbox *)tbox; if (!tbox) return; gfx_clip(x, y, box->w, box->h); /* printf("line: %d\n", box->line->y); */ txt_layout_draw_ex(box->lay, box->line, x, y - box->off, box->off, box->h, clear); gfx_noclip(); } void txt_layout_update_links(layout_t layout, int x, int y, clear_fn clear) { struct layout *lay = (struct layout *)layout; /* gfx_clip(x, y, box->w, box->h); printf("line: %d\n", box->line->y); */ txt_layout_draw_ex(lay, lay->lines, x, y, 0, lay->h, clear); /* gfx_noclip(); */ } img_t get_img(struct layout *layout, char *p, int *al) { int len; int align; img_t img; struct image *image; int escaped = 0; *al = 0; len = word_img(p, NULL); if (!len) return NULL; p += 3; p[len - 1] = 0; align = strcspn(p, "|"); if (!p[align]) align = 0; else { if (!strcmp(p + align + 1, "left")) *al = ALIGN_LEFT; else if (!strcmp(p + align + 1, "right")) *al = ALIGN_RIGHT; if (*al) { p[align] = 0; if (align && p[align - 1] == '\\') { p[align - 1] = 0; escaped = 1; } } } img = layout_lookup_image(layout, p); if (img) goto out; img = cache_get(layout->img_cache, p); if (!img) { unix_path(p); if (!(img = gfx_load_image(p))) { game_res_err_msg(p, debug_sw); goto out; } theme_img_scale(&img); /* bad style, no gfx layer :( */ } image = image_new(p, img); if (!image) { gfx_free_image(img); img = NULL; } else { layout_add_image(layout, image); image->free_it = 1; /* free on layout destroy */ /* if (gfx_img_w(img) <= GFX_MAX_CACHED_W && gfx_img_h(img) <= GFX_MAX_CACHED_H) */ cache_add(layout->img_cache, p, img); } out: if (align) { p[align] = '|'; if (escaped) p[align - 1] = '\\'; } p[len - 1] = '>'; if (!img) *al = 0; return img; } static char *get_word_token(char *p, int *token) { int len; char *r; char *val = NULL; len = word_token(p, NULL); if (token) *token = 0; if (!len) return p; if (token) *token = 1; p[len - 1 + 3] = 0; r = strdup((p + 3)); parse_esc_string(r, &val); free(p); if (val) { free(r); r = val; } return r; } char *process_token(char *ptr, struct layout *layout, struct line *line, struct xref **xref, int *sp) { int token; char *val = NULL; int bit = 0; int al = 0; int *cnt = NULL; char *eptr; token = gfx_get_token(ptr, &eptr, &val, sp); if (!token) return NULL; if (TOKEN(token) == TOKEN_B) { cnt = &layout->scnt[0]; bit = TTF_STYLE_BOLD; } else if (TOKEN(token) == TOKEN_I) { cnt = &layout->scnt[1]; bit = TTF_STYLE_ITALIC; } else if (TOKEN(token) == TOKEN_U) { cnt = &layout->scnt[2]; bit = TTF_STYLE_UNDERLINE; } else if (TOKEN(token) == TOKEN_S) { cnt = &layout->scnt[3]; #ifdef TTF_STYLE_STRIKETHROUGH bit = TTF_STYLE_STRIKETHROUGH; #else bit = TTF_STYLE_ITALIC; #endif } if (bit) { if (token & TOKEN_CLOSE) { -- (*cnt); if (*cnt < 0) /* fuzzy */ *cnt = 0; if (!*cnt) layout->style &= ~bit; } else { ++ (*cnt); layout->style |= bit; } goto out; } if (TOKEN(token) == TOKEN_L) al = ALIGN_LEFT; else if (TOKEN(token) == TOKEN_R) al = ALIGN_RIGHT; else if (TOKEN(token) == TOKEN_C) al = ALIGN_CENTER; else if (TOKEN(token) == TOKEN_J) al = ALIGN_JUSTIFY; if (al) { if (token & TOKEN_CLOSE) { layout->acnt --; if (layout->acnt <0) layout->acnt = 0; layout->align = layout->saved_align[layout->acnt]; } else { layout->saved_align[layout->acnt] = layout->align; layout->acnt ++; if (layout->acnt >= ALIGN_NEST) layout->acnt = ALIGN_NEST - 1; layout->align = al; line->align = al; } goto out; } al = 0; if (TOKEN(token) == TOKEN_T) al = ALIGN_TOP; else if (TOKEN(token) == TOKEN_D) al = ALIGN_BOTTOM; else if (TOKEN(token) == TOKEN_M) al = ALIGN_MIDDLE; if (al) { if (token & TOKEN_CLOSE) { layout->vcnt --; if (layout->vcnt <0) layout->vcnt = 0; layout->valign = layout->saved_valign[layout->vcnt]; } else { layout->saved_valign[layout->vcnt] = layout->valign; layout->vcnt ++; if (layout->vcnt >= ALIGN_NEST) layout->vcnt = ALIGN_NEST - 1; layout->valign = al; } goto out; } if (TOKEN(token) == TOKEN_X || TOKEN(token) == TOKEN_Y) { int pos; pos = atoi(val) * game_theme.scale; if (strchr(val, '%') && sscanf(val, "%d%%", &pos) == 1) { if (TOKEN(token) == TOKEN_Y) { if (layout->box) pos = layout->box->h * pos / 100; } else pos = layout->w * pos / 100; } if (TOKEN(token) == TOKEN_X) { line->tabx = pos; line->al_tabx = ALIGN_LEFT; if (strstr(val, "right")) line->al_tabx = ALIGN_RIGHT; else if (strstr(val, "center")) line->al_tabx = ALIGN_CENTER; } else { line->taby = pos; line->al_taby = ALIGN_BOTTOM; if (strstr(val, "top")) line->al_taby = ALIGN_TOP; else if (strstr(val, "middle")) line->al_taby = ALIGN_MIDDLE; } goto out; } if (TOKEN(token) == TOKEN_A) { if (token & TOKEN_CLOSE) { if (*xref) layout_add_xref(layout, *xref); *xref = NULL; } else { if (*xref) { eptr = NULL; goto out; } if (!strcmp(val, "#")) { /* jump anchor */ layout->anchor = line; } else { *xref = xref_new(val); } } } out: if (val) free(val); return eptr; } int get_unbreakable_len(struct layout *layout, const char *ptr) { int w = 0; int ww = 0; char *p, *eptr; while (ptr && *ptr) { int sp; while (gfx_get_token(ptr, &eptr, NULL, &sp)) { if (sp) return w; ptr = eptr; } p = get_word(ptr, &eptr, &sp); if (!p) return w; if (sp || !*p || cjk_here(p) || word_img(p, NULL) || (word_token(p, NULL) > 1)) { free(p); return w; } txt_size(layout->fn, p, &ww, NULL); ptr = eptr; w += ww; if (!*p) ptr ++; else if (is_delim(*(ptr - 1))) { free(p); break; } free(p); } return w; } int txt_layout_pos2off(layout_t lay, int pos, int *hh) { int off = 0; struct line *line; struct layout *layout = (struct layout*)lay; if (!layout) return 0; for (line = layout->lines; line && (line->pos <= pos); line = line->next) { off = line->y; /* + line->h; */ if (hh) *hh = line->h; } return off; } int txt_layout_anchor(layout_t lay, int *hh) { int off; struct line *line; struct layout *layout = (struct layout*)lay; if (!layout) return -1; line = layout->anchor; if (!line) return -1; off = line->y; /* + line->h; */ if (hh) *hh = line->h; return off; } static void line_y(layout_t lay, struct line *line) { int y = line->taby; if (line->taby < 0) return; if (line->al_taby == ALIGN_BOTTOM) { y -= line->h; } else if (line->al_taby == ALIGN_MIDDLE) y -= line->h/2; line->taby = -1; if (y > line->y) line->y = y; margin_rebase(lay); } static void word_x(struct line *line, struct word *word, int width) { if (line->tabx < 0) return; word->x = line->tabx - line->x; if (line->al_tabx == ALIGN_RIGHT) word->x -= word->w; else if (line->al_tabx == ALIGN_CENTER) word->x -= word->w/2; if (word->x + word->w > width) word->x = width - word->w; if (word->x < line->w) word->x = line->w; else line->w = word->x; line->tabx = -1; line->align = ALIGN_LEFT; } #ifdef _USE_HARFBUZZ static void layout_lines_dir(struct layout *layout) { /* Set direction of each line based on the first non-image, alphabet word in that line. */ struct word *word = NULL; struct line *ln = NULL; for (ln = layout->lines; ln; ln = ln->next) { for (word = ln->words; word; word = word->next ) { /* Continue until we get a word with some text (not letters or symbols) */ if (!word->isalpha) continue; if (!word->img) { ln->rtl = word->rtl; break; } } } } #endif void _txt_layout_add(layout_t lay, char *txt) { int sp = 0; int saved_style; int width; int img_align; struct margin *m; struct line *line, *lastline = NULL; struct layout *layout = (struct layout*)lay; char *p, *eptr; char *ptr = txt; struct xref *xref = NULL; int w = 0, h = 0, nl = 0; int spw; img_t img = NULL; if (!layout || !layout->fn) return; saved_style = layout->style; fnt_style(layout->fn, 0); txt_size(layout->fn, " ", &spw, NULL); if (layout->lines) { lastline = layout->lines->prev; lastline->pos = 0; } if (!lastline) { line = line_new(); if (!line) goto err; line->h = h; line->align = layout->align; } else { line = lastline; } line->x = layout_find_margin(layout, line->y, &width); while (ptr && *ptr) { struct word *word; int sp2, addlen = 0; int wtok; eptr = process_token(ptr, layout, line, &xref, &sp2); if (eptr) { ptr = eptr; if (xref && layout->style == saved_style) fnt_style(layout->fn, layout->lstyle); /* & ~TTF_STYLE_ITALIC); */ else fnt_style(layout->fn, layout->style);/* & ~TTF_STYLE_ITALIC); */ if (!ptr || !*ptr) break; if (sp2) sp = -1; continue; } if (sp == -1) { p = get_word(ptr, &eptr, NULL); sp = 1; } else p = get_word(ptr, &eptr, &sp); if (!p) break; img = get_img(layout, p, &img_align); if (!img_align) /* margins reset */ addlen = get_unbreakable_len(layout, eptr); wtok = 0; if (img) { w = gfx_img_w(img); h = gfx_img_h(img); if (img_align) { if (!line_margin(line)) { line->y = layout_skip_margin(layout, line->y); width = layout->w; line->x = 0; } if (width - w <= 0) img_align = 0; } } else { p = get_word_token(p, &wtok); if (wtok && *p == 0) sp = 1; #ifdef _USE_HARFBUZZ /* Correct size depends on the script and direction. Set them correctly before calling txt_size */ word = word_new(p); if (word) { word_detect_rtl(word, layout->rtl); TTF_SetDirection(hb_dir(word->rtl)); TTF_SetScript(word->script); txt_size(layout->fn, p, &w, &h); TTF_SetDirection(HB_DIRECTION_LTR); TTF_SetScript(HB_SCRIPT_COMMON); free(word); } #else txt_size(layout->fn, p, &w, &h); #endif h *= layout->fn_height; } nl = (wtok)?0:!*p; if (!line->h && !img_align && line_empty(line)) /* first word ? */ line->h = h; if (img_align && !line->w) line->h = 0; #if 0 if (!nl) { int ww = width - (line->w + ((sp && line->w)?spw:0) + addlen); p = word_hyphen(layout, p, ww, &eptr, &w); } #endif if ((line->num && (line->w + ((sp && line->w)?spw:0) + w + addlen) > width) || nl) { struct line *ol = line; h = 0; /* reset h for new line */ if ((layout->h) && (line->y + line->h) >= layout->h) break; if (line != lastline) { layout_add_line(layout, line); } line_y(layout, line); line_align(line, width, line->align, nl); line = line_new(); if (!line) { free(p); goto err; } line->align = layout->align; line->h = 0;/* h; */ line->y = ol->y + ol->h; /* line->x = 0; */ line->x = layout_find_margin(layout, line->y, &width); /* fprintf(stderr,"%d %d\n", line->x, width); */ if (nl) { ptr = eptr + 1; } free(p); /* ptr = eptr; */ line->pos = (int)(ptr - txt); continue; } if (h > line->h && !img_align) line->h = h; word = word_new(p); if (!word) { line_free(line); free(p); goto err; } word_detect_rtl(word, layout->rtl); word->valign = layout->valign; if (!sp && !line_empty(line)) word->unbrake = 1; word->style = layout->style; if (line->w && !word->unbrake) line->w += spw; word->w = w; word->x = line->w; word_x(line, word, width); word->img = img; word->img_align = img_align; if (img_align && (m = margin_new())) { int x2, w2; x2 = layout_find_margin(layout, line->y, &w2); if (img_align == ALIGN_LEFT) { line->x += w; m->w = x2 + w; } else m->w = layout->w - x2 - w2 + w; /* fprintf(stderr,"w: %d %d %d\n", width, w, width - w); */ width -= w; m->h = h; m->y = line->y; m->align = img_align; m->word = word; word->w = 0; if (img_align == ALIGN_LEFT) word->x = x2; else word->x = x2 + w2 - w; h = 0; w = 0; layout_add_margin(layout, m); } /* if (line->w) w += spw; */ line_add_word(line, word); if (xref) xref_add_word(xref, word); line->w += w; if (nl) eptr ++; ptr = eptr; free(p); } #ifdef _USE_HARFBUZZ layout_lines_dir(layout); #endif if (layout->h == 0) layout->h = line->y + line->h; /* if (line->num) { */ if (line != lastline) { layout_add_line(layout, line); } line_y(layout, line); line_align(line, width, line->align, nl); /* } else line_free(line); */ if (xref) layout_add_xref(layout, xref); layout->style = saved_style; return; err: txt_layout_free(layout); return; } void txt_layout_add(layout_t lay, char *txt) { struct layout *layout = (struct layout*)lay; if (layout) layout->h = 0; _txt_layout_add(lay, txt); } xref_t xref_next(xref_t x) { if (!x) return NULL; return ((struct xref*)x)->next; } xref_t xref_prev(xref_t x) { struct layout *l; if (!x) return NULL; l = ((struct xref*)x)->layout; if (x == l->xrefs) /* last one */ return NULL; x = ((struct xref*)x)->prev; return x; } xref_t txt_layout_xrefs(layout_t lay) { struct layout *layout = (struct layout*)lay; if (!layout) return NULL; return layout->xrefs; } int xref_valid(xref_t x) { struct xref *xref = (struct xref*)x; if (!xref) return -1; if (!xref->num) return -1; return 0; } int xref_position(xref_t x, int *xc, int *yc) { int i; int w = 0; struct line *line = NULL; struct word *word = NULL; struct xref *xref = (struct xref*)x; if (xref_valid(x)) return -1; for (i = 0; i < xref->num; i ++) { word = xref->words[i]; if (!word->img_align) w += word->w; } w = w/2; for (i = 0; i < xref->num; i ++) { word = xref->words[i]; if (word->img_align) continue; line = word->line; w -= word->w; if (w < 0) break; } if (!line || !word) return -1; if (xc) *xc = line_pos(line, line->x + word->x + word->w + w); if (yc) *yc = line->y + line->h / 2; return 0; } xref_t txt_layout_xref(layout_t lay, int x, int y) { struct layout *layout = (struct layout*)lay; struct xref *xref; struct word *word; struct line *line; int i; if (!lay || x < 0 || y < 0) return NULL; for (xref = layout->xrefs; xref; xref = xref->next) { for (i = 0; i < xref->num; i ++) { int hh, yy, lx; word = xref->words[i]; line = word->line; lx = line_pos(line, x); if (word->img_align) continue; if (y < line->y || y > line->y + line->h) continue; yy = vertical_align(word, &hh); if (y < line->y + yy || y > line->y + yy + hh) continue; if (lx < line->x + word->x) continue; if (lx <= line->x + word->x + word->w) return xref; if (word->next && word->next->xref == xref && lx < line->x + word->next->x + word->next->w) { yy = vertical_align(word->next, &hh); if (y < line->y + yy || y > line->y + yy + hh) continue; return xref; } } } return NULL; } layout_t xref_layout(xref_t x) { struct xref *xref = (struct xref*)x; if (!xref) return NULL; return xref->layout; } char *xref_get_text(xref_t x) { struct xref *xref = (struct xref*)x; if (!xref) return NULL; return xref->link; } void xref_set_active(xref_t x, int val) { struct xref *xref = (struct xref*)x; if (!xref) return; xref->active = val; } int xref_get_active(xref_t x) { struct xref *xref = (struct xref*)x; if (!xref) return 0; return xref->active; } layout_t txt_layout(fnt_t fn, int align, int width, int height) { struct layout *layout; layout = layout_new(fn, width, height); if (!layout) return NULL; layout->align = align; /* _txt_layout_add(layout, txt); */ return layout; } void txt_layout_set(layout_t lay, char *txt) { struct layout *layout = (struct layout*)lay; if (!layout) return; layout->h = 0; _txt_layout_free(lay); _txt_layout_add(lay, txt); } void _txt_layout_real_size(layout_t lay, struct line *line, int *pw, int *ph) { int w = 0; int h = 0; struct margin *margin; struct layout *layout = (struct layout*)lay; if (!layout) return; if (!line) line = layout->lines; for ( ; line; line = line->next) { while (!line->num && line->next) line = line->next; if (line->w > w) w = line->w; if (line->num && line->y + line->h > h) h = line->y + line->h; } for (margin = layout->margin; margin; margin = margin->next) { if (margin->y + margin->h > h) h = margin->y + margin->h; } if (pw) *pw = w; if (ph) *ph = h; } void txt_layout_real_size(layout_t lay, int *pw, int *ph) { _txt_layout_real_size(lay, NULL, pw, ph); } void txt_box_real_size(textbox_t box, int *pw, int *ph) { if (!box) return; if (pw) _txt_layout_real_size(txt_box_layout(box), NULL, pw, ph); else {/* faster path */ struct line *line = ((struct layout*)txt_box_layout(box))->lines; struct line *lines = line; if (lines) line = lines->prev; for (; line != lines && !line->num; line = line->prev); _txt_layout_real_size(txt_box_layout(box), line, NULL, ph); } } int gfx_cursor(int *xp, int *yp) { int x, y; x = mouse_x; y = mouse_y; if (xp) *xp = x; if (yp) *yp = y; return SDL_GetMouseState(NULL, NULL); } void gfx_warp_cursor(int x, int y) { float sx, sy; SDL_Rect rect; #ifdef _USE_SWROTATE if (gfx_flip_rotate) { /* TODO? */ int tmp; tmp = y; y = x; x = gfx_height - tmp; } #endif SDL_RenderGetViewport(Renderer, &rect); SDL_RenderGetScale(Renderer, &sx, &sy); x = (x + rect.x) * sx; y = (y + rect.y) * sy; SDL_WarpMouseInWindow(SDL_VideoWindow, x, y); } static int ALPHA_STEPS = 4; static volatile int fade_step_nr = -1; int gfx_fading(void) { return (fade_step_nr != -1); } static img_t fade_bg = NULL; static img_t fade_fg = NULL; static void *fade_aux = NULL; static void (*fade_cb)(void *) = NULL; static SDL_TimerID fade_timer; static long gfx_change_nr = 0; static SDL_Texture *fade_bg_texture = NULL; static SDL_Texture *fade_fg_texture = NULL; static void update_gfx(void) { img_t img = fade_fg; if (fade_step_nr == -1 || !img || !fade_bg || !fade_fg) return; gfx_render_copy(fade_bg_texture, NULL, 1); SDL_SetTextureAlphaMod(fade_fg_texture, (SDL_ALPHA_OPAQUE * (fade_step_nr + 1)) / ALPHA_STEPS); gfx_render_copy(fade_fg_texture, NULL, 0); if (game_cursor_show) gfx_render_cursor(); SDL_RenderPresent(Renderer); fade_step_nr ++; if (fade_step_nr == ALPHA_STEPS) fade_step_nr = -1; } static void gfx_change_screen_step(void *aux) { gfx_change_nr --; if (gfx_fading()) { update_gfx(); } if (gfx_fading()) return; gfx_cancel_change_screen(); return; } static Uint32 update(Uint32 interval, void *aux) { if (!gfx_fading()) return 0; if (gfx_change_nr > 0) return interval; gfx_change_nr ++; push_user_event(gfx_change_screen_step, NULL); return interval; } void gfx_cancel_change_screen(void) { if (!fade_bg) return; fade_step_nr = -1; SDL_RemoveTimer(fade_timer); SDL_DestroyTexture(fade_fg_texture); SDL_DestroyTexture(fade_bg_texture); game_cursor(CURSOR_CLEAR); gfx_copy(fade_fg, 0, 0); game_cursor(CURSOR_ON); gfx_flip(); gfx_commit(); gfx_free_image(fade_bg); fade_bg = NULL; if (fade_cb) fade_cb(fade_aux); } void gfx_change_screen(img_t src, int steps, void (*callback)(void *), void *aux) { struct inp_event ev; if (steps <= 1 || !opt_fading) { gfx_copy(src, 0, 0); game_cursor(CURSOR_ON); gfx_flip(); if (callback) callback(aux); return; } gfx_change_nr = 0; fade_fg = NULL; fade_aux = aux; fade_cb = callback; fade_bg = gfx_grab_screen(0, 0, gfx_width, gfx_height); if (!fade_bg) /* ok, i like kernel logic. No memory, but we must work! */ return; fade_fg = src; fade_bg_texture = SDL_CreateTextureFromSurface(Renderer, Surf(fade_bg)); if (!fade_bg_texture) goto err; SDL_SetTextureAlphaMod(fade_bg_texture, SDL_ALPHA_OPAQUE); SDL_SetTextureBlendMode(fade_bg_texture, SDL_BLENDMODE_NONE); fade_fg_texture = SDL_CreateTextureFromSurface(Renderer, Surf(src)); if (!fade_fg_texture) goto err2; SDL_SetTextureBlendMode(fade_fg_texture, SDL_BLENDMODE_BLEND); memset(&ev, 0, sizeof(ev)); ALPHA_STEPS = steps; fade_step_nr = 0; fade_timer = SDL_AddTimer(60, update, NULL); return; err2: SDL_DestroyTexture(fade_bg_texture); err: gfx_free_image(fade_bg); fade_bg = NULL; return; } int gfx_init(void) { SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); if (render_sw) SDL_SetHint(SDL_HINT_RENDER_DRIVER, render_sw); #if defined(_WIN32) /* do not use buggy D3D by default: fullscreen problem with NVidia */ else if (!software_sw) SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); #endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); return -1; } if (!(images = cache_init(-1, gfx_cache_free_image))) { fprintf(stderr, "Can't init cache subsystem.\n"); gfx_done(); return -1; } /* SDL_DisableScreenSaver(); */ return 0; } void gfx_done(void) { if (screen) gfx_free_image(screen); /* if (SDL_VideoTexture) SDL_DestroyTexture(SDL_VideoTexture); */ if (Renderer) SDL_DestroyRenderer(Renderer); if (SDL_VideoWindow) SDL_DestroyWindow(SDL_VideoWindow); cache_free(images); images = NULL; SDL_Quit(); } gtimer_t gfx_add_timer(int delay, int (*fn)(int, void*), void *aux) { return (gtimer_t)SDL_AddTimer(delay, (SDL_TimerCallback)fn, aux); } void gfx_del_timer(gtimer_t han) { if (han) SDL_RemoveTimer((SDL_TimerID)han); } unsigned long gfx_ticks(void) { return SDL_GetTicks(); } int gfx_pending(void) { return queue_dirty; } int gfx_set_title(const char *title) { char stitle[4096]; if (!title) { strcpy( stitle, "INSTEAD - " ); strcat( stitle, VERSION ); title = stitle; } if (SDL_VideoWindow) SDL_SetWindowTitle(SDL_VideoWindow, title); return 0; } int gfx_set_icon(img_t ic) { if (SDL_VideoWindow) { if (ic) SDL_SetWindowIcon(SDL_VideoWindow, Surf(ic)); else if (icon) SDL_SetWindowIcon(SDL_VideoWindow, icon); } return 0; } float gfx_get_dpi(void) { float hdpi = 96.0f; if (dpi_sw > 0) return (float)dpi_sw; #if SDL_VERSION_ATLEAST(2,0,4) if (SDL_GetDisplayDPI(SDL_CurrentDisplay, NULL, &hdpi, NULL)) hdpi = 96.0f; #endif return hdpi; } instead-3.5.2+dfsg/src/graphics.h000066400000000000000000000224231467622671600166530ustar00rootroot00000000000000/* * Copyright 2009-2020 Peter Kosyh * * 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. * */ #ifndef __GRAPHICS_H__ #define __GRAPHICS_H__ #include /* #define GFX_CACHE_SIZE 64 #define GFX_MAX_CACHED_W 256 #define GFX_MAX_CACHED_H 256 #define WORD_CACHE_SIZE 1024 #define LINK_CACHE_SIZE 64 */ typedef int gtimer_t; #define NULL_TIMER 0 struct _img_t; typedef struct _img_t* img_t; typedef void* fnt_t; typedef void* layout_t; typedef void* textbox_t; typedef void* xref_t; typedef void* word_t; typedef struct { int r; int g; int b; int a; } color_t; #define ALIGN_LEFT 1 #define ALIGN_RIGHT 2 #define ALIGN_CENTER 4 #define ALIGN_JUSTIFY 8 #define ALIGN_TOP 16 #define ALIGN_BOTTOM 32 #define ALIGN_MIDDLE 64 #define STYLE_NORMAL 0x00 #define STYLE_BOLD 0x01 #define STYLE_ITALIC 0x02 #define STYLE_UNDERLINE 0x04 extern color_t gfx_col(int r, int g, int b); extern int gfx_init(void); extern void gfx_done(void); extern int gfx_parse_color (const char *spec, color_t *def); extern void gfx_flip(void); extern void gfx_commit(void); extern cache_t gfx_image_cache(void); extern img_t gfx_screen(img_t nscreen); extern void gfx_bg(int x, int y, int w, int h, color_t col, color_t brdcol); extern void gfx_noclip(void); extern void gfx_clip(int x, int y, int w, int h); extern void gfx_getclip(int *x, int *y, int *w, int *h); extern void gfx_img_clip(img_t img, int x, int y, int w, int h); extern void gfx_img_noclip(img_t img); extern int gfx_width; extern int gfx_height; extern int gfx_fs; extern int gfx_video_init(void); extern int gfx_set_mode(int w, int h, int fs); extern int gfx_get_mode(int n, int *w, int *h); extern int gfx_get_token(const char *ptr, char **eptr, char **val, int *sp); #define MODE_ANY 0 #define MODE_H 1 #define MODE_V 2 extern int gfx_get_max_mode(int *w, int *h, int o); extern int gfx_check_mode(int w, int h); extern int gfx_set_title(const char *title); extern int gfx_set_icon(img_t icon); extern int gfx_next_mode(int *w, int *h); extern int gfx_prev_mode(int *w, int *h); extern void gfx_update(int x, int y, int w, int h); extern void gfx_video_done(void); extern void gfx_clear(int x, int y, int w, int h); extern void gfx_resize(int w, int h); extern void gfx_copy_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy); extern void gfx_draw(img_t p, int x, int y); extern void gfx_copy(img_t p, int x, int y); extern void gfx_draw_wh(img_t p, int x, int y, int w, int h); extern img_t gfx_grab_screen(int x, int y, int w, int h); extern img_t gfx_new(int w, int h); extern img_t gfx_new_rgba(int w, int h); extern img_t gfx_new_from(int w, int h, unsigned char *pixels); extern img_t gfx_dup(img_t src); extern img_t gfx_load_image(char *filename); extern void gfx_free_image(img_t pixmap); extern int gfx_img_w(img_t pixmap); extern int gfx_img_h(img_t pixmap); extern img_t gfx_combine(img_t src, img_t dst); extern void gfx_set_alpha(img_t src, int alpha); extern int gfx_unset_alpha(img_t src); extern void gfx_set_colorkey(img_t src, color_t col); extern void gfx_unset_colorkey(img_t src); extern img_t gfx_alpha_img(img_t src, int alpha); extern img_t gfx_display_alpha(img_t src); extern img_t gfx_scale(img_t src, float xscale, float yscale, int smooth); extern img_t gfx_rotate(img_t src, float angle, int smooth); extern void gfx_draw_bg(img_t p, int x, int y, int width, int height); extern void gfx_draw_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy); extern void gfx_draw_from_alpha(img_t s, int x, int y, int w, int h, img_t d, int xx, int yy, int alpha); extern void gfx_compose_from(img_t p, int x, int y, int width, int height, img_t to, int xx, int yy); extern int gfx_cursor(int *xp, int *yp); extern void gfx_warp_cursor(int x, int y); extern void gfx_change_screen(img_t src, int steps, void (*callback)(void *), void *); extern void gfx_cancel_change_screen(void); extern int gfx_fading(void); extern void gfx_img_fill(img_t img, int x, int y, int w, int h, color_t col); extern void gfx_fill(int x, int y, int w, int h, color_t col); extern int gfx_get_pixel(img_t src, int x, int y, color_t *color); extern int gfx_set_pixel(img_t src, int x, int y, color_t color); extern void gfx_put_pixels(img_t src); extern unsigned char *gfx_get_pixels(img_t src); extern fnt_t fnt_load(const char *fname, int size); extern void fnt_free(fnt_t); extern int fnt_height(fnt_t fn); extern void fnt_style(fnt_t fn, int style); extern img_t fnt_render(fnt_t fn, const char *p, color_t col); extern void txt_draw(fnt_t fnt, const char *txt, int x, int y, color_t col); extern void txt_size(fnt_t fnt, const char *txt, int *w, int *h); /* extern int txt_width(fnt_t fnt, const char *txt); extern layout_t txt_layout(fnt_t fn, char *txt, int width, int height); */ extern layout_t txt_layout(fnt_t fn, int align, int width, int height); extern void txt_layout_add(layout_t lay, char *txt); extern void txt_layout_set(layout_t lay, char *txt); extern void txt_layout_draw(layout_t lay, int x, int y); extern void txt_layout_free(layout_t lay); extern void _txt_layout_free(layout_t lay); /* do not free lay obj */ extern xref_t txt_layout_xref(layout_t lay, int x, int y); extern void txt_layout_color(layout_t lay, color_t fg); extern void txt_layout_rtl(layout_t lay, int rtl); extern fnt_t txt_layout_font(layout_t lay); extern void txt_layout_font_height(layout_t lay, float height); extern textbox_t txt_layout_box(layout_t lay); extern void txt_layout_link_color(layout_t lay, color_t link); extern void txt_layout_active_color(layout_t lay, color_t link); extern void txt_layout_link_style(layout_t lay, int style); extern int txt_layout_add_img(layout_t lay, const char *name, img_t img); extern img_t txt_layout_images(layout_t lay, void **v); /* enumerator */ extern word_t txt_layout_words(layout_t lay, word_t w); /* enumerator */ extern int word_geom(word_t v, int *x, int *y, int *w, int *h); extern img_t word_image(word_t v); extern void txt_layout_size(layout_t lay, int *w, int *h); extern textbox_t txt_box(int w, int h); extern layout_t txt_box_layout(textbox_t tbox); extern void txt_box_set(textbox_t tbox, layout_t lay); extern void txt_box_free(textbox_t tbox); extern void txt_box_draw(textbox_t tbox, int x, int y); extern void txt_box_next(textbox_t tbox); extern void txt_box_prev(textbox_t tbox); extern void txt_box_next_line(textbox_t tbox); extern void txt_box_prev_line(textbox_t tbox); extern void txt_box_scroll(textbox_t tbox, int disp); extern xref_t txt_box_xref(textbox_t tbox, int x, int y); extern xref_t txt_box_xrefs(textbox_t tbox); extern void txt_box_real_size(textbox_t box, int *pw, int *ph); extern int txt_box_off(textbox_t tbox); extern void txt_box_size(textbox_t tbox, int *w, int *h); extern void txt_box_resize(textbox_t tbox, int w, int h); typedef void (*clear_fn)(int x, int y, int w, int h); extern void txt_box_update_links(textbox_t tbox, int x, int y, clear_fn); extern void txt_layout_update_links(layout_t layout, int x, int y, clear_fn clear); extern void txt_layout_real_size(layout_t lay, int *w, int *h); extern void txt_layout_set_size(layout_t lay, int w, int h); /* without text only */ extern int txt_layout_pos2off(layout_t lay, int pos, int *hh); extern int txt_layout_anchor(layout_t lay, int *hh); extern img_t txt_box_render(textbox_t tbox); extern char *xref_get_text(xref_t x); extern void xref_set_active(xref_t x, int val); extern int xref_get_active(xref_t x); extern xref_t xref_next(xref_t x); extern xref_t xref_prev(xref_t x); extern int xref_position(xref_t x, int *xc, int *yc); extern int xref_valid(xref_t x); extern xref_t txt_layout_xrefs(layout_t lay); extern layout_t xref_layout(xref_t x); typedef void (*update_fn)(int x, int y, int w, int h); extern void xref_update(xref_t xref, int x, int y, clear_fn clear, update_fn update); extern void gfx_start_anim(img_t img); extern int gfx_is_drawn_anims(void); extern void gfx_stop_anim(img_t img); extern int gfx_frame_anim(img_t img); extern void gfx_del_timer(gtimer_t han); extern gtimer_t gfx_add_timer(int delay, int (*fn)(int, void*), void *aux); extern void gfx_update_anim(img_t img, update_fn update); extern void gfx_dispose_anim(img_t p); extern unsigned long gfx_ticks(void); extern void gfx_set_cursor(img_t cur, int xc, int yc); extern int gfx_pending(void); extern float gfx_get_dpi(void); #endif instead-3.5.2+dfsg/src/input.c000066400000000000000000000454711467622671600162150ustar00rootroot00000000000000/* * Copyright 2009-2024 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" #include static int m_focus = 1; static int m_minimized = 0; int minimized(void) { if (nopause_sw) return 0; return m_minimized; } int mouse_focus(void) { return m_focus; } int mouse_cursor(int on) { if (nocursor_sw) return 0; if (on) SDL_ShowCursor(SDL_ENABLE); else SDL_ShowCursor(SDL_DISABLE); return 0; } void push_user_event(void (*p) (void*), void *data) { SDL_Event event; SDL_UserEvent uevent; memset(&event, 0, sizeof(event)); memset(&uevent, 0, sizeof(uevent)); uevent.type = SDL_USEREVENT; uevent.code = 0; event.type = SDL_USEREVENT; uevent.data1 = (void*) p; uevent.data2 = data; event.user = uevent; SDL_PushEvent(&event); } int system_clipboard(const char *text, char **buf) { if (buf) { if (!SDL_HasClipboardText()) return -1; *buf = SDL_GetClipboardText(); if (*buf == NULL) return -1; return 0; } if (!text) return -1; return SDL_SetClipboardText(text); } #ifdef SAILFISHOS static SDL_FingerID finger_mouse = 0; static void touch_mouse_event(SDL_Event *sevent) { SDL_Event event; memset(&event, 0, sizeof(event)); if (sevent->type == SDL_FINGERDOWN) { finger_mouse = sevent->tfinger.fingerId; event.type = SDL_MOUSEBUTTONDOWN; } else if (sevent->type == SDL_FINGERUP) { finger_mouse = 0; event.type = SDL_MOUSEBUTTONUP; } else if (sevent->type == SDL_FINGERMOTION) { if (sevent->tfinger.fingerId != finger_mouse) return; event.type = SDL_MOUSEMOTION; } event.button.x = sevent->tfinger.x; event.button.y = sevent->tfinger.y; event.button.clicks = 1; event.button.button = 1; SDL_PushEvent(&event); } #endif static unsigned long last_press_ms = 0; static unsigned long last_repeat_ms = 0; extern void gfx_finger_pos_scale(float x, float y, int *ox, int *oy, int norm); #define INPUT_REP_DELAY_MS 500 #define INPUT_REP_INTERVAL_MS 30 #define GAMEPAD_TICKS 20 #if defined(IOS) || defined(ANDROID) int HandleAppEvents(void *userdata, SDL_Event *event) { switch (event->type) { case SDL_APP_LOWMEMORY: return 0; case SDL_APP_WILLENTERBACKGROUND: /* Prepare your app to go into the background. Stop loops, etc. This gets called when the user hits the home button, or gets a call. */ return 0; case SDL_APP_DIDENTERBACKGROUND: /* This will get called if the user accepted whatever sent your app to the background. If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops. When you get this, you have 5 seconds to save all your state or the app will be terminated. Your app is NOT active at this point. */ /* snd_pause(1); */ m_minimized = 1; if (opt_autosave && curgame_dir) /* autosave the game */ game_save(0); cfg_save(); return 0; case SDL_APP_WILLENTERFOREGROUND: /* This call happens when your app is coming back to the foreground. Restore all your state here. */ return 0; case SDL_APP_DIDENTERFOREGROUND: /* Restart your loops here. Your app is interactive and getting CPU again. */ /* snd_pause(0); */ m_minimized = 0; game_flip(); game_gfx_commit(0); return 0; case SDL_APP_TERMINATING: #if !defined(ANDROID) cfg_save(); game_done(0); snd_done(); gfx_video_done(); gfx_done(); #endif return 0; default: /* No special processing, add it to the event queue */ return 1; } } #endif static gtimer_t gamepad_timer = NULL_TIMER; static SDL_GameController *gamepad = NULL; static int deadzone = 8192; const float MOUSE_SHIFT_MIN = 1.0; const float MOUSE_SHIFT_MAX = 10.0; static int gamepad_deadzone(SDL_GameController *g) { #if SDL_VERSION_ATLEAST(2,0,12) switch (SDL_GameControllerGetType(g)) { case SDL_CONTROLLER_TYPE_UNKNOWN: case SDL_CONTROLLER_TYPE_XBOXONE: case SDL_CONTROLLER_TYPE_XBOX360: case SDL_CONTROLLER_TYPE_PS3: return 10000; case SDL_CONTROLLER_TYPE_PS4: case SDL_CONTROLLER_TYPE_PS5: return 4096; case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO: return 8192; // Actual dead-zone should be closer to 10% of full-scale, but we use this to account for variances in 3rd-party controllers case SDL_CONTROLLER_TYPE_VIRTUAL: return 8192; default: return 8192; } #else return 8192; #endif } static int gamepad_mouse_shift(int axis_value) { float range; if (abs(axis_value) < deadzone) return 0; range = 32768.0 - deadzone; if (axis_value > deadzone) return MOUSE_SHIFT_MIN + (MOUSE_SHIFT_MAX - MOUSE_SHIFT_MIN) * (axis_value - deadzone) / range; else return -MOUSE_SHIFT_MIN + (MOUSE_SHIFT_MAX - MOUSE_SHIFT_MIN) * (axis_value + deadzone) / range; } static void gamepad_init(void) { int i; static char gamepad_cfg[PATH_MAX] = ""; if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) { fprintf(stderr, "Couldn't initialize GameController subsystem: %s\n", SDL_GetError()); return; } for (i = 0; i < SDL_NumJoysticks(); ++i) { if (SDL_IsGameController(i)) { gamepad = SDL_GameControllerOpen(i); if (gamepad) { fprintf(stderr, "Found gamepad: %s\n", SDL_GameControllerName(gamepad)); deadzone = gamepad_deadzone(gamepad); break; } else { fprintf(stderr, "Could not open gamepad %i: %s\n", i, SDL_GetError()); } } } snprintf(gamepad_cfg, sizeof(gamepad_cfg) - 1, "%s/gamecontrollerdb.txt", appdir()); SDL_GameControllerAddMappingsFromFile(gamepad_cfg); } static void gamepad_done(void) { if(gamepad) { gfx_del_timer(gamepad_timer); SDL_GameControllerClose(gamepad); } if(SDL_WasInit(SDL_INIT_GAMECONTROLLER)) SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); } static void gamepad_check_triggers(void) { SDL_Event event; memset(&event, 0, sizeof(event)); event.type = SDL_MOUSEWHEEL; int trigger_left = 0, trigger_right = 0; trigger_left = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERLEFT); trigger_right = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_TRIGGERRIGHT); if (abs(trigger_left) > deadzone) { event.wheel.y = 1; SDL_PushEvent(&event); } else if (abs(trigger_right) > deadzone) { event.wheel.y = -1; SDL_PushEvent(&event); } } static int gamepad_timer_fn(int interval, void *p) { SDL_Event event; int axis_x = 0, axis_y = 0; if (!gamepad) return interval; gamepad_check_triggers(); axis_x = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTX); axis_y = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_RIGHTY); if (abs(axis_x) <= deadzone && abs(axis_y) <= deadzone) { axis_x = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_LEFTX); axis_y = SDL_GameControllerGetAxis(gamepad, SDL_CONTROLLER_AXIS_LEFTY); } if (abs(axis_x) > deadzone || abs(axis_y) > deadzone) { memset(&event, 0, sizeof(event)); event.type = SDL_MOUSEMOTION; gfx_cursor(&event.button.x, &event.button.y); event.button.x += ceil(game_theme.scale * gamepad_mouse_shift(axis_x)); event.button.y += ceil(game_theme.scale * gamepad_mouse_shift(axis_y)); gfx_warp_cursor(event.button.x, event.button.y); SDL_PushEvent(&event); } return interval; } static int gamepad_mouse_event(SDL_Event *ev) { int rc = 0; SDL_Event event; memset(&event, 0, sizeof(event)); gfx_cursor(&event.button.x, &event.button.y); event.type = SDL_MOUSEMOTION; event.button.clicks = 1; event.button.button = 1; if (ev->type == SDL_CONTROLLERBUTTONDOWN) { if (ev->cbutton.button != SDL_CONTROLLER_BUTTON_LEFTSTICK && ev->cbutton.button != SDL_CONTROLLER_BUTTON_RIGHTSTICK) return 0; event.type = SDL_MOUSEBUTTONDOWN; rc = 1; } else if (ev->type == SDL_CONTROLLERBUTTONUP) { if (ev->cbutton.button != SDL_CONTROLLER_BUTTON_LEFTSTICK && ev->cbutton.button != SDL_CONTROLLER_BUTTON_RIGHTSTICK) return 0; event.type = SDL_MOUSEBUTTONUP; rc = 1; } else if (ev->type == SDL_CONTROLLERAXISMOTION) { if (gamepad_timer == NULL_TIMER) gamepad_timer = gfx_add_timer(GAMEPAD_TICKS, gamepad_timer_fn, NULL); } if (rc) SDL_PushEvent(&event); return rc; } static int gamepad_map(struct inp_event *inp) { const char *key; switch(inp->code) { case SDL_CONTROLLER_BUTTON_DPAD_UP: key = "up"; break; case SDL_CONTROLLER_BUTTON_DPAD_DOWN: key = "down"; break; case SDL_CONTROLLER_BUTTON_DPAD_LEFT: key = "left"; break; case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: key = "right"; break; case SDL_CONTROLLER_BUTTON_A: /* emulate click */ inp->type = (inp->type == KEY_DOWN)?MOUSE_DOWN:MOUSE_UP; gfx_cursor(&inp->x, &inp->y); inp->code = 1; return 1; case SDL_CONTROLLER_BUTTON_B: key = "space"; break; case SDL_CONTROLLER_BUTTON_X: key = "tab"; break; case SDL_CONTROLLER_BUTTON_Y: key = "return"; break; case SDL_CONTROLLER_BUTTON_START: key = "escape"; break; case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: key = "page up"; break; case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: key = "page down"; break; default: return 0; } strncpy(inp->sym, key, sizeof(inp->sym)); inp->sym[sizeof(inp->sym) - 1] = 0; return 1; } int input_init(void) { gamepad_init(); /* SDL_EnableKeyRepeat(500, 30); */ /* TODO ? */ last_press_ms = 0; last_repeat_ms = 0; #if defined(IOS) || defined(ANDROID) SDL_SetEventFilter(HandleAppEvents, NULL); #endif return 0; } void input_done(void) { gamepad_done(); } void input_clear(void) { SDL_Event event; while (SDL_PollEvent(&event)); return; } void input_uevents(void) { char *g = curgame_dir; SDL_Event peek; curgame_dir = NULL; while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_USEREVENT, SDL_USEREVENT) > 0) { void (*p) (void*) = (void (*)(void*)) peek.user.data1; if (p) p(peek.user.data2); } curgame_dir = g; } static void key_compat(struct inp_event *inp) { int len = strlen(inp->sym); if (!strcmp(inp->sym, "pageup")) strcpy(inp->sym, "page up"); else if (!strcmp(inp->sym, "pagedown")) strcpy(inp->sym, "page down"); else if (!strcmp(inp->sym, "numlock")) strcpy(inp->sym, "num lock"); else if (!strcmp(inp->sym, "scrolllock")) strcpy(inp->sym, "scroll lock"); else if (!strcmp(inp->sym, "capslock")) strcpy(inp->sym, "caps lock"); else if (len >= 8 && !strncmp(inp->sym, "keypad ", 7)) { inp->sym[0] = '['; strcpy(inp->sym + 1, inp->sym + 7); strcpy(inp->sym + 1 + len - 7, "]"); } } #if defined(IOS) || defined(SAILFISHOS) static unsigned long touch_stamp = 0; static int touch_num = 0; #endif int finger_pos(const char *finger, int *x, int *y, float *pressure) { SDL_TouchID tid; SDL_FingerID fid; SDL_Finger *f; int i, n; i = hex2data(finger, &fid, sizeof(fid)); if (i != sizeof(fid) * 2 || finger[i] != ':') return -1; if (hex2data(finger + i + 1, &tid, sizeof(tid)) != sizeof(tid) * 2) return -1; n = SDL_GetNumTouchFingers(tid); if (n <= 0) return -1; for (i = 0; i < n; i++) { f = SDL_GetTouchFinger(tid, i); if (f->id == fid) { if (pressure) *pressure = f->pressure; gfx_finger_pos_scale(f->x, f->y, x, y, 1); return 0; } } return -1; } int input(struct inp_event *inp, int wait) { int rc; SDL_Event event; SDL_Event peek; memset(&event, 0, sizeof(event)); memset(&peek, 0, sizeof(peek)); #if !defined(__EMSCRIPTEN__) if (wait) { rc = SDL_WaitEvent(&event); } else #endif rc = SDL_PollEvent(&event); if (!rc) return 0; if (gamepad_mouse_event(&event)) return AGAIN; inp->sym[0] = 0; inp->type = 0; inp->count = 1; switch(event.type){ case SDL_TEXTINPUT: inp->type = KEY_TEXT; strncpy(inp->sym, event.text.text, sizeof(inp->sym)); inp->sym[sizeof(inp->sym) - 1] = 0; break; case SDL_MULTIGESTURE: case SDL_FINGERMOTION: if (DIRECT_MODE && !game_paused()) return AGAIN; if (SDL_PeepEvents(&peek, 1, SDL_PEEKEVENT, event.type, event.type) > 0) return AGAIN; /* to avoid flickering */ #if defined(SAILFISHOS) touch_mouse_event(&event); #endif break; case SDL_FINGERUP: #ifdef IOS touch_num = 0; #endif case SDL_FINGERDOWN: #if defined(SAILFISHOS) touch_mouse_event(&event); #endif #if defined(IOS) || defined(SAILFISHOS) if (event.type == SDL_FINGERDOWN) { if (gfx_ticks() - touch_stamp > 100) { touch_num = 0; touch_stamp = gfx_ticks(); } touch_num ++; if (touch_num >= 3) { inp->type = KEY_DOWN; inp->code = 0; strncpy(inp->sym, "escape", sizeof(inp->sym)); break; } } #endif #if SDL_VERSION_ATLEAST(2,0,7) /* broken. normalized by event watcher */ gfx_finger_pos_scale(event.tfinger.x, event.tfinger.y, &inp->x, &inp->y, 0); #else gfx_finger_pos_scale(event.tfinger.x, event.tfinger.y, &inp->x, &inp->y, 1); #endif inp->type = (event.type == SDL_FINGERDOWN) ? FINGER_DOWN : FINGER_UP; data2hex(&event.tfinger.fingerId, sizeof(event.tfinger.fingerId), inp->sym); inp->sym[sizeof(event.tfinger.fingerId) * 2] = ':'; data2hex(&event.tfinger.touchId, sizeof(event.tfinger.touchId), inp->sym + sizeof(event.tfinger.fingerId) * 2 + 1); inp->sym[sizeof(event.tfinger.fingerId) * 2 + 1 + sizeof(event.tfinger.touchId) * 2] = 0; break; case SDL_CONTROLLERBUTTONDOWN: inp->type = KEY_DOWN; inp->code = event.cbutton.button; if (!gamepad_map(inp)) return AGAIN; break; case SDL_CONTROLLERBUTTONUP: inp->type = KEY_UP; inp->code = event.cbutton.button; if (!gamepad_map(inp)) return AGAIN; break; case SDL_WINDOWEVENT: switch (event.window.event) { /* case SDL_WINDOWEVENT_SHOWN: */ case SDL_WINDOWEVENT_RESIZED: /* Android send this on screen rotate */ case SDL_WINDOWEVENT_SIZE_CHANGED: gfx_resize(event.window.data1, event.window.data2); /* Fall through */ case SDL_WINDOWEVENT_EXPOSED: if (m_minimized) { /* broken WM? no RESTORE msg? */ m_minimized = 0; snd_pause(0); } game_flip(); game_gfx_commit(0); break; case SDL_WINDOWEVENT_MINIMIZED: case SDL_WINDOWEVENT_RESTORED: m_minimized = (event.window.event == SDL_WINDOWEVENT_MINIMIZED && !opt_fs); snd_pause(!nopause_sw && m_minimized); break; #if defined(SAILFISHOS) case SDL_WINDOWEVENT_FOCUS_LOST: snd_pause(!nopause_sw); while (1) { /* pause */ SDL_WaitEvent(&event); if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) { snd_pause(0); break; } if (event.type == SDL_QUIT) { game_running = 0; return -1; } } break; #endif case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_FOCUS_GAINED: m_focus = 1; if (opt_fs) mouse_cursor(0); break; case SDL_WINDOWEVENT_LEAVE: m_focus = 0; if (opt_fs) mouse_cursor(1); /* is it hack?*/ break; default: break; } if (SDL_PeepEvents(&peek, 1, SDL_PEEKEVENT, SDL_WINDOWEVENT, SDL_WINDOWEVENT) > 0) return AGAIN; /* to avoid flickering */ return 0; case SDL_USEREVENT: { void (*p) (void*) = (void (*)(void*))event.user.data1; if (!p) /* idle cycles */ return 1; p(event.user.data2); return AGAIN; } case SDL_QUIT: game_running = 0; return -1; case SDL_KEYDOWN: /* A key has been pressed */ if (event.key.repeat) { if (DIRECT_MODE && !game_paused()) /* do not send key repeats */ return AGAIN; if (gfx_ticks() - last_press_ms < INPUT_REP_DELAY_MS) return AGAIN; if ((gfx_ticks() - last_repeat_ms) < INPUT_REP_INTERVAL_MS) return AGAIN; last_repeat_ms = gfx_ticks(); } else { last_press_ms = gfx_ticks(); last_repeat_ms = gfx_ticks(); } inp->type = KEY_DOWN; inp->code = event.key.keysym.scancode; strncpy(inp->sym, SDL_GetScancodeName(inp->code), sizeof(inp->sym)); inp->sym[sizeof(inp->sym) - 1] = 0; tolow(inp->sym); key_compat(inp); if (DIRECT_MODE && SDL_PeepEvents(&peek, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYUP) > 0) { if (peek.key.keysym.scancode == event.key.keysym.scancode && peek.key.repeat == 0) return AGAIN; } break; case SDL_KEYUP: inp->type = KEY_UP; inp->code = event.key.keysym.scancode; strncpy(inp->sym, SDL_GetScancodeName(inp->code), sizeof(inp->sym)); inp->sym[sizeof(inp->sym) - 1] = 0; tolow(inp->sym); key_compat(inp); if (DIRECT_MODE && SDL_PeepEvents(&peek, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYUP) > 0) { if (event.key.keysym.scancode == peek.key.keysym.scancode && peek.key.repeat == 0) return AGAIN; } break; case SDL_MOUSEMOTION: m_focus = 1; /* ahhh */ if (DIRECT_MODE && !game_paused()) return AGAIN; inp->type = MOUSE_MOTION; inp->x = event.button.x; inp->y = event.button.y; while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) { inp->x = peek.button.x; inp->y = peek.button.y; } break; case SDL_MOUSEBUTTONUP: inp->type = MOUSE_UP; inp->x = event.button.x; inp->y = event.button.y; inp->code = event.button.button; if (event.button.button == 4) inp->type = 0; else if (event.button.button == 5) inp->type = 0; break; case SDL_MOUSEWHEEL: if (!game_grab_events && DIRECT_MODE && !game_paused()) return AGAIN; inp->type = (event.wheel.y > 0) ? MOUSE_WHEEL_UP : MOUSE_WHEEL_DOWN; while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_MOUSEWHEEL, SDL_MOUSEWHEEL) > 0) { if (!((event.wheel.y > 0 && inp->type == MOUSE_WHEEL_UP) || (event.wheel.y < 0 && inp->type == MOUSE_WHEEL_DOWN))) break; inp->count ++; } break; case SDL_MOUSEBUTTONDOWN: m_focus = 1; /* ahhh */ inp->type = MOUSE_DOWN; inp->x = event.button.x; inp->y = event.button.y; inp->code = event.button.button; if (event.button.button == 4) inp->type = MOUSE_WHEEL_UP; else if (event.button.button == 5) inp->type = MOUSE_WHEEL_DOWN; while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONDOWN) > 0) { if (!((event.button.button == 4 && inp->type == MOUSE_WHEEL_UP) || (event.button.button == 5 && inp->type == MOUSE_WHEEL_DOWN))) break; inp->count ++; } break; default: break; } return 1; } extern void gfx_real_size(int *ww, int *hh); int input_text(int start) { SDL_Rect rect; int w, h; if (start == -1) return SDL_IsTextInputActive(); if (start) { gfx_real_size(&w, &h); rect.x = w / 2; rect.y = h - 1; rect.w = 1; rect.h = 1; SDL_SetTextInputRect(&rect); SDL_StartTextInput(); } else SDL_StopTextInput(); return 0; } instead-3.5.2+dfsg/src/input.h000066400000000000000000000040461467622671600162130ustar00rootroot00000000000000/* * Copyright 2009-2019 Peter Kosyh * * 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. * */ #ifndef __INPUT_H__ #define __INPUT_H__ #define KEY_DOWN 1 #define KEY_UP 2 #define MOUSE_DOWN 3 #define MOUSE_UP 4 #define MOUSE_WHEEL_UP 5 #define MOUSE_WHEEL_DOWN 6 #define MOUSE_MOTION 7 #define USER_EVENT 8 #define FINGER_UP 9 #define FINGER_DOWN 10 #define KEY_TEXT 11 #define EV_CODE_KBD -1 #define EV_CODE_FINGER -2 #define EV_CODE_TEXT -3 #define EV_CODE_WHEEL -4 #define AGAIN 2 struct inp_event { int type; int code; char sym[64]; int x; int y; int count; }; int input(struct inp_event *ev, int wait); int input_init(void); void input_done(void); void input_clear(void); void input_uevents(void); void push_user_event(void (*p) (void*), void *data); int mouse_focus(void); extern int minimized(void); extern int mouse_cursor(int on); extern int finger_pos(const char *finger, int *x, int *y, float *pressure); extern int system_clipboard(const char *text, char **buf); extern int input_text(int start); #endif instead-3.5.2+dfsg/src/instead/000077500000000000000000000000001467622671600163265ustar00rootroot00000000000000instead-3.5.2+dfsg/src/instead/cache.c000066400000000000000000000161171467622671600175430ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #include "list.h" #include "cache.h" extern unsigned long hash_string(const char *str); #define HASH_SIZE 511 typedef struct { struct list_head list; struct list_head unused; int auto_grow; int size; int max_size; int used; cache_free_fn free_fn; struct list_head hash[HASH_SIZE]; struct list_head vhash[HASH_SIZE]; } _cache_t; typedef struct { struct list_node list; struct list_node *hash; struct list_node *vhash; char *name; void *data; int used; } _cache_e_t; typedef struct { struct list_node list; _cache_e_t *data; } _hash_item_t; /* #define GOLDEN_RATIO_PRIME_32 0x9e370001UL */ #include static unsigned long hash_long32(unsigned long a) { a = (a+0x7ed55d16) + (a<<12); a = (a^0xc761c23c) ^ (a>>19); a = (a+0x165667b1) + (a<<5); a = (a+0xd3a2646c) ^ (a<<9); a = (a+0xfd7046c5) + (a<<3); a = (a^0xb55a4f09) ^ (a>>16); return a; } static unsigned long hash_long64(unsigned long key) { key = (~key) + (key << 21); /* key = (key << 21) - key - 1; */ key = key ^ (key >> 24); key = (key + (key << 3)) + (key << 8); /* key * 265 */ key = key ^ (key >> 14); key = (key + (key << 2)) + (key << 4); /* key * 21 */ key = key ^ (key >> 28); key = key + (key << 31); return key; } unsigned long hash_addr(void *p) { if (sizeof(long) == 8) return hash_long64((unsigned long)p); return hash_long32((unsigned long)p); } unsigned long hash_string(const char *str) { unsigned long hash = 0; int c; while ((c = *str++)) hash = c + (hash << 6) + (hash << 16) - hash; return hash; } cache_t cache_init(int size, cache_free_fn free_fn) { int i = 0; _cache_t *c = malloc(sizeof(_cache_t)); if (!c) return NULL; list_head_init(&c->list); list_head_init(&c->unused); c->auto_grow = 0; c->size = 0; c->used = 0; if (!size) c->auto_grow = 1; c->max_size = size; c->free_fn = free_fn; for (i = 0; i < HASH_SIZE; i++) { list_head_init(&c->hash[i]); list_head_init(&c->vhash[i]); } return (cache_t)c; } static void cache_e_free(cache_t cache, _cache_e_t *cc) { _cache_t *c = cache; if (!c) return; list_del(cc->hash); list_del(cc->vhash); list_del(&cc->list); if (c->free_fn && !cc->used) { c->free_fn(cc->data); } free(cc->name); free(cc->hash); free(cc->vhash); free(cc); } void cache_zap(cache_t cache) { _cache_t *c = cache; if (!c) return; while (!list_empty(&c->list)) cache_e_free(cache, list_top(&c->list, _cache_e_t, list)); while (!list_empty(&c->unused)) cache_e_free(cache, list_top(&c->unused, _cache_e_t, list)); c->size = 0; c->used = 0; } void cache_free(cache_t cache) { if (!cache) return; cache_zap(cache); free(cache); } static _cache_e_t *_cache_lookup(cache_t cache, const char *name) { _hash_item_t *pos = NULL; struct list_head *list; _cache_t *c = cache; _cache_e_t *cc; if (!c || !name) return NULL; list = &c->hash[hash_string(name) % HASH_SIZE]; list_for_each(list, pos, list) { cc = pos->data; if (!strcmp(cc->name, name)) return cc; } return NULL; } static _cache_e_t *cache_data(cache_t cache, void *p) { _hash_item_t *pos = NULL; struct list_head *list; _cache_t *c = cache; _cache_e_t *cc; if (!c || !p) return NULL; list = &c->vhash[hash_addr(p) % HASH_SIZE]; list_for_each(list, pos, list) { cc = pos->data; if (p == cc->data) return cc; } return NULL; } int cache_forget(cache_t cache, void *p) { _cache_t *c = cache; _cache_e_t *cc = cache_data(cache, p); /* if (cc) fprintf(stderr, "Forget %p at %d\n", p, cc->used); */ if (cc && cc->used) { cc->used --; if (!cc->used) { ((_cache_t*)cache)->used --; list_del(&cc->list); list_add_tail(&c->unused, &cc->list); } return 0; } return -1; } void *cache_get(cache_t cache, const char *name) { _cache_e_t *cc; _cache_t *c = cache; if (!c || !name) return NULL; cc = _cache_lookup(cache, name); if (!cc) return NULL; cc->used ++; /* need again! */ if (cc->used == 1) ((_cache_t*)cache)->used ++; list_del(&cc->list); list_add(&c->list, &cc->list); /* first place */ /* printf("cache_get %s:%p %d\n", name, cc->data, cc->used); */ return cc->data; } void *cache_lookup(cache_t cache, const char *name) { _cache_e_t *cc; _cache_t *c = cache; if (!c || !name) return NULL; cc = _cache_lookup(cache, name); if (!cc) return NULL; return cc->data; } int cache_have(cache_t cache, void *p) { _cache_e_t *cc; _cache_t *c = cache; if (!c || !p) return -1; cc = cache_data(cache, p); if (!cc) return -1; return 0; } static void __cache_shrink(_cache_t *c) { while (c->size && c->size > c->max_size && !list_empty(&c->unused)) { _cache_e_t *cc = list_top(&c->unused, _cache_e_t, list); c->size --; cache_e_free(c, cc); } /* fprintf(stderr,"%d/%d\n", c->size, c->used); */ } int cache_add(cache_t cache, const char *name, void *p) { _cache_e_t *cc; _hash_item_t *hh; _hash_item_t *vh; _cache_t *c = cache; struct list_head *list; if (!c || !name) return -1; cc = _cache_lookup(cache, name); if (cc) return 0; cc = malloc(sizeof(_cache_e_t)); if (!cc) return -1; hh = malloc(sizeof(_hash_item_t)); if (!hh) { free(cc); return -1; } vh = malloc(sizeof(_hash_item_t)); if (!vh) { free(hh); free(cc); return -1; } cc->name = strdup(name); if (!cc->name) { free(vh); free(hh); free(cc); return -1; } cc->data = p; cc->used = 1; cc->hash = &hh->list; cc->vhash = &vh->list; list_add(&c->list, &cc->list); list = &c->hash[hash_string(name) % HASH_SIZE]; hh->data = cc; list_add(list, &hh->list); list = &c->vhash[hash_addr(p) % HASH_SIZE]; vh->data = cc; list_add(list, &vh->list); c->size ++; c->used ++; if (c->auto_grow && c->used > c->max_size) c->max_size = c->used; /* printf("cache_add %s:%p %d\n", name, cc->data, cc->used); __cache_shrink(c); */ return 0; } void cache_shrink(cache_t cache) { _cache_t *c = cache; if (!c) return; if (c->auto_grow && c->max_size > 2*c->used) c->max_size = c->used + c->used / 2; __cache_shrink(c); /* printf("size: %d:%d:%d\n", c->used, c->size, c->max_size); */ } instead-3.5.2+dfsg/src/instead/cache.h000066400000000000000000000034051467622671600175440ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh * * 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. * */ #ifndef __CACHE_H #define __CACHE_H typedef void * cache_t; typedef void (*cache_free_fn)(void *p); extern cache_t cache_init(int size, cache_free_fn); extern void cache_free(cache_t cache); extern int cache_forget(cache_t cache, void *p); extern void cache_zap(cache_t cache); extern void cache_shrink(cache_t cache); extern void *cache_get(cache_t cache, const char *name); extern void *cache_lookup(cache_t cache, const char *name); extern int cache_add(cache_t cache, const char *name, void *p); extern int cache_have(cache_t cache, void *p); extern unsigned long hash_addr(void *p); extern unsigned long hash_string(const char *str); #endif instead-3.5.2+dfsg/src/instead/idf.c000066400000000000000000000326511467622671600172430ustar00rootroot00000000000000/* * Copyright 2009-2017 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "system.h" #include "idf.h" #include "util.h" #include "cache.h" #include "list.h" typedef struct _idfd_t { struct list_head list; unsigned long offset; unsigned long size; idf_t idf; } idfd_t; struct _idff_t { struct list_node list; idfd_t *dir; unsigned long pos; FILE *fd; }; struct _idf_t { unsigned long size; FILE *fd; char *path; char cwd[PATH_MAX]; cache_t dir; int idfonly; }; static void free_idfd(void *p) { idfd_t *dir = (idfd_t*)p; if (!p) return; while (!list_empty(&dir->list)) { idff_t idff; idff = list_top(&dir->list, struct _idff_t, list); idf_close(idff); } free(p); } void idf_done(idf_t idf) { if (!idf) return; if (idf->path) free(idf->path); if (idf->dir) cache_free(idf->dir); if (idf->fd) fclose(idf->fd); free(idf); } void idf_shrink(idf_t idf) { if (!idf) return; if (idf->dir) cache_shrink(idf->dir); } static int read_word(FILE *fd, unsigned long *w) { unsigned char word[4]; if (fread(word, 1, 4, fd) != 4) return -1; *w = (unsigned long)word[0] | ((unsigned long)word[1] << 8) | ((unsigned long)word[2] << 16) | ((unsigned long)word[3] << 24); return 0; } static int write_word(FILE *fd, unsigned long w) { char word[4]; word[0] = w & 0xff; word[1] = (w & 0xff00) >> 8; word[2] = (w & 0xff0000) >> 16; word[3] = (w & 0xff000000) >> 24; if (fwrite(word, 1, 4, fd) != 4) return -1; return 0; } int idf_magic(const char *fname) { char sign[4]; FILE *fd = fopen(dirpath(fname), "rb"); if (!fd) return 0; if (fread(sign, 1, 4, fd) != 4) { fclose(fd); return 0; } fclose(fd); if (!memcmp(sign, "IDF1", 4)) return 1; return 0; } int idf_setdir(idf_t idf, const char *path) { if (idf && path) strcpy(idf->cwd, path); return 0; } char *idf_getdir(idf_t idf) { if (!idf) return NULL; return idf->cwd; } idf_t idf_init(const char *fname) { char sign[4]; unsigned long dir_size; char *fp = dirpath(fname); idf_t idf = malloc(sizeof(struct _idf_t)); if (!idf) return NULL; memset(idf, 0, sizeof(struct _idf_t)); idf->path = strdup(fname); if (!idf->path) goto err; idf->idfonly = 0; idf->fd = fopen(fp, "rb"); idf->dir = cache_init(-1, free_idfd); idf->cwd[0] = 0; if (!idf->fd || !idf->dir) goto err; if (fseek(idf->fd, 0, SEEK_END)) goto err; idf->size = ftell(idf->fd); if ((int)idf->size < 0) goto err; if (fseek(idf->fd, 0, SEEK_SET)) goto err; if (fread(sign, 1, 4, idf->fd) != 4) goto err; if (memcmp(sign, "IDF1", 4)) goto err; if (read_word(idf->fd, &dir_size)) goto err; if (dir_size > idf->size) goto err; while (dir_size > 0) { unsigned long off; unsigned long size; unsigned char sz; char name[256]; idfd_t *e; if (fread(&sz, 1, 1, idf->fd) != 1) goto err; if (fread(name, 1, sz, idf->fd) != sz) goto err; name[sz] = 0; if (read_word(idf->fd, &off)) goto err; if (read_word(idf->fd, &size)) goto err; e = malloc(sizeof(idfd_t)); if (!e) goto err; e->offset = off; e->size = size; e->idf = idf; list_head_init(&e->list); if (cache_add(idf->dir, name, e)) { free(e); goto err; } cache_forget(idf->dir, e); /* use like hash */ /* fprintf(stderr,"Parsed: '%s' @ %ld, %ld\n", name, off, size); */ dir_size -= (1 + sz + 4 + 4); } return idf; err: idf_done(idf); return NULL; } typedef struct { struct list_node list; char *path; long size; struct list_head dir; } idf_item_t; typedef struct { struct list_node list; char *dname; } idf_dir_item_t; static int fcopy(FILE *to, const char *fname) { int rc = -1; char buff[4096]; FILE *fd; fd = fopen(fname, "rb"); if (!fd) return -1; while (!feof(fd)) { int s = fread(buff, 1, sizeof(buff), fd); if (!s) { if (feof(fd)) break; goto err; } if (fwrite(buff, 1, s, to) != (size_t)s) goto err; } rc = 0; err: fclose(fd); return rc; } static int idf_tree(const char *path, struct list_head *list, const char *fname) { idf_item_t *dir; DIR *d; struct dirent *de; if (!path) return 0; d = opendir(dirpath(path)); if (!d) { if (!access(dirpath(path), R_OK) && fname) { FILE *fd; idf_item_t *i; fd = fopen(dirpath(path), "rb"); if (!fd) { fprintf(stderr, "Can not open file: '%s'\n", path); return -1; } i = malloc(sizeof(idf_item_t)); if (!i) { fclose(fd); return -1; } /* list_head_init(&i->list); */ if (!(i->path = strdup(fname))) goto err; if (fseek(fd, 0, SEEK_END) < 0) goto err; if ((i->size = ftell(fd)) < 0) goto err; list_head_init(&i->dir); fclose(fd); fprintf(stderr, "Added file: '%s' size: %ld\n", path, i->size); list_add(list, &i->list); return 0; err: if (i->path) free(i->path); free(i); return -1; } return 0; } dir = malloc(sizeof(idf_item_t)); if (!dir) goto err1; if (fname) { char *d = malloc(strlen(fname) + 2); if (!d) goto err2; strcpy(d, fname); strcat(d, "/"); dir->path = d; } else { dir->path = strdup("/"); } dir->size = 0; list_head_init(&dir->dir); while ((de = readdir(d))) { char *p; idf_dir_item_t *di; if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; di = malloc(sizeof(idf_dir_item_t)); if (di) { di->dname = strdup(de->d_name); list_add(&dir->dir, &di->list); dir->size += strlen(de->d_name) + 1; } p = getfilepath(path, de->d_name); if (p) { char *pp = getfilepath(fname, de->d_name); if (pp) { idf_tree(p, list, pp); free(pp); } free(p); } } list_add(list, &dir->list); fprintf(stderr, "Added dir: '%s' size: %ld\n", dir->path, dir->size); closedir(d); return 0; err2: free(dir); err1: closedir(d); return -1; } int idf_create(const char *file, const char *path) { int rc = -1, i; FILE *fd; char *p; unsigned long off = 0; long dict_size = 0; idf_item_t *pos = NULL; LIST_HEAD(items); p = strdup(path); if (!p) return -1; unix_path(p); i = strlen(p) - 1; while (i >= 0 && p[i] == '/') { p[i --] = 0; } idf_tree(p, &items, NULL); free(p); list_for_each(&items, pos, list) { idf_item_t *it = pos; dict_size += (1 + strlen(it->path) + 4 + 4); } fd = fopen(dirpath(file), "wb"); if (!fd) goto err; if (fwrite("IDF1", 1, 4, fd) != 4) goto err; if (write_word(fd, dict_size) < 0) goto err; off = 4 + 4 + dict_size; list_for_each(&items, pos, list) { unsigned char s; idf_item_t *it = pos; s = strlen(it->path); if (fwrite(&s, 1, 1, fd) != 1) goto err; p = strdup(it->path); if (!p) goto err; tolow(p); /* in idf always lowcase */ if (fwrite(p, 1, s, fd) != s) { free(p); goto err; } free(p); if (write_word(fd, off) < 0) goto err; if (write_word(fd, it->size) < 0) goto err; off += it->size; } list_for_each(&items, pos, list) { idf_item_t *it = pos; char *p; if (!list_empty(&it->dir)) { /* directory-file */ idf_dir_item_t *d = NULL; list_for_each(&it->dir, d, list) { fprintf(fd, "%s\n", d->dname); } continue; } p = getfilepath(path, it->path); if (p) { int rc = fcopy(fd, p); free(p); if (rc) { fprintf(stderr, "Error while copy file '%s'...\n", it->path); goto err; } } } rc = 0; err: if (rc) fprintf(stderr, "Error creating idf file...\n"); while (!list_empty(&items)) { idf_item_t *it = list_top(&items, idf_item_t, list); while (!list_empty(&it->dir)) { idf_dir_item_t *di = list_top(&it->dir, idf_dir_item_t, list); free(di->dname); list_del(&di->list); free(di); } free(it->path); list_del(&it->list); free(it); } if (fd) fclose(fd); return rc; } int idf_seek(idff_t fil, int offset, int whence) { idfd_t *dir = fil->dir; switch (whence) { case SEEK_SET: if (offset < 0 || (unsigned int)offset > dir->size) { return -1; } fil->pos = offset; break; case SEEK_END: if (dir->size + offset > dir->size || (int)(dir->size + offset) < 0) { return -1; } fil->pos = dir->size + offset; break; case SEEK_CUR: if (fil->pos + offset > dir->size || (int)(fil->pos + offset) < 0) { return -1; } fil->pos += offset; break; } if (!fseek(fil->fd, fil->pos + dir->offset, SEEK_SET)) return fil->pos; return -1; } int idf_close(idff_t fil) { if (fil) { fclose(fil->fd); list_del(&fil->list); free(fil); } return 0; /* nothing todo */ } #if 0 int idf_extract(idf_t idf, const char *fname) { FILE *out; int size; idfd_t *dir = NULL; char buff[4096]; if (idf) dir = cache_lookup(idf->dir, fname); if (!dir) return -1; fseek(idf->fd, dir->offset, SEEK_SET); out = fopen("out.bin", "wb"); size = dir->size; while (size>0) { int s ; if (size < sizeof(buff)) s = fread(buff, 1, size, idf->fd); else s = fread(buff, 1, sizeof(buff), idf->fd); fwrite(buff, 1, s, out); size -= s; fprintf(stderr, "size = %d\n", size); } fclose(out); return 0; } #endif int idf_eof(idff_t idf) { if (!idf) return 1; if (idf->pos >= idf->dir->size) return 1; return 0; } int idf_error(idff_t idf) { if (!idf || !idf->fd) return -1; return ferror(idf->fd); } int idf_only(idf_t idf, int fl) { int i; if (!idf) return -1; if (fl == -1) return idf->idfonly; i = idf->idfonly; idf->idfonly = fl; return i; } idff_t idf_open(idf_t idf, const char *fname) { char *rp; idfd_t *dir = NULL; idff_t fil = NULL; char *p; if (!idf || !fname) return NULL; p = strdup(fname); if (!p) return NULL; tolow(p); rp = getfilepath(idf->cwd, p); if (rp) { dir = cache_lookup(idf->dir, rp); free(rp); } free(p); if (!dir) return NULL; fil = malloc(sizeof(struct _idff_t)); if (!fil) return NULL; /* list_head_init(&fil->list); */ fil->dir = dir; fil->pos = 0; fil->fd = fopen(dirpath(idf->path), "rb"); if (!fil->fd) goto err; list_add(&dir->list, &fil->list); return fil; err: free(fil); return NULL; } int idf_access(idf_t idf, const char *fname) { char *rp; idfd_t *dir = NULL; if (idf) { rp = getfilepath(idf->cwd, fname); if (rp) { dir = cache_lookup(idf->dir, rp); free(rp); } } if (!dir) return -1; return 0; } idff_t idf_opendir(idf_t idf, const char *dname) { return idf_open(idf, dname); } int idf_closedir(idff_t d) { return idf_close(d); } char *idf_readdir(idff_t d) { char buff[256]; char *p = idf_gets(d, buff, sizeof(buff) - 1); if (!p) return p; return strdup(p); } char *idf_gets(idff_t idf, char *b, int size) { int rc, rc2; if (!idf) return NULL; if (!size) return NULL; rc = idf_read(idf, b, 1, size); if (rc < 0) return NULL; if (!rc && idf_eof(idf)) return NULL; if (!idf_eof(idf)) b[rc - 1] = 0; else { if (rc < size) b[rc] = 0; else b[size - 1] = 0; } rc2 = strcspn(b, "\n"); b[rc2] = 0; idf_seek(idf, - (rc - rc2 - 1), SEEK_CUR); return b; } int idf_read(idff_t fil, void *ptr, int size, int maxnum) { int rc = 0; long pos; idfd_t *dir = fil->dir; if (fseek(fil->fd, dir->offset + fil->pos, SEEK_SET) < 0) { return 0; } #if 1 while (maxnum) { pos = ftell(fil->fd); fil->pos = pos - dir->offset; if (fil->pos + size > dir->size) { break; } if (fread(ptr, size, 1, fil->fd) != 1) break; /* fil->pos += size; */ ptr = (char *)ptr + size; maxnum --; rc ++; } #else rc = fread(ptr, size, maxnum, fil->fd); #endif pos = ftell(fil->fd); fil->pos = pos - dir->offset; return rc; } #ifdef _USE_SDL #include static Sint64 idfrw_seek(struct SDL_RWops *context, Sint64 offset, int whence) { idff_t fil = (idff_t)context->hidden.unknown.data1; return idf_seek(fil, offset, whence); } static size_t idfrw_read(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum) { idff_t fil = (idff_t)context->hidden.unknown.data1; return idf_read(fil, ptr, size, maxnum); } static int idfrw_close(struct SDL_RWops *context) { if (context) { idff_t fil = (idff_t)context->hidden.unknown.data1; idf_close(fil); SDL_FreeRW(context); } return 0; } static Sint64 idfrw_size(struct SDL_RWops *context) { idff_t fil = (idff_t)context->hidden.unknown.data1; if (!fil || !fil->dir) return -1; return fil->dir->size; } SDL_RWops *RWFromIdf(idf_t idf, const char *fname) { idff_t fil = NULL; SDL_RWops *n; fil = idf_open(idf, fname); if (!fil) { if (!idf || !idf->idfonly) return SDL_RWFromFile(dirpath(fname), "rb"); return NULL; } n = SDL_AllocRW(); if (!n) goto err; n->size = idfrw_size; n->seek = idfrw_seek; n->read = idfrw_read; n->close = idfrw_close; n->hidden.unknown.data1 = fil; return n; err: if (n) SDL_FreeRW(n); free(fil); return NULL; } #endif instead-3.5.2+dfsg/src/instead/idf.h000066400000000000000000000043241467622671600172440ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh * * 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. * */ #ifndef __IDF_H_INCLUDED #define __IDF_H_INCLUDED struct _idf_t; struct _idff_t; typedef struct _idf_t *idf_t; typedef struct _idff_t *idff_t; extern idf_t idf_init(const char *path); extern void idf_shrink(idf_t idf); extern void idf_done(idf_t idf); extern int idf_create(const char *file, const char *path); extern idff_t idf_open(idf_t idf, const char *fname); extern int idf_setdir(idf_t idf, const char *path); extern char *idf_getdir(idf_t idf); extern int idf_seek(idff_t fil, int offset, int whence); extern int idf_read(idff_t fil, void *ptr, int size, int maxnum); extern int idf_close(idff_t fil); extern int idf_eof(idff_t idf); extern int idf_error(idff_t idf); extern int idf_access(idf_t idf, const char *fname); extern idff_t idf_opendir(idf_t idf, const char *dname); extern int idf_closedir(idff_t d); extern char *idf_readdir(idff_t d); extern char *idf_gets(idff_t idf, char *b, int size); extern int idf_magic(const char *fname); extern int idf_only(idf_t idf, int fl); #ifdef _USE_SDL #include extern SDL_RWops *RWFromIdf(idf_t idf, const char *fname); #endif #endif instead-3.5.2+dfsg/src/instead/instead.c000066400000000000000000000667161467622671600201410ustar00rootroot00000000000000/* * Copyright 2009-2022 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "system.h" #include "instead.h" #include "util.h" #include "list.h" #define DATA_IDF INSTEAD_IDF #ifdef _USE_SDL #if !defined(__EMSCRIPTEN__) && !defined(WINRT) static SDL_mutex *sem; #endif void instead_lock(void) { #if !defined(__EMSCRIPTEN__) && !defined(WINRT) SDL_LockMutex(sem); #endif } void instead_unlock(void) { #if !defined(__EMSCRIPTEN__) && !defined(WINRT) SDL_UnlockMutex(sem); #endif } #else void instead_lock(void) { } void instead_unlock(void) { } #endif static char instead_cwd_path[PATH_MAX]; static char instead_game_path[PATH_MAX]; static int debug_sw = 0; static int standalone_sw = 0; static int busy = 0; static idf_t data_idf = NULL; /* the Lua interpreter */ char *instead_fromgame(const char *s); char *togame(const char *s); lua_State *L = NULL; static char *err_msg = NULL; static char instead_api_path[PATH_MAX + 1]; static char instead_base_path[PATH_MAX] = STEAD_PATH; static char *API = NULL; static char *MAIN = NULL; #define STEAD_API_PATH instead_api_path static struct list_head extensions = LIST_HEAD_INIT(extensions); #define for_each_extension(ext) list_for_each(&extensions, ext, list) enum instead_hook { init, done, cmd, err, }; #define HOOK_INIT 1 #define HOOK_DONE 2 #define HOOK_CMD 3 #define HOOK_ERR 4 static int extensions_hook(enum instead_hook nr) { int rc = 0; struct instead_ext *ext = NULL; for_each_extension(ext) { switch (nr) { case init: if (ext->init) rc = ext->init(); break; case done: if (ext->done) rc = ext->done(); break; case cmd: if (ext->cmd) rc = ext->cmd(); break; case err: if (ext->err) rc = ext->err(); break; default: return -1; } if (rc) break; } return rc; } int instead_extension(struct instead_ext *ext) { struct instead_ext *e = NULL; for_each_extension(e) { if (e == ext) return 0; } list_add(&extensions, &ext->list); return 0; } int instead_busy(void) { return busy; } void instead_err_msg(const char *s) { if (err_msg) free(err_msg); if (s) err_msg = strdup(s); else err_msg = NULL; } const char *instead_err(void) { return err_msg; } static int report (lua_State *L, int status) { if (status && !lua_isnil(L, -1)) { char *p; const char *msg = lua_tostring(L, -1); if (msg == NULL) msg = "(error object is not a string)"; fprintf(stderr,"Error: %s\n", msg); p = instead_fromgame(msg); instead_err_msg(p?p:msg); if (p) free(p); lua_pop(L, 1); status = -1; extensions_hook(err); } return status; } #if LUA_VERSION_NUM >= 502 static int traceback (lua_State *L) { const char *msg = lua_tostring(L, 1); if (msg) luaL_traceback(L, L, msg, 1); else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ lua_pushliteral(L, "(no error message)"); } return 1; } #else static int traceback (lua_State *L) { lua_getfield(L, LUA_GLOBALSINDEX, "debug"); if (!lua_istable(L, -1)) { lua_pop(L, 1); return 1; } lua_getfield(L, -1, "traceback"); if (!lua_isfunction(L, -1)) { lua_pop(L, 2); return 1; } lua_pushvalue(L, 1); /* pass error message */ lua_pushinteger(L, 2); /* skip this function and traceback */ lua_call(L, 2, 1); /* call debug.traceback */ return 1; } #endif static int docall (lua_State *L, int narg) { int status; int base = 0; if (debug_sw) { base = lua_gettop(L) - narg; /* function index */ lua_pushcfunction(L, traceback); /* push traceback function */ lua_insert(L, base); /* put it under chunk and args */ } busy ++; status = lua_pcall(L, narg, LUA_MULTRET, base); busy --; if (debug_sw) lua_remove(L, base); /* remove traceback function */ /* force a complete garbage collection in case of errors */ if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); return status; } int instead_pcall(lua_State *L, int nargs) { int status; status = docall(L, nargs); status = report(L, status); return status; } static int dofile (lua_State *L, const char *name) { int status = luaL_loadfile(L, name) || docall(L, 0); return report(L, status); } static const char *idf_reader(lua_State *L, void *data, size_t *size) { static char buff[4096]; int rc; rc = idf_read((idff_t)data, buff, 1, sizeof(buff)); *size = rc; if (!rc) return NULL; return buff; } static int dofile_idf (lua_State *L, idff_t idf, const char *name) { #if LUA_VERSION_NUM >= 502 int status = lua_load(L, idf_reader, idf, name, "bt") || docall(L, 0); #else int status = lua_load(L, idf_reader, idf, name) || docall(L, 0); #endif return report(L, status); } static int dostring (lua_State *L, const char *s) { int status = luaL_loadstring(L, s) || docall(L, 0); return report(L, status); } char *getstring(char *cmd) { char *s; int N; if (!L) return NULL; if (dostring(L, cmd)) return NULL; N = lua_gettop(L); /* number of arguments */ if (-N >=0) return NULL; s = (char*)lua_tostring(L, -N); if (s) s = instead_fromgame(s); return s; } int instead_eval(char *s) { if (!L) return -1; if (dostring(L, s)) return -1; return 0; } int instead_clear(void) { int N; if (!L) return -1; N = lua_gettop(L); /* number of arguments */ lua_pop(L, N); return 0; } char *instead_retval(int n) { char *s; int N; if (!L) return NULL; N = lua_gettop(L); /* number of arguments */ /* fprintf(stderr,"%d\n", N); */ if (n - N >= 0) return NULL; s = (char*)lua_tostring(L, n - N); if (s) s = instead_fromgame(s); return s; } int instead_bretval(int n) { int N; if (!L) return 0; N = lua_gettop(L); /* number of arguments */ if (n - N >= 0) return 1; return lua_toboolean(L, n - N); } static int instead_bstatus(int n) { int N; if (!L) return 0; N = lua_gettop(L); /* number of arguments */ if (n - N >= 0 || lua_isnil(L, n - N)) return 1; return lua_toboolean(L, n - N); } int instead_iretval(int n) { int N; if (!L) return 0; N = lua_gettop(L); /* number of arguments */ if (n - N >= 0) return 0; return lua_tonumber(L, n - N); } char *instead_file_cmd(char *s, int *rc) { struct instead_args args[] = { { .val = NULL, .type = INSTEAD_STR }, { .val = NULL, }, }; if (!s) return NULL; args[0].val = s; instead_function("iface:cmd", args); s = instead_retval(0); if (rc) *rc = !instead_bstatus(1); instead_clear(); extensions_hook(cmd); return s; } char *instead_cmd(char *s, int *rc) { struct instead_args args[] = { { .val = NULL, .type = INSTEAD_STR }, { .val = NULL, }, }; if (!s) return NULL; s = togame(s); if (!s) return NULL; args[0].val = s; instead_function("iface:cmd", args); free(s); s = instead_retval(0); if (rc) *rc = !instead_bstatus(1); instead_clear(); extensions_hook(cmd); return s; } int instead_function(char *s, struct instead_args *args) { int base = 0; int status = 0; int n = 0; char *p; char f[64]; int method = 0; if (!L) return -1; strcpy(f, s); p = strchr(f, '.'); if (!p) p = strchr(f, ':'); if (p) { if (*p == ':') method = 1; *p = 0; p ++; lua_getglobal(L, f); lua_getfield(L, -1, p); lua_remove(L, -2); if (method) lua_getglobal(L, f); } else lua_getglobal(L, s); if (args) { while (args->val) { switch(args->type) { case INSTEAD_NIL: lua_pushnil(L); break; case INSTEAD_NUM: lua_pushinteger(L, atoi(args->val)); break; case INSTEAD_BOOL: if (!strcmp(args->val, "true")) lua_pushboolean(L, 1); else lua_pushboolean(L, 0); break; default: case INSTEAD_STR: lua_pushstring(L, args->val); } args ++; n ++; } } if (debug_sw) { base = lua_gettop(L) - (method + n); /* function index */ lua_pushcfunction(L, traceback); /* push traceback function */ lua_insert(L, base); /* put it under chunk and args */ } busy ++; status = lua_pcall(L, method + n, LUA_MULTRET, base); busy --; if (debug_sw) lua_remove(L, base); /* remove traceback function */ if (status) { fprintf(stderr, "Error calling:%s\n", s); lua_gc(L, LUA_GCCOLLECT, 0); } return report(L, status); } #ifdef _HAVE_ICONV static char *curcp = NULL; static char *fromcp = NULL; #endif #ifdef _HAVE_ICONV void instead_set_encoding(const char *cp) { if (curcp) free(curcp); if (cp) curcp = strdup(cp); else curcp = NULL; return; } char *instead_fromgame(const char *s) { iconv_t han; char *str; if (!s) return NULL; if (!fromcp) goto out0; han = iconv_open(curcp, fromcp); if (han == (iconv_t)-1) goto out0; if (!(str = decode(han, s))) goto out1; iconv_close(han); return str; out1: iconv_close(han); out0: return strdup(s); } char *togame(const char *s) { iconv_t han; char *str; if (!s) return NULL; if (!fromcp) goto out0; han = iconv_open(fromcp, curcp); if (han == (iconv_t)-1) goto out0; if (!(str = decode(han, s))) goto out1; iconv_close(han); return str; out1: iconv_close(han); out0: return strdup(s); } #else char *instead_fromgame(const char *s) { if (!s) return NULL; return strdup(s); } char *togame(const char *s) { if (!s) return NULL; return strdup(s); } void instead_set_encoding(const char *cp) { } #endif static int instead_getargs (char **argv, int n) { int i; for (i = 0; i < n; i++) { lua_pushstring(L, argv[i]); } lua_createtable(L, n, 0); for (i = 0; i < n; i++) { lua_pushstring(L, argv[i]); lua_rawseti(L, -2, i + 1); } lua_setglobal(L, "arg"); return 0; } int instead_load(char **info) { int rc; idff_t idf; rc = instead_function("stead:init", NULL); instead_clear(); if (rc) goto err; idf = idf_open(data_idf, MAIN); if (idf) { int rc = dofile_idf(L, idf, MAIN); idf_close(idf); if (rc) goto err; } else if (dofile(L, dirpath(MAIN))) { goto err; } instead_clear(); #ifdef _HAVE_ICONV if (fromcp) free(fromcp); fromcp = getstring("return game.codepage;"); instead_clear(); #endif rc = instead_function("game:ini", NULL); if (rc) goto err2; if (info) { *info = instead_retval(0); *info = instead_fromgame(*info); } instead_clear(); return rc; err2: instead_clear(); err: return -1; } int instead_loadfile(const char *name) { return instead_loadscript(name, -1, NULL, 1); } int instead_loadscript(const char *name, int argc, char **argv, int exec) { int status; if (exec && argc >= 0) instead_getargs(argv, argc); status = luaL_loadfile(L, name); if (!status) { if (exec) { if (argc >= 0) lua_insert(L, -(argc + 1)); else argc = 0; status |= docall(L, argc); } } status = report(L, status); instead_clear(); return status; } typedef struct LoadF { int extraline; unsigned char byte; FILE *f; idff_t idff; int enc; unsigned char buff[4096]; } LoadF; static const char *getF (lua_State *L, void *ud, size_t *size) { unsigned int i = 0; LoadF *lf = (LoadF *)ud; (void)L; if (lf->extraline) { lf->extraline = 0; *size = 1; return "\n"; } if (lf->f && feof(lf->f)) return NULL; if (lf->idff && idf_eof(lf->idff)) return NULL; if (lf->idff) *size = idf_read(lf->idff, lf->buff, 1, sizeof(lf->buff)); else *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); if (lf->enc) { for (i = 0; i < *size; i ++) { unsigned char b = lf->buff[i]; lf->buff[i] ^= lf->byte; lf->buff[i] = (lf->buff[i] >> 3) | (lf->buff[i] << 5); lf->byte = b; } } return (*size > 0) ? (char*)lf->buff : NULL; } static int errfile (lua_State *L, const char *what, int fnameindex) { const char *serr = strerror(errno); const char *filename = lua_tostring(L, fnameindex) + 1; lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); lua_remove(L, fnameindex); return LUA_ERRFILE; } static int loadfile (lua_State *L, const char *filename, int enc) { LoadF lf; int status, readstatus; int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ lf.extraline = 0; lua_pushfstring(L, "@%s", filename); lf.idff = idf_open(data_idf, filename); if (!lf.idff) lf.f = fopen(dirpath(filename), "rb"); else lf.f = NULL; lf.byte = 0xcc; lf.enc = enc; if (lf.f == NULL && lf.idff == NULL) return errfile(L, "open", fnameindex); #if LUA_VERSION_NUM >= 502 status = lua_load(L, getF, &lf, lua_tostring(L, -1), "bt"); #else status = lua_load(L, getF, &lf, lua_tostring(L, -1)); #endif if (lf.f) readstatus = ferror(lf.f); else readstatus = idf_error(lf.idff); if (lf.f) fclose(lf.f); /* close file (even in case of errors) */ else idf_close(lf.idff); if (readstatus) { lua_settop(L, fnameindex); /* ignore results from `lua_load' */ return errfile(L, "read", fnameindex); } lua_remove(L, fnameindex); return status; } static int luaB_doencfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); int n = lua_gettop(L); if (loadfile(L, fname, 1) != 0) lua_error(L); lua_call(L, 0, LUA_MULTRET); return lua_gettop(L) - n; } static int luaB_dofile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); int n = lua_gettop(L); if (loadfile(L, fname, 0) != 0) lua_error(L); lua_call(L, 0, LUA_MULTRET); return lua_gettop(L) - n; } #if LUA_VERSION_NUM <= 503 /* is this hack still needed? */ static int luaB_print (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ int i; lua_getglobal(L, "tostring"); for (i=1; i<=n; i++) { const char *s; lua_pushvalue(L, -1); /* function to be called */ lua_pushvalue(L, i); /* value to print */ lua_call(L, 1, 1); s = lua_tostring(L, -1); /* get result */ if (s == NULL) return luaL_error(L, LUA_QL("tostring") " must return a string to "LUA_QL("print")); if (i>1) fputs("\t", stdout); fputs(s, stdout); lua_pop(L, 1); /* pop result */ } fputs("\n", stdout); return 0; } #else static int luaB_print (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ int i; for (i = 1; i <= n; i++) { /* for each argument */ size_t l; const char *s = luaL_tolstring(L, i, &l); /* convert it to string */ if (i > 1) /* not the first element? */ lua_writestring("\t", 1); /* add a tab before it */ lua_writestring(s, l); /* print it */ lua_pop(L, 1); /* pop result */ } lua_writeline(); return 0; } #endif static int luaB_maxn (lua_State *L) { lua_Integer max = 0; luaL_checktype(L, 1, LUA_TTABLE); lua_pushnil(L); /* first key */ while (lua_next(L, 1)) { lua_pop(L, 1); /* remove value */ if (lua_type(L, -1) == LUA_TNUMBER) { lua_Number v = lua_tonumber(L, -1); if (v > max) max = v; } } lua_pushinteger(L, max); return 1; } static int luaB_srandom(lua_State *L) { mt_random_seed(luaL_optnumber(L, 1, time(NULL))); return 0; } static int luaB_random(lua_State *L) { lua_Number rt; unsigned long r = 0; long a = luaL_optnumber(L, 1, -1); long b = luaL_optnumber(L, 2, -1); r = mt_random(); if (a >=0 && b > a) { r = a + (r % (b - a + 1)); lua_pushinteger(L, r); } else if (a > 0 && b == -1) { r = (r % a) + 1; lua_pushinteger(L, r); } else { rt = mt_random_double(); lua_pushnumber(L, rt); } return 1; } static int luaB_get_realpath(lua_State *L) { char realpath[PATH_MAX]; char outpath[PATH_MAX]; const char *path = luaL_optstring(L, 1, NULL); if (!path) return 0; strncpy(realpath, path, sizeof(realpath)); realpath[sizeof(realpath) - 1] = 0; unix_path(realpath); path = getrealpath(realpath, outpath); if (!path) return 0; lua_pushstring(L, outpath); return 1; } static int luaB_get_gamepath(lua_State *L) { char path[PATH_MAX * 2]; char *p = getdir(path, sizeof(path)); if (!p) return 0; unix_path(p); if (idf_only(instead_idf(), -1) == 1) { /* no gamepath */ strcpy(path, instead_game_path); } lua_pushstring(L, p); return 1; } static int luaB_get_steadpath(lua_State *L) { char stead_path[PATH_MAX]; if (STEAD_API_PATH[0] != '/') { strcpy(stead_path, instead_cwd()); strcat(stead_path, "/"); } else stead_path[0] = 0; strcat(stead_path, STEAD_API_PATH); unix_path(stead_path); lua_pushstring(L, stead_path); return 1; } #define utf_cont(p) ((*(p) & 0xc0) == 0x80) static int utf_ff(const char *s, const char *e) { int l = 0; if (!s || !e) return 0; if (s > e) return 0; if ((*s & 0x80) == 0) /* ascii */ return 1; l = 1; while (s < e && utf_cont(s + 1)) { s ++; l ++; } return l; } static int utf_bb(const char *s, const char *e) { int l = 0; if (!s || !e) return 0; if (s > e) return 0; if ((*e & 0x80) == 0) /* ascii */ return 1; l = 1; while (s < e && utf_cont(e)) { e --; l ++; } return l; } static int luaB_utf_next(lua_State *L) { int l = 0; const char *s = luaL_optstring(L, 1, NULL); int idx = luaL_optnumber(L, 2, 1) - 1; if (s && idx >= 0) { int len = strlen(s); if (idx < len) l = utf_ff(s + idx, s + len - 1); } lua_pushinteger(L, l); return 1; } static int luaB_utf_prev(lua_State *L) { int l = 0; const char *s = luaL_optstring(L, 1, NULL); int idx = luaL_optnumber(L, 2, 0) - 1; int len = 0; if (s) { len = strlen(s); if (idx < 0) idx += len; if (idx >= 0) { if (idx < len) l = utf_bb(s, s + idx); } } lua_pushinteger(L, l); return 1; } static int luaB_utf_char(lua_State *L) { int len, l = 0; char *rs; const char *s = luaL_optstring(L, 1, NULL); int idx = luaL_optnumber(L, 2, 1) - 1; if (!s || idx < 0) return 0; len = strlen(s) - 1; while (idx >= 0 && len >= 0) { s += l; l = utf_ff(s, s + len); if (l <= 0) return 0; idx --; len -= l; } rs = malloc(l + 1); if (!rs) return 0; if (l) memcpy(rs, s, l); rs[l] = 0; lua_pushstring(L, rs); free(rs); return 1; } static int luaB_utf_len(lua_State *L) { int l = 0; int sym = 0; const char *s = luaL_optstring(L, 1, NULL); if (s) { int len = strlen(s) - 1; while (len >= 0) { l = utf_ff(s, s + len); if (!l) break; s += l; len -= l; sym ++; } } lua_pushinteger(L, sym); return 1; } extern int dir_iter_factory (lua_State *L); extern int luaopen_lfs (lua_State *L); static const luaL_Reg base_funcs[] = { {"print", luaB_print}, /* for some mystic, it is needed in win version (with -debug) */ {"doencfile", luaB_doencfile}, {"dofile", luaB_dofile}, {"table_get_maxn", luaB_maxn}, {"instead_random", luaB_random}, {"instead_srandom", luaB_srandom}, {"instead_realpath", luaB_get_realpath}, {"instead_gamepath", luaB_get_gamepath}, {"instead_steadpath", luaB_get_steadpath}, {"instead_readdir", dir_iter_factory}, {"utf8_next", luaB_utf_next}, {"utf8_prev", luaB_utf_prev}, {"utf8_char", luaB_utf_char}, {"utf8_len", luaB_utf_len}, { NULL, NULL } }; static int instead_platform(void) { char plat[64]; if (!L) return 0; #if defined(IOS) snprintf(plat, sizeof(plat) - 1, "PLATFORM='IOS'"); #elif defined(__APPLE__) snprintf(plat, sizeof(plat) - 1, "PLATFORM='MACOSX'"); #elif defined(WINRT) snprintf(plat, sizeof(plat) - 1, "PLATFORM='WINRT'"); #elif defined(ANDROID) snprintf(plat, sizeof(plat) - 1, "PLATFORM='ANDROID'"); #elif defined(_WIN32) snprintf(plat, sizeof(plat) - 1, "PLATFORM='WIN32'"); #elif defined(SAILFISHOS) snprintf(plat, sizeof(plat) - 1, "PLATFORM='SFOS'"); #else snprintf(plat, sizeof(plat) - 1, "PLATFORM='UNIX'"); #endif plat[sizeof(plat) - 1] = 0; instead_eval(plat); instead_clear(); return 0; } static int instead_package(const char *path) { char *stead_path; stead_path = malloc(PATH_MAX * 5); /* instead_cwd + STEAD_API_PATH and so on... */ if (!stead_path) return -1; strcpy(stead_path, "package.path=\""); if (path) { #if defined(WINRT) strcat(stead_path, path); /* winrt have not cwd :) */ strcat(stead_path, "/?.lua;"); #else strcat(stead_path, "./?.lua;"); #endif } #ifdef INSTEAD_LEGACY p = instead_local_stead_path(wd); if (p) { strcat(stead_path, p); strcat(stead_path, "/?.lua;"); } #endif if (!is_absolute_path(STEAD_API_PATH)) { strcat(stead_path, instead_cwd()); strcat(stead_path, "/"); strcat(stead_path, STEAD_API_PATH); } else { strcat(stead_path, STEAD_API_PATH); } strcat(stead_path, "/?.lua"); strcat(stead_path, "\""); if (standalone_sw) { strcat(stead_path, "..';'..(package.path or '')"); } instead_eval(stead_path); instead_clear(); free(stead_path); /* putenv(stead_path); */ return 0; } const char *instead_get_api(void) { return API; } const char *instead_lua_path(const char *path) { if (!path) return instead_base_path; if (!*path) { strncpy(instead_base_path, STEAD_PATH, sizeof(instead_base_path) - 1); return instead_base_path; } strncpy(instead_base_path, path, sizeof(instead_base_path) - 1); return instead_base_path; } static int instead_set_api(const char *api) { int i, c = 0; ssize_t s; char *oa; if (!api || !*api) { FREE(API); snprintf(instead_api_path, sizeof(instead_api_path), "%s", instead_lua_path(NULL)); } else { s = strlen(api); for (i = 0; i < s; i ++) { if (api[i] == '.') { if (c > 0) { instead_err_msg("Wrong API."); fprintf(stderr, "Wrong API.\n"); return -1; } c ++; } else c = 0; } oa = API; API = strdup(api); FREE(oa); snprintf(instead_api_path, sizeof(instead_api_path), "%s/%s", instead_lua_path(NULL), API); } return 0; } static int instead_detect_api(const char *path) { int api = 0; char *p; if (data_idf && idf_only(data_idf, -1) == 1) { if (!idf_access(data_idf, INSTEAD_MAIN3)) api = 3; else if (!idf_access(data_idf, INSTEAD_MAIN)) api = 2; } else { p = getfilepath(path, INSTEAD_MAIN3); if (!p) return -1; if (!access(dirpath(p), R_OK)) api = 3; free(p); if (api) goto out; p = getfilepath(path, INSTEAD_MAIN); if (!access(dirpath(p), R_OK)) api = 2; free(p); } out: switch (api){ case 2: if (instead_set_api("stead2") < 0) return -1; MAIN = INSTEAD_MAIN; break; case 3: if (instead_set_api("stead3") < 0) return -1; MAIN = INSTEAD_MAIN3; break; default: return -1; } return api; } int instead_init_lua(const char *path, int detect) { int api = 0; busy = 0; setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); /* to avoid . -> , in numbers */ setlocale(LC_CTYPE, "C"); /* to avoid lower/upper problems */ #ifdef LC_MESSAGES setlocale(LC_MESSAGES, "C"); #endif #ifdef LC_COLLATE setlocale(LC_COLLATE, "C"); #endif /* strcpy(curcp, "UTF-8"); */ instead_set_encoding("UTF-8"); getdir(instead_cwd_path, sizeof(instead_cwd_path)); unix_path(instead_cwd_path); instead_cwd_path[sizeof(instead_cwd_path) - 1] = 0; strncpy(instead_game_path, path, sizeof(instead_game_path) - 1); instead_cwd_path[sizeof(instead_game_path) - 1] = 0; if (detect && (api = instead_detect_api(path)) < 0) { fprintf(stderr, "Can not detect game format: %s\n", path); instead_err_msg("Can not detect game format."); return -1; } /* initialize Lua */ #if LUA_VERSION_NUM >= 502 L = luaL_newstate(); #else L = lua_open(); #endif if (!L) return -1; luaL_openlibs(L); #if LUA_VERSION_NUM >= 502 lua_pushglobaltable(L); lua_pushglobaltable(L); lua_setfield(L, -2, "_G"); /* open lib into global table */ luaL_setfuncs(L, base_funcs, 0); #else luaL_register(L, "_G", base_funcs); #endif instead_package(path); instead_platform(); /* instead_set_lang(opt_lang); */ if (api == 3) instead_eval("API='stead3'"); else if (api == 2) instead_eval("API='stead2'"); if (debug_sw) instead_eval("DEBUG=true"); else instead_eval("DEBUG=false"); instead_clear(); if (standalone_sw) instead_eval("STANDALONE=true"); else instead_eval("STANDALONE=false"); instead_clear(); srand(time(NULL)); mt_random_init(); luaopen_lfs(L); return 0; } int instead_init(const char *path) { char stead_path[PATH_MAX]; int idf = 0; if (data_idf) idf_done(data_idf); data_idf = idf_init(path); if (data_idf) { idf_only(data_idf, 1); idf = 1; } if (instead_init_lua(path, 1)) goto err; if (snprintf(stead_path, sizeof(stead_path), "%s/stead.lua", STEAD_API_PATH) >= (int)sizeof(stead_path)) fprintf(stderr, "Path is too long.\n"); if (dofile(L, dirpath(stead_path))) goto err; if (extensions_hook(init) < 0) { fprintf(stderr, "Can't init instead engine.\n"); goto err; } #ifdef _USE_SDL #if !defined(__EMSCRIPTEN__) && !defined(WINRT) sem = SDL_CreateMutex(); if (!sem) goto err; #endif #endif if ((!idf && setdir(path))) { instead_clear(); goto err; } if (!idf) data_idf = idf_init(DATA_IDF); /* cleanup Lua */ instead_clear(); instead_err_msg(NULL); return 0; err: if (data_idf) { idf_done(data_idf); data_idf = NULL; } if (L) lua_close(L); L = NULL; return -1; } int instead_api_register(const luaL_Reg *api) { if (!L) return -1; #if LUA_VERSION_NUM >= 502 lua_pushglobaltable(L); luaL_setfuncs(L, api, 0); #else lua_getfield(L, LUA_GLOBALSINDEX, "_G"); luaL_register(L, NULL, api); #endif lua_pop(L, 1); return 0; } void instead_done(void) { int wasL = !!L; if (wasL) extensions_hook(done); #ifdef _USE_SDL #if !defined(__EMSCRIPTEN__) && !defined(WINRT) if (sem) SDL_DestroyMutex(sem); sem = NULL; #endif #endif #ifdef _HAVE_ICONV FREE(fromcp); FREE(curcp); #endif if (L) lua_close(L); L = NULL; if (data_idf) idf_done(data_idf); data_idf = NULL; if (wasL) setdir(instead_cwd_path); FREE(API); } int instead_encode(const char *s, const char *d) { FILE *src; FILE *dst; size_t size; unsigned int i = 0; unsigned char byte = 0xcc; unsigned char buff[4096]; src = fopen(s, "rb"); if (!src) { fprintf(stderr,"Can't open on read: '%s'.\n", s); return -1; } dst = fopen(d, "wb"); if (!dst) { fprintf(stderr,"Can't open on write: '%s'.\n", s); fclose(src); return -1; } while ((size = fread(buff, 1, sizeof(buff), src))) { for (i = 0; i < size; i++) { buff[i] = (buff[i] << 3) | (buff[i] >> 5); buff[i] ^= byte; byte = buff[i]; } if (fwrite(buff, 1, size, dst) != size) { fprintf(stderr, "Error while writing file: '%s'.\n", d); fclose(src); fclose(dst); return -1; } } fclose(src); fclose(dst); return 0; } idf_t instead_idf(void) { return data_idf; } char *instead_stead_path(void) { return instead_api_path; } char *instead_path(void) { return instead_game_path; } char *instead_cwd(void) { return instead_cwd_path; } int instead_set_debug(int sw) { int ov = debug_sw; debug_sw = sw; if (L) { if (sw) instead_eval("DEBUG=true"); else instead_eval("DEBUG=false"); instead_clear(); } return ov; } int instead_set_standalone(int sw) { int ov = standalone_sw; standalone_sw = sw; if (L) { if (sw) instead_eval("STANDALONE=true"); else instead_eval("STANDALONE=false"); instead_clear(); } return ov; } int instead_set_lang(const char *opt_lang) { char lang[64]; if (!L) return 0; if (opt_lang && *opt_lang) snprintf(lang, sizeof(lang) - 1, "LANG='%s'", opt_lang); else snprintf(lang, sizeof(lang) - 1, "LANG='en'"); instead_eval(lang); instead_clear(); return 0; } lua_State *instead_lua(void) { return L; } instead-3.5.2+dfsg/src/instead/instead.h000066400000000000000000000065231467622671600201340ustar00rootroot00000000000000/* * Copyright 2009-2021 Peter Kosyh * * 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. * */ #ifndef __INSTEAD_H__ #define __INSTEAD_H__ #include #include #include "idf.h" #include "list.h" #define INSTEAD_NIL 0 #define INSTEAD_NUM 1 #define INSTEAD_STR 2 #define INSTEAD_BOOL 3 #define INSTEAD_MAIN "main.lua" #define INSTEAD_MAIN3 "main3.lua" #define INSTEAD_IDF "data.idf" #ifndef STEAD_PATH #define STEAD_PATH "./stead" #endif struct instead_args { int type; const char *val; }; struct instead_ext { struct list_node list; int (*init)(void); int (*done)(void); int (*err)(void); int (*cmd)(void); }; extern int instead_init(const char *path); extern int instead_load(char **info); extern void instead_done(void); extern void instead_lock(void); extern void instead_unlock(void); extern char *instead_cmd(char *s, int *rc); extern char *instead_file_cmd(char *s, int *rc); extern int instead_function(char *s, struct instead_args *args); extern int instead_eval(char *s); extern int instead_pcall(lua_State *L, int nargs); extern int instead_clear(void); extern char *instead_retval(int n); extern int instead_bretval(int n); extern int instead_iretval(int n); extern char *instead_fromgame(const char *s); extern int instead_encode(const char *s, const char *d); extern int instead_busy(void); extern void instead_set_encoding(const char *cp); /* UTF-8 by default */ /* internal use */ extern int instead_init_lua(const char *path, int detect); extern int instead_loadscript(const char *name, int argc, char **argv, int exec); extern int instead_loadfile(const char *name); extern void instead_err_msg(const char *s); extern const char *instead_err(void); extern int instead_extension(struct instead_ext *ext); extern int instead_api_register(const luaL_Reg *api); extern idf_t instead_idf(void); extern int instead_set_lang(const char *lang); extern int instead_set_debug(int); extern int instead_set_standalone(int); /* extern int instead_set_api(const char *api); */ extern const char *instead_lua_path(const char *path); /* override STEAD_PATH */ extern const char *instead_get_api(void); extern lua_State *instead_lua(void); extern char *instead_local_stead_path(void); extern char *instead_path(void); extern char *instead_stead_path(void); extern char *instead_cwd(void); #endif instead-3.5.2+dfsg/src/instead/lfs.c000066400000000000000000000056201467622671600172610ustar00rootroot00000000000000/* From: ** LuaFileSystem ** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem) ** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $ */ #include "system.h" #include "util.h" #define DIR_METATABLE "directory metatable" typedef struct dir_data { int closed; #ifdef _WIN32 intptr_t hFile; char pattern[PATH_MAX + 1]; #else DIR *dir; #endif } dir_data; /* ** Directory iterator */ static int dir_iter (lua_State *L) { #ifdef _WIN32 struct _finddata_t c_file; #else struct dirent *entry; #endif dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE); luaL_argcheck (L, d->closed == 0, 1, "closed directory"); #ifdef _WIN32 if (d->hFile == 0L) { /* first entry */ if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) { lua_pushnil (L); lua_pushstring (L, "Error while iterating dir."); d->closed = 1; return 2; } else { lua_pushstring (L, c_file.name); return 1; } } else { /* next entry */ if (_findnext (d->hFile, &c_file) == -1L) { /* no more entries => close directory */ _findclose (d->hFile); d->closed = 1; return 0; } else { lua_pushstring (L, c_file.name); return 1; } } #else if (!d->dir) return 0; /* no directory opened */ if ((entry = readdir (d->dir)) != NULL) { lua_pushstring (L, entry->d_name); return 1; } else { /* no more entries => close directory */ closedir (d->dir); d->closed = 1; return 0; } #endif } /* ** Closes directory iterators */ static int dir_close (lua_State *L) { dir_data *d = (dir_data *)lua_touserdata (L, 1); #ifdef _WIN32 if (!d->closed && d->hFile) { _findclose (d->hFile); } #else if (!d->closed && d->dir) { closedir (d->dir); } #endif d->closed = 1; return 0; } /* ** Factory of directory iterators */ int dir_iter_factory (lua_State *L) { const char *path = luaL_checkstring (L, 1); dir_data *d; lua_pushcfunction (L, dir_iter); d = (dir_data *) lua_newuserdata (L, sizeof(dir_data)); d->closed = 0; #ifdef _WIN32 d->hFile = 0L; luaL_getmetatable (L, DIR_METATABLE); lua_setmetatable (L, -2); if (strlen(path) > PATH_MAX - 2) luaL_error (L, "path too long: %s", path); else sprintf (d->pattern, "%s/*", path); #else luaL_getmetatable (L, DIR_METATABLE); lua_setmetatable (L, -2); d->dir = opendir (dirpath(path)); if (d->dir == NULL) luaL_error (L, "cannot open %s.", path); #endif return 2; } /* ** Creates directory metatable. */ static int dir_create_meta (lua_State *L) { luaL_newmetatable (L, DIR_METATABLE); /* set its __gc field */ lua_pushstring (L, "__index"); lua_newtable(L); lua_pushstring (L, "next"); lua_pushcfunction (L, dir_iter); lua_settable(L, -3); lua_pushstring (L, "close"); lua_pushcfunction (L, dir_close); lua_settable(L, -3); lua_settable (L, -3); lua_pushstring (L, "__gc"); lua_pushcfunction (L, dir_close); lua_settable (L, -3); return 1; } int luaopen_lfs (lua_State *L) { dir_create_meta (L); return 1; } instead-3.5.2+dfsg/src/instead/list.c000066400000000000000000000072241467622671600174520ustar00rootroot00000000000000/* Licensed under BSD-MIT - see LICENSE file for details */ #include #include #include "list.h" void list_head_init(struct list_head *h) { h->n.next = h->n.prev = &h->n; } void list_add(struct list_head *h, struct list_node *n) { n->next = h->n.next; n->prev = &h->n; h->n.next->prev = n; h->n.next = n; (void)list_debug(h); } void list_add_tail(struct list_head *h, struct list_node *n) { n->next = &h->n; n->prev = h->n.prev; h->n.prev->next = n; h->n.prev = n; (void)list_debug(h); } int list_empty(const struct list_head *h) { (void)list_debug(h); return h->n.next == &h->n; } void list_del(struct list_node *n) { (void)list_debug_node(n); n->next->prev = n->prev; n->prev->next = n->next; #ifdef CCAN_LIST_DEBUG /* Catch use-after-del. */ n->next = n->prev = NULL; #endif } void list_del_from(struct list_head *h, struct list_node *n) { #ifdef CCAN_LIST_DEBUG { /* Thorough check: make sure it was in list! */ struct list_node *i; for (i = h->n.next; i != n; i = i->next) assert(i != &h->n); } #endif /* CCAN_LIST_DEBUG */ /* Quick test that catches a surprising number of bugs. */ assert(!list_empty(h)); list_del(n); } const void *list_top_(const struct list_head *h, size_t off) { if (list_empty(h)) return NULL; return (const char *)h->n.next - off; } const void *list_pop_(const struct list_head *h, size_t off) { struct list_node *n; if (list_empty(h)) return NULL; n = h->n.next; list_del(n); return (const char *)n - off; } const void *list_tail_(const struct list_head *h, size_t off) { if (list_empty(h)) return NULL; return (const char *)h->n.prev - off; } void list_append_list(struct list_head *to, struct list_head *from) { struct list_node *from_tail = list_debug(from)->n.prev; struct list_node *to_tail = list_debug(to)->n.prev; /* Sew in head and entire list. */ to->n.prev = from_tail; from_tail->next = &to->n; to_tail->next = &from->n; from->n.prev = to_tail; /* Now remove head. */ list_del(&from->n); list_head_init(from); } void list_prepend_list(struct list_head *to, struct list_head *from) { struct list_node *from_tail = list_debug(from)->n.prev; struct list_node *to_head = list_debug(to)->n.next; /* Sew in head and entire list. */ to->n.next = &from->n; from->n.prev = &to->n; to_head->prev = from_tail; from_tail->next = to_head; /* Now remove head. */ list_del(&from->n); list_head_init(from); } void *list_node_to_off_(struct list_node *node, size_t off) { return (void *)((char *)node - off); } struct list_node *list_node_from_off_(void *ptr, size_t off) { return (struct list_node *)((char *)ptr + off); } void *list_entry_or_null(const struct list_head *h, const struct list_node *n, size_t off) { if (n == &h->n) return NULL; return (char *)n - off; } static void *corrupt(const char *abortstr, const struct list_node *head, const struct list_node *node, unsigned int count) { if (abortstr) { fprintf(stderr, "%s: prev corrupt in node %p (%u) of %p\n", abortstr, node, count, head); abort(); } return NULL; } struct list_node *list_check_node(const struct list_node *node, const char *abortstr) { const struct list_node *p, *n; int count = 0; for (p = node, n = node->next; n != node; p = n, n = n->next) { count++; if (n->prev != p) return corrupt(abortstr, node, n, count); } /* Check prev on head node. */ if (node->prev != p) return corrupt(abortstr, node, node, 0); return (struct list_node *)node; } struct list_head *list_check(const struct list_head *h, const char *abortstr) { if (!list_check_node(&h->n, abortstr)) return NULL; return (struct list_head *)h; } instead-3.5.2+dfsg/src/instead/list.h000066400000000000000000000517751467622671600174710ustar00rootroot00000000000000/* Licensed under BSD-MIT - see LICENSE file for details */ #ifndef CCAN_LIST_H #define CCAN_LIST_H #include #include /** * BUILD_ASSERT - assert a build-time dependency. * @cond: the compile-time condition which must be true. * * Your compile will fail if the condition isn't true, or can't be evaluated * by the compiler. This can only be used within a function. * * Example: * #include * ... * static char *foo_to_char(struct foo *foo) * { * // This code needs string to be at start of foo. * BUILD_ASSERT(offsetof(struct foo, string) == 0); * return (char *)foo; * } */ #define BUILD_ASSERT(cond) \ do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) /** * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. * @cond: the compile-time condition which must be true. * * Your compile will fail if the condition isn't true, or can't be evaluated * by the compiler. This can be used in an expression: its value is "0". * * Example: * #define foo_to_char(foo) \ * ((char *)(foo) \ * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) */ #define BUILD_ASSERT_OR_ZERO(cond) \ (sizeof(char [1 - 2*!(cond)]) - 1) /** * check_type - issue a warning or build failure if type is not correct. * @expr: the expression whose type we should check (not evaluated). * @type: the exact type we expect the expression to be. * * This macro is usually used within other macros to try to ensure that a macro * argument is of the expected type. No type promotion of the expression is * done: an unsigned int is not the same as an int! * * check_type() always evaluates to 0. * * If your compiler does not support typeof, then the best we can do is fail * to compile if the sizes of the types are unequal (a less complete check). * * Example: * // They should always pass a 64-bit value to _set_some_value! * #define set_some_value(expr) \ * _set_some_value((check_type((expr), uint64_t), (expr))) */ /** * check_types_match - issue a warning or build failure if types are not same. * @expr1: the first expression (not evaluated). * @expr2: the second expression (not evaluated). * * This macro is usually used within other macros to try to ensure that * arguments are of identical types. No type promotion of the expressions is * done: an unsigned int is not the same as an int! * * check_types_match() always evaluates to 0. * * If your compiler does not support typeof, then the best we can do is fail * to compile if the sizes of the types are unequal (a less complete check). * * Example: * // Do subtraction to get to enclosing type, but make sure that * // pointer is of correct type for that member. * #define container_of(mbr_ptr, encl_type, mbr) \ * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \ * ((encl_type *) \ * ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr)))) */ #if HAVE_TYPEOF #define check_type(expr, type) \ ((typeof(expr) *)0 != (type *)0) #define check_types_match(expr1, expr2) \ ((typeof(expr1) *)0 != (typeof(expr2) *)0) #else /* Without typeof, we can only test the sizes. */ #define check_type(expr, type) \ BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type)) #define check_types_match(expr1, expr2) \ BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2)) #endif /* HAVE_TYPEOF */ /** * container_of - get pointer to enclosing structure * @member_ptr: pointer to the structure member * @containing_type: the type this member is within * @member: the name of this member within the structure. * * Given a pointer to a member of a structure, this macro does pointer * subtraction to return the pointer to the enclosing type. * * Example: * struct foo { * int fielda, fieldb; * // ... * }; * struct info { * int some_other_field; * struct foo my_foo; * }; * * static struct info *foo_to_info(struct foo *foo) * { * return container_of(foo, struct info, my_foo); * } */ #define container_of(member_ptr, containing_type, member) \ ((containing_type *) \ ((char *)(member_ptr) \ - container_off(containing_type, member)) \ + check_types_match(*(member_ptr), ((containing_type *)0)->member)) /** * container_off - get offset to enclosing structure * @containing_type: the type this member is within * @member: the name of this member within the structure. * * Given a pointer to a member of a structure, this macro does * typechecking and figures out the offset to the enclosing type. * * Example: * struct foo { * int fielda, fieldb; * // ... * }; * struct info { * int some_other_field; * struct foo my_foo; * }; * * static struct info *foo_to_info(struct foo *foo) * { * size_t off = container_off(struct info, my_foo); * return (void *)((char *)foo - off); * } */ #define container_off(containing_type, member) \ offsetof(containing_type, member) /** * container_of_var - get pointer to enclosing structure using a variable * @member_ptr: pointer to the structure member * @container_var: a pointer of same type as this member's container * @member: the name of this member within the structure. * * Given a pointer to a member of a structure, this macro does pointer * subtraction to return the pointer to the enclosing type. * * Example: * static struct info *foo_to_i(struct foo *foo) * { * struct info *i = container_of_var(foo, i, my_foo); * return i; * } */ #if HAVE_TYPEOF #define container_of_var(member_ptr, container_var, member) \ container_of(member_ptr, typeof(*container_var), member) #else #define container_of_var(member_ptr, container_var, member) \ ((void *)((char *)(member_ptr) - \ container_off_var(container_var, member))) #endif /** * container_off_var - get offset of a field in enclosing structure * @container_var: a pointer to a container structure * @member: the name of a member within the structure. * * Given (any) pointer to a structure and a its member name, this * macro does pointer subtraction to return offset of member in a * structure memory layout. * */ #if HAVE_TYPEOF #define container_off_var(var, member) \ container_off(typeof(*var), member) #else #define container_off_var(var, member) \ ((char *)&(var)->member - (char *)(var)) #endif /** * struct list_node - an entry in a doubly-linked list * @next: next entry (self if empty) * @prev: previous entry (self if empty) * * This is used as an entry in a linked list. * Example: * struct child { * const char *name; * // Linked list of all us children. * struct list_node list; * }; */ struct list_node { struct list_node *next, *prev; }; /** * struct list_head - the head of a doubly-linked list * @h: the list_head (containing next and prev pointers) * * This is used as the head of a linked list. * Example: * struct parent { * const char *name; * struct list_head children; * unsigned int num_children; * }; */ struct list_head { struct list_node n; }; /** * list_check - check head of a list for consistency * @h: the list_head * @abortstr: the location to print on aborting, or NULL. * * Because list_nodes have redundant information, consistency checking between * the back and forward links can be done. This is useful as a debugging check. * If @abortstr is non-NULL, that will be printed in a diagnostic if the list * is inconsistent, and the function will abort. * * Returns the list head if the list is consistent, NULL if not (it * can never return NULL if @abortstr is set). * * See also: list_check_node() * * Example: * static void dump_parent(struct parent *p) * { * struct child *c; * * printf("%s (%u children):\n", p->name, p->num_children); * list_check(&p->children, "bad child list"); * list_for_each(&p->children, c, list) * printf(" -> %s\n", c->name); * } */ struct list_head *list_check(const struct list_head *h, const char *abortstr); /** * list_check_node - check node of a list for consistency * @n: the list_node * @abortstr: the location to print on aborting, or NULL. * * Check consistency of the list node is in (it must be in one). * * See also: list_check() * * Example: * static void dump_child(const struct child *c) * { * list_check_node(&c->list, "bad child list"); * printf("%s\n", c->name); * } */ struct list_node *list_check_node(const struct list_node *n, const char *abortstr); #ifdef CCAN_LIST_DEBUG #define list_debug(h) list_check((h), __func__) #define list_debug_node(n) list_check_node((n), __func__) #else #define list_debug(h) (h) #define list_debug_node(n) (n) #endif /** * LIST_HEAD_INIT - initializer for an empty list_head * @name: the name of the list. * * Explicit initializer for an empty list. * * See also: * LIST_HEAD, list_head_init() * * Example: * static struct list_head my_list = LIST_HEAD_INIT(my_list); */ #define LIST_HEAD_INIT(name) { { &name.n, &name.n } } /** * LIST_HEAD - define and initialize an empty list_head * @name: the name of the list. * * The LIST_HEAD macro defines a list_head and initializes it to an empty * list. It can be prepended by "static" to define a static list_head. * * See also: * LIST_HEAD_INIT, list_head_init() * * Example: * static LIST_HEAD(my_global_list); */ #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) /** * list_head_init - initialize a list_head * @h: the list_head to set to the empty list * * Example: * ... * struct parent *parent = malloc(sizeof(*parent)); * * list_head_init(&parent->children); * parent->num_children = 0; */ void list_head_init(struct list_head *h); /** * list_add - add an entry at the start of a linked list. * @h: the list_head to add the node to * @n: the list_node to add to the list. * * The list_node does not need to be initialized; it will be overwritten. * Example: * struct child *child = malloc(sizeof(*child)); * * child->name = "marvin"; * list_add(&parent->children, &child->list); * parent->num_children++; */ void list_add(struct list_head *h, struct list_node *n); /** * list_add_tail - add an entry at the end of a linked list. * @h: the list_head to add the node to * @n: the list_node to add to the list. * * The list_node does not need to be initialized; it will be overwritten. * Example: * list_add_tail(&parent->children, &child->list); * parent->num_children++; */ void list_add_tail(struct list_head *h, struct list_node *n); /** * list_empty - is a list empty? * @h: the list_head * * If the list is empty, returns true. * * Example: * assert(list_empty(&parent->children) == (parent->num_children == 0)); */ int list_empty(const struct list_head *h); /** * list_del - delete an entry from an (unknown) linked list. * @n: the list_node to delete from the list. * * Note that this leaves @n in an undefined state; it can be added to * another list, but not deleted again. * * See also: * list_del_from() * * Example: * list_del(&child->list); * parent->num_children--; */ void list_del(struct list_node *n); /** * list_del_from - delete an entry from a known linked list. * @h: the list_head the node is in. * @n: the list_node to delete from the list. * * This explicitly indicates which list a node is expected to be in, * which is better documentation and can catch more bugs. * * See also: list_del() * * Example: * list_del_from(&parent->children, &child->list); * parent->num_children--; */ void list_del_from(struct list_head *h, struct list_node *n); /** * list_entry - convert a list_node back into the structure containing it. * @n: the list_node * @type: the type of the entry * @member: the list_node member of the type * * Example: * // First list entry is children.next; convert back to child. * child = list_entry(parent->children.n.next, struct child, list); * * See Also: * list_top(), list_for_each() */ #define list_entry(n, type, member) container_of(n, type, member) /** * list_top - get the first entry in a list * @h: the list_head * @type: the type of the entry * @member: the list_node member of the type * * If the list is empty, returns NULL. * * Example: * struct child *first; * first = list_top(&parent->children, struct child, list); * if (!first) * printf("Empty list!\n"); */ #define list_top(h, type, member) \ ((type *)list_top_((h), list_off_(type, member))) const void *list_top_(const struct list_head *h, size_t off); /** * list_pop - remove the first entry in a list * @h: the list_head * @type: the type of the entry * @member: the list_node member of the type * * If the list is empty, returns NULL. * * Example: * struct child *one; * one = list_pop(&parent->children, struct child, list); * if (!one) * printf("Empty list!\n"); */ #define list_pop(h, type, member) \ ((type *)list_pop_((h), list_off_(type, member))) const void *list_pop_(const struct list_head *h, size_t off); /** * list_tail - get the last entry in a list * @h: the list_head * @type: the type of the entry * @member: the list_node member of the type * * If the list is empty, returns NULL. * * Example: * struct child *last; * last = list_tail(&parent->children, struct child, list); * if (!last) * printf("Empty list!\n"); */ #define list_tail(h, type, member) \ ((type *)list_tail_((h), list_off_(type, member))) const void *list_tail_(const struct list_head *h, size_t off); /** * list_for_each - iterate through a list. * @h: the list_head (warning: evaluated multiple times!) * @i: the structure containing the list_node * @member: the list_node member of the structure * * This is a convenient wrapper to iterate @i over the entire list. It's * a for loop, so you can break and continue as normal. * * Example: * list_for_each(&parent->children, child, list) * printf("Name: %s\n", child->name); */ #define list_for_each(h, i, member) \ list_for_each_off(h, i, list_off_var_(i, member)) /** * list_for_each_rev - iterate through a list backwards. * @h: the list_head * @i: the structure containing the list_node * @member: the list_node member of the structure * * This is a convenient wrapper to iterate @i over the entire list. It's * a for loop, so you can break and continue as normal. * * Example: * list_for_each_rev(&parent->children, child, list) * printf("Name: %s\n", child->name); */ #define list_for_each_rev(h, i, member) \ for (i = container_of_var(list_debug(h)->n.prev, i, member); \ &i->member != &(h)->n; \ i = container_of_var(i->member.prev, i, member)) /** * list_for_each_safe - iterate through a list, maybe during deletion * @h: the list_head * @i: the structure containing the list_node * @nxt: the structure containing the list_node * @member: the list_node member of the structure * * This is a convenient wrapper to iterate @i over the entire list. It's * a for loop, so you can break and continue as normal. The extra variable * @nxt is used to hold the next element, so you can delete @i from the list. * * Example: * struct child *next; * list_for_each_safe(&parent->children, child, next, list) { * list_del(&child->list); * parent->num_children--; * } */ #define list_for_each_safe(h, i, nxt, member) \ list_for_each_safe_off(h, i, nxt, list_off_var_(i, member)) /** * list_next - get the next entry in a list * @h: the list_head * @i: a pointer to an entry in the list. * @member: the list_node member of the structure * * If @i was the last entry in the list, returns NULL. * * Example: * struct child *second; * second = list_next(&parent->children, first, list); * if (!second) * printf("No second child!\n"); */ #define list_next(h, i, member) \ ((list_typeof(i))list_entry_or_null(list_debug(h), \ (i)->member.next, \ list_off_var_((i), member))) /** * list_prev - get the previous entry in a list * @h: the list_head * @i: a pointer to an entry in the list. * @member: the list_node member of the structure * * If @i was the first entry in the list, returns NULL. * * Example: * first = list_prev(&parent->children, second, list); * if (!first) * printf("Can't go back to first child?!\n"); */ #define list_prev(h, i, member) \ ((list_typeof(i))list_entry_or_null(list_debug(h), \ (i)->member.prev, \ list_off_var_((i), member))) /** * list_append_list - empty one list onto the end of another. * @to: the list to append into * @from: the list to empty. * * This takes the entire contents of @from and moves it to the end of * @to. After this @from will be empty. * * Example: * struct list_head adopter; * * list_append_list(&adopter, &parent->children); * assert(list_empty(&parent->children)); * parent->num_children = 0; */ void list_append_list(struct list_head *to, struct list_head *from); /** * list_prepend_list - empty one list into the start of another. * @to: the list to prepend into * @from: the list to empty. * * This takes the entire contents of @from and moves it to the start * of @to. After this @from will be empty. * * Example: * list_prepend_list(&adopter, &parent->children); * assert(list_empty(&parent->children)); * parent->num_children = 0; */ void list_prepend_list(struct list_head *to, struct list_head *from); /** * list_for_each_off - iterate through a list of memory regions. * @h: the list_head * @i: the pointer to a memory region wich contains list node data. * @off: offset(relative to @i) at which list node data resides. * * This is a low-level wrapper to iterate @i over the entire list, used to * implement all oher, more high-level, for-each constructs. It's a for loop, * so you can break and continue as normal. * * WARNING! Being the low-level macro that it is, this wrapper doesn't know * nor care about the type of @i. The only assumtion made is that @i points * to a chunk of memory that at some @offset, relative to @i, contains a * properly filled `struct node_list' which in turn contains pointers to * memory chunks and it's turtles all the way down. Whith all that in mind * remember that given the wrong pointer/offset couple this macro will * happilly churn all you memory untill SEGFAULT stops it, in other words * caveat emptor. * * It is worth mentioning that one of legitimate use-cases for that wrapper * is operation on opaque types with known offset for `struct list_node' * member(preferably 0), because it allows you not to disclose the type of * @i. * * Example: * list_for_each_off(&parent->children, child, * offsetof(struct child, list)) * printf("Name: %s\n", child->name); */ #define list_for_each_off(h, i, off) \ for (i = list_node_to_off_(list_debug(h)->n.next, (off)); \ list_node_from_off_((void *)i, (off)) != &(h)->n; \ i = list_node_to_off_(list_node_from_off_((void *)i, (off))->next, \ (off))) /** * list_for_each_safe_off - iterate through a list of memory regions, maybe * during deletion * @h: the list_head * @i: the pointer to a memory region wich contains list node data. * @nxt: the structure containing the list_node * @off: offset(relative to @i) at which list node data resides. * * For details see `list_for_each_off' and `list_for_each_safe' * descriptions. * * Example: * list_for_each_safe_off(&parent->children, child, * next, offsetof(struct child, list)) * printf("Name: %s\n", child->name); */ #define list_for_each_safe_off(h, i, nxt, off) \ for (i = list_node_to_off_(list_debug(h)->n.next, (off)), \ nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \ (off)); \ list_node_from_off_(i, (off)) != &(h)->n; \ i = nxt, \ nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \ (off))) /* Other -off variants. */ #define list_entry_off(n, type, off) \ ((type *)list_node_from_off_((n), (off))) #define list_head_off(h, type, off) \ ((type *)list_head_off((h), (off))) #define list_tail_off(h, type, off) \ ((type *)list_tail_((h), (off))) #define list_add_off(h, n, off) \ list_add((h), list_node_from_off_((n), (off))) #define list_del_off(n, off) \ list_del(list_node_from_off_((n), (off))) #define list_del_from_off(h, n, off) \ list_del_from(h, list_node_from_off_((n), (off))) /* Offset helper functions so we only single-evaluate. */ void *list_node_to_off_(struct list_node *node, size_t off); struct list_node *list_node_from_off_(void *ptr, size_t off); /* Get the offset of the member, but make sure it's a list_node. */ #define list_off_(type, member) \ (container_off(type, member) + \ check_type(((type *)0)->member, struct list_node)) #define list_off_var_(var, member) \ (container_off_var(var, member) + \ check_type(var->member, struct list_node)) #if HAVE_TYPEOF #define list_typeof(var) typeof(var) #else #define list_typeof(var) void * #endif /* Returns member, or NULL if at end of list. */ void *list_entry_or_null(const struct list_head *h, const struct list_node *n, size_t off); #endif /* CCAN_LIST_H */ instead-3.5.2+dfsg/src/instead/snprintf.c000066400000000000000000001472111467622671600203430ustar00rootroot00000000000000/* $Id: snprintf.c,v 1.9 2008/01/20 14:02:00 holger Exp $ */ /* * Copyright (c) 1995 Patrick Powell. * * This code is based on code written by Patrick Powell . * It may be used for any purpose as long as this notice remains intact on all * source code distributions. */ /* * Copyright (c) 2008 Holger Weiss. * * This version of the code is maintained by Holger Weiss . * My changes to the code may freely be used, modified and/or redistributed for * any purpose. It would be nice if additions and fixes to this file (including * trivial code cleanups) would be sent back in order to let me include them in * the version available at . * However, this is not a requirement for using or redistributing (possibly * modified) versions of this file, nor is leaving this notice intact mandatory. */ /* * History * * 2008-01-20 Holger Weiss for C99-snprintf 1.1: * * Fixed the detection of infinite floating point values on IRIX (and * possibly other systems) and applied another few minor cleanups. * * 2008-01-06 Holger Weiss for C99-snprintf 1.0: * * Added a lot of new features, fixed many bugs, and incorporated various * improvements done by Andrew Tridgell , Russ Allbery * , Hrvoje Niksic , Damien Miller * , and others for the Samba, INN, Wget, and OpenSSH * projects. The additions include: support the "e", "E", "g", "G", and * "F" conversion specifiers (and use conversion style "f" or "F" for the * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", * "t", and "z" length modifiers; support the "#" flag and the (non-C99) * "'" flag; use localeconv(3) (if available) to get both the current * locale's decimal point character and the separator between groups of * digits; fix the handling of various corner cases of field width and * precision specifications; fix various floating point conversion bugs; * handle infinite and NaN floating point values; don't attempt to write to * the output buffer (which may be NULL) if a size of zero was specified; * check for integer overflow of the field width, precision, and return * values and during the floating point conversion; use the OUTCHAR() macro * instead of a function for better performance; provide asprintf(3) and * vasprintf(3) functions; add new test cases. The replacement functions * have been renamed to use an "rpl_" prefix, the function calls in the * main project (and in this file) must be redefined accordingly for each * replacement function which is needed (by using Autoconf or other means). * Various other minor improvements have been applied and the coding style * was cleaned up for consistency. * * 2007-07-23 Holger Weiss for Mutt 1.5.13: * * C99 compliant snprintf(3) and vsnprintf(3) functions return the number * of characters that would have been written to a sufficiently sized * buffer (excluding the '\0'). The original code simply returned the * length of the resulting output string, so that's been fixed. * * 1998-03-05 Michael Elkins for Mutt 0.90.8: * * The original code assumed that both snprintf(3) and vsnprintf(3) were * missing. Some systems only have snprintf(3) but not vsnprintf(3), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * * 1998-01-27 Thomas Roessler for Mutt 0.89i: * * The PGP code was using unsigned hexadecimal formats. Unfortunately, * unsigned formats simply didn't work. * * 1997-10-22 Brandon Long for Mutt 0.87.1: * * Ok, added some minimal floating point support, which means this probably * requires libm on most operating systems. Don't yet support the exponent * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just * wasn't being exercised in ways which showed it, so that's been fixed. * Also, formatted the code to Mutt conventions, and removed dead code left * over from the original. Also, there is now a builtin-test, run with: * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf * * 2996-09-15 Brandon Long for Mutt 0.43: * * This was ugly. It is still ugly. I opted out of floating point * numbers, but the formatter understands just about everything from the * normal C string format, at least as far as I can tell from the Solaris * 2.5 printf(3S) man page. */ /* * ToDo * * - Add wide character support. * - Add support for "%a" and "%A" conversions. * - Create test routines which predefine the expected results. Our test cases * usually expose bugs in system implementations rather than in ours :-) */ /* * Usage * * 1) The following preprocessor macros should be defined to 1 if the feature or * file in question is available on the target system (by using Autoconf or * other means), though basic functionality should be available as long as * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: * * HAVE_VSNPRINTF * HAVE_SNPRINTF * HAVE_VASPRINTF * HAVE_ASPRINTF * HAVE_STDARG_H * HAVE_STDDEF_H * HAVE_STDINT_H * HAVE_STDLIB_H * HAVE_INTTYPES_H * HAVE_LOCALE_H * HAVE_LOCALECONV * HAVE_LCONV_DECIMAL_POINT * HAVE_LCONV_THOUSANDS_SEP * HAVE_LONG_DOUBLE * HAVE_LONG_LONG_INT * HAVE_UNSIGNED_LONG_LONG_INT * HAVE_INTMAX_T * HAVE_UINTMAX_T * HAVE_UINTPTR_T * HAVE_PTRDIFF_T * HAVE_VA_COPY * HAVE___VA_COPY * * 2) The calls to the functions which should be replaced must be redefined * throughout the project files (by using Autoconf or other means): * * #define vsnprintf rpl_vsnprintf * #define snprintf rpl_snprintf * #define vasprintf rpl_vasprintf * #define asprintf rpl_asprintf * * 3) The required replacement functions should be declared in some header file * included throughout the project files: * * #if HAVE_CONFIG_H * #include * #endif * #if HAVE_STDARG_H * #include * #if !HAVE_VSNPRINTF * int rpl_vsnprintf(char *, size_t, const char *, va_list); * #endif * #if !HAVE_SNPRINTF * int rpl_snprintf(char *, size_t, const char *, ...); * #endif * #if !HAVE_VASPRINTF * int rpl_vasprintf(char **, const char *, va_list); * #endif * #if !HAVE_ASPRINTF * int rpl_asprintf(char **, const char *, ...); * #endif * #endif * * Autoconf macros for handling step 1 and step 2 are available at * . */ #define HAVE_STDARG_H 1 #define HAVE_STDLIB_H 1 #if HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #if TEST_SNPRINTF #include /* For pow(3), NAN, and INFINITY. */ #include /* For strcmp(3). */ #if defined(__NetBSD__) || \ defined(__FreeBSD__) || \ defined(__OpenBSD__) || \ defined(__NeXT__) || \ defined(__bsd__) #define OS_BSD 1 #elif defined(sgi) || defined(__sgi) #ifndef __c99 #define __c99 /* Force C99 mode to get included on IRIX 6.5.30. */ #endif /* !defined(__c99) */ #define OS_IRIX 1 #define OS_SYSV 1 #elif defined(__svr4__) #define OS_SYSV 1 #elif defined(__linux__) #define OS_LINUX 1 #endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */ #if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */ #ifdef HAVE_SNPRINTF #undef HAVE_SNPRINTF #endif /* defined(HAVE_SNPRINTF) */ #ifdef HAVE_VSNPRINTF #undef HAVE_VSNPRINTF #endif /* defined(HAVE_VSNPRINTF) */ #ifdef HAVE_ASPRINTF #undef HAVE_ASPRINTF #endif /* defined(HAVE_ASPRINTF) */ #ifdef HAVE_VASPRINTF #undef HAVE_VASPRINTF #endif /* defined(HAVE_VASPRINTF) */ #ifdef snprintf #undef snprintf #endif /* defined(snprintf) */ #ifdef vsnprintf #undef vsnprintf #endif /* defined(vsnprintf) */ #ifdef asprintf #undef asprintf #endif /* defined(asprintf) */ #ifdef vasprintf #undef vasprintf #endif /* defined(vasprintf) */ #else /* By default, we assume a modern system for testing. */ #ifndef HAVE_STDARG_H #define HAVE_STDARG_H 1 #endif /* HAVE_STDARG_H */ #ifndef HAVE_STDDEF_H #define HAVE_STDDEF_H 1 #endif /* HAVE_STDDEF_H */ #ifndef HAVE_STDINT_H #define HAVE_STDINT_H 1 #endif /* HAVE_STDINT_H */ #ifndef HAVE_STDLIB_H #define HAVE_STDLIB_H 1 #endif /* HAVE_STDLIB_H */ #ifndef HAVE_INTTYPES_H #define HAVE_INTTYPES_H 1 #endif /* HAVE_INTTYPES_H */ #ifndef HAVE_LOCALE_H #define HAVE_LOCALE_H 1 #endif /* HAVE_LOCALE_H */ #ifndef HAVE_LOCALECONV #define HAVE_LOCALECONV 1 #endif /* !defined(HAVE_LOCALECONV) */ #ifndef HAVE_LCONV_DECIMAL_POINT #define HAVE_LCONV_DECIMAL_POINT 1 #endif /* HAVE_LCONV_DECIMAL_POINT */ #ifndef HAVE_LCONV_THOUSANDS_SEP #define HAVE_LCONV_THOUSANDS_SEP 1 #endif /* HAVE_LCONV_THOUSANDS_SEP */ #ifndef HAVE_LONG_DOUBLE #define HAVE_LONG_DOUBLE 1 #endif /* !defined(HAVE_LONG_DOUBLE) */ #ifndef HAVE_LONG_LONG_INT #define HAVE_LONG_LONG_INT 1 #endif /* !defined(HAVE_LONG_LONG_INT) */ #ifndef HAVE_UNSIGNED_LONG_LONG_INT #define HAVE_UNSIGNED_LONG_LONG_INT 1 #endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */ #ifndef HAVE_INTMAX_T #define HAVE_INTMAX_T 1 #endif /* !defined(HAVE_INTMAX_T) */ #ifndef HAVE_UINTMAX_T #define HAVE_UINTMAX_T 1 #endif /* !defined(HAVE_UINTMAX_T) */ #ifndef HAVE_UINTPTR_T #define HAVE_UINTPTR_T 1 #endif /* !defined(HAVE_UINTPTR_T) */ #ifndef HAVE_PTRDIFF_T #define HAVE_PTRDIFF_T 1 #endif /* !defined(HAVE_PTRDIFF_T) */ #ifndef HAVE_VA_COPY #define HAVE_VA_COPY 1 #endif /* !defined(HAVE_VA_COPY) */ #ifndef HAVE___VA_COPY #define HAVE___VA_COPY 1 #endif /* !defined(HAVE___VA_COPY) */ #endif /* HAVE_CONFIG_H */ #define snprintf rpl_snprintf #define vsnprintf rpl_vsnprintf #define asprintf rpl_asprintf #define vasprintf rpl_vasprintf #endif /* TEST_SNPRINTF */ #if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF #include /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ #ifdef VA_START #undef VA_START #endif /* defined(VA_START) */ #ifdef VA_SHIFT #undef VA_SHIFT #endif /* defined(VA_SHIFT) */ #if HAVE_STDARG_H #include #define VA_START(ap, last) va_start(ap, last) #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ #else /* Assume is available. */ #include #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ #define VA_SHIFT(ap, value, type) value = va_arg(ap, type) #endif /* HAVE_STDARG_H */ #if !HAVE_VASPRINTF #if HAVE_STDLIB_H #include /* For malloc(3). */ #endif /* HAVE_STDLIB_H */ #ifdef VA_COPY #undef VA_COPY #endif /* defined(VA_COPY) */ #ifdef VA_END_COPY #undef VA_END_COPY #endif /* defined(VA_END_COPY) */ #if HAVE_VA_COPY #define VA_COPY(dest, src) va_copy(dest, src) #define VA_END_COPY(ap) va_end(ap) #elif HAVE___VA_COPY #define VA_COPY(dest, src) __va_copy(dest, src) #define VA_END_COPY(ap) va_end(ap) #else #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) #define VA_END_COPY(ap) /* No-op. */ #define NEED_MYMEMCPY 1 static void *mymemcpy(void *, void *, size_t); #endif /* HAVE_VA_COPY */ #endif /* !HAVE_VASPRINTF */ #if !HAVE_VSNPRINTF #include /* For ERANGE and errno. */ #include /* For *_MAX. */ #if HAVE_INTTYPES_H #include /* For intmax_t (if not defined in ). */ #endif /* HAVE_INTTYPES_H */ #if HAVE_LOCALE_H #include /* For localeconv(3). */ #endif /* HAVE_LOCALE_H */ #if HAVE_STDDEF_H #include /* For ptrdiff_t. */ #endif /* HAVE_STDDEF_H */ #if HAVE_STDINT_H #include /* For intmax_t. */ #endif /* HAVE_STDINT_H */ /* Support for unsigned long long int. We may also need ULLONG_MAX. */ #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ #ifdef UINT_MAX #define ULONG_MAX UINT_MAX #else #define ULONG_MAX INT_MAX #endif /* defined(UINT_MAX) */ #endif /* !defined(ULONG_MAX) */ #ifdef ULLONG #undef ULLONG #endif /* defined(ULLONG) */ #if HAVE_UNSIGNED_LONG_LONG_INT #define ULLONG unsigned long long int #ifndef ULLONG_MAX #define ULLONG_MAX ULONG_MAX #endif /* !defined(ULLONG_MAX) */ #else #define ULLONG unsigned long int #ifdef ULLONG_MAX #undef ULLONG_MAX #endif /* defined(ULLONG_MAX) */ #define ULLONG_MAX ULONG_MAX #endif /* HAVE_LONG_LONG_INT */ /* Support for uintmax_t. We also need UINTMAX_MAX. */ #ifdef UINTMAX_T #undef UINTMAX_T #endif /* defined(UINTMAX_T) */ #if HAVE_UINTMAX_T || defined(uintmax_t) #define UINTMAX_T uintmax_t #ifndef UINTMAX_MAX #define UINTMAX_MAX ULLONG_MAX #endif /* !defined(UINTMAX_MAX) */ #else #define UINTMAX_T ULLONG #ifdef UINTMAX_MAX #undef UINTMAX_MAX #endif /* defined(UINTMAX_MAX) */ #define UINTMAX_MAX ULLONG_MAX #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ /* Support for long double. */ #ifndef LDOUBLE #if HAVE_LONG_DOUBLE #define LDOUBLE long double #else #define LDOUBLE double #endif /* HAVE_LONG_DOUBLE */ #endif /* !defined(LDOUBLE) */ /* Support for long long int. */ #ifndef LLONG #if HAVE_LONG_LONG_INT #define LLONG long long int #else #define LLONG long int #endif /* HAVE_LONG_LONG_INT */ #endif /* !defined(LLONG) */ /* Support for intmax_t. */ #ifndef INTMAX_T #if HAVE_INTMAX_T || defined(intmax_t) #define INTMAX_T intmax_t #else #define INTMAX_T LLONG #endif /* HAVE_INTMAX_T || defined(intmax_t) */ #endif /* !defined(INTMAX_T) */ /* Support for uintptr_t. */ #ifndef UINTPTR_T #if HAVE_UINTPTR_T || defined(uintptr_t) #define UINTPTR_T uintptr_t #else #define UINTPTR_T unsigned long int #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ #endif /* !defined(UINTPTR_T) */ /* Support for ptrdiff_t. */ #ifndef PTRDIFF_T #if HAVE_PTRDIFF_T || defined(ptrdiff_t) #define PTRDIFF_T ptrdiff_t #else #define PTRDIFF_T long int #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ #endif /* !defined(PTRDIFF_T) */ /* * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an * unsigned type if necessary. This should work just fine in practice. */ #ifndef UPTRDIFF_T #define UPTRDIFF_T PTRDIFF_T #endif /* !defined(UPTRDIFF_T) */ /* * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). * However, we'll simply use size_t and convert it to a signed type if * necessary. This should work just fine in practice. */ #ifndef SSIZE_T #define SSIZE_T size_t #endif /* !defined(SSIZE_T) */ /* Either ERANGE or E2BIG should be available everywhere. */ #ifndef ERANGE #define ERANGE E2BIG #endif /* !defined(ERANGE) */ #ifndef EOVERFLOW #define EOVERFLOW ERANGE #endif /* !defined(EOVERFLOW) */ /* * Buffer size to hold the octal string representation of UINT128_MAX without * nul-termination ("3777777777777777777777777777777777777777777"). */ #ifdef MAX_CONVERT_LENGTH #undef MAX_CONVERT_LENGTH #endif /* defined(MAX_CONVERT_LENGTH) */ #define MAX_CONVERT_LENGTH 43 /* Format read states. */ #define PRINT_S_DEFAULT 0 #define PRINT_S_FLAGS 1 #define PRINT_S_WIDTH 2 #define PRINT_S_DOT 3 #define PRINT_S_PRECISION 4 #define PRINT_S_MOD 5 #define PRINT_S_CONV 6 /* Format flags. */ #define PRINT_F_MINUS (1 << 0) #define PRINT_F_PLUS (1 << 1) #define PRINT_F_SPACE (1 << 2) #define PRINT_F_NUM (1 << 3) #define PRINT_F_ZERO (1 << 4) #define PRINT_F_QUOTE (1 << 5) #define PRINT_F_UP (1 << 6) #define PRINT_F_UNSIGNED (1 << 7) #define PRINT_F_TYPE_G (1 << 8) #define PRINT_F_TYPE_E (1 << 9) /* Conversion flags. */ #define PRINT_C_CHAR 1 #define PRINT_C_SHORT 2 #define PRINT_C_LONG 3 #define PRINT_C_LLONG 4 #define PRINT_C_LDOUBLE 5 #define PRINT_C_SIZE 6 #define PRINT_C_PTRDIFF 7 #define PRINT_C_INTMAX 8 #ifndef MAX #define MAX(x, y) ((x >= y) ? x : y) #endif /* !defined(MAX) */ #ifndef CHARTOINT #define CHARTOINT(ch) (ch - '0') #endif /* !defined(CHARTOINT) */ #ifndef ISDIGIT #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') #endif /* !defined(ISDIGIT) */ #ifndef ISNAN #define ISNAN(x) (x != x) #endif /* !defined(ISNAN) */ #ifndef ISINF #define ISINF(x) (x != 0.0 && x + x == x) #endif /* !defined(ISINF) */ #ifdef OUTCHAR #undef OUTCHAR #endif /* defined(OUTCHAR) */ #define OUTCHAR(str, len, size, ch) \ do { \ if (len + 1 < size) \ str[len] = ch; \ (len)++; \ } while (/* CONSTCOND */ 0) #define rpl_vsnprintf vsnprintf #define rpl_snprintf snprintf #define rpl_vasprintf vasprintf #define rpl_asprintf asprintf static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); static void printsep(char *, size_t *, size_t); static int getnumsep(int); static int getexponent(LDOUBLE); static int convert(UINTMAX_T, char *, size_t, int, int); static UINTMAX_T cast(LDOUBLE); static UINTMAX_T myround(LDOUBLE); static LDOUBLE mypow10(int); #ifndef errno extern int errno; #endif int rpl_vsnprintf(char *str, size_t size, const char *format, va_list args) { LDOUBLE fvalue; INTMAX_T value; unsigned char cvalue; const char *strvalue; INTMAX_T *intmaxptr; PTRDIFF_T *ptrdiffptr; SSIZE_T *sizeptr; LLONG *llongptr; long int *longptr; int *intptr; short int *shortptr; signed char *charptr; size_t len = 0; int overflow = 0; int base = 0; int cflags = 0; int flags = 0; int width = 0; int precision = -1; int state = PRINT_S_DEFAULT; char ch = *format++; /* * C99 says: "If `n' is zero, nothing is written, and `s' may be a null * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer * even if a size larger than zero was specified. At least NetBSD's * snprintf(3) does the same, as well as other versions of this file. * (Though some of these versions will write to a non-NULL buffer even * if a size of zero was specified, which violates the standard.) */ if (str == NULL && size != 0) size = 0; while (ch != '\0') switch (state) { case PRINT_S_DEFAULT: if (ch == '%') state = PRINT_S_FLAGS; else OUTCHAR(str, len, size, ch); ch = *format++; break; case PRINT_S_FLAGS: switch (ch) { case '-': flags |= PRINT_F_MINUS; ch = *format++; break; case '+': flags |= PRINT_F_PLUS; ch = *format++; break; case ' ': flags |= PRINT_F_SPACE; ch = *format++; break; case '#': flags |= PRINT_F_NUM; ch = *format++; break; case '0': flags |= PRINT_F_ZERO; ch = *format++; break; case '\'': /* SUSv2 flag (not in C99). */ flags |= PRINT_F_QUOTE; ch = *format++; break; default: state = PRINT_S_WIDTH; break; } break; case PRINT_S_WIDTH: if (ISDIGIT(ch)) { ch = CHARTOINT(ch); if (width > (INT_MAX - ch) / 10) { overflow = 1; goto out; } width = 10 * width + ch; ch = *format++; } else if (ch == '*') { /* * C99 says: "A negative field width argument is * taken as a `-' flag followed by a positive * field width." (7.19.6.1, 5) */ if ((width = va_arg(args, int)) < 0) { flags |= PRINT_F_MINUS; width = -width; } ch = *format++; state = PRINT_S_DOT; } else state = PRINT_S_DOT; break; case PRINT_S_DOT: if (ch == '.') { state = PRINT_S_PRECISION; ch = *format++; } else state = PRINT_S_MOD; break; case PRINT_S_PRECISION: if (precision == -1) precision = 0; if (ISDIGIT(ch)) { ch = CHARTOINT(ch); if (precision > (INT_MAX - ch) / 10) { overflow = 1; goto out; } precision = 10 * precision + ch; ch = *format++; } else if (ch == '*') { /* * C99 says: "A negative precision argument is * taken as if the precision were omitted." * (7.19.6.1, 5) */ if ((precision = va_arg(args, int)) < 0) precision = -1; ch = *format++; state = PRINT_S_MOD; } else state = PRINT_S_MOD; break; case PRINT_S_MOD: switch (ch) { case 'h': ch = *format++; if (ch == 'h') { /* It's a char. */ ch = *format++; cflags = PRINT_C_CHAR; } else cflags = PRINT_C_SHORT; break; case 'l': ch = *format++; if (ch == 'l') { /* It's a long long. */ ch = *format++; cflags = PRINT_C_LLONG; } else cflags = PRINT_C_LONG; break; case 'L': cflags = PRINT_C_LDOUBLE; ch = *format++; break; case 'j': cflags = PRINT_C_INTMAX; ch = *format++; break; case 't': cflags = PRINT_C_PTRDIFF; ch = *format++; break; case 'z': cflags = PRINT_C_SIZE; ch = *format++; break; } state = PRINT_S_CONV; break; case PRINT_S_CONV: switch (ch) { case 'd': /* FALLTHROUGH */ case 'i': switch (cflags) { case PRINT_C_CHAR: value = (signed char)va_arg(args, int); break; case PRINT_C_SHORT: value = (short int)va_arg(args, int); break; case PRINT_C_LONG: value = va_arg(args, long int); break; case PRINT_C_LLONG: value = va_arg(args, LLONG); break; case PRINT_C_SIZE: value = va_arg(args, SSIZE_T); break; case PRINT_C_INTMAX: value = va_arg(args, INTMAX_T); break; case PRINT_C_PTRDIFF: value = va_arg(args, PTRDIFF_T); break; default: value = va_arg(args, int); break; } fmtint(str, &len, size, value, 10, width, precision, flags); break; case 'X': flags |= PRINT_F_UP; /* FALLTHROUGH */ case 'x': base = 16; /* FALLTHROUGH */ case 'o': if (base == 0) base = 8; /* FALLTHROUGH */ case 'u': if (base == 0) base = 10; flags |= PRINT_F_UNSIGNED; switch (cflags) { case PRINT_C_CHAR: value = (unsigned char)va_arg(args, unsigned int); break; case PRINT_C_SHORT: value = (unsigned short int)va_arg(args, unsigned int); break; case PRINT_C_LONG: value = va_arg(args, unsigned long int); break; case PRINT_C_LLONG: value = va_arg(args, ULLONG); break; case PRINT_C_SIZE: value = va_arg(args, size_t); break; case PRINT_C_INTMAX: value = va_arg(args, UINTMAX_T); break; case PRINT_C_PTRDIFF: value = va_arg(args, UPTRDIFF_T); break; default: value = va_arg(args, unsigned int); break; } fmtint(str, &len, size, value, base, width, precision, flags); break; case 'A': /* Not yet supported, we'll use "%F". */ /* FALLTHROUGH */ case 'F': flags |= PRINT_F_UP; case 'a': /* Not yet supported, we'll use "%f". */ /* FALLTHROUGH */ case 'f': if (cflags == PRINT_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else fvalue = va_arg(args, double); fmtflt(str, &len, size, fvalue, width, precision, flags, &overflow); if (overflow) goto out; break; case 'E': flags |= PRINT_F_UP; /* FALLTHROUGH */ case 'e': flags |= PRINT_F_TYPE_E; if (cflags == PRINT_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else fvalue = va_arg(args, double); fmtflt(str, &len, size, fvalue, width, precision, flags, &overflow); if (overflow) goto out; break; case 'G': flags |= PRINT_F_UP; /* FALLTHROUGH */ case 'g': flags |= PRINT_F_TYPE_G; if (cflags == PRINT_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else fvalue = va_arg(args, double); /* * If the precision is zero, it is treated as * one (cf. C99: 7.19.6.1, 8). */ if (precision == 0) precision = 1; fmtflt(str, &len, size, fvalue, width, precision, flags, &overflow); if (overflow) goto out; break; case 'c': cvalue = va_arg(args, int); OUTCHAR(str, len, size, cvalue); break; case 's': strvalue = va_arg(args, char *); fmtstr(str, &len, size, strvalue, width, precision, flags); break; case 'p': /* * C99 says: "The value of the pointer is * converted to a sequence of printing * characters, in an implementation-defined * manner." (C99: 7.19.6.1, 8) */ if ((strvalue = va_arg(args, void *)) == NULL) /* * We use the glibc format. BSD prints * "0x0", SysV "0". */ fmtstr(str, &len, size, "(nil)", width, -1, flags); else { /* * We use the BSD/glibc format. SysV * omits the "0x" prefix (which we emit * using the PRINT_F_NUM flag). */ flags |= PRINT_F_NUM; flags |= PRINT_F_UNSIGNED; fmtint(str, &len, size, (UINTPTR_T)strvalue, 16, width, precision, flags); } break; case 'n': switch (cflags) { case PRINT_C_CHAR: charptr = va_arg(args, signed char *); *charptr = len; break; case PRINT_C_SHORT: shortptr = va_arg(args, short int *); *shortptr = len; break; case PRINT_C_LONG: longptr = va_arg(args, long int *); *longptr = len; break; case PRINT_C_LLONG: llongptr = va_arg(args, LLONG *); *llongptr = len; break; case PRINT_C_SIZE: /* * C99 says that with the "z" length * modifier, "a following `n' conversion * specifier applies to a pointer to a * signed integer type corresponding to * size_t argument." (7.19.6.1, 7) */ sizeptr = va_arg(args, SSIZE_T *); *sizeptr = len; break; case PRINT_C_INTMAX: intmaxptr = va_arg(args, INTMAX_T *); *intmaxptr = len; break; case PRINT_C_PTRDIFF: ptrdiffptr = va_arg(args, PTRDIFF_T *); *ptrdiffptr = len; break; default: intptr = va_arg(args, int *); *intptr = len; break; } break; case '%': /* Print a "%" character verbatim. */ OUTCHAR(str, len, size, ch); break; default: /* Skip other characters. */ break; } ch = *format++; state = PRINT_S_DEFAULT; base = cflags = flags = width = 0; precision = -1; break; } out: if (len < size) str[len] = '\0'; else if (size > 0) str[size - 1] = '\0'; if (overflow || len >= INT_MAX) { errno = overflow ? EOVERFLOW : ERANGE; return -1; } return (int)len; } static void fmtstr(char *str, size_t *len, size_t size, const char *value, int width, int precision, int flags) { int padlen, strln; /* Amount to pad. */ int noprecision = (precision == -1); if (value == NULL) /* We're forgiving. */ value = "(null)"; /* If a precision was specified, don't read the string past it. */ for (strln = 0; value[strln] != '\0' && (noprecision || strln < precision); strln++) continue; if ((padlen = width - strln) < 0) padlen = 0; if (flags & PRINT_F_MINUS) /* Left justify. */ padlen = -padlen; while (padlen > 0) { /* Leading spaces. */ OUTCHAR(str, *len, size, ' '); padlen--; } while (*value != '\0' && (noprecision || precision-- > 0)) { OUTCHAR(str, *len, size, *value); value++; } while (padlen < 0) { /* Trailing spaces. */ OUTCHAR(str, *len, size, ' '); padlen++; } } static void fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, int precision, int flags) { UINTMAX_T uvalue; char iconvert[MAX_CONVERT_LENGTH]; char sign = 0; char hexprefix = 0; int spadlen = 0; /* Amount to space pad. */ int zpadlen = 0; /* Amount to zero pad. */ int pos; int separators = (flags & PRINT_F_QUOTE); int noprecision = (precision == -1); if (flags & PRINT_F_UNSIGNED) uvalue = value; else { uvalue = (value >= 0) ? value : -value; if (value < 0) sign = '-'; else if (flags & PRINT_F_PLUS) /* Do a sign. */ sign = '+'; else if (flags & PRINT_F_SPACE) sign = ' '; } pos = convert(uvalue, iconvert, sizeof(iconvert), base, flags & PRINT_F_UP); if (flags & PRINT_F_NUM && uvalue != 0) { /* * C99 says: "The result is converted to an `alternative form'. * For `o' conversion, it increases the precision, if and only * if necessary, to force the first digit of the result to be a * zero (if the value and precision are both 0, a single 0 is * printed). For `x' (or `X') conversion, a nonzero result has * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) */ switch (base) { case 8: if (precision <= pos) precision = pos + 1; break; case 16: hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; break; } } if (separators) /* Get the number of group separators we'll print. */ separators = getnumsep(pos); zpadlen = precision - pos - separators; spadlen = width /* Minimum field width. */ - separators /* Number of separators. */ - MAX(precision, pos) /* Number of integer digits. */ - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; /* * C99 says: "If the `0' and `-' flags both appear, the `0' flag is * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) */ if (flags & PRINT_F_MINUS) /* Left justify. */ spadlen = -spadlen; else if (flags & PRINT_F_ZERO && noprecision) { zpadlen += spadlen; spadlen = 0; } while (spadlen > 0) { /* Leading spaces. */ OUTCHAR(str, *len, size, ' '); spadlen--; } if (sign != 0) /* Sign. */ OUTCHAR(str, *len, size, sign); if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ OUTCHAR(str, *len, size, '0'); OUTCHAR(str, *len, size, hexprefix); } while (zpadlen > 0) { /* Leading zeros. */ OUTCHAR(str, *len, size, '0'); zpadlen--; } while (pos > 0) { /* The actual digits. */ pos--; OUTCHAR(str, *len, size, iconvert[pos]); if (separators > 0 && pos > 0 && pos % 3 == 0) printsep(str, len, size); } while (spadlen < 0) { /* Trailing spaces. */ OUTCHAR(str, *len, size, ' '); spadlen++; } } static void fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, int precision, int flags, int *overflow) { LDOUBLE ufvalue; UINTMAX_T intpart; UINTMAX_T fracpart; UINTMAX_T mask; const char *infnan = NULL; char iconvert[MAX_CONVERT_LENGTH]; char fconvert[MAX_CONVERT_LENGTH]; char econvert[4]; /* "e-12" (without nul-termination). */ char esign = 0; char sign = 0; int leadfraczeros = 0; int exponent = 0; int emitpoint = 0; int omitzeros = 0; int omitcount = 0; int padlen = 0; int epos = 0; int fpos = 0; int ipos = 0; int separators = (flags & PRINT_F_QUOTE); int estyle = (flags & PRINT_F_TYPE_E); #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT struct lconv *lc = localeconv(); #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ /* * AIX' man page says the default is 0, but C99 and at least Solaris' * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX * defaults to 6. */ if (precision == -1) precision = 6; if (fvalue < 0.0) sign = '-'; else if (flags & PRINT_F_PLUS) /* Do a sign. */ sign = '+'; else if (flags & PRINT_F_SPACE) sign = ' '; if (ISNAN(fvalue)) infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; else if (ISINF(fvalue)) infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; if (infnan != NULL) { if (sign != 0) iconvert[ipos++] = sign; while (*infnan != '\0') iconvert[ipos++] = *infnan++; fmtstr(str, len, size, iconvert, width, ipos, flags); return; } /* "%e" (or "%E") or "%g" (or "%G") conversion. */ if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { if (flags & PRINT_F_TYPE_G) { /* * For "%g" (and "%G") conversions, the precision * specifies the number of significant digits, which * includes the digits in the integer part. The * conversion will or will not be using "e-style" (like * "%e" or "%E" conversions) depending on the precision * and on the exponent. However, the exponent can be * affected by rounding the converted value, so we'll * leave this decision for later. Until then, we'll * assume that we're going to do an "e-style" conversion * (in order to get the exponent calculated). For * "e-style", the precision must be decremented by one. */ precision--; /* * For "%g" (and "%G") conversions, trailing zeros are * removed from the fractional portion of the result * unless the "#" flag was specified. */ if (!(flags & PRINT_F_NUM)) omitzeros = 1; } exponent = getexponent(fvalue); estyle = 1; } again: /* * Sorry, we only support 9, 19, or 38 digits (that is, the number of * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value * minus one) past the decimal point due to our conversion method. */ switch (sizeof(UINTMAX_T)) { case 16: if (precision > 38) precision = 38; break; case 8: if (precision > 19) precision = 19; break; default: if (precision > 9) precision = 9; break; } ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; if (estyle) /* We want exactly one integer digit. */ ufvalue /= mypow10(exponent); if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { *overflow = 1; return; } /* * Factor of ten with the number of digits needed for the fractional * part. For example, if the precision is 3, the mask will be 1000. */ mask = mypow10(precision); /* * We "cheat" by converting the fractional part to integer by * multiplying by a factor of ten. */ if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { /* * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 * (because precision = 3). Now, myround(1000 * 0.99962) will * return 1000. So, the integer part must be incremented by one * and the fractional part must be set to zero. */ intpart++; fracpart = 0; if (estyle && intpart == 10) { /* * The value was rounded up to ten, but we only want one * integer digit if using "e-style". So, the integer * part must be set to one and the exponent must be * incremented by one. */ intpart = 1; exponent++; } } /* * Now that we know the real exponent, we can check whether or not to * use "e-style" for "%g" (and "%G") conversions. If we don't need * "e-style", the precision must be adjusted and the integer and * fractional parts must be recalculated from the original value. * * C99 says: "Let P equal the precision if nonzero, 6 if the precision * is omitted, or 1 if the precision is zero. Then, if a conversion * with style `E' would have an exponent of X: * * - if P > X >= -4, the conversion is with style `f' (or `F') and * precision P - (X + 1). * * - otherwise, the conversion is with style `e' (or `E') and precision * P - 1." (7.19.6.1, 8) * * Note that we had decremented the precision by one. */ if (flags & PRINT_F_TYPE_G && estyle && precision + 1 > exponent && exponent >= -4) { precision -= exponent; estyle = 0; goto again; } if (estyle) { if (exponent < 0) { exponent = -exponent; esign = '-'; } else esign = '+'; /* * Convert the exponent. The sizeof(econvert) is 4. So, the * econvert buffer can hold e.g. "e+99" and "e-99". We don't * support an exponent which contains more than two digits. * Therefore, the following stores are safe. */ epos = convert(exponent, econvert, 2, 10, 0); /* * C99 says: "The exponent always contains at least two digits, * and only as many more digits as necessary to represent the * exponent." (7.19.6.1, 8) */ if (epos == 1) econvert[epos++] = '0'; econvert[epos++] = esign; econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; } /* Convert the integer part and the fractional part. */ ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); leadfraczeros = precision - fpos; if (omitzeros) { if (fpos > 0) /* Omit trailing fractional part zeros. */ while (omitcount < fpos && fconvert[omitcount] == '0') omitcount++; else { /* The fractional part is zero, omit it completely. */ omitcount = precision; leadfraczeros = 0; } precision -= omitcount; } /* * Print a decimal point if either the fractional part is non-zero * and/or the "#" flag was specified. */ if (precision > 0 || flags & PRINT_F_NUM) emitpoint = 1; if (separators) /* Get the number of group separators we'll print. */ separators = getnumsep(ipos); padlen = width /* Minimum field width. */ - ipos /* Number of integer digits. */ - epos /* Number of exponent characters. */ - precision /* Number of fractional digits. */ - separators /* Number of group separators. */ - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ if (padlen < 0) padlen = 0; /* * C99 says: "If the `0' and `-' flags both appear, the `0' flag is * ignored." (7.19.6.1, 6) */ if (flags & PRINT_F_MINUS) /* Left justifty. */ padlen = -padlen; else if (flags & PRINT_F_ZERO && padlen > 0) { if (sign != 0) { /* Sign. */ OUTCHAR(str, *len, size, sign); sign = 0; } while (padlen > 0) { /* Leading zeros. */ OUTCHAR(str, *len, size, '0'); padlen--; } } while (padlen > 0) { /* Leading spaces. */ OUTCHAR(str, *len, size, ' '); padlen--; } if (sign != 0) /* Sign. */ OUTCHAR(str, *len, size, sign); while (ipos > 0) { /* Integer part. */ ipos--; OUTCHAR(str, *len, size, iconvert[ipos]); if (separators > 0 && ipos > 0 && ipos % 3 == 0) printsep(str, len, size); } if (emitpoint) { /* Decimal point. */ #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT if (lc->decimal_point != NULL && *lc->decimal_point != '\0') OUTCHAR(str, *len, size, *lc->decimal_point); else /* We'll always print some decimal point character. */ #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ OUTCHAR(str, *len, size, '.'); } while (leadfraczeros > 0) { /* Leading fractional part zeros. */ OUTCHAR(str, *len, size, '0'); leadfraczeros--; } while (fpos > omitcount) { /* The remaining fractional part. */ fpos--; OUTCHAR(str, *len, size, fconvert[fpos]); } while (epos > 0) { /* Exponent. */ epos--; OUTCHAR(str, *len, size, econvert[epos]); } while (padlen < 0) { /* Trailing spaces. */ OUTCHAR(str, *len, size, ' '); padlen++; } } static void printsep(char *str, size_t *len, size_t size) { #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP struct lconv *lc = localeconv(); int i; if (lc->thousands_sep != NULL) for (i = 0; lc->thousands_sep[i] != '\0'; i++) OUTCHAR(str, *len, size, lc->thousands_sep[i]); else #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ OUTCHAR(str, *len, size, ','); } static int getnumsep(int digits) { int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP int strln; struct lconv *lc = localeconv(); /* We support an arbitrary separator length (including zero). */ if (lc->thousands_sep != NULL) { for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) continue; separators *= strln; } #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ return separators; } static int getexponent(LDOUBLE value) { LDOUBLE tmp = (value >= 0.0) ? value : -value; int exponent = 0; /* * We check for 99 > exponent > -99 in order to work around possible * endless loops which could happen (at least) in the second loop (at * least) if we're called with an infinite value. However, we checked * for infinity before calling this function using our ISINF() macro, so * this might be somewhat paranoid. */ while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) tmp *= 10; while (tmp >= 10.0 && ++exponent < 99) tmp /= 10; return exponent; } static int convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) { const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; size_t pos = 0; /* We return an unterminated buffer with the digits in reverse order. */ do { buf[pos++] = digits[value % base]; value /= base; } while (value != 0 && pos < size); return (int)pos; } static UINTMAX_T cast(LDOUBLE value) { UINTMAX_T result; /* * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), * it may be increased to the nearest higher representable value for the * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE * value although converting the latter to UINTMAX_T would overflow. */ if (value >= UINTMAX_MAX) return UINTMAX_MAX; result = value; /* * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates * the standard). Sigh. */ return (result <= value) ? result : result - 1; } static UINTMAX_T myround(LDOUBLE value) { UINTMAX_T intpart = cast(value); return ((value -= intpart) < 0.5) ? intpart : intpart + 1; } static LDOUBLE mypow10(int exponent) { LDOUBLE result = 1; while (exponent > 0) { result *= 10; exponent--; } while (exponent < 0) { result /= 10; exponent++; } return result; } #endif /* !HAVE_VSNPRINTF */ #if !HAVE_VASPRINTF #if NEED_MYMEMCPY void * mymemcpy(void *dst, void *src, size_t len) { const char *from = src; char *to = dst; /* No need for optimization, we use this only to replace va_copy(3). */ while (len-- > 0) *to++ = *from++; return dst; } #endif /* NEED_MYMEMCPY */ int rpl_vasprintf(char **ret, const char *format, va_list ap) { size_t size; int len; va_list aq; VA_COPY(aq, ap); len = vsnprintf(NULL, 0, format, aq); VA_END_COPY(aq); if (len < 0 || (*ret = malloc(size = len + 1)) == NULL) return -1; return vsnprintf(*ret, size, format, ap); } #endif /* !HAVE_VASPRINTF */ #if !HAVE_SNPRINTF #if HAVE_STDARG_H int rpl_snprintf(char *str, size_t size, const char *format, ...) #else int rpl_snprintf(va_alist) va_dcl #endif /* HAVE_STDARG_H */ { #if !HAVE_STDARG_H char *str; size_t size; char *format; #endif /* HAVE_STDARG_H */ va_list ap; int len; VA_START(ap, format); VA_SHIFT(ap, str, char *); VA_SHIFT(ap, size, size_t); VA_SHIFT(ap, format, const char *); len = vsnprintf(str, size, format, ap); va_end(ap); return len; } #endif /* !HAVE_SNPRINTF */ #if !HAVE_ASPRINTF #if HAVE_STDARG_H int rpl_asprintf(char **ret, const char *format, ...) #else int rpl_asprintf(va_alist) va_dcl #endif /* HAVE_STDARG_H */ { #if !HAVE_STDARG_H char **ret; char *format; #endif /* HAVE_STDARG_H */ va_list ap; int len; VA_START(ap, format); VA_SHIFT(ap, ret, char **); VA_SHIFT(ap, format, const char *); len = vasprintf(ret, format, ap); va_end(ap); return len; } #endif /* !HAVE_ASPRINTF */ #else /* Dummy declaration to avoid empty translation unit warnings. */ int main(void); #endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */ #if TEST_SNPRINTF int main(void) { const char *float_fmt[] = { /* "%E" and "%e" formats. */ #if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX "%.16e", "%22.16e", "%022.16e", "%-22.16e", "%#+'022.16e", #endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */ "foo|%#+0123.9E|bar", "%-123.9e", "%123.9e", "%+23.9e", "%+05.8e", "%-05.8e", "%05.8e", "%+5.8e", "%-5.8e", "% 5.8e", "%5.8e", "%+4.9e", #if !OS_LINUX /* glibc sometimes gets these wrong. */ "%+#010.0e", "%#10.1e", "%10.5e", "% 10.5e", "%5.0e", "%5.e", "%#5.0e", "%#5.e", "%3.2e", "%3.1e", "%-1.5e", "%1.5e", "%01.3e", "%1.e", "%.1e", "%#.0e", "%+.0e", "% .0e", "%.0e", "%#.e", "%+.e", "% .e", "%.e", "%4e", "%e", "%E", #endif /* !OS_LINUX */ /* "%F" and "%f" formats. */ #if !OS_BSD && !OS_IRIX "% '022f", "%+'022f", "%-'22f", "%'22f", #if HAVE_LONG_LONG_INT "%.16f", "%22.16f", "%022.16f", "%-22.16f", "%#+'022.16f", #endif /* HAVE_LONG_LONG_INT */ #endif /* !OS_BSD && !OS_IRIX */ "foo|%#+0123.9F|bar", "%-123.9f", "%123.9f", "%+23.9f", "%+#010.0f", "%#10.1f", "%10.5f", "% 10.5f", "%+05.8f", "%-05.8f", "%05.8f", "%+5.8f", "%-5.8f", "% 5.8f", "%5.8f", "%5.0f", "%5.f", "%#5.0f", "%#5.f", "%+4.9f", "%3.2f", "%3.1f", "%-1.5f", "%1.5f", "%01.3f", "%1.f", "%.1f", "%#.0f", "%+.0f", "% .0f", "%.0f", "%#.f", "%+.f", "% .f", "%.f", "%4f", "%f", "%F", /* "%G" and "%g" formats. */ #if !OS_BSD && !OS_IRIX && !OS_LINUX "% '022g", "%+'022g", "%-'22g", "%'22g", #if HAVE_LONG_LONG_INT "%.16g", "%22.16g", "%022.16g", "%-22.16g", "%#+'022.16g", #endif /* HAVE_LONG_LONG_INT */ #endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */ "foo|%#+0123.9G|bar", "%-123.9g", "%123.9g", "%+23.9g", "%+05.8g", "%-05.8g", "%05.8g", "%+5.8g", "%-5.8g", "% 5.8g", "%5.8g", "%+4.9g", #if !OS_LINUX /* glibc sometimes gets these wrong. */ "%+#010.0g", "%#10.1g", "%10.5g", "% 10.5g", "%5.0g", "%5.g", "%#5.0g", "%#5.g", "%3.2g", "%3.1g", "%-1.5g", "%1.5g", "%01.3g", "%1.g", "%.1g", "%#.0g", "%+.0g", "% .0g", "%.0g", "%#.g", "%+.g", "% .g", "%.g", "%4g", "%g", "%G", #endif /* !OS_LINUX */ NULL }; double float_val[] = { -4.136, -134.52, -5.04030201, -3410.01234, -999999.999999, -913450.29876, -913450.2, -91345.2, -9134.2, -913.2, -91.2, -9.2, -9.9, 4.136, 134.52, 5.04030201, 3410.01234, 999999.999999, 913450.29876, 913450.2, 91345.2, 9134.2, 913.2, 91.2, 9.2, 9.9, 9.96, 9.996, 9.9996, 9.99996, 9.999996, 9.9999996, 9.99999996, 0.99999996, 0.99999999, 0.09999999, 0.00999999, 0.00099999, 0.00009999, 0.00000999, 0.00000099, 0.00000009, 0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1.0, 1.5, -1.5, -1.0, -0.1, #if !OS_BSD /* BSD sometimes gets these wrong. */ #ifdef INFINITY INFINITY, -INFINITY, #endif /* defined(INFINITY) */ #ifdef NAN NAN, #endif /* defined(NAN) */ #endif /* !OS_BSD */ 0 }; const char *long_fmt[] = { "foo|%0123ld|bar", #if !OS_IRIX "% '0123ld", "%+'0123ld", "%-'123ld", "%'123ld", #endif /* !OS_IRiX */ "%123.9ld", "% 123.9ld", "%+123.9ld", "%-123.9ld", "%0123ld", "% 0123ld", "%+0123ld", "%-0123ld", "%10.5ld", "% 10.5ld", "%+10.5ld", "%-10.5ld", "%010ld", "% 010ld", "%+010ld", "%-010ld", "%4.2ld", "% 4.2ld", "%+4.2ld", "%-4.2ld", "%04ld", "% 04ld", "%+04ld", "%-04ld", "%5.5ld", "%+22.33ld", "%01.3ld", "%1.5ld", "%-1.5ld", "%44ld", "%4ld", "%4.0ld", "%4.ld", "%.44ld", "%.4ld", "%.0ld", "%.ld", "%ld", NULL }; long int long_val[] = { #ifdef LONG_MAX LONG_MAX, #endif /* LONG_MAX */ #ifdef LONG_MIN LONG_MIN, #endif /* LONG_MIN */ -91340, 91340, 341, 134, 0203, -1, 1, 0 }; const char *ulong_fmt[] = { /* "%u" formats. */ "foo|%0123lu|bar", #if !OS_IRIX "% '0123lu", "%+'0123lu", "%-'123lu", "%'123lu", #endif /* !OS_IRiX */ "%123.9lu", "% 123.9lu", "%+123.9lu", "%-123.9lu", "%0123lu", "% 0123lu", "%+0123lu", "%-0123lu", "%5.5lu", "%+22.33lu", "%01.3lu", "%1.5lu", "%-1.5lu", "%44lu", "%lu", /* "%o" formats. */ "foo|%#0123lo|bar", "%#123.9lo", "%# 123.9lo", "%#+123.9lo", "%#-123.9lo", "%#0123lo", "%# 0123lo", "%#+0123lo", "%#-0123lo", "%#5.5lo", "%#+22.33lo", "%#01.3lo", "%#1.5lo", "%#-1.5lo", "%#44lo", "%#lo", "%123.9lo", "% 123.9lo", "%+123.9lo", "%-123.9lo", "%0123lo", "% 0123lo", "%+0123lo", "%-0123lo", "%5.5lo", "%+22.33lo", "%01.3lo", "%1.5lo", "%-1.5lo", "%44lo", "%lo", /* "%X" and "%x" formats. */ "foo|%#0123lX|bar", "%#123.9lx", "%# 123.9lx", "%#+123.9lx", "%#-123.9lx", "%#0123lx", "%# 0123lx", "%#+0123lx", "%#-0123lx", "%#5.5lx", "%#+22.33lx", "%#01.3lx", "%#1.5lx", "%#-1.5lx", "%#44lx", "%#lx", "%#lX", "%123.9lx", "% 123.9lx", "%+123.9lx", "%-123.9lx", "%0123lx", "% 0123lx", "%+0123lx", "%-0123lx", "%5.5lx", "%+22.33lx", "%01.3lx", "%1.5lx", "%-1.5lx", "%44lx", "%lx", "%lX", NULL }; unsigned long int ulong_val[] = { #ifdef ULONG_MAX ULONG_MAX, #endif /* ULONG_MAX */ 91340, 341, 134, 0203, 1, 0 }; const char *llong_fmt[] = { "foo|%0123lld|bar", "%123.9lld", "% 123.9lld", "%+123.9lld", "%-123.9lld", "%0123lld", "% 0123lld", "%+0123lld", "%-0123lld", "%5.5lld", "%+22.33lld", "%01.3lld", "%1.5lld", "%-1.5lld", "%44lld", "%lld", NULL }; LLONG llong_val[] = { #ifdef LLONG_MAX LLONG_MAX, #endif /* LLONG_MAX */ #ifdef LLONG_MIN LLONG_MIN, #endif /* LLONG_MIN */ -91340, 91340, 341, 134, 0203, -1, 1, 0 }; const char *string_fmt[] = { "foo|%10.10s|bar", "%-10.10s", "%10.10s", "%10.5s", "%5.10s", "%10.1s", "%1.10s", "%10.0s", "%0.10s", "%-42.5s", "%2.s", "%.10s", "%.1s", "%.0s", "%.s", "%4s", "%s", NULL }; const char *string_val[] = { "Hello", "Hello, world!", "Sound check: One, two, three.", "This string is a little longer than the other strings.", "1", "", NULL }; #if !OS_SYSV /* SysV uses a different format than we do. */ const char *pointer_fmt[] = { "foo|%p|bar", "%42p", "%p", NULL }; const char *pointer_val[] = { *pointer_fmt, *string_fmt, *string_val, NULL }; #endif /* !OS_SYSV */ char buf1[1024], buf2[1024]; double value, digits = 9.123456789012345678901234567890123456789; int i, j, r1, r2, failed = 0, num = 0; /* * Use -DTEST_NILS in order to also test the conversion of nil values. Might * segfault on systems which don't support converting a NULL pointer with "%s" * and lets some test cases fail against BSD and glibc due to bugs in their * implementations. */ #ifndef TEST_NILS #define TEST_NILS 0 #elif TEST_NILS #undef TEST_NILS #define TEST_NILS 1 #endif /* !defined(TEST_NILS) */ #ifdef TEST #undef TEST #endif /* defined(TEST) */ #define TEST(fmt, val) \ do { \ for (i = 0; fmt[i] != NULL; i++) \ for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \ r1 = sprintf(buf1, fmt[i], val[j]); \ r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \ if (strcmp(buf1, buf2) != 0 || r1 != r2) { \ (void)printf("Results don't match, " \ "format string: %s\n" \ "\t sprintf(3): [%s] (%d)\n" \ "\tsnprintf(3): [%s] (%d)\n", \ fmt[i], buf1, r1, buf2, r2); \ failed++; \ } \ num++; \ } \ } while (/* CONSTCOND */ 0) #if HAVE_LOCALE_H (void)setlocale(LC_ALL, ""); #endif /* HAVE_LOCALE_H */ (void)puts("Testing our snprintf(3) against your system's sprintf(3)."); TEST(float_fmt, float_val); TEST(long_fmt, long_val); TEST(ulong_fmt, ulong_val); TEST(llong_fmt, llong_val); TEST(string_fmt, string_val); #if !OS_SYSV /* SysV uses a different format than we do. */ TEST(pointer_fmt, pointer_val); #endif /* !OS_SYSV */ (void)printf("Result: %d out of %d tests failed.\n", failed, num); (void)fputs("Checking how many digits we support: ", stdout); for (i = 0; i < 100; i++) { value = pow(10, i) * digits; (void)sprintf(buf1, "%.1f", value); (void)snprintf(buf2, sizeof(buf2), "%.1f", value); if (strcmp(buf1, buf2) != 0) { (void)printf("apparently %d.\n", i); break; } } return (failed == 0) ? 0 : 1; } #endif /* TEST_SNPRINTF */ /* vim: set joinspaces textwidth=80: */ instead-3.5.2+dfsg/src/instead/snprintf.h000066400000000000000000000007211467622671600203420ustar00rootroot00000000000000#ifndef _PORTABLE_SNPRINTF_H_ #define _PORTABLE_SNPRINTF_H_ #define PORTABLE_SNPRINTF_VERSION_MAJOR 1 #define PORTABLE_SNPRINTF_VERSION_MINOR 3 #ifdef HAVE_SNPRINTF #include #else extern int snprintf(char *, size_t, const char *, /*args*/ ...); #endif #if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF) extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); #define snprintf portable_snprintf #endif #endif instead-3.5.2+dfsg/src/instead/system.h000066400000000000000000000010701467622671600200210ustar00rootroot00000000000000#ifndef __INSTEAD_EXTERNAL_H_ #define __INSTEAD_EXTERNAL_H_ #if defined(WINRT) #define errno 0 #define putenv(a) ; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(PLAN9) #include #include #endif #ifndef PATH_MAX #define PATH_MAX 4096 #endif #endif instead-3.5.2+dfsg/src/instead/tinymt32.c000066400000000000000000000076101467622671600201670ustar00rootroot00000000000000/** * @file tinymt32.c * * @brief Tiny Mersenne Twister only 127 bit internal state * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (The University of Tokyo) * * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, * Hiroshima University and The University of Tokyo. * All rights reserved. * * The 3-clause BSD License is applied to this software, see * http://www.math.sci.hiroshima-u.ac.jp/~%20m-mat/MT/TINYMT/LICENSE.txt * * Changes: * a) some code removed * b) SDL_types.h Uint32 instead of uint32_t * c) url to LICENSE */ #include "tinymt32.h" #define MIN_LOOP 8 #define PRE_LOOP 8 /** * This function represents a function used in the initialization * by init_by_array * @param x 32-bit integer * @return 32-bit integer */ static Uint32 ini_func1(Uint32 x) { return (x ^ (x >> 27)) * UINT32_C(1664525); } /** * This function represents a function used in the initialization * by init_by_array * @param x 32-bit integer * @return 32-bit integer */ static Uint32 ini_func2(Uint32 x) { return (x ^ (x >> 27)) * UINT32_C(1566083941); } /** * This function certificate the period of 2^127-1. * @param random tinymt state vector. */ static void period_certification(tinymt32_t * random) { if ((random->status[0] & TINYMT32_MASK) == 0 && random->status[1] == 0 && random->status[2] == 0 && random->status[3] == 0) { random->status[0] = 'T'; random->status[1] = 'I'; random->status[2] = 'N'; random->status[3] = 'Y'; } } /** * This function initializes the internal state array with a 32-bit * unsigned integer seed. * @param random tinymt state vector. * @param seed a 32-bit unsigned integer used as a seed. */ void tinymt32_init(tinymt32_t * random, Uint32 seed) { int i; random->status[0] = seed; random->status[1] = random->mat1; random->status[2] = random->mat2; random->status[3] = random->tmat; for (i = 1; i < MIN_LOOP; i++) { random->status[i & 3] ^= i + UINT32_C(1812433253) * (random->status[(i - 1) & 3] ^ (random->status[(i - 1) & 3] >> 30)); } period_certification(random); for (i = 0; i < PRE_LOOP; i++) { tinymt32_next_state(random); } } /** * This function initializes the internal state array, * with an array of 32-bit unsigned integers used as seeds * @param random tinymt state vector. * @param init_key the array of 32-bit integers, used as a seed. * @param key_length the length of init_key. */ void tinymt32_init_by_array(tinymt32_t * random, Uint32 init_key[], int key_length) { const int lag = 1; const int mid = 1; const int size = 4; int i, j; int count; Uint32 r; Uint32 * st = &random->status[0]; st[0] = 0; st[1] = random->mat1; st[2] = random->mat2; st[3] = random->tmat; if (key_length + 1 > MIN_LOOP) { count = key_length + 1; } else { count = MIN_LOOP; } r = ini_func1(st[0] ^ st[mid % size] ^ st[(size - 1) % size]); st[mid % size] += r; r += key_length; st[(mid + lag) % size] += r; st[0] = r; count--; for (i = 1, j = 0; (j < count) && (j < key_length); j++) { r = ini_func1(st[i % size] ^ st[(i + mid) % size] ^ st[(i + size - 1) % size]); st[(i + mid) % size] += r; r += init_key[j] + i; st[(i + mid + lag) % size] += r; st[i % size] = r; i = (i + 1) % size; } for (; j < count; j++) { r = ini_func1(st[i % size] ^ st[(i + mid) % size] ^ st[(i + size - 1) % size]); st[(i + mid) % size] += r; r += i; st[(i + mid + lag) % size] += r; st[i % size] = r; i = (i + 1) % size; } for (j = 0; j < size; j++) { r = ini_func2(st[i % size] + st[(i + mid) % size] + st[(i + size - 1) % size]); st[(i + mid) % size] ^= r; r -= i; st[(i + mid + lag) % size] ^= r; st[i % size] = r; i = (i + 1) % size; } period_certification(random); for (i = 0; i < PRE_LOOP; i++) { tinymt32_next_state(random); } } instead-3.5.2+dfsg/src/instead/tinymt32.h000066400000000000000000000074261467622671600202010ustar00rootroot00000000000000#ifndef TINYMT32_H #define TINYMT32_H #ifdef _USE_SDL #include #else #include typedef uint32_t Uint32; #endif /** * @file tinymt32.h * * @brief Tiny Mersenne Twister only 127 bit internal state * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (University of Tokyo) * * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, * Hiroshima University and The University of Tokyo. * All rights reserved. * * The 3-clause BSD License is applied to this software, see * http://www.math.sci.hiroshima-u.ac.jp/~%20m-mat/MT/TINYMT/LICENSE.txt * * Changes: * a) some code removed * b) SDL_types.h Uint32 instead of uint32_t * c) url to LICENSE */ #if defined(PLAN9) #define __inline #endif #if defined(PLAN9) #define UINT32_C(c) (c ## U) #else #include #include #endif #define TINYMT32_MEXP 127 #define TINYMT32_SH0 1 #define TINYMT32_SH1 10 #define TINYMT32_SH8 8 #define TINYMT32_MASK UINT32_C(0x7fffffff) #define TINYMT32_MUL (1.0f / 4294967296.0f) /** * tinymt32 internal state vector and parameters */ struct TINYMT32_T { Uint32 status[4]; Uint32 mat1; Uint32 mat2; Uint32 tmat; }; typedef struct TINYMT32_T tinymt32_t; void tinymt32_init(tinymt32_t * random, Uint32 seed); void tinymt32_init_by_array(tinymt32_t * random, Uint32 init_key[], int key_length); /** * This function changes internal state of tinymt32. * Users should not call this function directly. * @param random tinymt internal status */ __inline static void tinymt32_next_state(tinymt32_t * random) { Uint32 x; Uint32 y; y = random->status[3]; x = (random->status[0] & TINYMT32_MASK) ^ random->status[1] ^ random->status[2]; x ^= (x << TINYMT32_SH0); y ^= (y >> TINYMT32_SH0) ^ x; random->status[0] = random->status[1]; random->status[1] = random->status[2]; random->status[2] = x ^ (y << TINYMT32_SH1); random->status[3] = y; random->status[1] ^= -((int32_t)(y & 1)) & random->mat1; random->status[2] ^= -((int32_t)(y & 1)) & random->mat2; } /** * This function outputs 32-bit unsigned integer from internal state. * Users should not call this function directly. * @param random tinymt internal status * @return 32-bit unsigned pseudorandom number */ __inline static Uint32 tinymt32_temper(tinymt32_t * random) { Uint32 t0, t1; t0 = random->status[3]; t1 = random->status[0] + (random->status[2] >> TINYMT32_SH8); t0 ^= t1; t0 ^= -((int32_t)(t1 & 1)) & random->tmat; return t0; } /** * This function outputs 32-bit unsigned integer from internal state. * @param random tinymt internal status * @return 32-bit unsigned integer r (0 <= r < 2^32) */ __inline static Uint32 tinymt32_generate_uint32(tinymt32_t * random) { tinymt32_next_state(random); return tinymt32_temper(random); } /** * This function outputs floating point number from internal state. * This function is implemented using multiplying by 1 / 2^32. * floating point multiplication is faster than using union trick in * my Intel CPU. * @param random tinymt internal status * @return floating point number r (0.0 <= r < 1.0) */ __inline static float tinymt32_generate_float(tinymt32_t * random) { tinymt32_next_state(random); return tinymt32_temper(random) * TINYMT32_MUL; } /** * This function outputs double precision floating point number from * internal state. The returned value has 32-bit precision. * In other words, this function makes one double precision floating point * number from one 32-bit unsigned integer. * @param random tinymt internal status * @return floating point number r (0.0 < r <= 1.0) */ __inline static double tinymt32_generate_32double(tinymt32_t * random) { tinymt32_next_state(random); return tinymt32_temper(random) * (1.0 / 4294967296.0); } #endif instead-3.5.2+dfsg/src/instead/util.c000066400000000000000000000301311467622671600174450ustar00rootroot00000000000000/* * Copyright 2009-2022 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "system.h" #include "util.h" #include "tinymt32.h" int get_utf8(const char *sp, unsigned long *sym_out) { int i = 0, l = 0; unsigned long sym = 0; const unsigned char *p = (const unsigned char*)sp; if (sym_out) *sym_out = *p; if (!*p) return 0; if (!(*p & 0xc0)) return 1; if ((*p & 0xe0) == 0xc0) { l = 1; sym = (*p & 0x1f); } else if ((*p & 0xf0) == 0xe0) { l = 2; sym = (*p & 0xf); } else if ((*p & 0xf8) == 0xf0) { l = 3; sym = (*p & 7); } else if ((*p & 0xfc) == 0xf8) { l = 4; sym = (*p & 3); } else if ((*p & 0xfe) == 0xfc) { l = 5; sym = (*p & 1); } else { return 1; } p ++; for (i = 0; i < l; i ++) { sym <<= 6; if ((*p & 0xc0) != 0x80) { return 1; } sym |= (*p++ & 0x3f); } if (sym_out) *sym_out = sym; return l + 1; } int is_cjk(unsigned long sym) { if (sym >=0x2E80 && sym <= 0x2EFF) return 1; if (sym >=0x2F00 && sym <= 0x2FDF) return 1; if (sym >= 0x2FF0 && sym <= 0x2FFF) return 1; if (sym >= 0x3000 && sym <= 0x303F) return 1; if (sym >= 0x3040 && sym <= 0x309F) return 1; if (sym >= 0x30A0 && sym <=0x30FF) return 1; if (sym >= 0x3100 && sym <=0x312F) return 1; if (sym >= 0x3130 && sym <= 0x318F) return 1; if (sym >= 0x3190 && sym <= 0x319F) return 1; if (sym >= 0x31A0 && sym <= 0x31BF) return 1; if (sym >= 0x31F0 && sym <= 0x31FF) return 1; if (sym >= 0x3200 && sym <= 0x32FF) return 1; if (sym >= 0x3300 && sym <= 0x33FF) return 1; if (sym >= 0x3400 && sym <= 0x4DBF) return 1; if (sym >= 0x4DC0 && sym <= 0x4DFF) return 1; if (sym >= 0x4E00 && sym <= 0x9FFF) return 1; if (sym >= 0xA000 && sym <= 0xA48F) return 1; if (sym >= 0xA490 && sym <= 0xA4CF) return 1; if (sym >= 0xAC00 && sym <= 0xD7AF) return 1; if (sym >= 0xF900 && sym <= 0xFAFF) return 1; if (sym >= 0xFE30 && sym <= 0xFE4F) return 1; if (sym >= 0x1D300 && sym <= 0x1D35F) return 1; if (sym >= 0x20000 && sym <= 0x2A6DF) return 1; if (sym >= 0x2F800 && sym <= 0x2FA1F) return 1; return 0; } int is_space(int c) { return (c == ' ' || c == '\t'); } int is_empty(const char *str) { if (!str || !*str) return 1; while (*str && !is_space(*str++)) return 0; return 1; } char *strip(char *s) { char *e; while (is_space(*s)) s ++; if (!*s) return s; e = s + strlen(s) - 1; while (e != s && is_space(*e)) { *e = 0; e --; } return s; } int strlowcmp(const char *s, const char *d) { int rc; char *ss = NULL; char *dd = NULL; ss = strdup(s); dd = strdup(d); if (!ss || !dd) { rc = strcmp(s, d); goto err; } tolow(ss); tolow(dd); rc = strcmp(ss, dd); err: if (ss) free(ss); if (dd) free(dd); return rc; } char *getpath(const char *d, const char *n) { char *p = getfilepath(d, n); strcat(p, "/"); return p; } void tolow(char *p) { while (*p) { if (*p >= 'A' && *p <= 'Z') *p |= 0x20; p ++; } } char *getfilepath(const char *d, const char *n) { int i = ((d)?strlen(d):0) + ((n)?strlen(n):0) + 3; char *p = malloc(i); if (p) { p[0] = 0; if (d && d[0]) { /* non empty string */ strcpy(p, d); if (p[strlen(d) - 1] != '/') strcat(p, "/"); } if (n) strcat(p, n); unix_path(p); } return p; } void unix_path(char *path) { char *p = path; if (!path) return; while (*p) { /* bad bad Windows!!! */ if (*p == '\\') *p = '/'; p ++; } return; } #ifdef _HAVE_ICONV #define CHAR_MAX_LEN 4 char *decode(iconv_t hiconv, const char *s) { size_t s_size, chs_size, outsz, insz; char *inbuf, *outbuf, *chs_buf; if (!s || hiconv == (iconv_t)(-1)) return NULL; s_size = strlen(s) + 1; chs_size = s_size * CHAR_MAX_LEN; if ((chs_buf = malloc(chs_size + CHAR_MAX_LEN))==NULL) goto exitf; outsz = chs_size; outbuf = chs_buf; insz = s_size; inbuf = (char*)s; while (insz) { if (iconv(hiconv, &inbuf, &insz, &outbuf, &outsz) == (size_t)(-1)) goto exitf; } *outbuf++ = 0; return chs_buf; exitf: if(chs_buf) free(chs_buf); return NULL; } #endif static tinymt32_t trandom; void mt_random_init(void) { tinymt32_init(&trandom, time(NULL)); } void mt_random_seed(unsigned long seed) { tinymt32_init(&trandom, seed); } unsigned long mt_random(void) { return tinymt32_generate_uint32(&trandom); } double mt_random_double(void) { return tinymt32_generate_32double(&trandom); } #if defined(WINRT) #include "system.h" #include #include #include #include #include #include static char curdir[PATH_MAX]; int setdir(const char *path) { strncpy(curdir, path, sizeof(curdir) - 1); return 0; } char *getdir(char *path, size_t size) { strncpy(path, curdir, size - 1); return path; } char *dirpath(const char *path) { static char fp[PATH_MAX * 4]; if (path[0] == '/' || path[1] == ':') return (char*)path; snprintf(fp, sizeof(fp), "%s/%s", curdir, path); fp[sizeof(fp) - 1] = 0; unix_path(fp); return fp; } int is_absolute_path(const char *path) { if (!path || !*path) return 0; return (*path == '/' || *path == '\\' || path[1] == ':'); } char *dirname(char *path) { char *p; if (path == NULL || *path == '\0') return "."; p = path + strlen(path) - 1; while (*p == '/') { if (p == path) return path; *p-- = '\0'; } while (p >= path && *p != '/') p--; return p < path ? "." : p == path ? "/" : (*p = '\0', path); } char* basename(char* path) { char *ptr = path; int l = 0; while (ptr[(l = strcspn(ptr, "\\//"))]) ptr += l + 1; return ptr; } #elif defined(_WIN32) #include #include #include #include #include #ifndef _MSC_VER #include #endif #include #include #include int setdir(const char *path) { return chdir(path); } char *getdir(char *path, size_t size) { return getcwd(path, size); } char *dirpath(const char *path) { return (char*)path; } int is_absolute_path(const char *path) { if (!path || !path[0]) return 0; if (path[0] == '/' || path[0] == '\\') return 1; if (!path[1]) return 0; return (path[1] == ':'); } #ifdef _MSC_VER char *dirname(char *path) { char *p; if (path == NULL || *path == '\0') return "."; p = path + strlen(path) - 1; while (*p == '/') { if (p == path) return path; *p-- = '\0'; } while (p >= path && *p != '/') p--; return p < path ? "." : p == path ? "/" : (*p = '\0', path); } char* basename(char* path) { char *ptr = path; int l = 0; while (ptr[(l = strcspn(ptr, "\\//"))]) ptr += l + 1; return ptr; } #endif #elif defined(__APPLE__) #include #include #include #include #include #include #include #include #include #include #include "system.h" int setdir(const char *path) { return chdir(path); } char *getdir(char *path, size_t size) { return getcwd(path, size); } char *dirpath(const char *path) { return (char*)path; } int is_absolute_path(const char *path) { if (!path || !*path) return 0; return (*path == '/'); } #else #include #include #include #include #include #include #include #include #include #include #include #ifndef ANDROID int setdir(const char *path) { return chdir(path); } char *getdir(char *path, size_t size) { return getcwd(path, size); } char *dirpath(const char *path) { return (char*)path; } #else static char curdir[PATH_MAX]; int setdir(const char *path) { strncpy(curdir, path, sizeof(curdir) - 1); return chdir(path); } char *getdir(char *path, size_t size) { strncpy(path, curdir, size - 1); return path; } char *dirpath(const char *path) { static char fp[PATH_MAX * 4]; if (path[0] == '/') return (char*)path; snprintf(fp, sizeof(fp), "%s/%s", curdir, path); fp[sizeof(fp) - 1] = 0; unix_path(fp); return fp; } #endif int is_absolute_path(const char *path) { if (!path || !*path) return 0; return (*path == '/'); } #endif /* * * This code is derived from software contributed to Berkeley by * Jan-Simon Pendry. * */ /* * char *realpath(const char *path, char *resolved); * * Find the real name of path, by removing all ".", ".." and symlink * components. Returns (resolved) on success, or (NULL) on failure, * in which case the path which caused trouble is left in (resolved). */ char *getrealpath(const char *path, char *resolved) { const char *q; char *p, *fres; size_t len; #if defined(unix) struct stat sb; ssize_t n; int idx = 0, nlnk = 0; char wbuf[2][PATH_MAX]; #endif /* POSIX sez we must test for this */ if (path == NULL) { return NULL; } if (resolved == NULL) { fres = resolved = malloc(PATH_MAX); if (resolved == NULL) return NULL; } else fres = NULL; /* * Build real path one by one with paying an attention to ., * .. and symbolic link. */ /* * `p' is where we'll put a new component with prepending * a delimiter. */ p = resolved; if (*path == '\0') { *p = '\0'; goto out; } /* If relative path, start from current working directory. */ if (!is_absolute_path(path)) { /* check for resolved pointer to appease coverity */ if (getdir(resolved, PATH_MAX) == NULL) { p[0] = '.'; p[1] = '\0'; goto out; } unix_path(resolved); len = strlen(resolved); if (len > 1) { p += len; while (p != resolved && *(p-1) == '/') *(--p) = 0; } } loop: /* Skip any slash. */ while (*path == '/') path++; if (*path == '\0') { if (p == resolved) *p++ = '/'; *p = '\0'; return resolved; } /* Find the end of this component. */ q = path; do q++; while (*q != '/' && *q != '\0'); /* Test . or .. */ if (path[0] == '.') { if (q - path == 1) { path = q; goto loop; } if (path[1] == '.' && q - path == 2) { /* Trim the last component. */ if (p != resolved) while (*--p != '/' && p != resolved) continue; path = q; goto loop; } } /* Append this component. */ if (p - resolved + 1 + q - path + 1 > PATH_MAX) { if (p == resolved) *p++ = '/'; *p = '\0'; goto out; } if (p == resolved && is_absolute_path(path) && path[0] != '/') { /* win? */ memcpy(&p[0], path, q - path); p[q - path] = '\0'; p += q - path; path = q; goto loop; } else { p[0] = '/'; memcpy(&p[1], path, /* LINTED We know q > path. */ q - path); p[1 + q - path] = '\0'; } #if defined(unix) /* * If this component is a symlink, toss it and prepend link * target to unresolved path. */ if (lstat(resolved, &sb) != -1 && S_ISLNK(sb.st_mode)) { if (nlnk++ >= 16) { goto out; } n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1); if (n < 0) goto out; if (n == 0) { goto out; } /* Append unresolved path to link target and switch to it. */ if (n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) { goto out; } memcpy(&wbuf[idx][n], q, len + 1); path = wbuf[idx]; idx ^= 1; /* If absolute symlink, start from root. */ if (*path == '/') p = resolved; goto loop; } #endif /* Advance both resolved and unresolved path. */ p += 1 + q - path; path = q; goto loop; out: free(fres); return NULL; } instead-3.5.2+dfsg/src/instead/util.h000066400000000000000000000047661467622671600174710ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh * * 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. * */ #ifndef __INSTEAD_UTIL_H_INCLUDED #define __INSTEAD_UTIL_H_INCLUDED extern char *strip(char *s); extern int is_cjk(unsigned long sym); extern int get_utf8(const char *p, unsigned long *sym_out); extern int is_space(int c); extern int is_empty(const char *str); extern char *getfilepath(const char *d, const char *n); extern int strlowcmp(const char *s, const char *d); extern void unix_path(char *path); extern int setdir(const char *path); extern char *getpath(const char *d, const char *n); extern char *getdir(char *path, size_t size); extern char *dirpath(const char *path); extern void tolow(char *p); extern int is_absolute_path(const char *p); extern void mt_random_init(void); extern void mt_random_seed(unsigned long seed); extern unsigned long mt_random(void); extern double mt_random_double(void); #define FREE(v) do { if ((v)) free((v)); v = NULL; } while(0) #ifdef _USE_SDL #include #include #ifdef _USE_SDL_ICONV #include #define iconv SDL_iconv #define iconv_t SDL_iconv_t #define iconv_open SDL_iconv_open #define iconv_close SDL_iconv_close #else #ifdef _HAVE_ICONV #include #endif #endif #else #ifdef _HAVE_ICONV #include #endif #endif #ifdef _HAVE_ICONV extern char *decode(iconv_t hiconv, const char *s); #endif extern char *getrealpath(const char *path, char *resolved); #endif instead-3.5.2+dfsg/src/instead_bits.c000066400000000000000000000110151467622671600175110ustar00rootroot00000000000000/* * Copyright 2009-2017 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "instead/instead.h" static int luaB_bit_and(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a & b; lua_pushinteger(L, r); return 1; } static int luaB_bit_or(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a | b; lua_pushinteger(L, r); return 1; } static int luaB_bit_xor(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a ^ b; lua_pushinteger(L, r); return 1; } static int luaB_bit_shl(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a << b; lua_pushinteger(L, r); return 1; } static int luaB_bit_shr(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a >> b; lua_pushinteger(L, r); return 1; } static int luaB_bit_not(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int r = ~a; lua_pushinteger(L, r); return 1; } static int luaB_bit_div(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 1); unsigned int r; if (b) { r = a / b; lua_pushinteger(L, r); return 1; } return 0; } static int luaB_bit_idiv(lua_State *L) { int a = luaL_optinteger(L, 1, 0); int b = luaL_optinteger(L, 2, 1); int r; if (b) { r = a / b; lua_pushinteger(L, r); return 1; } return 0; } static int luaB_bit_mod(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 1); unsigned int r; if (b) { r = a % b; lua_pushinteger(L, r); return 1; } return 0; } static int luaB_bit_mul(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a * b; lua_pushinteger(L, r); return 1; } static int luaB_bit_imul(lua_State *L) { int a = luaL_optinteger(L, 1, 0); int b = luaL_optinteger(L, 2, 0); int r = a * b; lua_pushinteger(L, r); return 1; } static int luaB_bit_sub(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a - b; lua_pushinteger(L, r); return 1; } static int luaB_bit_add(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); unsigned int b = luaL_optinteger(L, 2, 0); unsigned int r = a + b; lua_pushinteger(L, r); return 1; } static int luaB_bit_unsigned(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); lua_pushinteger(L, a); return 1; } static int luaB_bit_signed(lua_State *L) { unsigned int a = luaL_optinteger(L, 1, 0); lua_pushinteger(L, (int)a); return 1; } const luaL_Reg bits_funcs[] = { {"bit_or", luaB_bit_or}, {"bit_and", luaB_bit_and}, {"bit_xor", luaB_bit_xor}, {"bit_shl", luaB_bit_shl}, {"bit_shr", luaB_bit_shr}, {"bit_not", luaB_bit_not}, {"bit_div", luaB_bit_div}, {"bit_idiv", luaB_bit_idiv}, {"bit_mod", luaB_bit_mod}, {"bit_mul", luaB_bit_mul}, {"bit_imul", luaB_bit_imul}, {"bit_sub", luaB_bit_sub}, {"bit_add", luaB_bit_add}, {"bit_signed", luaB_bit_signed}, {"bit_unsigned", luaB_bit_unsigned}, {NULL, NULL} }; static int bits_init(void) { return instead_api_register(bits_funcs); } static struct instead_ext ext = { .init = bits_init, }; int instead_bits_init(void) { return instead_extension(&ext); } instead-3.5.2+dfsg/src/instead_paths.c000066400000000000000000000045271467622671600177010ustar00rootroot00000000000000/* * Copyright 2009-2017 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" #include "utils.h" static int luaB_get_savepath(lua_State *L) { lua_pushstring(L, dirname(game_save_path(1, 0))); return 1; } extern char *instead_exec; static int luaB_get_exepath(lua_State *L) { char instead_path[PATH_MAX]; if (instead_exec) { strcpy(instead_path, instead_exec); unix_path(instead_path); lua_pushstring(L, instead_exec); return 1; } return 0; } static int luaB_get_gamespath(lua_State *L) { char games_path[PATH_MAX]; if (GAMES_PATH[0] != '/') { strcpy(games_path, instead_cwd()); strcat(games_path, "/"); } else games_path[0] = 0; strcat(games_path, GAMES_PATH); unix_path(games_path); lua_pushstring(L, games_path); return 1; } const luaL_Reg paths_funcs[] = { {"instead_savepath", luaB_get_savepath}, {"instead_exepath", luaB_get_exepath}, {"instead_gamespath", luaB_get_gamespath}, { NULL, NULL } }; static int paths_init(void) { char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", instead_stead_path(), "/ext/paths.lua"); instead_api_register(paths_funcs); return instead_loadfile(dirpath(path)); } static struct instead_ext ext = { .init = paths_init, }; int instead_paths_init(void) { return instead_extension(&ext); } instead-3.5.2+dfsg/src/instead_sound.c000066400000000000000000000420471467622671600177110ustar00rootroot00000000000000/* * Copyright 2009-2018 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" static int cur_vol = 0; int game_change_vol(int d, int val) { int v = snd_volume_mus(-1); int pc = snd_vol_to_pcn(v); int opc = pc; if (d) { pc += d; if (pc < 0) pc = 0; if (pc > 100) pc = 100; while (snd_vol_to_pcn(v) != pc) v += (d<0)?-1:1; } else { v = val; pc = snd_vol_to_pcn(v); } if (!pc) v = 0; snd_volume_mus(v); if (opc && !pc) { game_stop_mus(0); } if (!opc && pc) { game_music_player(); } cur_vol = snd_volume_mus(-1); if (!nosound_sw) opt_vol = cur_vol; return 0; } #define MAX_WAVS SND_CHANNELS * 2 static LIST_HEAD(sounds); static int sounds_nr = 0; typedef struct { struct list_node list; char *fname; wav_t wav; int loaded; int system; int fmt; short *buf; size_t len; } _snd_t; typedef struct { _snd_t *snd; int loop; int channel; } _snd_req_t; static _snd_t *channels[SND_CHANNELS]; static _snd_req_t sound_reqs[SND_CHANNELS]; static void sound_play(_snd_t *sn, int chan, int loop); void sound_play_click(void) { sound_play(game_theme.click, -1, 1); } static void sound_callback(void *aux) { _snd_req_t *r; int channel = *((int *)aux); int c = channel % SND_CHANNELS; free(aux); /* fprintf(stderr, "finished: %d\n", channel); */ channels[c] = NULL; r = &sound_reqs[c]; if (r->snd) { _snd_t *s = r->snd; r->snd = NULL; sound_play(s, channel, r->loop); } else { snd_halt_chan(channel, 0); /* to avoid races */ } } void game_channel_finished(int channel) /* SDL callback */ { int *i = malloc(sizeof(channel)); if (!i) { fprintf(stderr, "game_channel_finished: No memory\n"); return; } *i = channel; push_user_event(sound_callback, i); } static int sound_playing(_snd_t *snd) { int i; for (i = 0; i < SND_CHANNELS; i++) { if (channels[i] == snd) return i; if (sound_reqs[i].snd == snd) return i; } return -1; } static const char *sound_channel(int i) { _snd_t *sn; if (i >= SND_CHANNELS) i = i % SND_CHANNELS; if (i == -1) { for (i = 0; i < SND_CHANNELS; i++) { sn = channels[i]; if (sn && !sn->system) return sn->fname; } return NULL; } sn = channels[i]; if (!sn) return NULL; if (sn->system) return NULL; /* hidden system sound */ return sn->fname; } static void sound_free(_snd_t *sn) { if (!sn) return; list_del(&sn->list); sounds_nr --; free(sn->fname); snd_free_wav(sn->wav); if (sn->buf) free(sn->buf); free(sn); } static void sounds_shrink(void) { _snd_t *pos, *pos2; _snd_t *sn; pos = list_top(&sounds, _snd_t, list); /* fprintf(stderr,"shrink try\n"); */ while (pos && sounds_nr > MAX_WAVS) { sn = (_snd_t*)pos; if (sound_playing(sn) != -1 || sn->loaded) { pos = list_next(&sounds, pos, list); continue; } pos2 = list_next(&sounds, pos, list); sound_free(sn); pos = pos2; /* fprintf(stderr,"shrink by 1\n"); */ } } static void sounds_free(void) { int i = 0; _snd_t *pos, *pos2; _snd_t *sn; pos = list_top(&sounds, _snd_t, list); snd_halt_chan(-1, 0); /* halt sounds */ while (pos) { sn = (_snd_t*)pos; pos2 = list_next(&sounds, pos, list); if (sn->system) sn->loaded = 1; /* ref by system only */ else sound_free(sn); pos = pos2; } for (i = 0; i < SND_CHANNELS; i++) { channels[i] = NULL; sound_reqs[i].snd = NULL; } /* sounds_nr = 0; fprintf(stderr, "%d\n", sounds_nr); */ input_uevents(); /* all callbacks */ } static _snd_t *sound_find(const char *fname) { _snd_t *pos = NULL; _snd_t *sn; if (!fname) return NULL; list_for_each(&sounds, pos, list) { sn = (_snd_t*)pos; if (!strcmp(fname, sn->fname)) { list_del(&sn->list); list_add(&sounds, &sn->list); /* move it on head */ return sn; } } return NULL; } static int sound_find_channel(void) { int i; for (i = 0; i < SND_CHANNELS; i ++) { if (!channels[i] && !sound_reqs[i].snd) return i; } return -1; } static void sound_play(_snd_t *sn, int chan, int loop) { int c; if (!sn) return; if (chan == -1) { c = sound_find_channel(); if (c == -1) return; /* all channels are busy */ } else c = chan; if (channels[c]) { sound_reqs[c].snd = sn; sound_reqs[c].loop = loop; sound_reqs[c].channel = chan; snd_halt_chan(chan, 0); /* work in callback */ input_uevents(); /* all callbacks */ return; } c = snd_play(sn->wav, c, loop - 1); /* fprintf(stderr, "added: %d\n", c); */ if (c == -1) return; channels[c] = sn; } static _snd_t *sound_add(const char *fname, int fmt, short *buf, int len) { wav_t w; _snd_t *sn; if (!fname || !*fname) return NULL; sn = malloc(sizeof(_snd_t)); if (!sn) return NULL; memset(sn, 0, sizeof(*sn)); /* LIST_HEAD_INIT(&sn->list); */ sn->fname = strdup(fname); sn->loaded = 0; sn->system = 0; sn->buf = buf; sn->len = len; sn->fmt = fmt; if (!sn->fname) { free(sn); return NULL; } if (buf) w = snd_load_mem(fmt, buf, len); else w = snd_load_wav(fname); if (!w) { if (snd_enabled()) game_res_err_msg(fname, debug_sw); goto err; } sn->wav = w; sounds_shrink(); list_add(&sounds, &sn->list); sounds_nr ++; return sn; err: free(sn->fname); free(sn); return NULL; } static void sounds_reload(void) { _snd_t *pos = NULL; _snd_t *sn; int i; snd_halt_chan(-1, 0); /* stop all sound */ list_for_each(&sounds, pos, list) { sn = (_snd_t*)pos; snd_free_wav(sn->wav); if (sn->buf) sn->wav = snd_load_mem(sn->fmt, sn->buf, sn->len); else sn->wav = snd_load_wav(sn->fname); } for (i = 0; i < SND_CHANNELS; i++) { channels[i] = NULL; sound_reqs[i].snd = NULL; } input_uevents(); /* all callbacks */ } static void *_sound_get(const char *fname, int fmt, short *buff, size_t len) { _snd_t *sn = NULL; if (fname) { sn = sound_find(fname); if (sn) { sn->loaded ++; /* to pin */ return sn; } sn = sound_add(fname, fmt, buff, len); } else if (buff) { char *name = malloc(64); if (!name) return NULL; snprintf(name, 64, "snd:%p", buff); name[64 - 1] = 0; sn = sound_add(name, fmt, buff, len); if (!sn) free(name); else { snprintf(name, 64, "snd:%p", sn); name[64 - 1] = 0; free(sn->fname); sn->fname = name; } } if (!sn) return NULL; sn->loaded = 1; return sn; } static void _sound_put(void *s) { _snd_t *sn = (_snd_t *)s; if (!sn || !sn->loaded) return; if (!sn->system || sn->loaded > 1) sn->loaded --; if (!sn->loaded && sound_playing(sn) == -1) sound_free(sn); return; } void *sound_get(const char *fname) { _snd_t *sn = _sound_get(fname, 0, NULL, 0); if (!sn) return NULL; sn->system = 1; return sn; } void sound_put(void *s) { _snd_t *sn = (_snd_t *)s; if (!sn) return; sn->system = 0; _sound_put(sn); } static int sound_load(const char *fname) { _snd_t *sn = _sound_get(fname, 0, NULL, 0); if (!sn) return -1; return 0; } static char *sound_load_mem(int fmt, short *buff, size_t len) { _snd_t *sn = _sound_get(NULL, fmt, buff, len); if (!sn) return NULL; return sn->fname; } static void sound_unload(const char *fname) { _snd_t *sn; sn = sound_find(fname); _sound_put(sn); return; } static int _play_combined_snd(char *filename, int chan, int loop) { char *str; char *p, *ep; _snd_t *sn; p = str = strdup(filename); if (!str) return -1; p = strip(p); while (*p) { int c = chan, l = loop; int at = 0; ep = p + strcspn(p, ";@"); if (*ep == '@') { at = 1; *ep = 0; ep ++; if (sscanf(ep, "%d,%d", &c, &l) > 1) at ++; ep += strcspn(ep, ";"); if (*ep) ep ++; } else if (*ep == ';') { *ep = 0; ep ++; } else if (*ep) { goto err; } p = strip(p); sn = sound_find(p); if (!sn) sn = sound_add(p, 0, NULL, 0); if (sn) sound_play(sn, c, l); else if (at || c != -1) { /* if @ or specific channel */ snd_halt_chan(c, (at == 2)?l:500); } p = ep; } free(str); return 0; err: free(str); return -1; } static void game_sound_player(void) { char *snd; int chan = -1; int loop = 1; struct instead_args args[] = { { .val = "nil", .type = INSTEAD_NIL }, { .val = "-1", .type = INSTEAD_NUM }, { .val = NULL } }; if (!snd_volume_mus(-1)) return; instead_lock(); instead_function("instead.get_sound", NULL); loop = instead_iretval(2); chan = instead_iretval(1); snd = instead_retval(0); instead_clear(); if (!snd) { if (chan != -1) { /* halt channel */ snd_halt_chan(chan, 500); instead_function("instead.set_sound", args); instead_clear(); } instead_unlock(); return; } instead_function("instead.set_sound", args); instead_clear(); instead_unlock(); unix_path(snd); _play_combined_snd(snd, chan, loop); free(snd); } static char *last_music = NULL; static void free_last_music(void) { if (last_music) free(last_music); last_music = NULL; } int game_change_hz(int hz) { if (!hz) return -1; #ifndef __EMSCRIPTEN__ snd_close(); free_last_music(); snd_open(hz); snd_volume_mus(cur_vol); sounds_reload(); game_music_player(); #endif opt_hz = snd_hz(); return 0; } void game_stop_mus(int ms) { snd_stop_mus(ms); free_last_music(); } static void finish_music(void *data) { int rc; if (!curgame_dir) return; instead_lock(); instead_function("instead.finish_music", NULL); rc = instead_bretval(0); instead_clear(); instead_unlock(); if (rc) free_last_music(); snd_volume_mus(cur_vol); /* reset volume */ } void game_music_finished(void) /* SDL callback */ { push_user_event(&finish_music, NULL); } void game_music_player(void) { int loop; char *mus; int cf_out = 0; int cf_in = 0; if (!snd_volume_mus(-1)) return; if (!opt_music || !curgame_dir) return; instead_lock(); instead_function("instead.get_music", NULL); mus = instead_retval(0); loop = instead_iretval(1); unix_path(mus); instead_clear(); instead_function("instead.get_music_fading", NULL); cf_out = instead_iretval(0); cf_in = instead_iretval(1); instead_clear(); instead_unlock(); if (mus && loop == -1) { /* disabled, 0 - forever, 1-n - loops */ free(mus); mus = NULL; } if (loop == 0) loop = -1; if (cf_out == 0) cf_out = 500; else if (cf_out < 0) cf_out = 0; if (cf_in < 0) cf_in = 0; if (!mus) { if (last_music) { game_stop_mus(cf_out); } } else if (!last_music || strcmp(last_music, mus)) { game_stop_mus(cf_out); last_music = mus; if (snd_play_mus(mus, cf_in, loop) < 0) game_res_err_msg(mus, debug_sw); } else free(mus); } static int luaB_is_sound(lua_State *L) { const char *chan = luaL_optstring(L, 1, NULL); int c, r; if (!chan) c = -1; else c = atoi(chan); r = (sound_channel(c) != NULL); lua_pushboolean(L, r); /* else not a number */ return 1; } static int luaB_load_sound(lua_State *L) { int rc; const char *fname = luaL_optstring(L, 1, NULL); if (!fname) return 0; rc = sound_load(fname); if (rc) return 0; lua_pushstring(L, fname); return 1; } #define SND_F2S(v) ((short)((float)(v) * 16383.0) * 2) static int luaB_load_sound_mem(lua_State *L) { int hz = luaL_optinteger(L, 1, -1); int channels = luaL_optinteger(L, 2, -1); int len; int i; short *buf = NULL; const char *name; int fmt = 0; luaL_checktype(L, 3, LUA_TTABLE); if (hz < 0 || channels < 0) return 0; #if LUA_VERSION_NUM >= 502 len = lua_rawlen(L, 3); #else len = lua_objlen(L, 3); #endif if (len <= 0) return 0; buf = malloc(sizeof(short) * len); if (!buf) return 0; lua_pushvalue(L, 3); for (i = 0; i < len; i++) { float v; lua_pushinteger(L, i + 1); lua_gettable(L, -2); if (!lua_isnumber(L, -1)) { v = 0; } else { v = (float)lua_tonumber(L, -1); } buf[i] = SND_F2S(v); lua_pop(L, 1); } lua_pop(L, 1); /* here we got the sample */ if (channels == 2) fmt |= SND_FMT_STEREO; if (hz == 11025) fmt |= SND_FMT_11; else if (hz == 22050) fmt |= SND_FMT_22; else fmt |= SND_FMT_44; name = sound_load_mem(fmt, buf, len); /* free(buf); */ if (!name) return 0; lua_pushstring(L, name); return 1; } static int luaB_free_sound(lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); if (!fname) return 0; sound_unload(fname); return 0; } static int luaB_free_sounds(lua_State *L) { sounds_free(); return 0; } static int luaB_panning_sound(lua_State *L) { int chan = luaL_optinteger(L, 1, -1); int left = luaL_optnumber(L, 2, 255); int right = luaL_optnumber(L, 3, 255); snd_panning(chan, left, right); return 0; } static int luaB_volume_sound(lua_State *L) { int vol = luaL_optnumber(L, 1, -1); vol = snd_volume_mus(vol); lua_pushinteger(L, vol); return 1; } static int luaB_channel_sound(lua_State *L) { const char *s; int ch = luaL_optinteger(L, 1, 0); ch = ch % SND_CHANNELS; s = sound_channel(ch); if (s) { lua_pushstring(L, s); return 1; } return 0; } static int callback_ref = 0; static int sound_inited = 0; #define SOUND_MAGIC 0x2004 struct lua_sound { int type; short *buf; int len; }; static void mus_callback(void *udata, unsigned char *stream, int len) { lua_State *L = (lua_State *) udata; struct lua_sound *hdr; if (!callback_ref) return; instead_lock(); lua_rawgeti(L, LUA_REGISTRYINDEX, callback_ref); lua_pushinteger(L, snd_hz()); lua_pushinteger(L, len >> 1); hdr = lua_newuserdata(L, sizeof(*hdr)); if (!hdr) goto err; hdr->type = SOUND_MAGIC; hdr->len = len >> 1; /* 16bits */ hdr->buf = (short *)stream; luaL_getmetatable(L, "soundbuffer metatable"); lua_setmetatable(L, -2); if (instead_pcall(L, 3)) { /* on any error */ err: snd_mus_callback(NULL, NULL); luaL_unref(L, LUA_REGISTRYINDEX, callback_ref); callback_ref = 0; } instead_clear(); instead_unlock(); return; } static int luaB_music_callback(lua_State *L) { if (!sound_inited) return 0; snd_mus_callback(NULL, NULL); if (callback_ref) luaL_unref(L, LUA_REGISTRYINDEX, callback_ref); callback_ref = 0; if (lua_isfunction(L, 1)) { game_stop_mus(0); callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); snd_mus_callback(mus_callback, L); } return 0; } static const luaL_Reg sound_funcs[] = { {"instead_sound", luaB_is_sound}, {"instead_sound_load", luaB_load_sound}, {"instead_sound_load_mem", luaB_load_sound_mem}, {"instead_sound_free", luaB_free_sound}, {"instead_sound_channel", luaB_channel_sound}, {"instead_sound_panning", luaB_panning_sound}, {"instead_sound_volume", luaB_volume_sound}, {"instead_sounds_free", luaB_free_sounds}, {"instead_music_callback", luaB_music_callback}, {NULL, NULL} }; static int sound_done(void) { if (!sound_inited) return 0; if (callback_ref) { snd_mus_callback(NULL, NULL); luaL_unref(instead_lua(), LUA_REGISTRYINDEX, callback_ref); callback_ref = 0; } game_stop_mus(0); sounds_free(); snd_close(); sound_inited = 0; return 0; } /* static int sound_size(lua_State *L) { struct lua_sound *hdr = (struct lua_sound*)lua_touserdata(L, 1); if (!hdr || hdr->type != SOUND_MAGIC) return 0; lua_pushnumber(L, hdr->len); return 1; } */ static int sound_value(lua_State *L) { struct lua_sound *hdr = (struct lua_sound*)lua_touserdata(L, 1); int pos = luaL_optinteger(L, 2, -1); float v = luaL_optnumber(L, 3, 0.0f); if (pos <= 0) return 0; if (pos > hdr->len) return 0; pos --; if (lua_isnoneornil(L, 3)) { lua_pushinteger(L, hdr->buf[pos]); return 1; } hdr->buf[pos] = SND_F2S(v); return 0; } /* ** Creates chunk metatable. */ static int chunk_create_meta (lua_State *L) { luaL_newmetatable (L, "soundbuffer metatable"); lua_pushstring (L, "__index"); lua_pushcfunction(L, sound_value); lua_settable(L, -3); lua_pushstring (L, "__newindex"); lua_pushcfunction(L, sound_value); lua_settable(L, -3); /* lua_pushstring (L, "size"); lua_pushcfunction (L, sound_size); lua_settable(L, -3); */ return 0; } static int sound_init(void) { int rc; char path[PATH_MAX]; instead_api_register(sound_funcs); chunk_create_meta(instead_lua()); snprintf(path, sizeof(path), "%s/%s", instead_stead_path(), "/ext/sound.lua"); rc = instead_loadfile(dirpath(path)); if (rc) return rc; snd_open(opt_hz); if (!nosound_sw) game_change_vol(0, opt_vol); sound_inited = 1; return 0; } static int sound_cmd(void) { game_music_player(); game_sound_player(); return 0; } static struct instead_ext ext = { .init = sound_init, .done = sound_done, .cmd = sound_cmd, }; int instead_sound_init(void) { return instead_extension(&ext); } instead-3.5.2+dfsg/src/instead_sprites.c000066400000000000000000001563631467622671600202610ustar00rootroot00000000000000/* * Copyright 2009-2023 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" #include "noise1234.h" static LIST_HEAD(sprites); static LIST_HEAD(fonts); #define FN_SCALED 1 typedef struct { struct list_node list; char *name; int flags; fnt_t fnt; } _fnt_t; typedef struct { struct list_node list; char *name; img_t img; } _spr_t; struct lua_pixels; static img_t pixels_img(struct lua_pixels *hdr); static void sprites_free(void) { /* fprintf(stderr, "sprites free \n"); */ while (!list_empty(&sprites)) { _spr_t *sp = list_top(&sprites, _spr_t, list); free(sp->name); cache_forget(gfx_image_cache(), sp->img); list_del(&sp->list); free(sp); } while (!list_empty(&fonts)) { _fnt_t *fn = list_top(&fonts, _fnt_t, list); fnt_free(fn->fnt); free(fn->name); list_del(&fn->list); free(fn); } game_pict_modify(NULL); cache_shrink(gfx_image_cache()); } static _spr_t *sprite_lookup(const char *name) { _spr_t *pos = NULL; _spr_t *sp; list_for_each(&sprites, pos, list) { sp = (_spr_t*)pos; if (!strcmp(name, sp->name)) { list_del(&sp->list); list_add(&sprites, &sp->list); /* move it on head */ return sp; } } return NULL; } static _fnt_t *font_lookup(const char *name) { _fnt_t *pos = NULL; _fnt_t *fn; list_for_each(&fonts, pos, list) { fn = (_fnt_t*)pos; if (!strcmp(name, fn->name)) { list_del(&fn->list); list_add(&fonts, &fn->list); /* move it on head */ return fn; } } return NULL; } static _spr_t *sprite_new(const char *name, img_t img) { _spr_t *sp; sp = malloc(sizeof(_spr_t)); if (!sp) return NULL; /* INIT_LIST_HEAD(&sp->list); */ sp->name = strdup(name); if (!sp->name) { free(sp); return NULL; } sp->img = img; if (cache_add(gfx_image_cache(), name, img)) { free(sp->name); free(sp); return NULL; } /* fprintf(stderr, "added: %s\n", name); */ list_add(&sprites, &sp->list); return sp; } static _fnt_t *font_new(const char *name, fnt_t fnt) { _fnt_t *fn; fn = malloc(sizeof(_fnt_t)); if (!fn) return NULL; /* INIT_LIST_HEAD(&fn->list); */ fn->name = strdup(name); if (!fn->name) { free(fn); return NULL; } fn->fnt = fnt; fn->flags = 0; list_add(&fonts, &fn->list); return fn; } static void sprite_name(const char *name, char *sname, int size) { unsigned long h = 0; if (!sname || !size) return; h = hash_string(name); do { /* new uniq name */ snprintf(sname, size, "spr:%lx", h); h ++; } while (sprite_lookup(sname) || cache_lookup(gfx_image_cache(), sname)); sname[size - 1] = 0; } static void font_name(const char *name, char *sname, int size) { unsigned long h = 0; if (!sname || !size) return; h = hash_string(name); do { /* new uniq name */ snprintf(sname, size, "fnt:%lx", h); h ++; } while (font_lookup(sname)); sname[size - 1] = 0; } static int _free_sprite(const char *key); static int luaB_free_sprites(lua_State *L) { sprites_free(); return 0; } #define PIXELS_MAGIC 0x1980 struct lua_pixels { int type; int w; int h; float scale; size_t size; img_t img; int dirty; int direct; }; static int luaB_load_sprite(lua_State *L) { int convert = 0; img_t img = NULL; _spr_t *sp; const char *key; char sname[sizeof(unsigned long) * 2 + 16]; struct lua_pixels *pixels = lua_touserdata(L, 1); const char *desc = NULL; const char *fname = NULL; char pixels_name[32]; if (lua_isstring(L, 2)) desc = luaL_optstring(L, 2, NULL); if (!pixels) fname = luaL_optstring(L, 1, NULL); else { snprintf(pixels_name, sizeof(pixels_name), "pxl:%p", pixels); pixels_name[sizeof(pixels_name) - 1] = 0; fname = pixels_name; } if (!fname) return 0; if (pixels) { if (lua_isboolean(L, 2)) { convert = lua_toboolean(L, 2); desc = luaL_optstring(L, 3, NULL); } if (convert) { /* slow path */ img = gfx_new_from(pixels->w, pixels->h, (unsigned char*)(pixels + 1)); if (img) theme_gfx_scale(&img, pixels->scale); } else { img = pixels_img(pixels); if (img) img = gfx_dup(img); } } else { img = gfx_load_image((char*)fname); if (img) theme_gfx_scale(&img, 1.0f); } if (img) img = gfx_display_alpha(img); /*speed up */ if (!img) goto err; if (!desc || sprite_lookup(desc)) { key = sname; sprite_name(fname, sname, sizeof(sname)); } else key = desc; sp = sprite_new(key, img); if (!sp) goto err; lua_pushstring(L, key); return 1; err: game_res_err_msg(fname, debug_sw); gfx_free_image(img); return 0; } static int luaB_load_font(lua_State *L) { int scaled = 0; fnt_t fnt = NULL; _fnt_t *fn; const char *key; char sname[sizeof(unsigned long) * 2 + 16]; struct game_theme *t = &game_theme; const char *fname = luaL_optstring(L, 1, NULL); int sz = luaL_optnumber(L, 2, t->font_size); const char *desc = luaL_optstring(L, 3, NULL); if (!fname || sz == 0) return 0; if (sz > 0) { sz *= game_theme.scale; scaled = 1; } else sz = - sz; /* sz < 0 is unscalable */ fnt = fnt_load((char*)fname, sz); if (!fnt) return 0; if (!desc || font_lookup(desc)) { key = sname; font_name(fname, sname, sizeof(sname)); } else key = desc; fn = font_new(key, fnt); if (!fn) goto err; if (scaled) fn->flags |= FN_SCALED; lua_pushstring(L, key); return 1; err: fnt_free(fnt); return 0; } static int luaB_text_size(lua_State *L) { _fnt_t *fn; int w = 0, h = 0; const char *font = luaL_optstring(L, 1, NULL); const char *text = luaL_optstring(L, 2, NULL); int style = luaL_optnumber(L, 3, 0); if (!font) return 0; fn = font_lookup(font); if (!fn) return 0; if (!text) { w = 0; if (fn->flags & FN_SCALED) h = ceil((float)fnt_height(fn->fnt) / game_theme.scale); else h = fnt_height(fn->fnt); } else { fnt_style(fn->fnt, style); txt_size(fn->fnt, text, &w, &h); if (fn->flags & FN_SCALED) { w = ceil((float)w / game_theme.scale); h = ceil((float)h / game_theme.scale); } } lua_pushinteger(L, w); lua_pushinteger(L, h); return 2; } static int luaB_font_size_scaled(lua_State *L) { int sz = luaL_optnumber(L, 1, game_theme.font_size); lua_pushinteger(L, FONT_SZ(sz)); return 1; } static int luaB_text_sprite(lua_State *L) { img_t img = NULL; _spr_t *sp; _fnt_t *fn; const char *key; char sname[sizeof(unsigned long) * 2 + 16]; const char *font = luaL_optstring(L, 1, NULL); const char *text = luaL_optstring(L, 2, NULL); char txtkey[32]; const char *color = luaL_optstring(L, 3, NULL); int style = luaL_optnumber(L, 4, 0); const char *desc = luaL_optstring(L, 5, NULL); color_t col = { .r = game_theme.fgcol.r, .g = game_theme.fgcol.g, .b = game_theme.fgcol.b }; if (!font) return 0; if (color) gfx_parse_color (color, &col); if (!text) text = ""; fn = font_lookup(font); if (!fn) return 0; fnt_style(fn->fnt, style); img = fnt_render(fn->fnt, text, col); if (img) img = gfx_display_alpha(img); /*speed up */ if (!img) return 0; if (!desc || sprite_lookup(desc)) { key = sname; strncpy(txtkey, text, sizeof(txtkey)); txtkey[sizeof(txtkey) - 1] = 0; sprite_name(txtkey, sname, sizeof(sname)); } else key = desc; sp = sprite_new(key, img); if (!sp) goto err; lua_pushstring(L, key); return 1; err: gfx_free_image(img); return 0; } static int in_callback = 0; static img_t grab_sprite(const char *dst, int *xoff, int *yoff) { img_t oldscreen; img_t d; if (!dst) return NULL; if ((DIRECT_MODE || in_callback) && !strcmp(dst, "screen")) { d = gfx_screen(NULL); *xoff = game_theme.xoff; *yoff = game_theme.yoff; } else if (opt_owntheme && !strcmp(dst, "screen")) { if (!game_theme.bg) { /* create on the fly */ game_theme.bg = gfx_new(game_theme.w, game_theme.h); oldscreen = gfx_screen(game_theme.bg); gfx_clear(0, 0, game_theme.w, game_theme.h); gfx_screen(oldscreen); } d = game_theme.bg; *xoff = game_theme.xoff; *yoff = game_theme.yoff; } else { *xoff = 0; *yoff = 0; d = cache_lookup(gfx_image_cache(), dst); } return d; } static int luaB_sprite_size(lua_State *L) { img_t s = NULL; float v; int w, h; int xoff, yoff; const char *src = luaL_optstring(L, 1, NULL); if (!src) return 0; s = grab_sprite(src, &xoff, &yoff); if (!s) return 0; v = game_theme.scale; w = ceil ((float)(gfx_img_w(s) - xoff * 2) / v); h = ceil ((float)(gfx_img_h(s) - yoff * 2) / v); lua_pushinteger(L, w); lua_pushinteger(L, h); return 2; } #define BLIT_COPY 0 #define BLIT_DRAW 1 #define BLIT_COMPOSE 2 static int luaB_blit_sprite(lua_State *L, int mode) { img_t s = NULL, d = NULL; float v; struct lua_pixels *pixels = lua_touserdata(L, 1); const char *src = NULL; int x = luaL_optnumber(L, 2, 0); int y = luaL_optnumber(L, 3, 0); int w = luaL_optnumber(L, 4, -1); int h = luaL_optnumber(L, 5, -1); const char *dst = luaL_optstring(L, 6, NULL); int xx = luaL_optnumber(L, 7, 0); int yy = luaL_optnumber(L, 8, 0); int alpha = luaL_optnumber(L, 9, 255); int xoff = 0, yoff = 0; int xoff0 = 0, yoff0 = 0; if (!pixels) src = luaL_optstring(L, 1, NULL); if ((!src && !pixels) || !dst) return 0; if (pixels) s = pixels_img(pixels); if (!s) s = grab_sprite(src, &xoff0, &yoff0); d = grab_sprite(dst, &xoff, &yoff); if (!s || !d) return 0; v = game_theme.scale; if (v != 1.0f) { x *= v; y *= v; if (w != -1) w = ceil(w * v); if (h != -1) h = ceil(h * v); xx *= v; yy *= v; } if (w == -1) w = gfx_img_w(s) - 2 * xoff0; if (h == -1) h = gfx_img_h(s) - 2 * yoff0; game_pict_modify(d); game_gfx_clip(); switch (mode) { case BLIT_DRAW: if (alpha != 255) gfx_draw_from_alpha(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff, alpha); else gfx_draw_from(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff); break; case BLIT_COPY: gfx_copy_from(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff); break; case BLIT_COMPOSE: gfx_compose_from(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff); break; default: break; } game_gfx_noclip(); lua_pushboolean(L, 1); return 1; } static int luaB_draw_sprite(lua_State *L) { return luaB_blit_sprite(L, BLIT_DRAW); } static int luaB_copy_sprite(lua_State *L) { return luaB_blit_sprite(L, BLIT_COPY); } static int luaB_compose_sprite(lua_State *L) { return luaB_blit_sprite(L, BLIT_COMPOSE); } static int luaB_alpha_sprite(lua_State *L) { _spr_t *sp; img_t s; img_t img2 = NULL; const char *key; char sname[sizeof(unsigned long) * 2 + 16]; const char *src = luaL_optstring(L, 1, NULL); int alpha = luaL_optnumber(L, 2, 255); const char *desc = luaL_optstring(L, 3, NULL); if (!src) return 0; s = cache_lookup(gfx_image_cache(), src); if (!s) return 0; img2 = gfx_alpha_img(s, alpha); if (!img2) return 0; if (!desc || sprite_lookup(desc)) { key = sname; sprite_name(src, sname, sizeof(sname)); } else key = desc; sp = sprite_new(key, img2); if (!sp) goto err; lua_pushstring(L, sname); return 1; err: gfx_free_image(img2); return 0; } static int luaB_colorkey_sprite(lua_State *L) { img_t s; color_t col; const char *src = luaL_optstring(L, 1, NULL); const char *color = luaL_optstring(L, 2, NULL); if (color) gfx_parse_color(color, &col); if (!src) return 0; s = cache_lookup(gfx_image_cache(), src); if (!s) return 0; if (color) gfx_set_colorkey(s, col); else gfx_unset_colorkey(s); return 0; } static int luaB_dup_sprite(lua_State *L) { _spr_t *sp; img_t s; img_t img2 = NULL; const char *key; char sname[sizeof(unsigned long) * 2 + 16]; const char *src = luaL_optstring(L, 1, NULL); const char *desc = luaL_optstring(L, 2, NULL); if (!src) return 0; s = cache_lookup(gfx_image_cache(), src); if (!s) return 0; img2 = gfx_dup(s); if (!img2) return 0; if (!desc || sprite_lookup(desc)) { key = sname; sprite_name(src, sname, sizeof(sname)); } else key = desc; sp = sprite_new(key, img2); if (!sp) goto err; lua_pushstring(L, sname); return 1; err: gfx_free_image(img2); return 0; } static int luaB_scale_sprite(lua_State *L) { _spr_t *sp; img_t s; img_t img2 = NULL; const char *key; char sname[sizeof(unsigned long) * 2 + 16]; const char *src = luaL_optstring(L, 1, NULL); float xs = luaL_optnumber(L, 2, 0); float ys = luaL_optnumber(L, 3, 0); int smooth = lua_toboolean(L, 4); const char *desc = luaL_optstring(L, 5, NULL); if (!src) return 0; s = cache_lookup(gfx_image_cache(), src); if (!s) return 0; if (xs == 0) xs = 1.0f; if (ys == 0) ys = xs; img2 = gfx_scale(s, xs, ys, smooth); if (!img2) return 0; if (!desc || sprite_lookup(desc)) { key = sname; sprite_name(src, sname, sizeof(sname)); } else key = desc; sp = sprite_new(key, img2); if (!sp) goto err; lua_pushstring(L, sname); return 1; err: gfx_free_image(img2); return 0; } static int luaB_rotate_sprite(lua_State *L) { _spr_t *sp; img_t s; img_t img2 = NULL; const char *key; char sname[sizeof(unsigned long) * 2 + 16]; const char *src = luaL_optstring(L, 1, NULL); float angle = luaL_optnumber(L, 2, 1.0f); int smooth = lua_toboolean(L, 3); const char *desc = luaL_optstring(L, 4, NULL); if (!src) return 0; s = cache_lookup(gfx_image_cache(), src); if (!s) return 0; img2 = gfx_rotate(s, angle, smooth); if (!img2) return 0; if (!desc || sprite_lookup(desc)) { key = sname; sprite_name(src, sname, sizeof(sname)); } else key = desc; sp = sprite_new(key, img2); if (!sp) goto err; lua_pushstring(L, sname); return 1; err: gfx_free_image(img2); return 0; } static int luaB_fill_sprite(lua_State *L) { img_t d; float v; const char *dst = luaL_optstring(L, 1, NULL); int x = luaL_optnumber(L, 2, 0); int y = luaL_optnumber(L, 3, 0); int w = luaL_optnumber(L, 4, -1); int h = luaL_optnumber(L, 5, -1); const char *color = luaL_optstring(L, 6, NULL); int xoff = 0, yoff = 0; color_t col = { .r = game_theme.bgcol.r, .g = game_theme.bgcol.g, .b = game_theme.bgcol.b }; if (!dst) return 0; d = grab_sprite(dst, &xoff, &yoff); if (color) gfx_parse_color(color, &col); if (!d) return 0; v = game_theme.scale; if (v != 1.0f) { x *= v; y *= v; if (w != -1) w = ceil(w * v); if (h != -1) h = ceil(h * v); } if (w == -1) w = gfx_img_w(d) - 2 * xoff; if (h == -1) h = gfx_img_h(d) - 2 * yoff; game_pict_modify(d); game_gfx_clip(); gfx_img_fill(d, x + xoff, y + yoff, w, h, col); game_gfx_noclip(); lua_pushboolean(L, 1); return 1; } static int luaB_pixel_sprite(lua_State *L) { img_t d; float v; int rc, w, h; color_t col = { .r = game_theme.bgcol.r, .g = game_theme.bgcol.g, .b = game_theme.bgcol.b, .a = 255 }; const char *dst = luaL_optstring(L, 1, NULL); int x = luaL_optnumber(L, 2, 0); int y = luaL_optnumber(L, 3, 0); const char *color = luaL_optstring(L, 4, NULL); int alpha = luaL_optnumber(L, 5, 255); int xoff = 0, yoff = 0; if (!dst) return 0; d = grab_sprite(dst, &xoff, &yoff); if (color) gfx_parse_color(color, &col); if (!d) return 0; w = gfx_img_w(d) - 2 * xoff; h = gfx_img_h(d) - 2 * yoff; v = game_theme.scale; if (v != 1.0f) { x *= v; y *= v; } if (color) { if (x < 0 || y < 0 || x >= w || y >= h) return 0; game_pict_modify(d); col.a = alpha; rc = gfx_set_pixel(d, x + xoff, y + yoff, col); } else { rc = gfx_get_pixel(d, x + xoff, y + yoff, &col); } if (rc) return 0; lua_pushinteger(L, col.r); lua_pushinteger(L, col.g); lua_pushinteger(L, col.b); lua_pushinteger(L, col.a); return 4; } static int _free_sprite(const char *key) { _spr_t *sp; if (!key) return -1; sp = sprite_lookup(key); if (!sp) return -1; cache_forget(gfx_image_cache(), sp->img); cache_shrink(gfx_image_cache()); list_del(&sp->list); free(sp->name); free(sp); return 0; } static int luaB_free_sprite(lua_State *L) { const char *key = luaL_optstring(L, 1, NULL); if (_free_sprite(key)) return 0; lua_pushboolean(L, 1); return 1; } static int luaB_free_font(lua_State *L) { const char *key = luaL_optstring(L, 1, NULL); _fnt_t *fn; if (!key) return 0; fn = font_lookup(key); if (!fn) return 0; list_del(&fn->list); fnt_free(fn->fnt); free(fn->name); free(fn); lua_pushboolean(L, 1); return 1; } extern int theme_setvar(char *name, char *val); extern char *theme_getvar(const char *name); static int luaB_theme_var(lua_State *L) { const char *var = luaL_optstring(L, 1, NULL); const char *val = luaL_optstring(L, 2, NULL); if (var && !val) { /* get */ char *p = theme_getvar(var); if (p) { lua_pushstring(L, p); free(p); return 1; } return 0; } if (!val || !var) return 0; /* if (!game_own_theme) return 0; */ if (!opt_owntheme) return 0; if (!strcmp(var, "scr.w") || !strcmp(var, "scr.h") || !strcmp(var, "scr.scale_aware") || !strcmp(var, "scr.dpi")) /* filter resolution */ return 0; if (!theme_setvar((char*)var, (char*)val)) { if (strcmp(var, "win.scroll.mode")) /* let change scroll mode w/o theme reload */ game_theme_changed = 1; } return 0; } static int luaB_theme_name(lua_State *L) { char *name; if (game_own_theme && opt_owntheme) { if (game_own_theme == 2) { name = malloc(strlen(curtheme_dir[THEME_GAME]) + 2); if (!name) return 0; sprintf(name, ".%s", curtheme_dir[THEME_GAME]); lua_pushstring(L, name); free(name); } else { lua_pushstring(L, "."); } } else lua_pushstring(L, curtheme_dir[THEME_GLOBAL]); return 1; } static int luaB_instead_direct(lua_State *L) { int direct = -1; int old = DIRECT_MODE; if (lua_isboolean(L, 1)) direct = lua_toboolean(L, 1); if (direct == -1) { lua_pushboolean(L, old); return 1; } if (!opt_owntheme) { lua_pushboolean(L, 0); return 1; } if (direct) game_theme.gfx_mode = GFX_DIRECT_SET(game_theme.gfx_mode); else { if (game_theme.gfx_mode != GFX_MODE_DIRECT) { game_theme.gfx_mode = GFX_DIRECT_CLR(game_theme.gfx_mode); } } lua_pushboolean(L, 1); return 1; } static unsigned long busy_time = 0; void instead_ready(void) { if (menu_visible() == menu_wait) { menu_toggle(-1); } busy_time = 0; } static int luaB_stead_busy(lua_State *L) { int busy = lua_toboolean(L, 1); if (busy) { struct inp_event ev; int dirty = 0; memset(&ev, 0, sizeof(ev)); if (!game_freezed()) { if (game_bg_modify(NULL)) game_redraw_all(); game_flip(); } while (input(&ev, 0) == AGAIN); if (ev.type == MOUSE_MOTION) { game_cursor(CURSOR_ON); /* to make all happy */ dirty = 1; } if (!busy_time) busy_time = gfx_ticks(); if (gfx_ticks() - busy_time >= 750 && menu_visible() != menu_wait) { game_menu(menu_wait); dirty = 1; } if (dirty) game_gfx_commit(0); return 0; } instead_ready(); game_gfx_commit(0); return 0; } static int luaB_mouse_pos(lua_State *L) { int x = luaL_optnumber(L, 1, -1); int y = luaL_optnumber(L, 2, -1); int m; float v = game_theme.scale; if (x != -1 && y != -1) { x *= v; y *= v; gfx_warp_cursor(x + game_theme.xoff, y + game_theme.yoff); x = -1; y = -1; } m = gfx_cursor(&x, &y); x = (x - game_theme.xoff) / v; y = (y - game_theme.yoff) / v; lua_pushinteger(L, x); lua_pushinteger(L, y); lua_pushinteger(L, m); return 3; } static int luaB_finger_pos(lua_State *L) { int x, y; float pressure; float v = game_theme.scale; const char *finger = luaL_optstring(L, 1, NULL); if (!finger) return 0; if (finger_pos(finger, &x, &y, &pressure)) /* no finger */ return 0; x = (x - game_theme.xoff) / v; y = (y - game_theme.yoff) / v; lua_pushinteger(L, x); lua_pushinteger(L, y); lua_pushnumber(L, pressure); return 3; } extern int mouse_filter_delay; static int luaB_mouse_filter(lua_State *L) { int d = luaL_optnumber(L, 1, -1); int ov = mouse_filter_delay; if (d != -1) mouse_filter_delay = d; lua_pushinteger(L, ov); return 1; } static int luaB_mouse_show(lua_State *L) { int show = lua_toboolean(L, 1); int ov = game_cursor_show; if (lua_isboolean(L, 1)) game_cursor_show = show; lua_pushboolean(L, ov); return 1; } static int luaB_get_ticks(lua_State *L) { lua_pushinteger(L, gfx_ticks()); return 1; } static int luaB_get_themespath(lua_State *L) { char themes_path[PATH_MAX]; if (THEMES_PATH[0] != '/') { strcpy(themes_path, instead_cwd()); strcat(themes_path, "/"); } else themes_path[0] = 0; strcat(themes_path, THEMES_PATH); unix_path(themes_path); lua_pushstring(L, themes_path); return 1; } static int pixels_size(lua_State *L) { struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1); if (!hdr || hdr->type != PIXELS_MAGIC) return 0; lua_pushinteger(L, hdr->w); lua_pushinteger(L, hdr->h); lua_pushnumber(L, hdr->scale); return 3; } #define PXL_BLEND_COPY 1 #define PXL_BLEND_BLEND 2 static __inline void blend(unsigned char *s, unsigned char *d) { unsigned int r, g, b, a; unsigned int sa = s[3]; unsigned int da = d[3]; a = sa + (da * (255 - sa) >> 8); r = ((unsigned int)s[0] * sa >> 8) + ((unsigned int)d[0] * da * (255 - sa) >> 16); g = ((unsigned int)s[1] * sa >> 8) + ((unsigned int)d[1] * da * (255 - sa) >> 16); b = ((unsigned int)s[2] * sa >> 8) + ((unsigned int)d[2] * da * (255 - sa) >> 16); d[0] = r; d[1] = g; d[2] = b; d[3] = a; } static __inline void draw(unsigned char *s, unsigned char *d) { unsigned int r, g, b, a; unsigned int sa = s[3]; a = 255; r = ((unsigned int)s[0] * sa >> 8) + ((unsigned int)d[0] * (255 - sa) >> 8); g = ((unsigned int)s[1] * sa >> 8) + ((unsigned int)d[1] * (255 - sa) >> 8); b = ((unsigned int)s[2] * sa >> 8) + ((unsigned int)d[2] * (255 - sa) >> 8); d[0] = r; d[1] = g; d[2] = b; d[3] = a; } static __inline void pixel(unsigned char *s, unsigned char *d) { unsigned char a_src = s[3]; unsigned char a_dst = d[3]; if (a_src == 255 || a_dst == 0) { memcpy(d, s, 4); } else if (a_src == 0) { /* nothing to do */ } else if (a_dst == 255) { draw(s, d); } else { blend(s, d); } } static __inline void line0(struct lua_pixels *hdr, int x1, int y1, int dx, int dy, int xd, unsigned char *col) { int dy2 = dy * 2; int dyx2 = dy2 - dx * 2; int err = dy2 - dx; unsigned char *ptr = NULL; int w = hdr->w; int h = hdr->h; int ly = w * 4; int lx = xd * 4; while ((x1 < 0 || y1 < 0 || x1 >= w || y1 >= h) && dx --) { if (err >= 0) { y1 ++; err += dyx2; } else { err += dy2; } x1 += xd; } if (dx < 0) return; ptr = (unsigned char*)(hdr + 1); ptr += (y1 * w + x1) << 2; pixel(col, ptr); while (dx --) { if (err >= 0) { y1 ++; if (y1 >= h) break; ptr += ly; err += dyx2; } else { err += dy2; } x1 += xd; if (x1 >= w || x1 < 0) break; ptr += lx; pixel(col, ptr); } return; } static __inline void line1(struct lua_pixels *hdr, int x1, int y1, int dx, int dy, int xd, unsigned char *col) { int dx2 = dx * 2; int dxy2 = dx2 - dy * 2; int err = dx2 - dy; int w = hdr->w; int h = hdr->h; unsigned char *ptr = NULL; int ly = w * 4; int lx = xd * 4; while ((x1 < 0 || y1 < 0 || x1 >= w || y1 >= h) && dy --) { if (err >= 0) { x1 += xd; err += dxy2; } else { err += dx2; } y1 ++; } if (dy < 0) return; ptr = (unsigned char*)(hdr + 1); ptr += (y1 * w + x1) << 2; pixel(col, ptr); while (dy --) { if (err >= 0) { x1 += xd; if (x1 < 0 || x1 >= w) break; ptr += lx; err += dxy2; } else { err += dx2; } y1 ++; if (y1 >= h) break; ptr += ly; pixel(col, ptr); } return; } static void lineAA(struct lua_pixels *src, int x0, int y0, int x1, int y1, int r, int g, int b, int a) { int dx, dy, err, e2, sx; int w, h; int syp, sxp, ed; unsigned char *ptr; unsigned char col[4]; col[0] = r; col[1] = g; col[2] = b; col[3] = a; if (y0 > y1) { int tmp; tmp = x0; x0 = x1; x1 = tmp; tmp = y0; y0 = y1; y1 = tmp; } w = src->w; h = src->h; if (y1 < 0 || y0 >= h) return; if (x0 < x1) { sx = 1; if (x0 >= w || x1 < 0) return; } else { sx = -1; if (x1 >= w || x0 < 0) return; } sxp = sx * 4; syp = w * 4; dx = abs(x1 - x0); dy = y1 - y0; err = dx - dy; ed = dx + dy == 0 ? 1: sqrt((float)dx * dx + (float)dy * dy); while (y0 < 0 || x0 < 0 || x0 >= w) { e2 = err; if (2 * e2 >= -dx) { if (x0 == x1) break; err -= dy; x0 += sx; } if (2 * e2 <= dy) { if (y0 == y1) break; err += dx; y0 ++; } } if (y0 < 0 || x0 < 0 || x0 >= w) return; ptr = (unsigned char*)(src + 1); ptr += (y0 * w + x0) << 2; while (1) { unsigned char *optr = ptr; col[3] = a - a * abs(err - dx + dy) / ed; pixel(col, ptr); e2 = err; if (2 * e2 >= -dx) { if (x0 == x1) break; if (e2 + dy < ed) { col[3] = a - a * (e2 + dy) / ed; pixel(col, ptr + syp); } err -= dy; x0 += sx; if (x0 < 0 || x0 >= w) break; ptr += sxp; } if (2 * e2 <= dy) { if (y0 == y1) break; if (dx - e2 < ed) { col[3] = a - a * (dx - e2) / ed; pixel(col, optr + sxp); } err += dx; y0 ++; if (y0 >= h) break; ptr += syp; } } src->dirty = 1; } static void line(struct lua_pixels *src, int x1, int y1, int x2, int y2, int r, int g, int b, int a) { int dx, dy, tmp; unsigned char col[4]; if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; tmp = x1; x1 = x2; x2 = tmp; } col[0] = r; col[1] = g; col[2] = b; col[3] = a; if (y1 >= src->h) return; if (y2 < 0) return; if (x1 < x2) { if (x2 < 0) return; if (x1 >= src->w) return; } else { if (x1 < 0) return; if (x2 >= src->w) return; } dx = x2 - x1; dy = y2 - y1; if (dx > 0) { if (dx > dy) { line0(src, x1, y1, dx, dy, 1, col); } else { line1(src, x1, y1, dx, dy, 1, col); } } else { dx = -dx; if (dx > dy) { line0(src, x1, y1, dx, dy, -1, col); } else { line1(src, x1, y1, dx, dy, -1, col); } } src->dirty = 1; } static int _pixels_blend(struct lua_pixels *src, int x, int y, int w, int h, struct lua_pixels *dst, int xx, int yy, int mode) { unsigned char *ptr1, *ptr2; int cy, cx, srcw, dstw; if (!w) w = src->w; if (!h) h = src->h; if (x < 0 || x + w > src->w) return 0; if (y < 0 || y + h > src->h) return 0; if (w <= 0 || h <= 0) return 0; if (xx < 0) { w += xx; x -= xx; xx = 0; } if (yy < 0) { h += yy; y -= yy; yy = 0; } if (w <= 0 || h <= 0) return 0; if (xx >= dst->w || yy >= dst->h) return 0; if (xx + w > dst->w) w = dst->w - xx; if (yy + h > dst->h) h = dst->h - yy; ptr1 = (unsigned char *)(src + 1); ptr2 = (unsigned char *)(dst + 1); ptr1 += (y * src->w + x) << 2; ptr2 += (yy * dst->w + xx) << 2; srcw = src->w * 4; dstw = dst->w * 4; dst->dirty = 1; for (cy = 0; cy < h; cy ++) { if (mode == PXL_BLEND_COPY) memcpy(ptr2, ptr1, w << 2); else { unsigned char *p2 = ptr2; unsigned char *p1 = ptr1; for (cx = 0; cx < w; cx ++) { pixel(p1, p2); p1 += 4; p2 += 4; } } ptr2 += dstw; ptr1 += srcw; } return 0; } static int pixels_copy(lua_State *L) { int x = 0, y = 0, w = 0, h = 0, xx = 0, yy = 0; struct lua_pixels *src, *dst; src = (struct lua_pixels*)lua_touserdata(L, 1); dst = (struct lua_pixels*)lua_touserdata(L, 2); if (!dst) { x = luaL_optnumber(L, 2, 0); y = luaL_optnumber(L, 3, 0); w = luaL_optnumber(L, 4, 0); h = luaL_optnumber(L, 5, 0); dst = (struct lua_pixels*)lua_touserdata(L, 6); xx = luaL_optnumber(L, 7, 0); yy = luaL_optnumber(L, 8, 0); } else { xx = luaL_optnumber(L, 3, 0); yy = luaL_optnumber(L, 4, 0); } if (!src || src->type != PIXELS_MAGIC) return 0; if (!dst || dst->type != PIXELS_MAGIC) return 0; return _pixels_blend(src, x, y, w, h, dst, xx, yy, PXL_BLEND_COPY); } static int pixels_blend(lua_State *L) { int x = 0, y = 0, w = 0, h = 0, xx = 0, yy = 0; struct lua_pixels *src, *dst; src = (struct lua_pixels*)lua_touserdata(L, 1); dst = (struct lua_pixels*)lua_touserdata(L, 2); if (!dst) { x = luaL_optnumber(L, 2, 0); y = luaL_optnumber(L, 3, 0); w = luaL_optnumber(L, 4, 0); h = luaL_optnumber(L, 5, 0); dst = (struct lua_pixels*)lua_touserdata(L, 6); xx = luaL_optnumber(L, 7, 0); yy = luaL_optnumber(L, 8, 0); } else { xx = luaL_optnumber(L, 3, 0); yy = luaL_optnumber(L, 4, 0); } if (!src || src->type != PIXELS_MAGIC) return 0; if (!dst || dst->type != PIXELS_MAGIC) return 0; return _pixels_blend(src, x, y, w, h, dst, xx, yy, PXL_BLEND_BLEND); } static void _fill(struct lua_pixels *src, int x, int y, int w, int h, int r, int g, int b, int a, int mode) { unsigned char col[4]; unsigned char *ptr1; int cy, cx; if (!src || src->type != PIXELS_MAGIC) return; col[0] = r; col[1] = g; col[2] = b; col[3] = a; if (!w) w = src->w; if (!h) h = src->h; if (x < 0) { w += x; x = 0; } if (y < 0) { h += y; y = 0; } if (w <= 0 || h <= 0 || x >= src->w || y >= src->h) return; if (x + w > src->w) w = src->w - x; if (y + h > src->h) h = src->h - y; ptr1 = (unsigned char *)(src + 1); ptr1 += (y * src->w + x) << 2; src->dirty = 1; for (cy = 0; cy < h; cy ++) { unsigned char *p1 = ptr1; for (cx = 0; cx < w; cx ++) { if (mode == PXL_BLEND_COPY) memcpy(p1, col, 4); else pixel(col, p1); p1 += 4; } ptr1 += (src->w * 4); } return; } static __inline int orient2d(int ax, int ay, int bx, int by, int cx, int cy) { return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax); } static __inline int min3(int a, int b, int c) { if (a < b) { if (a < c) return a; return c; } else { if (b < c) return b; return c; } } static __inline int max3(int a, int b, int c) { if (a > b) { if (a > c) return a; return c; } else { if (b > c) return b; return c; } } static void triangle(struct lua_pixels *src, int x0, int y0, int x1, int y1, int x2, int y2, int r, int g, int b, int a) { int A01 = y0 - y1, B01 = x1 - x0; int A12 = y1 - y2, B12 = x2 - x1; int A20 = y2 - y0, B20 = x0 - x2; int minx = min3(x0, x1, x2); int miny = min3(y0, y1, y2); int maxx = max3(x0, x1, x2); int maxy = max3(y0, y1, y2); int w0_row = orient2d(x1, y1, x2, y2, minx, miny); int w1_row = orient2d(x2, y2, x0, y0, minx, miny); int w2_row = orient2d(x0, y0, x1, y1, minx, miny); int y, x, w, h; int yd; unsigned char col[4]; unsigned char *ptr; w = src->w; h = src->h; yd = 4 * w; col[0] = r; col[1] = b; col[2] = g; col[3] = a; if (minx >= w || miny >= h) return; if (minx < 0) minx = 0; if (miny < 0) miny = 0; if (maxy >= h) maxy = h - 1; if (maxx >= w) maxx = w - 1; ptr = (unsigned char *)(src + 1) + miny * yd + 4 * minx; src->dirty = 1; for (y = miny; y <= maxy; y ++) { int w0 = w0_row; int w1 = w1_row; int w2 = w2_row; unsigned char *p = ptr; for (x = minx; x <= maxx; x++) { if ((w0 | w1 | w2) >= 0) pixel(col, p); p += 4; w0 += A12; w1 += A20; w2 += A01; } w0_row += B12; w1_row += B20; w2_row += B01; ptr += yd; } } static void fill_circle(struct lua_pixels *src, int xc, int yc, int radius, int r, int g, int b, int a) { int r2 = radius * radius; int x, y, x1, x2, y1, y2; unsigned char col[4] = { r, g, b, a }; int w = src->w, h = src->h; unsigned char *ptr; if (xc + radius < 0 || yc + radius < 0) return; if (xc - radius >= w || yc - radius >= h) return; if (radius <= 0) return; ptr = (unsigned char *)(src + 1); src->dirty = 1; ptr += (w * yc + xc) << 2; if (radius == 1) { pixel(col, ptr); return; } y1 = -radius; y2 = radius; x1 = -radius; x2 = radius; if (yc - radius < 0) y1 = -yc; if (xc - radius < 0) x1 = -xc; if (xc + radius >= w) x2 = w - xc - 1; if (yc + radius >= h) y2 = h - yc - 1; for (y = y1; y <= y2; y ++) { unsigned char *ptrl = ptr + ((y * w + x1) << 2); for (x = x1; x <= x2; x++) { if (x*x + y*y < r2 - 1) pixel(col, ptrl); ptrl += 4; } } } static void circle(struct lua_pixels *src, int xc, int yc, int rr, int r, int g, int b, int a) { int x = -rr, y = 0, err = 2 - 2 * rr; unsigned char *ptr = (unsigned char *)(src + 1); unsigned char col[4] = { r, g, b, a }; int w = src->w, h = src->h; if (rr <= 0) return; if (xc + rr < 0 || yc + rr < 0) return; if (xc - rr >= w || yc - rr >= h) return; src->dirty = 1; ptr += (w * yc + xc) * 4; if (xc - rr >= 0 && xc + rr < w && yc - rr >=0 && yc + rr < h) { do { int xmy = (x - y * w) * 4; int yax = (y + x * w) * 4; pixel(col, ptr - xmy); pixel(col, ptr - yax); pixel(col, ptr + xmy); pixel(col, ptr + yax); rr = err; if (rr <= y) err += ++y * 2 + 1; if (rr > x || err > y) err += ++x * 2 + 1; } while (x < 0); return; } /* slow */ do { int xmy = (x - y * w) * 4; int yax = (y + x * w) * 4; if (((xc - x) | (w - xc + x - 1) | (yc + y) | (h - yc - y - 1)) >= 0) pixel(col, ptr - xmy); if (((xc - y) | (w - xc + y - 1) | (yc - x) | (h - yc + x - 1)) >= 0) pixel(col, ptr - yax); if (((xc + x) | (w - xc - x - 1) | (yc - y) | (h - yc + y - 1)) >= 0) pixel(col, ptr + xmy); if (((xc + y) | (w - xc - y - 1) | (yc + x) | (h - yc - x - 1)) >= 0) pixel(col, ptr + yax); rr = err; if (rr <= y) err += ++y * 2 + 1; if (rr > x || err > y) err += ++x * 2 + 1; } while (x < 0); } static void circleAA(struct lua_pixels *src, int xc, int yc, int rr, int r, int g, int b, int a) { int p1, p2, p3, p4; int x = -rr, y = 0, x2, e2, err = 2 - 2 * rr; unsigned char *ptr = (unsigned char *)(src + 1); unsigned char col[4] = { r, g, b, a }; int w = src->w, h = src->h; if (rr <= 0) return; if (xc + rr < 0 || yc + rr < 0) return; if (xc - rr >= w || yc - rr >= h) return; src->dirty = 1; rr = 1 - err; ptr += (w * yc + xc) * 4; do { int i = 255 * abs(err - 2 *(x + y)-2) / rr; int xmy = (x - y * w) * 4; int yax = (y + x * w) * 4; col[3] = ((255 - i) * a) >> 8; p1 = 0; p2 = 0; p3 = 0; p4 = 0; if (((xc - x) | (w - xc + x - 1) | (yc + y) | (h - yc - y - 1)) >= 0) { pixel(col, ptr - xmy); p1 = 1; } if (((xc - y) | (w - xc + y - 1) | (yc - x) | (h - yc + x - 1)) >= 0) { pixel(col, ptr - yax); p2 = 1; } if (((xc + x) | (w - xc - x - 1) | (yc - y) | (h - yc + y - 1)) >= 0) { pixel(col, ptr + xmy); p3 = 1; } if (((xc + y) | (w - xc - y - 1) | (yc + x) | (h - yc - x - 1)) >= 0) { pixel(col, ptr + yax); p4 = 1; } e2 = err; x2 = x; if (err + y > 0) { i = 255 * (err - 2 * x - 1) / rr; if (i < 256) { col[3] = ((255 - i) * a) >> 8; if (p1 && yc + y + 1 < h) pixel(col, ptr - xmy + w * 4); if (p2 && xc - y - 1 >= 0) pixel(col, ptr - yax - 4); if (p3 && yc - y - 1 >= 0) pixel(col, ptr + xmy - w * 4); if (p4 && xc + y < w) pixel(col, ptr + yax + 4); } err += ++x * 2 + 1; } if (e2 + x <= 0) { i = 255 * (2 * y + 3 - e2) / rr; if (i < 256) { col[3] = ((255 - i) * a) >> 8; if (p1 && xc - x2 - 1 >= 0) pixel(col, ptr - xmy - 4); if (p2 && yc - x2 - 1 >= 0) pixel(col, ptr - yax - w * 4); if (p3 && xc + x2 + 1 < w) pixel(col, ptr + xmy + 4); if (p4 && yc + x2 + 1 < h) pixel(col, ptr + yax + w * 4); } err += ++y * 2 + 1; } } while (x < 0); } static int pixels_fill(lua_State *L) { int x = 0, y = 0, w = 0, h = 0, r = 0, g = 0, b = 0, a = 255; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; b = luaL_optnumber(L, 8, -1); if (b < 0) { r = luaL_optnumber(L, 2, 0); g = luaL_optnumber(L, 3, 0); b = luaL_optnumber(L, 4, 0); a = luaL_optnumber(L, 5, 255); } else { x = luaL_optnumber(L, 2, 0); y = luaL_optnumber(L, 3, 0); w = luaL_optnumber(L, 4, 0); h = luaL_optnumber(L, 5, 0); r = luaL_optnumber(L, 6, 0); g = luaL_optnumber(L, 7, 0); b = luaL_optnumber(L, 8, 0); a = luaL_optnumber(L, 9, 255); } _fill(src, x, y, w, h, r, g, b, a, (a == 255)?PXL_BLEND_COPY:PXL_BLEND_BLEND); return 0; } static int pixels_clear(lua_State *L) { int x = 0, y = 0, w = 0, h = 0, r = 0, g = 0, b = 0, a = 0; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; b = luaL_optnumber(L, 8, -1); if (b < 0) { r = luaL_optnumber(L, 2, 0); g = luaL_optnumber(L, 3, 0); b = luaL_optnumber(L, 4, 0); a = luaL_optnumber(L, 5, 0); } else { x = luaL_optnumber(L, 2, 0); y = luaL_optnumber(L, 3, 0); w = luaL_optnumber(L, 4, 0); h = luaL_optnumber(L, 5, 0); r = luaL_optnumber(L, 6, 0); g = luaL_optnumber(L, 7, 0); b = luaL_optnumber(L, 8, 0); a = luaL_optnumber(L, 9, 0); } _fill(src, x, y, w, h, r, g, b, a, PXL_BLEND_COPY); return 0; } static int pixels_triangle(lua_State *L) { int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0, r = 0, g = 0, b = 0, a = 0; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; x0 = luaL_optnumber(L, 2, 0); y0 = luaL_optnumber(L, 3, 0); x1 = luaL_optnumber(L, 4, 0); y1 = luaL_optnumber(L, 5, 0); x2 = luaL_optnumber(L, 6, 0); y2 = luaL_optnumber(L, 7, 0); #define XOR_SWAP(x,y) x=x^y; y=x^y; x=x^y; if (orient2d(x0, y0, x1, y1, x2, y2) < 0) { XOR_SWAP(x1, x2) XOR_SWAP(y1, y2) } #undef XOR_SWAP r = luaL_optnumber(L, 8, 0); g = luaL_optnumber(L, 9, 0); b = luaL_optnumber(L, 10, 0); a = luaL_optnumber(L, 11, 255); triangle(src, x0, y0, x1, y1, x2, y2, r, g, b, a); return 0; } static int pixels_line(lua_State *L) { int x1 = 0, y1 = 0, x2 = 0, y2 = 0, r = 0, g = 0, b = 0, a = 255; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; x1 = luaL_optnumber(L, 2, 0); y1 = luaL_optnumber(L, 3, 0); x2 = luaL_optnumber(L, 4, 0); y2 = luaL_optnumber(L, 5, 0); r = luaL_optnumber(L, 6, 0); g = luaL_optnumber(L, 7, 0); b = luaL_optnumber(L, 8, 0); a = luaL_optnumber(L, 9, 255); line(src, x1, y1, x2, y2, r, g, b, a); return 0; } static int pixels_lineAA(lua_State *L) { int x1 = 0, y1 = 0, x2 = 0, y2 = 0, r = 0, g = 0, b = 0, a = 255; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; x1 = luaL_optnumber(L, 2, 0); y1 = luaL_optnumber(L, 3, 0); x2 = luaL_optnumber(L, 4, 0); y2 = luaL_optnumber(L, 5, 0); r = luaL_optnumber(L, 6, 0); g = luaL_optnumber(L, 7, 0); b = luaL_optnumber(L, 8, 0); a = luaL_optnumber(L, 9, 255); lineAA(src, x1, y1, x2, y2, r, g, b, a); return 0; } static int pixels_circle(lua_State *L) { int xc = 0, yc = 0, rr = 0, r = 0, g = 0, b = 0, a = 255; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; xc = luaL_optnumber(L, 2, 0); yc = luaL_optnumber(L, 3, 0); rr = luaL_optnumber(L, 4, 0); r = luaL_optnumber(L, 5, 0); g = luaL_optnumber(L, 6, 0); b = luaL_optnumber(L, 7, 0); a = luaL_optnumber(L, 8, 255); circle(src, xc, yc, rr, r, g, b, a); return 0; } static int pixels_circleAA(lua_State *L) { int xc = 0, yc = 0, rr = 0, r = 0, g = 0, b = 0, a = 255; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; xc = luaL_optnumber(L, 2, 0); yc = luaL_optnumber(L, 3, 0); rr = luaL_optnumber(L, 4, 0); r = luaL_optnumber(L, 5, 0); g = luaL_optnumber(L, 6, 0); b = luaL_optnumber(L, 7, 0); a = luaL_optnumber(L, 8, 255); circleAA(src, xc, yc, rr, r, g, b, a); return 0; } static int pixels_fill_circle(lua_State *L) { int xc = 0, yc = 0, rr = 0, r = 0, g = 0, b = 0, a = 255; struct lua_pixels *src; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; xc = luaL_optnumber(L, 2, 0); yc = luaL_optnumber(L, 3, 0); rr = luaL_optnumber(L, 4, 0); r = luaL_optnumber(L, 5, 0); g = luaL_optnumber(L, 6, 0); b = luaL_optnumber(L, 7, 0); a = luaL_optnumber(L, 8, 255); fill_circle(src, xc, yc, rr, r, g, b, a); return 0; } struct lua_point { int x; int y; int nodex; }; /* http://alienryderflex.com/polygon_fill/ public-domain code by Darel Rex Finley, 2007 */ static void fill_poly(struct lua_pixels *src, struct lua_point *v, int nr, unsigned char *col) { unsigned char *ptr = (unsigned char *)(src + 1), *ptr1; int y, x, xmin, xmax, ymin, ymax, swap, w; int nodes = 0, j, i; xmin = v[0].x; xmax = v[0].x; ymin = v[0].y; ymax = v[0].y; for (i = 0; i < nr; i++) { if (v[i].x < xmin) xmin = v[i].x; if (v[i].x > xmax) xmax = v[i].x; if (v[i].y < ymin) ymin = v[i].y; if (v[i].y > ymax) ymax = v[i].y; } if (ymin < 0) ymin = 0; if (xmin < 0) xmin = 0; if (xmax >= src->w) xmax = src->w; if (ymax >= src->h) ymax = src->h; ptr += (ymin * src->w) << 2; for (y = ymin; y < ymax; y ++) { nodes = 0; j = nr - 1; for (i = 0; i < nr; i++) { if ((v[i].y < y && v[j].y >= y) || (v[j].y < y && v[i].y >= y)) { v[nodes ++].nodex = v[i].x + ((y - v[i].y) * (v[j].x - v[i].x)) / (v[j].y - v[i].y); } j = i; } if (nodes < 2) goto skip; i = 0; while (i < nodes - 1) { /* sort */ if (v[i].nodex > v[i + 1].nodex) { swap = v[i].nodex; v[i].nodex = v[i + 1].nodex; v[i + 1].nodex = swap; if (i) i --; } else { i ++; } } for (i = 0; i < nodes; i += 2) { if (v[i].nodex >= xmax) break; if (v[i + 1].nodex > xmin) { if (v[i].nodex < xmin) v[i].nodex = xmin; if (v[i + 1].nodex > xmax) v[i + 1].nodex = xmax; // hline src->dirty = 1; w = (v[i + 1].nodex - v[i].nodex); ptr1 = ptr + v[i].nodex * 4; for (x = 0; x < w; x ++) { pixel(col, ptr1); ptr1 += 4; } } } skip: ptr += src->w * 4; } } static int pixels_fill_poly(lua_State *L) { int nr, i; struct lua_pixels *src; struct lua_point *v; unsigned char col[4]; src = (struct lua_pixels*)lua_touserdata(L, 1); if (!src || src->type != PIXELS_MAGIC) return 0; luaL_checktype(L, 2, LUA_TTABLE); #if LUA_VERSION_NUM >= 502 nr = lua_rawlen(L, 2); #else nr = lua_objlen(L, 2); #endif if (nr < 6) return 0; col[0] = luaL_optnumber(L, 3, 0); col[1] = luaL_optnumber(L, 4, 0); col[2] = luaL_optnumber(L, 5, 0); col[3] = luaL_optnumber(L, 6, 255); nr /= 2; v = malloc(sizeof(*v) * nr); if (!v) return 0; lua_pushvalue(L, 2); for (i = 0; i < nr; i++) { lua_pushinteger(L, (i * 2) + 1); lua_gettable(L, -2); v[i].x = lua_tonumber(L, -1); lua_pop(L, 1); lua_pushinteger(L, (i * 2) + 2); lua_gettable(L, -2); v[i].y = lua_tonumber(L, -1); lua_pop(L, 1); } lua_pop(L, 1); fill_poly(src, v, nr, col); free(v); return 0; } static int pixels_value(lua_State *L) { struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1); int x = luaL_optnumber(L, 2, -1); int y = luaL_optnumber(L, 3, -1); int r = luaL_optnumber(L, 4, -1); int g = 0, b = 0, a = 0; unsigned char *ptr; if (r != -1) { g = luaL_optnumber(L, 5, 0); b = luaL_optnumber(L, 6, 0); a = luaL_optnumber(L, 7, 255); } if (x < 0 || y < 0) return 0; if (!hdr || hdr->type != PIXELS_MAGIC) return 0; if (x >= hdr->w || y >= hdr->h) return 0; ptr = (unsigned char*)(hdr + 1); ptr += ((y * hdr->w + x) << 2); if (r == -1) { lua_pushinteger(L, *(ptr ++)); lua_pushinteger(L, *(ptr ++)); lua_pushinteger(L, *(ptr ++)); lua_pushinteger(L, *ptr); return 4; } hdr->dirty = 1; *(ptr ++) = r; *(ptr ++) = g; *(ptr ++) = b; *(ptr) = a; return 0; } static int pixels_pixel(lua_State *L) { struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1); int x = luaL_optnumber(L, 2, -1); int y = luaL_optnumber(L, 3, -1); int r = luaL_optnumber(L, 4, -1); int g, b, a; unsigned char col[4]; unsigned char *ptr; if (r == -1) return 0; g = luaL_optnumber(L, 5, 0); b = luaL_optnumber(L, 6, 0); a = luaL_optnumber(L, 7, 255); if (x < 0 || y < 0) return 0; if (!hdr || hdr->type != PIXELS_MAGIC) return 0; if (x >= hdr->w || y >= hdr->h) return 0; hdr->dirty = 1; ptr = (unsigned char*)(hdr + 1); ptr += ((y * hdr->w + x) << 2); col[0] = r; col[1] = g; col[2] = b; col[3] = a; pixel(col, ptr); return 0; } static img_t pixels_img(struct lua_pixels *hdr) { int w, h, ww, hh, xx, yy, dx, dy; unsigned char *ptr, *optr = NULL; unsigned char *p; img_t img; if (!hdr) return NULL; if (hdr->type != PIXELS_MAGIC) return NULL; img = hdr->img; if (!img) return NULL; if (hdr->direct || !hdr->dirty) return img; hdr->dirty = 0; ptr = (unsigned char*)(hdr + 1); ww = gfx_img_w(img); hh = gfx_img_h(img); w = hdr->w; h = hdr->h; p = gfx_get_pixels(img); if (!p) return NULL; dy = 0; for (yy = 0; yy < hh; yy++) { unsigned char *ptrl = ptr; dx = 0; if (optr) { memcpy(p, optr, ww * 4); p += ww * 4; } else { optr = p; for (xx = 0; xx < ww; xx++) { memcpy(p, ptrl, 4); p += 4; dx += w; while (dx >= ww) { dx -= ww; ptrl += 4; } } } dy += h; while (dy >= hh) { dy -= hh; ptr += (w << 2); optr = NULL; } } gfx_put_pixels(img); return img; } static int pixels_destroy(lua_State *L) { struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1); if (!hdr || hdr->type != PIXELS_MAGIC) return 0; if (hdr->img) gfx_free_image(hdr->img); return 0; } static int pixels_new(lua_State *L, int w, int h, float scale, img_t src) { int ww, hh, direct = 0; img_t img2 = NULL, img; size_t size; float v = game_theme.scale; struct lua_pixels *hdr; if (src) { w = gfx_img_w(src); h = gfx_img_h(src); img2 = gfx_new_rgba(w, h); if (!img2) return 0; gfx_copy_from(src, 0, 0, w, h, img2, 0, 0); } if (w <=0 || h <= 0) return 0; ww = w; hh = h; if (v != 1.0f) { ww = ceil((float)w * v); hh = ceil((float)h * v); } ww = ceil((float)ww * scale); hh = ceil((float)hh * scale); size = w * h * 4; hdr = lua_newuserdata(L, sizeof(*hdr) + size); if (!hdr) { if (img2) gfx_free_image(img2); return 0; } hdr->type = PIXELS_MAGIC; hdr->img = NULL; hdr->w = w; hdr->h = h; hdr->scale = scale; hdr->size = size; hdr->dirty = 0; if (ww == w && hh == h) { /* direct map */ direct = 1; img = gfx_new_from(ww, hh, (unsigned char*)(hdr + 1)); } else { img = gfx_new_rgba(ww, hh); } hdr->direct = direct; if (!img) { fprintf(stderr, "Error: no free memory\n"); memset(hdr, 0, sizeof(*hdr) + size); if (img2) gfx_free_image(img2); return 1; } hdr->img = img; if (img2) { unsigned char *ptr = gfx_get_pixels(img2); if (ptr) { memcpy(hdr + 1, ptr, size); gfx_put_pixels(img2); } gfx_free_image(img2); } else { memset(hdr + 1, 0, size); } hdr->dirty = 1; luaL_getmetatable(L, "pixels metatable"); lua_setmetatable(L, -2); return 1; } static int luaB_pixels_sprite(lua_State *L) { const char *fname; int w, h, rc; float scale; img_t img = NULL; if (!lua_isnumber(L, 1)) { fname = luaL_optstring(L, 1, NULL); if (!fname) return 0; img = gfx_load_image((char*)fname); if (!img) return 0; // if (!cache_have(gfx_image_cache(), img)) // v = 1.0f; /* do not scale sprites! */ w = 0; h = 0; scale = luaL_optnumber(L, 2, 1.0f); } else { w = luaL_optnumber(L, 1, -1); h = luaL_optnumber(L, 2, -1); scale = luaL_optnumber(L, 3, 1.0f); } rc = pixels_new(L, w, h, scale, img); if (img) gfx_free_image(img); return rc; } static int pixels_scale(lua_State *L) { img_t img, img2; int rc; struct lua_pixels *src = (struct lua_pixels*)lua_touserdata(L, 1); float xs = luaL_optnumber(L, 2, 0); float ys = luaL_optnumber(L, 3, 0); int smooth = lua_toboolean(L, 4); if (!src || src->type != PIXELS_MAGIC) return 0; if (ys == 0) ys = xs; img = gfx_new_from(src->w, src->h, (unsigned char*)(src + 1)); if (!img) return 0; img2 = gfx_scale(img, xs, ys, smooth); gfx_free_image(img); rc = pixels_new(L, 0, 0, src->scale, img2); gfx_free_image(img2); return rc; } static int pixels_rotate(lua_State *L) { img_t img, img2; int rc; struct lua_pixels *src = (struct lua_pixels*)lua_touserdata(L, 1); float angle = luaL_optnumber(L, 2, 0); int smooth = lua_toboolean(L, 3); if (!src || src->type != PIXELS_MAGIC) return 0; img = gfx_new_from(src->w, src->h, (unsigned char*)(src + 1)); if (!img) return 0; img2 = gfx_rotate(img, angle, smooth); gfx_free_image(img); rc = pixels_new(L, 0, 0, src->scale, img2); gfx_free_image(img2); return rc; } /* ** Creates pixels metatable. */ static int pixels_create_meta (lua_State *L) { luaL_newmetatable (L, "pixels metatable"); lua_pushstring (L, "__index"); lua_newtable(L); lua_pushstring (L, "val"); lua_pushcfunction (L, pixels_value); lua_settable(L, -3); lua_pushstring (L, "pixel"); lua_pushcfunction (L, pixels_pixel); lua_settable(L, -3); lua_pushstring (L, "size"); lua_pushcfunction (L, pixels_size); lua_settable(L, -3); lua_pushstring(L, "copy"); lua_pushcfunction (L, pixels_copy); lua_settable(L, -3); lua_pushstring(L, "blend"); lua_pushcfunction (L, pixels_blend); lua_settable(L, -3); lua_pushstring(L, "clear"); lua_pushcfunction (L, pixels_clear); lua_settable(L, -3); lua_pushstring(L, "fill"); lua_pushcfunction (L, pixels_fill); lua_settable(L, -3); lua_pushstring(L, "line"); lua_pushcfunction (L, pixels_line); lua_settable(L, -3); lua_pushstring(L, "lineAA"); lua_pushcfunction (L, pixels_lineAA); lua_settable(L, -3); lua_pushstring(L, "circle"); lua_pushcfunction (L, pixels_circle); lua_settable(L, -3); lua_pushstring(L, "circleAA"); lua_pushcfunction (L, pixels_circleAA); lua_settable(L, -3); lua_pushstring(L, "fill_circle"); lua_pushcfunction (L, pixels_fill_circle); lua_settable(L, -3); lua_pushstring(L, "fill_triangle"); lua_pushcfunction (L, pixels_triangle); lua_settable(L, -3); lua_pushstring(L, "fill_poly"); lua_pushcfunction (L, pixels_fill_poly); lua_settable(L, -3); lua_pushstring(L, "new_scaled"); lua_pushcfunction (L, pixels_scale); lua_settable(L, -3); lua_pushstring(L, "new_rotated"); lua_pushcfunction (L, pixels_rotate); lua_settable(L, -3); lua_settable(L, -3); lua_pushstring (L, "__gc"); lua_pushcfunction (L, pixels_destroy); lua_settable (L, -3); return 0; } static int luaB_noise1(lua_State *L) { float r; int px; float x = luaL_optnumber(L, 1, 0); px = luaL_optnumber(L, 2, 0); if (px > 0) { r = pnoise1(x, px); } else { r = noise1(x); } lua_pushnumber(L, r); return 1; } static int luaB_noise2(lua_State *L) { float r; int px; int py; float x = luaL_optnumber(L, 1, 0); float y = luaL_optnumber(L, 2, 0); px = luaL_optnumber(L, 3, 0); py = luaL_optnumber(L, 4, 0); if (px > 0 && py > 0) { r = pnoise2(x, y, px, py); } else { r = noise2(x, y); } lua_pushnumber(L, r); return 1; } static int luaB_noise3(lua_State *L) { float r; int px; int py; int pz; float x = luaL_optnumber(L, 1, 0); float y = luaL_optnumber(L, 2, 0); float z = luaL_optnumber(L, 3, 0); px = luaL_optnumber(L, 4, 0); py = luaL_optnumber(L, 5, 0); pz = luaL_optnumber(L, 6, 0); if (px > 0 && py > 0 && pz > 0) { r = pnoise3(x, y, z, px, py, pz); } else { r = noise3(x, y, z); } lua_pushnumber(L, r); return 1; } static int luaB_noise4(lua_State *L) { float r; int px; int py; int pz; int pw; float x = luaL_optnumber(L, 1, 0); float y = luaL_optnumber(L, 2, 0); float z = luaL_optnumber(L, 3, 0); float w = luaL_optnumber(L, 4, 0); px = luaL_optnumber(L, 5, 0); py = luaL_optnumber(L, 6, 0); pz = luaL_optnumber(L, 7, 0); pw = luaL_optnumber(L, 8, 0); if (px > 0 && py > 0 && pz > 0 && pw > 0) { r = pnoise4(x, y, z, w, px, py, pz, pw); } else { r = noise4(x, y, z, w); } lua_pushnumber(L, r); return 1; } static int callback_ref = 0; static int render_callback_dirty = 0; int instead_render_callback_dirty(int fl) { int rc = render_callback_dirty; if (!callback_ref || game_freezed()) return 0; if (fl != -1) render_callback_dirty = fl; return rc; } void instead_render_callback(void) { if (!callback_ref || game_freezed() || render_callback_dirty == -1) return; game_cursor(CURSOR_CLEAR); instead_lock(); lua_rawgeti(instead_lua(), LUA_REGISTRYINDEX, callback_ref); in_callback ++; if (instead_pcall(instead_lua(), 0)) { /* on any error */ luaL_unref(instead_lua(), LUA_REGISTRYINDEX, callback_ref); callback_ref = 0; } in_callback --; instead_clear(); instead_unlock(); if (game_pict_modify(NULL)) render_callback_dirty = -1; game_cursor(CURSOR_DRAW); return; } static int luaB_after_callback(lua_State *L) { if (!opt_owntheme) { lua_pushboolean(L, 0); return 1; } if (callback_ref) luaL_unref(L, LUA_REGISTRYINDEX, callback_ref); callback_ref = 0; if (lua_isfunction(L, 1)) callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); lua_pushboolean(L, 0); return 1; } static int luaB_screen_size(lua_State *L) { int w = 0; int h = 0; gfx_get_max_mode(&w, &h, MODE_ANY); lua_pushinteger(L, w); lua_pushinteger(L, h); return 2; } static int luaB_screen_dpi(lua_State *L) { lua_pushnumber(L, gfx_get_dpi()); return 1; } static const luaL_Reg sprites_funcs[] = { {"instead_font_load", luaB_load_font}, {"instead_font_free", luaB_free_font}, {"instead_font_scaled_size", luaB_font_size_scaled}, {"instead_sprite_load", luaB_load_sprite}, {"instead_sprite_text", luaB_text_sprite}, {"instead_sprite_free", luaB_free_sprite}, {"instead_sprites_free", luaB_free_sprites}, {"instead_sprite_draw", luaB_draw_sprite}, {"instead_sprite_copy", luaB_copy_sprite}, {"instead_sprite_compose", luaB_compose_sprite}, {"instead_sprite_fill", luaB_fill_sprite}, {"instead_sprite_dup", luaB_dup_sprite}, {"instead_sprite_alpha", luaB_alpha_sprite}, {"instead_sprite_colorkey", luaB_colorkey_sprite}, {"instead_sprite_size", luaB_sprite_size}, {"instead_sprite_scale", luaB_scale_sprite}, {"instead_sprite_rotate", luaB_rotate_sprite}, {"instead_sprite_text_size", luaB_text_size}, {"instead_sprite_pixel", luaB_pixel_sprite}, {"instead_sprite_pixels", luaB_pixels_sprite}, {"instead_theme_var", luaB_theme_var}, {"instead_theme_name", luaB_theme_name}, {"instead_ticks", luaB_get_ticks}, {"instead_busy", luaB_stead_busy}, {"instead_direct", luaB_instead_direct}, {"instead_mouse_pos", luaB_mouse_pos}, {"instead_mouse_filter", luaB_mouse_filter}, {"instead_mouse_show", luaB_mouse_show}, {"instead_finger_pos", luaB_finger_pos}, {"instead_themespath", luaB_get_themespath}, {"instead_noise1", luaB_noise1}, {"instead_noise2", luaB_noise2}, {"instead_noise3", luaB_noise3}, {"instead_noise4", luaB_noise4}, {"instead_screen_size", luaB_screen_size}, {"instead_screen_dpi", luaB_screen_dpi}, {"instead_render_callback", luaB_after_callback}, {NULL, NULL} }; static int sprites_done(void) { if (callback_ref) { luaL_unref(instead_lua(), LUA_REGISTRYINDEX, callback_ref); callback_ref = 0; render_callback_dirty = 0; } sprites_free(); return 0; } static int sprites_init(void) { char path[PATH_MAX]; if (pixels_create_meta(instead_lua())) return -1; instead_api_register(sprites_funcs); snprintf(path, sizeof(path), "%s/%s", instead_stead_path(), "/ext/sprites.lua"); return instead_loadfile(dirpath(path)); } static int sprites_err(void) { if (callback_ref) { luaL_unref(instead_lua(), LUA_REGISTRYINDEX, callback_ref); callback_ref = 0; } return 0; } static struct instead_ext ext = { .init = sprites_init, .done = sprites_done, .err = sprites_err, }; int instead_sprites_init(void) { return instead_extension(&ext); } instead-3.5.2+dfsg/src/instead_timer.c000066400000000000000000000055231467622671600176770ustar00rootroot00000000000000/* * Copyright 2009-2017 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" /* the Lua interpreter */ static gtimer_t instead_timer = NULL_TIMER; static int volatile instead_timer_nr = 0; static int instead_fn(int interval, void *p); static void instead_timer_do(void *data) { char *p; instead_timer_nr = 0; instead_lock(); if (game_paused() || !curgame_dir || instead_timer == NULL_TIMER) { instead_unlock(); return; } if (instead_function("stead.timer", NULL)) { instead_clear(); instead_unlock(); return; } p = instead_retval(0); instead_clear(); instead_unlock(); if (!p) return; game_cmd(p, 0); free(p); game_cursor(CURSOR_ON); } static int instead_fn(int interval, void *p) { if (instead_timer_nr > 0) { return interval; /* framedrop */ } instead_timer_nr ++; push_user_event(instead_timer_do, NULL); return interval; } static int luaB_set_timer(lua_State *L) { const char *delay = luaL_optstring(L, 1, NULL); int d; gfx_del_timer(instead_timer); instead_timer = NULL_TIMER; if (!delay) d = 0; else d = atoi(delay); if (!d) return 0; instead_timer_nr = 0; instead_timer = gfx_add_timer(d, instead_fn, NULL); return 0; } static const luaL_Reg timer_funcs[] = { {"instead_timer", luaB_set_timer}, {NULL, NULL} }; static int timer_done(void) { gfx_del_timer(instead_timer); instead_timer = NULL_TIMER; return 0; } static int timer_init(void) { char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", instead_stead_path(), "/ext/timer.lua"); instead_api_register(timer_funcs); return instead_loadfile(dirpath(path)); } static struct instead_ext ext = { .err = timer_done, .done = timer_done, /* to avoid loop errors */ .init = timer_init, }; int instead_timer_init(void) { return instead_extension(&ext); } instead-3.5.2+dfsg/src/internals.h000066400000000000000000000003451467622671600170510ustar00rootroot00000000000000#ifdef __IPHONEOS__ #include "ios.h" #endif #include "utils.h" #include "graphics.h" #include "sound.h" #include "game.h" #include "themes.h" #include "menu.h" #include "config.h" #include "input.h" #include "instead/instead.h" instead-3.5.2+dfsg/src/ioapi.c000066400000000000000000000170021467622671600161440ustar00rootroot00000000000000#ifdef _USE_UNPACK /* ioapi.h -- IO base function header for compress/uncompress .zip part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt */ #if (defined(_WIN32)) #define _CRT_SECURE_NO_WARNINGS #endif #include "ioapi.h" voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) { if (pfilefunc->zfile_func64.zopen64_file != NULL) return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); else { return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); } } long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); else { uLong offsetTruncated = (uLong)offset; if (offsetTruncated != offset) return -1; else return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); } } ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) { if (pfilefunc->zfile_func64.zseek64_file != NULL) return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); else { uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); if ((tell_uLong) == ((uLong)-1)) return (ZPOS64_T)-1; else return tell_uLong; } } void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) { p_filefunc64_32->zfile_func64.zopen64_file = NULL; p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; /* p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; */ p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; p_filefunc64_32->zfile_func64.ztell64_file = NULL; p_filefunc64_32->zfile_func64.zseek64_file = NULL; p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; } static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) mode_fopen = "rb"; else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) mode_fopen = "r+b"; else if (mode & ZLIB_FILEFUNC_MODE_CREATE) mode_fopen = "wb"; if ((filename!=NULL) && (mode_fopen != NULL)) file = fopen(filename, mode_fopen); return file; } static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) { FILE* file = NULL; const char* mode_fopen = NULL; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) mode_fopen = "rb"; else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) mode_fopen = "r+b"; else if (mode & ZLIB_FILEFUNC_MODE_CREATE) mode_fopen = "wb"; if ((filename!=NULL) && (mode_fopen != NULL)) file = fopen64((const char*)filename, mode_fopen); return file; } static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) { uLong ret; ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); return ret; } static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong ret; ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); return ret; } static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) { long ret; ret = ftell((FILE *)stream); return ret; } static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) { ZPOS64_T ret; ret = ftello64((FILE *)stream); return ret; } static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) { int fseek_origin=0; long ret; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : fseek_origin = SEEK_CUR; break; case ZLIB_FILEFUNC_SEEK_END : fseek_origin = SEEK_END; break; case ZLIB_FILEFUNC_SEEK_SET : fseek_origin = SEEK_SET; break; default: return -1; } ret = 0; if (fseek((FILE *)stream, offset, fseek_origin) != 0) ret = -1; return ret; } static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) { int fseek_origin=0; long ret; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : fseek_origin = SEEK_CUR; break; case ZLIB_FILEFUNC_SEEK_END : fseek_origin = SEEK_END; break; case ZLIB_FILEFUNC_SEEK_SET : fseek_origin = SEEK_SET; break; default: return -1; } ret = 0; if(fseeko64((FILE *)stream, offset, fseek_origin) != 0) ret = -1; return ret; } static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) { int ret; ret = fclose((FILE *)stream); return ret; } static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) { int ret; ret = ferror((FILE *)stream); return ret; } void fill_fopen_filefunc (pzlib_filefunc_def) zlib_filefunc_def* pzlib_filefunc_def; { pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->ztell_file = ftell_file_func; pzlib_filefunc_def->zseek_file = fseek_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = fopen64_file_func; pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->ztell64_file = ftell64_file_func; pzlib_filefunc_def->zseek64_file = fseek64_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->opaque = NULL; } #endif instead-3.5.2+dfsg/src/ioapi.h000066400000000000000000000155571467622671600161660ustar00rootroot00000000000000/* ioapi.h -- IO base function header for compress/uncompress .zip part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt Changes Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. More if/def section may be needed to support other platforms Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. (but you should use iowin32.c for windows instead) */ #ifndef _ZLIBIOAPI64_H #define _ZLIBIOAPI64_H /* we need no > 2Gb games */ #define USE_FILE32API #if (!defined(_WIN32)) && (!defined(WIN32)) /* Linux needs this to support file operation on files larger then 4+GB But might need better if/def to select just the platforms that needs them. */ #ifndef __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64 #endif #ifndef __USE_LARGEFILE64 #define __USE_LARGEFILE64 #endif #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #ifndef _FILE_OFFSET_BIT #define _FILE_OFFSET_BIT 64 #endif #endif #include #include #include "zlib.h" #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif #if defined(USE_FILE32API) #define fopen64 fopen #define ftello64 ftell #define fseeko64 fseek #else #ifdef _MSC_VER #define fopen64 fopen #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) #define ftello64 _ftelli64 #define fseeko64 _fseeki64 #else // old MSC #define ftello64 ftell #define fseeko64 fseek #endif #endif #endif /* #ifndef ZPOS64_T #ifdef _WIN32 #define ZPOS64_T fpos_t #else #include #define ZPOS64_T uint64_t #endif #endif */ #ifdef HAVE_MINIZIP64_CONF_H #include "mz64conf.h" #endif /* a type choosen by DEFINE */ #ifdef HAVE_64BIT_INT_CUSTOM typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; #else #ifdef HAS_STDINT_H #include "stdint.h" typedef uint64_t ZPOS64_T; #else #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 ZPOS64_T; #else typedef unsigned long long int ZPOS64_T; #endif #endif #endif #ifdef __cplusplus extern "C" { #endif #define ZLIB_FILEFUNC_SEEK_CUR (1) #define ZLIB_FILEFUNC_SEEK_END (2) #define ZLIB_FILEFUNC_SEEK_SET (0) #define ZLIB_FILEFUNC_MODE_READ (1) #define ZLIB_FILEFUNC_MODE_WRITE (2) #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) #define ZLIB_FILEFUNC_MODE_EXISTING (4) #define ZLIB_FILEFUNC_MODE_CREATE (8) #ifndef ZCALLBACK #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) #define ZCALLBACK CALLBACK #else #define ZCALLBACK #endif #endif typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); /* here is the "old" 32 bits structure structure */ typedef struct zlib_filefunc_def_s { open_file_func zopen_file; read_file_func zread_file; write_file_func zwrite_file; tell_file_func ztell_file; seek_file_func zseek_file; close_file_func zclose_file; testerror_file_func zerror_file; voidpf opaque; } zlib_filefunc_def; typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); typedef struct zlib_filefunc64_def_s { open64_file_func zopen64_file; read_file_func zread_file; write_file_func zwrite_file; tell64_file_func ztell64_file; seek64_file_func zseek64_file; close_file_func zclose_file; testerror_file_func zerror_file; voidpf opaque; } zlib_filefunc64_def; void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); /* now internal definition, only for zip.c and unzip.h */ typedef struct zlib_filefunc64_32_def_s { zlib_filefunc64_def zfile_func64; open_file_func zopen32_file; tell_file_func ztell32_file; seek_file_func zseek32_file; } zlib_filefunc64_32_def; #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) /* #define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) #define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) */ #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); #define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) #define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) #define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) #ifdef __cplusplus } #endif #endif instead-3.5.2+dfsg/src/ios.h000066400000000000000000000005161467622671600156440ustar00rootroot00000000000000#ifndef _IOS_H_INCLUDED #define _IOS_H_INCLUDED #define VERSION "3.5.2" #define STEAD_PATH "__private__/stead" #define THEMES_PATH "__private__/themes" #define GAMES_PATH "__private__/games" #define ICON_PATH "__private__/icon" #define LANG_PATH "__private__/lang" extern int setup_inbox(void); extern void ios_cfg_init(void); #endif instead-3.5.2+dfsg/src/ios.m000066400000000000000000000132071467622671600156520ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "externals.h" #include "internals.h" static char save_path[PATH_MAX]; static char cfg_path[PATH_MAX]; static char local_games_path[PATH_MAX]; static char local_themes_path[PATH_MAX]; static char local_stead_path[PATH_MAX]; extern int setup_zip(const char *file, char *p); char *game_locale(void) { NSString * language = [[NSLocale preferredLanguages] objectAtIndex:0]; return strdup([language UTF8String]); } char *game_tmp_path(void) { static char tmp[PATH_MAX]; NSString * tmpdir = NSTemporaryDirectory(); snprintf(tmp, sizeof(tmp), "%s/instead-games", [tmpdir UTF8String]); tmp[sizeof(tmp) - 1] = 0; if (mkdir(tmp, S_IRWXU) && errno != EEXIST) return NULL; return tmp; } static char *inbox(void) { static char dir[PATH_MAX]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; snprintf(dir, sizeof(dir) - 1 , "%s/Inbox", [basePath UTF8String]); return dir; } int setup_inbox(void) { char path[PATH_MAX]; DIR *d; struct dirent *de; char *p; if (!path) return 0; d = opendir(inbox()); if (!d) return -1; while ((de = readdir(d))) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; snprintf(path, sizeof(path), "%s/%s", inbox(), de->d_name); path[sizeof(path) - 1] = 0; p = game_local_games_path(1); fprintf(stderr, "Install zip: %s\n", path); setup_zip(path, game_local_games_path(1)); unlink(path); } closedir(d); return 0; } char *appdir(void) { static char dir[PATH_MAX]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; snprintf(dir, sizeof(dir) - 1 , "%s/.instead", [basePath UTF8String]); return dir; } char *game_local_games_path(int cr) { char *app = appdir(); if (!app) return NULL; strcpy(local_games_path, app); if (cr) { if (mkdir(local_games_path, S_IRWXU) && errno != EEXIST) return NULL; } strcat(local_games_path,"/games"); if (cr) { if (mkdir(local_games_path, S_IRWXU) && errno != EEXIST) return NULL; } return local_games_path; } char *game_local_themes_path(void) { char *app = appdir(); if (!app) return NULL; snprintf(local_themes_path, sizeof(local_themes_path) - 1 , "%s/themes", app); return local_themes_path; } char *game_local_stead_path(void) { char *app = appdir(); if (!app) return NULL; snprintf(local_stead_path, sizeof(local_stead_path) - 1 , "%s/stead", app); return local_stead_path; } char *game_cfg_path(void) { char *app = appdir(); snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/", app); mkdir(cfg_path, S_IRWXU); snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/insteadrc", app); return cfg_path; } char *game_save_path(int cr, int nr) { char *app = appdir(); if (!curgame_dir) return NULL; if (!access("saves", R_OK)) { if (nr) snprintf(save_path, sizeof(save_path) - 1, "saves/save%d", nr); else snprintf(save_path, sizeof(save_path) - 1, "saves/autosave"); return save_path; } if (!app) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/", app); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/saves", app); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/", app, curgame_dir); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; if (nr) snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/save%d", app, curgame_dir, nr); else snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/autosave", app, curgame_dir); return save_path; } int debug_init(void) { return 0; } void debug_done() { } char *sdl_path(char *p) { unix_path(p); return p; } char *open_file_dialog(void) { #if 0 const char *filename; static char *file_name[PATH_MAX]; NSArray* fileTypes = [NSArray arrayWithObjects: @"zip", @"lua", @"idf", nil]; NSOpenPanel * panel = [NSOpenPanel openPanel]; [panel setCanChooseDirectories:NO]; [panel setCanChooseFiles:YES]; [panel setAllowsMultipleSelection:NO]; if ([panel runModalForTypes:fileTypes] == NSOKButton) { #ifdef __POWERPC__ filename = [[panel filename] cString]; #else filename = [[panel filename] cStringUsingEncoding:NSUTF8StringEncoding]; #endif strcpy(file_name, filename); return file_name; } #endif return NULL; } void rotate_landscape(void) { SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight"); if (UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)) { [[UIDevice currentDevice] setValue:@(UIDeviceOrientationLandscapeRight) forKey:@"orientation"]; } } void rotate_portrait(void) { SDL_SetHint(SDL_HINT_ORIENTATIONS, "Portrait PortraitUpsideDown"); if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { [[UIDevice currentDevice] setValue:@(UIDeviceOrientationPortrait) forKey:@"orientation"]; } } void unlock_rotation(void) { SDL_SetHint(SDL_HINT_ORIENTATIONS, "Portrait PortraitUpsideDown LandscapeLeft LandscapeRight"); } void ios_cfg_init(void) { BOOL is_iPhone = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone; opt_fsize = (is_iPhone) ? 5 : 0; } instead-3.5.2+dfsg/src/iowin32.c000066400000000000000000000272311467622671600163420ustar00rootroot00000000000000#ifdef _USE_UNPACK /* iowin32.c -- IO base function header for compress/uncompress .zip Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt */ #include #include "zlib.h" #include "ioapi.h" #include "iowin32.h" #ifndef INVALID_HANDLE_VALUE #define INVALID_HANDLE_VALUE (0xFFFFFFFF) #endif #ifndef INVALID_SET_FILE_POINTER #define INVALID_SET_FILE_POINTER ((DWORD)-1) #endif voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); typedef struct { HANDLE hf; int error; } WIN32FILE_IOWIN; static void win32_translate_open_mode(int mode, DWORD* lpdwDesiredAccess, DWORD* lpdwCreationDisposition, DWORD* lpdwShareMode, DWORD* lpdwFlagsAndAttributes) { *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) { *lpdwDesiredAccess = GENERIC_READ; *lpdwCreationDisposition = OPEN_EXISTING; *lpdwShareMode = FILE_SHARE_READ; } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) { *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; *lpdwCreationDisposition = OPEN_EXISTING; } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) { *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; *lpdwCreationDisposition = CREATE_ALWAYS; } } static voidpf win32_build_iowin(HANDLE hFile) { voidpf ret=NULL; if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) { WIN32FILE_IOWIN w32fiow; w32fiow.hf = hFile; w32fiow.error = 0; ret = malloc(sizeof(WIN32FILE_IOWIN)); if (ret==NULL) CloseHandle(hFile); else *((WIN32FILE_IOWIN*)ret) = w32fiow; } return ret; } voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); return win32_build_iowin(hFile); } voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); return win32_build_iowin(hFile); } voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); return win32_build_iowin(hFile); } voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) { const char* mode_fopen = NULL; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; HANDLE hFile = NULL; win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); if ((filename!=NULL) && (dwDesiredAccess != 0)) hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); return win32_build_iowin(hFile); } uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { if (!ReadFile(hFile, buf, size, &ret, NULL)) { DWORD dwErr = GetLastError(); if (dwErr == ERROR_HANDLE_EOF) dwErr = 0; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; } } return ret; } uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) { uLong ret=0; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { if (!WriteFile(hFile, buf, size, &ret, NULL)) { DWORD dwErr = GetLastError(); if (dwErr == ERROR_HANDLE_EOF) dwErr = 0; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; } } return ret; } long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) { long ret=-1; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); if (dwSet == INVALID_SET_FILE_POINTER) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = -1; } else ret=(long)dwSet; } return ret; } ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) { ZPOS64_T ret= (ZPOS64_T)-1; HANDLE hFile = NULL; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream)->hf; if (hFile) { LARGE_INTEGER li; li.QuadPart = 0; li.u.LowPart = SetFilePointer(hFile, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); if ( (li.LowPart == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = (ZPOS64_T)-1; } else ret=li.QuadPart; } return ret; } long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream) -> hf; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : dwMoveMethod = FILE_CURRENT; break; case ZLIB_FILEFUNC_SEEK_END : dwMoveMethod = FILE_END; break; case ZLIB_FILEFUNC_SEEK_SET : dwMoveMethod = FILE_BEGIN; break; default: return -1; } if (hFile != NULL) { DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); if (dwSet == INVALID_SET_FILE_POINTER) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = -1; } else ret=0; } return ret; } long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) { DWORD dwMoveMethod=0xFFFFFFFF; HANDLE hFile = NULL; long ret=-1; if (stream!=NULL) hFile = ((WIN32FILE_IOWIN*)stream)->hf; switch (origin) { case ZLIB_FILEFUNC_SEEK_CUR : dwMoveMethod = FILE_CURRENT; break; case ZLIB_FILEFUNC_SEEK_END : dwMoveMethod = FILE_END; break; case ZLIB_FILEFUNC_SEEK_SET : dwMoveMethod = FILE_BEGIN; break; default: return -1; } if (hFile) { LARGE_INTEGER* li = (LARGE_INTEGER*)&offset; DWORD dwSet = SetFilePointer(hFile, li->u.LowPart, &li->u.HighPart, dwMoveMethod); if (dwSet == INVALID_SET_FILE_POINTER) { DWORD dwErr = GetLastError(); ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ret = -1; } else ret=0; } return ret; } int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) { int ret=-1; if (stream!=NULL) { HANDLE hFile; hFile = ((WIN32FILE_IOWIN*)stream) -> hf; if (hFile != NULL) { CloseHandle(hFile); ret=0; } free(stream); } return ret; } int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) { int ret=-1; if (stream!=NULL) { ret = ((WIN32FILE_IOWIN*)stream) -> error; } return ret; } void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen_file = win32_open_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell_file = win32_tell_file_func; pzlib_filefunc_def->zseek_file = win32_seek_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) { pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->opaque = NULL; } #endif instead-3.5.2+dfsg/src/iowin32.h000066400000000000000000000015231467622671600163430ustar00rootroot00000000000000/* iowin32.h -- IO base function header for compress/uncompress .zip Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt */ #include #ifdef __cplusplus extern "C" { #endif void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); #ifdef __cplusplus } #endif instead-3.5.2+dfsg/src/macosx.m000066400000000000000000000110211467622671600163420ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include "externals.h" #include "internals.h" static char save_path[PATH_MAX]; static char cfg_path[PATH_MAX]; static char local_games_path[PATH_MAX]; static char local_themes_path[PATH_MAX]; static char local_stead_path[PATH_MAX]; char *game_locale(void) { char *p; char *s; p = getenv("LANG"); if (!p || !(s = strdup(p))) return NULL; if ((p = strchr(s, '_'))) *p = 0; return s; } char *game_tmp_path(void) { static time_t t = 0; static char tmp[PATH_MAX]="/tmp/instead-games"; if (!t) { t = time(NULL); sprintf(tmp, "/tmp/instead-games-%ld", (unsigned long)t); } if (mkdir(tmp, S_IRWXU) && errno != EEXIST) return NULL; return tmp; } char *appdir(void) { static char dir[PATH_MAX]; struct passwd *pw; #ifdef _LOCAL_APPDATA strcpy(dir, game_cwd); strcat(dir, "/appdata"); if (!access(dir, W_OK)) return dir; #endif pw = getpwuid(getuid()); if (!pw) return NULL; snprintf(dir, sizeof(dir) - 1 , "%s/.instead", pw->pw_dir); return dir; } char *game_local_games_path(int cr) { char *app = appdir(); if (!app) return NULL; strcpy(local_games_path, app); if (cr) { if (mkdir(local_games_path, S_IRWXU) && errno != EEXIST) return NULL; } strcat(local_games_path,"/games"); if (cr) { if (mkdir(local_games_path, S_IRWXU) && errno != EEXIST) return NULL; } return local_games_path; } char *game_local_themes_path(void) { char *app = appdir(); if (!app) return NULL; snprintf(local_themes_path, sizeof(local_themes_path) - 1 , "%s/themes", app); return local_themes_path; } char *game_local_stead_path(void) { char *app = appdir(); if (!app) return NULL; snprintf(local_stead_path, sizeof(local_stead_path) - 1 , "%s/stead", app); return local_stead_path; } char *game_cfg_path(void) { char *app = appdir(); struct passwd *pw; pw = getpwuid(getuid()); if (!pw) return NULL; snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/.insteadrc", pw->pw_dir); /* at home */ if (!access(cfg_path, R_OK)) return cfg_path; /* no at home? Try in dir */ if (app) snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/", app); if (!app || (mkdir(cfg_path, S_IRWXU) && errno != EEXIST)) snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/.insteadrc", pw->pw_dir); /* fallback to home */ else snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/insteadrc", app); return cfg_path; } char *game_save_path(int cr, int nr) { char *app = appdir(); if (!curgame_dir) return NULL; if (!access("saves", R_OK)) { if (nr) snprintf(save_path, sizeof(save_path) - 1, "saves/save%d", nr); else snprintf(save_path, sizeof(save_path) - 1, "saves/autosave"); return save_path; } if (!app) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/", app); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/saves", app); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/", app, curgame_dir); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; if (nr) snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/save%d", app, curgame_dir, nr); else snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/autosave", app, curgame_dir); return save_path; } int debug_init(void) { return 0; } void debug_done() { } char *sdl_path(char *p) { unix_path(p); return p; } char *open_file_dialog(void) { const char *filename; static char *file_name[PATH_MAX]; NSArray* fileTypes = [NSArray arrayWithObjects: @"zip", @"lua", @"idf", nil]; NSOpenPanel * panel = [NSOpenPanel openPanel]; [panel setCanChooseDirectories:NO]; [panel setCanChooseFiles:YES]; [panel setAllowsMultipleSelection:NO]; if ([panel runModalForTypes:fileTypes] == NSOKButton) { #ifdef __POWERPC__ filename = [[panel filename] cString]; #else filename = [[panel filename] cStringUsingEncoding:NSUTF8StringEncoding]; #endif strcpy(file_name, filename); return file_name; } return NULL; } #if 0 int setdir(const char *path) { return chdir(path); } char *getdir(char *path, size_t size) { return getcwd(path, size); } char *dirpath(const char *path) { return (char*)path; } int is_absolute_path(const char *path) { if (!path || !*path) return 0; return (*path == '/'); } #endif instead-3.5.2+dfsg/src/main.c000066400000000000000000000507561467622671600160040ustar00rootroot00000000000000/* * Copyright 2009-2022 Peter Kosyh * * 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. * */ #if defined(__APPLE__) || defined(ANDROID) || defined(WINRT) #include #endif #include "externals.h" #include "internals.h" #ifdef _USE_GTK #include #endif #ifdef ANDROID #include "android.h" #endif #ifdef _WIN32 #include #endif extern int debug_init(void); extern void debug_done(void); extern luaL_Reg paths_funcs[]; extern luaL_Reg bits_funcs[]; int debug_sw = 0; int noauto_sw = 0; int nostdgames_sw = 0; int nostdthemes_sw = 0; int version_sw = 0; int owntheme_sw = 0; int noowntheme_sw = 0; int nopause_sw = 0; int chunksize_sw = 0; int software_sw = 0; int hinting_sw = 1; int vsync_sw = 0; int resizable_sw = 0; int scale_sw = 1; int standalone_sw = 0; int nocursor_sw = 0; int glhack_sw = 0; int dpi_sw = 0; static int opt_index = 1; static int nohires_sw = 0; static char *fsize_sw = NULL; char *game_sw = NULL; char *games_sw = NULL; char *theme_sw = NULL; char *themes_sw = NULL; char *encode_sw = NULL; char *encode_output = NULL; char *mode_sw = NULL; char *modes_sw = NULL; char *appdata_sw = NULL; char *idf_sw = NULL; char *start_idf_sw = NULL; char *lua_sw = NULL; char *render_sw = NULL; char *lang_sw = NULL; static int lua_exec = 1; static int nocfg_sw = 0; char *instead_exec = NULL; #ifdef _USE_UNPACK extern int unpack(const char *zipfilename, const char *where); extern char zip_game_dirname[]; int setup_zip(const char *file, char *p) { if (!p) return -1; fprintf(stderr,"Trying to install: %s\n", file); if (unpack(file, p)) { if (zip_game_dirname[0]) { p = getpath(p, zip_game_dirname); fprintf(stderr, "Cleaning: '%s'...\n", p); remove_dir(p); free(p); } return -1; } p = strdup(p); FREE(game_sw); FREE(games_sw); game_sw = strdup(zip_game_dirname); games_sw = p; return 0; } #endif static int start_idf(char *file) { if (!file) return -1; if (!idf_magic(file)) return -1; FREE(start_idf_sw); start_idf_sw = strdup(file); return 0; } #ifdef __APPLE__ #include void macosx_init(void) { char resourcePath[PATH_MAX]; CFBundleRef mainBundle; CFURLRef resourcesDirectoryURL; mainBundle = CFBundleGetMainBundle(); if (!mainBundle) return; resourcesDirectoryURL = CFBundleCopyResourcesDirectoryURL(mainBundle); if (!resourcesDirectoryURL) return; CFURLGetFileSystemRepresentation(resourcesDirectoryURL, true, (UInt8 *) resourcePath, PATH_MAX); CFRelease(resourcesDirectoryURL); chdir(resourcePath); #ifdef IOS setup_inbox(); #endif return; } #endif static int run_game(const char *path) { char *b, *d; struct stat path_stat; static char dir[PATH_MAX + 1]; static char base[PATH_MAX + 1]; if (!path) return -1; if (!path[0]) return -1; if (strlen(path) >= PATH_MAX) return -1; strcpy(dir, getrealpath(path, base)); /* always get full path */ unix_path(dir); stat(dir, &path_stat); if (S_ISREG(path_stat.st_mode) && (!strlowcmp(basename(dir), INSTEAD_MAIN) || !strlowcmp(basename(dir), INSTEAD_MAIN3))) { d = dirname(dir); strcpy(base, d); d = dirname(d); } else { d = dirname(dir); strcpy(base, path); unix_path(base); } b = basename(base); if (!is_game(d, b)) { fprintf(stderr, "%s/%s is not a game path.\n", d, b); return -1; } FREE(game_sw); FREE(games_sw); game_sw = strdup(b); games_sw = strdup(d); return 0; } static void usage(void) { fprintf(stderr, "INSTEAD "VERSION" - Simple Text Adventure Engine, The Interpreter\n" "Usage:\n" " sdl-instead [options] [game.zip or game.idf or path to game]\n" "Some options:\n" " -debug Debug mode\n (for game developers).\n" " -nosound\n Run the game without sound.\n" " -gamespath\n Add path with games.\n" " -game \n Select game in gamespath.\n" " -owntheme\n Force game to use own theme.\n" " -fullscreen\n Run the game in fullscreen mode.\n" " -hires\n Set the high resolution if run in fullscreen mode.\n" " -window\n Run the game in windowed mode.\n" " -noautosave\n Disable autosave load.\n" " -mode [WxH]\n Use WxH resolution.\n" " -software\n Force software rendering.\n" " -nopause\n Do not pause the game on window minimize.\n" " -hinting 0|1|2|3\n Set the font hinting mode (helpful with infinality)\n" " -install [game in zip]\n Install game from zip archive.\n" " -appdata [fullpath]\n Store saves and settings in appdata path. Path must exist!\n" " -chunksize [size in bytes]\n Size for audio buffer. Try this if sound lags.\n" " -vsync\n Enable vsync display output.\n"); } static int profile_load(const char *path); extern int game_instead_extensions(void); static int luaB_clipboard(lua_State *L) { char *buf = NULL; const char *text = luaL_optstring(L, 1, NULL); if (!text) { /* get */ if (system_clipboard(NULL, &buf) == 0) { lua_pushstring(L, buf); free(buf); } else lua_pushboolean(L, 0); return 1; } lua_pushboolean(L, system_clipboard(text, NULL) == 0); return 1; } static int luaB_wait_use(lua_State *L) { int v = -1; int old = game_wait_use; if (lua_isboolean(L, 1)) v = lua_toboolean(L, 1); if (v == -1) { lua_pushboolean(L, old); return 1; } if (!opt_owntheme) { lua_pushboolean(L, 0); return 1; } game_wait_use = v; lua_pushboolean(L, old); return 1; } static int luaB_grab_events(lua_State *L) { int grab = lua_toboolean(L, 1); int ov = game_grab_events; if (lua_isboolean(L, 1)) game_grab_events = grab; lua_pushboolean(L, ov); return 1; } static int luaB_text_input(lua_State *L) { int rc; int inp = lua_toboolean(L, 1); if (!lua_isboolean(L, 1)) { rc = input_text(-1); lua_pushboolean(L, rc > 0); return 1; } rc = input_text(inp); lua_pushboolean(L, rc >= 0); return 1; } static const luaL_Reg sdl_funcs[] = { { "instead_clipboard", luaB_clipboard }, { "instead_wait_use", luaB_wait_use }, { "instead_grab_events", luaB_grab_events}, { "instead_text_input", luaB_text_input}, {NULL, NULL} }; static int input_text_state = 0; static int sdl_ext_init(void) { char path[PATH_MAX]; instead_api_register(sdl_funcs); input_text_state = input_text(-1); game_wait_use = 1; game_grab_events = 0; snprintf(path, sizeof(path), "%s/%s", instead_stead_path(), "/ext/gui.lua"); return instead_loadfile(dirpath(path)); } static int sdl_ext_done(void) { input_text(input_text_state); return 0; } static struct instead_ext sdl_ext = { .init = sdl_ext_init, .done = sdl_ext_done, }; static int sdl_extensions(void) { if (game_instead_extensions()) return -1; return instead_extension(&sdl_ext); } int instead_main(int argc, char *argv[]) { #ifdef _USE_UNPACK int clean_tmp = 0; #endif int err = 0; int i; #if defined(_WIN32) && !defined(WINRT) char *exe_path; HINSTANCE lib = LoadLibrary("user32.dll"); int (*SetProcessDPIAware)() = (void*) GetProcAddress(lib, "SetProcessDPIAware"); if (SetProcessDPIAware) SetProcessDPIAware(); #endif #ifdef __APPLE__ macosx_init(); #endif putenv("SDL_MOUSE_RELATIVE=0"); /* test this! */ #if GTK_MAJOR_VERSION == 4 /* fix crash when SDL2 uses gl */ putenv("GDK_DEBUG=gl-disable"); #endif #if defined(APPIMAGE) unix_path(argv[0]); strcpy(game_cwd, dirname(argv[0])); #elif defined(WINRT) unix_path(argv[0]); strcpy(game_cwd, argv[0]); /* argv[0] is directory */ #elif defined(_WIN32) exe_path = malloc(PATH_MAX + 1); if (exe_path) { i = GetModuleFileName(NULL, exe_path, PATH_MAX); exe_path[i] = 0; strcpy(game_cwd, dirname(exe_path)); free(exe_path); } else /* Sorry, kernel mode programming practice. Useless here. */ strcpy(game_cwd, dirname(argv[0])); #else if (!getcwd(game_cwd, sizeof(game_cwd))) fprintf(stderr,"Warning: can not get current dir\n."); #endif if (sdl_extensions() < 0) { fprintf(stderr, "Fatal: can not init SDL extensions\n"); return 1; } if (argc > 0) instead_exec = strdup(argv[0]); unix_path(game_cwd); setdir(game_cwd); profile_load(NULL); for (i = 1; i < argc; i++) { if (lua_sw) /* during load profile */ break; if (!strcmp(argv[i], "-vsync")) vsync_sw = 1; else if (!strcmp(argv[i], "-nosound")) nosound_sw = 1; else if (!strcmp(argv[i], "-dpi")) if ((i + 1) < argc) dpi_sw = atoi(argv[++i]); else dpi_sw = 96; else if (!strcmp(argv[i], "-fullscreen")) fullscreen_sw = 1; else if (!strcmp(argv[i], "-hires")) hires_sw = 1; else if (!strcmp(argv[i], "-nohires")) nohires_sw = 1; else if (!strcmp(argv[i], "-mode")) { FREE(mode_sw); if ((i + 1) < argc) mode_sw = strdup(argv[++i]); else mode_sw = strdup("-1x-1"); } else if (!strcmp(argv[i], "-modes")) { FREE(modes_sw); if ((i + 1) < argc) modes_sw = strdup(argv[++i]); } else if (!strcmp(argv[i], "-fontscale")) { FREE(fsize_sw); if (i + 1 < argc) fsize_sw = strdup(argv[++i]); else fsize_sw = NULL; } else if (!strcmp(argv[i], "-window")) window_sw = 1; else if (!strcmp(argv[i], "-debug")) { if (!debug_sw) debug_init(); debug_sw = 1; } else if (!strcmp(argv[i], "-owntheme")) owntheme_sw = 1; else if (!strcmp(argv[i], "-notheme")) noowntheme_sw = 1; else if (!strcmp(argv[i], "-noautosave")) noauto_sw = 1; else if (!strcmp(argv[i], "-game")) { FREE(game_sw); if ((i + 1) < argc) game_sw = strdup(argv[++i]); else game_sw = strdup(""); } else if (!strcmp(argv[i], "-theme")) { FREE(theme_sw); if ((i + 1) < argc) theme_sw = strdup(argv[++i]); else theme_sw = strdup(""); } else if (!strcmp(argv[i], "-nostdgames")) { nostdgames_sw = 1; } else if (!strcmp(argv[i], "-appdata")) { FREE(appdata_sw); if ((i + 1) < argc) appdata_sw = strdup(argv[++i]); else appdata_sw = strdup(""); } else if (!strcmp(argv[i], "-chunksize")) { if ((i + 1) < argc) chunksize_sw = atoi(argv[++i]); else chunksize_sw = DEFAULT_CHUNKSIZE; } else if (!strcmp(argv[i], "-gamespath")) { FREE(games_sw); if ((i + 1) < argc) games_sw = strdup(argv[++i]); else games_sw = strdup(""); } else if (!strcmp(argv[i], "-themespath")) { FREE(themes_sw); if ((i + 1) < argc) themes_sw = strdup(argv[++i]); else themes_sw = strdup(""); } else if (!strcmp(argv[i], "-idf")) { FREE(idf_sw); if ((i + 1) < argc) idf_sw = strdup(argv[++i]); else { fprintf(stderr,"No data directory specified.\n"); err = 1; goto out; } } else if (!strcmp(argv[i], "-encode")) { FREE(encode_sw); if ((i + 1) < argc) encode_sw = strdup(argv[++i]); else { fprintf(stderr,"No lua file specified.\n"); err = 1; goto out; } FREE(encode_output); if ((i + 1) < argc) encode_output = strdup(argv[++i]); else encode_output = strdup("lua.enc"); } else if (!strcmp(argv[i], "-version")) { version_sw = 1; } else if (!strcmp(argv[i], "-nopause")) { nopause_sw = 1; } else if (!strcmp(argv[i], "-nocursor")) { nocursor_sw = 1; } else if (!strcmp(argv[i], "-software")) { software_sw = 1; } else if (!strcmp(argv[i], "-glhack")) { if ((i + 1) < argc) glhack_sw = atoi(argv[++i]); else glhack_sw = 565; /* some samsung devices */ } else if (!strcmp(argv[i], "-resizable")) { resizable_sw = 1; } else if (!strcmp(argv[i], "-scale")) { if ((i + 1) < argc) scale_sw = atoi(argv[++i]); else scale_sw = 2; } else if (!strcmp(argv[i], "-standalone")) { standalone_sw = 1; owntheme_sw = 1; } else if (!strcmp(argv[i], "-noconfig")) { nocfg_sw = 1; } else if (!strcmp(argv[i], "-profile")) { if ((i + 1) < argc) { profile_load(argv[++i]); i ++; } #ifdef _USE_UNPACK } else if (!strcmp(argv[i], "-install")) { if ((i + 1) < argc) { char *file = argv[++i]; char *p; if (games_sw) p = games_sw; else p = game_local_games_path(1); if (setup_zip(file, p)) { err = 1; goto out; } } #endif } else if (!strcmp(argv[i], "-quit")) { exit(0); } else if (!strcmp(argv[i], "-hinting")) { if ((i + 1) < argc) hinting_sw = atoi(argv[++i]); else hinting_sw = 1; } else if (!strcmp(argv[i], "-lua") || !strcmp(argv[i], "-luac")) { if ((i + 1) < argc) { lua_exec = !strcmp(argv[i], "-lua"); FREE(lua_sw); lua_sw = strdup(argv[++ i]); opt_index = i + 1; break; } else { fprintf(stderr, "No lua script.\n"); err = 1; goto out; } } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) { usage(); goto out; } else if (!strcmp(argv[i], "-renderer")) { FREE(render_sw); if ((i + 1) < argc) render_sw = strdup(argv[++i]); else { fprintf(stderr, "Parameter required: %s\n", argv[i]); fprintf(stderr, "opengl, opengles2, opengles, software, direct3d\n"); err = 1; goto out; } } else if (!strcmp(argv[i], "-lang")) { if ((i + 1) < argc) lang_sw = strdup(argv[++i]); else lang_sw = strdup("en"); } else if (argv[i][0] == '-') { fprintf(stderr,"Unknown option: %s\n", argv[i]); usage(); err = 1; goto out; } else if (!start_idf(argv[i])) { fprintf(stderr, "Adding idf: %s\n", argv[i]); } else if (!run_game(argv[i])) { fprintf(stderr, "Opening game: %s\n", argv[i]); } #ifdef _USE_UNPACK else { char *p; if (games_sw) p = games_sw; else p = game_tmp_path(); if (setup_zip(argv[i], p)) { err = 1; goto out; } clean_tmp = 1; } #endif opt_index = i; } if (scale_sw <= 0) scale_sw = 1; else if (scale_sw > 8) scale_sw = 8; if (nocfg_sw || cfg_load()) { /* no config */ cfg_init(); } if (fsize_sw) { int i = atoi(fsize_sw); if (i > 0) opt_fsize = (i - 100) / 10; } if (opt_fsize < FONT_MIN_SZ) opt_fsize = FONT_MIN_SZ; else if (opt_fsize > FONT_MAX_SZ) opt_fsize = FONT_MAX_SZ; if (opt_debug == 1 && debug_sw == 0) { debug_sw = 1; debug_init(); } if (opt_vsync == 1 && vsync_sw == 0) vsync_sw = 1; if (opt_resizable == 1 && resizable_sw == 0) resizable_sw = 1; if (version_sw) { fprintf(stdout, VERSION"\n"); goto out; } if (lua_sw) { char *script_dir = strdup(lua_sw); instead_set_standalone(1); instead_set_debug(debug_sw); err = instead_init_lua(dirname(script_dir), 0); free(script_dir); if (err) goto out; instead_api_register(paths_funcs); instead_api_register(bits_funcs); if (!err) err = instead_loadscript(lua_sw, argc - opt_index, argv + opt_index, lua_exec); instead_done(); goto out; } if (encode_sw) { err = instead_encode(encode_sw, encode_output); goto out; } if (idf_sw) { char *p = malloc(strlen(idf_sw) + 5); if (p) { char *b; strcpy(p, idf_sw); b = basename(p); strcat(b, ".idf"); idf_create(b, idf_sw); free(p); } else idf_create("data.idf", idf_sw); goto out; } menu_langs_lookup(dirpath(LANG_PATH)); if (!langs_nr) { fprintf(stderr, "No languages found in: %s.\n", dirpath(LANG_PATH)); err = 1; goto out; } if (lang_sw) opt_lang = strdup(lang_sw); else if (!opt_lang || !opt_lang[0]) opt_lang = game_locale(); if (menu_lang_select(opt_lang) && menu_lang_select(LANG_DEF)) { fprintf(stderr, "Can not load default language.\n"); err = 1; goto out; } if (games_sw) games_lookup(games_sw); if (!nostdgames_sw && games_lookup(dirpath(GAMES_PATH))) fprintf(stderr, "No games found in: %s.\n", GAMES_PATH); if (themes_sw) themes_lookup(themes_sw, THEME_GLOBAL); if (!nostdthemes_sw) { themes_lookup(dirpath(THEMES_PATH), THEME_GLOBAL); themes_lookup(game_local_themes_path(), THEME_GLOBAL); } if (!nostdgames_sw) games_lookup(game_local_games_path(0)); if (start_idf_sw) { char *d, *b; char *dd, *bb; static char idf_game[255]; d = strdup(start_idf_sw); b = strdup(start_idf_sw); if (d && b) { dd = dirname(d); bb = basename(b); if (!games_replace(dirpath(dd), bb)) { strncpy(idf_game, bb, sizeof(idf_game) - 1); idf_game[sizeof(idf_game) - 1] = 0; FREE(game_sw); game_sw = strdup(idf_game); } } if (d) free(d); if (b) free(b); } /* too dangerous to be in release if (games_nr == 1) { if (strncmp(GAMES_PATH, games[0].path, strlen(GAMES_PATH))) { standalone_sw = 1; } } */ if (standalone_sw) { fprintf(stderr, "Standalone mode...\n"); owntheme_sw = 1; } if (owntheme_sw && !opt_owntheme) { opt_owntheme = 2; } if (noowntheme_sw && opt_owntheme) { opt_owntheme = 0; } else noowntheme_sw = 0; if (noauto_sw && opt_autosave) opt_autosave = 2; if (window_sw) opt_fs = 0; if (fullscreen_sw) opt_fs = 1; if (nohires_sw) opt_hires = 0; if (hires_sw != -1) opt_hires = hires_sw; if (mode_sw) parse_mode(mode_sw, opt_mode); if (game_sw) { FREE(opt_game); opt_game = game_sw; } if (theme_sw) { FREE(opt_theme); opt_theme = theme_sw; } if (opt_theme) game_theme_select(opt_theme); if (!curtheme_dir[THEME_GLOBAL]) game_theme_select(DEFAULT_THEME); /* Initialize SDL */ if (gfx_init() < 0) return -1; /* Initialize Sound */ snd_init(opt_hz); snd_volume_mus(opt_vol); #ifdef _USE_GTK #if GTK_MAJOR_VERSION == 4 gtk_init(); #else gtk_init(&argc, &argv); /* must be called AFTER SDL_Init when using SDL2 */ #endif #endif if (gfx_video_init() || input_init()) return -1; if (game_init(opt_game?opt_game:"")) { game_error(); } game_loop(); #ifdef __EMSCRIPTEN__ return 0; #endif cfg_save(); game_done(0); snd_done(); input_done(); gfx_video_done(); gfx_done(); out: if (debug_sw) debug_done(); #ifdef _USE_GTK /* gtk_main_quit (); */ #endif #ifdef _USE_UNPACK if (clean_tmp) remove_dir(game_tmp_path()); #endif return err; } static struct parser profile_parser[] = { { "standalone", parse_int, &standalone_sw, 0 }, { "vsync", parse_int, &vsync_sw, 0 }, { "debug", parse_int, &debug_sw, 0 }, { "lua", parse_string, &lua_sw, 0 }, { "nopause", parse_int, &nopause_sw, 0 }, { "noconfig", parse_int, &nocfg_sw, 0 }, { "noautosave", parse_int, &noauto_sw, 0 }, { "nostdgames", parse_int, &nostdgames_sw, 0 }, { "nostdthemes", parse_int, &nostdthemes_sw, 0 }, { "chunksize", parse_int, &chunksize_sw, 0 }, { "software", parse_int, &software_sw, 0 }, { "hinting", parse_int, &hinting_sw, 0 }, { "resizable", parse_int, &resizable_sw, 0 }, { "scale", parse_int, &scale_sw, 0 }, { "gamespath", parse_string, &games_sw, 0 }, { "themespath", parse_string, &themes_sw, 0 }, { "game", parse_string, &game_sw, 0 }, { "owntheme", parse_int, &owntheme_sw, 0 }, { "notheme", parse_int, &noowntheme_sw, 0 }, { "lang", parse_string, &lang_sw, 0 }, { "appdata", parse_string, &appdata_sw, 0 }, { "fullscreen", parse_int, &fullscreen_sw, 0 }, { "hires", parse_int, &hires_sw, 0 }, { "nohires", parse_int, &nohires_sw, 0 }, { "window", parse_int, &window_sw, 0 }, { "mode", parse_string, &mode_sw, 0 }, { "modes", parse_string, &modes_sw, 0 }, { "fontscale", parse_string, &fsize_sw, 0 }, { "renderer", parse_string, &render_sw, 0 }, { "nocursor", parse_int, &nocursor_sw, 0 }, { "dpi", parse_int, &dpi_sw, 0 }, { NULL, NULL, NULL, 0 }, }; static int profile_parse(const char *path) { return parse_ini(path, profile_parser); } static int profile_load(const char *prof) { char path[PATH_MAX]; const char *p = (prof)?prof:appdir(); if (!p) return -1; if (!prof) snprintf(path, sizeof(path), "%s/profile", p); else snprintf(path, sizeof(path), "%s", p); if (access(path, R_OK)) return 0; if (prof) fprintf(stderr, "Using profile...'%s'\n", path); return profile_parse(path); } #ifndef NOMAIN int main(int argc, char *argv[]) { int err; err = instead_main(argc, argv); #if defined(ANDROID) || defined(IOS) exit(err); #endif return err; } #endif instead-3.5.2+dfsg/src/menu.c000066400000000000000000000667051467622671600160250ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" static int restart_needed = 0; static int games_menu_from = 0; static int themes_menu_page = 0; static int cur_lang = 0; int cur_menu = menu_main; int top_menu = menu_main; char *UNKNOWN_ERROR = NULL; char *ERROR_MENU = NULL; char *WARNING_MENU = NULL; char *SAVE_SLOT_EMPTY = NULL; char *SELECT_LOAD_MENU = NULL; char *AUTOSAVE_SLOT = NULL; char *BROKEN_SLOT = NULL; char *SELECT_SAVE_MENU = NULL; char *MAIN_MENU = NULL; char *ABOUT_MENU = NULL; char *BACK_MENU = NULL; char *SETTINGS_SND_MENU = NULL; char *SETTINGS_GFX_MENU = NULL; char *SETTINGS_OTH_MENU = NULL; char *CUSTOM_THEME_MENU = NULL; char *OWN_THEME_MENU = NULL; char *WAIT_MENU = NULL; char *SELECT_GAME_MENU = NULL; char *SELECT_THEME_MENU = NULL; char *SAVED_MENU = NULL; char *NOGAMES_MENU = NULL; char *NOTHEMES_MENU = NULL; char *BROWSE_MENU = NULL; char *QUIT_MENU = NULL; char *REMOVE_MENU = NULL; char *ON = NULL; char *OFF = NULL; char *KBD_MODE_LINKS = NULL; char *KBD_MODE_SMART = NULL; char *KBD_MODE_SCROLL = NULL; char *CANCEL_MENU = NULL; char *FROM_THEME = NULL; char *DISABLED_SAVE_MENU = NULL; static char menu_buff[8192]; static char *slot_name(const char *path) { struct stat st; char *l; if (stat(path, &st)) return NULL; l = lookup_tag(path, "Name", "--"); if (l) { trunc_lines(l, 0); if (!is_empty(l) && game_tag_valid(l)) { int y; char *m; static char *months[] = {/* to work on every locale ;)*/ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; struct tm *tm; time_t t; char *s = instead_fromgame(l); free(l); if (!s) return s; time(&t); tm = localtime(&t); y = tm->tm_year; tm = localtime(&st.st_mtime); l = malloc(strlen(s) + 64); if (!l) return s; if (tm->tm_mon >=0 && tm->tm_mon < 12) m = months[tm->tm_mon]; else m = "?"; if (tm->tm_year == y) snprintf(l, 64, "%02d %s %02d:%02d - ", tm->tm_mday, m, tm->tm_hour, tm->tm_min); else { if (tm->tm_year < 1900) tm->tm_year += 1900; snprintf(l, 64, "%02d %s %02d:%02d %04d - ", tm->tm_mday, m, tm->tm_hour, tm->tm_min, tm->tm_year); } strcat(l, s); free(s); return l; } free(l); } l = ctime(&st.st_mtime); if (!l) return NULL; l[strcspn(l,"\n")] = 0; return strdup(l); } static void load_menu(void) { int i; *menu_buff = 0; /* if (!game_saves_enabled()) { strcat(menu_buff, DISABLED_SAVE_MENU); strcat(menu_buff, CANCEL_MENU); return; } */ strcpy(menu_buff, SELECT_LOAD_MENU); for (i = 0; i < MAX_SAVE_SLOTS; i ++) { char tmp[PATH_MAX]; char *s = game_save_path(0, i); if (!s || access(s, R_OK)) { if (!i) continue; snprintf(tmp, sizeof(tmp), "%d - %s\n", i, SAVE_SLOT_EMPTY); } else { char *name; if (!i) name = strdup(AUTOSAVE_SLOT); else name = slot_name(s); if (!name) snprintf(tmp, sizeof(tmp), "%d - %s\n", i, BROKEN_SLOT); else { snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, name); free(name); } } strcat(menu_buff, tmp); } strcat(menu_buff,"\n"); strcat(menu_buff, CANCEL_MENU); } static void save_menu(void) { int i; *menu_buff = 0; if (!game_saves_enabled()) { strcat(menu_buff, DISABLED_SAVE_MENU); strcat(menu_buff, CANCEL_MENU); return; } strcpy(menu_buff, SELECT_SAVE_MENU); for (i = 1; i < MAX_SAVE_SLOTS; i ++) { char tmp[PATH_MAX]; char *s = game_save_path(0, i); if (!s || access(s, R_OK)) snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, SAVE_SLOT_EMPTY); else { char *name; if (!i) name = strdup(AUTOSAVE_SLOT); else name = slot_name(s); if (!name) snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, BROKEN_SLOT); else { snprintf(tmp, sizeof(tmp), "%d - %s\n", i, i, name); free(name); } } strcat(menu_buff, tmp); } strcat(menu_buff,"\n"); strcat(menu_buff, CANCEL_MENU); } static int pages_menu(char *res, int nr, int max, const char *menu, const char *append) { static char buff[256]; int k = MENU_PER_PAGER; int i = nr - MENU_PER_PAGER / 2; if (i < 0) i = 0; else if (max - i < MENU_PER_PAGER) i = max - MENU_PER_PAGER; if (i < 0) i = 0; if (nr) sprintf(buff, "<< ", menu); else sprintf(buff, "<< "); strcat(res, buff); for (; i < max && k-- ; i ++) { if (i != nr) sprintf(buff, "[%d] ", menu, i, i + 1); else sprintf(buff, "[%d] ", i + 1); strcat(res, buff); } if ((nr + 1) != max) sprintf(buff, ">>", menu); else sprintf(buff, ">>"); strcat(res, buff); strcat(res, append); return 0; } static void games_menu(void) { int i, n; #ifdef _USE_BROWSE int append_browse = 0; #endif char tmp[PATH_MAX]; #ifdef _USE_BROWSE snprintf(tmp, sizeof(tmp), " %s\n", BROWSE_MENU); #else snprintf(tmp, sizeof(tmp), "\n"); #endif strcpy(menu_buff, SELECT_GAME_MENU); if ((games_nr - 1) / MENU_GAMES_MAX) pages_menu(menu_buff, games_menu_from / MENU_GAMES_MAX, (games_nr - 1) / MENU_GAMES_MAX + 1, "games", tmp); #ifdef _USE_BROWSE else append_browse = 1; #endif for (i = games_menu_from, n = 0; i < games_nr && n < MENU_GAMES_MAX; i ++) { if (!games[i].name[0]) /* empty */ continue; if (curgame_dir && !strcmp(games[i].dir, curgame_dir)) snprintf(tmp, sizeof(tmp), "%s", games[i].name); else snprintf(tmp, sizeof(tmp), "%s", games[i].dir, games[i].name); if (!strncmp(game_local_games_path(0), games[i].path, strlen(game_local_games_path(0))) && !access(games[i].path, W_OK)) { snprintf(tmp + strlen(tmp), sizeof(tmp), " [X]\n", i); } else strcat(tmp, "\n"); strcat(menu_buff, tmp); n ++; } for(;n < MENU_GAMES_MAX && games_nr > MENU_GAMES_MAX; n++) /* align h */ strcat(menu_buff, "\n"); #ifdef _USE_BROWSE if (append_browse) { snprintf(tmp, sizeof(tmp), "%s\n", BROWSE_MENU); strcat(menu_buff, tmp); } #endif if (!games_nr) { sprintf(menu_buff, NOGAMES_MENU, GAMES_PATH); #ifdef _USE_BROWSE strcat(menu_buff,"\n"); snprintf(tmp, sizeof(tmp), "%s\n", BROWSE_MENU); strcat(menu_buff, tmp); #endif } strcat(menu_buff,"\n"); strcat(menu_buff, BACK_MENU); } int games_menu_maxw(void) { int i = 0; int oldm = games_menu_from; int maxw = 0; for (i = 0; i < games_nr; i += MENU_GAMES_MAX) { int w; games_menu_from = i; games_menu(); game_menu_box_wh(menu_buff, &w, NULL); if (w > maxw) maxw = w; } games_menu_from = oldm; return maxw; } static void themes_menu(void) { int i, n, m; int type; int count = themes_max(&type); int pages = 0; if (count > 0) pages = (count - 1) / MENU_THEMES_MAX + 1; if (themes_menu_page >= pages) themes_menu_page = 0; strcpy(menu_buff, SELECT_THEME_MENU); if (pages > 1) pages_menu(menu_buff, themes_menu_page, pages, "themes", "\n"); for (i = 0, n = 0, m = 0; i < themes_nr && n < MENU_THEMES_MAX; i ++) { char tmp[PATH_MAX]; if (!themes[i].name[0]) /* empty */ continue; if (themes[i].type != type) continue; m ++; if ((m - 1) / MENU_THEMES_MAX < themes_menu_page) continue; if (curtheme_dir[type] && !strcmp(themes[i].dir, curtheme_dir[type])) snprintf(tmp, sizeof(tmp), "%s\n", themes[i].name); else snprintf(tmp, sizeof(tmp), "%s\n", themes[i].dir, themes[i].name); strcat(menu_buff, tmp); n ++; } for(;n < MENU_THEMES_MAX && count > MENU_THEMES_MAX; n++) /* align h */ strcat(menu_buff, "\n"); if (!count) sprintf(menu_buff, NOTHEMES_MENU, THEMES_PATH); strcat(menu_buff, "\n"); strcat(menu_buff, BACK_MENU); } int themes_menu_maxw(void) { int i = 0; int oldm = themes_menu_page; int maxw = 0; int pages = 0; int count = themes_max(NULL); if (count > 0) pages = (count - 1) / MENU_THEMES_MAX + 1; else pages = 1; for (i = 0; i < pages; i ++) { int w; themes_menu_page = i; themes_menu(); game_menu_box_wh(menu_buff, &w, NULL); if (w > maxw) maxw = w; } themes_menu_page = oldm; return maxw; } static char *opt_get_mode(void) { static char buff[128]; if (opt_mode[0] == -1 || opt_mode[1] == -1) { snprintf(buff, sizeof(buff), "%s", FROM_THEME); return buff; } snprintf(buff, sizeof(buff), "%dx%d", opt_mode[0], opt_mode[1]); return buff; } static int gtr = 0; static int menu_settings_num = 0; static void menu_strip_tag(const char *a, const char *b) { char *p, *ep; size_t len; p = strstr(menu_buff, a); if (!p) return; ep = strstr(p, b); if (!ep) return; /* ep += strcspn(ep, "\n\r"); ep += strspn(ep, "\n\r"); */ ep += strlen(b); len = strlen(ep); memmove(p, ep, len); p[len] = 0; } static void menu_remove_tag(const char *a, const char *b) { char *p, *ep; size_t len; p = strstr(menu_buff, a); if (!p) return; ep = p + strlen(a); len = strlen(ep); memmove(p, ep, len); p[len] = 0; ep = strstr(p, b); if (!ep) return; p = ep; ep += strlen(b); len = strlen(ep); memmove(p, ep, len); p[len] = 0; } static char err_msg[512]; char *game_menu_gen(void) { if (cur_menu == menu_main) { strcpy(menu_buff, MAIN_MENU); if (standalone_sw) { int count = 0, n; menu_strip_tag("", ""); count = themes_count(THEME_GLOBAL); if (curgame_dir && opt_owntheme) { if ((n = themes_count(THEME_GAME)) > 0) count = n; else if (game_own_theme) count = 1; } if (count <= 1) menu_strip_tag("", ""); else menu_remove_tag("", ""); } else { menu_remove_tag("", ""); menu_remove_tag("", ""); } } else if (cur_menu == menu_about || cur_menu == menu_about_instead) { struct game *g; if (cur_menu == menu_about && curgame_dir && (g = game_lookup(curgame_dir))) { char version[32]; char author[64]; char info[192]; char instead[64]; if (g->version) snprintf(version, sizeof(version), "%s", g->version); else strcpy(version, "1.0"); if (g->author) snprintf(author, sizeof(author), "\n%s", g->author); else strcpy(author, ""); if (g->info) snprintf(info, sizeof(info), "\n\n%s", g->info); else strcpy(info, ""); if (!standalone_sw) snprintf(instead, sizeof(instead), "INSTEAD | "); else strcpy(instead, ""); author[sizeof(author) - 1] = 0; version[sizeof(version) - 1] = 0; info[sizeof(info) - 1] = 0; snprintf(menu_buff, sizeof(menu_buff), "%s - %s%s%s\n\n%s%s", g->name, version, author, info, instead, BACK_MENU); } else { snprintf(menu_buff, sizeof(menu_buff), ABOUT_MENU, VERSION); } } else if (cur_menu == menu_settings) { char *just[JUST_MAX] = { FROM_THEME, OFF, ON }; char *kbd [KBD_MAX] = { KBD_MODE_SMART, KBD_MODE_LINKS, KBD_MODE_SCROLL }; int fsize = 100 + (10 * opt_fsize); opt_kbd = (unsigned int)opt_kbd % KBD_MAX; opt_justify = (unsigned int)opt_justify % JUST_MAX; switch (menu_settings_num) { case 0: snprintf(menu_buff, sizeof(menu_buff), SETTINGS_GFX_MENU, opt_get_mode(), opt_fs?ON:OFF, opt_hires?ON:OFF, fsize, just[opt_justify], opt_hl?ON:OFF, opt_fading?ON:OFF, opt_owntheme?ON:OFF); if (standalone_sw) menu_strip_tag("", ""); else menu_remove_tag("", ""); break; case 1: snprintf(menu_buff, sizeof(menu_buff), SETTINGS_SND_MENU, snd_vol_to_pcn(snd_volume_mus(-1)), snd_hz(), opt_music?ON:OFF, opt_click?ON:OFF); break; case 2: snprintf(menu_buff, sizeof(menu_buff), SETTINGS_OTH_MENU, opt_motion?ON:OFF, opt_filter?ON:OFF, kbd[opt_kbd], langs[cur_lang].name, (opt_autosave & 1)?ON:OFF); break; } } else if (cur_menu == menu_askquit) { strcpy(menu_buff, QUIT_MENU); } else if (cur_menu == menu_saved) { strcpy(menu_buff, SAVED_MENU); } else if (cur_menu == menu_games) { games_menu(); } else if (cur_menu == menu_themes) { themes_menu(); } else if (cur_menu == menu_own_theme) { strcpy(menu_buff, OWN_THEME_MENU); } else if (cur_menu == menu_wait) { strcpy(menu_buff, WAIT_MENU); } else if (cur_menu == menu_custom_theme) { strcpy(menu_buff, CUSTOM_THEME_MENU); } else if (cur_menu == menu_load) { load_menu(); } else if (cur_menu == menu_save) { save_menu(); } else if (cur_menu == menu_error) { strncpy(err_msg, instead_err()?instead_err():UNKNOWN_ERROR, sizeof(err_msg) - 1); strcpy(err_msg + sizeof(err_msg) - 4, "..."); snprintf(menu_buff, sizeof(menu_buff), ERROR_MENU, err_msg); instead_err_msg(NULL); } else if (cur_menu == menu_warning) { strncpy(err_msg, instead_err()?instead_err():UNKNOWN_ERROR, sizeof(err_msg) - 1); strcpy(err_msg + sizeof(err_msg) - 4, "..."); snprintf(menu_buff, sizeof(menu_buff), WARNING_MENU, err_msg); instead_err_msg(NULL); } else if (cur_menu == menu_remove) { const char *sname = games[gtr].path; if (strlen(games[gtr].path) >= 48) { sname = games[gtr].name; } snprintf(menu_buff, sizeof(menu_buff), REMOVE_MENU, sname); } return menu_buff; } int game_menu_act(const char *a) { static int old_vol = 0; if (!strcmp(a, "/autosave")) { opt_autosave = !(opt_autosave & 1); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/kbd")) { opt_kbd += 1; if (opt_kbd == KBD_MAX) opt_kbd = 0; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/owntheme")) { opt_owntheme = !opt_owntheme; if (game_own_theme) restart_needed = 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/motion")) { opt_motion ^= 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/filter")) { opt_filter ^= 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/click")) { opt_click ^= 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/mode++")) { if (gfx_next_mode(&opt_mode[0], &opt_mode[1])) opt_mode[0] = opt_mode[1] = -1; restart_needed = 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/mode--")) { if (gfx_prev_mode(&opt_mode[0], &opt_mode[1])) opt_mode[0] = opt_mode[1] = -1; restart_needed = 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/just++")) { restart_needed = 1; opt_justify ++; if (opt_justify >= JUST_MAX) opt_justify = 0; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/just--")) { restart_needed = 1; opt_justify --; if (opt_justify < 0) opt_justify = JUST_MAX - 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/fs--")) { opt_fsize --; if (opt_fsize >= FONT_MIN_SZ) { restart_needed = 1; } else opt_fsize ++; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/fs++")) { opt_fsize ++; if (opt_fsize <= FONT_MAX_SZ) { restart_needed = 1; } else opt_fsize --; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/hl")) { opt_hl ^= 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/fading")) { opt_fading ^= 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/fs")) { #if !defined(ANDROID) && !defined(IOS) restart_needed = 1; opt_fs ^= 1; game_menu_box(1, game_menu_gen()); #endif } else if (!strcmp(a, "/hires")) { opt_hires ^= 1; restart_needed = 1; game_menu_box(1, game_menu_gen()); } else if (!strncmp(a, "/games ", 7)) { if (!strcmp(a + 7, "prev")) { games_menu_from -= MENU_GAMES_MAX; if (games_menu_from < 0) games_menu_from = 0; } else if (!strcmp(a + 7, "next")) { if (games_menu_from + MENU_GAMES_MAX < games_nr) games_menu_from += MENU_GAMES_MAX; } else { int nr = atoi(a + 7); games_menu_from = nr * MENU_GAMES_MAX; } game_menu_box(1, game_menu_gen()); } else if (!strncmp(a, "/themes ", 8)) { if (!strcmp(a + 8, "prev")) { themes_menu_page --; if (themes_menu_page < 0) themes_menu_page = 0; } else if (!strcmp(a + 8, "next")) { int count = themes_max(NULL); int pages = 0; if (count > 0) pages = (count - 1) / MENU_THEMES_MAX + 1; if (themes_menu_page + 1 < pages) themes_menu_page ++; } else { int nr = atoi(a + 8); themes_menu_page = nr; } game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/select")) { game_menu(menu_games); } else if (!strcmp(a, "/remove")) { fprintf(stderr,"Removing '%s'\n", games[gtr].path); if (curgame_dir && !strcmp(curgame_dir, games[gtr].dir)) { game_done(0); if (game_init(NULL)) { game_error(); return 0; } } games_remove(gtr); if (games_menu_from >= games_nr) games_menu_from -= MENU_GAMES_MAX; if (games_menu_from < 0) games_menu_from = 0; game_menu(menu_games); } else if (!strcmp(a, "/themes")) { game_menu(menu_themes); } else if (!strcmp(a, "/save_menu")) { if (curgame_dir) game_menu(menu_save); } else if (!strncmp(a, "/save", 5)) { if (!game_save(atoi(a + 5))) { game_menu(menu_saved); } } else if (!strcmp(a, "/load_menu")) { if (curgame_dir) game_menu(menu_load); } else if (!strncmp(a, "/load", 5)) { int nr = atoi(a + 5); if (!curgame_dir) return 0; game_menu_box(0, NULL); if (!game_reset()) { game_load(nr); cur_menu = menu_main; } /* game_menu_box(0, NULL); */ } else if (!strcmp(a, "/new")) { char *s; if (!curgame_dir) return 0; /* remove autlosave */ s = game_save_path(0, 0); if (s && !access(s, R_OK) && (opt_autosave & 1)) unlink (s); game_menu_box(0, NULL); if (!game_reset()) { game_cmd("look", 0); custom_theme_warn(); } } else if (!strcmp(a,"/main")) { if (top_menu != menu_main) { cur_menu = menu_main; game_menu_box(0, NULL); } else game_menu(menu_main); if (restart_needed) { game_restart(); restart_needed = 0; } } else if (!strcmp(a,"/ask_quit")) { game_menu(menu_askquit); } else if (!strncmp(a, "/remove_", 8)) { gtr = atoi(a + 8); game_menu(menu_remove); } else if (!strcmp(a,"/about")) { game_menu(menu_about); } else if (!strcmp(a,"/about-instead")) { game_menu(menu_about_instead); } else if (!strcmp(a,"/mtoggle")) { if (!old_vol) { old_vol = snd_volume_mus(-1); game_change_vol(0, 0); } else { game_change_vol(0, old_vol); old_vol = 0; } game_menu_box(1, game_menu_gen()); } else if (!strcmp(a,"/music")) { opt_music ^= 1; if (!opt_music) { game_stop_mus(0); } else game_music_player(); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a,"/resume")) { cur_menu = menu_main; game_menu_box(0, NULL); } else if (!strcmp(a, "/settings")) { game_menu(menu_settings); } else if (!strcmp(a, "/settings-gfx")) { menu_settings_num = 0; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/settings-snd")) { menu_settings_num = 1; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/settings-oth")) { menu_settings_num = 2; game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/vol--")) { game_change_vol(-10, 0); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/vol++")) { game_change_vol(+10, 0); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/vol-")) { game_change_vol(-1, 0); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/vol+")) { game_change_vol(+1, 0); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/hz-")) { int hz = snd_hz(); if (hz == 44100) hz = 22050; else if (hz == 22050) hz = 11025; else if (hz == 11025) hz = 0; else hz = 22050; game_change_hz(hz); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/hz+")) { int hz = snd_hz(); if (hz == 11025) hz = 22050; else if (hz == 22050) hz = 44100; else if (hz == 44100) hz = 0; else hz = 22050; game_change_hz(hz); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/lang++")) { do { cur_lang ++; if (cur_lang >= langs_nr) cur_lang = 0; } while (menu_lang_select(langs[cur_lang].file)); if (curgame_dir) instead_set_lang(opt_lang); themes_rename(); games_rename(); game_reset_name(); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a, "/lang--")) { do { cur_lang --; if (cur_lang < 0) cur_lang = langs_nr - 1; } while (menu_lang_select(langs[cur_lang].file)); if (curgame_dir) instead_set_lang(opt_lang); themes_rename(); games_rename(); game_reset_name(); game_menu_box(1, game_menu_gen()); } else if (!strcmp(a,"/quit")) { return -1; #ifdef _USE_BROWSE } else if (!strcmp(a,"/browse")) { game_from_disk(); return 0; #endif } else if (cur_menu == menu_games) { char *p; p = strdup(a); if (p) { game_done(0); if (game_init(p)) { game_error(); } free(p); } } else if (cur_menu == menu_themes) { char *p; p = strdup(a); if (p) { char *og; if (game_theme_select(p)) fprintf(stderr, "Can't select theme:%s:%s\n", p, strerror(errno)); og = curgame_dir; game_save(-1); game_done(0); if (game_init(og)) { game_error(); } else if (curgame_dir && game_own_theme && opt_owntheme && !curtheme_dir[THEME_GAME]) { game_menu(menu_own_theme); } free(p); } } return 0; } void custom_theme_warn(void) { if (game_own_theme && !opt_owntheme && cur_menu != menu_warning) { game_menu(menu_custom_theme); } } struct lang *langs = NULL; int langs_nr = 0; static void lang_free(void) { FREE(UNKNOWN_ERROR); FREE(ERROR_MENU); FREE(WARNING_MENU); FREE(SAVE_SLOT_EMPTY); FREE(SELECT_LOAD_MENU); FREE(AUTOSAVE_SLOT); FREE(BROKEN_SLOT); FREE(SELECT_SAVE_MENU); FREE(MAIN_MENU); FREE(ABOUT_MENU); FREE(BACK_MENU); FREE(SETTINGS_SND_MENU); FREE(SETTINGS_GFX_MENU); FREE(SETTINGS_OTH_MENU); FREE(CUSTOM_THEME_MENU); FREE(OWN_THEME_MENU); FREE(WAIT_MENU); FREE(SELECT_GAME_MENU); FREE(SELECT_THEME_MENU); FREE(SAVED_MENU); FREE(NOGAMES_MENU); FREE(NOTHEMES_MENU); FREE(QUIT_MENU); FREE(REMOVE_MENU); FREE(ON); FREE(OFF); FREE(KBD_MODE_LINKS); FREE(KBD_MODE_SMART); FREE(KBD_MODE_SCROLL); FREE(CANCEL_MENU); FREE(FROM_THEME); FREE(DISABLED_SAVE_MENU); FREE(BROWSE_MENU); } static int lang_ok(void) { if (UNKNOWN_ERROR && ERROR_MENU && WARNING_MENU && SAVE_SLOT_EMPTY && SELECT_LOAD_MENU && AUTOSAVE_SLOT && BROKEN_SLOT && SELECT_SAVE_MENU && MAIN_MENU && ABOUT_MENU && BACK_MENU && SETTINGS_SND_MENU && SETTINGS_GFX_MENU && SETTINGS_OTH_MENU && CUSTOM_THEME_MENU && OWN_THEME_MENU && SELECT_GAME_MENU && SELECT_THEME_MENU && WAIT_MENU && SAVED_MENU && NOGAMES_MENU && NOTHEMES_MENU && QUIT_MENU && REMOVE_MENU && ON && OFF && KBD_MODE_LINKS && KBD_MODE_SMART && KBD_MODE_SCROLL && CANCEL_MENU && FROM_THEME && DISABLED_SAVE_MENU && BROWSE_MENU) return 0; return -1; } struct parser lang_parser[] = { { "UNKNOWN_ERROR", parse_esc_string, &UNKNOWN_ERROR, 0 }, { "ERROR_MENU", parse_esc_string, &ERROR_MENU, 0 }, { "WARNING_MENU", parse_esc_string, &WARNING_MENU, 0 }, { "SAVE_SLOT_EMPTY", parse_esc_string, &SAVE_SLOT_EMPTY, 0 }, { "SELECT_LOAD_MENU", parse_esc_string, &SELECT_LOAD_MENU, 0 }, { "AUTOSAVE_SLOT", parse_esc_string, &AUTOSAVE_SLOT, 0 }, { "BROKEN_SLOT", parse_esc_string, &BROKEN_SLOT, 0 }, { "SELECT_SAVE_MENU", parse_esc_string, &SELECT_SAVE_MENU, 0 }, { "MAIN_MENU", parse_esc_string, &MAIN_MENU, 0 }, { "ABOUT_MENU", parse_esc_string, &ABOUT_MENU, 0 }, { "BACK_MENU", parse_esc_string, &BACK_MENU, 0 }, { "SETTINGS_GFX_MENU", parse_esc_string, &SETTINGS_GFX_MENU, 0 }, { "SETTINGS_SND_MENU", parse_esc_string, &SETTINGS_SND_MENU, 0 }, { "SETTINGS_OTH_MENU", parse_esc_string, &SETTINGS_OTH_MENU, 0 }, { "CUSTOM_THEME_MENU", parse_esc_string, &CUSTOM_THEME_MENU, 0 }, { "OWN_THEME_MENU", parse_esc_string, &OWN_THEME_MENU, 0 }, { "WAIT_MENU", parse_esc_string, &WAIT_MENU, 0 }, { "SELECT_GAME_MENU", parse_esc_string, &SELECT_GAME_MENU, 0 }, { "SELECT_THEME_MENU", parse_esc_string, &SELECT_THEME_MENU, 0 }, { "SAVED_MENU", parse_esc_string, &SAVED_MENU, 0 }, { "NOGAMES_MENU", parse_esc_string, &NOGAMES_MENU, 0 }, { "NOTHEMES_MENU", parse_esc_string, &NOTHEMES_MENU, 0 }, { "QUIT_MENU", parse_esc_string, &QUIT_MENU, 0 }, { "REMOVE_MENU", parse_esc_string, &REMOVE_MENU, 0 }, { "ON", parse_esc_string, &ON, 0 }, { "OFF", parse_esc_string, &OFF, 0 }, { "KBD_MODE_LINKS", parse_esc_string, &KBD_MODE_LINKS, 0 }, { "KBD_MODE_SMART", parse_esc_string, &KBD_MODE_SMART, 0 }, { "KBD_MODE_SCROLL", parse_esc_string, &KBD_MODE_SCROLL, 0 }, { "CANCEL_MENU", parse_esc_string, &CANCEL_MENU, 0 }, { "FROM_THEME", parse_esc_string, &FROM_THEME, 0 }, { "DISABLED_SAVE_MENU", parse_esc_string, &DISABLED_SAVE_MENU, 0 }, { "BROWSE_MENU", parse_esc_string, &BROWSE_MENU, 0 }, { NULL, NULL, NULL, 0 }, }; static int lang_parse(const char *path) { return parse_ini(path, lang_parser); } static int is_lang(const char *path, const char *n) { char *p = getfilepath(path, n); if (!p) return 0; if (access(p, F_OK)) return 0; free(p); if (!(p = strstr(n, ".ini")) && !(p = strstr(n, ".INI"))) return 0; return 1; } static char *lang_code(const char *str) { char *p = strdup(str); if (!p) return NULL; p[strcspn(p, ".")] = 0; tolow(p); return p; } static char *lang_name(const char *path, const char *file) { char *l; l = lookup_tag(path, "Name", ";"); if (l) return l; return lang_code(file); } static int cmp_lang(const void *p1, const void *p2) { const struct lang *l1 = (const struct lang*)p1; const struct lang *l2 = (const struct lang*)p2; return strcmp(l1->name, l2->name); } static void langs_sort() { qsort(langs, langs_nr, sizeof(struct lang), cmp_lang); } int menu_langs_lookup(const char *path) { char *p; int n = 0, i = 0; DIR *d; struct dirent *de; struct lang *new_langs; if (!path) return 0; d = opendir(path); if (!d) return -1; while ((de = readdir(d))) { if (!is_lang(path, de->d_name)) continue; n ++; } if (!n) goto out; closedir(d); d = opendir(path); if (!d) return -1; new_langs = realloc(langs, sizeof(struct lang) * (n + langs_nr)); if (!new_langs) { closedir(d); return -1; } langs = new_langs; while ((de = readdir(d)) && i < n) { if (!is_lang(path, de->d_name)) continue; p = getfilepath(path, de->d_name); langs[langs_nr].path = p; langs[langs_nr].file = lang_code(de->d_name); langs[langs_nr].name = lang_name(p, de->d_name); langs_nr ++; i ++; } out: langs_sort(); closedir(d); return 0; } int menu_lang_select(const char *name) { int i; char cwd[PATH_MAX]; if (!name) return -1; getdir(cwd, sizeof(cwd)); setdir(game_cwd); for (i = 0; i * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" #ifdef SAILFISHOS #include #include #endif #include #include int audio_rate = 22050; Uint16 audio_format = MIX_DEFAULT_FORMAT; int audio_channels = 2; int audio_buffers = 8192; static mus_t mus; static char *next_mus = NULL; static int next_fadein = 0; static int next_loop = -1; static SDL_TimerID timer_id = NULL_TIMER; static int sound_on = 0; struct _mus_t { Mix_Music *mus; SDL_RWops *rw; }; int snd_enabled(void) { return sound_on; } static void mus_callback(void *aux) { if (!timer_id) return; if (snd_playing_mus()) return; if (mus) snd_free_mus(mus); mus = NULL; if (next_mus) { if (snd_play_mus(next_mus, next_fadein, next_loop) < 0) game_res_err_msg(next_mus, debug_sw); free(next_mus); next_mus = NULL; } SDL_RemoveTimer(timer_id); timer_id = NULL_TIMER; } static Uint32 callback(Uint32 interval, void *aux) { push_user_event(mus_callback, aux); return interval; } int snd_hz(void) { int freq = 0; if (sound_on) Mix_QuerySpec(&freq, NULL, NULL); return freq; } int nosound_sw = 0; void snd_pause(int on) { if (!sound_on) return; if (on) { Mix_Pause(-1); Mix_PauseMusic(); } else { Mix_Resume(-1); Mix_ResumeMusic(); } return; } static int _snd_open(int hz) { int chunk; if (!hz) hz = audio_rate; else audio_rate = hz; chunk = (chunksize_sw>0)?chunksize_sw:DEFAULT_CHUNKSIZE; audio_buffers = (audio_rate / 11025) * chunk; if (audio_buffers <= 0) /* wrong parameter? */ audio_buffers = DEFAULT_CHUNKSIZE; #ifdef __EMSCRIPTEN__ if (Mix_OpenAudioDevice(44100, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE)) { #else if (Mix_OpenAudio(hz, audio_format, audio_channels, audio_buffers)) { #endif fprintf(stderr, "Unable to open audio!\n"); return -1; } sound_on = 1; Mix_ChannelFinished(game_channel_finished); return 0; } #ifdef SAILFISHOS static audioresource_t *audio_resource = NULL; static void on_audio_resource_acquired(audioresource_t *ar, bool acquired, void *phz) { if (acquired && !sound_on) _snd_open(*(int *)phz); } int snd_open(int hz) { if (nosound_sw) return -1; if (sound_on) snd_close(); /* reopen */ if (!audio_resource) { audio_resource = audioresource_init(AUDIO_RESOURCE_GAME, on_audio_resource_acquired, &hz); if (!audio_resource) return -1; audioresource_acquire(audio_resource); } while (!sound_on) { fprintf(stderr, "Waiting for audio resource to be acquired...\n"); g_main_context_iteration(NULL, true); } return 0; } #else int snd_open(int hz) { if (nosound_sw) return -1; if (sound_on) snd_close(); /* reopen */ return _snd_open(hz); } #endif int snd_init(int hz) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Unable to init audio!\n"); return -1; } return snd_open(hz); } int snd_volume_mus(int vol) { if (!sound_on) return 0; Mix_Volume(-1, vol); return Mix_VolumeMusic(vol); } #if SDL_BYTEORDER == SDL_LIL_ENDIAN #define SND_DEFAULT_FORMAT AUDIO_S16LSB #else #define SND_DEFAULT_FORMAT AUDIO_S16MSB #endif #define MIXER_VERSION_ATLEAST(a,b,c) (SDL_VERSIONNUM(SDL_MIXER_MAJOR_VERSION, SDL_MIXER_MINOR_VERSION,SDL_MIXER_PATCHLEVEL) >= SDL_VERSIONNUM(a, b, c)) wav_t snd_load_mem(int fmt, const short *data, size_t len) { int freq = 22050, ffreq; SDL_AudioCVT wavecvt; Mix_Chunk *chunk; size_t size = len * sizeof(short); freq = snd_hz(); if (fmt & SND_FMT_11) ffreq = 11025; else if (fmt & SND_FMT_22) ffreq = 22050; else ffreq = 44100; if (audio_format != SND_DEFAULT_FORMAT || audio_channels != ((fmt & SND_FMT_STEREO) ? 2:1) || ffreq != freq) { if (SDL_BuildAudioCVT(&wavecvt, SND_DEFAULT_FORMAT, (fmt & SND_FMT_STEREO) ? 2:1, ffreq, audio_format, audio_channels, freq) < 0) return NULL; wavecvt.len = size; wavecvt.buf = (Uint8 *)SDL_calloc(1, wavecvt.len * wavecvt.len_mult); if (!wavecvt.buf) return NULL; SDL_memcpy(wavecvt.buf, data, size); if (SDL_ConvertAudio(&wavecvt) < 0) { SDL_free(wavecvt.buf); return NULL; } chunk = Mix_QuickLoad_RAW(wavecvt.buf, wavecvt.len_cvt); } else { Uint8 *b = (Uint8 *)SDL_calloc(1, size); if (!b) return NULL; SDL_memcpy(b, data, size); chunk = Mix_QuickLoad_RAW(b, size); } if (!chunk) return NULL; chunk->allocated = 1; return (wav_t)chunk; } wav_t snd_load_wav(const char *fname) { SDL_RWops *rw; wav_t r; if (!sound_on) return NULL; if (!fname || !*fname) return NULL; rw = RWFromIdf(instead_idf(), fname); if (!rw || !(r = (wav_t)Mix_LoadWAV_RW(rw, 1))) { return NULL; } return r; } void snd_free_wav(wav_t w) { if (!w) return; /* Mix_HaltChannel(-1); */ Mix_FreeChunk((Mix_Chunk*)w); } static int mix_fn = 0; void snd_halt_chan(int han, int ms) { if (han >= MIX_CHANNELS) han %= MIX_CHANNELS; if (han == -1 && mix_fn) /* forever wait */ return; if (ms) Mix_FadeOutChannel(han, ms); else { Mix_HaltChannel(han); } } mus_t snd_load_mus(const char *fname) { mus_t mus = NULL; if (!sound_on) return NULL; mus = malloc(sizeof(struct _mus_t)); if (!mus) return NULL; mus->rw = RWFromIdf(instead_idf(), fname); if (!mus->rw) goto err; mus->mus = Mix_LoadMUS_RW(mus->rw, SDL_FALSE); if (!mus->mus) goto err1; return mus; err1: SDL_RWclose(mus->rw); err: free(mus); return NULL; } extern void game_music_finished(void); int snd_play_mus(char *fname, int ms, int loop) { if (!sound_on) return 0; if (snd_playing_mus()) { if (next_mus) { free(next_mus); } next_mus = strdup(fname); next_fadein = ms; next_loop = loop; if (!timer_id) timer_id = SDL_AddTimer(200, callback, NULL); return 1; } if (mus) snd_free_mus(mus); mus = snd_load_mus(fname); if (!mus) return -1; if (loop >= 0) Mix_HookMusicFinished(game_music_finished); else Mix_HookMusicFinished(NULL); if (ms) Mix_FadeInMusic(mus->mus, loop, ms); else Mix_PlayMusic(mus->mus, loop); snd_volume_mus(snd_volume_mus(-1)); /* SDL hack? */ return 0; } void snd_stop_mus(int ms) { if (!sound_on) return; if (mix_fn) return; Mix_HookMusicFinished(NULL); if (ms) Mix_FadeOutMusic(ms); else Mix_HaltMusic(); } int snd_playing_mus(void) { if (!sound_on) return 0; if (Mix_PlayingMusic() | Mix_FadingMusic()) return 1; return 0; } int snd_playing(int channel) { if (!sound_on) return 0; if (channel >= MIX_CHANNELS) channel %= MIX_CHANNELS; if (channel < 0) channel = -1; return Mix_Playing(channel); } int snd_panning(int channel, int left, int right) { if (channel >= MIX_CHANNELS) channel %= MIX_CHANNELS; if (channel < 0) channel = -1; return Mix_SetPanning(channel, left, right); } void snd_free_mus(mus_t mus) { if (!sound_on) return; if (!mus) return; Mix_HaltMusic(); if (mus->mus) { Mix_FreeMusic((Mix_Music*) mus->mus); SDL_RWclose(mus->rw); } free(mus); } int snd_play(void *chunk, int channel, int loop) { if (!sound_on) return -1; if (!chunk) return -1; if (channel >= MIX_CHANNELS) channel %= MIX_CHANNELS; if (channel < 0) channel = -1; if (channel != -1) snd_halt_chan(channel, 0); snd_volume_mus(snd_volume_mus(-1)); /* SDL hack? */ return Mix_PlayChannel(channel, (Mix_Chunk*)chunk, loop); } void snd_mus_callback(void (*fn)(void *udata, unsigned char *stream, int len), void *arg) { mix_fn = !!fn; Mix_HookMusic(fn, arg); } void snd_close(void) { if (!sound_on) return; Mix_HookMusic(NULL, NULL); Mix_ChannelFinished(NULL); if (timer_id) { SDL_RemoveTimer(timer_id); timer_id = NULL_TIMER; } Mix_HaltChannel(-1); Mix_HookMusicFinished(NULL); Mix_HaltMusic(); if (mus) snd_free_mus(mus); mus = NULL; if (next_mus) free(next_mus); next_mus = NULL; #ifndef __EMSCRIPTEN__ Mix_CloseAudio(); #endif sound_on = 0; #ifdef SAILFISHOS audioresource_release(audio_resource); audioresource_free(audio_resource); audio_resource = NULL; #endif } void snd_done(void) { if (sound_on) snd_close(); SDL_QuitSubSystem(SDL_INIT_AUDIO); } int snd_vol_from_pcn(int v) { return (v * 127) / 100; } int snd_vol_to_pcn(int v) { return (v * 100) / 127; } instead-3.5.2+dfsg/src/sound.h000066400000000000000000000022521467622671600162010ustar00rootroot00000000000000#ifndef __SOUND_H__ #define __SOUND_H__ typedef void* wav_t; typedef struct _mus_t *mus_t; #define DEFAULT_CHUNKSIZE 1024 /* extern mus_t snd_load_mus(const char *path); */ extern void snd_free_mus(mus_t mus); extern int snd_open(int hz); extern int snd_init(int hz); extern int snd_hz(void); extern int snd_play(wav_t chunk, int channel, int loop); extern void snd_halt_chan(int han, int ms); extern void snd_free_wav(wav_t chunk); extern wav_t snd_load_wav(const char *fname); #define SND_FMT_STEREO 1 #define SND_FMT_44 2 #define SND_FMT_22 4 #define SND_FMT_11 8 extern wav_t snd_load_mem(int fmt, const short *buf, size_t len); extern int snd_play_mus(char *music, int ms, int loop); extern void snd_mus_callback(void (*fn)(void *udata, unsigned char *stream, int len), void *arg); extern int snd_playing_mus(); extern void snd_stop_mus(int ms); extern int snd_volume_mus(int vol); extern void snd_done(void); extern void snd_close(void); extern int snd_vol_from_pcn(int v); extern int snd_vol_to_pcn(int v); extern int snd_playing(int channel); extern void snd_pause(int on); extern int snd_panning(int channel, int left, int right); extern int snd_enabled(void); #endif instead-3.5.2+dfsg/src/themes.c000066400000000000000000001074341467622671600163410ustar00rootroot00000000000000/* * Copyright 2009-2022 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "internals.h" int theme_relative = 0; char *curtheme_dir[2] = { NULL, NULL }; struct theme *curtheme_loading = NULL; static int parse_win_align(const char *v, void *data) { int *i = (int *)data; if (!strcmp(v, "left")) *i = ALIGN_LEFT; else if (!strcmp(v, "justify")) *i = ALIGN_JUSTIFY; else if (!strcmp(v, "center")) *i = ALIGN_CENTER; else if (!strcmp(v, "right")) *i = ALIGN_RIGHT; else return -1; return 0; } static int parse_gfx_mode(const char *v, void *data) { int *i = (int *)data; if (!strcmp(v, "fixed")) *i = GFX_MODE_FIXED; else if (!strcmp(v, "embedded")) *i = GFX_MODE_EMBEDDED; else if (!strncmp(v, "float", 5)) { *i = GFX_MODE_FLOAT; v += 5; if (!*v) /* compat */ *i |= GFX_ALIGN_SET(ALIGN_TOP); while (*v) { if (*v != '-') return -1; v ++; if (!strncmp(v, "top", 3)) { *i |= GFX_ALIGN_SET(ALIGN_TOP); v += 3; } else if (!strncmp(v, "middle", 6)) { *i |= GFX_ALIGN_SET(ALIGN_MIDDLE); v += 6; } else if (!strncmp(v, "bottom", 6)) { *i |= GFX_ALIGN_SET(ALIGN_BOTTOM); v += 6; } else if (!strncmp(v, "left", 4)) { *i |= GFX_ALIGN_SET(ALIGN_LEFT); v += 4; } else if (!strncmp(v, "right", 5)) { *i |= GFX_ALIGN_SET(ALIGN_RIGHT); v += 5; } else if (!strncmp(v, "center", 6)) { *i |= GFX_ALIGN_SET(ALIGN_CENTER); v += 6; } else return -1; } } else if (!strcmp(v, "direct")) *i = GFX_MODE_DIRECT; else return -1; return 0; } static int out_gfx_mode(const void *v, char **out) { char *o; char buff[256]; int m = *((int*)v); switch (GFX_MODE(m)) { case GFX_MODE_FIXED: o = strdup("fixed"); break; case GFX_MODE_EMBEDDED: o = strdup("embedded"); break; case GFX_MODE_FLOAT: strcpy(buff, "float"); if (GFX_ALIGN(m) != ALIGN_TOP) { /* compat */ if (GFX_ALIGN(m) & ALIGN_TOP) strcat(buff,"-top"); else if (GFX_ALIGN(m) & ALIGN_BOTTOM) strcat(buff,"-bottom"); if (GFX_ALIGN(m) & ALIGN_LEFT) strcat(buff,"-left"); else if (GFX_ALIGN(m) & ALIGN_RIGHT) strcat(buff,"-right"); } o = strdup(buff); break; case GFX_MODE_DIRECT: o = strdup("direct"); break; default: o = strdup(""); break; } if (!o) return -1; *out = o; return 0; } static int parse_inv_mode(const char *v, void *data) { int *i = (int *)data; if (!strcmp(v, "vertical") || !strcmp(v, "0") || !strcmp(v, "vertical-left")) *i = INV_MODE_VERT | INV_ALIGN_SET(ALIGN_LEFT); else if (!strcmp(v, "horizontal") || !strcmp(v, "1") || !strcmp(v, "horizontal-center")) *i = INV_MODE_HORIZ | INV_ALIGN_SET(ALIGN_CENTER); else if (!strcmp(v, "horizontal-left") || !strcmp(v, "1")) *i = INV_MODE_HORIZ | INV_ALIGN_SET(ALIGN_LEFT); else if (!strcmp(v, "horizontal-right") || !strcmp(v, "1")) *i = INV_MODE_HORIZ | INV_ALIGN_SET(ALIGN_RIGHT); else if (!strcmp(v, "disabled") || !strcmp(v, "-1")) *i = INV_MODE_DISABLED; else if (!strcmp(v, "vertical-right")) *i = INV_MODE_VERT | INV_ALIGN_SET(ALIGN_RIGHT); else if (!strcmp(v, "vertical-center")) *i = INV_MODE_VERT | INV_ALIGN_SET(ALIGN_CENTER); else return -1; return 0; } static int parse_ways_mode(const char *v, void *data) { int *i = (int *)data; if (!strcmp(v, "top")) *i = ALIGN_TOP; else if (!strcmp(v, "bottom")) *i = ALIGN_BOTTOM; else return -1; return 0; } static int out_ways_mode(const void *v, char **out) { char *o; int m = *((int*)v); o = malloc(64); if (!o) return -1; if (m == ALIGN_BOTTOM) sprintf(o, "bottom"); else sprintf(o, "top"); *out = o; return 0; } static int out_inv_mode(const void *v, char **out) { char *o; int m = *((int*)v); o = malloc(64); if (!o) return -1; if (m == INV_MODE_DISABLED) { sprintf(o, "disabled"); *out = o; return 0; } if ((INV_MODE(m) == INV_MODE_HORIZ)) sprintf(o, "horizontal"); else sprintf(o, "vertical"); if ((m & INV_ALIGN_SET(ALIGN_CENTER)) == INV_ALIGN_SET(ALIGN_CENTER)) { strcat(o, "-center"); } else if ((m & INV_ALIGN_SET(ALIGN_LEFT)) == INV_ALIGN_SET(ALIGN_LEFT)) { strcat(o, "-left"); } else if ((m & INV_ALIGN_SET(ALIGN_RIGHT)) == INV_ALIGN_SET(ALIGN_RIGHT)) { strcat(o, "-right"); } *out = o; return 0; } static int parse_color(const char *v, void *data) { color_t *c = (color_t *)data; return gfx_parse_color(v, c); } static int out_color(const void *v, char **out) { char *o; color_t *c = (color_t *)v; o = malloc(16); if (!o) return -1; sprintf(o, "#%02x%02x%02x", c->r, c->g, c->b); *out = o; return 0; } int parse_dpi(const char *v, void *data) { struct dpi *dpi = (struct dpi*)data; if (sscanf(v, "%d-%d", &dpi->min, &dpi->max) != 2) { if (sscanf(v, "%d", &dpi->min) != 1) { dpi->min = DEFAULT_DPI_MIN; dpi->max = DEFAULT_DPI_MAX; return -1; } dpi->max = dpi->min; } return 0; } static int out_dpi(const void *v, char **out) { char *o; struct dpi *dpi = (struct dpi *)v; o = malloc(64); if (!o) return -1; if (dpi->min == dpi->max) sprintf(o, "%d", dpi->min); else sprintf(o, "%d-%d", dpi->min, dpi->max); *out = o; return 0; } static int parse_include(const char *v, void *data) { int rc; char cwd[PATH_MAX]; if (!strlowcmp(v, DEFAULT_THEME)) return 0; if (curtheme_loading && curtheme_loading->type == THEME_GAME && strlowcmp(v, curtheme_loading->dir) && theme_lookup(v, THEME_GAME)) { /* internal theme? */ return game_theme_load(v, THEME_GAME); } getdir(cwd, sizeof(cwd)); setdir(game_cwd); rc = game_theme_load(v, THEME_GLOBAL); /* if (!rc) game_theme_select(v); */ setdir(cwd); return rc; } static int theme_parse_full_path(const char *v, void *data) { int rc; char **p = (char **)data; char *np; if (theme_relative) { if (!strncmp(v, "blank:", 6) || !strncmp(v, "box:", 4) || !strncmp(v, "spr:", 4)) /* hack for special files*/ return parse_path(v, data); rc = parse_path(v, data); if (rc || !*p || !*p[0]) return rc; if (curtheme_loading && curtheme_loading->type == THEME_GAME) { np = getfilepath(curtheme_loading->path, *p); if (!*np) return -1; free(*p); *p = np; } return 0; } return parse_full_path(v, data); } struct parser cmd_parser[] = { { "scr.w", parse_int, &game_theme.w, 0 }, /* must be 0 */ { "scr.h", parse_int, &game_theme.h, 0 }, /* must be 1, see scale_aware logic */ { "scr.scale_aware", parse_int, &game_theme.scale_aware, 0 }, { "scr.dpi", parse_dpi, &game_theme.dpi, 0 }, { "scr.gfx.scalable", parse_int, &game_theme.gfx_scalable, CHANGED_ALL }, { "scr.gfx.scale", parse_float, &game_theme.img_scale, CHANGED_IMG }, { "scr.col.bg", parse_color, &game_theme.bgcol, 0 }, { "scr.col.brd", parse_color, &game_theme.brdcol, 0 }, { "scr.gfx.icon", theme_parse_full_path, &game_theme.icon_name, CHANGED_ICON }, { "scr.gfx.bg", theme_parse_full_path, &game_theme.bg_name, CHANGED_BG }, { "scr.gfx.cursor.normal", theme_parse_full_path, &game_theme.cursor_name, CHANGED_CURSOR }, { "scr.gfx.cursor.x", parse_int, &game_theme.cur_x, 0 }, { "scr.gfx.cursor.y", parse_int, &game_theme.cur_y, 0 }, { "scr.gfx.use", theme_parse_full_path, &game_theme.use_name, CHANGED_USE }, /* compat */ { "scr.gfx.cursor.use", theme_parse_full_path, &game_theme.use_name, CHANGED_USE }, { "scr.gfx.pad", parse_int, &game_theme.pad, CHANGED_WIN | CHANGED_INV }, { "scr.gfx.x", parse_int, &game_theme.gfx_x, 0 }, { "scr.gfx.y", parse_int, &game_theme.gfx_y, 0 }, { "scr.gfx.w", parse_int, &game_theme.max_scene_w, 0 }, { "scr.gfx.h", parse_int, &game_theme.max_scene_h, 0 }, { "scr.gfx.mode", parse_gfx_mode, &game_theme.gfx_mode, CHANGED_WIN }, { "win.align", parse_win_align, &game_theme.win_align, CHANGED_WIN }, { "win.x", parse_int, &game_theme.win_x, CHANGED_WIN }, { "win.y", parse_int, &game_theme.win_y, CHANGED_WIN }, { "win.w", parse_int, &game_theme.win_w, CHANGED_WIN }, { "win.h", parse_int, &game_theme.win_h, CHANGED_WIN }, { "win.ways.mode", parse_ways_mode, &game_theme.ways_mode, CHANGED_WIN }, { "win.scroll.mode", parse_int, &game_theme.win_scroll_mode, CHANGED_WIN }, { "win.fnt.name", theme_parse_full_path, &game_theme.font_name, CHANGED_FONT | CHANGED_WIN }, { "win.fnt.size", parse_int, &game_theme.font_size, CHANGED_FONT | CHANGED_WIN }, { "win.fnt.height", parse_float, &game_theme.font_height, CHANGED_WIN }, /* compat mode directive */ { "win.gfx.h", parse_int, &game_theme.max_scene_h, CHANGED_WIN }, /* here it was */ { "win.gfx.up", theme_parse_full_path, &game_theme.a_up_name, CHANGED_UP | CHANGED_WIN}, { "win.gfx.down", theme_parse_full_path, &game_theme.a_down_name, CHANGED_DOWN | CHANGED_WIN}, { "win.up.x", parse_int, &game_theme.a_up_x, CHANGED_WIN }, { "win.up.y", parse_int, &game_theme.a_up_y, CHANGED_WIN }, { "win.down.x", parse_int, &game_theme.a_down_x, CHANGED_WIN }, { "win.down.y", parse_int, &game_theme.a_down_y, CHANGED_WIN }, { "win.col.fg", parse_color, &game_theme.fgcol, CHANGED_WIN }, { "win.col.link", parse_color, &game_theme.lcol, CHANGED_WIN }, { "win.col.alink", parse_color, &game_theme.acol, CHANGED_WIN }, { "inv.x", parse_int, &game_theme.inv_x, CHANGED_INV }, { "inv.y", parse_int, &game_theme.inv_y, CHANGED_INV }, { "inv.w", parse_int, &game_theme.inv_w, CHANGED_INV }, { "inv.h", parse_int, &game_theme.inv_h, CHANGED_INV }, { "inv.mode", parse_inv_mode, &game_theme.inv_mode, CHANGED_INV }, { "inv.horiz", parse_inv_mode, &game_theme.inv_mode, CHANGED_INV }, { "inv.col.fg", parse_color, &game_theme.icol, CHANGED_INV }, { "inv.col.link", parse_color, &game_theme.ilcol, CHANGED_INV }, { "inv.col.alink", parse_color, &game_theme.iacol, CHANGED_INV }, { "inv.fnt.name", theme_parse_full_path, &game_theme.inv_font_name, CHANGED_IFONT | CHANGED_INV }, { "inv.fnt.size", parse_int, &game_theme.inv_font_size, CHANGED_IFONT | CHANGED_INV }, { "inv.fnt.height", parse_float, &game_theme.inv_font_height, CHANGED_INV }, { "inv.gfx.up", theme_parse_full_path, &game_theme.inv_a_up_name, CHANGED_IUP | CHANGED_INV }, { "inv.gfx.down", theme_parse_full_path, &game_theme.inv_a_down_name, CHANGED_IDOWN | CHANGED_INV}, { "inv.up.x", parse_int, &game_theme.inv_a_up_x, CHANGED_INV }, { "inv.up.y", parse_int, &game_theme.inv_a_up_y, CHANGED_INV }, { "inv.down.x", parse_int, &game_theme.inv_a_down_x, CHANGED_INV }, { "inv.down.y", parse_int, &game_theme.inv_a_down_y, CHANGED_INV }, { "menu.col.bg", parse_color, &game_theme.menu_bg, 0 }, { "menu.col.fg", parse_color, &game_theme.menu_fg, 0 }, { "menu.col.link", parse_color, &game_theme.menu_link, 0 }, { "menu.col.alink", parse_color, &game_theme.menu_alink, 0 }, { "menu.col.alpha", parse_int, &game_theme.menu_alpha, 0 }, { "menu.col.border", parse_color, &game_theme.border_col, 0 }, { "menu.bw", parse_int, &game_theme.border_w, 0 }, { "menu.fnt.name", theme_parse_full_path, &game_theme.menu_font_name, CHANGED_MFONT }, { "menu.fnt.size", parse_int, &game_theme.menu_font_size, CHANGED_MFONT }, { "menu.fnt.height", parse_float, &game_theme.menu_font_height, 0 }, { "menu.gfx.button", theme_parse_full_path, &game_theme.menu_button_name, CHANGED_BUTTON }, { "menu.button.x", parse_int, &game_theme.menu_button_x, 0 }, { "menu.button.y", parse_int, &game_theme.menu_button_y, 0 }, /* compat */ { "menu.buttonx", parse_int, &game_theme.menu_button_x, 0 }, { "menu.buttony", parse_int, &game_theme.menu_button_y, 0 }, { "snd.click", theme_parse_full_path, &game_theme.click_name, CHANGED_CLICK }, { "include", parse_include, NULL, 0 }, { NULL, NULL, NULL, 0 }, }; #define TF_POSX 1 #define TF_POSY 2 #define TF_NEG 4 typedef struct { const char *name; int *val; int flags; } theme_scalable_t; static theme_scalable_t theme_scalables[] = { { "scr.w", &game_theme.w, 0 }, { "scr.h", &game_theme.h, 0 }, { "scr.gfx.cursor.x", &game_theme.cur_x, 0 }, { "scr.gfx.cursor.y", &game_theme.cur_y, 0 }, { "scr.gfx.pad", &game_theme.pad, 0 }, { "scr.gfx.x", &game_theme.gfx_x, TF_POSX }, { "scr.gfx.y", &game_theme.gfx_y, TF_POSY }, { "scr.gfx.w", &game_theme.max_scene_w, TF_NEG }, { "scr.gfx.h", &game_theme.max_scene_h, TF_NEG }, { "win.x", &game_theme.win_x, TF_POSX }, { "win.y", &game_theme.win_y, TF_POSY }, { "win.w", &game_theme.win_w, 0 }, { "win.h", &game_theme.win_h, 0 }, { "win.fnt.size", &game_theme.font_size, 0 }, { "inv.x", &game_theme.inv_x, TF_POSX }, { "inv.y", &game_theme.inv_y, TF_POSY }, { "inv.w", &game_theme.inv_w, 0 }, { "inv.h", &game_theme.inv_h, 0 }, { "inv.fnt.size", &game_theme.inv_font_size, 0 }, { "menu.fnt.size", &game_theme.menu_font_size, 0 }, { "menu.button.x", &game_theme.menu_button_x, TF_POSX }, { "menu.button.y", &game_theme.menu_button_y, TF_POSY }, { "win.up.x", &game_theme.a_up_x, TF_POSX | TF_NEG }, { "win.up.y", &game_theme.a_up_y, TF_POSY | TF_NEG }, { "win.down.x", &game_theme.a_down_x, TF_POSX | TF_NEG }, { "win.down.y", &game_theme.a_down_y, TF_POSY | TF_NEG }, { "inv.up.x", &game_theme.inv_a_up_x, TF_POSX | TF_NEG }, { "inv.up.y", &game_theme.inv_a_up_y, TF_POSY | TF_NEG }, { "inv.down.x", &game_theme.inv_a_down_x, TF_POSX | TF_NEG }, { "inv.down.y", &game_theme.inv_a_down_y, TF_POSY | TF_NEG }, { NULL, NULL, 0 }, }; static int theme_scalables_unscaled[sizeof(theme_scalables)/sizeof(theme_scalable_t)]; struct game_theme game_theme; static void free_theme_strings(void) { struct game_theme *t = &game_theme; FREE(t->use_name); FREE(t->icon_name); FREE(t->cursor_name); FREE(t->bg_name); FREE(t->inv_a_up_name); FREE(t->inv_a_down_name); FREE(t->a_down_name); FREE(t->a_up_name); FREE(t->font_name); FREE(t->inv_font_name); FREE(t->menu_font_name); FREE(t->menu_button_name); FREE(t->click_name); } int game_theme_free(void) { free_theme_strings(); if (game_theme.font) fnt_free(game_theme.font); if (game_theme.inv_font) fnt_free(game_theme.inv_font); if (game_theme.menu_font) fnt_free(game_theme.menu_font); if (game_theme.a_up) gfx_free_image(game_theme.a_up); if (game_theme.a_down) gfx_free_image(game_theme.a_down); if (game_theme.inv_a_up) gfx_free_image(game_theme.inv_a_up); if (game_theme.inv_a_down) gfx_free_image(game_theme.inv_a_down); if (game_theme.use) gfx_free_image(game_theme.use); if (game_theme.cursor) { gfx_free_image(game_theme.cursor); gfx_set_cursor(NULL, 0, 0); } if (game_theme.bg) gfx_free_image(game_theme.bg); if (game_theme.menu_button) gfx_free_image(game_theme.menu_button); if (game_theme.click) { sound_put(game_theme.click); } if (game_theme.icon) { gfx_set_icon(NULL); gfx_free_image(game_theme.icon); } game_theme.font = game_theme.inv_font = game_theme.menu_font = NULL; game_theme.a_up = game_theme.a_down = game_theme.use = NULL; game_theme.inv_a_up = game_theme.inv_a_down = NULL; game_theme.menu_button = NULL; game_theme.bg = NULL; game_theme.click = NULL; game_theme.cur_x = game_theme.cur_y = 0; game_theme.cursor = game_theme.use = NULL; game_theme.icon = NULL; return 0; } int theme_img_scale(img_t *p) { return theme_gfx_scale(p, game_theme.img_scale); } int theme_gfx_scale(img_t *p, float scale) { img_t pic; float v = game_theme.scale * scale; if (!p || !*p || v == 1.0f) return 0; if (!cache_have(gfx_image_cache(), *p)) return 0; /* do not scale sprites! */ pic = gfx_scale(*p, v, v, SCALABLE_THEME_SMOOTH); if (!pic) return -1; gfx_free_image(*p); *p = pic; return 0; } static int game_theme_scale(int w, int h) { int i; float xs, ys, v; int xoff, yoff; struct game_theme *t = &game_theme; if ((w < 0 || h < 0) && opt_hires) { int ww = 0, hh = 0; float dpi = gfx_get_dpi(); if (dpi > game_theme.dpi.max && game_theme.dpi.max > 0) dpi = dpi / (float)game_theme.dpi.max; else if (dpi < game_theme.dpi.min && game_theme.dpi.min > 0) dpi = dpi / (float)game_theme.dpi.min; else dpi = 1.0f; if ((SCALABLE_THEME || dpi > 1.0f) && !gfx_get_max_mode(&ww, &hh, MODE_ANY)) { w = t->w * dpi; h = t->h * dpi; xs = ys = dpi; if (w > ww) xs = (float)ww / (float)t->w; if (h > hh) ys = (float)hh / (float)t->h; v = (xs < ys)?xs:ys; w = t->w * v; h = t->h * v; printf("DPI scale: %f\n", v); } } if (w < 0 || h < 0 || (w == t->w && h == t->h)) { t->scale = 1.0f; t->xoff = 0; t->yoff = 0; w = t->w; h = t->h; goto out; } xs = (float)w / (float)t->w; ys = (float)h / (float)t->h; v = (xs < ys)?xs:ys; if (!SCALABLE_THEME) { if (v > 1.0f) { int ff = 1; while (ff && ff <= v && ff < 0x1000) ff <<= 1; ff >>= 1; v = ff; } else { float f = ceil(1.0f / v); int ff = 1; while (ff && ff < f && ff < 0x1000) ff <<= 1; v = 1.0f / (float)ff; } } xoff = (w - t->w*v)/2; yoff = (h - t->h*v)/2; if (xoff < 0) xoff = 0; if (yoff < 0) yoff = 0; t->scale = v; t->xoff = xoff; t->yoff = yoff; out: for (i = 0; theme_scalables[i].name; i++) { int val = *(theme_scalables[i].val); theme_scalables_unscaled[i] = val; if (val == -1 && (theme_scalables[i].flags & TF_NEG)) continue; val *= t->scale; if (theme_scalables[i].flags & TF_POSX) val += t->xoff; if (theme_scalables[i].flags & TF_POSY) val += t->yoff; *(theme_scalables[i].val) = val; } t->w = w; t->h = h; if (t->scale_aware) { if (t->scale_aware == 2) { t->img_scale *= t->scale; t->scale = 1.0f; } t->xoff = t->yoff = 0; theme_scalables_unscaled[0] = w / t->scale; theme_scalables_unscaled[1] = h / t->scale; for (i = 2; theme_scalables[i].name; i++) theme_scalables_unscaled[i] = *(theme_scalables[i].val) / t->scale; } return 0; } extern int parse_relative_path; char *theme_getvar(char *name) { int i; for (i = 0; theme_scalables[i].name; i ++) { int val; char buf[64]; if (strcmp(theme_scalables[i].name, name)) continue; val = theme_scalables_unscaled[i]; sprintf(buf, "%d", val); return strdup(buf); } /* so, it is a string or like this */ for (i = 0; cmd_parser[i].cmd; i++) { int *num; char *s; float *f; char buf[64]; if (strcmp(cmd_parser[i].cmd, name)) continue; if (cmd_parser[i].fn == parse_int) { num = (int *)cmd_parser[i].p; sprintf(buf, "%d", *num); return strdup(buf); } else if (cmd_parser[i].fn == theme_parse_full_path) { s = *((char **)cmd_parser[i].p); if (!s) return NULL; return strdup(s); } else if (cmd_parser[i].fn == parse_inv_mode) { if (out_inv_mode(cmd_parser[i].p, &s)) return NULL; return s; } else if (cmd_parser[i].fn == parse_ways_mode) { if (out_ways_mode(cmd_parser[i].p, &s)) return NULL; return s; } else if (cmd_parser[i].fn == parse_gfx_mode) { if (out_gfx_mode(cmd_parser[i].p, &s)) return NULL; return s; } else if (cmd_parser[i].fn == parse_float) { f = (float*)cmd_parser[i].p; sprintf(buf, "%f", *f); return strdup(buf); } else if (cmd_parser[i].fn == parse_color) { if (out_color(cmd_parser[i].p, &s)) return NULL; return s; } else if (cmd_parser[i].fn == parse_dpi) { if (out_dpi(cmd_parser[i].p, &s)) return NULL; return s; } else return NULL; break; } return NULL; } static int theme_process_cmd(char *n, char *v, struct parser *cmd_parser) { int i; n = strip(n); v = strip(v); if (process_cmd(n, v, cmd_parser)) return -1; for (i = 0; cmd_parser[i].cmd; i++) { if (!strcmp(cmd_parser[i].cmd, n)) { game_theme.changed |= cmd_parser[i].aux; return 0; } } return -1; } int theme_setvar(char *name, char *val) { int rc = -1; struct game_theme *t = &game_theme; theme_relative = 1; if (!theme_process_cmd(name, val, cmd_parser)) { int i; for (i = 0; theme_scalables[i].name; i++) { int val; if (strcmp(theme_scalables[i].name, name)) continue; val = *(theme_scalables[i].val); theme_scalables_unscaled[i] = val; if (val == -1 && (theme_scalables[i].flags & TF_NEG)) continue; val *= t->scale; if (theme_scalables[i].flags & TF_POSX) val += t->xoff; if (theme_scalables[i].flags & TF_POSY) val += t->yoff; *(theme_scalables[i].val) = val; break; } rc = 0; } theme_relative = 0; return rc; } static int theme_bg_scale(void) { struct game_theme *t = &game_theme; if (t->bg) { img_t screen, pic; int xoff = (t->w - gfx_img_w(t->bg))/2; int yoff = (t->h - gfx_img_h(t->bg))/2; if (xoff < 0) xoff = 0; if (yoff < 0) yoff = 0; if (gfx_img_w(t->bg) < t->w || gfx_img_h(t->bg) < t->h) { pic = gfx_new(t->w, t->h); if (!pic) return -1; screen = gfx_screen(pic); gfx_img_fill(pic, 0, 0, t->w, t->h, gfx_col(t->brdcol.r, t->brdcol.g, t->brdcol.b)); gfx_copy(t->bg, xoff, yoff); gfx_screen(screen); gfx_free_image(t->bg); t->bg = pic; } } return 0; } int game_theme_optimize(void) { /* todo: check errors */ struct game_theme *t = &game_theme; if (t->bg && cache_have(gfx_image_cache(), t->bg)) { t->bg = gfx_display_alpha(t->bg); gfx_unset_alpha(t->bg); } if (t->a_up && cache_have(gfx_image_cache(), t->a_up)) t->a_up = gfx_display_alpha(t->a_up); if (t->a_down && cache_have(gfx_image_cache(), t->a_down)) t->a_down = gfx_display_alpha(t->a_down); if (t->inv_a_up && cache_have(gfx_image_cache(), t->inv_a_up)) t->inv_a_up = gfx_display_alpha(t->inv_a_up); if (t->inv_a_down && cache_have(gfx_image_cache(), t->inv_a_down)) t->inv_a_down = gfx_display_alpha(t->inv_a_down); if (t->use && cache_have(gfx_image_cache(), t->use)) t->use = gfx_display_alpha(t->use); if (t->cursor && cache_have(gfx_image_cache(), t->cursor)) { t->cursor = gfx_display_alpha(t->cursor); gfx_set_cursor(t->cursor, t->cur_x, t->cur_y); } if (t->menu_button && cache_have(gfx_image_cache(), t->menu_button)) t->menu_button = gfx_display_alpha(t->menu_button); return 0; } static int game_theme_update_data(void) { struct game_theme *t = &game_theme; const char *res = NULL; int idf = idf_only(instead_idf(), 0); if (t->font_name && (t->changed & CHANGED_FONT)) { fnt_free(t->font); if (!(t->font = fnt_load(t->font_name, FONT_SZ(t->font_size)))) { res = t->font_name; goto err; } } if (t->inv_font_name && (t->changed & CHANGED_IFONT)) { fnt_free(t->inv_font); if (!(t->inv_font = fnt_load(t->inv_font_name, FONT_SZ(t->inv_font_size)))) { res = t->inv_font_name; goto err; } } if (t->menu_font_name && (t->changed & CHANGED_MFONT)) { int m = FONT_SZ(t->menu_font_size); if (MAX_MENU_LINES * m * game_theme.menu_font_height > game_theme.h) m = game_theme.h / MAX_MENU_LINES / game_theme.menu_font_height; else if (m < t->menu_font_size) m = t->menu_font_size; /* fprintf(stderr, "%d %d > %d? %d", (int)FONT_SZ(t->inv_font_size), (int)FONT_SZ(t->inv_font_size) * MAX_MENU_LINES, game_theme.h, m); */ fnt_free(t->menu_font); if (!(t->menu_font = fnt_load(t->menu_font_name, m))) { /* do not scale menu!!! */ res = t->menu_font_name; goto err; } } if (t->a_up_name && (t->changed & CHANGED_UP)) { gfx_free_image(t->a_up); if (!(t->a_up = gfx_load_image(t->a_up_name))) { res = t->a_up_name; goto err; } if (theme_img_scale(&t->a_up)) goto err; } if (t->a_down_name && (t->changed & CHANGED_DOWN)) { gfx_free_image(t->a_down); if (!(t->a_down = gfx_load_image(t->a_down_name))) { res = t->a_down_name; goto err; } if (theme_img_scale(&t->a_down)) goto err; } if (t->inv_a_up_name && (t->changed & CHANGED_IUP)) { gfx_free_image(t->inv_a_up); if (!(t->inv_a_up = gfx_load_image(t->inv_a_up_name))) { res = t->inv_a_up_name; goto err; } if (theme_img_scale(&t->inv_a_up)) goto err; } if (t->inv_a_down_name && (t->changed & CHANGED_IDOWN)) { gfx_free_image(t->inv_a_down); if (!(t->inv_a_down = gfx_load_image(t->inv_a_down_name))) { res = t->inv_a_down_name; goto err; } if (theme_img_scale(&t->inv_a_down)) goto err; } if (t->bg_name && (t->changed & CHANGED_BG)) { gfx_free_image(t->bg); t->bg = NULL; if (t->bg_name[0] && !(t->bg = gfx_load_image(t->bg_name))) { res = t->bg_name; goto skip; /* not fatal */ } if (theme_img_scale(&t->bg)) goto err; if (theme_bg_scale()) goto err; } skip: if (t->icon_name && (t->changed & CHANGED_ICON)) { if (t->icon) gfx_free_image(t->icon); t->icon = gfx_load_image(t->icon_name); } if (t->use_name && (t->changed & CHANGED_USE)) { gfx_free_image(t->use); if (!(t->use = gfx_load_image(t->use_name))) { res = t->use_name; goto err; } if (theme_img_scale(&t->use)) goto err; } if (t->cursor_name && (t->changed & CHANGED_CURSOR)) { gfx_free_image(t->cursor); if (!(t->cursor = gfx_load_image(t->cursor_name))) { res = t->cursor_name; goto err; } if (theme_img_scale(&t->cursor)) goto err; gfx_set_cursor(t->cursor, t->cur_x, t->cur_y); } if (t->menu_button_name && (t->changed & CHANGED_BUTTON)) { gfx_free_image(t->menu_button); if (!(t->menu_button = gfx_load_image(t->menu_button_name))) { res = t->menu_button_name; goto err; } if (theme_img_scale(&t->menu_button)) goto err; } if (t->click_name && (t->changed & CHANGED_CLICK)) { sound_put(t->click); t->click = sound_get(t->click_name); } /* free_theme_strings(); */ /* todo, font */ t->changed = 0; if (!t->cursor || !t->use || !t->inv_a_up || !t->inv_a_down || !t->a_down || !t->a_up || !t->font || !t->inv_font || !t->menu_font || !t->menu_button) { fprintf(stderr,"Can't init theme. Not all required elements are defined.\n"); goto err; } idf_only(instead_idf(), idf); return 0; err: idf_only(instead_idf(), idf); t->changed = 0; game_res_err_msg(res, 1); return -1; } int game_theme_update(void) { game_theme_changed = 0; game_release_theme(0); if (game_theme_update_data()) { fprintf(stderr, "Can not update theme!\n"); game_release_theme(1); game_error(); return -1; } if (game_apply_theme()) { fprintf(stderr, "Can not apply theme!\n"); game_error(); return -1; } return 0; } #if defined(ANDROID) || defined(IOS) || defined(WINRT) || defined(_USE_SWROTATE) extern void rotate_landscape(void); extern void rotate_portrait(void); extern void unlock_rotation(void); #endif int game_theme_init(void) { int w = opt_mode[0]; int h = opt_mode[1]; game_cursor_show = 1; if (opt_fs && opt_hires && !gfx_get_max_mode(&w, &h, MODE_ANY)) { #if defined(IOS) || defined(ANDROID) || defined(WINRT) || defined(_USE_SWROTATE) if ((game_theme.w > game_theme.h && w < h) || (game_theme.w < game_theme.h && w > h)) { /* rotated */ if (gfx_get_max_mode(&w, &h, (game_theme.w > game_theme.h)?MODE_H:MODE_V)) { gfx_get_max_mode(&w, &h, MODE_ANY); /* fallback to any mode */ } } if (game_theme.w > game_theme.h) rotate_landscape(); else if (game_theme.w < game_theme.h) rotate_portrait(); else unlock_rotation(); #if defined(ANDROID) usleep(100000); gfx_get_max_mode(&w, &h, MODE_ANY); #endif #endif } #if defined(ANDROID) || defined(IOS) || defined(WINRT) || defined(_USE_SWROTATE) else { unlock_rotation(); } #endif if (w == -1) { /* as theme */ #if !defined(IOS) && !defined(SAILFISHOS) /* always hardware accelerated */ if (gfx_get_max_mode(&w, &h, MODE_ANY) || (game_theme.w <= w && game_theme.h <= h)) { w = opt_mode[0]; h = opt_mode[1]; } #endif } game_theme_scale(w, h); if (gfx_set_mode(game_theme.w, game_theme.h, opt_fs)) { opt_mode[0] = opt_mode[1] = -1; opt_fs = 0; /* safe options */ return -1; } if (game_theme_update_data()) { fprintf(stderr, "Can not init theme!\n"); game_theme_free(); game_theme_select(DEFAULT_THEME); return -1; } gfx_bg(game_theme.xoff, game_theme.yoff, game_theme.w - 2*game_theme.xoff, game_theme.h - 2*game_theme.yoff, game_theme.bgcol, game_theme.brdcol); game_clear_all(); gfx_flip(); gfx_commit(); return 0; } static int theme_parse_idf(idf_t idf, const char *path) { idff_t idff = NULL; if (idf) idff = idf_open(idf, path); if (idff) { int rc = parse_idff(idff, path, cmd_parser); idf_close(idff); if (rc) fprintf(stderr, "Theme parsed with errors!\n"); return rc; } if (parse_ini(dirpath(path), cmd_parser)) { fprintf(stderr, "Theme parsed with errors!\n"); /* game_theme_free(); */ return -1; } return 0; } int theme_load(const char *name) { idf_t idf = NULL; if (theme_relative) idf = instead_idf(); if (theme_parse_idf(idf, name)) return 0; /* no theme loaded if error in parsing */ return 0; } int theme_load_idf(idf_t idf, const char *name) { if (theme_parse_idf(idf, name)) return 0; /* no theme loaded if error in parsing */ return 0; } struct theme *themes = NULL; int themes_nr = 0; static int is_theme_idf(idf_t idf, const char *path, const char *n) { int rc = 0; char *p = getpath(path, n); char *pp; if (!p) return 0; pp = malloc(strlen(p) + strlen(THEME_FILE) + 1); if (pp) { strcpy(pp, p); strcat(pp, THEME_FILE); if (idf) rc = !idf_access(idf, pp); else rc = !access(pp, R_OK); free(pp); } free(p); return rc; } static int is_theme(const char *path, const char *n) { if (!n) return 0; if (!strcmp("..", n) || !strcmp(".", n)) return 0; return is_theme_idf(NULL, path, n); } static char *theme_name(const char *path, const char *d_name) { char *l; char *p = getfilepath(path, THEME_FILE); if (!p) goto err; l = lookup_lang_tag(p, "Name", ";", opt_lang); free(p); if (l) return l; err: return strdup(d_name); } static char *theme_name_idf(idf_t idf, const char *path, const char *d_name) { char *l; char *p = getfilepath(path, THEME_FILE); if (!p) goto err; l = lookup_lang_tag_idf(idf, p, "Name", ";", opt_lang); free(p); if (l) return l; err: return strdup(d_name); } static int cmp_theme(const void *p1, const void *p2) { const struct theme *t1 = (const struct theme*)p1; const struct theme *t2 = (const struct theme*)p2; if (t1->type != t2->type) return t1->type - t2->type; return strcmp(t1->name, t2->name); } static void themes_sort() { qsort(themes, themes_nr, sizeof(struct theme), cmp_theme); } struct theme *theme_lookup(const char *name, int type); int themes_count(int type) { int rc = 0; int i; for (i = 0; i < themes_nr; i++) rc = rc + (themes[i].type == type); return rc; } int themes_max(int *type) { int n; int count = themes_count(THEME_GLOBAL); if (type) *type = THEME_GLOBAL; if ((n = themes_count(THEME_GAME)) > 0 && opt_owntheme) { count = n; if (type) *type = THEME_GAME; } return count; } void themes_drop(int type) { int new_size; struct theme *new_themes = NULL; int rc, i, k = 0; rc = themes_count(type); if (!rc) return; new_size = (themes_nr - rc) * sizeof(struct theme); if (new_size) new_themes = malloc(new_size); if (!new_themes) { fprintf(stderr, "Fatal: can't alloc memory.\n"); return; } for (i = 0; i < themes_nr; i ++) { if (themes[i].type == type) { free(themes[i].path); free(themes[i].dir); free(themes[i].name); } else { char *p = curtheme_dir[themes[i].type]; new_themes[k++] = themes[i]; if (p && !strlowcmp(p, themes[i].dir)) curtheme_dir[themes[i].type] = p; } } themes_nr = k; curtheme_dir[type] = NULL; free(themes); themes = new_themes; } int themes_lookup_idf(idf_t idf, const char *path, int type) { char *p; idff_t idf_dir; int n = 0, i = 0; struct theme *new_themes; char *idf_de; if (!idf) return -1; idf_dir = idf_opendir(idf, path); if (!idf_dir) return -1; while ((idf_de = idf_readdir(idf_dir))) { if (theme_lookup(idf_de, type)) continue; if (!is_theme_idf(idf, path, idf_de)) continue; n ++; } if (!n) goto out; idf_closedir(idf_dir); idf_dir = idf_opendir(idf, path); if (!idf_dir) return -1; new_themes = realloc(themes, sizeof(struct theme) * (n + themes_nr)); if (!new_themes) { idf_closedir(idf_dir); return -1; } themes = new_themes; while ((idf_de = idf_readdir(idf_dir)) && i < n) { if (theme_lookup(idf_de, type)) continue; if (!is_theme_idf(idf, path, idf_de)) continue; p = getpath(path, idf_de); themes[themes_nr].path = p; themes[themes_nr].dir = strdup(idf_de); themes[themes_nr].name = theme_name_idf(idf, p, idf_de); themes[themes_nr].type = type; themes[themes_nr].idf = 1; themes_nr ++; i ++; } out: idf_closedir(idf_dir); themes_sort(); return 0; } int themes_lookup(const char *path, int type) { char *p; int n = 0, i = 0; DIR *d; struct dirent *de; struct theme *new_themes; if (!path) return 0; d = opendir(path); if (!d) return -1; while ((de = readdir(d))) { if (theme_lookup(de->d_name, type)) continue; if (!is_theme(path, de->d_name)) continue; n ++; } if (!n) goto out; closedir(d); d = opendir(path); if (!d) return -1; new_themes = realloc(themes, sizeof(struct theme) * (n + themes_nr)); if (!new_themes) { closedir(d); return -1; } themes = new_themes; while ((de = readdir(d)) && i < n) { /*if (de->d_type != DT_DIR) continue;*/ if (theme_lookup(de->d_name, type)) continue; if (!is_theme(path, de->d_name)) continue; p = getpath(path, de->d_name); themes[themes_nr].path = p; themes[themes_nr].dir = strdup(de->d_name); themes[themes_nr].name = theme_name(p, de->d_name); themes[themes_nr].type = type; themes[themes_nr].idf = 0; themes_nr ++; i ++; } out: closedir(d); themes_sort(); return 0; } int themes_rename(void) { int i; char cwd[PATH_MAX]; getdir(cwd, sizeof(cwd)); setdir(game_cwd); for (i = 0; i < themes_nr; i++) { FREE(themes[i].name); themes[i].name = theme_name(dirpath(themes[i].path), themes[i].dir); } setdir(cwd); return 0; } struct theme *theme_lookup(const char *name, int type) { int i; if (!name || !*name) { if (themes_nr == 1 && themes[0].type == type) return &themes[0]; return NULL; } for (i = 0; iidf) setdir(game->path); theme_relative = 1; } theme = theme_lookup(name, type); if (!theme) goto err; if (theme->idf) /* cwd is always game_cwd */ strcpy(cwd, idf_getdir(instead_idf())); curtheme_loading = theme; if (theme->idf) { if (idf_setdir(instead_idf(), theme->path)) goto err; if (theme_load_idf(instead_idf(), THEME_FILE)) goto err; } else { if (setdir(theme->path)) goto err; if (theme_load(THEME_FILE)) goto err; } rc = 0; err: curtheme_loading = otheme; if (theme && theme->idf) idf_setdir(instead_idf(), cwd); else setdir(cwd); theme_relative = rel; return rc; } int game_theme_select(const char *name) { struct theme *theme; theme = theme_lookup(name, THEME_GAME); if (theme) { curtheme_dir[THEME_GAME] = theme->dir; game_cfg_save(); return 0; } theme = theme_lookup(name, THEME_GLOBAL); if (!theme) return -1; curtheme_dir[THEME_GLOBAL] = theme->dir; return 0; } int game_default_theme(void) { int rc; memset(&game_theme, 0, sizeof(game_theme)); game_theme.changed = CHANGED_ALL; rc = game_theme_load(DEFAULT_THEME, THEME_GLOBAL); if (rc) return rc; if (opt_owntheme && themes_count(THEME_GAME) > 0) rc = game_theme_load(DEFAULT_THEME, THEME_GAME); return rc; } instead-3.5.2+dfsg/src/themes.h000066400000000000000000000126101467622671600163350ustar00rootroot00000000000000/* * Copyright 2009-2021 Peter Kosyh * * 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. * */ #ifndef __THEMES_INCLUDED_H #define __THEMES_INCLUDED_H #include "graphics.h" #include "sound.h" #define DEFAULT_THEME "default" #ifndef THEMES_PATH #define THEMES_PATH "./themes" #endif #define THEME_FILE "theme.ini" #define THEME_GLOBAL 0 #define THEME_GAME 1 struct game_theme { float scale; float img_scale; int scale_aware; struct dpi { int min; int max; } dpi; int w; int h; int gfx_scalable; color_t bgcol; color_t brdcol; char *bg_name; img_t bg; char *use_name; char *cursor_name; int cur_x; int cur_y; img_t use; img_t cursor; int pad; int win_align; int win_x; int win_y; int win_w; int win_h; int win_scroll_mode; char *font_name; int font_size; float font_height; fnt_t font; int gfx_x; int gfx_y; int max_scene_w; int max_scene_h; char *a_up_name; char *a_down_name; img_t a_up; img_t a_down; int a_up_x; int a_up_y; int a_down_x; int a_down_y; color_t fgcol; color_t lcol; color_t acol; int inv_x; int inv_y; int inv_w; int inv_h; color_t icol; color_t ilcol; color_t iacol; char *inv_font_name; int inv_font_size; float inv_font_height; fnt_t inv_font; char *inv_a_up_name; char *inv_a_down_name; img_t inv_a_up; img_t inv_a_down; int inv_a_up_x; int inv_a_up_y; int inv_a_down_x; int inv_a_down_y; /* int lstyle; int ilstyle; */ color_t menu_bg; color_t menu_fg; color_t border_col; color_t menu_link; color_t menu_alink; int menu_alpha; int border_w; char *menu_font_name; int menu_font_size; float menu_font_height; fnt_t menu_font; char *menu_button_name; img_t menu_button; int menu_button_x; int menu_button_y; int gfx_mode; int inv_mode; int ways_mode; char *click_name; void *click; char *icon_name; img_t icon; int xoff; int yoff; int changed; }; #define CHANGED_FONT 1 #define CHANGED_IFONT 2 #define CHANGED_MFONT 4 #define CHANGED_BG 8 #define CHANGED_WIN 0x10 #define CHANGED_INV 0x20 #define CHANGED_CLICK 0x40 #define CHANGED_CURSOR 0x80 #define CHANGED_USE 0x100 #define CHANGED_UP 0x200 #define CHANGED_DOWN 0x400 #define CHANGED_IUP 0x800 #define CHANGED_IDOWN 0x1000 #define CHANGED_BUTTON 0x2000 #define CHANGED_ICON 0x4000 #define CHANGED_IMG (CHANGED_BG | CHANGED_CLICK | CHANGED_CURSOR | CHANGED_USE | \ CHANGED_UP | CHANGED_DOWN | CHANGED_IUP |CHANGED_IDOWN | \ CHANGED_BUTTON) #define CHANGED_ALL 0xffff struct theme { char *path; char *name; char *dir; int type; int idf; }; extern struct theme *themes; extern int themes_nr; extern char *curtheme_dir[]; extern char *curgametheme_dir; extern struct game_theme game_theme; extern struct game_theme game_theme_unscaled; extern int game_default_theme(void); extern int game_theme_select(const char *name); extern int themes_lookup(const char *path, int type); extern int themes_lookup_idf(idf_t idf, const char *path, int type); extern struct theme *theme_lookup(const char *name, int type); extern int themes_rename(void); extern int themes_count(int type); extern int themes_max(int *type); extern void themes_drop(int type); extern int game_theme_load(const char *name, int type); extern int game_theme_init(void); extern int game_theme_free(void); extern int game_theme_optimize(void); extern int game_theme_update(void); extern int theme_load(const char *name); extern int theme_load_idf(idf_t idf, const char *name); extern int theme_img_scale(img_t *p); extern int theme_gfx_scale(img_t *p, float scale); extern int theme_scalable_mode(int w, int h); extern int theme_relative; #define GFX_MODE_FLOAT 1 #define GFX_MODE_FIXED 2 #define GFX_MODE_EMBEDDED 4 #define GFX_MODE_DIRECT 0x100 #define GFX_MODE(v) ((v) & 0x1ff) #define GFX_DIRECT(v) (!!((v) & 0x100)) #define GFX_DIRECT_SET(v) ((v)|0x100) #define GFX_DIRECT_CLR(v) ((v)&(~0x100)) #define GFX_ALIGN(v) ((v)>>16) #define GFX_ALIGN_SET(v) ((v)<<16) #define INV_MODE_DISABLED -1 #define INV_MODE_VERT 0 #define INV_MODE_HORIZ 1 #define INV_MODE(v) ((v)&0xff) #define INV_ALIGN(v) ((v)>>8) #define INV_ALIGN_SET(v) ((v)<<8) #define WAYS_BOTTOM (game_theme.ways_mode == ALIGN_BOTTOM) #define DIRECT_MODE (GFX_DIRECT(game_theme.gfx_mode)) #define SCALABLE_FONT (!(game_theme.gfx_scalable & 4)) #define SCALABLE_THEME (game_theme.gfx_scalable & 3) #define SCALABLE_THEME_SMOOTH (game_theme.gfx_scalable & 1) #define DEFAULT_DPI_MIN 96 #define DEFAULT_DPI_MAX 96 #endif instead-3.5.2+dfsg/src/tiny/000077500000000000000000000000001467622671600156625ustar00rootroot00000000000000instead-3.5.2+dfsg/src/tiny/Makefile000066400000000000000000000013711467622671600173240ustar00rootroot00000000000000include ../../Rules.make.standalone include ../../config.make CFLAGS += $(LUA_CFLAGS) $(EXTRA_CFLAGS) -DSTEAD_PATH=\"${STEADPATH}/\" -DVERSION=\"$(VERSION)\" LDFLAGS += $(LUA_LFLAGS) $(EXTRA_LDFLAGS) INSTEAD_SRC := instead.c util.c list.c cache.c idf.c tinymt32.c lfs.c SRC := $(INSTEAD_SRC) OBJ := $(patsubst %.c, %.o, $(SRC)) all: instead stead tiny-instead$(EXE) tiny-mp$(EXE) $(OBJ): %.o : instead/%.c $(CC) -c $(<) $(I) $(CFLAGS) $(CPPFLAGS) -o $(@) tiny-instead$(EXE): main.c $(OBJ) $(CC) $(CFLAGS) $(^) $(LDFLAGS) -o $(@) tiny-mp$(EXE): metaparser.c $(OBJ) $(CC) $(CFLAGS) $(^) $(LDFLAGS) -o $(@) instead: ln -s ../instead instead stead: ln -s ../../stead stead clean: $(RM) -f *.o instead stead tiny-instead$(EXE) tiny-mp$(EXE) instead-3.5.2+dfsg/src/tiny/ifbot/000077500000000000000000000000001467622671600167655ustar00rootroot00000000000000instead-3.5.2+dfsg/src/tiny/ifbot/discord-bot/000077500000000000000000000000001467622671600211765ustar00rootroot00000000000000instead-3.5.2+dfsg/src/tiny/ifbot/discord-bot/main.go000066400000000000000000000042721467622671600224560ustar00rootroot00000000000000package main import ( "../ifbot" "flag" "fmt" "github.com/bwmarrin/discordgo" "hash/fnv" "os" "os/signal" "strings" "syscall" ) // Variables used for command line parameters var ( Token string Channels string ChannelsList []string ) func init() { flag.StringVar(&Token, "t", "", "Bot Token") flag.StringVar(&Channels, "c", "", "Channels") flag.Parse() } func main() { ChannelsList = strings.Split(Channels, ",") ifbot.SaveDir = "discord-saves/" // Create a new Discord session using the provided bot token. dg, err := discordgo.New("Bot " + Token) if err != nil { fmt.Println("error creating Discord session,", err) return } // Register the messageCreate func as a callback for MessageCreate events. dg.AddHandler(messageCreate) // Open a websocket connection to Discord and begin listening. err = dg.Open() if err != nil { fmt.Println("error opening connection,", err) return } // Wait here until CTRL-C or other term signal is received. fmt.Println("Bot is now running. Press CTRL-C to exit.") sc := make(chan os.Signal, 1) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) <-sc // Cleanly close down the Discord session. dg.Close() } func hash(s string) int64 { h := fnv.New32a() h.Write([]byte(s)) return int64(h.Sum32()) } func isPrivate(s *discordgo.Session, m *discordgo.MessageCreate) bool { channel, err := s.State.Channel(m.ChannelID) if err != nil { if channel, err = s.Channel(m.ChannelID); err != nil { return false } } return channel.Type == discordgo.ChannelTypeDM } func isChannel(s *discordgo.Session, m *discordgo.MessageCreate) bool { if len(ChannelsList) == 0 { return true } for _, id := range ChannelsList { if m.ChannelID == id { return true } } return false } func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { // Ignore all messages created by the bot itself // This isn't required in this specific example but it's a good practice. if m.Author.ID == s.State.User.ID { return } text := m.Content if !(isChannel(s, m) || isPrivate(s, m)) { return } reply := ifbot.Input(hash(m.ChannelID), text) s.ChannelMessageSend(m.ChannelID, reply) ifbot.Cleanup() } instead-3.5.2+dfsg/src/tiny/ifbot/ifbot/000077500000000000000000000000001467622671600200705ustar00rootroot00000000000000instead-3.5.2+dfsg/src/tiny/ifbot/ifbot/server.go000066400000000000000000000137211467622671600217310ustar00rootroot00000000000000/* golang metaparser3 bot package */ package ifbot import ( "bufio" "io/ioutil" "log" "os" "os/exec" "regexp" "strconv" "strings" "time" ) type Instance struct { id int64 name string input chan string output chan string last_time int64 } var servers []*Instance func Input(id int64, str string) string { var msg string var new bool var ctx *Instance if ctx = Lookup(id); ctx == nil { new = true ctx, msg = Spawn(id) } if ctx == nil { return msg } ctx.last_time = time.Now().Unix() if msg != "" { msg += "\n" } str = strings.TrimSpace(str) if len(str) > 128 { str = str[0:128] } cmd := strings.ToLower(str) if strings.HasPrefix(cmd, "*") { // comment return "" } if strings.HasPrefix(cmd, "load") || strings.HasPrefix(cmd, "save") || strings.HasPrefix(cmd, "quit") { return "" } else if strings.HasPrefix(cmd, "/restart") || strings.HasPrefix(cmd, "/stop") || strings.HasPrefix(cmd, "/start") { if !new || strings.HasPrefix(cmd, "/restart") { // restart Stop(ctx) if strings.HasPrefix(cmd, "/restart") { os.Remove(savedir(ctx) + "/autosave") } if ctx, msg = Spawn(id); ctx == nil { return msg } new = true } } else if strings.HasPrefix(cmd, "/help") { b, err := ioutil.ReadFile("./HELP") if err == nil { return string(b) + "\n" } } // log.Printf("input: %s\n", str) if new { return msg } ctx.input <- str o := <-ctx.output if strings.HasPrefix(o, "%ERROR") { log.Printf("Error in game %d\n", id) Purge(ctx) return msg } return msg + o } func Cleanup() { var stop_servers []*Instance t := time.Now().Unix() for _, v := range servers { if t-v.last_time >= 60*15 { stop_servers = append(stop_servers, v) } } for _, v := range stop_servers { log.Printf("Stopped %d after %d\n", v.id, t-v.last_time) Stop(v) } } func Purge(ctx *Instance) { for n, v := range servers { if v.id == ctx.id { servers[len(servers)-1], servers[n] = servers[n], servers[len(servers)-1] servers = servers[:len(servers)-1] return } } } func Kill() { t := time.Now().Unix() var oldest int64 = 0 var ctx *Instance for _, v := range servers { if t-v.last_time > oldest { oldest = t - v.last_time ctx = v } } if ctx != nil && oldest > 60*5 { log.Printf("Killing %d\n", ctx.id) Stop(ctx) } } func Stop(ctx *Instance) { ctx.input <- ("save " + autosave(ctx)) log.Printf("%s\n", <-ctx.output) ctx.input <- "quit" log.Printf("%s\n", <-ctx.output) Purge(ctx) } func Lookup(id int64) *Instance { for k, v := range servers { if v.id == id { return servers[k] } } return nil } func Spawn(id int64) (*Instance, string) { msg := "" ctx := Lookup(id) if ctx != nil { return ctx, msg } if len(servers) >= 16 { Cleanup() if len(servers) >= 16 { Kill() } if len(servers) >= 16 { return nil, "Server full" } } ctx = new(Instance) ctx.input = make(chan string) ctx.output = make(chan string) ctx.id = id ctx.last_time = time.Now().Unix() servers = append(servers, ctx) go server(ctx) msg = <-ctx.output // fmt.Print(<-ctx.output) return ctx, msg } var SaveDir string = "saves" func savedir(ctx *Instance) string { return "./games/" + ctx.name + "/" + SaveDir + "/" + strconv.FormatInt(ctx.id, 10) } func autosave(ctx *Instance) string { return "./" + SaveDir + "/" + strconv.FormatInt(ctx.id, 10) + "/autosave" } func grab(b *bufio.Reader) (string, bool) { var res string for { result, _, err := b.ReadLine() if err != nil { return "", false } if string(result) == ">" { break } res = res + string(result) + "\n" } return res, true } func gamename(dir string) string { file, err := os.Open("./games/" + dir + "/main3.lua") if err != nil { return dir } defer file.Close() scanner := bufio.NewScanner(file) var commentID = regexp.MustCompile(`^[ \t]*--`) var nameID = regexp.MustCompile(`^[ \t]*--[ \t]*\$Name:[ \t]*(.+)`) for scanner.Scan() { if !commentID.MatchString(scanner.Text()) { break } if !nameID.MatchString(scanner.Text()) { continue } name := nameID.ReplaceAllString(scanner.Text(), "${1}") name = strings.TrimRight(name, "$") return name } return dir } func server(ctx *Instance) { input := ctx.input output := ctx.output res := "" b, err := ioutil.ReadFile("./MOTD") if err == nil { res = string(b) + "\n" } files, err := ioutil.ReadDir("./games/") if err != nil { output <- "%ERROR 0" return } var num int if len(files) == 1 { num = 0 } else if len(files) == 0 { output <- "%ERROR 0" return } else { for k, f := range files { res = res + strconv.Itoa(k+1) + ") " + gamename(f.Name()) + "\n" } for { output <- res inp := <-input if inp == "quit" { output <- "%ERROR quit" return } num, err = strconv.Atoi(inp) if err != nil { continue } num-- if num < 0 || num >= len(files) { continue } break } } ctx.name = files[num].Name() err = os.MkdirAll(savedir(ctx), os.ModePerm) if err != nil { output <- "%ERROR 0" return } cmd := exec.Command("./tiny-mp", "./games/"+ctx.name) in, err := cmd.StdinPipe() if err != nil { output <- "%ERROR 1" return } defer in.Close() out, err := cmd.StdoutPipe() if err != nil { output <- "%ERROR 2" return } defer out.Close() cmd.Stderr = os.Stderr bufOut := bufio.NewReader(out) if err = cmd.Start(); err != nil { output <- "%ERROR 3" return } defer cmd.Wait() res, ok := grab(bufOut) if !ok { output <- "%ERROR 3" return } if _, err := os.Stat(savedir(ctx) + "/autosave"); err == nil { in.Write([]byte("load " + autosave(ctx) + "\n")) res, ok = grab(bufOut) if !ok { output <- "%ERROR 3" return } } output <- string(res) for { str := <-input i := strings.Index(str, "\n") if i > -1 { str = str[:i] } _, err = in.Write([]byte(str + "\n")) if err != nil { output <- "%ERROR 4" return } res, ok = grab(bufOut) if !ok { output <- "%ERROR 5" return } output <- string(res) } output <- "%ERROR 0" } instead-3.5.2+dfsg/src/tiny/ifbot/tg-bot/000077500000000000000000000000001467622671600201615ustar00rootroot00000000000000instead-3.5.2+dfsg/src/tiny/ifbot/tg-bot/main.go000066400000000000000000000013331467622671600214340ustar00rootroot00000000000000/* golang metaparser3 telegram bot */ package main import ( "../ifbot" "fmt" "github.com/Syfaro/telegram-bot-api" "log" "os" ) func main() { if len(os.Args) != 2 { fmt.Println("BOT Token missing") os.Exit(1) } bot, err := tgbotapi.NewBotAPI(os.Args[1]) if err != nil { log.Panic(err) } // bot.Debug = true log.Printf("Authorized on account %s", bot.Self.UserName) u := tgbotapi.NewUpdate(0) u.Timeout = 60 updates, err := bot.GetUpdatesChan(u) for update := range updates { if update.Message == nil { continue } ChatID := update.Message.Chat.ID Text := update.Message.Text reply := ifbot.Input(ChatID, Text) msg := tgbotapi.NewMessage(ChatID, reply) bot.Send(msg) ifbot.Cleanup() } } instead-3.5.2+dfsg/src/tiny/ifbot/tty/000077500000000000000000000000001467622671600176055ustar00rootroot00000000000000instead-3.5.2+dfsg/src/tiny/ifbot/tty/main.go000066400000000000000000000003311467622671600210550ustar00rootroot00000000000000package main import ( "../ifbot" "bufio" "fmt" "os" ) func main() { scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { str := ifbot.Input(1, scanner.Text()) fmt.Printf(str) ifbot.Cleanup() } } instead-3.5.2+dfsg/src/tiny/ifbot/vk-bot/000077500000000000000000000000001467622671600201675ustar00rootroot00000000000000instead-3.5.2+dfsg/src/tiny/ifbot/vk-bot/main.go000066400000000000000000000027521467622671600214500ustar00rootroot00000000000000/* golang metaparser3 vk bot */ package main import ( "../ifbot" "fmt" "github.com/Dimonchik0036/vk-api" "log" "os" "strings" "time" ) func main() { if len(os.Args) != 2 { fmt.Println("BOT Token missing") os.Exit(1) } client, err := vkapi.NewClientFromToken(os.Args[1]) if err != nil { log.Panic(err) } // client.Log(true) if err := client.InitLongPoll(0, 2); err != nil { log.Panic(err) } updates, _, err := client.GetLPUpdatesChan(100, vkapi.LPConfig{25, vkapi.LPModeAttachments}) if err != nil { log.Panic(err) } ifbot.SaveDir = "vk-saves" for update := range updates { if update.Message == nil || !update.IsNewMessage() || update.Message.Outbox() { continue } ID := update.Message.FromID Text := update.Message.Text // log.Printf("Input: %s", Text) reply := ifbot.Input(ID, Text) // log.Printf("Output: %s", reply) lines := strings.Split(reply, "\n") chunk := "" for _, l := range lines { if len(chunk)+len(l) > 1024 { var first bool if chunk == "" { chunk = l + "\n" first = true } for count := 3; count > 0; count-- { rc, _ := client.SendMessage(vkapi.NewMessage(vkapi.NewDstFromUserID(ID), chunk)) if rc > 0 { break } time.Sleep(time.Second / 2.0) } if first { chunk = "" } else { chunk = l + "\n" } } else { chunk += (l + "\n") } } if chunk != "" { client.SendMessage(vkapi.NewMessage(vkapi.NewDstFromUserID(ID), chunk)) } ifbot.Cleanup() } } instead-3.5.2+dfsg/src/tiny/instead.lua000066400000000000000000000102051467622671600200120ustar00rootroot00000000000000-- pure Lua instead (stead3 api) -- metaparser example: -- -- local instead = require "instead":new() -- print(instead:start()) -- for l in io.lines() do -- print(instead:parser(l)) -- end local env = { __super = false, __mods_loaded__ = {}, package = { path = './stead/stead3/?.lua;'..package.path }, debug = debug, type = type, setfenv = setfenv, getfenv = getfenv, rawset = rawset, rawget = rawget, rawequal = rawequal, setmetatable = setmetatable, getmetatable = getmetatable, table = table, math = math, string = string, pairs = pairs, ipairs = ipairs, io = io, os = os, tonumber = tonumber, tostring = tostring, print = print, collectgarbage = collectgarbage, error = error, sys = sys, PLATFORM = 'unix', DEBUG = false, } if not table.clone then function table.clone(src) local dst = {} if type(src) ~= 'table' then return src end for k, _ in pairs(src) do dst[table.clone(k)] = table.clone(src[k]) end return dst end end if not string.split then function string.split(self, n, sep, rexp) if type(n) ~= 'number' then sep, rexp, n = n, sep, false end if not sep then rexp = true sep = "[ \t]+" end local ret = {} if self:len() == 0 then return ret end n = n or -1 local idx, start = 1, 1 local s, e = self:find(sep, start, not rexp) while s and n ~= 0 do ret[idx] = self:sub(start, s - 1) idx = idx + 1 start = e + 1 s, e = self:find(sep, start, not rexp) n = n - 1 end ret[idx] = self:sub(start) return ret end end function env.instead_gamepath() return "./" end local loadf = loadfile local function make_loadfile(n, env) if setfenv then setfenv(1, env) end return loadf(n, "t", env) end local function make_dofile(n, env) local r, e = make_loadfile(n, env) if setfenv then setfenv(1, env) end if not r then error(e..'\n'..debug.traceback()) end return r() end local function make_require(n, env) local mods = env.__mods_loaded__ if mods[n] then return mods[n] end local pathes = env.package.path:split(";") for _, p in ipairs(pathes) do local name = p:gsub("%?", n) local f = io.open(name, "r") if f then f:close() mods[n] = make_dofile(name, env) or true break end end if not mods[n] then error("Can't load module: "..tostring(n), 2) end return mods[n] end local function init(env, f) local _ENV = env if setfenv then setfenv(1, _ENV) end require("stead") require("tiny3") stead:init() std.mod_start(function() local mp = std.ref '@metaparser' if mp then VerbExtend ({ "#MetaSave", "*:MetaSave", }, mp) VerbExtend ({ "#MetaLoad", "*:MetaLoad", }, mp) rawset(mp, 'MetaSave', function(self, w) __super:save(w) end) rawset(mp, 'MetaLoad', function(self, w) __super.need_load = w end) rawset(instead, 'restart', function() __super.need_restart = true end) end end) dofile(f or "main3.lua") end local boot = {} function boot:newenv() local new = table.clone(env) -- mt can't be used :( new.dofile = function(f) return make_dofile(f, new) end new.require = function(f) return make_require(f, new) end new.loadfile = function(f) return make_loadfile(f, new) end new._G = new init(new) return new end function boot:start() self.env.game:ini() return self.env.iface:cmd 'look' end function boot:restart() self.env = boot:newenv() self.env.__super = self return self:start() end function boot:load(file) self.env = boot:newenv() self.env.__super = self self.env.game:ini() return self.env.iface:cmd(string.format('load %s', file)) end function boot:save(file) return self.env.iface:cmd(string.format('save %s', file)) end function boot:cmd(cmd) return self.env.iface:cmd(cmd) end function boot:parser(cmd) return self:cmd(string.format("@metaparser %q", cmd)) end function boot:new() local new = boot:newenv() local o = { env = new } new.__super = o self.__index = self setmetatable(o, self) return o end return boot instead-3.5.2+dfsg/src/tiny/main.c000066400000000000000000000036461467622671600167630ustar00rootroot00000000000000#include #include #include #include "instead/instead.h" static int log_opt = 0; static int tiny_init(void) { int rc; rc = instead_loadfile("tiny.lua"); if (rc) return rc; return 0; } static struct instead_ext ext = { .init = tiny_init, }; static void footer(void) { char *p; p = instead_cmd("way", NULL); if (p && *p) { printf(">> %s", p); free(p); } p = instead_cmd("inv", NULL); if (p && *p) { printf("** %s", p); free(p); } } int main(int argc, const char **argv) { int rc; char *str; const char *game = NULL; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } game = argv[1]; if (instead_extension(&ext)) { fprintf(stderr, "Can't register tiny extension\n"); exit(1); } instead_set_debug(1); if (instead_init(game)) { fprintf(stderr, "Can not init game: %s\n", game); exit(1); } if (instead_load(&str)) { fprintf(stderr, "Can not load game: %s\n", instead_err()); exit(1); } printf("%s\n", str); #if 0 /* no autoload */ str = instead_cmd("load autosave", &rc); #else str = instead_cmd("look", &rc); #endif if (!rc) { printf("%s", str); footer(); } free(str); while (1) { char input[128], *p, cmd[64]; p = fgets(input, sizeof(input), stdin); if (!p) break; printf(" * * *\n"); p[strcspn(p, "\n\r")] = 0; if (!strcmp(p, "quit")) break; if (!strcmp(p, "log")) { log_opt = 1; continue; } snprintf(cmd, sizeof(cmd), "use %s", p); str = instead_cmd(cmd, &rc); if (rc) { /* try go */ free(str); snprintf(cmd, sizeof(cmd), "go %s", p); str = instead_cmd(cmd, &rc); } if (rc) { /* try act */ free(str); snprintf(cmd, sizeof(cmd), "%s", p); str = instead_cmd(cmd, &rc); } if (str) printf("%s", str); free(str); if (rc) printf("error!\n"); else { footer(); if (log_opt) fprintf(stderr, "%s\n", p); } } instead_cmd("save autosave", NULL); instead_done(); exit(0); } instead-3.5.2+dfsg/src/tiny/metaparser.c000066400000000000000000000032031467622671600201670ustar00rootroot00000000000000#include #include #include #include "instead/instead.h" static int log_opt = 0; static int tiny_init(void) { int rc; rc = instead_loadfile("tiny.lua"); if (rc) return rc; return 0; } static struct instead_ext ext = { .init = tiny_init, }; int main(int argc, const char **argv) { int rc; char *str; const char *game = NULL; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } game = argv[1]; if (instead_extension(&ext)) { fprintf(stderr, "Can't register tiny extension\n"); exit(1); } instead_set_debug(1); if (instead_init(game)) { fprintf(stderr, "Can not init game: %s\n", game); exit(1); } if (instead_load(NULL)) { fprintf(stderr, "Can not load game: %s\n", instead_err()); exit(1); } #if 0 /* no autoload */ str = instead_cmd("load autosave", &rc); #else str = instead_cmd("look", &rc); #endif if (!rc) { printf("%s\n", str); fflush(stdout); } free(str); while (1) { char input[256], *p, cmd[256 + 64]; printf(">\n"); fflush(stdout); p = fgets(input, sizeof(input), stdin); if (!p) break; p[strcspn(p, "\n\r")] = 0; if (!strcmp(p, "quit")) break; if (!strcmp(p, "log")) { log_opt = 1; continue; } if (!strncmp(p, "load ", 5) || !strncmp(p, "save ", 5)) snprintf(cmd, sizeof(cmd), "%s", p); else snprintf(cmd, sizeof(cmd), "@metaparser \"%s\"", p); str = instead_cmd(cmd, &rc); if (rc && !str) /* menu? */ str = instead_cmd(p, NULL); if (str) { printf("%s\n", str); fflush(stdout); } free(str); if (log_opt) fprintf(stderr, "%s\n", p); } instead_cmd("save autosave", NULL); instead_done(); exit(0); } instead-3.5.2+dfsg/src/tiny/tiny.lua000066400000000000000000000007401467622671600173510ustar00rootroot00000000000000-- some stubs for tiny-instead -- fake game.gui -- stat, menu -- fake audio -- fake input if API == 'stead3' then dofile 'tiny3.lua' local instead = std '@instead' instead.savepath = function() return "./" end std.mod_start(function() std.mod_init(function() std.rawset(_G, 'instead', instead) require "ext/sandbox" end) local mp = std.ref '@metaparser' if mp then mp.msg.CUTSCENE_MORE = '^'..mp.msg.CUTSCENE_HELP end end) return end dofile 'tiny2.lua' instead-3.5.2+dfsg/src/tiny/tiny2.lua000066400000000000000000000130061467622671600174320ustar00rootroot00000000000000-- some stubs for tiny-instead -- fake game.gui -- stat, menu -- fake audio -- fake input -- show hints (numbers) game.hinting = true -- fake gui game.gui = { fading = 4; ways_delim = ' | '; inv_delim = ' | '; hinv_delim = ' | '; hideways = false; hideinv = false; hidetitle = false; } stead.list_search = function(self, n, dis) local i if stead.tonum(n) then i = self:byid(stead.tonum(n), dis); end if not i then i = self:look(n) if not i then i = self:name(n, dis); end if not i then return nil end end if not dis and isDisabled(stead.ref(self[i])) then return nil end return self[i], i end local dict = {} iface.xref = function(self, str, obj, ...) local cmd = '' local o = stead.ref(obj) if not isObject(o) or isStatus(o) or (not o.id and not isXaction(o)) then return str end if stead.cmd == 'way' then cmd = 'go' elseif stead.cmd == 'inv' then cmd = 'use' elseif isSceneUse(o) then cmd = 'use' elseif isXaction(o) and not o.id then cmd = 'act' elseif stead.ref(stead.here():srch(obj)) then cmd = 'act' end local a = '' local varg = {...} for i = 1, stead.table.maxn(varg) do a = a..','..varg[i] end local n = stead.deref(obj) local xref = string.format("%s%s", stead.tostr(o.id or n), a) if not dict[cmd..xref] then stead.table.insert(dict, { xref, cmd } ) dict[cmd..xref] = #dict end xref = stead.tostr(dict[cmd..xref]) return stead.cat(str, "("..xref..")"); end local tag_all = stead.player_tagall -- save old stead.player_tagall = function(self) dict = {} return tag_all(self) end local iface_cmd = iface.cmd -- save old function iface:cmd(inp) local cmd, a = stead.getcmd(inp) if stead.tonum(cmd) then stead.table.insert(a, 1, cmd) cmd = 'act' end if cmd == 'act' or cmd == 'use' or cmd == 'go' then if a[1] == '' then -- fix use vs look return iface_cmd(self, "look") end if cmd == 'use' then local use = { } local c = false for i = 1, #a do local u = stead.tonum(a[i]) u = u and dict[u] c = c or (u and u[2]) stead.table.insert(use, u and u[1] or a[i]) end if #a == 1 and c == 'act' then -- fix use 1,2 where 1,2 is object and look cmd = 'act' end inp = cmd .. ','..stead.table.concat(use, ',') elseif stead.tonum(a[1]) then local d = dict[stead.tonum(a[1])] a[1] = d and d[1] or a[1] inp = cmd .. ','..stead.table.concat(a, ',') end end return iface_cmd(self, inp) end -- menu and stat stat = function(v) v.status_type = true v.id = false return obj(v) end function isStatus(v) if stead.type(v) ~= 'table' then return false end if v.status_type then return true end return false end function isMenu(v) if stead.type(v) ~= 'table' then return false end if v.menu_type then return true end return false end stead.menu_save = function(self, name, h, need) local dsc; if need then print ("Warning: menu "..name.." can not be saved!"); return end stead.savemembers(h, self, name, need); end function menu(v) v.menu_type = true if v.inv == nil then v.inv = function(s) local r,v r, v = stead.call(s, 'menu'); if v == nil then v = true end if r == nil then stead.obj_tag(stead.me(), MENU_TAG_ID); -- retag menu field end return r, v end end if v.act == nil then v.act = function(s) local r,v r,v = stead.call(s, 'menu'); if v == nil then v = true end if r == nil then stead.obj_tag(stead.me(), MENU_TAG_ID); -- retag menu field end return r, v end end if v.save == nil then v.save = stead.menu_save; end return obj(v); end function iface:title(t) if type(t) ~= 'string' then return end return '['..t..']' end function iface:imgl() return '' end function iface:imgr() return '' end function iface:nb(t) return t == '' and ' ' or t end function iface:y() return '' end function iface:tab(str) return stead.tostr(str)..' ' end -- fake audio and timer stead.get_music = function() return '', 0 end stead.get_music_loop = function() return 0 end stead.save_music = function(s) end stead.restore_music = function(s) end stead.set_music = function(s, count) end stead.set_music_fading = function(o, i) end stead.get_music_fading = function() end stead.stop_music = function() end stead.is_music = function() return false end function instead_sound() return false end stead.is_sound = instead_sound stead.get_sound = function() return end stead.get_sound_chan = function() return 0 end stead.get_sound_loop = function() return 0 end stead.stop_sound = function(chan, fo) end stead.add_sound = function(s, chan, loop) end stead.set_sound = function(s, chan, loop) end -- those are sill in global space add_sound = stead.add_sound set_sound = stead.set_sound stop_sound = stead.stop_sound get_sound = stead.get_sound get_sound_loop = stead.get_sound_loop get_sound_chan = stead.get_sound_chan get_music = stead.get_music get_music_fading = stead.get_music_fading get_music_loop = stead.get_music_loop set_music = stead.set_music set_music_fading = stead.set_music_fading stop_music = stead.stop_music save_music = stead.save_music restore_music = stead.restore_music is_music = stead.is_music stead.set_timer = function() end stead.timer = function() return end instead_theme_name = function() return 'default' end stead.module_init(function(s) timer = obj { nam = 'timer', get = function(s) return 0 end, stop = function(s) end, del = function(s) end, set = function(s, v) return true end, }; end) stead.objects.input = function() return obj { -- input object system_type = true, nam = 'input', }; end; instead-3.5.2+dfsg/src/tiny/tiny3.lua000066400000000000000000000127061467622671600174410ustar00rootroot00000000000000local std = stead local instead = std.obj { nam = '@instead' } instead.nosave = false instead.noautosave = false instead.tiny = true function instead.mouse_filter() return 0 end function instead.render_callback() return false end function instead.wait_use() return true end local iface = std '@iface' local type = std.type local dict = {} instead.inv_delim = '\n' instead.hinv_delim = ' | ' instead.ways_delim = ' | ' instead.notitle = false instead.noways = false instead.noinv = false instead.nopic = false instead.fading_value = 0 function instead.fading() end function instead.need_fading() end function instead.autosave(slot) end function instead.menu(n) end function instead.restart(v) end function instead.text_input() return false end function instead.atleast(...) return true end function instead.version(...) end function iface:title(str) -- hide title return str end function iface:img() return '' end function iface:imgl() return '' end function iface:imgr() return '' end function iface:anchor() return '' end function iface:nb(t) return t == '' and ' ' or t end std.stat = std.class({ __stat_type = true; }, std.obj); -- luacheck: globals menu std.menu = std.class({ __menu_type = true; new = function(_, v) if type(v) ~= 'table' then std.err ("Wrong argument to std.menu:"..std.tostr(v), 2) end v = std.obj(v) -- std.setmt(v, self) return v end; inv = function(s, ...) local r, v if s.menu ~= nil then r, v = std.call(s, 'menu', ...) -- special method while in inv else r, v = std.call(s, 'act', ...) -- fallback to act end if not r and not v then return true, false -- menu mode end return r, v end; }, std.obj); std.setmt(std.phr, std.menu) -- make phrases menus std.setmt(std.ref '@', std.menu) -- make xact menu function iface:xref(str, o, ...) if type(str) ~= 'string' then std.err ("Wrong parameter to iface:xref: "..std.tostr(str), 2) end if not std.is_obj(o) or std.is_obj(o, 'stat') then return str end local a = { ... } local args = '' for i = 1, #a do if type(a[i]) ~= 'string' and type(a[i]) ~= 'number' then std.err ("Wrong argument to iface:xref: "..std.tostr(a[i]), 2) end args = args .. ' '..std.dump(a[i]) end local xref = std.string.format("%s%s", std.deref_str(o), args) -- std.string.format("%s%s", iface:esc(std.deref_str(o)), iface:esc(args)) if not dict[xref] then table.insert(dict, xref) dict[xref] = #dict end xref = std.tostr(dict[xref]) return str..std.string.format("(%s)", xref) end local iface_cmd = iface.cmd -- save old function iface:cmd(inp) local a = std.split(inp) if std.tonum(a[1]) then std.table.insert(a, 1, 'act') end if a[1] == 'act' or a[1] == 'use' or a[1] == 'go' then if a[1] == 'use' then local use = std.split(a[2], ',') for i = 1, 2 do local u = std.tonum(use[i]) if u then use[i] = dict[u] end end a[2] = std.join(use, ',') elseif std.tonum(a[2]) then a[2] = dict[std.tonum(a[2])] end inp = std.join(a) end return iface_cmd(self, inp) end std.obj { -- input object nam = '@input'; }; -- some aliases menu = std.menu stat = std.stat -- fake sound local sound = std.obj { nam = '@snd'; } sound.set = function() end sound.play = function() end sound.stop = function() end sound.music = function() end sound.stop_music = function() end sound.music_fading = function() end sound.new = function() return sound end -- fake timer std.obj { nam = '@timer'; get = function(s) return s.__timer or 0; end; stop = function(s) return s:set(0) end; set = function(s, v) s.__timer = v return true end; } -- fake sprite std.obj { nam = '@sprite'; new = function() end; fnt = function() end; scr = function() end; direct = function() return false end; render_callback = instead.render_callback; } -- fake pixels std.obj { nam = '@pixels'; fnt = function() end; new = function() end; } -- fake themes local theme = std.obj { nam = '@theme'; { win = { gfx = {}}; inv = { gfx = {}}; menu = { gfx = {}}; gfx = {}; snd = {}; }; } function theme.restore() end function theme.set() end function theme.reset() end function theme.name() end function theme.get() end function theme.win.reset() end function theme.win.geom() end function theme.win.color() end function theme.win.font() end function theme.win.gfx.reset() end function theme.win.gfx.up() end function theme.win.gfx.down() end function theme.inv.reset() end function theme.inv.geom() end function theme.inv.color(f) end function theme.inv.font() end function theme.inv.mode() end function theme.inv.gfx.reset() end function theme.inv.gfx.up() end function theme.inv.gfx.down() end function theme.menu.reset() end function theme.menu.bw(w) end function theme.menu.color() end function theme.menu.font() end function theme.menu.gfx.reset() end function theme.menu.gfx.button() end; function theme.gfx.reset() end function theme.gfx.cursor() end function theme.gfx.mode() end function theme.gfx.pad() end function theme.gfx.bg() end function theme.snd.reset() end function theme.snd.click() end std.mod_init(function() std.rawset(_G, 'instead', instead) end) local mp_hooked = false std.mod_start(function() dict = {} local mp = std.ref '@metaparser' if mp then mp.winsize = 0 mp.prompt = false if not mp_hooked then -- force truncate text for all commands std.mod_cmd(function(cmd) mp:trim() end) mp_hooked = true end end end) std.mod_step(function(state) if state then dict = {} end end) require "ext/paths" instead-3.5.2+dfsg/src/unix.c000066400000000000000000000221601467622671600160270ustar00rootroot00000000000000/* * Copyright 2009-2021 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #include #include #include #include #include #include #include #include #include #include "externals.h" #include "internals.h" #ifdef _USE_GTK #include "input.h" #include #endif static char save_path[PATH_MAX]; static char cfg_path[PATH_MAX]; static char local_games_path[PATH_MAX]; static char local_themes_path[PATH_MAX]; static char local_stead_path[PATH_MAX]; char *game_locale(void) { char *p; char *s; p = getenv("LANG"); if (!p || !(s = strdup(p))) return NULL; if ((p = strchr(s, '_'))) *p = 0; return s; } char *game_tmp_path(void) { static time_t t = 0; static char tmp[PATH_MAX]="/tmp/instead-games"; if (!t) { t = time(NULL); sprintf(tmp, "/tmp/instead-games-%lu", (unsigned long)t); } if (mkdir(tmp, S_IRWXU) && errno != EEXIST) return NULL; return tmp; } #ifdef _USE_GTK static volatile int gtk_response = -1; static void run_response_handler (GtkDialog *dialog, gint response_id, gpointer data) { gtk_response = response_id; } GdkPixbuf *create_pixbuf(const gchar * filename) { gchar path[PATH_MAX]; GdkPixbuf *pixbuf; GError *error = NULL; path[0] = 0; if (filename[0] != '/') { strcpy(path, game_cwd); strcat(path, "/"); } strcat(path, filename); pixbuf = gdk_pixbuf_new_from_file(path, &error); if(!pixbuf) { fprintf(stderr, "%s\n", error->message); g_error_free(error); } return pixbuf; } #endif extern char *BROWSE_MENU; char *open_file_dialog(void) { #ifndef _USE_GTK /* unix people don't need win solutions */ return NULL; #else gulong response_handler; static int old_dir_set = 0; static char file[PATH_MAX]; static char old_dir[PATH_MAX]; GtkWidget *file_dialog; GtkFileFilter *file_filter_all; GtkFileFilter *file_filter_zip; /* GtkFileFilter *file_filter_lua; */ file_filter_all = gtk_file_filter_new(); gtk_file_filter_add_pattern(file_filter_all, "*"); gtk_file_filter_set_name(file_filter_all, "*"); file_filter_zip = gtk_file_filter_new(); gtk_file_filter_add_pattern(file_filter_zip, "*.zip"); gtk_file_filter_add_pattern(file_filter_zip, "main.lua"); gtk_file_filter_add_pattern(file_filter_zip, "main3.lua"); gtk_file_filter_add_pattern(file_filter_zip, "*.idf"); gtk_file_filter_set_name(file_filter_zip, "main?.lua; *.zip; *.idf"); /* file_filter_lua = gtk_file_filter_new(); gtk_file_filter_add_pattern(file_filter_lua, "main.lua"); gtk_file_filter_set_name(file_filter_lua, "main.lua"); */ file[0] = 0; file_dialog = gtk_file_chooser_dialog_new (BROWSE_MENU, NULL, GTK_FILE_CHOOSER_ACTION_OPEN, #if GTK_MAJOR_VERSION == 4 g_dgettext("gtk40", "_Cancel"), GTK_RESPONSE_CANCEL, g_dgettext("gtk40", "_Open"), GTK_RESPONSE_ACCEPT, NULL); #elif GTK_MAJOR_VERSION == 3 g_dgettext("gtk30", "_Cancel"), GTK_RESPONSE_CANCEL, g_dgettext("gtk30", "_Open"), GTK_RESPONSE_ACCEPT, NULL); #else GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); #endif if (old_dir_set) { #if GTK_MAJOR_VERSION == 4 GFile *f = g_file_new_for_path(old_dir); gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_dialog), f, NULL); g_object_unref(f); #else gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_dialog), old_dir); #endif } #if GTK_MAJOR_VERSION != 4 gtk_window_set_icon(GTK_WINDOW(file_dialog), create_pixbuf(ICON_PATH"/sdl_instead.png")); #endif gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_dialog), file_filter_all); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_dialog), file_filter_zip); /* gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(file_dialog), file_filter_lua);*/ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(file_dialog), file_filter_zip); response_handler = g_signal_connect (file_dialog, "response", G_CALLBACK (run_response_handler), NULL); gtk_window_set_modal (GTK_WINDOW (file_dialog), TRUE); gtk_widget_show(file_dialog); gtk_response = -1; /* dirty, but we need both SDL and gtk */ while (gtk_response == -1) { struct inp_event ev; memset(&ev, 0, sizeof(struct inp_event)); while (g_main_context_pending(NULL)) { g_main_context_iteration(NULL, FALSE); while ((input(&ev, 0)) == AGAIN); } while ((input(&ev, 0)) == AGAIN); usleep(HZ*100); } if (gtk_response == GTK_RESPONSE_ACCEPT) { #if GTK_MAJOR_VERSION == 4 GFile *f = gtk_file_chooser_get_file(GTK_FILE_CHOOSER (file_dialog)); if (f) { strcpy(file, g_file_get_path(f)); g_object_unref(f); } f = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(file_dialog)); if (f) { strcpy(old_dir, g_file_get_path(f)); g_object_unref(f); old_dir_set = 1; } #else char *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_dialog)); if (filename) { strcpy(file, filename); g_free (filename); } filename = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(file_dialog)); if (filename) { strcpy(old_dir, filename); g_free (filename); old_dir_set = 1; } #endif } if (gtk_response != GTK_RESPONSE_DELETE_EVENT) { g_signal_handler_disconnect (GTK_WIDGET(file_dialog), response_handler); #if GTK_MAJOR_VERSION == 4 gtk_window_destroy(GTK_WINDOW(file_dialog)); #else gtk_widget_destroy(GTK_WIDGET(file_dialog)); #endif } while (g_main_context_pending(NULL)) g_main_context_iteration(NULL, FALSE); return (file[0])?file:NULL; #endif } char *appdir(void) { static char dir[PATH_MAX] = ""; struct passwd *pw; #ifdef _LOCAL_APPDATA if (!appdata_sw) { strcpy(dir, game_cwd); strcat(dir, "/appdata"); } #endif if (appdata_sw) strcpy(dir, appdata_sw); if (dir[0] && !access(dir, W_OK)) return dir; pw = getpwuid(getuid()); if (!pw) return NULL; snprintf(dir, sizeof(dir) - 1 , "%s/.instead", pw->pw_dir); return dir; } char *game_local_games_path(int cr) { char *app = appdir(); if (!app) return NULL; strcpy(local_games_path, app); if (cr) { if (mkdir(local_games_path, S_IRWXU) && errno != EEXIST) return NULL; } strcat(local_games_path,"/games"); if (cr) { if (mkdir(local_games_path, S_IRWXU) && errno != EEXIST) return NULL; } return local_games_path; } char *game_local_themes_path(void) { char *app = appdir(); if (!app) return NULL; snprintf(local_themes_path, sizeof(local_themes_path) - 1 , "%s/themes", app); return local_themes_path; } char *instead_local_stead_path(void) { char *app = appdir(); if (!app) return NULL; snprintf(local_stead_path, sizeof(local_stead_path) - 1 , "%s/stead", app); return local_stead_path; } char *game_cfg_path(void) { char *app = appdir(); struct passwd *pw; if (app) { snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/", app); if (mkdir(cfg_path, S_IRWXU) == 0 || errno == EEXIST) { snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/insteadrc", app); return cfg_path; } } pw = getpwuid(getuid()); if (!pw) return NULL; snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/.insteadrc", pw->pw_dir); /* at home */ return cfg_path; } char *game_save_path(int cr, int nr) { char *app = appdir(); if (!curgame_dir) return NULL; if (!access("saves", R_OK)) { if (nr) snprintf(save_path, sizeof(save_path) - 1, "saves/save%d", nr); else snprintf(save_path, sizeof(save_path) - 1, "saves/autosave"); return save_path; } if (!app) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/", app); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/saves", app); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/", app, curgame_dir); if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST) return NULL; if (nr) snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/save%d", app, curgame_dir, nr); else snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/autosave", app, curgame_dir); return save_path; } int debug_init(void) { return 0; } void debug_done() { } char *sdl_path(char *p) { unix_path(p); return p; } instead-3.5.2+dfsg/src/unpack.c000066400000000000000000000216011467622671600163240ustar00rootroot00000000000000#ifdef _USE_UNPACK /* miniunz.c Version 1.1, February 14h, 2010 sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) */ #ifndef _WIN32 #ifndef __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64 #endif #ifndef __USE_LARGEFILE64 #define __USE_LARGEFILE64 #endif #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #ifndef _FILE_OFFSET_BIT #define _FILE_OFFSET_BIT 64 #endif #endif #include "externals.h" #ifdef unix # include # include #else # include # include #endif #include "unzip.h" #include "utils.h" #define CASESENSITIVITY (0) #define WRITEBUFFERSIZE (8192) #define MAXFILENAME (256) #ifdef _WIN32 #define USEWIN32IOAPI #include "iowin32.h" #endif char zip_game_dirname[PATH_MAX]; /* change_file_date : change the date/time of a file filename : the filename of the file where date/time must be modified dosdate : the new date at the MSDos format (4 bytes) tmu_date : the SAME new date at the tm_unz format */ static void change_file_date(filename, dosdate, tmu_date) const char *filename; uLong dosdate; tm_unz tmu_date; { #ifdef _WIN32 HANDLE hFile; FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite; hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); GetFileTime(hFile, &ftCreate, &ftLastAcc, &ftLastWrite); DosDateTimeToFileTime((WORD) (dosdate >> 16), (WORD) dosdate, &ftLocal); LocalFileTimeToFileTime(&ftLocal, &ftm); SetFileTime(hFile, &ftm, &ftLastAcc, &ftm); CloseHandle(hFile); #else #ifdef unix struct utimbuf ut; struct tm newdate; newdate.tm_sec = tmu_date.tm_sec; newdate.tm_min = tmu_date.tm_min; newdate.tm_hour = tmu_date.tm_hour; newdate.tm_mday = tmu_date.tm_mday; newdate.tm_mon = tmu_date.tm_mon; if (tmu_date.tm_year > 1900) newdate.tm_year = tmu_date.tm_year - 1900; else newdate.tm_year = tmu_date.tm_year; newdate.tm_isdst = -1; ut.actime = ut.modtime = mktime(&newdate); utime(filename, &ut); #endif #endif } /* mymkdir and change_file_date are not 100 % portable As I don't know well Unix, I wait feedback for the unix portion */ static int mymkdir(dirname) const char *dirname; { int ret = 0; #ifdef _WIN32 ret = _mkdir(dirname); #else #ifdef unix ret = mkdir(dirname, 0775); #endif #endif return ret; } static int makedir(newdir) const char *newdir; { char *buffer; char *p; int len = (int)strlen(newdir); if (len <= 0) return 0; buffer = (char *)malloc(len + 1); if (buffer == NULL) { fprintf(stderr, "Error allocating memory\n"); return UNZ_INTERNALERROR; } strcpy(buffer, newdir); if (buffer[len - 1] == '/') { buffer[len - 1] = '\0'; } if (mymkdir(buffer) == 0) { free(buffer); return 1; } p = buffer + 1; while (1) { char hold; while (*p && *p != '\\' && *p != '/') p++; hold = *p; *p = 0; if ((mymkdir(buffer) == -1) && (errno == ENOENT)) { fprintf(stderr, "couldn't create directory %s\n", buffer); free(buffer); return 0; } if (hold == 0) break; *p++ = hold; } free(buffer); return 1; } static int do_extract_currentfile(uf, password) unzFile uf; const char *password; { char filename_inzip[256]; char dir_inzip[256]; char *filename_withoutpath; char *p; int err = UNZ_OK; FILE *fout = NULL; void *buf; uInt size_buf; unz_file_info64 file_info; err = unzGetCurrentFileInfo64(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); if (err != UNZ_OK) { fprintf(stderr, "error %d with zipfile in unzGetCurrentFileInfo\n", err); return err; } size_buf = WRITEBUFFERSIZE; buf = (void *)malloc(size_buf); if (buf == NULL) { fprintf(stderr, "Error allocating memory\n"); return UNZ_INTERNALERROR; } p = filename_withoutpath = filename_inzip; strcpy(dir_inzip, filename_inzip); while ((*p) != '\0') { if (((*p) == '/') || ((*p) == '\\')) filename_withoutpath = p + 1; p++; } p = dir_inzip + strcspn(dir_inzip, "/\\"); *p = 0; if ((*filename_withoutpath) == '\0') { if (zip_game_dirname[0] && strncmp(zip_game_dirname, filename_inzip, strlen(zip_game_dirname))) { err = -1; fprintf(stderr, "Too many dirs in zip...\n"); goto out; } fprintf(stderr, "creating directory: %s\n", filename_inzip); mymkdir(filename_inzip); if (!*zip_game_dirname) strcpy(zip_game_dirname, dir_inzip); } else { const char *write_filename; int skip = 0; write_filename = filename_inzip; err = unzOpenCurrentFilePassword(uf, password); if (err != UNZ_OK) { fprintf (stderr, "error %d with zipfile in unzOpenCurrentFilePassword\n", err); goto out; } if (skip == 0) { fout = fopen64(write_filename, "wb"); /* some zipfile don't contain directory alone before file */ if ((fout == NULL) && (filename_withoutpath != (char *)filename_inzip)) { char c = *(filename_withoutpath - 1); *(filename_withoutpath - 1) = '\0'; makedir(write_filename); *(filename_withoutpath - 1) = c; fout = fopen64(write_filename, "wb"); } if (fout == NULL) { fprintf(stderr, "error opening %s\n", write_filename); } } if ((filename_withoutpath != (char *)filename_inzip) && !*zip_game_dirname) { strcpy(zip_game_dirname, dir_inzip); } if (fout != NULL) { fprintf(stderr, " extracting: %s\n", write_filename); do { err = unzReadCurrentFile(uf, buf, size_buf); if (err < 0) { fprintf (stderr, "error %d with zipfile in unzReadCurrentFile\n", err); break; } if (err > 0) if (fwrite(buf, err, 1, fout) != 1) { fprintf (stderr, "error in writing extracted file\n"); err = UNZ_ERRNO; break; } } while (err > 0); if (fout) fclose(fout); if (err == 0) change_file_date(write_filename, file_info.dosDate, file_info.tmu_date); } if (err == UNZ_OK) { err = unzCloseCurrentFile(uf); if (err != UNZ_OK) { fprintf (stderr, "error %d with zipfile in unzCloseCurrentFile\n", err); } } else unzCloseCurrentFile(uf); /* don't lose the error */ if (!*zip_game_dirname) { err = -1; fprintf(stderr, "No dir in zip...\n"); if (idf_magic(write_filename)) { fprintf(stderr, "Idf unpacked: %s\n", write_filename); strcpy(zip_game_dirname, write_filename); err = 0; } else unlink(write_filename); goto out; } } if (*zip_game_dirname) { size_t s = strlen(zip_game_dirname); unix_path(zip_game_dirname); if (s && (zip_game_dirname[s - 1] == '/')) s --; zip_game_dirname[s] = 0; } out: free(buf); return err; } static int do_extract(uf, password) unzFile uf; const char *password; { uLong i; unz_global_info64 gi; int err; err = unzGetGlobalInfo64(uf, &gi); if (err != UNZ_OK) fprintf(stderr, "error %d with zipfile in unzGetGlobalInfo \n", err); for (i = 0; i < gi.number_entry; i++) { if (do_extract_currentfile(uf, password) != UNZ_OK) return -1; if ((i + 1) < gi.number_entry) { err = unzGoToNextFile(uf); if (err != UNZ_OK) { fprintf (stderr, "error %d with zipfile in unzGoToNextFile\n", err); return -1; } } } return 0; } int unpack(const char *zipfilename, const char *dirname) { char game_cwd[PATH_MAX]; unzFile uf; char filename_try[MAXFILENAME + 16] = ""; int ret_value = 0; if (dirname && !getcwd(game_cwd, sizeof(game_cwd))) { fprintf(stderr, "Error: can not get current dir.\n"); return -1; } uf = NULL; zip_game_dirname[0] = 0; # ifdef USEWIN32IOAPI zlib_filefunc64_def ffunc; # endif strncpy(filename_try, zipfilename, MAXFILENAME - 1); /* strncpy doesnt append the trailing NULL, of the string is too long. */ filename_try[MAXFILENAME] = '\0'; # ifdef USEWIN32IOAPI fill_win32_filefunc64A(&ffunc); uf = unzOpen2_64(zipfilename, &ffunc); # else uf = unzOpen64(zipfilename); # endif if (uf == NULL) { strcat(filename_try, ".zip"); # ifdef USEWIN32IOAPI uf = unzOpen2_64(filename_try, &ffunc); # else uf = unzOpen64(filename_try); # endif } if (uf == NULL) { fprintf(stderr, "Cannot open %s or %s.zip\n", zipfilename, zipfilename); return -1; } fprintf(stderr, "%s opened\n", filename_try); #ifdef _WIN32 if (dirname && _chdir(dirname)) #else if (dirname && chdir(dirname)) #endif { ret_value = -1; fprintf(stderr, "Error changing dir to %s, aborting\n", dirname); goto out; } ret_value = do_extract(uf, NULL); out: unzClose(uf); #ifdef _WIN32 if (dirname) _chdir(game_cwd); #else if (dirname) { if (chdir(game_cwd)) fprintf(stderr, "Warning: can not chdir.\n"); } #endif return ret_value; } #endif instead-3.5.2+dfsg/src/unzip.c000066400000000000000000002130061467622671600162120ustar00rootroot00000000000000#ifdef _USE_UNPACK /* unzip.c -- IO for uncompress .zip files using zlib Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt ------------------------------------------------------------------------------------ Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of compatibility with older software. The following is from the original crypt.c. Code woven in by Terry Thorsen 1/2003. Copyright (c) 1990-2000 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] The encryption/decryption parts of this source code (as opposed to the non-echoing password parts) were originally written in Europe. The whole source package can be freely distributed, including from the USA. (Prior to January 2000, re-export from the US was a violation of US law.) This encryption code is a direct transcription of the algorithm from Roger Schlafly, described by Phil Katz in the file appnote.txt. This file (appnote.txt) is distributed with the PKZIP program (even in the version without encryption capabilities). ------------------------------------------------------------------------------------ Changes in unzip.c 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* 2007-2008 - Even Rouault - Remove old C style function prototypes 2007-2008 - Even Rouault - Add unzip support for ZIP64 Copyright (C) 2007-2008 Even Rouault Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G should only read the compressed/uncompressed size from the Zip64 format if the size from normal header was 0xFFFFFFFF Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) Patch created by Daniel Borca Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson */ #include #include #include #ifndef NOUNCRYPT #define NOUNCRYPT #endif #include "zlib.h" #include "unzip.h" #ifdef STDC # include # include # include #endif #ifdef NO_ERRNO_H extern int errno; #else # include #endif #ifndef local # define local static #endif /* compile with -Dlocal if your debugger can't find static symbols */ #ifndef CASESENSITIVITYDEFAULT_NO # if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) # define CASESENSITIVITYDEFAULT_NO # endif #endif #ifndef UNZ_BUFSIZE #define UNZ_BUFSIZE (16384) #endif #ifndef UNZ_MAXFILENAMEINZIP #define UNZ_MAXFILENAMEINZIP (256) #endif #ifndef ALLOC # define ALLOC(size) (malloc(size)) #endif #ifndef TRYFREE # define TRYFREE(p) {if (p) free(p);} #endif #define SIZECENTRALDIRITEM (0x2e) #define SIZEZIPLOCALHEADER (0x1e) const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; /* unz_file_info_interntal contain internal info about a file in zipfile*/ typedef struct unz_file_info64_internal_s { ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ } unz_file_info64_internal; /* file_in_zip_read_info_s contain internal information about a file in zipfile, when reading and decompress it */ typedef struct { char *read_buffer; /* internal buffer for compressed data */ z_stream stream; /* zLib stream structure for inflate */ #ifdef HAVE_BZIP2 bz_stream bstream; /* bzLib stream structure for bziped */ #endif ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ uLong stream_initialised; /* flag set if stream structure is initialised*/ ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ uInt size_local_extrafield;/* size of the local extra field */ ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ ZPOS64_T total_out_64; uLong crc32; /* crc32 of all data uncompressed */ uLong crc32_wait; /* crc32 we must obtain after decompress all */ ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ zlib_filefunc64_32_def z_filefunc; voidpf filestream; /* io structore of the zipfile */ uLong compression_method; /* compression method (0==store) */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ int raw; } file_in_zip64_read_info_s; /* unz64_s contain internal information about the zipfile */ typedef struct { zlib_filefunc64_32_def z_filefunc; int is64bitOpenFunction; voidpf filestream; /* io structore of the zipfile */ unz_global_info64 gi; /* public global information */ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ ZPOS64_T num_file; /* number of the current file in the zipfile*/ ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ ZPOS64_T central_pos; /* position of the beginning of the central dir*/ ZPOS64_T size_central_dir; /* size of the central directory */ ZPOS64_T offset_central_dir; /* offset of start of central directory with respect to the starting disk number */ unz_file_info64 cur_file_info; /* public info about the current file in zip*/ unz_file_info64_internal cur_file_info_internal; /* private info about it*/ file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current file if we are decompressing it */ int encrypted; int isZip64; # ifndef NOUNCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ const unsigned long* pcrc_32_tab; # endif } unz64_s; #ifndef NOUNCRYPT #include "crypt.h" #endif /* =========================================================================== Read a byte from a gz_stream; update next_in and avail_in. Return EOF for end of file. IN assertion: the stream s has been sucessfully opened for reading. */ local int unz64local_getByte OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) { unsigned char c; int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); if (err==1) { *pi = (int)c; return UNZ_OK; } else { if (ZERROR64(*pzlib_filefunc_def,filestream)) return UNZ_ERRNO; else return UNZ_EOF; } } /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ local int unz64local_getShort OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX) { uLong x ; int i = 0; int err; err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((uLong)i)<<8; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } local int unz64local_getLong OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX) { uLong x ; int i = 0; int err; err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x = (uLong)i; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((uLong)i)<<8; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((uLong)i)<<16; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x += ((uLong)i)<<24; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } local int unz64local_getLong64 OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) { ZPOS64_T x ; int i = 0; int err; err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x = (ZPOS64_T)i; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<8; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<16; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<24; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<32; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<40; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<48; if (err==UNZ_OK) err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); x |= ((ZPOS64_T)i)<<56; if (err==UNZ_OK) *pX = x; else *pX = 0; return err; } /* My own strcmpi / strcasecmp */ local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) { for (;;) { char c1=*(fileName1++); char c2=*(fileName2++); if ((c1>='a') && (c1<='z')) c1 -= 0x20; if ((c2>='a') && (c2<='z')) c2 -= 0x20; if (c1=='\0') return ((c2=='\0') ? 0 : -1); if (c2=='\0') return 1; if (c1c2) return 1; } } #ifdef CASESENSITIVITYDEFAULT_NO #define CASESENSITIVITYDEFAULTVALUE 2 #else #define CASESENSITIVITYDEFAULTVALUE 1 #endif #ifndef STRCMPCASENOSENTIVEFUNCTION #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal #endif /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity) { if (iCaseSensitivity==0) iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; if (iCaseSensitivity==1) return strcmp(fileName1,fileName2); return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); } #ifndef BUFREADCOMMENT #define BUFREADCOMMENT (0x400) #endif /* Locate the Central directory of a zipfile (at the end, just before the global comment) */ local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); return uPosFound; } /* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */ local ZPOS64_T unz64local_SearchCentralDir64 OF(( const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) { unsigned char* buf; ZPOS64_T uSizeFile; ZPOS64_T uBackRead; ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ ZPOS64_T uPosFound=0; uLong uL; ZPOS64_T relativeOffset; if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) return 0; uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); if (buf==NULL) return 0; uBackRead = 4; while (uBackReaduMaxBack) uBackRead = uMaxBack; else uBackRead+=BUFREADCOMMENT; uReadPos = uSizeFile-uBackRead ; uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) break; if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) break; for (i=(int)uReadSize-3; (i--)>0;) if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { uPosFound = uReadPos+i; break; } if (uPosFound!=0) break; } TRYFREE(buf); if (uPosFound == 0) return 0; /* Zip64 end of central directory locator */ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) return 0; /* the signature, already checked */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; /* number of the disk with the start of the zip64 end of central directory */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; if (uL != 0) return 0; /* relative offset of the zip64 end of central directory record */ if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) return 0; /* total number of disks */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; if (uL != 1) return 0; /* Goto end of central directory record */ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) return 0; /* the signature */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return 0; if (uL != 0x06064b50) return 0; return relativeOffset; } /* Open a Zip file. path contain the full pathname (by example, on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer "zlib/zlib114.zip". If the zipfile cannot be opened (file doesn't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. */ local unzFile unzOpenInternal (const void *path, zlib_filefunc64_32_def* pzlib_filefunc64_32_def, int is64bitOpenFunction) { unz64_s us; unz64_s *s; ZPOS64_T central_pos; uLong uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ ZPOS64_T number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ int err=UNZ_OK; if (unz_copyright[0]!=' ') return NULL; us.z_filefunc.zseek32_file = NULL; us.z_filefunc.ztell32_file = NULL; if (pzlib_filefunc64_32_def==NULL) fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); else us.z_filefunc = *pzlib_filefunc64_32_def; us.is64bitOpenFunction = is64bitOpenFunction; us.filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); if (us.filestream==NULL) return NULL; central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); if (central_pos) { uLong uS; ZPOS64_T uL64; us.isZip64 = 1; if (ZSEEK64(us.z_filefunc, us.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* the signature, already checked */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; /* size of zip64 end of central directory record */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) err=UNZ_ERRNO; /* version made by */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) err=UNZ_ERRNO; /* version needed to extract */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) err=UNZ_ERRNO; /* number of this disk */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; /* number of the disk with the start of the central directory */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central directory on this disk */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central directory */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO; if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; /* size of the central directory */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; us.gi.size_comment = 0; } else { central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); if (central_pos==0) err=UNZ_ERRNO; us.isZip64 = 0; if (ZSEEK64(us.z_filefunc, us.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* the signature, already checked */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; /* number of this disk */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; /* number of the disk with the start of the central directory */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir on this disk */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; us.gi.number_entry = uL; /* total number of entries in the central dir */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; number_entry_CD = uL; if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; /* size of the central directory */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; us.size_central_dir = uL; /* offset of start of central directory with respect to the starting disk number */ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; us.offset_central_dir = uL; /* zipfile comment length */ if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO; } if ((central_pospfile_in_zip_read!=NULL) unzCloseCurrentFile(file); ZCLOSE64(s->z_filefunc, s->filestream); TRYFREE(s); return UNZ_OK; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; *pglobal_info=s->gi; return UNZ_OK; } extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) { unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; /* to do : check if number_entry is not truncated */ pglobal_info32->number_entry = (uLong)s->gi.number_entry; pglobal_info32->size_comment = s->gi.size_comment; return UNZ_OK; } /* Translate date/time from Dos format to tm_unz (readable more easilty) */ local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) { ZPOS64_T uDate; uDate = (ZPOS64_T)(ulDosDate>>16); ptm->tm_mday = (uInt)(uDate&0x1f) ; ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; } /* Get Info about the current file in the zipfile, with internal only info */ local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, unz_file_info64 *pfile_info, unz_file_info64_internal *pfile_info_internal, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); local int unz64local_GetCurrentFileInfoInternal (unzFile file, unz_file_info64 *pfile_info, unz_file_info64_internal *pfile_info_internal, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize) { unz64_s* s; unz_file_info64 file_info; unz_file_info64_internal file_info_internal; int err=UNZ_OK; uLong uMagic; long lSeek=0; uLong uL; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (ZSEEK64(s->z_filefunc, s->filestream, s->pos_in_central_dir+s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* we check the magic */ if (err==UNZ_OK) { if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x02014b50) err=UNZ_BADZIPFILE; } if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) err=UNZ_ERRNO; unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; file_info.compressed_size = uL; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; file_info.uncompressed_size = uL; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) err=UNZ_ERRNO; /* relative offset of local header */ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; file_info_internal.offset_curfile = uL; lSeek+=file_info.size_filename; if ((err==UNZ_OK) && (szFileName!=NULL)) { uLong uSizeRead ; if (file_info.size_filename0) && (fileNameBufferSize>0)) if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek -= uSizeRead; } /* Read extrafield */ if ((err==UNZ_OK) && (extraField!=NULL)) { ZPOS64_T uSizeRead ; if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek += file_info.size_file_extra - (uLong)uSizeRead; } else lSeek += file_info.size_file_extra; if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) { uLong acc = 0; /* since lSeek now points to after the extra field we need to move back */ lSeek -= file_info.size_file_extra; if (lSeek!=0) { if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } while(acc < file_info.size_file_extra) { uLong headerId; uLong dataSize; if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) err=UNZ_ERRNO; /* ZIP64 extra fields */ if (headerId == 0x0001) { uLong uL; if(file_info.uncompressed_size == (ZPOS64_T)(unsigned long)-1) { if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) err=UNZ_ERRNO; } if(file_info.compressed_size == (ZPOS64_T)(unsigned long)-1) { if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) err=UNZ_ERRNO; } if(file_info_internal.offset_curfile == (ZPOS64_T)(unsigned long)-1) { /* Relative Header offset */ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) err=UNZ_ERRNO; } if(file_info.disk_num_start == (unsigned long)-1) { /* Disk Start Number */ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; } } else { if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) err=UNZ_ERRNO; } acc += 2 + 2 + dataSize; } } if ((err==UNZ_OK) && (szComment!=NULL)) { uLong uSizeRead ; if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) lSeek=0; else err=UNZ_ERRNO; } if ((file_info.size_file_comment>0) && (commentBufferSize>0)) if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; lSeek+=file_info.size_file_comment - uSizeRead; } else lSeek+=file_info.size_file_comment; if ((err==UNZ_OK) && (pfile_info!=NULL)) *pfile_info=file_info; if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) *pfile_info_internal=file_info_internal; return err; } /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, unz_file_info64 * pfile_info, char * szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char* szComment, uLong commentBufferSize) { return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, szFileName,fileNameBufferSize, extraField,extraFieldBufferSize, szComment,commentBufferSize); } extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, unz_file_info * pfile_info, char * szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char* szComment, uLong commentBufferSize) { int err; unz_file_info64 file_info64; err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, szFileName,fileNameBufferSize, extraField,extraFieldBufferSize, szComment,commentBufferSize); if (err==UNZ_OK) { pfile_info->version = file_info64.version; pfile_info->version_needed = file_info64.version_needed; pfile_info->flag = file_info64.flag; pfile_info->compression_method = file_info64.compression_method; pfile_info->dosDate = file_info64.dosDate; pfile_info->crc = file_info64.crc; pfile_info->size_filename = file_info64.size_filename; pfile_info->size_file_extra = file_info64.size_file_extra; pfile_info->size_file_comment = file_info64.size_file_comment; pfile_info->disk_num_start = file_info64.disk_num_start; pfile_info->internal_fa = file_info64.internal_fa; pfile_info->external_fa = file_info64.external_fa; pfile_info->tmu_date = file_info64.tmu_date, pfile_info->compressed_size = (uLong)file_info64.compressed_size; pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; } return err; } /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToFirstFile (unzFile file) { int err=UNZ_OK; unz64_s* s; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; s->pos_in_central_dir=s->offset_central_dir; s->num_file=0; err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzGoToNextFile (unzFile file) { unz64_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ if (s->num_file+1==s->gi.number_entry) return UNZ_END_OF_LIST_OF_FILE; s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; s->num_file++; err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzipStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) { unz64_s* s; int err; /* We remember the 'current' position in the file so that we can jump * back there if we fail. */ unz_file_info64 cur_file_infoSaved; unz_file_info64_internal cur_file_info_internalSaved; ZPOS64_T num_fileSaved; ZPOS64_T pos_in_central_dirSaved; if (file==NULL) return UNZ_PARAMERROR; if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; /* Save the current state */ num_fileSaved = s->num_file; pos_in_central_dirSaved = s->pos_in_central_dir; cur_file_infoSaved = s->cur_file_info; cur_file_info_internalSaved = s->cur_file_info_internal; err = unzGoToFirstFile(file); while (err == UNZ_OK) { char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; err = unzGetCurrentFileInfo64(file,NULL, szCurrentFileName,sizeof(szCurrentFileName)-1, NULL,0,NULL,0); if (err == UNZ_OK) { if (unzStringFileNameCompare(szCurrentFileName, szFileName,iCaseSensitivity)==0) return UNZ_OK; err = unzGoToNextFile(file); } } /* We failed, so restore the state of the 'current file' to where we * were. */ s->num_file = num_fileSaved ; s->pos_in_central_dir = pos_in_central_dirSaved ; s->cur_file_info = cur_file_infoSaved; s->cur_file_info_internal = cur_file_info_internalSaved; return err; } /* /////////////////////////////////////////// // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) // I need random access // // Further optimization could be realized by adding an ability // to cache the directory in memory. The goal being a single // comprehensive file read to put the file I need in a memory. */ /* typedef struct unz_file_pos_s { ZPOS64_T pos_in_zip_directory; // offset in file ZPOS64_T num_of_file; // # of file } unz_file_pos; */ extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) { unz64_s* s; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_END_OF_LIST_OF_FILE; file_pos->pos_in_zip_directory = s->pos_in_central_dir; file_pos->num_of_file = s->num_file; return UNZ_OK; } extern int ZEXPORT unzGetFilePos( unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; int err = unzGetFilePos64(file,&file_pos64); if (err==UNZ_OK) { file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; file_pos->num_of_file = (uLong)file_pos64.num_of_file; } return err; } extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) { unz64_s* s; int err; if (file==NULL || file_pos==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; /* jump to the right spot */ s->pos_in_central_dir = file_pos->pos_in_zip_directory; s->num_file = file_pos->num_of_file; /* set the current file */ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); /* return results */ s->current_file_ok = (err == UNZ_OK); return err; } extern int ZEXPORT unzGoToFilePos( unzFile file, unz_file_pos* file_pos) { unz64_file_pos file_pos64; if (file_pos == NULL) return UNZ_PARAMERROR; file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; file_pos64.num_of_file = file_pos->num_of_file; return unzGoToFilePos64(file,&file_pos64); } /* // Unzip Helper Functions - should be here? /////////////////////////////////////////// */ /* Read the local header of the current zipfile Check the coherency of the local header and info in the end of central directory about this file store in *piSizeVar the size of extra info in local header (filename and size of extra field data) */ local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, ZPOS64_T * poffset_local_extrafield, uInt * psize_local_extrafield) { uLong uMagic,uData,uFlags; uLong size_filename; uLong size_extra_field; int err=UNZ_OK; *piSizeVar = 0; *poffset_local_extrafield = 0; *psize_local_extrafield = 0; if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (err==UNZ_OK) { if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) err=UNZ_ERRNO; else if (uMagic!=0x04034b50) err=UNZ_BADZIPFILE; } if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; /* else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) err=UNZ_BADZIPFILE; */ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) err=UNZ_ERRNO; if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) err=UNZ_BADZIPFILE; if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && /* #ifdef HAVE_BZIP2 */ (s->cur_file_info.compression_method!=Z_BZIP2ED) && /* #endif */ (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ err=UNZ_ERRNO; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ err=UNZ_ERRNO; else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ err=UNZ_ERRNO; else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ err=UNZ_ERRNO; else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) err=UNZ_BADZIPFILE; if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) err=UNZ_ERRNO; else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) err=UNZ_BADZIPFILE; *piSizeVar += (uInt)size_filename; if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) err=UNZ_ERRNO; *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename; *psize_local_extrafield = (uInt)size_extra_field; *piSizeVar += (uInt)size_extra_field; return err; } /* Open for reading data the current file in the zipfile. If there is no error and the file is opened, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, int* level, int raw, const char* password) { int err=UNZ_OK; uInt iSizeVar; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ uInt size_local_extrafield; /* size of the local extra field */ # ifndef NOUNCRYPT char source[12]; # else if (password != NULL) return UNZ_PARAMERROR; # endif if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; if (!s->current_file_ok) return UNZ_PARAMERROR; if (s->pfile_in_zip_read != NULL) unzCloseCurrentFile(file); if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) return UNZ_BADZIPFILE; pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); if (pfile_in_zip_read_info==NULL) return UNZ_INTERNALERROR; pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; pfile_in_zip_read_info->pos_local_extrafield=0; pfile_in_zip_read_info->raw=raw; if (pfile_in_zip_read_info->read_buffer==NULL) { TRYFREE(pfile_in_zip_read_info); return UNZ_INTERNALERROR; } pfile_in_zip_read_info->stream_initialised=0; if (method!=NULL) *method = (int)s->cur_file_info.compression_method; if (level!=NULL) { *level = 6; switch (s->cur_file_info.flag & 0x06) { case 6 : *level = 1; break; case 4 : *level = 2; break; case 2 : *level = 9; break; } } if ((s->cur_file_info.compression_method!=0) && /* #ifdef HAVE_BZIP2 */ (s->cur_file_info.compression_method!=Z_BZIP2ED) && /* #endif */ (s->cur_file_info.compression_method!=Z_DEFLATED)) err=UNZ_BADZIPFILE; pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; pfile_in_zip_read_info->crc32=0; pfile_in_zip_read_info->total_out_64=0; pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; pfile_in_zip_read_info->filestream=s->filestream; pfile_in_zip_read_info->z_filefunc=s->z_filefunc; pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; pfile_in_zip_read_info->stream.total_out = 0; if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) { #ifdef HAVE_BZIP2 pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; pfile_in_zip_read_info->bstream.bzfree = (free_func)0; pfile_in_zip_read_info->bstream.opaque = (voidpf)0; pfile_in_zip_read_info->bstream.state = (voidpf)0; pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; pfile_in_zip_read_info->stream.zfree = (free_func)0; pfile_in_zip_read_info->stream.opaque = (voidpf)0; pfile_in_zip_read_info->stream.next_in = (voidpf)0; pfile_in_zip_read_info->stream.avail_in = 0; err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); if (err == Z_OK) pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; else { TRYFREE(pfile_in_zip_read_info); return err; } #else pfile_in_zip_read_info->raw=1; #endif } else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) { pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; pfile_in_zip_read_info->stream.zfree = (free_func)0; pfile_in_zip_read_info->stream.opaque = (voidpf)0; pfile_in_zip_read_info->stream.next_in = 0; pfile_in_zip_read_info->stream.avail_in = 0; err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); if (err == Z_OK) pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; else { TRYFREE(pfile_in_zip_read_info); return err; } /* windowBits is passed < 0 to tell that there is no zlib header. * Note that in this case inflate *requires* an extra "dummy" byte * after the compressed stream in order to complete decompression and * return Z_STREAM_END. * In unzip, i don't wait absolutely Z_STREAM_END because I known the * size of both compressed and uncompressed data */ } pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size ; pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size ; pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar; pfile_in_zip_read_info->stream.avail_in = (uInt)0; s->pfile_in_zip_read = pfile_in_zip_read_info; s->encrypted = 0; # ifndef NOUNCRYPT if (password != NULL) { int i; s->pcrc_32_tab = get_crc_table(); init_keys(password,s->keys,s->pcrc_32_tab); if (ZSEEK64(s->z_filefunc, s->filestream, s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile, SEEK_SET)!=0) return UNZ_INTERNALERROR; if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) return UNZ_INTERNALERROR; for (i = 0; i<12; i++) zdecode(s->keys,s->pcrc_32_tab,source[i]); s->pfile_in_zip_read->pos_in_zipfile+=12; s->encrypted=1; } # endif return UNZ_OK; } extern int ZEXPORT unzOpenCurrentFile (unzFile file) { return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); } extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) { return unzOpenCurrentFile3(file, NULL, NULL, 0, password); } extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) { return unzOpenCurrentFile3(file, method, level, raw, NULL); } /** Addition for GDAL : START */ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; s=(unz64_s*)file; if (file==NULL) return 0; /* UNZ_PARAMERROR; */ pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return 0; /* UNZ_PARAMERROR; */ return pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile; } /** Addition for GDAL : END */ /* Read bytes from the current file. buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) { int err=UNZ_OK; uInt iRead = 0; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if (pfile_in_zip_read_info->read_buffer == NULL) return UNZ_END_OF_LIST_OF_FILE; if (len==0) return 0; pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; pfile_in_zip_read_info->stream.avail_out = (uInt)len; if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && (!(pfile_in_zip_read_info->raw))) pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; if ((len>pfile_in_zip_read_info->rest_read_compressed+ pfile_in_zip_read_info->stream.avail_in) && (pfile_in_zip_read_info->raw)) pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_compressed+ pfile_in_zip_read_info->stream.avail_in; while (pfile_in_zip_read_info->stream.avail_out>0) { if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0)) { uInt uReadThis = UNZ_BUFSIZE; if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; if (uReadThis == 0) return UNZ_EOF; if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (ZREAD64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->read_buffer, uReadThis)!=uReadThis) return UNZ_ERRNO; # ifndef NOUNCRYPT if(s->encrypted) { uInt i; for(i=0;iread_buffer[i] = zdecode(s->keys,s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); } # endif pfile_in_zip_read_info->pos_in_zipfile += uReadThis; pfile_in_zip_read_info->rest_read_compressed-=uReadThis; pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->read_buffer; pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; } if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) { uInt uDoCopy,i ; if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed == 0)) return (iRead==0) ? UNZ_EOF : iRead; if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) uDoCopy = pfile_in_zip_read_info->stream.avail_out ; else uDoCopy = pfile_in_zip_read_info->stream.avail_in ; for (i=0;istream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i); pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, pfile_in_zip_read_info->stream.next_out, uDoCopy); pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; pfile_in_zip_read_info->stream.avail_in -= uDoCopy; pfile_in_zip_read_info->stream.avail_out -= uDoCopy; pfile_in_zip_read_info->stream.next_out += uDoCopy; pfile_in_zip_read_info->stream.next_in += uDoCopy; pfile_in_zip_read_info->stream.total_out += uDoCopy; iRead += uDoCopy; } else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) { #ifdef HAVE_BZIP2 uLong uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; uLong uOutThis; pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; pfile_in_zip_read_info->bstream.total_in_hi32 = 0; pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; pfile_in_zip_read_info->bstream.total_out_hi32 = 0; uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; uOutThis = uTotalOutAfter-uTotalOutBefore; pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; if (err==BZ_STREAM_END) return (iRead==0) ? UNZ_EOF : iRead; if (err!=BZ_OK) break; #endif } /* end Z_BZIP2ED */ else { ZPOS64_T uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; ZPOS64_T uOutThis; int flush=Z_SYNC_FLUSH; uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; bufBefore = pfile_in_zip_read_info->stream.next_out; /* if ((pfile_in_zip_read_info->rest_read_uncompressed == pfile_in_zip_read_info->stream.avail_out) && (pfile_in_zip_read_info->rest_read_compressed == 0)) flush = Z_FINISH; */ err=inflate(&pfile_in_zip_read_info->stream,flush); if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) err = Z_DATA_ERROR; uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; uOutThis = uTotalOutAfter-uTotalOutBefore; pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); if (err==Z_STREAM_END) return (iRead==0) ? UNZ_EOF : iRead; if (err!=Z_OK) break; } } if (err==Z_OK) return iRead; return err; } /* Give the current position in uncompressed data */ extern z_off_t ZEXPORT unztell (unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; return (z_off_t)pfile_in_zip_read_info->stream.total_out; } extern ZPOS64_T ZEXPORT unztell64 (unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return (ZPOS64_T)-1; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return (ZPOS64_T)-1; return pfile_in_zip_read_info->total_out_64; } /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzeof (unzFile file) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if (pfile_in_zip_read_info->rest_read_uncompressed == 0) return 1; else return 0; } /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field that can be read if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) { unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; uInt read_now; ZPOS64_T size_to_read; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; size_to_read = (pfile_in_zip_read_info->size_local_extrafield - pfile_in_zip_read_info->pos_local_extrafield); if (buf==NULL) return (int)size_to_read; if (len>size_to_read) read_now = (uInt)size_to_read; else read_now = (uInt)len ; if (read_now==0) return 0; if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (ZREAD64(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, buf,read_now)!=read_now) return UNZ_ERRNO; return (int)read_now; } /* Close the file in zip opened with unzipOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzCloseCurrentFile (unzFile file) { int err=UNZ_OK; unz64_s* s; file_in_zip64_read_info_s* pfile_in_zip_read_info; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && (!pfile_in_zip_read_info->raw)) { if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) err=UNZ_CRCERROR; } TRYFREE(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) inflateEnd(&pfile_in_zip_read_info->stream); #ifdef HAVE_BZIP2 else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); #endif pfile_in_zip_read_info->stream_initialised = 0; TRYFREE(pfile_in_zip_read_info); s->pfile_in_zip_read=NULL; return err; } /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) { unz64_s* s; uLong uReadThis ; if (file==NULL) return (int)UNZ_PARAMERROR; s=(unz64_s*)file; uReadThis = uSizeBuf; if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) return UNZ_ERRNO; if (uReadThis>0) { *szComment='\0'; if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) return UNZ_ERRNO; } if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0'; return (int)uReadThis; } /* Additions by RX '2004 */ extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) { unz64_s* s; if (file==NULL) return 0; /* UNZ_PARAMERROR; */ s=(unz64_s*)file; if (!s->current_file_ok) return 0; if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) if (s->num_file==s->gi.number_entry) return 0; return s->pos_in_central_dir; } extern uLong ZEXPORT unzGetOffset (unzFile file) { ZPOS64_T offset64; if (file==NULL) return 0; /* UNZ_PARAMERROR; */ offset64 = unzGetOffset64(file); return (uLong)offset64; } extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) { unz64_s* s; int err; if (file==NULL) return UNZ_PARAMERROR; s=(unz64_s*)file; s->pos_in_central_dir = pos; s->num_file = s->gi.number_entry; /* hack */ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, &s->cur_file_info_internal, NULL,0,NULL,0,NULL,0); s->current_file_ok = (err == UNZ_OK); return err; } extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) { return unzSetOffset64(file,pos); } #endif instead-3.5.2+dfsg/src/unzip.h000066400000000000000000000377461467622671600162360ustar00rootroot00000000000000/* unzip.h -- IO for uncompress .zip files using zlib Version 1.1, February 14h, 2010 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) For more info read MiniZip_info.txt --------------------------------------------------------------------------------- Condition of use and distribution are the same than zlib : This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. --------------------------------------------------------------------------------- Changes See header of unzip64.c */ #ifndef _unz64_H #define _unz64_H #ifdef __cplusplus extern "C" { #endif #ifndef _ZLIB_H #include "zlib.h" #endif #ifndef _ZLIBIOAPI_H #include "ioapi.h" #endif #ifdef HAVE_BZIP2 #include "bzlib.h" #endif #define Z_BZIP2ED 12 #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) /* like the STRICT of WIN32, we define a pointer that cannot be converted from (void*) without cast */ typedef struct TagunzFile__ { int unused; } unzFile__; typedef unzFile__ *unzFile; #else typedef voidp unzFile; #endif #define UNZ_OK (0) #define UNZ_END_OF_LIST_OF_FILE (-100) #define UNZ_ERRNO (Z_ERRNO) #define UNZ_EOF (0) #define UNZ_PARAMERROR (-102) #define UNZ_BADZIPFILE (-103) #define UNZ_INTERNALERROR (-104) #define UNZ_CRCERROR (-105) /* tm_unz contain date/time info */ typedef struct tm_unz_s { uInt tm_sec; /* seconds after the minute - [0,59] */ uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_mday; /* day of the month - [1,31] */ uInt tm_mon; /* months since January - [0,11] */ uInt tm_year; /* years - [1980..2044] */ } tm_unz; /* unz_global_info structure contain global data about the ZIPfile These data comes from the end of central dir */ typedef struct unz_global_info64_s { ZPOS64_T number_entry; /* total number of entries in the central dir on this disk */ uLong size_comment; /* size of the global comment of the zipfile */ } unz_global_info64; typedef struct unz_global_info_s { uLong number_entry; /* total number of entries in the central dir on this disk */ uLong size_comment; /* size of the global comment of the zipfile */ } unz_global_info; /* unz_file_info contain information about a file in the zipfile */ typedef struct unz_file_info64_s { uLong version; /* version made by 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */ uLong flag; /* general purpose bit flag 2 bytes */ uLong compression_method; /* compression method 2 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong crc; /* crc-32 4 bytes */ ZPOS64_T compressed_size; /* compressed size 8 bytes */ ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ uLong size_filename; /* filename length 2 bytes */ uLong size_file_extra; /* extra field length 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */ uLong disk_num_start; /* disk number start 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ tm_unz tmu_date; } unz_file_info64; typedef struct unz_file_info_s { uLong version; /* version made by 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */ uLong flag; /* general purpose bit flag 2 bytes */ uLong compression_method; /* compression method 2 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong crc; /* crc-32 4 bytes */ uLong compressed_size; /* compressed size 4 bytes */ uLong uncompressed_size; /* uncompressed size 4 bytes */ uLong size_filename; /* filename length 2 bytes */ uLong size_file_extra; /* extra field length 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */ uLong disk_num_start; /* disk number start 2 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */ uLong external_fa; /* external file attributes 4 bytes */ tm_unz tmu_date; } unz_file_info; extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, const char* fileName2, int iCaseSensitivity)); /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) If iCaseSenisivity = 0, case sensitivity is defaut of your operating system (like 1 on Unix, 2 on Windows) */ extern unzFile ZEXPORT unzOpen OF((const char *path)); extern unzFile ZEXPORT unzOpen64 OF((const void *path)); /* Open a Zip file. path contain the full pathname (by example, on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer "zlib/zlib113.zip". If the zipfile cannot be opened (file don't exist or in not valid), the return value is NULL. Else, the return value is a unzFile Handle, usable with other function of this unzip package. the "64" function take a const void* pointer, because the path is just the value passed to the open64_file_func callback. Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* does not describe the reality */ extern unzFile ZEXPORT unzOpen2 OF((const char *path, zlib_filefunc_def* pzlib_filefunc_def)); /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, zlib_filefunc64_def* pzlib_filefunc_def)); /* Open a Zip file, like unz64Open, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ extern int ZEXPORT unzClose OF((unzFile file)); /* Close a ZipFile opened with unzipOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzipCloseCurrentFile before call unzipClose. return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, unz_global_info *pglobal_info)); extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, unz_global_info64 *pglobal_info)); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ extern int ZEXPORT unzGetGlobalComment OF((unzFile file, char *szComment, uLong uSizeBuf)); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. return the number of byte copied or an error code <0 */ /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ extern int ZEXPORT unzGoToNextFile OF((unzFile file)); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ extern int ZEXPORT unzLocateFile OF((unzFile file, const char *szFileName, int iCaseSensitivity)); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare return value : UNZ_OK if the file is found. It becomes the current file. UNZ_END_OF_LIST_OF_FILE if the file is not found */ /* ****************************************** */ /* Ryan supplied functions */ /* unz_file_info contain information about a file in the zipfile */ typedef struct unz_file_pos_s { uLong pos_in_zip_directory; /* offset in zip file directory */ uLong num_of_file; /* # of file */ } unz_file_pos; extern int ZEXPORT unzGetFilePos( unzFile file, unz_file_pos* file_pos); extern int ZEXPORT unzGoToFilePos( unzFile file, unz_file_pos* file_pos); typedef struct unz64_file_pos_s { ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ ZPOS64_T num_of_file; /* # of file */ } unz64_file_pos; extern int ZEXPORT unzGetFilePos64( unzFile file, unz64_file_pos* file_pos); extern int ZEXPORT unzGoToFilePos64( unzFile file, const unz64_file_pos* file_pos); /* ****************************************** */ extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, unz_file_info64 *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)); /* Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain somes info about the current file if szFileName!=NULL, the filemane string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). This is the Central-header version of the extra field if szComment!=NULL, the comment string of the file will be copied in szComment (commentBufferSize is the size of the buffer) */ /** Addition for GDAL : START */ extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); /** Addition for GDAL : END */ /***************************************************************************/ /* for reading the content of the current zipfile, you can open it, read data from it, and close it (you can close it before reading all the file) */ extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, const char* password)); /* Open for reading data the current file in the zipfile. password is a crypting password If there is no error, the return value is UNZ_OK. */ extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, int* method, int* level, int raw)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, int* method, int* level, int raw, const char* password)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 *method will receive method of compression, *level will receive level of compression note : you can set level parameter as NULL (if you did not want known level, but you CANNOT set method parameter as NULL */ extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ extern int ZEXPORT unzReadCurrentFile OF((unzFile file, voidp buf, unsigned len)); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied len the size of buf. return the number of byte copied if somes bytes are copied return 0 if the end of file was reached return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ extern z_off_t ZEXPORT unztell OF((unzFile file)); extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); /* Give the current position in uncompressed data */ extern int ZEXPORT unzeof OF((unzFile file)); /* return 1 if the end of file was reached, 0 elsewhere */ extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, voidp buf, unsigned len)); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is more info in the local-header version than in the central-header) if buf==NULL, it return the size of the local extra field if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. the return value is the number of bytes copied in buf, or (if <0) the error code */ /***************************************************************************/ /* Get the current file offset */ extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); extern uLong ZEXPORT unzGetOffset (unzFile file); /* Set the current file offset */ extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); #ifdef __cplusplus } #endif #endif /* _unz64_H */ instead-3.5.2+dfsg/src/utils.c000066400000000000000000000246651467622671600162200ustar00rootroot00000000000000/* * Copyright 2009-2022 Peter Kosyh * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include "externals.h" #include "utils.h" int process_cmd(char *n, char *v, struct parser *cmd_parser) { int i; n = strip(n); v = strip(v); for (i = 0; cmd_parser[i].cmd; i++) { if (!strcmp(cmd_parser[i].cmd, n)) { return cmd_parser[i].fn(v, cmd_parser[i].p); } } return -1; } static int fgetsesc(char *oline, size_t size, char *(*getl)(void *p, char *s, int size), void *fp) { int nr = 0; char line[4096]; size_t len; *oline = 0; *line = 0; while (getl(fp, line, sizeof(line))) { int i; nr ++; i = strcspn(line, "\n\r"); if (!i || !line[i]) break; line[i] = 0; if (line[i - 1] == '\\') { line[i - 1] = 0; strncat(oline, line, size - 1); len = strlen(line); if (len >= size) return nr; size -= len; line[0] = 0; } else { break; } } strncat(oline, line, size - 1); return nr; } char *find_in_esc(const char *l, const char *s) { int esc = 0; for (; *l; l++) { if (esc) { esc = 0; continue; } l += strcspn(l, s); if (*l == '\\') { esc = 1; continue; } if (!esc) return (char*)l; } return NULL; } static void unescape_sym(char *l, const char *s) { int esc = 0; char *r = l; int d = 0; for (; *l; ) { if (esc) { esc = 0; if (strspn(l, s)) r --; *r ++ = *l ++; continue; } d = strcspn(l, s); if (d) memmove(r, l, d); r += d; l += d; if (*l == '\\') esc = 1; if (*l) *r ++ = *l ++; } *r = 0; } static void comments_zap(char *p) { char *l = find_in_esc(p, "\\;\n"); if (l) *l = 0; unescape_sym(p, "\\;\n"); } int parse_all(void *fp, char *(*getl)(void *p, char *s, int size), const char *path, struct parser *cmd_parser) { int nr; int rc = 0; int line_nr = 1; char line[4096]; if (!fp) return -1; while ((nr = fgetsesc(line, sizeof(line), getl, fp))) { char *p = line; char *val; int len; line_nr += nr; p += strspn(p, " \t"); if (*p == ';') continue; len = strcspn(p, "="); if (p[len] != '=') /* just ignore it */ continue; p[len] = 0; val = p + len + 1; len = strcspn(p, " \t"); p[len] = 0; /* printf("%s\n", p); */ val += strspn(val, " \t"); comments_zap(val); /* val[strcspn(val, ";\n")] = 0; */ if (process_cmd(p, val, cmd_parser)) { rc = -1; fprintf(stderr, "Can't process cmd '%s' on line %d in '%s': %s\n", p, line_nr - nr, path, strerror(errno)); } } return rc; } static char *file_gets(void *fd, char *s, int size) { return fgets(s, size, (FILE *)fd); } static char *idff_gets(void *fd, char *s, int size) { return idf_gets((idff_t)fd, s, size); } int parse_ini(const char *path, struct parser *cmd_parser) { int rc = 0; FILE *fp; fp = fopen(path, "rb"); if (!fp) return -1; rc = parse_all(fp, file_gets, path, cmd_parser); fclose(fp); return rc; } int parse_idff(idff_t idff, const char *path, struct parser *cmd_parser) { if (!idff) return -1; return parse_all(idff, idff_gets, path, cmd_parser); } int parse_string(const char *v, void *data) { char **p = ((char **)data); if (*p) free(*p); *p = strdup(v); if (!*p) return -1; return 0; } char *encode_esc_string(const char *v) { char *r, *p; if (!v) return NULL; p = r = malloc((strlen(v)*2) + 1); if (!r) return NULL; while (*v) { switch (*v) { case ' ': *p ++ = '\\'; *p ++ = ' '; break; case '"': *p ++ = '\\'; *p ++ = '"'; break; case '\'': *p ++ = '\\'; *p ++ = '\''; break; case '\\': *p ++ = '\\'; *p ++ = '\\'; break; case '\n': *p ++ ='\\'; *p ++ ='\n'; break; default: *p ++ = *v; } v ++; } *p ++ = 0; return r; } int parse_esc_string(const char *v, void *data) { int esc = 0; char *ptr; char **p = ((char **)data); if (*p) free(*p); *p = strdup(v); if (!*p) return -1; for (ptr = *p; *v; v ++) { if (esc) { switch (*v) { case 'n': *ptr = '\n'; break; case '$': *ptr = '$'; break; case '\\': *ptr = '\\'; break; case ';': *ptr = ';'; break; case 'r': *ptr = '\n'; break; default: *ptr = *v; break; } esc = 0; ptr ++; continue; } else if (*v != '\\') { *ptr = *v; ptr ++; continue; } else esc = 1; } *ptr = 0; return 0; } int parse_int(const char *v, void *data) { int *i = (int *)data; char *eptr = NULL; *i = strtol(v, &eptr, 0); if (!eptr || *eptr) return -1; return 0; } int parse_float(const char *v, void *data) { float *f = (float *)data; if (sscanf(v, "%f", f) != 1) return -1; return 0; } int parse_path(const char *v, void *data) { char **p = ((char **)data); if (*p) free(*p); if (!v[0]) { *p = strdup(""); return (*p)?0:-1; } *p = strdup(v); if (!*p) return -1; /* *p = sdl_path(*p); note: do not convert relative paths to avoid double encoding */ unix_path(*p); return 0; } #if defined(_WIN32) && !defined(WINRT) #include #include static char *wchar2utf(const wchar_t *wc) { char *buf; int size = WideCharToMultiByte (CP_UTF8, 0, wc, -1, NULL, 0, NULL, NULL); if (!size) return NULL; buf = malloc(size); WideCharToMultiByte (CP_UTF8, 0, wc, -1, buf, size, NULL, NULL); return buf; } char *w32_getdir(char *path, size_t size) { wchar_t *wp; char *p = NULL; path[0] = 0; wp = _wgetcwd(NULL, 0); if (!wp) return path; p = wchar2utf(wp); free(wp); if (!p) return path; snprintf(path, size, "%s", p); free(p); return path; } #endif int parse_full_path(const char *v, void *data) { char cwd[PATH_MAX]; char **p = ((char **)data); if (*p) free(*p); if (!v[0]) { *p = strdup(""); return (*p)?0:-1; } #if defined(_WIN32) && !defined(WINRT) w32_getdir(cwd, sizeof(cwd)); #else getdir(cwd, sizeof(cwd)); #endif *p = malloc(strlen(v) + strlen(cwd) + 2); if (!*p) return -1; strcpy(*p, cwd); strcat(*p,"/"); strcat(*p, v); *p = sdl_path(*p); return 0; } static char *lookup_tag_all(const char *tag, const char *comm, char *(*getl)(void *p, char *s, int size), void *fp) { int brk = 0; char *l; char line[1024]; while ((l = getl(fp, line, sizeof(line))) && !brk) { l = parse_tag(l, tag, comm, &brk); if (l) return l; } return NULL; } char *lookup_tag(const char *fname, const char *tag, const char *comm) { char *l; FILE *fd = fopen(fname, "rb"); if (!fd) return NULL; l = lookup_tag_all(tag, comm, file_gets, fd); fclose(fd); return l; } char *lookup_lang_tag(const char *fname, const char *tag, const char *comm, const char *opt_lang) { char lang_tag[1024]; char *l; snprintf(lang_tag, sizeof(lang_tag), "%s(%s)", tag, opt_lang); l = lookup_tag(fname, lang_tag, comm); if (!l) l = lookup_tag(fname, tag, comm); return l; } char *lookup_lang_tag_idf(idf_t idf, const char *fname, const char *tag, const char *comm, const char *opt_lang) { char lang_tag[1024]; char *l; idff_t idff; if (!idf) return NULL; idff = idf_open(idf, fname); if (!idff) return NULL; snprintf(lang_tag, sizeof(lang_tag), "%s(%s)", tag, opt_lang); l = lookup_tag_all(lang_tag, comm, idff_gets, idff); if (!l) { idf_seek(idff, 0, SEEK_SET); l = lookup_tag_all(tag, comm, idff_gets, idff); } idf_close(idff); return l; } char *parse_tag(char *line, const char *tag, const char *comm, int *brk) { char *l = line; char *ns = NULL; char ftag[1024]; snprintf(ftag, sizeof(ftag), "$%s:", tag); l += strspn(l, " \t"); if (strncmp(l, comm, strlen(comm))) { /* non coment block */ *brk = 1; return NULL; } l += strlen(comm); l += strspn(l, " \t"); if (strncmp(l, ftag, strlen(ftag))) return NULL; l += strlen(ftag); l += strspn(l, " \t"); ns = l; l = find_in_esc(l, "\\$"); if (l) *l = 0; l = ns; ns = NULL; if (parse_esc_string(l, &ns)) return NULL; l = ns + strlen(ns); while (l != ns) { l --; if (*l != '\r' && *l != '\n') break; *l = 0; } return ns; } int remove_dir(const char *path) { DIR *d; struct dirent *de; if (!path) return 0; d = opendir(path); if (!d) { if (!access(path, F_OK)) { unlink(path); } return -1; } while ((de = readdir(d))) { char *p; if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; p = getfilepath(path, de->d_name); if (p) { remove_dir(p); free(p); } } closedir(d); rmdir(path); return 0; } void data2hex(const void *d, int len, void *o) { unsigned char *data = (unsigned char *)d; unsigned char *out = (unsigned char *)o; static char map[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; while (len --) { unsigned char a = *data ++; *out ++ = map[a & 0xf]; *out ++ = map[a >> 4]; } } int hex2data(const void *d, void *o, int len) { unsigned char *data = (unsigned char *)d; unsigned char *out = (unsigned char *)o; unsigned char b = 0; int rc = 0; len *= 2; while (len --) { unsigned char c = *data ++; if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) break; if (c >= 'a') c -= ('a' - 10); else c -= '0'; if (len & 1) b = c; else *out ++ = b + (c << 4); rc ++; } return rc; } void trunc_lines(char *pp, int max) { int n = 0; if (!pp) return; if (max == 0) { pp[strcspn(pp, "\n\r")] = 0; return; } while (pp[strcspn(pp, "\n\r")]) { n ++; pp += strcspn(pp, "\n\r"); if (n >= max) { *pp = 0; break; } pp ++; } } #ifdef __EMSCRIPTEN__ void data_sync(void) { EM_ASM(FS.syncfs(function(error) { if (error) { console.log("Error while syncing:", error); } else { console.log("Config synced"); } });); } #else void data_sync(void) { } #endif instead-3.5.2+dfsg/src/utils.h000066400000000000000000000052651467622671600162200ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh * * 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. * */ #ifndef __UTIL_H_INCLUDED #define __UTIL_H_INCLUDED #include "instead/util.h" #include "instead/idf.h" #include "instead/cache.h" #include "instead/list.h" typedef int (*parser_fn)(const char *v, void *data); struct parser { const char *cmd; parser_fn fn; void *p; long aux; }; extern int parse_ini(const char *path, struct parser *cmd_parser); extern int parse_idff(idff_t idff, const char *path, struct parser *cmd_parser); extern char *lookup_tag(const char *fname, const char *tag, const char *comm); extern char *lookup_lang_tag(const char *fname, const char *tag, const char *comm, const char *lang); extern char *lookup_lang_tag_idf(idf_t idf, const char *fname, const char *tag, const char *comm, const char *lang); extern int parse_esc_string(const char *v, void *data); extern int parse_string(const char *v, void *data); extern int parse_int(const char *v, void *data); extern int parse_float(const char *v, void *data); extern int parse_full_path(const char *v, void *data); extern int parse_path(const char *v, void *data); extern int process_cmd(char *n, char *v, struct parser *cmd_parser); extern char *encode_esc_string(const char *v); extern char *find_in_esc(const char *l, const char *s); extern char *sdl_path(char *path); extern char *parse_tag(char *line, const char *tag, const char *comm, int *brk); extern int remove_dir(const char *path); extern void data2hex(const void *d, int len, void *o); extern int hex2data(const void *d, void *o, int len); extern void trunc_lines(char *pp, int max); extern void data_sync(void); /* rw data sync */ #endif instead-3.5.2+dfsg/src/windows.c000066400000000000000000000221211467622671600165330ustar00rootroot00000000000000/* * Copyright 2009-2016 Peter Kosyh , 2009 Ilya Ryndin * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #include #include #include #ifndef _MSC_VER #include #endif #include #include #include #include "externals.h" #include "internals.h" #if !defined(_UWP) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0A00 && !defined(__MINGW32__) #define _UWP #endif extern char *curgame_dir; static char local_games_path[PATH_MAX]; static char local_themes_path[PATH_MAX]; static char local_stead_path[PATH_MAX]; static char save_path[PATH_MAX]; static char cfg_path[PATH_MAX]; #ifdef _UWP char *game_locale(void) { char buff[64]; char res[64]; buff[0] = 0; /* Antokolos: Note LOCALE_NAME_USER_DEFAULT instead of LOCALE_USER_DEFAULT */ if (!GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO639LANGNAME, buff, sizeof(buff) - 1)) return NULL; wcstombs(res, buff, sizeof(res)); return strdup(res); } #else char *game_locale(void) { char buff[64]; buff[0] = 0; if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, buff,sizeof(buff) - 1)) return NULL; return strdup(buff); } #endif static char *game_codepage = NULL; #ifdef _HAVE_ICONV #ifdef _UWP static char *game_cp(void) { char cpbuff[64]; char buff[64]; char res[64]; buff[0] = 0; /* Antokolos: Note LOCALE_NAME_USER_DEFAULT instead of LOCALE_USER_DEFAULT */ if (!GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO639LANGNAME, buff, sizeof(buff) - 1)) return NULL; wcstombs(res, buff, sizeof(res)); snprintf(cpbuff, sizeof(cpbuff), "WINDOWS-%s", res); return strdup(cpbuff); } #else static char *game_cp(void) { char cpbuff[64]; char buff[64]; buff[0] = 0; if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, buff,sizeof(buff) - 1)) return NULL; snprintf(cpbuff, sizeof(cpbuff), "WINDOWS-%s", buff); return strdup(cpbuff); } #endif char *mbs2utf8(const char *s) { iconv_t han; char *str; if (!game_codepage) game_codepage = game_cp(); if (!s) return NULL; if (!game_codepage) goto out0; han = iconv_open("UTF-8", game_codepage); if (han == (iconv_t)-1) goto out0; if (!(str = decode(han, s))) goto out1; iconv_close(han); return str; out1: iconv_close(han); out0: return strdup(s); } #else char *mbs2utf8(const char *s) { return strdup(s); } #endif extern void unix_path(char *); char *sdl_path(char *p) { #if 0 char *r = mbs2utf8(p); if (p) free(p); unix_path(r); return r; #else unix_path(p); return p; #endif } char *appdir( void ); static int mkdir_chk(const char *dirname) { #ifdef WINRT /* no errno? */ DWORD err; if (CreateDirectoryA(dirname, NULL)) return 0; err = GetLastError(); if (err == ERROR_ALREADY_EXISTS) return 0; return -1; #else return mkdir(dirname) && errno != EEXIST; #endif } #ifdef _UWP char *game_tmp_path(void) { static char lpTempPathBuffer[MAX_PATH]; getAppTempDir(lpTempPathBuffer); strcat((char*)lpTempPathBuffer, "/instead-games"); if (mkdir((char*)lpTempPathBuffer) && access((char*)lpTempPathBuffer, W_OK)) return NULL; unix_path((char*)lpTempPathBuffer); return (char*)lpTempPathBuffer; } #else char *game_tmp_path(void) { DWORD dwRetVal = 0; static TCHAR lpTempPathBuffer[MAX_PATH]; static char tmp[MAX_PATH]; // Gets the temp path env string (no guarantee it's a valid path). dwRetVal = GetTempPath(MAX_PATH, // length of the buffer lpTempPathBuffer); // buffer for path if (dwRetVal > MAX_PATH || (dwRetVal == 0)) { return NULL; } #ifdef _WIDE_CHARS wcstombs(tmp, lpTempPathBuffer, sizeof(tmp)); #else strcpy(tmp, (char*)lpTempPathBuffer); #endif strcat(tmp, "/instead-games"); if (mkdir_chk(tmp)) return NULL; unix_path(tmp); return tmp; } #endif char *game_local_games_path(int cr) { char *app = appdir(); if (!app) return NULL; snprintf(local_games_path, sizeof(local_games_path) - 1 , "%s/", app); if (cr) { if (mkdir_chk(local_games_path)) return NULL; } strcat(local_games_path,"/games"); if (cr) { if (mkdir_chk(local_games_path)) return NULL; } return local_games_path; } char *game_local_themes_path(void) { snprintf(local_themes_path, sizeof(local_themes_path) - 1 , "%s/themes", appdir()); return local_themes_path; } char *instead_local_stead_path(void) { snprintf(local_stead_path, sizeof(local_stead_path) - 1 , "%s/stead", appdir()); return local_stead_path; } #if 0 char *home_dir( void ) { static char homedir[PATH_MAX]=""; SHGetFolderPath( NULL, CSIDL_FLAG_CREATE | CSIDL_PROFILE, NULL, 0, (LPTSTR)homedir ); unix_path(homedir); return homedir; } #endif char *appdir( void ) { static char dir[PATH_MAX]=""; #ifdef _LOCAL_APPDATA if (!appdata_sw) { strcpy(dir, game_cwd); strcat(dir, "/appdata"); } #endif if (appdata_sw) strcpy(dir, appdata_sw); if (dir[0] && !access(dir, W_OK)) return dir; #ifdef _UWP /* TODO: always define _LOCAL_APPDATA on UWP??? */ return NULL; #else SHGetFolderPath( NULL, CSIDL_FLAG_CREATE | CSIDL_LOCAL_APPDATA, NULL, 0, (LPTSTR)dir ); unix_path(dir); strcat(dir, "/instead"); return dir; #endif } char *game_cfg_path( void ) { char *p = appdir(); if (!p) return NULL; snprintf(cfg_path, sizeof(cfg_path) - 1 , "%src", p); /* appdir/insteadrc ;) */ if (!access(cfg_path, R_OK)) return cfg_path; /* no at home? Try in dir */ snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s", p); if (mkdir_chk(cfg_path)) { snprintf(cfg_path, sizeof(cfg_path) - 1 , "%src", p); /* appdir/insteadrc ;) */ return cfg_path; } snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/insteadrc", p); return cfg_path; } char *game_save_path( int cr, int nr ) { char dir[PATH_MAX]; char *p = appdir(); if (!curgame_dir) return NULL; if (!access("saves", R_OK)) { if (nr) snprintf(save_path, sizeof(save_path) - 1, "saves/save%d", nr); else snprintf(save_path, sizeof(save_path) - 1, "saves/autosave"); return save_path; } if (!p) return NULL; strcpy(dir,p); if (cr && mkdir_chk(dir)) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/saves", dir); if (cr && mkdir_chk(save_path)) return NULL; snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s", dir, curgame_dir); if (cr && mkdir_chk(save_path)) return NULL; if (nr) snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/save%d", dir, curgame_dir, nr); else snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/autosave", dir, curgame_dir); return save_path; } int debug_init(void) { // No debugging for UWP for now #ifndef _UWP if (!AllocConsole()) return -1; SetConsoleTitle("Debug"); freopen("CON", "w", stdout); //Map stdout freopen("CON", "w", stderr); //Map stderr freopen("CON", "r", stdin); //Map stdin #endif return 0; } void debug_done() { #ifndef _UWP if (game_running) { fprintf(stderr, "Press enter to close the console.\n"); fgetc(stdin); } FreeConsole(); #endif } #ifdef _USE_BROWSE char *open_file_dialog(void) { OPENFILENAME ofn; static char szFile[MAX_PATH]; static char szOldDir[MAX_PATH]; static int old_dir_set = 0; ZeroMemory( &ofn , sizeof( ofn)); ofn.lStructSize = sizeof ( ofn ); ofn.hwndOwner = NULL ; ofn.lpstrFile = szFile ; ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = sizeof( szFile ); ofn.lpstrFilter = "*.*\0*.*\0main?.lua;*.zip;*.idf\0main.lua;main3.lua;*.zip;*.idf\0\0"; ofn.nFilterIndex = 2; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; if (!old_dir_set) ofn.lpstrInitialDir = NULL; else ofn.lpstrInitialDir = szOldDir; ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_READONLY; if (!GetOpenFileName(&ofn)) return NULL; old_dir_set = 1; strcpy(szOldDir, ofn.lpstrFile); dirname(szOldDir); unix_path(ofn.lpstrFile); return ofn.lpstrFile; } #endif #if 0 int setdir(const char *path) { return chdir(path); } char *getdir(char *path, size_t size) { return getcwd(path, size); } char *dirpath(const char *path) { return (char*)path; } int is_absolute_path(const char *path) { if (!path || !path[0]) return 0; if (path[0] == '/' || path[0] == '\\') return 1; if (!path[1]) return 0; return (path[1] == ':'); } #endif instead-3.5.2+dfsg/src/winrt.c000066400000000000000000000136371467622671600162200ustar00rootroot00000000000000/* * Copyright 2009-2017 Peter Kosyh , Anton Kolosov * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #include #include #include #include #include #include "externals.h" #include "internals.h" #include #include "dirent.h" extern char *curgame; extern char *curgame_dir; static char local_games_path[PATH_MAX]; static char local_themes_path[PATH_MAX]; static char local_stead_path[PATH_MAX]; static char save_path[PATH_MAX]; static char cfg_path[PATH_MAX]; char *game_locale(void) { char buff[64]; char res[64]; buff[0] = 0; /* Antokolos: Note LOCALE_NAME_USER_DEFAULT instead of LOCALE_USER_DEFAULT */ if (!GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO639LANGNAME, buff, sizeof(buff) - 1)) return NULL; wcstombs(res, buff, sizeof(res)); return strdup(res); } #if 0 static char *game_codepage = NULL; #ifdef _HAVE_ICONV static char *game_cp(void) { char cpbuff[64]; char buff[64]; buff[0] = 0; if (!GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, buff,sizeof(buff) - 1)) return NULL; snprintf(cpbuff, sizeof(cpbuff), "WINDOWS-%s", buff); return strdup(cpbuff); } char *mbs2utf8(const char *s) { iconv_t han; char *str; if (!game_codepage) game_codepage = game_cp(); if (!s) return NULL; if (!game_codepage) goto out0; han = iconv_open("UTF-8", game_codepage); if (han == (iconv_t)-1) goto out0; if (!(str = decode(han, s))) goto out1; iconv_close(han); return str; out1: iconv_close(han); out0: return strdup(s); } #else char *mbs2utf8(const char *s) { return strdup(s); } #endif #endif extern void unix_path(char *); char *sdl_path(char *p) { #if 0 char *r = mbs2utf8(p); if (p) free(p); unix_path(r); return r; #else unix_path(p); return p; #endif } char *appdir( void ); /* must be implemented as extern "C" in winrt cpp code */ extern void getAppTempDir(char *lpPathBuffer); char *game_tmp_path(void) { static char lpTempPathBuffer[MAX_PATH]; getAppTempDir(lpTempPathBuffer); strcat((char*)lpTempPathBuffer, "/instead-games"); if (mkdir((char*)lpTempPathBuffer) && access((char*)lpTempPathBuffer, W_OK)) return NULL; unix_path((char*)lpTempPathBuffer); return (char*)lpTempPathBuffer; } char *game_local_games_path(int cr) { char *app = appdir(); if (!app) return NULL; snprintf(local_games_path, sizeof(local_games_path) - 1 , "%s/", app); if (cr) { if (mkdir(local_games_path) && access(local_games_path, W_OK)) return NULL; } strcat(local_games_path,"/games"); if (cr) { if (mkdir(local_games_path) && access(local_games_path, W_OK)) return NULL; } return local_games_path; } char *game_local_themes_path(void) { snprintf(local_themes_path, sizeof(local_themes_path) - 1 , "%s/themes", appdir()); return local_themes_path; } char *instead_local_stead_path(void) { snprintf(local_stead_path, sizeof(local_stead_path) - 1 , "%s/stead", appdir()); return local_stead_path; } #if 0 char *home_dir( void ) { static char homedir[PATH_MAX]=""; SHGetFolderPath( NULL, CSIDL_FLAG_CREATE | CSIDL_PROFILE, NULL, 0, (LPTSTR)homedir ); unix_path(homedir); return homedir; } #endif char *appdir( void ) { static char dir[PATH_MAX]=""; if (appdata_sw) strcpy(dir, appdata_sw); else { strcpy(dir, game_cwd); strcat(dir, "/appdata"); } if (!access(dir, W_OK)) return dir; return NULL; } char *game_cfg_path( void ) { char *p = appdir(); if (!p) return NULL; snprintf(cfg_path, sizeof(cfg_path) - 1 , "%src", p); /* appdir/insteadrc ;) */ if (!access(cfg_path, R_OK)) return cfg_path; /* no at home? Try in dir */ snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s", p); if (mkdir(cfg_path) && access(cfg_path, W_OK)) { snprintf(cfg_path, sizeof(cfg_path) - 1 , "%src", p); /* appdir/insteadrc ;) */ return cfg_path; } snprintf(cfg_path, sizeof(cfg_path) - 1 , "%s/insteadrc", p); return cfg_path; } char *game_save_path( int cr, int nr ) { char dir[PATH_MAX]; char *p = appdir(); if (!curgame_dir) return NULL; if (!access("saves", R_OK)) { if (nr) snprintf(save_path, sizeof(save_path) - 1, "saves/save%d", nr); else snprintf(save_path, sizeof(save_path) - 1, "saves/autosave"); return save_path; } if (!p) return NULL; strcpy(dir, p); if (cr && mkdir(dir) && access(dir, W_OK)) return NULL; snprintf(save_path, sizeof(save_path) - 1 , "%s/saves", dir); if (cr && mkdir(save_path) && access(save_path, W_OK)) return NULL; snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s", dir, curgame_dir); if (cr && mkdir(save_path) && access(save_path, W_OK)) return NULL; if (nr) snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/save%d", dir, curgame_dir, nr); else snprintf(save_path, sizeof(save_path) - 1, "%s/saves/%s/autosave", dir, curgame_dir); return save_path; } int debug_init(void) { return 0; } void debug_done() { } instead-3.5.2+dfsg/stead/000077500000000000000000000000001467622671600152105ustar00rootroot00000000000000instead-3.5.2+dfsg/stead/CMakeLists.txt000066400000000000000000000000621467622671600177460ustar00rootroot00000000000000ADD_SUBDIRECTORY(stead2) ADD_SUBDIRECTORY(stead3) instead-3.5.2+dfsg/stead/Makefile000066400000000000000000000007431467622671600166540ustar00rootroot00000000000000include ../Rules.make include ../config.make clean: all: stead2/stead.lua stead3/stead.lua install: $(INSTALLD) $(DESTDIR)$(STEADPATH) for api in stead2 stead3; do \ $(INSTALLD) $(DESTDIR)$(STEADPATH)/$$api; \ $(INSTALLD) $(DESTDIR)$(STEADPATH)/$$api/ext; \ for f in $$api/*.lua; do \ $(INSTALL) $$f $(DESTDIR)$(STEADPATH)/$$f || exit 1; \ done; \ for f in $$api/ext/*.lua; do \ $(INSTALL) $$f $(DESTDIR)$(STEADPATH)/$$f || exit 1; \ done; \ done uninstall: instead-3.5.2+dfsg/stead/stead2/000077500000000000000000000000001467622671600163725ustar00rootroot00000000000000instead-3.5.2+dfsg/stead/stead2/CMakeLists.txt000066400000000000000000000006311467622671600211320ustar00rootroot00000000000000FILE(GLOB STEAD_FILES "*.lua") FILE(GLOB STEAD_EXT_FILES "ext/*.lua") IF(SYSTEMWIDE) INSTALL(FILES ${STEAD_FILES} DESTINATION ${STEADDIR}/stead2) INSTALL(FILES ${STEAD_EXT_FILES} DESTINATION ${STEADDIR}/stead2/ext) ELSEIF(STANDALONE) INSTALL(FILES ${STEAD_FILES} DESTINATION ${STANDALONEDIR}/stead/stead2) INSTALL(FILES ${STEAD_EXT_FILES} DESTINATION ${STANDALONEDIR}/stead/stead2/ext) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/stead/stead2/click.lua000066400000000000000000000041731467622671600201670ustar00rootroot00000000000000require "theme" click = { nam = 'click'; object_type = true; system_type = true; bg = false; press = false; button = false; save = function(self, name, h, need) local s = stead.tostring(self.bg) h:write(stead.string.format("click[%q] = %s;\n", 'bg', s)) s = stead.tostring(self.press) h:write(stead.string.format("click[%q] = %s;\n", 'press', s)) s = stead.tostring(self.button) h:write(stead.string.format("click[%q] = %s;\n", 'button', s)) end; } stead.module_init(function() input.click = stead.hook(input.click, function(f, s, press, mb, x, y, px, py, ...) local cmd = 'click ' local act = false if ( press or click.press ) and ( mb == 1 or click.button ) then cmd = cmd..stead.tostr(press)..','..stead.tostr(mb); if click.bg or theme.get 'scr.gfx.mode' == 'direct' then act = true cmd = cmd .. ',' .. x .. ','.. y end if px then act = true cmd = cmd .. ',' .. px .. ',' .. py end if act then return cmd end end return f(s, press, mb, x, y, px, py, ...) end) end) game.action = stead.hook(game.action, function(f, s, cmd, press, mb, x, y, px, py, ...) if cmd == 'click' then local r,v local x2 = px local y2 = py if stead.tonum(mb) then mb = stead.tonum(mb) end if stead.tonum(px) then x2 = stead.tonum(px) end if stead.tonum(py) then y2 = stead.tonum(py) end if stead.here().click then s = stead.here() end if press == 'true' then press = true else press = false end if s.click then if click.press then if click.button then r,v = stead.call(s, 'click', press, mb, stead.tonum(x), stead.tonum(y), x2, y2, ...); else r,v = stead.call(s, 'click', press, stead.tonum(x), stead.tonum(y), x2, y2, ...); end else if click.button then r,v = stead.call(s, 'click', mb, stead.tonum(x), stead.tonum(y), x2, y2, ...); else r,v = stead.call(s, 'click', stead.tonum(x), stead.tonum(y), x2, y2, ...); end end end if r == nil and v == nil and not stead.api_atleast(1, 3, 5) then return nil, true end return r,v end return f(s, cmd, press, mb, x, y, px, py, ...) end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/counters.lua000066400000000000000000000032131467622671600207360ustar00rootroot00000000000000if not stead.api_atleast(1, 6, 3) then error ("Counters module can not run with api version < 1.6.3", 3) end local function inc_nr(v, n) local name = '__'..n..'_nr' if not v[name] then v[name] = 0 end v[name] = v[name] + 1 end local function read_nr(v, n, set) local name = '__'..n..'_nr' v = stead.ref(v) if stead.type(v) ~= 'table' then return v end if not v[name] then if stead.type(set) == 'number' then v[name] = set end return 0 end n = v[name] if stead.type(set) == 'number' then v[name] = set end return n end game.onact = stead.hook(game.onact, function(f, v, w, ...) inc_nr(v, 'act'); inc_nr(w, 'act'); return f(v, w, ...) end) game.onuse = stead.hook(game.onuse, function(f, v, w, ...) inc_nr(v, 'use'); inc_nr(w, 'use'); return f(v, w, ...) end) game.oninv = stead.hook(game.oninv, function(f, v, w, ...) inc_nr(v, 'inv'); inc_nr(w, 'inv'); return f(v, w, ...) end) game.onwalk = stead.hook(game.onwalk, function(f, v, w, ...) inc_nr(v, 'walk'); inc_nr(w, 'walk'); return f(v, w, ...) end) function act_count(s, v) if not s and not v then s = game v = nil elseif stead.tonum(s) then v = s s = game end return read_nr(s, 'act', v) end function inv_count(s, v) if not s and not v then s = game v = nil elseif stead.tonum(s) then v = s s = game end return read_nr(s, 'inv', v) end function use_count(s, v) if not s and not v then s = game v = nil elseif stead.tonum(s) then v = s s = game end return read_nr(s, 'use', v) end function walk_count(s, v) if not s and not v then s = game v = nil elseif stead.tonum(s) then v = s s = game end return read_nr(s, 'walk', v) end instead-3.5.2+dfsg/stead/stead2/dash.lua000066400000000000000000000000441467622671600200120ustar00rootroot00000000000000require "format" format.dash = true instead-3.5.2+dfsg/stead/stead2/dbg.lua000066400000000000000000000227001467622671600176320ustar00rootroot00000000000000-- add this: reuire "dbg" -- in your project -- for debug tools require "input" local function _xref_escape(n) local delim = ':' if stead.api_atleast(1, 2, 2) then delim = stead.delim; end if xact then n = n:gsub("\\?[\\"..delim.."]", { [delim] = "\\"..delim } ) end return n end local function ordered_n(t) local ordered = {}; local max = 0 for i, v in stead.pairs(t) do local o = { k = i; v = v }; stead.table.insert(ordered, o); max = max + 1; end stead.table.sort(ordered, function(a, b) if isObject(a.v) and not isObject(b.v) then return true end if not isObject(a.v) and isObject(b.v) then return false end if isObject(a.v) and isObject(b.v) then local n = stead.call(a.v, 'nam'); local m = stead.call(b.v, 'nam'); if stead.type(n) ~= 'string' and stead.type(m) ~= 'string' then return false end if stead.type(n) ~= 'string' then return true end if stead.type(m) ~= 'string' then return false end if n == m then local o1, o2 o1 = stead.deref(a.v) o2 = stead.deref(b.v) if stead.type(o1) == 'string' and stead.type(o2) == 'string' then return o1 < o2 end end return n < m; end return false end) ordered.i = 1; ordered.max = max; return ordered; end local function snext(t, k) local v if not k then k = ordered_n(t); end if k.i > k.max then return nil end v = k[k.i] k.i = k.i + 1 return k, v.v, v.k; end local function spairs(s, var) return snext, s, nil; end function dbg_disp_obj() local v = obj { nam = 'disp', act = true, dsc = function(s) local r = s._txt s._txt = nil; return r end; save = function(self, name, h, need) if need then h:write(stead.string.format("%s = dbg_disp_obj();\n", name)); end stead.savemembers(h, self, name, false); end } return v; end dbg_dump_obj = function(w) w = stead.ref(w) if stead.type(w) ~= 'table' then seen('disp')._txt = '^^No such object.'; return true end local n local rc = '' for i, o in stead.pairs(w) do local t = stead.tostring(o); if t == i then t = stead.tostr(o); end if t then if rc ~='' then rc = rc..'^' end local n = ''; if isObject(o) then n = stead.call(o, 'nam'); if stead.type(n) ~= 'string' then n = '' else n = ' : '..n; end end rc = stead.cat(rc, stead.par(' ', stead.tostr(i)..' : '..t..n)); end end seen('disp')._txt = stead.cat('^^', rc) return true; end dbg_dump_globals = function() local rc='' if stead.type(variables) ~= 'table' then return end for i, o in stead.ipairs(variables) do local v = stead.rawget(_G, o); local t = stead.tostring(v); if t then if rc ~='' then rc = rc..'^' end rc = stead.cat(rc, stead.par(' ', stead.tostr(o)..' : '..t)); end end seen('disp')._txt = stead.cat('^^', rc) return true; end dbg_here = function() return debug_tool._here end dbg_list_objects = function() local dis = function(o) if isDisabled(o) then return ", disabled" end return '' end local rc = stead.par(' ', 'Room:'..stead.tostr(stead.deref(dbg_here())), 'Nam:'..stead.tostr(stead.call(dbg_here(),'nam'))); for i, o in stead.opairs(objs(dbg_here())) do rc = rc..'^'; o = stead.ref(o) rc = stead.cat(rc, stead.par(' ', 'Id: '..stead.tostr(o.id)..', '.. stead.tostr(stead.deref(o))..': '..stead.tostr(stead.call(o, 'nam'))..dis(o))); end -- seen('disp')._txt = rc return rc end dbg_list_inv = function() local rc = '' local dis = function(o) if isDisabled(o) then return ", disabled" end return '' end local tak = function(o) if taken(o) then return ", taken" end return '' end for i, o in stead.opairs(inv()) do if rc ~='' then rc = rc..'^' end o = stead.ref(o) rc = stead.cat(rc, stead.par(' ', 'Id: '..stead.tostr(o.id)..', '.. stead.tostr(stead.deref(o))..': '..stead.tostr(stead.call(o, 'nam'))..dis(o)..tak(o))); end if rc == '' then return end -- seen('disp')._txt = rc return rc end dbg_execute_cmd = room { nam = "Execute Lua code", debug = true, pic = true, system_type = true, forcedsc = true, dsc = "Enter Lua code here to exec.", inp_enter = function(s) if stead.type(s.obj[1]._txt) == 'string' then local f = stead.eval(s.obj[1]._txt); if f then seen('disp')._txt = stead.cat('^^', f()); return true end seen('disp')._txt = "^^Error in exec."; return true end return stead.back(); end, obj = { inp('inp', '{Enter cmd}: ', 'return "Hello World!"'), obj { nam = 'Back', dsc = '^{Back}', act = code [[ stead.back() ]] }, dbg_disp_obj(), }, exit = function(s) s.obj[1]:state(false) end; } dbg_dump_object = room { nam = "Dump object", debug = true, pic = true, system_type = true, forcedsc = true, dsc = "Enter object name here to dump.", inp_enter = function(s) local w = s.obj[1]._txt if stead.type(w) == 'string' then if not stead.ref(w) then w = objs(dbg_here()):srch(w); end return dbg_dump_obj(w); end return stead.back(); end, obj = { inp('inp', '{Enter object}: ', 'main'), obj{nam = 'Here', dsc = '^{Dump here}', act = code[[ return dbg_dump_obj(dbg_here())]]}, obj{nam = 'Player',dsc = '^{Dump player}', act = code[[ return dbg_dump_obj(stead.me())]]}, obj{nam = 'Lifes', dsc = '^{Dump lifes}', act = code[[ return dbg_dump_obj(debug_tool.lifes)]]}, obj{nam = 'Ways', dsc = '^{Dump ways}', act = code[[ return dbg_dump_obj(ways(dbg_here()))]]}, obj{nam = 'Globals', dsc = '^{Dump globals}', act = code [[return dbg_dump_globals()]] }, obj{nam = 'Back', dsc = '^{Back}', act = code [[ return stead.back() ]] }, dbg_disp_obj() }, exit = function(s) s.obj[1]:state(false) end; } dbg_choose_location = dlg { debug = true, pic = true, system_type = true, forcedsc = true, nam = 'Go to', dsc = 'Select location.', gen = function(s) objs(s):zap(); for k, v, kk in spairs(_G) do if isRoom(v) and not v.debug then local n = stead.tostr(stead.call(v, 'nam')); local o = kk; if stead.type(o) == 'string' then n = n..' : '..o; n = _xref_escape(n); put(phr(n, true, [[timer:set(debug_tool._timer); game.lifes:cat(debug_tool.lifes); return stead.walk(]]..o..[[)]]), s); end end end put (phr('Back',true, 'return stead.back()'), s) end } dbg_choose_object = dlg { debug = true, pic = true, system_type = true, forcedsc = true, nam = 'Get object', dsc = 'Select object to get.', gen = function(s) objs(s):zap(); for k, v, kk in spairs(_G) do if isObject(v) and not isPhrase(v) and not isRoom(v) and not isPlayer(v) and not v.debug and not have(v) and not isStatus(v) then local n = stead.tostr(stead.call(v, 'nam')); local o = kk; if stead.type(o) == 'string' then n = n..' : '..o; n = _xref_escape(n); put(phr(n, true, o..':enable(); return take('..o..')'), s); end end end put (phr('Back',true, 'return stead.back()'), s) end } dbg_drop_object = dlg { debug = true, pic = true, forcedsc = true, system_type = true, nam = 'Drop object', dsc = 'Select object to drop.', gen = function(s) objs(s):zap(); for k, v in stead.ipairs(inv()) do v = stead.ref(v); if not v.debug then local n = stead.tostr(stead.call(v, 'nam')); local o = stead.deref(v); if stead.type(o) == 'string' then n = n..' : '..o; n = _xref_escape(n); put (phr(n, true, o..':enable(); drop('..o..','..stead.deref(dbg_here())..')'), s) end end end put (phr('Back', true, 'return stead.back()'), s) end } function dbg_exit() local r if not stead.api_atleast(1, 2, 0) then r = stead.call(dbg_here(), 'dsc'); end game.lifes:cat(debug_tool.lifes); timer:set(debug_tool._timer); return stead.par ('^^', stead.back(), r); end debug_dlg = dlg { debug = true, pic = true, system_type = true, forcedsc = true, nam = 'Debug Tool', dsc = 'Select tool.', obj = { phr('Go to location...', true, [[pon(); dbg_choose_location:gen(); return stead.walk('dbg_choose_location')]]), phr('Get object...', true, [[pon(); dbg_choose_object:gen(); return stead.walk('dbg_choose_object')]]), phr('Put object...', true, [[pon(); dbg_drop_object:gen(); return stead.walk('dbg_drop_object')]]), phr('Current scene...', true, [[pon(); return dbg_list_objects();]]), phr('Inventory...', true, [[pon(); return dbg_list_inv();]]), phr('Dump object...', true, [[pon(); return stead.walk(dbg_dump_object);]]), phr('Exec Lua string...', true, [[pon(); return stead.walk('dbg_execute_cmd')]]), phr('Exit',true , [[pon(); return dbg_exit()]]), }, }; debug_tool = menu { debug = true, system_type = true, forcedsc = true, nam = txtb('debug'), lifes = list {}, inv = function(s) if stead.here().debug then return nil, true --nothing todo end debug_dlg.__from__ = stead.here(); s._timer = timer:get(); timer:stop(); s.lifes:zap(); s.lifes:cat(game.lifes); game.lifes:zap(); s._here = stead.here(); stead.me().where = 'debug_dlg'; -- force to go return stead.walk(self.where); end, }; game.action = stead.hook(game.action, function (f, s, cmd, ...) if cmd == 'use_debug' then return debug_tool:inv() elseif cmd == 'exit_debug' then stead.me().where = 'debug_dlg'; dbg_execute_cmd.obj[1]:state(false) dbg_dump_object.obj[1]:state(false) return dbg_exit() end return f(s, cmd, ...) end) stead.module_init(function() input.key = stead.hook(input.key, function(f, s, down, key, ...) if down and key == 'f7' then if stead.here().debug then return 'exit_debug' else return 'use_debug' end end return f(s, down, key, ...) end) putf('debug_tool', stead.me()); end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/dlg.lua000066400000000000000000000260121467622671600176440ustar00rootroot00000000000000-- stead.phrase_prefix = '--' local function isValid(p) return isPhrase(p) and p.dsc and (p.ans or p.code) end local function isDelimiter(p) return isPhrase(p) and not isDisabled(p) and (p.dsc == nil and p.ans == nil and p.code == nil) end local tagpnext = function(a, k) if not k then if isPhrase(a.tag) then return 1, a.tag end if stead.type(a.tag) == 'number' then local r = a.s:phrase(a.tag) if r then return 1, r end return end k = {} for r, v in stead.opairs(a.s.obj) do v = stead.ref(v) if isPhrase(v) and v.tag == a.tag then stead.table.insert(k, v) end end k.i = 0 k.n = stead.table.maxn(k) end if k == 1 or k.i >= k.n then return nil end k.i = k.i + 1 return k, k[k.i] end local function phrases(s, tag) local a = { s = s, tag = tag } return tagpnext, a, nil; end stead.phrase_seen = function(s, enb, ...) local ph, k local a = {...} if stead.table.maxn(a) == 0 then stead.table.insert(a, stead.cctx().self); end for i = 1,stead.table.maxn(a) do local r for k, ph in phrases(s, a[i]) do r = isPhrase(ph) and not isRemoved(ph) and not ph:disabled(); if r then break end end if enb then r = not r end if r then return false end end return true end local function ponoff(s, on, ...) local ph, k local a = {...} if stead.table.maxn(a) == 0 then stead.table.insert(a, stead.cctx().self) end for i = 1,stead.table.maxn(a) do for k, ph in phrases(s, a[i]) do if isPhrase(ph) and not isRemoved(ph) then if on then ph:enable(); else ph:disable(); end end end end end stead.dialog_prem = function(s, ...) local a = {...} if stead.table.maxn(a) == 0 then stead.table.insert(a, stead.cctx().self); end for i = 1, stead.table.maxn(a) do for k, ph in phrases(s, a[i]) do if isPhrase(ph) then ph:remove(); end end end end stead.dialog_pon = function(self,...) return ponoff(self, true, ...); end stead.dialog_poff = function(self,...) return ponoff(self, false, ...); end local function phr_get(self) local n = #self.__phr_stack; if n == 0 then return 1 end return self.__phr_stack[n]; end local function phr_pop(self) local n = #self.__phr_stack; if n <= 1 then return false end stead.table.remove(stead.here().__phr_stack, n) return true end local function call_empty(self) local ph = self:phrase(phr_get(self)) local r if not isPhrase(ph) or isDisabled(ph) or not ph.empty then self:pret() return end r = stead.call(ph, "empty") if stead.type(r) == 'string' then stead.p(r) end return r end local function call_enter(ph) local r, n if not isPhrase(ph) or isDisabled(ph) then return end if isValid(ph) then return end r = stead.call(ph, 'dsc') if stead.type(r) == 'string' then stead.p(r) end end local function dialog_reset(self) for i, ph in stead.pairs(self.obj) do if isPhrase(ph) then ph.nam = '' end end end stead.dialog_look = function(self) local n, v n = 1 local start = phr_get(self) dialog_reset(self) for i, ph, ii in stead.opairs(self.obj) do if ii >= start then if ii ~= start and isDelimiter(ph) then break end if isPhrase(ph) and not isDisabled(ph) and isValid(ph) then ph.nam = stead.tostr(n) if stead.type(stead.phrase_prefix) == 'string' then v = stead.par('^', v, stead.cat(stead.phrase_prefix, ph:look())); else v = stead.par('^', v, txtnm(n, ph:look())) end n = n + 1 end end end return v; end stead.dialog_rescan = function(self, naming, from) local k, start k = 0 if stead.type(from) == 'number' then start = from elseif stead.type(from) == 'string' then ph, start = self:phrase(from) else start = phr_get(self) end for i, ph, ii in stead.opairs(self.obj) do if ii >= start then if ii ~= start and isDelimiter(ph) then break end if isPhrase(ph) and not isDisabled(ph) and isValid(ph) then k = k + 1; if naming then ph.nam = stead.tostr(k) end end end end if k == 0 then return false end return k end stead.dialog_enter = function(self) if self:empty(self) then return nil, false end return nil, true end stead.dialog_current = function(self, w, ...) local r = phr_get(self) if w then local ph, i = self:phrase(w) if ph then self.__phr_stack = { i } end end return r end stead.dialog_curtag = function(self, w, ...) local p = self:phrase(phr_get(self)) if w then self:current(w) end if not isPhrase(p) then return end return p.tag end stead.dialog_empty = function(self, from) return (stead.dialog_rescan(self, false, from) == false) end stead.dialog_visible = function(self, from) local r = stead.dialog_rescan(self, false, from); if not r then r = 0 end return r end stead.dialog_pjump = function(self, w) local ph, i = self:phrase(w) if not ph then return end local n = #self.__phr_stack; if n == 0 then stead.table.insert(self.__phr_stack, i); else self.__phr_stack[n] = i end call_enter(ph) stead.cctx().action = true return end function pjump(w) if not isDialog(stead.here()) then return false end return stead.here():pjump(w) end stead.dialog_pstart = function(self, w) if not w then w = 1 end local ph, i = self:phrase(w) if not ph then return end self.__phr_stack = { i } call_enter(ph) stead.cctx().action = true return end function pstart(w) if not isDialog(stead.here()) then return end stead.here():pstart(w) end stead.dialog_psub = function(self, w) local ph, i = self:phrase(w) if not ph then return end stead.table.insert(self.__phr_stack, i); call_enter(ph) stead.cctx().action = true return end function psub(w) if not isDialog(stead.here()) then return false end return stead.here():psub(w) end stead.dialog_pret = function(self) if not phr_pop(self) then return end stead.cctx().action = true if not self:empty() then return end call_empty(self) return end function pret() if not isDialog(stead.here()) then return end return stead.here():pret() end function phr(ask, answ, act) local i = 1 local dis = false if stead.type(ask) ~= 'table' then -- old style local p = phrase ( { dsc = ask, ans = answ, code = act }); return p end local v = ask if stead.type(v[1]) == 'number' then -- just skip number i = i + 1 end if stead.type(v[i]) == 'boolean' then dis = not v[i] i = i + 1 end if v.dsc == nil then v.dsc = v[i]; i = i + 1 end if v.ans == nil then v.ans = v[i]; i = i + 1 end if v.code == nil and (stead.type(v[i]) == 'function' or stead.type(v[i]) == 'string') then v.code = v[i]; end v = phrase(v) if dis then v = v:disable() end return v; end function _phr(ask, answ, act) -- compat only? local p = phr(ask, answ, act); p:disable() return p end stead.phr = phr stead.phrase_save = function(self, name, h, need) if need then local m = " = phrase {" local post = '}\n' if isDisabled(self) then post = "}:disable()\n" end m = stead.string.format("%s%s", name, m); if self.dsc then m = m..stead.string.format("dsc = %s, ", stead.tostring(self.dsc)); end if self.ans then m = m..stead.string.format("ans = %s, ", stead.tostring(self.ans)); end if self.code then m = m..stead.string.format("code = %s, ", stead.tostring(self.code)); end if self.tag then m = m..stead.string.format("tag = %s, ", stead.tostring(self.tag)); end if self.always then m = m..stead.string.format("always = %s, ", stead.tostring(self.always)); end if self.empty then m = m..stead.string.format("empty = %s, ", stead.tostring(self.empty)); end h:write(m..post); end stead.savemembers(h, self, name, false); end local function dialog_phr2obj(self) local n = 0 local aliases = {} if stead.type(self.phr) ~= 'table' then return end for k, v in ipairs(self.phr) do if stead.type(v) == 'table' then if stead.type(v[1]) == 'number' then n = v[1] else n = n + 1 end local p = stead.phr(v) if self.obj[n] then error ("Error in phr structure (numbering).", 4); end if v.alias then p.alias = v.alias stead.table.insert(aliases, n); end self.obj[n] = p else error ("Error in phr structure (wrong item).", 4); end end for k, v in ipairs(aliases) do local ph = self:phrase(self.obj[v].alias) if not ph then error ("Wrong alias in dlg.", 3); end self.obj[v] = ph end end stead.dialog_phrase = function(self, num) if not num then return end if isPhrase(num) then return num end if stead.type(num) ~= 'number' then for k, v, i in stead.opairs(self.obj) do v = stead.ref(v) if isPhrase(v) and v.tag == num then return v, i end end return nil end return stead.ref(self.obj[num]), num; end stead.phrase_action = function(self) local ph = self; local r, ret; local empty if isDisabled(ph) then return nil, false end -- here it is if not ph.always then ph:disable(); -- /* disable it!!! */ end local last = stead.call(ph, 'ans'); if stead.type(ph.code) == 'string' then local f = stead.eval(ph.code); if f ~= nil then ret = f(); else error ("Error while eval phrase action:"..ph.code); end elseif stead.type(ph.code) == 'function' then ret = ph.code(self); end if ret == nil then ret = stead.pget(); end if last == true or ret == true then r = true; end if isDialog(stead.here()) and stead.here():empty() then empty = call_empty(stead.here()); end local wh = stead.here(); while isDialog(wh) and wh:empty() and stead.from(wh) ~= wh do wh = stead.from(wh) end if wh ~= stead.here() then ret = stead.par(stead.scene_delim, ret, stead.back(wh)); end ret = stead.par(stead.space_delim, last, empty, ret); if ret == nil then return r -- hack? end return ret end function dlg(v) --constructor v.dialog_type = true; if v.ini == nil then v.ini = function(s) stead.dialog_rescan(s, true); end end if v.enter == nil then v.enter = stead.dialog_enter; end if v.look == nil then v.look = stead.dialog_look; end if v.scene == nil then v.scene = stead.dialog_scene; end if v.pon == nil then v.pon = stead.dialog_pon; end if v.poff == nil then v.poff = stead.dialog_poff; end if v.prem == nil then v.prem = stead.dialog_prem; end if v.pseen == nil then v.pseen = stead.dialog_pseen; end if v.punseen == nil then v.punseen = stead.dialog_punseen; end if v.empty == nil then v.empty = stead.dialog_empty; end if v.visible == nil then v.visible = stead.dialog_visible; end if v.current == nil then v.current = stead.dialog_current end if v.curtag == nil then v.curtag = stead.dialog_curtag end if v.pstart == nil then v.pstart = stead.dialog_pstart end if v.pjump == nil then v.pjump = stead.dialog_pjump end if v.pret == nil then v.pret = stead.dialog_pret end if v.psub == nil then v.psub = stead.dialog_psub end if v.phrase == nil then v.phrase = stead.dialog_phrase end if v.dsc == nil then v.dsc = function(s) if stead.player_moved() then stead.last_act(false) elseif stead.type(stead.act_text()) ~= 'string' and stead.last_act() then stead.p(stead.last_act()) end end end v = room(v); v.__phr_stack = { 1 } dialog_phr2obj(v); return v; end instead-3.5.2+dfsg/stead/stead2/events.lua000066400000000000000000000006451467622671600204060ustar00rootroot00000000000000game.action = stead.hook(game.action, function(f, s, cmd, ...) if cmd == 'user_event' then local r,v; r, v = stead.call(stead, 'event', ... ); return r,v end return f(s, cmd, ...); end) stead.module_init(function() input.event = stead.hook(input.event, function(f, s, ev, ...) if type(stead.event) == 'function' then return 'user_event,'..tostring(ev) end return f(s, ev, ...) end) end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/ext/000077500000000000000000000000001467622671600171725ustar00rootroot00000000000000instead-3.5.2+dfsg/stead/stead2/ext/gui.lua000066400000000000000000000203211467622671600204570ustar00rootroot00000000000000game.hinting = true; game.showlast = true; game.gui = { fading = 4; ways_delim = ' | '; inv_delim = '\n'; hinv_delim = ' | '; hideways = false; hideinv = false; hidetitle = false; } iface.input = function(self, event, ...) if stead.type(input) ~= 'table' then return end if event == 'kbd' then if stead.type(input.key) == 'function' then return input:key(...); -- pressed, event end elseif event == 'mouse' then if stead.type(input.click) == 'function' then return input:click(...); -- pressed, x, y, mb end elseif event == 'finger' then if stead.type(input.finger) == 'function' then return input:finger(...); -- pressed, x, y, finger end elseif event == 'event' then if stead.type(input.event) == 'function' then return input:event(...); end end return end stead.objects.input = function() return obj { -- input object system_type = true, nam = 'input', }; end; iface.xref = function(self, str, obj, ...) local o = stead.ref(obj); local cmd='' if not isObject(o) or isStatus(o) or (not o.id and not isXaction(o)) then return str; end if stead.ref(ways():srch(obj)) then cmd = 'go '; elseif isMenu(o) then cmd = 'act '; elseif isSceneUse(o) then cmd = 'use '; elseif isXaction(o) and not o.id then cmd = 'act '; end local a = '' local varg = {...} for i = 1, stead.table.maxn(varg) do a = a..','..varg[i] end if isXaction(o) and not o.id then return stead.cat('',str,''); end return stead.cat('',str,''); end; iface.anchor = function(self) return '' end iface.enum = function(self, n, str) if str == nil or n == nil then return nil; end; return n..self:nb(' - ')..str; end iface.title = function(self, str) return nil end; iface.img = function(self, str) if str == nil then return nil; end; return ""; end; iface.imgl = function(self, str) if str == nil then return nil; end; return ""; end; iface.imgr = function(self, str) if str == nil then return nil; end; return ""; end; iface.nb = function(self, str) if stead.type(str) ~= 'string' then return nil end return "","\\>"):gsub("%^","\\^")..">"; end; iface.under = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.em = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.st = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.right = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.left = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.center = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.just = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.tab = function(self, str, al) if stead.tonum(str) then str = stead.tostr(str) end if stead.type(str) ~= 'string' then return nil; end if al == 'right' then str = str .. ",right" elseif al == 'center' then str = str .. ",center" end return '' end; iface.y = function(self, str, al) if stead.tonum(str) then str = stead.tostr(str) end if stead.type(str) ~= 'string' then return nil; end if al == 'middle' then str = str .. ",middle" elseif al == 'top' then str = str .. ",top" end return '' end; iface.bold = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.top = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.bottom = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.middle = function(self, str) if str == nil then return nil; end; return stead.cat('',str,''); end; iface.inv = function(self, str) return str end; iface.ways = function(self, str) return str end; instead.get_inv = stead.cacheable('inv', function(horiz) local r = stead.call_value(game.gui, 'hideinv'); if r then return end local str = iface:cmd("inv"); if str then str = stead.string.gsub(str, '\n$',''); if not horiz then str = stead.string.gsub(str, '\\?['.. stead.delim ..']', { [stead.delim] = game.gui.inv_delim, ['\\'..stead.delim] = stead.delim }); else str = stead.string.gsub(str, '\\?['.. stead.delim ..']', { [stead.delim] = game.gui.hinv_delim, ['\\'..stead.delim] = stead.delim }); end end return str end) instead.get_ways = stead.cacheable('ways', function() local r = stead.call_value(game.gui, 'hideways'); if r then return end local str = iface:cmd("way"); if str and str ~= '' then str = stead.string.gsub(str, '\n$',''); str = stead.string.gsub(str, '\\?['..stead.delim ..']', { [stead.delim] = game.gui.ways_delim, [ '\\'..stead.delim ] = stead.delim }); return iface:center(str); end return str end) instead.get_title = stead.cacheable('title', function() local r = stead.call_value(game.gui, 'hidetitle'); if r then return end local s if stead.api_atleast(1, 2, 0) then s = stead.dispof(stead.here()); else s = stead.call(stead.here(), 'nam'); end if stead.type(s) == 'string' and s ~= '' then stead.state = false s = ""..stead.fmt(s)..""; s = stead.string.gsub(s, '\\'..stead.delim, stead.delim); end return s end) instead.finish_music = function() if instead.get_music_loop() == 0 then return false end local n = stead.get_music() stead.set_music(n, -1); return true end instead.isEnableSave = isEnableSave; instead.isEnableAutosave = isEnableAutosave; -- here is gui staff only function stat(v) v.status_type = true return obj(v); end function isStatus(v) if stead.type(v) ~= 'table' then return false end if v.status_type then return true end return false end stead.menu_save = function(self, name, h, need) local dsc; if need then print ("Warning: menu "..name.." can not be saved!"); return end stead.savemembers(h, self, name, need); end MENU_TAG_ID = 1000000 function menu(v) v.menu_type = true if v.inv == nil then v.inv = function(s) local r,v r,v = stead.call(s, 'menu'); if v == nil then v = true end if r == nil then stead.obj_tag(stead.me(), MENU_TAG_ID); -- retag menu field end return r, v end end if v.act == nil then v.act = function(s) local r,v r,v = stead.call(s, 'menu'); if v == nil then v = true end if r == nil then stead.obj_tag(stead.me(), MENU_TAG_ID); -- retag menu field end return r, v end end if v.save == nil then v.save = stead.menu_save; end return obj(v); end function isMenu(v) if stead.type(v) ~= 'table' then return false end if v.menu_type then return true end return false end stead.fmt = function(...) local res local a = {...} for i = 1, stead.table.maxn(a) do if stead.type(a[i]) == 'string' then local s = stead.string.gsub(a[i],'\t', stead.space_delim):gsub('[\n]+', stead.space_delim); s = stead.string.gsub(s, '\\?[\\^]', { ['^'] = '\n', ['\\^'] = '^', ['\\\\'] = '\\' }); res = stead.par('', res, s); end end return res end game.fading = function(s) local rc = false local p = instead.get_picture(); if stead.cmd == 'load' then game.lastpic = p; return true end if not stead.state then --only for states!!! return false end if game._time == 1 then -- first cmd game.lastpic = p; return true end if stead.player_moved() or game.lastpic ~= p then rc = true end game.lastpic = p return rc end game.gui.is_fading = function() --to check fading from sdl gui local r,g,v local h = stead.here() if not isRoom(h) then return false end r,v = stead.call_value(h, 'fading'); if r then if stead.tonum(r) and v == nil then return true, stead.tonum(r) end return r, v end g,v = stead.call_value(game, 'fading'); if stead.tonum(g) and v == nil then return true, stead.tonum(g) end return g, v end instead.get_fading = function() local r, v r, v = stead.call_value(game.gui, 'is_fading') if v == nil and r then v = game.gui.fading end return r,v end -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/ext/paths.lua000066400000000000000000000005161467622671600210160ustar00rootroot00000000000000-- nothing todo in stead2 ;) local instead_gamepath = instead_gamepath io.open = stead.hook(io.open, function(f, path, acc, ...) if stead.type(path) == 'string' and path:sub(1, 1) ~= '/' and not (path:sub(2, 2) == ':' and path:find("^[A-Z]", 1) == 1) then path = instead_gamepath()..'/'..path end return f(path, acc, ...) end) instead-3.5.2+dfsg/stead/stead2/ext/sound.lua000066400000000000000000000067451467622671600210410ustar00rootroot00000000000000stead.get_music = function() return game._music, game._music_loop; end stead.get_music_loop = function() return game._music_loop; end stead.save_music = function(s) if s == nil then s = self end s.__old_music__ = stead.get_music(); s.__old_loop__ = stead.get_music_loop(); end stead.restore_music = function(s) if s == nil then s = self end stead.set_music(s.__old_music__, s.__old_loop__); end stead.set_music = function(s, count) game._music = s; if not stead.tonum(count) then game._music_loop = 0; else game._music_loop = stead.tonum(count); end end stead.set_music_fading = function(o, i) if o and o == 0 then o = -1 end if i and i == 0 then i = -1 end game._music_fadeout = o if not i then game._music_fadein = o else game._music_fadein = i end end stead.get_music_fading = function() return game._music_fadeout, game._music_fadein end stead.stop_music = function() stead.set_music(nil, -1); end stead.is_music = function() return game._music ~= nil and game._music_loop ~= -1 end if instead_sound == nil then function instead_sound() return false -- sdl-instead export own function end end stead.is_sound = instead_sound stead.get_sound = function() return game._sound, game._sound_channel, game._sound_loop; end stead.get_sound_chan = function() return game._sound_channel end stead.get_sound_loop = function() return game._sound_loop end stead.stop_sound = function(chan, fo) if not stead.tonum(chan) then if stead.tonum(fo) then stead.set_sound('@-1,'..stead.tostr(fo)); else stead.set_sound('@-1'); end return end if stead.tonum(fo) then stead.add_sound('@'..stead.tostr(chan)..','..stead.tostr(fo)); else stead.add_sound('@'..stead.tostr(chan)); end end stead.add_sound = function(s, chan, loop) if stead.type(s) ~= 'string' then return end if stead.type(game._sound) == 'string' then if stead.tonum(chan) then s = s..'@'..stead.tostr(chan); end if stead.tonum(loop) then s = s..','..stead.tostr(loop) end stead.set_sound(game._sound..';'..s, stead.get_sound_chan(), stead.get_sound_loop()); else stead.set_sound(s, chan, loop); end end stead.set_sound = function(s, chan, loop) game._sound = s; if not stead.tonum(loop) then game._sound_loop = 1; else game._sound_loop = stead.tonum(loop); end if not stead.tonum(chan) then game._sound_channel = -1; else game._sound_channel = stead.tonum(chan); end end stead.module_done(function(s) stead.stop_music(); stead.stop_sound(); end) stead.module_cmd(function(s) stead.set_sound(); -- empty sound end) -- those are sill in global space add_sound = stead.add_sound set_sound = stead.set_sound stop_sound = stead.stop_sound get_sound = stead.get_sound get_sound_loop = stead.get_sound_loop get_sound_chan = stead.get_sound_chan get_music = stead.get_music get_music_fading = stead.get_music_fading get_music_loop = stead.get_music_loop set_music = stead.set_music set_music_fading = stead.set_music_fading stop_music = stead.stop_music save_music = stead.save_music restore_music = stead.restore_music is_music = stead.is_music local function compat_api() if not stead.api_atleast(1, 7, 1) then is_sound = instead_sound sound_load = instead_sound_load sound_free = instead_sound_free sounds_free = instead_sounds_free sound_channel = instead_sound_channel sound_volume = instead_sound_volume sound_panning = instead_sound_panning end end stead.module_start(function(load) if compat_api and not load then compat_api() compat_api = nil end end) instead-3.5.2+dfsg/stead/stead2/ext/sprites.lua000066400000000000000000000011521467622671600213650ustar00rootroot00000000000000stead.ticks = instead_ticks stead.mouse_pos = instead_mouse_pos stead.mouse_show = instead_mouse_show stead.finger_pos = instead_finger_pos stead.mouse_filter = instead_mouse_filter stead.busy = instead_busy mouse_pos = stead.mouse_pos mouse_filter = stead.mouse_filter get_ticks = stead.ticks local function compat_api() if not stead.api_atleast(1, 7, 1) then stead_busy = instead_busy theme_var = instead_theme_var theme_name = instead_theme_name get_themespath = instead_themespath end end stead.module_start(function(load) if compat_api and not load then compat_api() compat_api = nil end end) instead-3.5.2+dfsg/stead/stead2/ext/timer.lua000066400000000000000000000021731467622671600210200ustar00rootroot00000000000000stead.set_timer = instead_timer stead.timer = function() if stead.type(timer) == 'table' and stead.type(timer.callback) == 'function' then return timer:callback(); end return end stead.module_done(function(s) timer:stop() end) local function compat_api() if not stead.api_atleast(1, 7, 1) then set_timer = instead_timer end end stead.module_start(function(load) if compat_api and not load then compat_api() compat_api = nil end end) stead.module_init(function(s) timer = obj { -- timer calls stead.timer callback nam = 'timer', ini = function(s) if stead.tonum(s._timer) ~= nil and stead.type(stead.set_timer) == 'function' then stead.set_timer(s._timer); end end, get = function(s) if stead.tonum(s._timer) == nil then return 0 end return stead.tonum(s._timer); end, stop = function(s) return s:set(0); end, del = function(s) return s:set(0); end, set = function(s, v) s._timer = stead.tonum(v); if stead.type(stead.set_timer) ~= 'function' then return false end stead.set_timer(v) return true end, --[[ callback = function(s) end, ]] }; end) instead-3.5.2+dfsg/stead/stead2/finger.lua000066400000000000000000000040501467622671600203460ustar00rootroot00000000000000require "theme" finger = { nam = 'finger'; object_type = true; system_type = true; fingers_list = { }; add = function(s, press, fid, x, y, px, py) if press then local v = s:lookup(fid) if v then v.x, v.y, v.px, v.py = x, y, px, py else stead.table.insert(s.fingers_list, { id = fid, x = x, y = y, px = px, py = py }) end return end local v, k v, k = s:lookup(fid) if k then stead.table.remove(s.fingers_list, k) return end end; list = function(s) local new = {} for k, v in stead.ipairs(s.fingers_list) do local x, y, pressure x, y, pressure = stead.finger_pos(v.id) if x then v.x, v.y, v.pressure = x, y, pressure stead.table.insert(new, v) end end s.fingers_list = new return new end; get = function(s, fid) local v,k local x, y, pressure x, y, pressure = stead.finger_pos(fid) if not x then v, k = s:lookup(fid) if k then stead.table.remove(s.fingers_list, k) end return end return x, y, pressure end; lookup = function(s, fid) for k, v in stead.ipairs(s.fingers_list) do if v.id == fid then return v, k end end end; } stead.module_init(function() input.finger = function(s, press, fid, x, y, px, py, ...) finger:add(press, fid, x, y, px, py, ...) local cmd = 'finger ' cmd = cmd..stead.tostr(press)..','..stead.tostr(fid)..',' .. x .. ','.. y; if px then cmd = cmd .. ',' .. px .. ',' .. py end return cmd end end) game.action = stead.hook(game.action, function(f, s, cmd, press, fid, x, y, px, py, ...) if cmd == 'finger' then local r,v local x2 = px local y2 = py if stead.here().finger then s = stead.here() end if not s.finger then return end if stead.tonum(px) then x2 = stead.tonum(px) end if stead.tonum(py) then y2 = stead.tonum(py) end if press == 'true' then press = true else press = false end r,v = stead.call(s, 'finger', press, fid, stead.tonum(x), stead.tonum(y), x2, y2, ...); return r,v end return f(s, cmd, press, fid, x, y, px, py, ...) end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/format.lua000066400000000000000000000026411467622671600203700ustar00rootroot00000000000000format = { nam = 'format'; object_type = true; system_type = true; para = false; para_space = ' '; quotes = false; dash = false; filter = nil; nopara = '_'; save = function(self, name, h, need) for k, v in stead.pairs(self) do if k == 'para' or k == 'para_space' or k == 'quotes' or k == 'dash' or k == 'nopara' then local s = stead.tostring(v) h:write(stead.string.format("format[%q] = %s;\n", k, s)) end end end; } stead.fmt = stead.hook(stead.fmt, function(f, ...) local utf8 local r = f(...) if game.codepage == 'UTF-8' or game.codepage == 'utf-8' then utf8 = true end if stead.type(r) == 'string' and stead.state then if stead.type(format.filter) == 'function' and stead.state then r = format.filter(r); end if stead.call_bool(format, 'dash') and utf8 then r = r:gsub('([^-])%-%-([^-])', '%1—%2'); r = r:gsub('^%-%-([^-])', '—%1'); end if stead.call_bool(format, 'quotes') and utf8 then r = r:gsub('_"','«'):gsub('"_',"»"); r = r:gsub('"([^"]*)"','«%1»'); r = r:gsub(',,','„'):gsub("''",'”'); end if stead.call_bool(format, 'para') then r = r:gsub('\n([^\n])', '<¶>%1'):gsub('<¶>[ \t]*'..format.nopara,'\n'):gsub('<¶>[ \t]*', '\n'..txtnb(format.para_space)); r = r:gsub('^[ \t]*', '<¶>'):gsub('<¶>[ \t]*'..format.nopara,''):gsub('<¶>[ \t]*', txtnb(format.para_space)); end end return r; end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/hideinv.lua000066400000000000000000000010121467622671600205150ustar00rootroot00000000000000local attr = "hideinv" if stead.api_atleast(1, 6, 3) then game.gui.hideinv = function(s) if stead.call_bool(stead.here(), 'hideinv') then return true end end attr = "noinv" end room = stead.inherit(room, function(v) v.entered = stead.hook(v.entered, function(f, s, ...) if stead.call_bool(s, attr) then me():disable_all(); end return f(s, ...) end) v.left = stead.hook(v.left, function(f, s, ...) if stead.call_bool(s, attr) then me():enable_all(); end return f(s, ...) end) return v end) instead-3.5.2+dfsg/stead/stead2/hotkeys.lua000066400000000000000000000007211467622671600205630ustar00rootroot00000000000000require 'kbd' stead.module_init(function() hook_keys('1','2','3','4','5','6','7','8','9','0'); end) game.kbd = stead.hook(game.kbd, function(f, s, down, key, ...) if down and key >= '0' and key <= '9' then if isDialog(stead.here()) then if key == '0' then key = '10' end local p = stead.here():srch(key); if p and stead.nameof(p) == key then return stead.call(p, 'act'); end end return end return f(s, down, key, ...); end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/input.lua000066400000000000000000000137051467622671600202420ustar00rootroot00000000000000local kbden = { shifted = { ["1"] = "!", ["2"] = "@", ["3"] = "#", ["4"] = "$", ["5"] = "%", ["6"] = "^", ["7"] = "&", ["8"] = "*", ["9"] = "(", ["0"] = ")", ["-"] = "_", ["="] = "+", ["["] = "{", ["]"] = "}", ["\\"] = "|", [";"] = ":", ["'"] = "\"", [","] = "<", ["."] = ">", ["/"] = "?", } } local kbdru = { ["q"] = "й", ["w"] = "ц", ["e"] = "у", ["r"] = "к", ["t"] = "е", ["y"] = "н", ["u"] = "г", ["i"] = "ш", ["o"] = "щ", ["p"] = "з", ["["] = "х", ["]"] = "ъ", ["a"] = "ф", ["s"] = "ы", ["d"] = "в", ["f"] = "а", ["g"] = "п", ["h"] = "р", ["j"] = "о", ["k"] = "л", ["l"] = "д", [";"] = "ж", ["'"] = "э", ["z"] = "я", ["x"] = "ч", ["c"] = "с", ["v"] = "м", ["b"] = "и", ["n"] = "т", ["m"] = "ь", [","] = "б", ["."] = "ю", ["`"] = "ё", shifted = { ["q"] = "Й", ["w"] = "Ц", ["e"] = "У", ["r"] = "К", ["t"] = "Е", ["y"] = "Н", ["u"] = "Г", ["i"] = "Ш", ["o"] = "Щ", ["p"] = "З", ["["] = "Х", ["]"] = "Ъ", ["a"] = "Ф", ["s"] = "Ы", ["d"] = "В", ["f"] = "А", ["g"] = "П", ["h"] = "Р", ["j"] = "О", ["k"] = "Л", ["l"] = "Д", [";"] = "Ж", ["'"] = "Э", ["z"] = "Я", ["x"] = "Ч", ["c"] = "С", ["v"] = "М", ["b"] = "И", ["n"] = "Т", ["m"] = "Ь", [","] = "Б", ["."] = "Ю", ["`"] = "Ё", ["1"] = "!", ["2"] = "@", ["3"] = "#", ["4"] = ";", ["5"] = "%", ["6"] = ":", ["7"] = "?", ["8"] = "*", ["9"] = "(", ["0"] = ")", ["-"] = "_", ["="] = "+", } } local kbdlower = { ['А'] = 'а', ['Б'] = 'б', ['В'] = 'в', ['Г'] = 'г', ['Д'] = 'д', ['Е'] = 'е', ['Ё'] = 'ё', ['Ж'] = 'ж', ['З'] = 'з', ['И'] = 'и', ['Й'] = 'й', ['К'] = 'к', ['Л'] = 'л', ['М'] = 'м', ['Н'] = 'н', ['О'] = 'о', ['П'] = 'п', ['Р'] = 'р', ['С'] = 'с', ['Т'] = 'т', ['У'] = 'у', ['Ф'] = 'ф', ['Х'] = 'х', ['Ц'] = 'ц', ['Ч'] = 'ч', ['Ш'] = 'ш', ['Щ'] = 'щ', ['Ъ'] = 'ъ', ['Э'] = 'э', ['Ь'] = 'ь', ['Ю'] = 'ю', ['Я'] = 'я', } local function tolow(s) if not s then return end s = s:lower(); local xlat = kbdlower if xlat then for k, v in stead.pairs(xlat) do s = s:gsub(k,v); end end return s; end local function kbdxlat(s) local kbd if s == 'space' then return ' ' end if s == 'return' then return '\n' end if s:len() > 1 then return end if input.kbd_alt_xlat and (game.codepage == 'UTF-8' or game.codepage == 'utf-8') then kbd = kbdru; else kbd = kbden end if kbd and input.kbd_shift then kbd = kbd.shifted; end if not kbd[s] then if input.kbd_shift then return s:upper(); end return s; end return kbd[s] end game.action = stead.hook(game.action, function (f, s, cmd, ...) if cmd == 'kbd_enter' then local r,v if stead.here().inp_enter then r,v = stead.call(stead.here(), 'inp_enter'); elseif s.inp_enter then r,v = stead.call(s, 'inp_enter'); end return r,v -- nothing todo end return f(s, cmd, ...) end) local lookup_inp = function() for i, o in stead.opairs(objs()) do o = stead.ref(o) if o._edit then return o end end end local input_kbd = function(s, down, key) if not input._txt then return end if key:find("shift") then input.kbd_shift = down elseif key:find("alt") then if down and input.inp_xlat then input.kbd_alt_xlat = not input.kbd_alt_xlat; end input.kbd_alt = down elseif down then local o = lookup_inp(); if not o then return end if input.kbd_alt then return end if key == "return" then if o then o._edit = false o._txt = input._txt input._txt = false return "kbd_enter" end return end if key == "backspace" then if input._txt == '' then return end if input._txt:byte(input._txt:len()) >= 128 then input._txt = input._txt:sub(1, input._txt:len() - 2); else input._txt = input._txt:sub(1, input._txt:len() - 1); end return "wait" end local c = kbdxlat(key); if not c then return end if o and stead.type(o.filter) == 'function' then c = o:filter(c); if not c then return end end input._txt = input._txt..c; return "wait" end end stead.module_init(function() input.cursor = '_' input.inp_xlat = true input.key = stead.hook(input.key, function(f, ...) local r = input_kbd(...) if r then return r end return f(...) end) end) local function input_esc(s) local rep = function(s) return txtnb(s) end if not s then return end -- return s:gsub("\\","\\\\\\\\"):gsub(">","\\\\>"):gsub("%^","\\%^"): local r = s:gsub("[^ ]+", rep):gsub("[ \t]", rep):gsub("{","\\{"):gsub("}","\\}"); return r end function inp(n, info, txt) if stead.type(n) ~= 'string' or stead.type(info) ~= 'string' then error ("Wrong parameter to inp.", 2); end local v = { nam = n, _txt = '', info = info } if txt then v._txt = txt end v.dsc = function(s) if s._edit then return s.info..input_esc(input._txt)..input.cursor end return s.info..input_esc(s._txt) end v.text = function(s, text) local t if s._edit then t = input._txt else t = s._txt end if text then if s._edit then input._txt = text else s._txt = text end return end return t end v.match = function(s, str) local aa = tolow(tostring(str)):gsub("[*]",".*"):gsub("[?]",".?"); local bb = tolow(tostring(s:text())); if bb:find("^"..aa.."$") then return true end end v.state = function(s, t) local os = s._edit if t == nil then return os end s._edit = t if os and t or (not os and not t) then return os end if s._edit then input._txt = s._txt; else s._txt = input._txt input._txt = false end return os end; v.act = function(s) if input._txt and not s._edit then return true end -- somewhere else s:state(not s._edit) return true end v.save = function(self, name, h, need) if need then h:write(stead.string.format("%s = inp (%q, %q, %q);\n", name, self.nam, self.info, self._txt)) end stead.savemembers(h, self, name, false); end return obj(v) end -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/kbd.lua000066400000000000000000000020711467622671600176350ustar00rootroot00000000000000game.action = stead.hook(game.action, function(f, s, cmd, ...) if cmd == 'user_kbd' then local r,v; if stead.here().kbd then r,v = stead.call(stead.here(), 'kbd', input.key_event.down, input.key_event.key); elseif s.kbd then r,v = stead.call(s, 'kbd', input.key_event.down, input.key_event.key); end if r == nil and v == nil and not stead.api_atleast(1, 3, 5) then return nil, true end return r,v end return f(s, cmd, ...); end) stead.module_init(function() input.key = stead.hook(input.key, function(f, s, down, key, ...) if input._key_hooks[key] then input.key_event = { key = key, down = down }; return 'user_kbd' end return f(s, down, key, ...) end) input._key_hooks = {} end) stead.hook_keys = function(...) local a = {...}; for i = 1, stead.table.maxn(a) do input._key_hooks[tostring(a[i])] = true; end end stead.unhook_keys = function(...) local a = {...}; for i = 1, stead.table.maxn(a) do input._key_hooks[tostring(a[i])] = nil; end end hook_keys = stead.hook_keys unhook_keys = stead.unhook_keys -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/nolife.lua000066400000000000000000000002061467622671600203470ustar00rootroot00000000000000game.life = stead.hook(game.life, function(f, ...) if stead.call_bool(stead.here(), 'nolife') then return end return f(...) end) instead-3.5.2+dfsg/stead/stead2/nouse.lua000066400000000000000000000003441467622671600202270ustar00rootroot00000000000000game.use = function(s, w, o) local r, v r, v = stead.call(w, 'nouse', o); if not r and not v then r, v = stead.call(o, 'noused', w); end if not r and not v then r, v = stead.call(s, 'nouse', w, o) end return r, v end instead-3.5.2+dfsg/stead/stead2/object.lua000066400000000000000000000160331467622671600203460ustar00rootroot00000000000000local function onevent(ev, ...) local vv, r if stead.api_atleast(1, 6, 3) then vv, r = stead.call(game, ev, ...); if r == false then return vv, false end if vv == false then return nil, false end return vv end end stead.player_action = function(self, what, ...) local v,r,obj,vv if isXaction(what) then -- already xact obj = what else obj = stead.rawget(_G, what); end if not isXaction(obj) then obj = stead.ref(self.where):srch(what); end if not obj then return stead.call(game, 'action', what, ...); --player_do(self, what, ...); end vv, r = onevent('onact', obj, ...); if vv == false then return end if r == false then return vv end v, r = stead.player_take(self, what, ...); if not v and not r then v, r = stead.call(obj, 'act', ...); if stead.type(vv) == 'string' then v = stead.par(stead.space_delim, vv, v); end if not v and not r then v, r = stead.call(game, 'act', obj, ...); end elseif stead.type(vv) == 'string' then v = stead.par(stead.space_delim, vv, v); end return v, r; end stead.player_use = function(self, what, onwhat, ...) local obj, obj2, v, vv, r; local scene_use_mode = false obj = stead.rawget(_G, what); if isXaction(obj) then -- use xact is act return self:action(obj, onwhat, ...) end obj = self:srch(what); -- in inv? if not obj then -- no obj = stead.ref(self.where):srch(what); -- in scene? if not obj then -- no! return game.err, false; end scene_use_mode = true -- scene_use_mode! end obj = stead.ref(obj); if onwhat == nil then -- only one? if scene_use_mode then return self:action(what, ...); -- call act end vv, r = onevent('oninv', obj, ...); if vv == false then return end if r == false then return vv end v, r = stead.call(obj, 'inv', ...); -- call inv if stead.type(vv) == 'string' then v = stead.par(stead.space_delim, vv, v); end if not v and not r then v, r = stead.call(game, 'inv', obj, ...); end return v, r; end obj2 = stead.ref(self.where):srch(onwhat); -- in scene? if not obj2 then obj2 = self:srch(onwhat); -- in inv? end if not obj2 then return game.err, false; end obj2 = stead.ref(obj2) if not scene_use_mode or isSceneUse(obj) then vv, r = onevent('onuse', obj, obj2, ...); if vv == false then return end if r == false then return vv end v, r = stead.call(obj, 'use', obj2, ...); if stead.type(vv) == 'string' then v = stead.par(stead.space_delim, vv, v); end if r ~= false then vv = stead.call(obj2, 'used', obj, ...); if stead.type(vv) == 'string' then v = stead.par(stead.space_delim, v, vv); end end end if v == nil and vv == true and stead.api_atleast(1, 7, 1) then v = true end if not v then v, r = stead.call(game, 'use', obj, obj2, ...); end -- if v == nil and stead.api_version >= "1.3.5" then -- return true -- end return v end stead.vobj_save = function(self, name, h, need) local w = stead.deref(self.where) local dsc = self.dsc if need then h:write(stead.string.format("%s = vobj(%s,%s,%s);\n", name, stead.tostring(self.nam), stead.tostring(dsc), stead.tostring(w))); end stead.savemembers(h, self, name, false); end stead.vobj_act = function(self, ...) local o, r = stead.here():srch(self); -- self.nam if stead.ref(o) and stead.ref(o).where then return stead.walk(stead.ref(o).where); end return stead.call(stead.ref(r),'act', self.nam, ...); end stead.vobj_used = function(self, ...) local o, r = stead.here():srch(self.nam); return stead.call(stead.ref(r),'used', self.nam, ...); end stead.vobj_use = function(self, ...) local o, r = stead.here():srch(self.nam); return stead.call(stead.ref(r),'use', self.nam, ...); end function vobj(name, dsc, w) return obj{ nam = stead.tostr(name), vobject_type = true, dsc = dsc, where = stead.deref(w), act = stead.vobj_act, used = stead.vobj_used, use = stead.vobj_use, save = stead.vobj_save }; end function vway(name, dsc, w) -- o.object_type = true; return obj{ nam = stead.tostr(name), vobject_type = true, dsc = dsc, act = stead.vobj_act, where = stead.deref(w), used = stead.vobj_used, use = stead.vobj_use, save = stead.vobj_save }; end function isVobject(v) return (stead.type(v) == 'table') and (v.vobject_type) end stead.list_check = function(self, name) -- force using of objects, instead refs for i, v, ii in stead.opairs(self) do local o = stead.ref(v); if not isObject(o) then error (stead.string.format("Wrong object: %q (%s) at %s", stead.tostr(v), stead.tostr(stead.type(v)), name .."["..stead.tostr(ii).."]")); return false end if (v.auto_allocated and not stead.ref(v.key_name)) -- renew or (isObject(stead.deref(v)) and not v._dynamic_type) then -- no named object! local n = stead.string.format("%s[%d]", name, ii); v = allocator:new(n, n); self[ii] = v; v.auto_allocated = true; for_each(v, n, stead.check_list, isList, stead.deref(v)); else self[ii] = o; end end return true; end stead.list_add = function(self, name, pos) local nam = name if stead.initialized then nam = stead.ref(name); end if not nam then error ("Add wrong object to list: "..stead.tostr(name), 2); end if self:look(nam) then return nil end self.__modified__ = true; if isObject(stead.deref(nam)) then nam._dynamic_type = true end if stead.tonum(pos) then pos = stead.tonum(pos) if pos <= #self then stead.table.insert(self, pos, nam); else self[pos] = nam; -- for spare lists end else stead.table.insert(self, nam); end return true end stead.list_set = function(self, name, pos) local nam = name local i = stead.tonum(pos); if not i then return nil end if stead.initialized then nam = stead.ref(name); end if not nam then error ("Set wrong object in list: "..stead.tostr(name), 2); end if isObject(stead.deref(nam)) then nam._dynamic_type = true end self.__modified__ = true; self[i] = nam; -- for spare lists return true end stead.list_concat = function(self, other, pos) for n, o, ii in stead.opairs(other) do o = stead.ref(o); if pos == nil then self:add(o); else self:add(o, pos); pos = pos + 1; end end end stead.delim = '|' stead.list_str = function(self) local v, vv for i, o in stead.opairs(self) do o = stead.ref(o); if isObject(o) and not isDisabled(o) then vv = stead.dispof(o) vv = stead.xref(vv, o); v = stead.par(stead.delim, v, vv); end end return v; end stead.obj_str = function(self) local v, vv; if not isObject(self) then return end if isDisabled(self) then return end for i, o in stead.opairs(self.obj) do o = stead.ref(o); if isObject(o) and not isDisabled(o) then vv = stead.dispof(o) vv = stead.xref(vv, o); v = stead.par(stead.delim, v, vv, stead.obj_str(o)); end end return v; end function path(w, wh) -- search in way, disabled too if not wh then wh = stead.here(); else wh = stead.ref(wh); end local o = ways(wh):srch(w, true); o = stead.ref(o); if isRoom(o) then return o end return nil end game.lifes = list(game.lifes) stead:init(); -- reinit ob -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/para.lua000066400000000000000000000000441467622671600200160ustar00rootroot00000000000000require "format" format.para = true instead-3.5.2+dfsg/stead/stead2/pixels.lua000066400000000000000000000023601467622671600204020ustar00rootroot00000000000000require "sprites" local pixels_mt = { } local font_mt = { __gc = function(s) stead.font_free(s.fnt) end; __tostring = function(s) return s.fnt end; } local pnew = function(p) if stead.type(p) ~= 'userdata' then return end local t = getmetatable(p).__index setmetatable(t, pixels_mt) return p end local fnew = function(f) if stead.type(f) ~= 'string' then return end local fn = { fnt = f; save = function() end; } setmetatable(fn, font_mt) return fn end local font_m = { text = function(s, text, col, style, ...) return pnew(stead.sprite_pixels(stead.sprite_text(s.fnt, text, col, style, ...))) end; size = function(s, ...) return stead.sprite_text_size(s.fnt, ...); end; } local pixels_m = { save = function() end; dup = function(self) local w, h, s = self:size() local p = stead.sprite_pixels(w, h, s) if p then self:copy(p) end return pnew(p) end; } font_mt.__index = font_m pixels_mt.__index = pixels_m pixels = { nam = 'pixels'; object_type = true; system_type = true; fnt = function(name, sz, ...) if not stead.tonum(sz) then error("No font size specified.", 2) end return fnew(stead.font_load(name, -sz, ...)) end; new = function(...) return pnew(stead.sprite_pixels(...)) end; } instead-3.5.2+dfsg/stead/stead2/prefs.lua000066400000000000000000000016021467622671600202130ustar00rootroot00000000000000prefs = obj { nam = 'preferences', system_type = true, load = function(s) local name = instead_savepath() .. '/prefs'; local f, err = loadfile(name); if not f then return nil end f(); end, ini = function(s) return s:load() end, store = function(s) s:save() stead.clearvar(s); end, save = function(s) -- save prefs on every save local name = instead_savepath() .. '/prefs'; local name_tmp = name..'.tmp' local h = stead.io.open(name_tmp, "wb"); if not h then return false end stead.savemembers(h, s, 'prefs', true); h:flush(); h:close(); stead.os.remove(name); stead.os.rename(name_tmp, name); end, purge = function(s) local name = instead_savepath() .. '/prefs'; for k, v in stead.pairs(s) do if stead.type(v) ~= 'function' and k ~= 'nam' and k ~= 'system_type' then s[k] = nil end end return stead.os.remove(name); end }; -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/proxymenu.lua000066400000000000000000000140261467622671600211460ustar00rootroot00000000000000stead.menu_prefix = '   ' local mpar = function(v, vv, rc) if stead.type(v) == 'string' or stead.type(vv) == 'string' then return stead.par(stead.space_delim, v, vv); elseif v == true or vv == true then return true end return rc end local call = function(o, m, ...) local rc = nil local v, r = stead.call(o, m, ...); if r == false or v == false then rc = false elseif r or v then rc = true end return v, r, rc end stead.obj_proxy = function(o, act, use_mode, used_act, useit_act) local v = {}; v.proxy_type = true; local d = stead.dispof(o); if stead.type(d) == 'string' then v.nam = stead.menu_prefix..d; end if inv():srch(o) then v.nam = txtem(v.nam); end if not v.nam then v.nam = true end v.pobj = o; v.pact = act; v.use_mode = use_mode; v.used_act = used_act; v.useit_act = useit_act; v.save = function(self, name, h, need) if need then h:write(stead.string.format(name.." = stead.obj_proxy(%s, %s, %s, %s, %s);\n", stead.tostring(self.pobj), stead.tostring(self.pact), stead.tostring(self.use_mode), stead.tostring(self.used_act), stead.tostring(self.useit_act))); end stead.savemembers(h, self, name, false); end if use_mode then v.use = function(s, w) if w.proxy_type then local v, r, vv, rr, rc, ri rc = false local act = s.pact v, r, ri = call(game, 'before_'..act, s.pobj, w.pobj); rc = ri or rc if ri == false then return v, false end vv, r, ri = call(s.pobj, act, w.pobj); rc = ri or rc v = mpar(v, vv, rc); if ri == false then return v, false end if stead.type(s.used_act) == 'string' and ri == nil then -- used only if use did nothing vv, r, ri = call(w.pobj, s.used_act, s.pobj); rc = ri or rc v = mpar(v, vv, rc); if ri == false then return v, false end end if ri then vv, rr, ri = call(game, 'after_'..act, s.pobj, w.pobj); rc = rc or ri v = mpar(v, vv, rc); if ri == false then return v, false end end if v == nil then v = stead.call(game, act, s.pobj, w.pobj); end return v, false; end end end v.inv = function(s) local v, r, vv, rr, rc, ri rc = false local act = s.pact if s.use_mode then act = s.useit_act if stead.type(act) ~= 'string' then return nil end end v, r, ri = call(game, 'before_'..act, s.pobj); rc = rc or ri if ri == false then return v end vv, r, ri = call(s.pobj, act); rc = rc or ri v = mpar(v, vv, rc) if ri == false then return v end if ri then vv, rr, ri = call(game, 'after_'..act, s.pobj); rc = rc or ri v = mpar(v, vv, rc); end if v == nil then v = stead.call(game, act, s.pobj); end return v, rc; end if use_mode then return obj(v) end return menu(v) end stead.proxy_fill_objs = function(s, w, act, use_mode, used_act, useit_act) local rc = false for i, o, ii in stead.opairs(w) do o = stead.ref(o); if isObject(o) and not isDisabled(o) and o ~= s and not isPhrase(o) and not o.proxy_type and not isStatus(o) then s.obj:add(stead.obj_proxy(o, act, use_mode, used_act, useit_act)); if not isRoom(o) then stead.proxy_fill_objs(s, o.obj, act, use_mode, used_act, useit_act); end rc = true end end return rc end local select_only = function(s) for k, o in stead.opairs(stead.me().obj) do o = stead.ref(o) if o.action_type and o._state and o ~= s then o:inv(); end end stead.obj_tag(stead.me(), MENU_TAG_ID); end local proxy_menu = function(nam, act, _scene, _inv, _way, use_mode, used_act, useit_act, _ifhave) local v = { }; if stead.type(act) ~= 'string' then error("Wrong parameter to proxy_menu.", 3) end if null[act] then error(stead.tostring(act).."is a reserved handler. Do not use it.", 3) end if used_act and null[used_act] then error(stead.tostring(used_act).."is a reserved handler. Do not use it.", 3) end if useit_act and null[useit_act] then error(stead.tostring(useit_act).."is a reserved handler. Do not use it.", 3) end v.action_type = true; v._state = false; v.nam = nam; v.disp = function(s) local n = stead.call(s, 'nam') if s._state then return txtu(txtnb(n)); end return txtnb(n); end v.fill_scene = _scene; v.fill_inv = _inv; v.fill_ifhave = _ifhave; v.fill_way = _way; v.gen = function(s) local k,o,i local rc = false s.obj:zap(); if s.fill_inv then rc = stead.proxy_fill_objs(s, inv(), act, use_mode, used_act, useit_act); end if not s.fill_ifhave or rc then if s.fill_scene then stead.proxy_fill_objs(s, stead.here().obj, act, use_mode, used_act, useit_act); end end if s.fill_way then stead.proxy_fill_objs(s, stead.here().way, act, use_mode, used_act, useit_act); end select_only(s); end v.inv = function(s) local i,o local k,v s._state = not s._state if s._state then s:gen(); else s.obj:zap(); end return nil, true -- to say instead, do not redraw scene, only inv ;) end return menu(v); end local function gen_actions(s) for k, o in stead.opairs(stead.me().obj) do o = stead.ref(o) if o.action_type and o._state then o:gen(); end end end act_menu = function(nam, act) local v = { }; v.action_type = true; v.nam = nam; v.gen = function(s) end v.inv = function(s) local v, r v, r = stead.call(game, act); return v, r end return menu(v); end obj_menu = function(nam, act, _scene, _inv, _way) return proxy_menu(nam, act, _scene, _inv, _way) end use_menu = function(nam, act, used_act, useit_act, _scene, _inv, _ifhave) return proxy_menu(nam, act, _scene, _inv, false, true, used_act, useit_act, _ifhave) end inv = function(s) return stead.me().inventory; end game.onuse = function(s, v, w) -- do not let use on non proxy obj if not v.proxy_type and not w.proxy_type then return end if not v.proxy_type or not w.proxy_type then return false end end player = stead.inherit(player, function(v) v.inv = function(s) gen_actions(s); return stead.player_inv(s); end v.inventory = list {} return v end) pl = player(pl) -- reinit -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/quotes.lua000066400000000000000000000000461467622671600204150ustar00rootroot00000000000000require "format" format.quotes = true instead-3.5.2+dfsg/stead/stead2/snapshots.lua000066400000000000000000000035431467622671600211240ustar00rootroot00000000000000local MAKE_SNAPSHOT game._snapshots = {} stead.make_snapshot = function(nr) if not stead.tonum(nr) then nr = 0 end local h = { }; h.txt = '' h.write = function(s, ...) local a = {...}; for i = 1, stead.table.maxn(a) do s.txt = s.txt .. stead.tostr(a[i]); end end local old = game._snapshots; game._snapshots = nil stead.do_savegame(game, h); game._snapshots = old game._snapshots[nr] = h.txt; end function isSnapshot(nr) if not stead.tonum(nr) then nr = 0 end return (game._snapshots[nr] ~= nil) end stead.restore_snapshot = function (nr) if not stead.tonum(nr) then nr = 0 end local ss = game._snapshots if not ss[nr] then return nil, true end -- nothing todo local i,v if stead.api_atleast(1, 7, 1) then stead.gamereset("main.lua", true); else stead.gamefile("main.lua", true); end local f, err = stead.eval(ss[nr]..' '); if not f then return end local i,r = f(); game._snapshots = ss if r then return nil, false end i = stead.do_ini(game, true); if stead.api_atleast(1, 7, 1) then i = game:start() stead.rawset(_G, 'PLAYER_MOVED', true) -- force fading else -- legacy if not game.showlast then stead.last_disp(false) end i = stead.cat('', stead.last_disp()) end stead.rawset(_G, 'RAW_TEXT', true) -- delete_snapshot(nr); if stead.cctx() then stead.pr(i) end return i; end stead.delete_snapshot = function(nr) if not stead.tonum(nr) then nr = 0 end game._snapshots[nr] = nil end function make_snapshot(nr) if stead.type(nr) ~= 'number' then nr = 0 end MAKE_SNAPSHOT = nr end function restore_snapshot(nr) return stead.restore_snapshot(nr) end function delete_snapshot(nr) return stead.delete_snapshot(nr); end iface.cmd = stead.hook(iface.cmd, function(f, ...) local r,v = f(...); if MAKE_SNAPSHOT ~= nil then stead.make_snapshot(MAKE_SNAPSHOT); MAKE_SNAPSHOT = nil end return r,v end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/sound.lua000066400000000000000000000022501467622671600202240ustar00rootroot00000000000000stead.sound_load = instead_sound_load stead.sound_free = instead_sound_free stead.sounds_free = instead_sounds_free stead.sound_channel = instead_sound_channel stead.sound_volume = instead_sound_volume stead.sound_panning = instead_sound_panning stead.sound_load_mem = instead_sound_load_mem stead.music_callback = instead_music_callback sound = { nam = 'sound'; object_type = true; system_type = true; load = function(a, b, t) if type(a) == 'string' then return stead.sound_load(a); elseif type(t) == 'table' then return stead.sound_load_mem(a, b, t) -- hz, channel, t end end; music_callback = function(...) return stead.music_callback(...) end; free = function(key) return stead.sound_free(key); end; play = function(key, ...) return stead.add_sound(key, ...) end; stop = function(...) stead.stop_sound(...); end; playing = function(s,...) if stead.type(s) ~= 'number' then return stead.is_sound() end return stead.sound_channel(s,...) end; pan = function(c, l, r, ...) return stead.sound_panning(c, l, r, ...) end; vol = function(v, ...) return stead.sound_volume(v, ...) end } stead.module_init(function() stead.sounds_free(); end) instead-3.5.2+dfsg/stead/stead2/sprites.lua000066400000000000000000000117321467622671600205720ustar00rootroot00000000000000require "theme" local type = stead.type stead.font_load = instead_font_load stead.font_free = instead_font_free stead.font_scaled_size = instead_font_scaled_size stead.sprite_alpha = instead_sprite_alpha stead.sprite_dup = instead_sprite_dup stead.sprite_scale = instead_sprite_scale stead.sprite_rotate = instead_sprite_rotate stead.sprite_text = instead_sprite_text stead.sprite_text_size = instead_sprite_text_size stead.sprite_draw = instead_sprite_draw stead.sprite_copy = instead_sprite_copy stead.sprite_compose = instead_sprite_compose stead.sprite_fill = instead_sprite_fill stead.sprite_pixel = instead_sprite_pixel stead.sprite_load = instead_sprite_load stead.sprite_free = instead_sprite_free stead.sprite_size = instead_sprite_size stead.sprites_free = instead_sprites_free stead.sprite_colorkey = instead_sprite_colorkey stead.sprite_pixels = instead_sprite_pixels sprite = { nam = 'sprites'; object_type = true; system_type = true; screen = function(s) if theme.get 'scr.gfx.mode' ~= 'direct' then return end return 'screen' end; font_scaled_size = function(size) return stead.font_scaled_size(size); end; font = function(font, size, ...) return stead.font_load(font, size, ...); end; free_font = function(font) return stead.font_free(font); end; font_height = function(font) local w,h = stead.sprite_text_size(font) return h end; alpha = function(name, alpha, ...) return stead.sprite_alpha(name, alpha, ...); end; colorkey = function(name, color, ...) return stead.sprite_colorkey(name, color, ...); end; dup = function(name, ...) return stead.sprite_dup(name, ...); end; scale = function(name, xs, ys, smooth, ...) if smooth == nil then smooth = true -- default is on end return stead.sprite_scale(name, xs, ys, smooth,...); end; rotate = function(name, angle, smooth, ...) if smooth == nil then smooth = true -- default is on end return stead.sprite_rotate(name, angle, smooth, ...); end; text = function(font, text, col, style, ...) return stead.sprite_text(font, text, col, style, ...); end; size = function(spr) return stead.sprite_size(spr); end; text_size = function(fnt, ...) return stead.sprite_text_size(fnt, ...); end; draw = function(s, fx, fy, fw, fh, d, x, y, alpha) if d == nil and x == nil and y == nil then d, x, y, alpha = fx, fy, fw, fh fx, fy, fw, fh = 0, 0, -1, -1 end return stead.sprite_draw(s, fx, fy, fw, fh, d, x, y, alpha); end; copy = function(s, fx, fy, fw, fh, d, x, y, alpha) if d == nil and x == nil and y == nil then d, x, y, alpha = fx, fy, fw, fh fx, fy, fw, fh = 0, 0, -1, -1 end if alpha then local ss = stead.sprite_alpha(s, alpha) local r = stead.sprite_copy(ss, fx, fy, fw, fh, d, x, y, alpha); stead.sprite_free(ss) return r end return stead.sprite_copy(s, fx, fy, fw, fh, d, x, y, alpha); end; compose = function(s, fx, fy, fw, fh, d, x, y, alpha) if d == nil and x == nil and y == nil then d, x, y, alpha = fx, fy, fw, fh fx, fy, fw, fh = 0, 0, -1, -1 end if alpha then local ss = stead.sprite_alpha(s, alpha) local r = stead.sprite_compose(ss, fx, fy, fw, fh, d, x, y, alpha); stead.sprite_free(ss) return r end return stead.sprite_compose(s, fx, fy, fw, fh, d, x, y, alpha); end; fill = function(d, x, y, w, h, col) if h == nil and col == nil then return stead.sprite_fill(d, 0, 0, -1, -1, x); end return stead.sprite_fill(d, x, y, w, h, col); end; pixel = function(d, x, y, col, alpha) return stead.sprite_pixel(d, x, y, col, alpha) end; load = function(fname, ...) return stead.sprite_load(fname, ...); end; blank = function(w, h, ...) local t = 'blank:'..stead.tostr(stead.math.floor(w))..'x'..stead.tostr(stead.math.floor(h)) return stead.sprite_load(t, ...) end; box = function(w, h, col, alpha, ...) local t = 'box:'..stead.tostr(stead.math.floor(w))..'x'..stead.tostr(stead.math.floor(h)) if col then t = t..','..stead.tostr(col) end if alpha then t = t..','..stead.tostr(alpha) end return stead.sprite_load(t, ...) end; free = function(key) return stead.sprite_free(key); end; } stead.module_done(function() stead.sprites_free(); end) local function compat_api() if not stead.api_atleast(1, 7, 1) then font_load = instead_font_load font_free = instead_font_free font_scaled_size = instead_font_scaled_size sprite_alpha = instead_sprite_alpha sprite_dup = instead_sprite_dup sprite_scale = instead_sprite_scale sprite_rotate = instead_sprite_rotate sprite_text = instead_sprite_text sprite_text_size = instead_sprite_text_size sprite_draw = instead_sprite_draw sprite_copy = instead_sprite_copy sprite_compose = instead_sprite_compose sprite_fill = instead_sprite_fill sprite_pixel = instead_sprite_pixel sprite_load = instead_sprite_load sprite_free = instead_sprite_free sprite_size = instead_sprite_size sprites_free = instead_sprites_free end end stead.module_start(function(load) if compat_api and not load then compat_api() compat_api = nil end end) instead-3.5.2+dfsg/stead/stead2/stead.lua000066400000000000000000002103131467622671600201750ustar00rootroot00000000000000stead = { version = "3.5.0", api_version = "1.1.6", -- last version before 1.2.0 table = table, delim = ',', scene_delim = "^^", space_delim = ' ', string = string, tostr = tostring, tonum = tonumber, collectgarbage = collectgarbage, type = type, ipairs = ipairs, pairs = pairs, getinfo = debug.getinfo; rawget = rawget; rawset = rawset; math = math, random = instead_random, randomseed = instead_srandom, next = next, math = math, io = io, os = os, readdir = instead_readdir, cache = {}, call_top = 0, call_ctx = { txt = nil, self = nil }, -- functions = {}, -- code blocks modules_ini = {}, modules_done = {}, modules_start = {}, modules_cmd = {}, busy = function() end; module_init = function(f, ...) if stead.type(f) ~= 'function' then error ("Wrong parameter to module_init.", 2); end stead.table.insert(stead.modules_ini, f); f(); end; module_done = function(f, ...) if stead.type(f) ~= 'function' then error ("Wrong parameter to module_done.", 2); end stead.table.insert(stead.modules_done, f); end; module_start = function(f, ...) if stead.type(f) ~= 'function' then error ("Wrong parameter to module_start.", 2); end stead.table.insert(stead.modules_start, f); end; module_cmd = function(f, ...) if stead.type(f) ~= 'function' then error ("Wrong parameter to module_cmd.", 2); end stead.table.insert(stead.modules_cmd, f); end; } function instead_menu_toggle(n) if n == nil then n = 'main' elseif type(n) ~= 'string' then n = 'toggle' end stead.need_menu = n end stead.menu_toggle = instead_menu_toggle stead.api_atleast = function(...) for k, v in stead.ipairs {...} do if stead.type(v) ~= 'number' then return false end if v > (stead.api_version_table[k] or 0) then return false end if v < (stead.api_version_table[k] or 0) then return true end end return true end; stead.atleast = function(...) for k, v in stead.ipairs {...} do if stead.type(k) ~= 'number' then return false end if v > (stead.version_table[k] or 0) then return false end if v < (stead.version_table[k] or 0) then return true end end return true end; stead.last_act = function(s) local r = game.__last_act if s ~= nil and s ~= true then game.__last_act = s end return r end stead.last_disp = function(s) local r = game._lastdisp if s == nil then return r end if not s then s = nil end game._lastdisp = s return r end stead.act_text = function(s) local o = stead.rawget(_G, 'ACTION_TEXT') if s == nil then return o end if not s then s = nil end stead.rawset(_G, 'ACTION_TEXT', s) return o end stead.nop = function(s) -- to refresh entry scene w/o time tick stead.act_text(true) return stead.last_disp() or '' end stead.need_scene = function(s) if s == nil then stead.rawset(_G, 'NEED_SCENE', true) else stead.rawset(_G, 'NEED_SCENE', s) end end if _VERSION == "Lua 5.1" then stead.eval = loadstring stead.unpack = unpack else stead.eval = load stead.unpack = table.unpack unpack = table.unpack -- buggy games stead.table.maxn = table_get_maxn string.gfind = string.gmatch math.mod = math.fmod math.log10 = function(a) return stead.math.log(a, 10) end end instead = stead; function stead.getcmd(str) local a = {} local n = 1 local cmd; local i,k = stead.string.find(str, '[a-zA-Z0-9_]+'); if not i or not k then cmd = str; else cmd = stead.string.sub(str, i, k); end stead.cmd = cmd if cmd == 'load' or cmd == 'save' then a[1] = stead.strip(stead.string.sub(str, k + 1)); stead.args = a; return cmd, a end while i do k = k + 1; i,k = stead.string.find(str,'[^,]+', k); if not i then break end a[n] = stead.strip(stead.string.sub(str, i, k)); n = n + 1; end stead.args = a; return cmd, a end stead.tostring = function(v) if isCode(v) then v = stead.string.format("code %q", stead.functions[v].code); elseif stead.type(v) == 'string' then v = stead.string.format("%q", v); elseif v == nil or stead.type(v) == 'boolean' or stead.type(v) == 'number' then v = stead.tostr(v); elseif stead.type(v) == 'table' and stead.type(stead.deref(v)) == 'string' then v = stead.deref(v); else v = nil end return v end stead.cctx = function() return stead.call_ctx[stead.call_top]; end stead.callpush = function(v, ...) stead.call_top = stead.call_top + 1; stead.call_ctx[stead.call_top] = { txt = nil, self = v, action = false }; stead.rawset(_G, 'args', {...}); stead.rawset(_G, 'arg1', args[1]) stead.rawset(_G, 'arg2', args[2]) stead.rawset(_G, 'arg3', args[3]) stead.rawset(_G, 'arg4', args[4]) stead.rawset(_G, 'arg5', args[5]) stead.rawset(_G, 'arg6', args[6]) stead.rawset(_G, 'arg7', args[7]) stead.rawset(_G, 'arg8', args[8]) stead.rawset(_G, 'arg9', args[9]) -- dirty but clean and fast :) stead.rawset(_G, 'self', v) end stead.clearargs = function() stead.rawset(_G, 'arg1', nil) stead.rawset(_G, 'arg2', nil) stead.rawset(_G, 'arg3', nil) stead.rawset(_G, 'arg4', nil) stead.rawset(_G, 'arg5', nil) stead.rawset(_G, 'arg6', nil) stead.rawset(_G, 'arg7', nil) stead.rawset(_G, 'arg8', nil) stead.rawset(_G, 'arg9', nil) stead.rawset(_G, 'self', nil) end stead.callpop = function() stead.call_ctx[stead.call_top] = nil; stead.call_top = stead.call_top - 1; if stead.call_top < 0 then error ("callpush/callpop mismatch") end stead.clearargs() end stead.pclr = function() stead.cctx().txt = nil end stead.pget = function() return stead.cctx().txt; end stead.p = function(...) local a = {...} if stead.cctx() == nil then error ("Call from global context.", 2); end for i = 1, stead.table.maxn(a) do stead.cctx().txt = stead.par('', stead.cctx().txt, stead.tostr(a[i])); end stead.cctx().txt = stead.cat(stead.cctx().txt, stead.space_delim); end stead.pr = function(...) local a = {...} if stead.cctx() == nil then error ("Call from global context.", 2); end for i = 1, stead.table.maxn(a) do stead.cctx().txt = stead.par('', stead.cctx().txt, stead.tostr(a[i])); end end stead.pn = function(...) if stead.cctx() == nil then error ("Call from global context.", 2); end p(...); stead.cctx().txt = stead.par('', stead.cctx().txt,'^'); end -- merge strings with "space" as separator stead.par = function(space,...) local res local a = {...}; for i = 1, stead.table.maxn(a) do if stead.type(a[i]) == 'string' then if res == nil then res = "" else res = res..space; end res = res..a[i]; end end return res; end -- add to not nill string any string stead.cat = function(v,...) local res if not v then return nil end res = v; local a = {...} for i = 1, stead.table.maxn(a) do if stead.type(a[i]) == 'string' then res = res..a[i]; end end return res; end function txtnb(v) if stead.type(v) ~= 'string' then return nil; end return iface:nb(v); end function img(v) if stead.type(v) ~= 'string' then return nil; end; return iface:img(v); end function imgl(v) if stead.type(v) ~= 'string' then return nil; end; return iface:imgl(v); end function imgr(v) if stead.type(v) ~= 'string' then return nil; end; return iface:imgr(v); end function txtem(v) if stead.type(v) ~= 'string' then return nil; end; return iface:em(v) end function txtst(v) if stead.type(v) ~= 'string' then return nil; end; return iface:st(v) end function txtr(v) if stead.type(v) ~= 'string' then return nil; end; return iface:right(v) end function txtl(v) if stead.type(v) ~= 'string' then return nil; end; return iface:left(v) end function txtc(v) if stead.type(v) ~= 'string' then return nil; end; return iface:center(v) end function txttab(v,a) return iface:tab(v, a) end function txty(v, a) return iface:y(v, a) end function txtj(v) if stead.type(v) ~= 'string' then return nil; end; return iface:just(v) end function txtb(v) if stead.type(v) ~= 'string' then return nil; end; return iface:bold(v) end function txtu(v) if stead.type(v) ~= 'string' then return nil; end; return iface:under(v) end function txtnm(n, v) if stead.type(v) ~= 'string' or not stead.tonum(n) then return nil; end return iface:enum(n, v); end function txttop(v) if stead.type(v) ~= 'string' then return nil; end; return iface:top(v) end function txtbottom(v) if stead.type(v) ~= 'string' then return nil; end; return iface:bottom(v) end function txtmiddle(v) if stead.type(v) ~= 'string' then return nil; end; return iface:middle(v) end stead.fmt = function(...) local res local a = {...}; for i = 1, stead.table.maxn(a) do if stead.type(a[i]) == 'string' then local s = stead.string.gsub(a[i],'[\t ]+', stead.space_delim); s = stead.string.gsub(s, '[\n]+', stead.space_delim); s = stead.string.gsub(s, '\\?[\\^]', { ['^'] = '\n', ['\\^'] = '^', ['\\\\'] = '\\'} ); res = stead.par('', res, s); end end return res end -- integer lists local inext = function(t, k) local v k, v = stead.next(t, k); while k and not stead.tonum(k) do k, v = stead.next(t, k); end if not stead.tonum(k) then return nil end return k, v end local ilist = function(s, var) return inext, s, nil; end local ordered_i = function(t) local ordered = {}; local max = 0 for i, v in ilist(t) do stead.table.insert(ordered, i); max = max + 1; end stead.table.sort(ordered); ordered.i = 1; ordered.max = max; return ordered; end local onext = function(t, k) local v if not k then k = ordered_i(t); end if k.i > k.max then return nil end v = k[k.i] k.i = k.i + 1 return k, t[v], v; end function opairs(s) return onext, s, nil; end stead.opairs = opairs function isPlayer(v) return (stead.type(v) == 'table') and (v.player_type) end function isRoom(v) return (stead.type(v) == 'table') and (v.location_type) end function isPhrase(v) return (stead.type(v) == 'table') and (v.phrase_type) end function isDialog(v) return (stead.type(v) == 'table') and (v.dialog_type) end function isDisabled(v) return (stead.type(v) == 'table') and (v._disabled) end function isRemoved(v) return (stead.type(v) == 'table') and (v._disabled == -1) end function isObject(v) return (stead.type(v) == 'table') and (v.object_type) end function isXaction(v) return (stead.type(v) == 'table') and (v.xaction_type) end stead.obj_xref = function(self,str) function xrefrep(str) local s = stead.string.gsub(str,'[\001\002]',''); return stead.xref(s, self); end if not str then return end if not isObject(self) then return str; end local s = stead.string.gsub(str, '\\?[\\{}]', { ['{'] = '\001', ['}'] = '\002', [ '\\{' ] = '{', [ '\\}' ] = '}' }):gsub('\001([^\002]+)\002', xrefrep):gsub('[\001\002]', { ['\001'] = '{', ['\002'] = '}' }); return s; end stead.obj_look = function(self) local vv if isDisabled(self) then return end local v = stead.call(self,'dsc'); if game.hinting then v = self:xref(v); elseif v then v = stead.string.gsub(v, '[{}]',''); end for i, o in stead.opairs(self.obj) do o = stead.ref(o); if isObject(o) then vv = stead.obj_look(o); v = stead.par(stead.space_delim, v, vv); end end return v; end stead.obj_remove = function(self) self._disabled = -1; return self end stead.obj_disable = function(self) self._disabled = true; return self end stead.obj_enable = function(self) self._disabled = false; return self end stead.obj_disabled = function(self) return (self._disabled == true); end stead.obj_enable_all = function(s) if not isObject(s) then return end objs(s):enable_all(); end stead.obj_disable_all = function(s) if not isObject(s) then return end objs(s):disable_all(); end stead.obj_save = function(self, name, h, need) local dsc; if need then print ("Warning: object "..name.." can not be saved!"); return end stead.savemembers(h, self, name, need); end stead.obj_str = function(self) local v, vv; if not isObject(self) then return end if isDisabled(self) then return end for i, o in stead.opairs(self.obj) do o = stead.ref(o); if o~= nil and not isDisabled(o) then -- isObject is better, but compat layer must be ok vv = stead.call(o, 'nam'); vv = stead.xref(vv, o); v = stead.par(',', v, vv, stead.obj_str(o)); end end return v; end function obj(v) if v.nam == nil then if isRoom(v) then if isDialog(v) then error ("No dialog name in constructor.", 3); end error ("No room name in constructor.", 3); end error ("No object name in constructor.", 2); end v.object_type = true; if v.xref == nil then v.xref = stead.obj_xref; end if v.look == nil then v.look = stead.obj_look; end if v.enable == nil then v.enable = stead.obj_enable; end if v.disable == nil then v.disable = stead.obj_disable; end if v.disabled == nil then v.disabled = stead.obj_disabled; end if v.enable_all == nil then v.enable_all = stead.obj_enable_all; end if v.disable_all == nil then v.disable_all = stead.obj_disable_all; end if v.remove == nil then v.remove = stead.obj_remove; end if v.obj == nil then v.obj = {}; end if v.srch == nil then v.srch = stead.obj_search; end if v.str == nil then v.str = stead.obj_str; end v.obj = list(v.obj); if v.save == nil then v.save = stead.obj_save; end return v end function stead.ref(n, nofunc) -- ref object by name if stead.type(n) == 'string' then if n:find("^[_a-zA-Z][_a-zA-Z0-9]*$") then -- fastest path return stead.rawget(_G, n); end local f = stead.eval('return '..n); if f then return stead.ref(f(), nofunc); end return nil; end if stead.type(n) == 'table' then return n; end if stead.type(n) == 'function' and not nofunc then local r,v = pcall(n); if not r then return nil end return stead.ref(v); end return nil end function stead.deref(n) if stead.type(n) == 'string' then return n end if stead.type(n) == 'table' and stead.type(n.key_name) == 'string' then return n.key_name end return n end stead.list_check = function(self, name) for i, v, ii in stead.opairs(self) do local o = stead.ref(v); if not o then -- isObject(o) then -- compat error ("No object: "..name.."["..stead.tostr(ii).."]".." ("..stead.tostr(stead.type(v))..")") return false end if stead.deref(v) then self[ii] = stead.deref(v); end end return true; end stead.list_str = function(self) local v, vv; for i, o in stead.opairs(self) do o = stead.ref(o); if o~= nil and not isDisabled(o) then vv = stead.call(o, 'nam'); vv = stead.xref(vv, o); v = stead.par(',', v, vv); end end return v; end stead.list_add = function(self, name, pos) local nam nam = stead.deref(name); if self:look(nam) then return nil end self.__modified__ = true; if stead.tonum(pos) then pos = stead.tonum(pos) if pos <= #self then stead.table.insert(self, pos, nam); else self[pos] = nam; -- for spare lists end else stead.table.insert(self, nam); end return true end stead.list_set = function(self, name, pos) local nam local i = stead.tonum(pos); if not i then return nil end nam = stead.deref(name); self.__modified__ = true; self[i] = nam; -- for spare lists return true end stead.list_find = function(self, name) local o = stead.ref(name, true) for n,v,ii in stead.opairs(self) do if stead.ref(v) == o then -- do not call func while search return ii; end end return nil end stead.list_disable_all = function(s) for k, v in stead.opairs(s) do local o = stead.ref(v); if isObject(o) then o:disable() end end end stead.list_enable_all = function(s) for k, v in stead.opairs(s) do local o = stead.ref(v); if isObject(o) then o:enable() end end end stead.list_enable = function(s, w) local o, i = stead.list_search(s, w, true); o = stead.ref(o); if isObject(o) then o:enable() return o end end stead.list_disable = function(s, w) local o, i = stead.list_search(s, w, true); o = stead.ref(o); if isObject(o) then o:disable() return o end end stead.list_save = function(self, name, h, need) if self.__modifyed__ or self.__modified__ then -- compat h:write(name.." = list({});\n"); need = true; end stead.savemembers(h, self, name, need); end stead.list_name = function(self, name, dis) for n, o, ii in stead.opairs(self) do o = stead.ref(o); if isObject(o) then local nam = stead.call(o,'nam') ; if ( not isDisabled(o) or dis ) and name == stead.tostr(nam) then return ii; end end end return nil end stead.list_id = function(self, id, dis) for n, o, ii in stead.opairs(self) do o = stead.ref(o); if dis or not isDisabled(o) then if isObject(o) and id == o.id then return ii; end end end end stead.list_search = function(self, n, dis) local i; i = self:look(n); if not i then i = self:name(n, dis); end if not i and stead.tonum(n) then i = self:byid(stead.tonum(n), dis); if not i then return nil end end if not dis and isDisabled(stead.ref(self[i])) then return nil; end return self[i], i; end stead.list_zap = function(self) for n, o, ii in stead.opairs(self) do self[ii] = nil; end self.__modified__ = true return self end stead.list_concat = function(self, other, pos) for n, o, ii in stead.opairs(other) do o = stead.ref(o); if pos == nil then self:add(stead.deref(o)); else self:add(stead.deref(o), pos); pos = pos + 1; end end end stead.list_del = function(self, name) local v,n v, n = self:srch(name); if n == nil then return nil; end self.__modified__ = true if n <= #self then v = stead.table.remove(self, n); else v = self[n]; self[n] = nil -- for spare lists end return v end stead.list_purge = function(self, name) local v,n v, n = self:srch(name, true); if n == nil then return nil; end self.__modified__ = true v = stead.table.remove(self, n); if not v then v = self[n]; self[n] = nil -- for spare lists end return v end stead.list_replace = function(self, name, name2) local o, ii o, ii = self:srch(name); if ii then self:set(name2, ii); else self:add(name2); end return ii; end function list(v) v.list_type = true; v.add = stead.list_add; v.set = stead.list_set; v.cat = stead.list_concat; v.zap = stead.list_zap; v.del = stead.list_del; v.purge = stead.list_purge; v.replace = stead.list_replace; v.look = stead.list_find; v.name = stead.list_name; v.byid = stead.list_id; v.srch = stead.list_search; v.str = stead.list_str; v.check = stead.list_check; v.save = stead.list_save; v.enable = stead.list_enable; v.disable = stead.list_disable; v.enable_all = stead.list_enable_all; v.disable_all = stead.list_disable_all; return v; end function isList(v) return (stead.type(v) == 'table') and (v.list_type == true) end stead.call = function(v, n, ...) if stead.type(v) ~= 'table' then error ("Call on non table object:"..stead.tostr(n), 2); end if v[n] == nil then return nil,nil; end if stead.type(v[n]) == 'string' then return v[n]; end if stead.type(v[n]) == 'function' then stead.callpush(v, ...) local a,b = v[n](v, ...); -- boolean, nil if stead.type(a) == 'boolean' and b == nil then b, a = a, stead.pget() if a == nil then if stead.cctx().action then a = true else a = b b = nil end end elseif a == nil and b == nil then a = stead.pget() b = nil end if a == nil and b == nil and stead.cctx().action then a = true end stead.callpop() return a,b end if stead.type(v[n]) == 'boolean' then return v[n] end error ("Method not string nor function:"..stead.tostr(n), 2); end stead.call_bool = function(v, n, ...) if stead.type(v) ~= 'table' then error ("Call bool on non table object:"..n, 2); end if v[n] == nil then return nil end if v[n] == false then return false; end if stead.type(v[n]) == 'function' then stead.callpush(v, ...) local r,v = v[n](v, ...); stead.callpop(); return r,v; end return true; -- not nil end stead.call_value = function(v, n, ...) if stead.type(v) ~= 'table' then error ("Call value on non table object:"..n, 2); end if v[n] == nil then return nil end if stead.type(v[n]) ~= 'function' then return v[n]; end stead.callpush(v, ...) local r,v = v[n](v, ...); stead.callpop(); return r,v; end stead.room_scene = function(self) local v; v = iface:title(stead.call(self,'nam')); v = stead.par(stead.scene_delim, v, stead.call(self,'dsc')); --obj_look(self)); return stead.cat(v, stead.space_delim); end stead.room_look = function(self) local vv; for i, o in stead.opairs(self.obj) do o = stead.ref(o); if isObject(o) then vv = stead.par(stead.space_delim, vv, o:look()); end end return stead.cat(vv, stead.space_delim); end stead.obj_search = function(v, n, dis) local i; local o; if not dis and isDisabled(v) then return end o = v.obj:srch(n, dis); if o then return o, v; end for i, o in stead.opairs(v.obj) do o = stead.ref(o); if isObject(o) then local r,rr = stead.obj_search(o, n, dis); if r then return r, rr; end end end return; end stead.room_save = function(self, name, h, need) local dsc; if need then print ("Warning: room "..name.." can not be saved!"); return end stead.savemembers(h, self, name, need); end function room(v) --constructor -- if v.nam == nil then -- error ("No room name in constructor.", 2); -- end if v.scene == nil then v.scene = stead.room_scene; end if v.look == nil then v.look = stead.room_look; end if v.save == nil then v.save = stead.room_save; end v.location_type = true; if v.way == nil then v.way = { }; end v.way = list(v.way); v = obj(v); return v; end stead.dialog_enter = function(self) if not stead.dialog_rescan(self) then return nil, false end return nil, true end stead.dialog_scene = function(self) local v v = iface:title(stead.call(self,'nam')); v = stead.par(stead.scene_delim, v, stead.call(self, 'dsc')); --obj_look(self)); return v; end stead.dialog_look = function(self) local n, v n = 1 for i, ph in stead.opairs(self.obj) do ph = stead.ref(ph); if isPhrase(ph) and not isDisabled(ph) then v = stead.par('^', v, txtnm(n, ph:look())); n = n + 1 end end return v; end stead.dialog_rescan = function(self) local k k = 1 for i, ph in stead.opairs(self.obj) do ph = stead.ref(ph); if isPhrase(ph) and not isDisabled(ph) then ph.nam = stead.tostr(k); k = k + 1; end end if k == 1 then return false end return true end stead.dialog_empty = function(self) return not stead.dialog_rescan(self); end stead.dialog_phrase = function(self, num) if not stead.tonum(num) then if isPhrase(stead.ref(num)) then return stead.ref(num); end return nil end return stead.ref(self.obj[stead.tonum(num)]); end stead.phrase_seen = function(s, enb, ...) local ph local a = {...} if stead.table.maxn(a) == 0 then stead.table.insert(a, stead.cctx().self); end for i = 1,stead.table.maxn(a) do ph = stead.dialog_phrase(s, a[i]); local r = not isPhrase(ph) or isRemoved(ph) or ph:disabled(); if not enb then r = not r end if r then return false end end return true end stead.dialog_pseen = function(s, ...) return stead.phrase_seen(s, true, ...); end stead.dialog_punseen = function(s, ...) return stead.phrase_seen(s, false, ...); end local function ponoff(s, on, ...) local ph local a = {...} if stead.table.maxn(a) == 0 then stead.table.insert(a, stead.cctx().self) end for i = 1,stead.table.maxn(a) do ph = stead.dialog_phrase(s, a[i]); if isPhrase(ph) and not isRemoved(ph) then if on then ph:enable(); else ph:disable(); end end end end stead.dialog_prem = function(s, ...) local ph local a = {...} if stead.table.maxn(a) == 0 then stead.table.insert(a, stead.cctx().self); end for i = 1,stead.table.maxn(a) do ph = stead.dialog_phrase(s, a[i]); if isPhrase(ph) then ph:remove(); end end end stead.dialog_pon = function(self,...) return ponoff(self, true, ...); end stead.dialog_poff = function(self,...) return ponoff(self, false, ...); end function dlg(v) --constructor v.dialog_type = true; if v.ini == nil then v.ini = stead.dialog_enter; end if v.enter == nil then v.enter = stead.dialog_enter; end if v.look == nil then v.look = stead.dialog_look; end if v.scene == nil then v.scene = stead.dialog_scene; end if v.pon == nil then v.pon = stead.dialog_pon; end if v.poff == nil then v.poff = stead.dialog_poff; end if v.prem == nil then v.prem = stead.dialog_prem; end if v.pseen == nil then v.pseen = stead.dialog_pseen; end if v.punseen == nil then v.punseen = stead.dialog_punseen; end if v.empty == nil then v.empty = stead.dialog_empty; end v = room(v); return v; end stead.phrase_action = function(self) local ph = self; local r, ret; if isDisabled(ph) then return nil, false end -- here it is ph:disable(); -- /* disable it!!! */ local last = stead.call(ph, 'ans'); if stead.type(ph.do_act) == 'string' then local f = stead.eval(ph.do_act); if f ~= nil then ret = f(); else error ("Error while eval phrase action."); end elseif stead.type(ph.do_act) == 'function' then ret = ph.do_act(self); end if ret == nil then ret = stead.pget(); end if last == true or ret == true then r = true; end local wh = stead.here(); while isDialog(wh) and not stead.dialog_rescan(wh) and stead.from(wh) ~= wh do wh = stead.from(wh) end if wh ~= stead.here() then ret = stead.par(stead.space_delim, ret, stead.back(wh)); end ret = stead.par(stead.scene_delim, last, ret); if ret == nil then return r -- hack? end return ret end stead.phrase_save = function(self, name, h, need) if need then local m = " = phr(" if isDisabled(self) then m = " = _phr(" end h:write(stead.string.format("%s%s%s,%s,%s);\n", name, m, stead.tostring(self.dsc), stead.tostring(self.ans), stead.tostring(self.do_act))); end stead.savemembers(h, self, name, false); end stead.phrase_look = function(self, n) if isDisabled(self) then return end local v = stead.call(self, 'dsc'); if stead.type(v) ~= 'string' then return; end if game.hinting then return self:xref('{'..v..'}'); end return v; end function phrase(o) --constructor local ret = o; ret.look = stead.phrase_look; ret.nam = ''; -- for start ret.phrase_type = true; ret.act = stead.phrase_action; ret.save = stead.phrase_save; ret = obj(ret); return ret; end function _phr(ask, answ, act) local p = phrase ({ dsc = ask, ans = answ, do_act = act }); p:disable(); return p; end function phr(ask, answ, act) local p = phrase ({ dsc = ask, ans = answ, do_act = act }); -- p:enable(); return p; end stead.player_inv = function(self) return iface:inv(stead.cat(self:str())); end stead.player_ways = function(self) return iface:ways(stead.cat(stead.ref(self.where).way:str())); end stead.player_objs = function(self) return iface:objs(stead.cat(stead.ref(self.where):str())); end stead.player_look = function(self) return stead.ref(self.where):scene(); end stead.obj_tag = function(self, id) if isDisabled(self) then return id end for k, v in stead.opairs(self.obj) do v = stead.ref(v); if isObject(v) and not isDisabled(v) and v.id ~= false then id = id + 1; v.id = id; id = stead.obj_tag(v, id); end end return id; end stead.player_tagall = function(self) local id = 0; id = stead.obj_tag(stead.here(), id); for k, v in stead.opairs(ways()) do v = stead.ref(v); if isRoom(v) and not isDisabled(v) then id = id + 1; v.id = id; end end stead.rawset(_G, 'MENU_TAG_ID', id) id = stead.obj_tag(stead.me(), id); end stead.player_action = function(self, what, ...) local v,r,obj obj = stead.ref(self.where):srch(what); if not obj then return stead.call(stead.ref(game), 'action', what, ...); --player_do(self, what, ...); end v, r = stead.player_take(self, what, ...); if not v then v, r = stead.call(stead.ref(obj), 'act', ...); if not v and r ~= true then v, r = stead.call(stead.ref(game), 'act', obj, ...); end end return v, r; end stead.player_take = function(self, what, ...) local v,r,obj,w obj,w = stead.ref(self.where):srch(what); if not obj then return nil, false; end v,r = stead.call(stead.ref(obj), 'tak', ...); if v and r ~= false then take(obj, w); end return v; end stead.player_use = function(self, what, onwhat, ...) local obj, obj2, v, vv, r; local scene_use_mode = false obj = self:srch(what); -- in inv? if not obj then -- no obj = stead.ref(self.where):srch(what); -- in scene? if not obj then -- no! return game.err, false; end scene_use_mode = true -- scene_use_mode! end if onwhat == nil then -- only one? if scene_use_mode then return self:action(what, ...); -- call act else v, r = stead.call(stead.ref(obj),'inv', ...); -- call inv end if not v and r ~= true then v, r = stead.call(game, 'inv', obj, ...); end return v, r; end obj2 = stead.ref(self.where):srch(onwhat); -- in scene? if not obj2 then obj2 = self:srch(onwhat); -- in inv? end if not obj2 or obj2 == obj then return game.err, false; end if not scene_use_mode or isSceneUse(stead.ref(obj)) then v, r = stead.call(stead.ref(obj), 'use', obj2, ...); if r ~= false then vv = stead.call(stead.ref(obj2), 'used', obj, ...); end end if not v and not vv then v, r = stead.call(game, 'use', obj, obj2, ...); end return stead.par(stead.space_delim, v, vv); end stead.player_back = function(self) local where = stead.ref(self.where); if where == nil then return nil,false end return stead.go(self, where.__from__, true); end stead.go = function(self, where, back) local was = self.where; local need_scene = false; local ret if not stead.in_walk_call then ret = function(rc) stead.in_walk_call = false return nil end else ret = function(rc) return rc end end stead.in_walk_call = true if where == nil then return nil,ret(false) end if not isRoom(stead.ref(where)) then error ("Trying to go nowhere: "..where, 2); end if not isRoom(stead.ref(self.where)) then error ("Trying to go from nowhere: "..self.where, 2); end if stead.in_entered_call or stead.in_onexit_call then error ("Do not use walk from onexit/entered action! Use exit/enter action instead:" .. self.where, 2); end local v, r; if not isVroom(stead.ref(where)) and not stead.in_exit_call then stead.in_exit_call = true -- to break recurse v,r = stead.call(stead.ref(self.where), 'exit', where); stead.in_exit_call = nil if r == false then return v, ret(r) end end local res = v; v = nil; if not back or not isDialog(stead.ref(self.where)) or isDialog(stead.ref(where)) then v, r = stead.call(stead.ref(where), 'enter', self.where); if r == false then return v, ret(r) end need_scene = true; if stead.ref(was) ~= stead.ref(self.where) then -- jump !!! where = stead.deref(self.where); need_scene = false; end end res = stead.par(stead.scene_delim, res, v); if not back then stead.ref(where).__from__ = stead.deref(self.where); end self.where = stead.deref(where); ret(); stead.rawset(_G, 'PLAYER_MOVED', true) if need_scene then -- or isForcedsc(stead.ref(where)) then -- i'am not sure... return stead.par(stead.scene_delim, res, stead.ref(where):scene()); end return res; end stead.player_walk = function(self, where, ...) local v, r = stead.go(self, where, ...); return v, r; end stead.player_go = function(self, where) local w = stead.ref(self.where).way:srch(where); if not w then return nil,false end local v, r = stead.go(self, w, false); return v, r; end stead.player_save = function(self, name, h) h:write(stead.string.format('%s.where = %q;\n', stead.tostr(name), stead.deref(self.where))); stead.savemembers(h, self, name, false); end function player(v) if v.nam == nil then error ("No player name in constructor.", 2); end if v.where == nil then v.where = 'main'; end if v.tag == nil then v.tag = stead.player_tagall; end if v.walk == nil then v.walk = stead.player_walk; end if v.go == nil then v.go = stead.player_go; end if v.ways == nil then v.ways = stead.player_ways; end if v.back == nil then v.back = stead.player_back; end if v.look == nil then v.look = stead.player_look; end if v.inv == nil then v.inv = stead.player_inv; end if v.use == nil then v.use = stead.player_use; end if v.action == nil then v.action = stead.player_action; end if v.save == nil then v.save = stead.player_save; end if v.objs == nil then v.objs = stead.player_objs; end v.player_type = true; return obj(v); end stead.game_life = function(self) local av, v stead.in_life_call = true; stead.in_life_move = false stead.lifes_op = {}; -- lifes to on/off stead.PLAYER_MOVED = stead.rawget(_G, 'PLAYER_MOVED') for i, o in stead.opairs(self.lifes) do local vv local pre o = stead.ref(o); if not isDisabled(o) then stead.rawset(_G, 'PLAYER_MOVED', false) vv,pre = stead.call(o, 'life'); if stead.rawget(_G, 'PLAYER_MOVED') then -- clear life output, but not current av = nil v = nil stead.in_life_move = true stead.rawset(_G, 'ACTION_TEXT', vv); elseif pre then av = stead.par(stead.space_delim, av, vv); else v = stead.par(stead.space_delim, v, vv); end end end stead.rawset(_G, 'PLAYER_MOVED', stead.in_life_move) if not stead.rawget(_G, 'PLAYER_MOVED') then stead.rawset(_G, 'PLAYER_MOVED', stead.PLAYER_MOVED) end stead.PLAYER_MOVED = nil stead.in_life_call = false; for i,o in stead.ipairs(stead.lifes_op) do if o[1] then stead.lifeon(o[2], o[3]); else stead.lifeoff(o[2]); end end stead.lifes_op = nil; return v, av; end stead.player_moved = function() return stead.rawget(_G, 'PLAYER_MOVED') or stead.PLAYER_MOVED end stead.life_moved = function() return stead.in_life_move end stead.check_list = function(k, v, p) if v.check == nil or not v:check(stead.string.format("%s[%q]", p, k)) then error ("error in list: "..stead.object..'.'..k); end end stead.check_room = function(k, v) if v.obj == nil then error("no obj in room:"..k); end if v.way == nil then error("no way in room:"..k); end end stead.check_player = function(k, v) v.where = stead.deref(v.where); end stead.check_object = function(k, v) if not v.nam then error ("No name in "..k); end if isRoom(v) then stead.check_room(k, v); end if isPlayer(v) then stead.check_player(k, v); end for_each(v, k, stead.check_list, isList, stead.deref(v)) end function for_everything(f, ...) local is_ok = function(s) return true end for_each(_G, '_G', f, is_ok, ...) end local compat_api = function() if stead.compat_api then return end if not stead.api_atleast(1, 6, 0) then if not stead.rawget(_G, 'go') then go = stead.go end if not stead.rawget(_G, 'goin') then goin = walkin end if not stead.rawget(_G, 'goout') then goout = walkout end if not stead.rawget(_G, 'goback') then goback = walkback end if not stead.rawget(_G, "goto") then if _VERSION == "Lua 5.1" then -- 5.1 lua stead.rawset(_G, "goto", walk) end end end if not stead.api_atleast(1, 7, 1) then if not stead.rawget(_G, 'goin') then goin = function() error ("Please use 'walkin' instead 'goin'.", 2) end end if not stead.rawget(_G, 'goout') then goout = function() error ("Please use 'walkout' instead 'goout'.", 2) end end if not stead.rawget(_G, 'goback') then goback = function() error ("Please use 'walkback' instead 'goback'.", 2) end end if not stead.rawget(_G, "goto") then if _VERSION == "Lua 5.1" then -- 5.1 lua stead.rawset(_G, "goto", function() error ("Please use 'walk' instead 'goto'.", 2) end) end end get_savepath = instead_savepath get_gamepath = instead_gamepath get_steadpath = instead_steadpath get_gamespath = instead_gamespath menu_toggle = instead_menu_toggle readdir = instead_readdir call = stead.call call_bool = stead.call_bool call_value = stead.call_value get_title = stead.get_title get_picture = stead.get_picture get_inv = stead.get_inv get_ways = stead.get_ways get_autosave = stead.get_autosave fmt = stead.fmt obj_tag = stead.obj_tag module_init = stead.module_init player_inv = stead.player_inv dialog_enter = stead.dialog_enter end if not stead.api_atleast(1, 4, 5) then stead.xref = function(...) return xref(...); end -- internals of call cctx = stead.cctx callpush = stead.callpush callpop = stead.callpop clearargs = stead.clearargs -- saving savemembers = stead.savemembers; savevar = stead.savevar clearvar = stead.clearvar end stead.compat_api = true end stead.do_ini = function(self, load) local v = '' local vv local function call_key(k, o) o.key_name = k; end local function call_codekey(k, o) stead.functions[o].key_name = k; end local function call_ini(k, o, ...) v = stead.par('', v, stead.call(o, 'ini', ...)); end stead.math.randomseed(stead.os.time(stead.os.date("*t"))) stead.rnd(1); stead.rnd(2); stead.rnd(3); -- Lua bug? if stead.type(game) ~= 'table' then error ("No valid 'game' object."); end if not isPlayer(stead.me()) then error ("No valid player."); end if not isRoom(stead.here()) then error ("No valid room."); end game.pl = stead.deref(game.pl); stead.me().where = stead.deref(stead.me().where); -- game.where = stead.deref(game.where); for i, f in ipairs(stead.modules_start) do f(load) end if not load then compat_api() for_everything(function(k, s) if isObject(s) then call_key(k, s) elseif isCode(s) then call_codekey(k, s) end end) for_each_object(stead.check_object); call_key("game", game); for_each(game, "game", stead.check_list, isList, stead.deref(game)) end for_each_object(call_ini, load); stead.me():tag(); stead.initialized = true return v end stead.game_ini = function(self) local v,vv v = stead.do_ini(self); vv = iface:title(stead.call(self,'nam')); vv = stead.par(stead.scene_delim, vv, stead.call(self,'dsc')); if stead.type(stead.rawget(_G, 'init')) == 'function' then init(); end return stead:fmt(stead.par(stead.scene_delim, vv, v)); end stead.game_start = function(s) if stead.type(stead.rawget(_G, 'start')) == 'function' then start() -- start function end stead.started = true if not s.showlast then stead.last_disp(false) end return stead.cat('', stead.last_disp()) end function game(v) if v.nam == nil then error ("No game name in constructor.", 2); end if v.pl == nil then v.pl = 'player'; end if v.ini == nil then v.ini = stead.game_ini; end if v.start == nil then v.start = stead.game_start end if v.save == nil then v.save = stead.game_save; end if v.load == nil then v.load = stead.game_load; end if v.life == nil then v.life = stead.game_life; end if v.step == nil then v.step = stead.game_step; end if v.lifes == nil then v.lifes = {}; end v.lifes = list(v.lifes); v._time = 0; v._running = true; v.game_type = true; return v; end function live(v) return stead.ref(game.lifes:srch(v)); end function isEnableSave() if game.enable_save == nil or stead.get_autosave() then return true end return stead.call_bool(game, 'enable_save'); end function isEnableAutosave() if game.enable_autosave == nil then return true end return stead.call_bool(game, 'enable_autosave'); end function for_each(o, n, f, fv, ...) local call_list = {} if stead.type(o) ~= 'table' then return end stead.object = n; for k, v in stead.pairs(o) do if v ~= _G and fv(v) then stead.table.insert(call_list, { k = k, v = v }); end end for k, v in stead.ipairs(call_list) do f(v.k, v.v, ...); end end function isCode(s) return stead.type(s) == 'function' and stead.type(stead.functions[s]) == 'table' end function for_each_codeblock(f,...) for_each(_G, '_G', f, isCode, ...) end function for_each_object(f,...) for_each(_G, '_G', f, isObject, ...) end function for_each_player(f,...) for_each(_G, '_G', f, isPlayer, ...) end function for_each_room(f,...) for_each(_G, '_G', f, isRoom, ...) end function for_each_list(f,...) for_each(_G, '_G', f, isList, ...) end stead.clearvar = function(v) for k, o in stead.pairs(v) do if stead.type(o) == 'table' and o ~= _G and o.__visited__ ~= nil then o.__visited__ = nil o.auto_saved = nil stead.clearvar(o) end end end stead.savemembers = function(h, self, name, need) for k, v in stead.pairs(self) do local need2 if k ~= "__visited__" then need2 = false if isForSave(k, v, self) then need2 = true; end if stead.type(k) == 'string' then stead.savevar(h, v, name..'['..stead.string.format("%q",k)..']', need or need2); elseif stead.type(k) == 'number' then stead.savevar(h, v, name.."["..k.."]", need or need2) elseif stead.type(k) == 'table' and stead.type(k.key_name) == 'string' then stead.savevar(h, v, name.."["..k.key_name.."]", need or need2) end end end end -- savemembers = stead.savemembers; stead.savevar = function(h, v, n, need) local r,f if v == nil or stead.type(v) == "userdata" or stead.type(v) == "function" then if isCode(v) and need then if stead.type(stead.functions[v].key_name) == 'string' and stead.functions[v].key_name ~= n then h:write(stead.string.format("%s=%s\n", n, stead.functions[v].key_name)) else h:write(stead.string.format("%s=code %q\n", n, stead.functions[v].code)) end end -- if need then -- error ("Variable "..n.." can not be saved!"); -- end return end -- if stead.string.find(n, '_') == 1 or stead.string.match(n,'^%u') then -- need = true; -- end if stead.type(v) == "string" then if not need then return end h:write(stead.string.format("%s=%q\n",n,v)) return; end if stead.type(v) == "table" then if v == _G then return end if stead.type(v.key_name) == 'string' and v.key_name ~= n then -- just xref if v.auto_allocated and not v.auto_saved then v:save(v.key_name, h, false, true); -- here todo end if need then if stead.ref(v.key_name) == nil then v.key_name = 'null' end h:write(stead.string.format("%s = %s\n", n, v.key_name)); end return end if v.__visited__ ~= nil then return end v.__visited__ = n; if stead.type(v.save) == 'function' then v:save(n, h, need); return; end if need then h:write(n.." = {};\n"); end stead.savemembers(h, v, n, need); return; end if not need then return end h:write(n, " = ",tostring(v)) h:write("\n") end -- savevar = stead.savevar stead.gamereset = function(file, forget) stead.clearargs() if stead.api_atleast(2, 2, 0) then init = function() -- init called only once end end if forget then stead:done(); stead.rawset(_G, 'init', function() -- null init function end) stead.rawset(_G, 'start', function() -- null start function end) for_each_object(function(k, o) -- destroy all objects if o.system_type then return end stead.rawset(_G, k, nil) end); game._scripts = { } game.lifes:zap() game.scriptsforget = true stead.collectgarbage() -- anything else? stead:init(); end dofile(file); game:ini(); if #game._scripts == 0 or file ~= game._scripts[#game._scripts] then if #game._scripts ~= 0 or file ~= 'main.lua' then stead.table.insert(game._scripts, file); end end end stead.gamefile = function(file, forget) stead.gamereset(file, forget) if forget then game:start() return stead.walk(stead.here(), false, false, true); end end stead.do_savegame = function(s, h) stead.busy(true) local function save_object(key, value, h) stead.busy(true) stead.savevar(h, value, key, false); end local function save_var(key, value, h) stead.busy(true) stead.savevar(h, value, key, isForSave(key, value, _G)) end local forget = game.scriptsforget for i, v in stead.ipairs(s._scripts) do h:write(stead.string.format("stead.gamereset(%q,%s)\n", v, stead.tostr(forget))) forget = nil end save_object('allocator', allocator, h); -- always first! for_each_object(save_object, h); save_object('game', s, h); for_everything(save_var, h); -- save_object('_G', _G, h); stead.clearvar(_G); stead.busy(false) end stead.savename = function() return stead.call(stead.here(), 'nam'); end stead.game_save = function(self, name, file) local h; if file ~= nil then file:write(stead.string.format("%s.pl = %q\n", name, stead.deref(self.pl))); stead.savemembers(file, self, name, false); return nil, true end if not isEnableSave() then return nil, false end if name == nil then return nil, false end h = stead.io.open(name .. '.tmp', "wb"); if not h then return nil, false end local n if stead.type(stead.savename) == 'function' then n = stead.savename() end if stead.type(n) == 'string' and n ~= "" then h:write("-- $Name: "..n:gsub("\n","\\n").."$\n"); end stead.do_savegame(self, h); h:flush(); h:close(); stead.os.remove(name); stead.os.rename(name .. '.tmp', name); game.autosave = false; -- we have only one try for autosave stead.restart_game = false return nil; end stead.game_load = function(self, name) if name == nil then return nil, false end if stead.started then stead.gamereset('main.lua', true) end local f, err = loadfile(name); if f then local i,r = f(); if r then return nil, false end i, r = stead.do_ini(self, true); if not stead.started then i, r = game:start() end return i, r end return nil, false end stead.game_step = function(self) self._time = self._time + 1; return self:life(self); end game = game { codepage = "UTF-8"; nam = [[INSTEAD -- Simple Text Adventure interpreter v]]..stead.version..[[ '2009-2020 by Peter Kosyh]]; dsc = [[ Commands:^ look(or just enter), act (or just what), use [on what], go ,^ back, inv, way, obj, quit, save , load .]]; pl ='pl'; showlast = true; _scripts = {}; }; stead.strip = function(s) local s = stead.tostr(s); s = stead.string.gsub(s, '^[ \t]*', ''); s = stead.string.gsub(s, '[ \t]*$', ''); return s; end function isForcedsc(v) local r,g r = stead.call_bool(v, 'forcedsc'); if r then return true end g = stead.call_bool(game, 'forcedsc', v); return g and r ~= false end function isSceneUse(v) local o,g o = stead.call_bool(v, 'scene_use'); if o then return true end g = stead.call_bool(game, 'scene_use', v); return g and o ~= false end iface = { anchor = function(self) return ''; end; img = function(self, str) return ''; end, nb = function(self, str) return str; end, em = function(self, str) return str; end, right = function(self, str) return str; end, left = function(self, str) return str; end, center = function(self, str) return str; end, just = function(self, str) return str; end, top = function(self, str) return str; end, bottom = function(self, str) return str; end, middle = function(self, str) return str; end, tab = function(self, str, al) return ''; end; bold = function(self, str) return str; end, under = function(self, str) return str; end, st = function(self, str) return str; end, enum = function(self, n, str) return n..' - '..str; end, xref = function(self, str, obj) local o = stead.ref(stead.here():srch(obj)); if not o then o = stead.ref(ways():srch(obj)); end if not o then o = stead.ref(stead.me():srch(obj)); end if not o or not o.id then return str; end local n = stead.tonum(stead.nameof(o)) return stead.cat(str, "("..stead.tostr(n or o.id)..")"); end, title = function(self, str) return "["..str.."]"; end, objs = function(self, str) return str; end, ways = function(self, str) return str; end, inv = function(self, str) return str; end, text = function(self, str) if str then print(str); end end, fmt = function(self, cmd, st, moved, r, av, objs, pv) -- st -- changed state (main win), move -- loc changed local l, vv if st and not moved then if cmd ~= 'look' then av = txtem(av); pv = txtem(pv); r = txtem(r); if isForcedsc(stead.here()) then l = stead.me():look(); end end end vv = stead.fmt(stead.cat(stead.par(stead.scene_delim, l, r, av, objs, pv), '^')); return vv end, cmd = function(self, inp) local r, v; v = false stead.state = false; -- changed state (main screen) local a = { }; local cmd; stead.rawset(_G, 'RAW_TEXT', nil) stead.rawset(_G, 'PLAYER_MOVED', nil) stead.cache = {} cmd, a = stead.getcmd(inp); for i, f in ipairs(stead.modules_cmd) do local r, v = f(cmd, stead.unpack(a)) if r ~= nil or v ~= nil then return r, v end end if cmd == '' then cmd = 'look' end -- stead.me():tag(); local oldloc = stead.here(); if cmd == 'look' then stead.state = true r, v = stead.me():look(); elseif cmd == 'obj' then r, v = stead.me():objs(); elseif cmd == 'inv' then r, v = stead.me():inv(); elseif cmd == 'way' then r, v = stead.me():ways(); elseif cmd == 'ls' then r = stead.par(stead.scene_delim, stead.me():objs(), stead.me():inv(), stead.me():ways()); v = nil; elseif cmd == 'go' then stead.state = true r, v = stead.me():go(stead.unpack(a)); elseif cmd == 'back' then stead.state = true r, v = stead.me():go(stead.from()); elseif cmd == 'act' then stead.state = true r, v = stead.me():action(stead.unpack(a)); elseif cmd == 'use' then stead.state = true r, v = stead.me():use(stead.unpack(a)); elseif cmd == 'save' then r, v = game:save(stead.unpack(a)); elseif cmd == 'load' then r, v = game:load(stead.unpack(a)); if v ~= false and game.showlast then return r; end elseif cmd == 'wait' then -- nothing todo in game, skip tick v = nil; r = true; stead.state = true elseif cmd == 'nop' then -- inv only v = true; r = nil; stead.state = true else stead.state = true r, v = stead.me():action(cmd, stead.unpack(a)); end -- here r is action result, v - ret code value -- state -- game state changed if stead.state and r == nil and v == true then -- we do nothing return nil, true; -- menu end if stead.state and r == nil and v == nil and stead.api_atleast(1, 3, 5) then -- new goto return nil, false -- really nothing end if stead.rawget(_G, 'RAW_TEXT') and v ~= false then return stead.cat(r, '\n'), true; end if v == false then return stead.cat(r, '\n'), false; end stead.rawset(_G, 'ACTION_TEXT', r); -- here, life methods can redefine this local av, pv -- av -- active lifes, pv -- background local vv if stead.state then pv,av = game:step(); stead.me():tag(); vv = stead.here():look(); end vv = self:fmt(cmd, stead.state, (oldloc ~= stead.here()) or stead.player_moved(), stead.act_text(), av, vv, pv); if stead.state then stead.last_disp(vv or false) stead.last_act(stead.act_text()) end if vv == nil then -- nil is error vv = '' end return vv, true; -- action is here end, shell = function(self) local inp, i, k, cmd, a, n; stead.me():tag(); while game._running do inp = stead.io.read("*l"); if inp == 'quit' then break; end self:text(self:cmd(inp)); end end }; function me() return stead.ref(game.pl); end stead.me = me function where(s) if not isObject(stead.ref(s)) then error("Wrong parameter to where.", 2); end if isPlayer(stead.ref(s)) then return stead.ref(stead.ref(s).where); end return stead.ref(stead.ref(s).__where__); end function here() return stead.ref(stead.me().where); end stead.here = here function from(w) if w == nil then w = stead.here(); else w = stead.ref(w); end return stead.ref(w.__from__); end stead.from = from stead.time = function(s) local n = game._time; if stead.type(s) == 'number' then game._time = s end return n end function inv() return stead.me().obj; end function objs(w) if not w then return stead.here().obj; else return stead.ref(w).obj; end end function ways(w) if not w then return stead.here().way; else return stead.ref(w).way; end end stead.xref = function(str, obj, ...) if stead.type(str) ~= 'string' then return nil; end; return iface:xref(str, obj, ...); end xref = stead.xref function pseen(...) if not isDialog(stead.here()) then return end return stead.here():pseen(...); end function punseen(...) if not isDialog(stead.here()) then return end return stead.here():punseen(...); end function pon(...) if not isDialog(stead.here()) then return end stead.here():pon(...); end function poff(...) if not isDialog(stead.here()) then return end stead.here():poff(...); end function prem(...) if not isDialog(stead.here()) then return end stead.here():prem(...); end function lifeon(what, nr) if stead.in_life_call then stead.table.insert(stead.lifes_op, { true, what, nr }); return end game.lifes:add(what, nr); end stead.lifeon = lifeon function lifeoff(what) if stead.in_life_call then stead.table.insert(stead.lifes_op, { false, what }); return end game.lifes:del(what); end stead.lifeoff = lifeoff stead.allocator_save = function(s, name, h, need, auto) if s.auto_allocated and not auto then return end if need then if s.auto_allocated then -- in current realization always false local m = stead.string.format("allocator:new(%s, %s)\n", stead.tostring(s.constructor), stead.tostring(s.constructor)); h:write(m); else local m = stead.string.format(" = allocator:get(%s, %s)\n", stead.tostring(name), stead.tostring(s.constructor)); h:write(name..m); if stead.api_atleast(1, 3, 0) then m = stead.string.format("stead.check_object(%s, %s)\n", stead.tostring(name), name); h:write(m); end end end stead.savemembers(h, s, name, false); if s.auto_allocated then s.auto_saved = true end end function new(str) if stead.type(str) ~= 'string' then error("Non string constructor in new.", 2); end return allocator:new(str); end function delete(v) allocator:delete(v); end stead.vobj_save = function(self, name, h, need) local dsc = self.dsc; local w = stead.deref(self.where); if need then h:write(stead.string.format("%s = vobj(%s, %s, %s, %s);\n", name, stead.tostring(self.key), stead.tostring(self.nam), stead.tostring(dsc), stead.tostring(w))); end stead.savemembers(h, self, name,false); end stead.vobj_act = function(self, ...) local o, r = stead.here():srch(self); -- self.nam if stead.ref(o) and stead.ref(o).where then return stead.walk(stead.ref(o).where); end return stead.call(stead.ref(r),'act', self.key, ...); end stead.vobj_used = function(self, ...) local o, r = stead.here():srch(self.nam); return stead.call(stead.ref(r),'used', self.key, ...); end function vobj(key, name, dsc, w) if not stead.tonum(key) then error ("vobj key must be number!", 2); end return obj{ key = key, nam = name, dsc = dsc, where = stead.deref(w), act = stead.vobj_act, used = stead.vobj_used, save = stead.vobj_save, obj = list({}) }; end function vway(name, dsc, w) return obj{ key = -1, nam = name, dsc = dsc, act = stead.vobj_act, where = stead.deref(w), used = stead.vobj_used, save = stead.vobj_save, obj = list({}), }; end stead.vroom_save = function(self, name, h, need) if need then local t = stead.string.format("%s = vroom(%s, %q);\n", name, stead.tostring(self.nam), stead.deref(self.where)) h:write(t); end stead.savemembers(h, self, name,false); end stead.vroom_enter = function(self, ...) return stead.walk(self.where); end function isVroom(v) return (stead.type(v) == 'table') and (v.vroom_type) end function vroom(name, w) if w == nil then error("Wrong parameter to vroom.", 2); end return room { vroom_type = true, nam = name, where = stead.deref(w), enter = stead.vroom_enter, save = stead.vroom_save, }; end function walk(what) local v,r=stead.me():walk(what); stead.me():tag(); return v,r; end stead.walk = walk; function back() return stead.me():back(); end stead.back = back; stead.rnd = function(...) if stead.random then return stead.random(...) end return stead.math.random(...); end stead.rndseed = function(...) if stead.randomseed then return stead.randomseed(...) end stead.math.randomseed(...) end function taken(obj) if isObject(stead.ref(obj)) and stead.ref(obj)._taken then return true end return false; end function remove(obj, from) local o,w from = stead.ref(from) if from then if isList(from) then return from:del(obj) end o,w = from:srch(obj); else o,w = stead.here():srch(obj); end if w then stead.ref(w).obj:del(obj); end o = stead.ref(o); if not isObject(o) then o = stead.ref(obj); end if isObject(o) then o.__where__ = nil; end return o end stead.remove = remove function purge(obj, from) local o,w from = stead.ref(from) if from then if isList(from) then return from:purge(obj) end o,w = from:srch(obj, true); else o,w = stead.here():srch(obj, true); end if w then stead.ref(w).obj:purge(obj); end o = stead.ref(o); if not isObject(o) then o = stead.ref(obj); end if isObject(o) then o.__where__ = nil; end return o end stead.purge = purge function taketo(obj, wh, pos) local o = remove(obj, wh); if not isObject(o) then error ("Trying to take wrong object.", 2); end inv():add(obj, pos); o._taken = true wh = stead.deref(stead.me()) if stead.type(wh) == 'string' then o.__where__ = wh; end return o end function take(obj, wh) return taketo(obj, wh); end function takef(obj, wh) return taketo(obj, wh, 1); end function putto(obj, w, pos) local wh local o = stead.ref(obj); if not isObject(o) then error ("Trying to put wrong object.", 2); end if not w then wh = stead.deref(stead.here()); w = stead.here(); else wh = stead.deref(w); w = stead.ref(w); end if isList(w) then w:add(obj, pos); else w.obj:add(obj, pos); end if stead.type(wh) == 'string' then o.__where__ = wh; end return o; end function put(obj, w) return stead.placeto(obj, w); end function putf(obj, w) return stead.placeto(obj, w, 1); end place = put placef = putf placeto = putto stead.placeto = placeto function replace(obj, obj2, from) local o,w,i if not isObject(stead.ref(obj2)) then error ("Wrong parameter to replace.", 2); end from = stead.ref(from) if from then if isList(from) then from:replace(obj, obj2); return stead.ref(obj) end o,w = from:srch(obj); else o,w = stead.here():srch(obj); end if w then stead.ref(w).obj:replace(o, obj2); stead.ref(obj2).__where__ = stead.deref(w); else stead.placeto(obj2, from); end o = stead.ref(o); if not isObject(o) then o = stead.ref(obj); end if isObject(o) then o.__where__ = nil; end return o; end function drop(obj, w) local o = put(obj, w); if not isObject(o) then error ("Trying to drop wrong object.", 2); end inv():del(obj); o._taken = false return o; end function dropf(obj, w) local o = putf(obj, w); if not isObject(o) then error ("Trying to dropf wrong object.", 2); end inv():del(obj); o._taken = false return o; end function dropto(obj, w, pos) local o = putto(obj, w, pos); if not isObject(o) then error ("Trying to dropto wrong object.", 2); end inv():del(obj); o._taken = false return o; end function seen(obj, wh) if not wh then wh = stead.here(); else wh = stead.ref(wh); end local o,w = wh:srch(obj); o = stead.ref(o); if isObject(o) then return o,w end return nil end function exist(obj, wh) if not wh then wh = stead.here(); else wh = stead.ref(wh); end local o,w = wh:srch(obj, true); o = stead.ref(o); if isObject(o) then return o,w end return nil end function have(obj) local o = inv():srch(obj); o = stead.ref(o); if isObject(o) then return o end return nil end function moveto(obj, there, from, pos) stead.remove(obj, from); stead.placeto(obj, there, pos); return stead.ref(obj); end stead.moveto = moveto function move(obj, there, from) return stead.moveto(obj, there, from); end function movef(obj, there, from) return stead.moveto(obj, there, from, 1); end stead.cacheable = function(n, f) return function(...) local s = stead.cache[n] if s ~= nil then if s == -1 then s = nil end return s end stead.cache[n] = -1 s = f(...) if s ~= nil then stead.cache[n] = s end return s end end stead.get_picture = stead.cacheable('pic', function() local s = stead.call(stead.here(), 'pic'); if not s then s = stead.call(game, 'pic'); end return s; end) stead.get_title = stead.cacheable('title', function() local s = stead.call(stead.here(), 'nam'); return s; end) if instead_savepath == nil then function instead_savepath() return "./" end end function autosave(slot) game.autosave = true; game.autosave_slot = slot; end stead.autosave = autosave; stead.get_restart = function() return stead.restart_game end stead.get_menu = function() local n = stead.need_menu stead.need_menu = nil return n end stead.restart = function() stead.restart_game = true end stead.get_autosave = function() return game.autosave, game.autosave_slot end function change_pl(p) local o = stead.ref(p); if stead.type(stead.deref(p)) ~= 'string' or not o then error ("Wrong player name in change_pl...", 2); end game.pl = stead.deref(p); return stead.walk(o.where, false, true, true); -- no call enter/exit end function disabled(o) return isDisabled(stead.ref(o)) end function disable(o) o = stead.ref(o) if isObject(o) then o:disable() end return o end function enable(o) o = stead.ref(o) if isObject(o) then o:enable() end return o end function disable_all(o) o = stead.ref(o) if isObject(o) or isList(o) then o:disable_all() end return o end function enable_all(o) o = stead.ref(o) if isObject(o) or isList(o) then o:enable_all() end return o end function isForSave(k, v, s) -- k - key, v - value, s -- parent table if stead.type(k) == 'function' then return false end if stead.type(v) == 'function' or stead.type(v) == 'userdata' then return false end return stead.string.find(k, '_') == 1 or stead.string.match(k,'^%u') end stead.inherit = function(o, f) return function(...) return f(o(...)) end end inherit = stead.inherit stead.hook = function(o, f) return function(...) local ff if stead.type(o) ~= 'function' then ff = function(s) return o; end else ff = o end return f(ff, ...) end end hook = stead.hook function nameof(v) if isObject(v) then local r = stead.call(v, 'nam'); return r end end stead.nameof = nameof stead.dispof = function(v) if isObject(v) then local r if game.gui then r = stead.call(v, 'disp') end if r == nil then r = stead.call(v, 'nam'); end return r end end function stead_version(v) if not stead.tostr(v) then return end stead.version_table = {} stead.api_version_table = {} for n in stead.string.gmatch(stead.version, "[0-9]+") do stead.table.insert(stead.version_table, stead.tonum(n)) end for n in stead.string.gmatch(v, "[0-9]+") do stead.table.insert(stead.api_version_table, stead.tonum(n)) end if not stead.atleast(stead.unpack(stead.api_version_table)) then error ([[The game requires instead engine of version ]] ..v.. [[ or higher. https://instead-hub.github.io]], 2) end stead.api_version = v if stead.api_atleast(1, 2, 0) then require ("walk") require ("vars") require ("object") end if stead.api_atleast(1, 6, 3) then require ("dlg") end end instead_version = stead_version function code(v) local f = stead.eval(v) if not f then error ("Wrong script: "..stead.tostr(v), 2); end stead.functions[f] = { f = f, code = v }; return f; end stead.code = code --- here the game begins stead.objects = { null = obj { nam = 'null'; }; allocator = function() return obj { nam = 'allocator', get = function(s, n, c) if isObject(stead.ref(n)) and stead.api_atleast(1, 3, 0) then -- static? return stead.ref(n); end local v = stead.ref(c); if not v then error ("Null object in allocator: "..stead.tostr(c)); end v.key_name = n; v.save = stead.allocator_save; v.constructor = c; return v end, delete = function(s, w) w = stead.ref(w); if stead.type(w.key_name) ~= 'string' then return end local f = stead.eval(w.key_name..'= nil;'); if f then f(); end end, new = function(s, n, key) local v = stead.ref(n); if stead.type(v) ~= 'table' or stead.type(n) ~= 'string' then error ("Error in new.", 2); end v.save = stead.allocator_save; v.constructor = n; if key then s.objects[key] = v v.key_name = stead.string.format('allocator["objects"][%s]', stead.tostring(key)); else local nm = #s.objects + 1 -- here is new index stead.table.insert(s.objects, v); v.key_name = 'allocator["objects"]['..stead.tostr(nm)..']'; end if stead.api_atleast(1, 3, 0) then stead.check_object(v.key_name, v) end return v end, objects = { save = function(self, name, h, need) stead.savemembers(h, self, name, true); end, }, }; end; pl = function() return player { nam = "Incognito", where = 'main', obj = { } }; end; main = function() return room { nam = 'main', dsc = 'No main room defined.', }; end; } stead.sandbox = function() if STANDALONE then return end -- sandbox -- local check_path = function(realpath, type, find, gsub, savepath, gamepath, path) if not path then return false end path = realpath(path) if not path then return false end local spath = realpath(savepath) if not spath then return false end local s = find(path, spath..'/', 1, true) if s ~= 1 then spath = realpath(gamepath); if spath then s = find(path, spath..'/', 1, true) end end if s ~= 1 then return false end return true end local build_sandbox_open = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(io.open, function(f, path, acc, ...) if type(acc) ~= 'string' or not find(acc, "[aw+]") then -- only write access return f(path, acc, ...) end if not check_path(realpath, type, find, gsub, savepath, gamepath, path) then error ("Access denied (write): ".. path, 3); return false end return f(path, acc, ...) end) end local build_sandbox_remove = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(os.remove, function(f, path, ...) if type(path) ~= 'string' then return f(path, ...) end if not check_path(realpath, type, find, gsub, savepath, gamepath, path) then error ("Access denied (remove): ".. path, 3); return false end return f(path, ...) end) end local build_sandbox_rename = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(os.rename, function(f, oldname, newname, ...) if not check_path(realpath, type, find, gsub, savepath, gamepath, oldname) or not check_path(realpath, type, find, gsub, savepath, gamepath, newname) then error ("Access denied (rename): ".. oldname .. ', '.. newname, 3); return false end return f(oldname, newname, ...) end) end local build_sandbox_output = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(io.output, function(f, path, ...) if type(path) == 'string' and not check_path(realpath, type, find, gsub, savepath, gamepath, path) then error ("Access denied (output): ".. path, 3); return false end return f(path, ...) end) end local build_sandbox_load = function(eval, error, type, find) return stead.hook(eval, function(f, str, ...) if type(str) == 'string' and find(str, "\x1b", 1, true) == 1 then error ("Loading bytecode is forbidden!", 3) return false end return f(str, ...) end) end io.open = build_sandbox_open(instead_realpath, error, type, string.find, string.gsub, instead_savepath(), instead_gamepath()); os.remove = build_sandbox_remove(instead_realpath, error, type, string.find, string.gsub, instead_savepath(), instead_gamepath()); os.rename = build_sandbox_rename(instead_realpath, error, type, string.find, string.gsub, instead_savepath(), instead_gamepath()); io.output = build_sandbox_output(instead_realpath, error, type, string.find, string.gsub, instead_savepath(), instead_gamepath()); os.execute = function(s) print ("Warning: trying to do os.execute: "..s); end io.popen = function(s) print ("Warning: trying to do io.popen: "..s); end os.tmpname = function(s) print ("Warning: trying to do os.tmpname"); end if not DEBUG then debug = nil end if _VERSION == "Lua 5.1" then loadstring = build_sandbox_load(loadstring, error, type, string.find) stead.eval = loadstring else load = build_sandbox_load(load, error, type, string.find) stead.eval = load end package.cpath = "" package.preload = {} package = nil end -- end of sandbox -- stead.init = function(s) stead.initialized = false stead.started = false for k, v in pairs(stead.objects) do if type(v) == 'function' then stead.rawset(_G, k, v()) else stead.rawset(_G, k, v) end end s.functions = {} -- code blocks for k,v in stead.ipairs(s.modules_ini) do v(); end if stead.type(stead.sandbox) == 'function' then stead.sandbox() stead.sandbox = nil end end stead.done = function(s) for k, v in stead.ipairs(s.modules_done) do v(); end end ref = stead.ref deref = stead.deref pclr = stead.pclr pget = stead.pget p = stead.p pr = stead.pr pn = stead.pn par = stead.par cat = stead.cat player_moved = stead.player_moved rnd = stead.rnd; gamefile = stead.gamefile time = stead.time instead_version(stead.api_version) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/theme.lua000066400000000000000000000113511467622671600202000ustar00rootroot00000000000000theme = { nam = 'theme'; object_type = true; system_type = true; save = function(self, name, h, need) if self.name() ~= '.' then return end for k, v in stead.pairs(self.vars) do h:write(stead.string.format("theme.set(%q, %q);\n", k, v)) end end; reset = function(...) local a = {...}; for i = 1, stead.table.maxn(a) do local name = a[i] local v if name then v = theme.reset_vars[name] if v then instead_theme_var(name, v); theme.vars[name] = nil theme.reset_vars[name] = nil end end end end; set = function(name, val) if val and name then if not theme.reset_vars[name] then theme.reset_vars[name] = instead_theme_var(name) end instead_theme_var(name, stead.tostr(val)); theme.vars[name] = stead.tostr(val); end end; name = function(...) return instead_theme_name(...); end; get = function(...) return instead_theme_var(...); end; win = { reset = function() theme.reset("win.x", "win.y", "win.w", "win.h", "win.col.fg", "win.col.link", "win.col.alink", "win.fnt.name", "win.fnt.size", "win.fnt.height"); end; geom = function(x, y, w, h) theme.set("win.x", x); theme.set("win.y", y); theme.set("win.w", w); theme.set("win.h", h); end; color = function(fg, link, alink) theme.set("win.col.fg", fg); theme.set("win.col.link", link); theme.set("win.col.alink", alink); end; font = function(name, size, height) theme.set("win.fnt.name", name); theme.set("win.fnt.size", size); theme.set("win.fnt.height", height); end; gfx = { reset = function() theme.reset("win.gfx.up", "win.up.x", "win.up.y"); theme.reset("win.gfx.down", "win.down.x", "win.down.y"); end; up = function(pic, x, y) theme.set("win.gfx.up", pic); theme.set("win.up.x", x); theme.set("win.up.y", y); end; down = function(pic, x, y) theme.set("win.gfx.down", pic); theme.set("win.down.x", x); theme.set("win.down.y", y); end; }; }; inv = { reset = function() theme.reset("inv.x", "inv.y", "inv.w", "inv.h", "inv.col.fg", "inv.col.link", "inv.col.alink", "inv.fnt.name", "inv.fnt.size", "inv.fnt.height", "inv.mode"); end; geom = function(x, y, w, h) theme.set("inv.x", x); theme.set("inv.y", y); theme.set("inv.w", w); theme.set("inv.h", h); end; color = function(fg, link, alink) theme.set("inv.col.fg", fg); theme.set("inv.col.link", link); theme.set("inv.col.alink", alink); end; font = function(name, size, height) theme.set("inv.fnt.name", name); theme.set("inv.fnt.size", size); theme.set("inv.fnt.height", height); end; mode = function(mode) theme.set("inv.mode", mode); end; gfx = { reset = function() theme.reset("inv.gfx.up", "inv.up.x", "inv.up.y"); theme.reset("inv.gfx.down", "inv.down.x", "inv.down.y"); end; up = function(pic, x, y) theme.set("inv.gfx.up", pic); theme.set("inv.up.x", x); theme.set("inv.up.y", y); end; down = function(pic, x, y) theme.set("inv.gfx.down", pic); theme.set("inv.down.x", x); theme.set("inv.down.y", y); end; }; }; menu = { reset = function() theme.reset("menu.bw", "menu.col.fg", "menu.col.bg", "menu.col.alpha", "menu.col.link", "menu.col.alink", "menu.fnt.name", "menu.fnt.size", "menu.fnt.height"); end; bw = function(w) theme.set("menu.bw", w); end; color = function(fg, bg, alpha, link, alink) theme.set("menu.col.fg", fg); theme.set("menu.col.bg", bg); theme.set("menu.col.alpha", alpha); theme.set("menu.col.link", link); theme.set("menu.col.alink", alink); end; font = function(name, size, height) theme.set("menu.fnt.name", name); theme.set("menu.fnt.size", size); theme.set("menu.fnt.height", height); end; gfx = { reset = function() theme.reset("menu.gfx.button", "menu.button.x", "menu.button.y"); end; button = function(b, x, y) theme.set("menu.gfx.button", b); theme.set("menu.button.x", x); theme.set("menu.button.y", y); end; }; }; gfx = { reset = function() theme.reset("scr.gfx.cursor.normal", "scr.gfx.cursor.use", "scr.gfx.cursor.x", "scr.gfx.cursor.y", "scr.gfx.mode", "scr.gfx.pad", "scr.gfx.bg"); end; cursor = function(norm, use, x, y) theme.set("scr.gfx.cursor.normal", norm); theme.set("scr.gfx.cursor.use", use); theme.set("scr.gfx.cursor.x", x); theme.set("scr.gfx.cursor.y", y); end; mode = function(mode) theme.set("scr.gfx.mode", mode); end; pad = function(pad) theme.set("scr.gfx.pad", pad); end; bg = function(bg) theme.set("scr.gfx.bg", bg); end; }; snd = { reset = function() theme.reset("snd.click"); end; click = function(w) theme.set("snd.click", w); end } } theme.vars = {} theme.reset_vars = {} instead-3.5.2+dfsg/stead/stead2/timer.lua000066400000000000000000000007431467622671600202210ustar00rootroot00000000000000game.action = stead.hook(game.action, function(f, s, cmd, ...) if cmd == 'user_timer' then local r,v if stead.here().timer then r,v = stead.call(stead.here(), 'timer'); elseif s.timer then r,v = stead.call(s, 'timer'); end if r == nil and v == nil and not stead.api_atleast(1, 3, 5) then return nil, true end return r,v end return f(s, cmd, ...); end) stead.module_init(function() timer.callback = function(s) return 'user_timer' end end) -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/vars.lua000066400000000000000000000064541467622671600200610ustar00rootroot00000000000000local G = { } local function variables(g) if g == _G then return G.variables end if type(g) == 'table' then return g.variables end end local function variables_save(g) if g == _G then return G.variables_save end if type(g) == 'table' then return g.variables_save end end function isForSave(k, v, s) -- k - key, v - value, s -- parent table local i,o if stead.type(variables_save(s)) == 'table' and variables_save(s)[k] then return true end if stead.type(k) == 'function' then return false end if stead.type(v) == 'function' or stead.type(v) == 'userdata' then return false end if stead.type(k) ~= 'string' then return false end return stead.string.find(k, '_') == 1 end local function __vars_add(s, v, set) if not variables(s) then s.variables = {} end for k, o in stead.pairs(v) do if stead.tonum(k) then stead.table.insert(variables(s), o); elseif variables(s)[k] then error ("Variable overwrites variables object: "..stead.tostr(k)) elseif k ~= 'variable_type' then if set and not isObject(o) then if stead.rawget(s, k) then if s == _G then print ("Global variable '"..stead.tostr(k).."' conflicts with "..stead.type(stead.rawget(s, k))); else error ("Variable conflict: "..stead.tostr(k)); end end stead.table.insert(variables(s), k); stead.rawset(s, k, o) else variables(s)[k] = o end end end end local function __vars_fill(v) if stead.type(v) ~= 'table' then return end for k, o in stead.ipairs(v) do if stead.type(o) == 'table' and o.variable_type then __vars_add(v, o); stead.rawset(v, k, false) end end if stead.type(variables(v)) == 'table' then local vars = {} if v == _G then G.variables_save = {} else v.variables_save = {} end for k, o in stead.pairs(variables(v)) do if stead.tonum(k) and stead.type(o) == 'string' then stead.table.insert(vars, o) else if stead.rawget(v, k) then error ("Variable overwrites object property: "..stead.tostr(k)); end stead.rawset(v, k, o) stead.table.insert(vars, k); end end for k, o in stead.ipairs(vars) do variables_save(v)[o] = true end if v == _G then G.variables = vars; else v.variables = vars; end end end vars_object = obj { nam = 'vars', system_type = true, ini = function(s) __vars_fill(_G) __vars_fill(pl) __vars_fill(game) end } obj = stead.hook(obj, function(f, v, ...) __vars_fill(v) return f(v, ...) end) stead.add_var = function(s, v) if not v then v = s s = _G end if stead.type(v) ~= 'table' then error("Wrong parameter to stead.add_var."); end if not v.variable_type then v = var(v) end __vars_add(s, v, true) __vars_fill(s) end local function mod_init() if stead.type(variables(_G)) == 'table' then for k, v in stead.ipairs(variables(_G)) do stead.rawset(_G, v, nil) end end G.variables = {} G.variables_save = {} if not stead.api_atleast(2, 5, 0) then -- fake data stead.rawset(_G, 'variables_save', {}) -- to save broken saves stead.rawset(_G, 'variables', {}) end end stead.module_init(mod_init) stead.module_done(mod_init) function var(v) v.variable_type = true return v end function global(v) if stead.type(v) ~= 'table' then error("Wrong parameter to global.", 2); end __vars_add(_G, v, true); end -- require 'strict' -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/walk.lua000066400000000000000000000140571467622671600200420ustar00rootroot00000000000000local function onevent(ev, ...) local vv, r if stead.api_atleast(1, 6, 3) then vv, r = stead.call(game, ev, ...); if r == false then return vv, false end if vv == false then return nil, false end return vv end end local go = function (self, where, back, noenter, noexit, nodsc) local was = self.where; local need_scene = false; local ret if not stead.in_walk_call then ret = function(rc) stead.in_walk_call = false return nil end else ret = function(rc) return rc end end stead.in_walk_call = true if where == nil then return nil, ret(false) end if not isRoom(stead.ref(where)) then error ("Trying to go nowhere: "..where); end if not isRoom(stead.ref(self.where)) then error ("Trying to go from nowhere: "..self.where); end if stead.in_entered_call or stead.in_onexit_call then error ("Do not use walk from left/entered action! Use exit/enter action instead:" .. self.where); end local v, r, jump; if not isVroom(stead.ref(where)) and not stead.in_exit_call and not noexit then stead.in_exit_call = true -- to break recurse v,r = stead.call(stead.ref(self.where), 'exit', stead.ref(where)); stead.in_exit_call = nil if r == false or (stead.api_atleast(1, 3, 0) and v == false and r == nil) then return v, ret(r) end if stead.api_atleast(2, 4, 0) then jump = stead.rawget(_G, 'PLAYER_MOVED') else jump = (self.where ~= was) end if jump then where = stead.deref(self.where) -- jump end end local res = v; v = nil; if not isVroom(stead.ref(where)) then self.where = stead.deref(where); end if not jump and not noenter then v, r = stead.call(stead.ref(where), 'enter', stead.ref(was)); if r == false or (stead.api_atleast(1, 3, 0) and v == false and r == nil) then self.where = was; return stead.par(stead.scene_delim, res, v), ret(r) end end if stead.api_atleast(2, 4, 0) then need_scene = not stead.rawget(_G, 'PLAYER_MOVED'); else need_scene = not (stead.ref(where) ~= stead.ref(self.where)) end res = stead.par(stead.scene_delim, res, v); if not back then stead.ref(where).__from__ = stead.deref(was); end ret() stead.rawset(_G, 'PLAYER_MOVED', true) if need_scene and not nodsc then stead.need_scene() end if not stead.in_walk_call then local to = self.where if not noexit then self.where = was stead.in_onexit_call = true v = stead.call(stead.ref(was), 'left', stead.ref(to)); stead.in_onexit_call = false res = stead.par(stead.scene_delim, res, v); end self.where = stead.deref(to) if not noenter then stead.in_entered_call = true v = stead.call(stead.ref(to), 'entered', stead.ref(was)); stead.in_entered_call = false res = stead.par(stead.scene_delim, res, v); end if stead.tonum(stead.ref(to).__visited) then stead.ref(to).__visited = stead.ref(to).__visited + 1; elseif stead.here().__visited == nil then stead.ref(to).__visited = 1 end if not stead.api_atleast(1, 6, 3) and isDialog(stead.ref(to)) then stead.dialog_rescan(stead.ref(to)) end end return res; end stead.player_go = function(self, where) -- cmd iface local w = stead.ref(self.where).way:srch(where); if not w then return nil,false end return self:walk(w); end stead.player_walk = function(self, where, ...) -- real work local v, r, vv; vv, r = onevent('onwalk', stead.ref(where), ...); if vv == false then return end if r == false then return vv end v, r = stead.go(self, where, ...); if stead.type(vv) == 'string' then v = stead.par(stead.space_delim, vv, v); end return v, r; end stead.player_back = function(self) -- deprecated error ("Do not use stead.me():back(). It's deprecated.", 2) end stead.back = function(w) if isDialog(stead.here()) and not isDialog(stead.from()) then return stead.walkout(w); end return stead.walkback(w); end back = stead.back stead.walkback = function(w) if isRoom(stead.ref(w)) then return stead.me():walk(w, true); end return stead.me():walk(stead.from(), true); end walkback = stead.walkback stead.walk = function(what, back, noenter, noexit, nodsc, ...) return stead.me():walk(what, back, noenter, noexit, nodsc, ...); end walk = stead.walk stead.walkin = function(what) return stead.me():walk(what, false, false, true); end walkin = stead.walkin stead.walkout = function(what) if isRoom(stead.ref(what)) then return stead.me():walk(what, true, true, false, true); end return stead.me():walk(stead.from(), true, true, false, true); end walkout = stead.walkout function visited(w) if not w then w = stead.here() end w = stead.ref(w) if w == nil then return nil; end if not isRoom(w) then error ("Wrong parameter to visited.", 2); end return w.__visited end stead.visited = visited function visits(w) local n = stead.visited(w) if not n then n = 0 end return n end stead.visits = visits iface.fmt = function(self, cmd, st, moved, r, av, objs, pv) -- st -- changed state (main win), move -- loc changed local l, vv if st then av = txtem(av); pv = txtem(pv); -- if not PLAYER_MOVED then r = txtem(r) -- end if isForcedsc(stead.here()) or stead.rawget(_G, 'NEED_SCENE') then l = stead.here():scene(); end end if moved then vv = stead.fmt(stead.cat(stead.par(stead.scene_delim, r, l, av, objs, pv), '^')); else vv = stead.fmt(stead.cat(stead.par(stead.scene_delim, l, r, av, objs, pv), '^')); end return vv end stead.go = function(...) local r,v = go(...) if stead.type(r) == 'string' and stead.cctx() then stead.pr (r) end -- if stead.in_life_call then -- ACTION_TEXT = nil -- end if r == nil and v == nil then if stead.cctx() then stead.cctx().action = true else r = true end end return r,v end iface.cmd = stead.hook(iface.cmd, function(f, ...) stead.rawset(_G, 'NEED_SCENE', nil) return f(...) end) player = stead.inherit(player, function(v) v.look = function(s) if not stead.started then game:start() end if game._time == 0 then return stead.walk(stead.here(), false, false, true); end stead.need_scene() if stead.api_atleast(1, 3, 5) then return true -- force action end end return v end) pl = player(pl) -- reinit -- vim:ts=4 instead-3.5.2+dfsg/stead/stead2/wroom.lua000066400000000000000000000021401467622671600202350ustar00rootroot00000000000000stead.wroom_enter = function(self, ...) local w = self.where if stead.type(w) ~= 'table' then w = stead.call(self, 'where') end local r, v = stead.walk(w); if v ~= false then self._toggle = true end return r, v end stead.wroom_save = function(self, name, h, need) if need then local a = stead.tostring(self.oldname); local b = stead.tostring(self.newname); local c = stead.tostring(self.where); if a == nil or b == nil or c == nil then error ("Can not save wroom "..name.."\nFunctions can not be saved, use code [[ ]]"); end local t = stead.string.format("%s = wroom(%s, %s, %s);\n", name, a, b, c); h:write(t); end stead.savemembers(h, self, name, false); end function wroom(a, b, c) local v = room { vroom_type = true, nam = a, where = c, enter = stead.wroom_enter, save = stead.wroom_save }; v.newname = b; v.oldname = a; v._toggle = false if c == nil then -- only two parameters v.newname = nil v.where = b end v.nam = function(s) if s._toggle and s.newname then return stead.call(s, 'newname') else return stead.call(s, 'oldname'); end end return v end instead-3.5.2+dfsg/stead/stead2/xact.lua000066400000000000000000000062171467622671600200420ustar00rootroot00000000000000xact = function(n, f) -- just simple action! local v = {}; if f == nil and stead.type(n) == 'table' then f = n[2]; n = n[1]; end if stead.type(n) ~= 'string' then error ("Wrong parameter to xact.", 2) end v.xaction_type = true v.nam = n if stead.api_atleast(1, 6, 3) then v.disp = false end v.act = f; v = obj(v); v.save = function(self, name, h, need) if need then local f = self.act; f = stead.tostring(f); if f == nil then error("Can not save xact: "..name); end h:write(stead.string.format("%s = xact(%q, %s);\n", name, self.nam, f)) end stead.savemembers(h, self, name, false); end return v end local __do_xact = function(str, self) local aarg = {} local function parg(v) stead.table.insert(aarg, v); return '' end local xrefrep = function(str) local s = stead.string.gsub(str,'[\001\002]',''); local o,d,a, oo; local delim = ':' if stead.api_atleast(1, 2, 2) then delim = stead.delim; end s = s:gsub('\\?[\\'..delim..']', { [ delim ] = '\001', [ '\\'..delim ] = delim }); local i = s:find('\001', 1, true); aarg = {} if i then o = s:sub(1, i - 1); d = s:sub(i + 1); i = o:find("(", 1, true); if i then a = o:sub(i); o = o:sub(1, i - 1); a:gsub('[^,()]+', parg); end if o == '' then if isObject(self) then oo = self else error("Empty link: "..s, 3); end else if stead.api_atleast(1, 6, 3) then oo = stead.here():srch(o) else oo = objs():srch(o) end if not oo then oo = stead.ref(o, true) end end elseif isObject(self) then oo = self d = s; else error("Wrong link: "..s, 3); end d = d:gsub("\001", delim); return stead.xref(d, stead.ref(oo, true), stead.unpack(aarg)); end if stead.type(str) ~= 'string' then return end local s = stead.string.gsub(str, '\\?[\\{}]', { ['{'] = '\001', ['}'] = '\002' }):gsub('\001([^\002]+)\002', xrefrep):gsub('[\001\002]', { ['\001'] = '{', ['\002'] = '}' }); return s; end stead.fmt = stead.hook(stead.fmt, function(f, ...) local res, s local a = {...} for i = 1, stead.table.maxn(a) do if stead.type(a[i]) == 'string' then s = __do_xact(a[i]); res = stead.par('', res, s):gsub('\\?[\\{}]', { [ '\\{' ] = '{', [ '\\}' ] = '}' }); end end return f(res); end) obj = stead.inherit(obj, function(v) v.xref = function(s, str) return __do_xact(str, s); end return v end) function xdsc(n) local v = {} v.nam = true if n == nil then v.disp = 'xdsc' elseif stead.type(n) == 'string' then v.disp = n; else error("Wrong parameter to xdsc.", 2); end v.dsc = function(s) return stead.call(stead.here(), s.disp); end v.save = function(self, name, h, need) if need then h:write(stead.string.format("%s = xdsc(%q);\n", name, self.disp)) end stead.savemembers(h, self, name, false); end return obj(v) end xroom = stead.inherit(room, function(v) v.look = stead.hook(v.look, function(f, s,...) local xdsc = stead.call(s, 'xdsc'); return stead.par(stead.space_delim, xdsc, f(s, ...)); end) return v end) if stead.api_atleast(1, 6, 3) then xwalk = xact('xwalk', code [[ stead.walk(arg1) ]]); xwalk.system_type = true end -- vim:ts=4 instead-3.5.2+dfsg/stead/stead3/000077500000000000000000000000001467622671600163735ustar00rootroot00000000000000instead-3.5.2+dfsg/stead/stead3/.luacheckrc000066400000000000000000000000411467622671600204730ustar00rootroot00000000000000globals = { 'stead', 'LANG', } instead-3.5.2+dfsg/stead/stead3/CMakeLists.txt000066400000000000000000000006311467622671600211330ustar00rootroot00000000000000FILE(GLOB STEAD_FILES "*.lua") FILE(GLOB STEAD_EXT_FILES "ext/*.lua") IF(SYSTEMWIDE) INSTALL(FILES ${STEAD_FILES} DESTINATION ${STEADDIR}/stead3) INSTALL(FILES ${STEAD_EXT_FILES} DESTINATION ${STEADDIR}/stead3/ext) ELSEIF(STANDALONE) INSTALL(FILES ${STEAD_FILES} DESTINATION ${STANDALONEDIR}/stead/stead3) INSTALL(FILES ${STEAD_EXT_FILES} DESTINATION ${STANDALONEDIR}/stead/stead3/ext) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/stead/stead3/click.lua000066400000000000000000000021361467622671600201650ustar00rootroot00000000000000local std = stead local input = std.ref '@input' -- luacheck: globals click click = std.obj { nam = '@click'; -- luacheck: no unused args filter = function(s, press, btn, x, y, px, py) -- luacheck: unused args return press and px end } function input:wheel(x, y) local a for _, v in std.ipairs {'scroll', x, y} do a = (a and (a..', ') or ' ') .. std.dump(v) end return '@click'.. (a or '') end function input:click(press, btn, x, y, px, py) local a if not click:filter(press, btn, x, y, px, py) then return end for _, v in std.ipairs {'click', press, btn, x, y, px, py} do a = (a and (a..', ') or ' ') .. std.dump(v) end return '@click'.. (a or '') end std.mod_cmd(function(cmd) if cmd[1] ~= '@click' then return end if cmd[2] ~= 'click' and cmd[2] ~= 'scroll' then return end local r, v r, v = std.call(std.here(), 'on'..cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8]) if not r and not v then r, v = std.call(std.game, 'on'..cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8]) end if not r and not v then -- nothing todo return nil, false end return r, v end) instead-3.5.2+dfsg/stead/stead3/dbg-ru.lua000066400000000000000000000030131467622671600202530ustar00rootroot00000000000000local kbden = { shifted = { ["1"] = "!", ["2"] = "@", ["3"] = "#", ["4"] = "$", ["5"] = "%", ["6"] = "^", ["7"] = "&", ["8"] = "*", ["9"] = "(", ["0"] = ")", ["-"] = "_", ["="] = "+", ["["] = "{", ["]"] = "}", ["\\"] = "|", [";"] = ":", ["'"] = "\"", [","] = "<", ["."] = ">", ["/"] = "?", } } local kbdru = { ["q"] = "й", ["w"] = "ц", ["e"] = "у", ["r"] = "к", ["t"] = "е", ["y"] = "н", ["u"] = "г", ["i"] = "ш", ["o"] = "щ", ["p"] = "з", ["["] = "х", ["]"] = "ъ", ["a"] = "ф", ["s"] = "ы", ["d"] = "в", ["f"] = "а", ["g"] = "п", ["h"] = "р", ["j"] = "о", ["k"] = "л", ["l"] = "д", [";"] = "ж", ["'"] = "э", ["z"] = "я", ["x"] = "ч", ["c"] = "с", ["v"] = "м", ["b"] = "и", ["n"] = "т", ["m"] = "ь", [","] = "б", ["."] = "ю", ["`"] = "ё", shifted = { ["q"] = "Й", ["w"] = "Ц", ["e"] = "У", ["r"] = "К", ["t"] = "Е", ["y"] = "Н", ["u"] = "Г", ["i"] = "Ш", ["o"] = "Щ", ["p"] = "З", ["["] = "Х", ["]"] = "Ъ", ["a"] = "Ф", ["s"] = "Ы", ["d"] = "В", ["f"] = "А", ["g"] = "П", ["h"] = "Р", ["j"] = "О", ["k"] = "Л", ["l"] = "Д", [";"] = "Ж", ["'"] = "Э", ["z"] = "Я", ["x"] = "Ч", ["c"] = "С", ["v"] = "М", ["b"] = "И", ["n"] = "Т", ["m"] = "Ь", [","] = "Б", ["."] = "Ю", ["`"] = "Ё", ["1"] = "!", ["2"] = "@", ["3"] = "#", ["4"] = ";", ["5"] = "%", ["6"] = ":", ["7"] = "?", ["8"] = "*", ["9"] = "(", ["0"] = ")", ["-"] = "_", ["="] = "+", } } return { main = kbden, alt = kbdru } instead-3.5.2+dfsg/stead/stead3/dbg.lua000066400000000000000000000456441467622671600176470ustar00rootroot00000000000000-- luacheck: globals dprint -- luacheck: read globals walk disable enable drop take remove utf8_prev utf8_next local std = stead local type = std.type local table = std.table local input = std.ref '@input' local string = std.string local pairs = std.pairs local ipairs = std.ipairs local txt = std.ref '@iface' local instead = std.ref '@instead' local iface = txt local function use_text_event(key) if key == "return" then return false end return instead.text_input and instead.text_input() end local kbden = { shifted = { ["1"] = "!", ["2"] = "@", ["3"] = "#", ["4"] = "$", ["5"] = "%", ["6"] = "^", ["7"] = "&", ["8"] = "*", ["9"] = "(", ["0"] = ")", ["-"] = "_", ["="] = "+", ["["] = "{", ["]"] = "}", ["\\"] = "|", [";"] = ":", ["'"] = "\"", [","] = "<", ["."] = ">", ["/"] = "?", } } local kbdalt = false local function txt_esc(s) local rep = function(self) return txt:nb(self) end if not s then return end local r = s:gsub("[<>]+", rep):gsub("[ \t]", rep); return r end local function dispof(v) local d = std.titleof(v) or std.dispof(v) local tag = (type(v.tag) == 'string' and v.tag) if type(d) ~= 'string' then d = tag or 'n/a' else d = d..((tag and '/'..tag) or '') end return d end local function show_obj(s, o, pfx, verbose) local wh = o:where() if wh then wh = '@'..std.tostr(std.nameof(wh))..'['..(dispof(wh))..']' else wh = '' end s:printf("%s%s%snam: %s%s | disp:%s\n", pfx or '', o:disabled() and '%' or '', o:closed() and '-' or '', std.tostr(std.nameof(o)), wh, dispof(o)) if verbose then for k, v in pairs(o) do s:printf("*[%s] = %s\n", std.tostr(k), std.dump(v) or 'n/a') end return end for _, v in ipairs(o.obj) do pfx = (pfx or '' .. ' ') show_obj(s, v, pfx) end end local function show_room(s, o) s:printf("nam: %s | title: %s | disp: %s\n", std.tostr(std.nameof(o)), std.tostr(std.titleof(o) or 'n/a'), dispof(o)) s:printf(" way: ") for k, v in ipairs(o.way) do if k ~= 1 then s:printf(" | ") end s:printf("%s[%s]", std.tostr(std.nameof(v)), dispof(v)) end s:printf("\n") end local take = take local function show_decl(s, t) local d = std.ref '@declare':declarations() for k, v in pairs(d) do if not t or v["type"] == t then local dump = std.dump(_G[k]) if dump == '' then dump = std.tostr(_G[k]) end s:printf("%s %s = %s\n", v["type"], k, dump) end end end local commands = { { nam = 'quit', act = function(s) s.on = false s:disable(); return std.nop() end; }; { nam = 'find', { nam = 'obj', act = function(s, par) if not par then return end std.for_each_obj(function(v) if v == s then return end local disp = dispof(v) local nam = std.tostr(std.nameof(v)) if disp:find(par, 1, true) or nam:find(par, 1, true) then s:printf("nam: %s disp: %s\n", nam, disp) end end) end }; { nam = 'dsc', act = function(s, par) if not par then return end std.for_each_obj(function(v) if v == s then return end local dsc = std.par(' ', std.call(v, 'dsc'), std.call(v, 'decor')) or '' local st, e = dsc:find(par, 1, true) if st then local nam = std.tostr(std.nameof(v)) local disp = dispof(v) st = st - 32 if st < 0 then st = 1 end s:printf("nam: %s disp: %s dsc: %s\n", nam, disp, dsc:sub(st, e + 32)) end end) end }; }; { nam = 'show', { nam = 'obj', act = function(s, par) if par == '*' then local objs = {} std.for_each_obj(function(v) if not v:type 'room' then table.insert(objs, v) end end) table.sort(objs, function(a, b) return std.tostr(std.nameof(a)) < std.tostr(std.nameof(b)) end) for i = 1, #objs do show_obj(s, objs[i]) end return end if not par then for i = 1, #std.here().obj do show_obj(s, std.here().obj[i]) end return end s:printf("[object]\n") local st, r = std.pcall(function() show_obj(s, std.object(std.tonum(par) or par), ' ', true) end) if not st then s:printf("%s\n", r) return end return end; }, { nam = 'inv', act = function(s) s:printf("[inventory]\n") for _, v in ipairs(std.me():inventory()) do show_obj(s, v, ' ') end end; }; { nam = 'room', act = function(s, par) if par == '*' then local rooms = {} std.for_each_obj(function(v) if v:type 'room' then table.insert(rooms, v) end end) table.sort(rooms, function(a, b) return std.tostr(std.nameof(a)) < std.tostr(std.nameof(b)) end) for i = 1, #rooms do show_room(s, rooms[i]) end return end local r, v = std.pcall(function() return par and std.object(par) or std.here() end) if not r then s:printf("%s\n", v) return end if not std.is_obj(v, 'room') then s:printf("It is not the room.\n") return end s:printf("[room]\n ") show_room(s, v) s:printf("[objects]\n") for _, o in ipairs(std.here().obj) do show_obj(s, o, ' ') end end; }; { nam = 'declare', act = function(s, par) if par == '*' then show_decl(s) else show_decl(s, 'declare') end end }, { nam = 'global', act = function(s, _) show_decl(s, 'global') end }, { nam = 'const', act = function(s, _) show_decl(s, 'const') end } }; { nam = 'take', act = function(s, par) if not par then return end local st, r, v = s:eval(take, std.tonum(par) or par) if not st then s:printf("%s\n", r) return end return r, v end; }, { nam = 'drop', act = function(s, par) if not par then return end local st, r, v = s:eval(drop, std.tonum(par) or par) if not st then s:printf("%s\n", r) return end return r, v end; }, { nam = 'remove', act = function(s, par) if not par then return end local st, r, v = s:eval(remove, std.tonum(par) or par) if not st then s:printf("%s\n", r) return end return r, v end; }, { nam = 'enable', act = function(s, par) if not par then return end local st, r, v = s:eval(enable, std.tonum(par) or par) if not st then s:printf("%s\n", r) return end return r, v end; }, { nam = 'disable', act = function(s, par) if not par then return end local st, r, v = s:eval(disable, std.tonum(par) or par) if not st then s:printf("%s\n", r) return end return r, v end; }, { nam = 'dump', act = function(s, par) if not par then return end local f, err = std.eval('return ('..par..')') if not f then s:printf("%s\n", err) return end err, f = std.pcall(f) if not err then s:printf("%s\n", f) return end if std.is_obj(f) then show_obj(s, f, '', true) else s:printf("%s\n", std.dump(f)) end end }; { nam = 'eval', act = function(s, par) if not par then return end local f, err = std.eval(par) if not f then s:printf("%s\n", err) return end f, err = std.pcall(f) if not f then s:printf("%s\n", err) return end end }; { nam = 'walk', act = function(s, par) if not par then return end local st, r, v = s:eval(walk, par, false) if not st then s:printf("%s\n", r) return end return r, v end; }; { nam = 'clear', act = function(s) s:cls() end; }; { nam = 'help', act = function(s) s:printf([[Use key to complete words. Use / for history. Use ctrl-l to clear screen. Use ctrl-d or f7 to enter/exit debugger. Some useful commands: show obj * - show all objects show room * - show all rooms find obj - search obj find dsc - search obj (in dsc and decor) show obj - show object (in verbose mode) show room - show room show room - show here walk - walk anywhere ]]); end; }; lookup = function(s, inp) local cmd = std.split(inp) local cur = s local found local last_found for k, v in ipairs(cmd) do found = nil for _, c in ipairs(cur) do if v == c.nam then cur = c found = k last_found = k break end end if not found then break end end local par if last_found then for i = last_found + 1, #cmd do par = (par and (par .. ' ') or '').. cmd[i] end else par = inp end return cur, par end; completion = function(s, inp) local cmd, par = s:lookup(inp) if not cmd then return end if #cmd == 0 then if par then local vars = {} std.for_each_obj(function(v, var) if std.tostr(v.nam):find(par, 1, true) == 1 and std.tostr(v.nam) ~= par then table.insert(var, std.tostr(v.nam)) end end, vars) return vars end return end local var = {} for i = 1, #cmd do if cmd[i].nam:find(par or '', 1, true) == 1 then table.insert(var, cmd[i].nam) end end return var end; save = function() end; }; local embed = { on = false; key_shift = false; cursor = 1; input = ''; output = [[INSTEAD dbg 0.1 Written by Peter Kosyh in 2017 Type "help" to see help ]]; hint = ''; history = {}; history_pos = 1; key_alt = false; key_ctrl = false; kbd_alt_xlat = false; __last_disp = false; __nostrict = false; last_timer = false; }; local theme = {} local function theme_var(a, b) local ov = instead.theme_var(a) if b then theme[a] = ov return instead.theme_var(a, b) end return ov end local function theme_reset() for k, v in pairs(theme) do instead.theme_var(k, v) end theme = {} end local funcs = {} local function instead_func(a) local ov = instead[a] funcs[a] = ov std.rawset(instead, a, function() end) end local function instead_reset() for k, v in pairs(funcs) do std.rawset(instead, k, v) end funcs = {} end local std_dbg = {} local function std_debug(a) if not a then for k, v in pairs(std_dbg) do std['debug_'..k] = v end return end std_dbg[a] = std['debug_'..a] std['debug_'..a] = false end local render_callback = false local dbg = std.obj { pri = 16384; nam = '@dbg'; embed; { commands = commands }, enable = function(s) s.key_ctrl = false -- sticky bug s.key_alt = false instead_func('get_picture') instead_func('get_fading') instead_func('get_title') instead_func('get_ways') render_callback = (std.ref '@sprite').render_callback(false) local timer = stead.ref '@timer' s.last_timer = timer:get() timer:stop() std_debug('input') std_debug('output') std_debug('xref') s.__last_disp = std.game:lastdisp() s.__nostrict = std.nostrict or false local w, h = std.tonum(theme_var 'scr.w'), std.tonum(theme_var 'scr.h') theme_var('scr.gfx.mode', 'embedded') theme_var('scr.gfx.bg', '') theme_var('scr.col.bg', 'white') theme_var('win.col.fg', 'black') theme_var('inv.mode', 'disabled') local padw = w > 320 and 16 or 0 local padh = h > 320 and 16 or 0 theme_var('win.x', padw) theme_var('win.y', padh) theme_var('win.w', w - padw) theme_var('win.h', h - padh) theme_var('menu.button.x', w) theme_var('menu.button.y', h) theme_var('win.fnt.size', 16) theme_var('win.scroll.mode', 3) std.nostrict = true iface:raw_mode(true) end; disable = function(s) theme_reset() std_debug() std.nostrict = s.__nostrict instead_reset() std.ref('@sprite').render_callback(render_callback) iface:raw_mode(false) local timer = stead.ref '@timer' timer:set(s.last_timer) s.key_ctrl = false -- sticky bug s.key_alt = false s:okey(false, 'left ctrl') s:okey(false, 'right ctrl') std.game:lastdisp(s.__last_disp) end; inp_split = function(s) local pre = s.input:sub(1, s.cursor - 1); local post = s.input:sub(s.cursor); return pre, post end; eval = function(s, fn, ...) local st, r, _ = std.pcall(fn, ...) if not st then -- s:printf("%s\n", r) return false, r else s.on = false s:disable() if std.me():moved() then return true, nil, true else return true, std.nop() end end end; cls = function(s) s.output = ''; s.hint = ''; end; completion = function(s, edit) local hint = s.commands:completion(s.input) if not hint or #hint == 0 then s.hint = '' return end if #hint == 1 and edit ~= false then local _, par = s.commands:lookup(s.input) if par then s.input = std.strip(s.input) local len = par:len() s.input = s.input:sub(1, s.input:len() - len) end s.input = s.input .. hint[1]..' ' s.cursor = #s.input + 1 s:completion(edit) return end s.hint = '' for _, v in ipairs(hint) do s.hint = s.hint .. v .. ' ' end end; printf = function(s, fmt, ...) s.output = s.output .. std.string.format(fmt, ...) end; exec = function(s) local c, par = s.commands:lookup(s.input) if not c or not c.act then return s:completion() end if #s.history == 0 or s.history[#s.history] ~= s.input then table.insert(s.history, s.input) end s.history_pos = 0 s:printf('$ '..s.input..'\n') s.input = '' s.hint = '' s.cursor = 1 return c.act(s, par) end; dsc = function(s) -- display debugger std.pr (txt_esc(s.output)) if s.kbd_alt_xlat then std.pr (txt:bold '&') else std.pr (txt:bold ' ') end local pre, post = s:inp_split() std.pr (txt:bold '$ '.. txt:bold(txt_esc(pre))..txt:bold '|'..txt:bold(txt_esc(post)) ..'\n') if s.hint == '' then s.hint = '?' end std.pr (s.hint ..'\n') std.pr (txt:anchor()) end; text = function(s, text) if not use_text_event() or not s.on then return end -- if text == " " then -- key will handle this -- return -- end return '@dbg text '..string.format("%q", text) end; key = function(s, press, key) if key:find 'shift' then s.key_shift = press return elseif key:find 'ctrl' then s.key_ctrl = press return elseif key:find 'alt' then s.key_alt = press if s.on then if not press and kbdalt then s.kbd_alt_xlat = not s.kbd_alt_xlat end return 'look' end return end if not press then return end if s.key_ctrl or s.key_alt then if s.on and key == 'q' then return '@dbg toggle' end if key == 'q' or key == 'r' then return end end if s.key_shift then if key == 'up' or key == 'down' then return end end if (key == 'f7'and not s.key_ctrl and not s.key_alt) or (s.key_ctrl and key == 'd') then return '@dbg toggle' end if s.on then return '@dbg key '..string.format("%q", key) end end; } local function utf_bb(b, pos) return utf8_prev(b, pos) end local function utf_ff(b, pos) return utf8_next(b, pos) end local function key_xlat(s) local kbd if s == 'return' then return '\n' end if s == 'space' then return ' ' end if s:len() > 1 then return end if dbg.kbd_alt_xlat and (std.game.codepage == 'UTF-8' or std.game.codepage == 'utf-8') and kbdalt then kbd = kbdalt else kbd = kbden end if kbd and dbg.key_shift then kbd = kbd.shifted; end if not kbd[s] then if dbg.key_shift then return s:upper(); end return s; end return kbd[s] end std.mod_cmd(function(cmd) if cmd[1] ~= '@dbg' then if dbg.on then if cmd[1] == 'look' then std.abort() return std.call(dbg, 'dsc') end return nil, false end return end if cmd[2] == 'toggle' then dbg.on = not dbg.on if dbg.on then dbg:enable() std.abort() return std.call(dbg, 'dsc') else dbg:disable() return std.nop() end elseif cmd[2] == 'key' then local key = cmd[3] if key:find 'return' and not dbg.key_ctrl and not dbg.key_alt then local r, v = dbg:exec() if r ~= nil or v ~= nil then return r, v end elseif key:find '^backspace' then if dbg.input == '' then std.abort() return std.call(dbg, 'dsc'), true end local pre, post = dbg:inp_split() if not pre or pre == '' then std.abort() return std.call(dbg, 'dsc'), true end local i = utf_bb(pre) dbg.input = dbg.input:sub(1, pre:len() - i) .. post dbg.cursor = dbg.cursor - i elseif key:find '^tab' then dbg:completion() elseif key:find 'home' or (key == 'a' and dbg.key_ctrl) then dbg.cursor = 1 elseif key:find 'end' or (key == 'e' and dbg.key_ctrl) then dbg.cursor = #dbg.input + 1 elseif (key == 'k' and dbg.key_ctrl) then dbg.cursor = 1 dbg.input = '' elseif (key == 'l' and dbg.key_ctrl) then dbg:cls() elseif key == 'right' then if dbg.cursor <= dbg.input:len() then local i = utf_ff(dbg.input, dbg.cursor) dbg.cursor = dbg.cursor + i end if dbg.cursor > dbg.input:len() then dbg.cursor = dbg.input:len() + 1 end elseif key == 'left' then if dbg.cursor > 1 then local i = utf_bb(dbg.input, dbg.cursor - 1) dbg.cursor = dbg.cursor - i end if dbg.cursor < 1 then dbg.cursor = 1 end elseif key == 'up' then local s = dbg if #s.history == 0 then return end if s.history_pos == 0 then s.history_pos = #s.history + 1 end s.history_pos = s.history_pos - 1 if s.history_pos == 0 then s.history_pos = 1 end s.input = s.history[s.history_pos] s.cursor = #s.input + 1 elseif key == 'down' then local s = dbg if #s.history == 0 or s.history_pos == #s.history then return end s.history_pos = s.history_pos + 1 if s.history_pos > #s.history then s.history_pos = #s.history end s.input = s.history[s.history_pos] s.cursor = #s.input + 1 elseif not use_text_event(key) and key_xlat(key) then local k = key_xlat(key) local pre, post = dbg:inp_split() dbg.cursor = dbg.cursor + k:len() dbg.input = pre .. k .. post else return nil, false end dbg:completion(false) std.abort() return std.call(dbg, 'dsc'), true elseif cmd[2] == 'text' then local text = cmd[3] local pre, post = dbg:inp_split() dbg.cursor = dbg.cursor + text:len() dbg.input = pre .. text .. post dbg:completion(false) std.abort() return std.call(dbg, 'dsc'), true end end, -100) function std.dprint(...) local a = { ... } dbg:printf("dbg> "); for i = 1, #a do if i ~= 1 then dbg:printf("%s", ' ') std.io.stderr:write(' ') end dbg:printf("%s", std.tostr(a[i])) std.io.stderr:write(std.tostr(a[i])) end dbg:printf("\n") std.io.stderr:write('\n') std.io.stderr:flush() end dprint = std.dprint local oldlang local okey, otext local hooked = false function dbg:okey(...) if okey then okey(input, ...) end end std.mod_start(function(_) local st, r if not use_text_event() and oldlang ~= LANG then st, r = std.pcall(function() return require ('dbg-'..LANG) end) if st and r then std.dprint("dbg: Using '"..LANG.."' keyboard layout.") kbden, kbdalt = r.main, r.alt end end oldlang = LANG iface:raw_mode(false) if not hooked then okey = input.key; otext = input.text; hooked = true end std.rawset(input, 'key', function(_, ...) return dbg:key(...) or (not dbg.on and okey and okey(input, ...)) end) std.rawset(input, 'text', function(_, ...) return dbg:text(...) or (not dbg.on and otext and otext(input, ...)) end) end, -100) std.mod_done(function() hooked = false iface:raw_mode(false) std.rawset(input, 'key', okey) std.rawset(input, 'text', otext) end, -100) -- std.rawset(_G, 'dbg', std.ref '@dbg') instead-3.5.2+dfsg/stead/stead3/declare.lua000066400000000000000000000116001467622671600204730ustar00rootroot00000000000000-- luacheck: globals const global declare local declarations = {} local variables = {} local std = stead local type = std.type local rawget = std.rawget local rawset = std.rawset local pairs = std.pairs local table = std.table local next = std.next local function __declare_one(k, v, t) local link if type(k) ~= 'string' then -- k:find("^[a-zA-Z_][a-zA-Z0-9_]*$") then std.err ("Wrong declaration name: "..k, 3) end if declarations[k] then std.err ("Duplicate declaration: "..k, 3) end link = rawget(_G, k) declarations[k] = { value = v, type = t, link = link } if link and v ~= link then std.err("Overwite global declaration: "..std.tostr(k), 3) end if t == 'global' then if type(v) == 'function' and not std.functions[v] then std.err("Use declare to declare function: "..k, 3) end rawset(_G, k, v) variables[k] = true end if type(v) == 'function' and not std.functions[v] then std.functions[v] = k end if std.__in_init and std.is_obj(v, 'list') then table.insert(v.__in_init, v) end end local function __declare(n, t) if stead.game then std.err ("Use "..t.." only in global context", 2) end if type(n) == 'string' then return function(v) if v == nil then v = false -- std.err("Wrong declaration: "..std.tostr(t), 2) end __declare_one(n, v, t) end end if type(n) ~= 'table' then std.err ("Wrong parameter to "..n, 2) end for k, v in std.pairs(n) do __declare_one(k, v, t) end return n end function std.const(n) return __declare(n, 'const') end function std.global(n) return __declare(n, 'global') end function std.declare(n) return __declare(n, 'declare') end local function do_depends(t, tables, deps) if type(t) ~= 'table' then return end if tables[t] then deps[t] = tables[t] end for _, v in pairs(t) do if type(v) == 'table' and not std.getmt(v) then do_depends(v, tables, deps) end end end local function makedeps(nam, depends, deps) local ndeps = {} local rc = false local t = rawget(_G, nam) if type(t) ~= 'table' then return end if type(depends[nam]) ~= 'table' then return end local d = depends[nam] for k, v in pairs(d) do local dd = depends[v] if dd and k ~= t then ndeps[k] = v rc = rc or makedeps(v, depends, deps) end end if not next(ndeps) then depends[nam] = nil table.insert(deps, t) rc = true else depends[nam] = ndeps end return rc end local function mod_save(fp) -- save global variables std.tables = {} local tables = {} local deps = {} for k, v in pairs(declarations) do -- name all table variables local o = rawget(_G, k) or v.value if type(o) == 'table' then if not tables[o] then tables[o] = k end end end for k, _ in pairs(variables) do local d = {} local o = rawget(_G, k) do_depends(o, tables, d) if k == tables[o] then -- self depend d[o] = nil end if next(d) then deps[k] = d end end std.tables = tables -- save all depends for k, _ in pairs(variables) do -- write w/o deps local o = rawget(_G, k) if not deps[k] then std.save_var(o, fp, k) end end for k, _ in pairs(variables) do local d = {} while makedeps(k, deps, d) do for i=1, #d do std.save_var(d[i], fp, k) end d = {} end end end local function mod_init() std.setmt(_G, { __index = function(_, n) local d = declarations[n] if d then -- if std.game and (d.type ~= 'const') then rawset(_, n, d.value) end return d.value end local f = std.getinfo(2, "S").source std.err ("Uninitialized global variable: "..n.." in "..f, 2) end; __newindex = function(t, k, v) if not std.game and std.is_obj(v) then -- autodeclare objects __declare_one(k, v, 'declare') end local d = declarations[k] if d then if v == d.value then return --nothing todo end if not std.game then d.value = v return end if d.type == 'const' then std.err ("Modify read-only constant: "..k, 2) else d.value = v rawset(t, k, v) end return end if std.game or type(v) ~= 'function' then local f = std.getinfo(2, "S").source if f ~= '=[C]' then std.err ("Set uninitialized variable: "..k.." in "..f, 2) end end rawset(t, k, v) end }) end std.obj { nam = '@declare'; ini = function(_, ...) -- init all list objs for _, v in pairs(declarations) do if std.is_obj(v.value, 'list') then v.value:__ini(...) end end end; declarations = function() return declarations; end; variables = function() return variables end; } local function mod_done() std.setmt(_G, {}) local decl = {} for k, v in pairs(declarations) do local o = std.rawget(_G, k) or v.value if std.is_system(o) then -- save system declarations decl[k] = v elseif not v.link then rawset(_G, k, nil) end end std.tables = {} std.functions = {} declarations = decl variables = {} end std.mod_init(mod_init) std.mod_done(mod_done) std.mod_save(mod_save) const = std.const global = std.global declare = std.declare instead-3.5.2+dfsg/stead/stead3/dlg.lua000066400000000000000000000163211467622671600176470ustar00rootroot00000000000000-- luacheck: read globals iface local std = stead local type = std.type local table = std.table std.phrase_prefix = '-- ' std.phrase_show = true local function phr_prefix(d, nr) if type(std.phrase_prefix) == 'string' then d = std.phrase_prefix .. d elseif type(std.phrase_prefix) == 'function' then d = std.phrase_prefix(nr) .. d end return d end std.dlg = std.class({ __dlg_type = true; new = function(s, v) if v.current == nil then v.current = false end v.dlg_enter = v.enter v.enter = nil v.__stack = {} if type(v.phr) == 'table' then if not v.obj then v.obj = {} end if type(v.obj) == 'table' then table.insert(v.obj, 1, v.phr) end end v = std.room(v) std.setmt(v, s) v:__recreate() return v end; __recreate = function(s) for i = 1, #s.obj do if not std.is_obj(s.obj[i]) then s.obj[i] = std.phr(s.obj[i]) end end end; with = function(self, ...) std.room.with(self, ...) self:__recreate() return self end; scene = function(s) local title, dsc, lact title = iface:title(std.titleof(s)) dsc = std.call(s, 'dsc') if not std.me():moved() then s.__lact = std.game:lastreact() or s.__lact lact = iface:em(s.__lact) end return std.par(std.scene_delim, title or false, lact or false, dsc) end; ph_onact = function(_, w) -- show dsc by default if not std.phrase_show then return end local r, v = std.call(w, 'dsc') if type(r) == 'string' then return phr_prefix(r) end return r, v end; empty = function(s, w) if not w then if not s.current then return true end return s.current:empty() end w = s:lookup(w) if not w then return true end return w:empty() end; enter = function(s, ...) s.__llact = false s.__stack = {} s.current = nil s:for_each(function(self) self:open() end) -- open all phrases local r, v = std.call(s, 'dlg_enter', ...) if std.here() ~= s or #s.__stack > 0 then return r, v end local rr, vv = s:push(s.current) if not vv then std.err("Wrong dialog: "..std.tostr(s), 2) end return std.par(std.scene_delim, r or false, rr or false), v end; push = function(s, p) local c = s.current local r = s:select(p) local t if r ~= false then if c then table.insert(s.__stack, c) end if r.dsc ~= nil and r.ph_act == nil and r.next == nil then -- no rection t = std.call(r, 'dsc') end if s.current ~= r or std.me():moved() then return t end if r:empty() then local tt, vv = s:pop() t = std.par(std.scene_delim, t or false, tt or false) if not vv then tt = std.walkout(s:from()) t = std.par(std.scene_delim, t or false, tt or false) end end end return t, r ~= false end; reset = function(s, phr) s.__stack = {} return s:push(phr) end; pop = function(s, phr) if #s.__stack == 0 then return false end if phr then local l = {} for i = 1, #s.__stack do table.insert(l, s.__stack[i]) if s.stack[i] == phr then break end end s.__stack = l end local p while #s.__stack > 0 do p = table.remove(s.__stack, #s.__stack) -- remove top p = s:select(p) if not p then return false end if p:empty() then local r, v = std.call(p, 'onempty') if v then return r, p end else return false, p end end return false end; select = function(s, p) if #s.obj == 0 then return false end if not p then -- get first one p = s.obj[1] end local c = s:lookup(p) if not c then std.err("Wrong dlg:select argumant: "..std.tostr(p), 2) end c:select() -- if c:disabled() then -- select always enables phrase -- c:enable() -- end s.current = c return c end; srch = function(s, w) local oo = s.current -- lookup in current if not oo then return end local r, l, i = s:lookup(w) if not r then return end if not std.is_obj(r, 'phr') then -- simple object return std.room.srch(s, w) end w = oo.obj:for_each(function(v) -- aliases v = v:__alias() if not v:visible() then return end if v == r then return v end end) if not w then return end return r, l, i end; display = function(s) local deco = std.call(s, 'decor'); -- static decorations return std.par(std.scene_delim, deco or false, s:ph_display()) end; ph_display = function(s) local r, nr nr = 1 local oo = s.current if not oo then -- nothing to show return end oo:select() -- to recheck all for i = 1, #oo.obj do local o = oo.obj[i] o = o:__alias() if o:visible() then if r then r = r .. '^' end local d = std.call(o, 'dsc') if type(d) == 'string' then d = phr_prefix(d, nr) d = o:__xref(d, true) r = (r or '').. d nr = nr + 1 end end end return r end; }, std.room) std.phr = std.class({ __phr_type = true; new = function(s, t) local disabled local a = t local o = { obj = {} } for i = 1, #a do local v = a[i] if i == 1 and type(v) == 'boolean' then if not v then disabled = true else o.always = true end elseif type(v) == 'table' then if not std.is_obj(v, 'phr') then v = s:new(v) end table.insert(o.obj, v) elseif o.tag == nil and v ~= nil and std.is_tag(v) then o.tag = v elseif o.dsc == nil and v ~= nil then o.dsc = v elseif o.act == nil and v ~= nil then o.act = v end end for k, v in std.pairs(a) do if type(k) == 'string' then o[k] = v end end -- if o.act == nil then -- std.err("Wrong phrase (no act)", 2) -- end o.ph_act = o.act o.act = nil disabled = disabled or (o.hidden == true) o = std.obj(o) std.setmt(o, s) if disabled then o = o:disable() end return o end, __alias = function(s) if s.alias ~= nil then local ss = std.here():lookup(s.alias) if not std.is_obj(ss) then std.err("Wrong alias: "..std.tostr(s.alias), 3) end s = ss end return s end; check = function(s) -- s = s:__alias() if type(s.cond) == 'function' then if s:cond() then s:enable() else s:disable() end end end; empty = function(s) for i = 1, #s.obj do local o = s.obj[i] if not o:disabled() and not o:closed() then return false end end return true end; visible = function(s) return not s:disabled() and not s:closed() end; act = function(s, ...) local r, _ local n = s -- s = s:__alias() local onact, v = std.call(std.here(), 'ph_onact', s) if not v then return onact end local w = s:where() if w and w.only then -- only one choice for i = 1, #w.obj do local o = w.obj[i] if not o.always then o:close() end end elseif not s.always then s:close() end local cur = std.here().current r, _ = std.call(s, 'ph_act', ...) r = std.par(std.scene_delim, onact or false, r or false) if std.me():moved() or cur ~= std.here().current then return r, v end if std.is_tag(s.next) then n = s.next end cur:select() -- conditions local t local rr, vv = std.here():push(n) if not vv then t = std.walkout(std.here():from()) end return std.par(std.scene_delim, r or false, rr or false, t or false), v end, select = function(s) if not s.always then s:close() end for i = 1, #s.obj do local o = s.obj[i] o = o:__alias() o:check() end end; }, std.obj) instead-3.5.2+dfsg/stead/stead3/events.lua000066400000000000000000000007511467622671600204050ustar00rootroot00000000000000local std = stead local input = std.ref '@input' local instead = std.ref '@instead' -- luacheck: no self function input:event(...) -- luacheck: self local a for _, v in std.ipairs {...} do a = (a and (a..', ') or ' ') .. std.dump(v) end return '@user_event'.. a or '' end std.mod_cmd(function(cmd) if cmd[1] ~= '@user_event' then return end local r, v = std.call(instead, 'onevent', cmd[2]) if not r and not v then -- nothing todo return nil, false end return r, v end) instead-3.5.2+dfsg/stead/stead3/ext/000077500000000000000000000000001467622671600171735ustar00rootroot00000000000000instead-3.5.2+dfsg/stead/stead3/ext/gui.lua000066400000000000000000000246051467622671600204710ustar00rootroot00000000000000-- sdl-instead specific methods local std = stead local instead = std.obj { nam = '@instead'; version_table = {3, 5, 2}; ini = function(s) -- after reset always do fade s.need_fading(true) end; } -- luacheck: read globals instead_clipboard -- luacheck: read globals instead_wait_use -- luacheck: read globals instead_grab_events -- luacheck: read globals instead_text_input -- luacheck: no self instead.clipboard = instead_clipboard instead.wait_use = instead_wait_use instead.grab_events = instead_grab_events instead.text_input = instead_text_input function instead.atleast(...) for k, v in std.ipairs {...} do if std.type(v) ~= 'number' then return false end if v > (instead.version_table[k] or 0) then return false end if v < (instead.version_table[k] or 0) then return true end end return true end function instead.version(...) if #{...} == 0 then return instead.version_table end if not instead.atleast(...) then local v = false for _, n in std.ipairs({...}) do if std.type(n) ~= 'number' then std.err([[Wrong instead.version argument: ]]..std.tostr(n), 2) end v = (v and (v .. '.') or '').. std.tostr(n) end std.err ([[The game requires instead engine of version ]] ..(v or '???').. [[ or higher. https://instead-hub.github.io]], 2) end end function instead.need_fading(v) local ov = instead.__need_fading if v ~= nil then instead.__need_fading = v end return ov end local iface = std '@iface' local type = std.type local dict = {} instead.inv_delim = '\n' instead.hinv_delim = ' | ' instead.ways_delim = ' | ' local function get_bool(o, nam) if type(o[nam]) == 'boolean' then return o[nam] end if type(o[nam]) == 'function' then return o[nam](o) end return nil end instead.notitle = false instead.get_title = std.cacheable('title', function() if get_bool(instead, 'notitle') then return end return iface:fmt(iface:bold(std.titleof(stead.here())), false) end) instead.noways = false instead.get_ways = std.cacheable('ways', function() if get_bool(instead, 'noways') then return end local str = iface:cmd("way"); if str then str = std.string.gsub(str, '\n$',''); str = std.string.gsub(str, '\\?['..std.delim ..']', { [std.delim] = instead.ways_delim, [ '\\'..std.delim ] = std.delim }); return iface:center(str); end return str end) instead.noinv = false instead.get_inv = std.cacheable('inv', function(horiz) if get_bool(instead, 'noinv') then return end local str = iface:cmd("inv"); if str then str = std.string.gsub(str, '\n$',''); if not horiz then str = std.string.gsub(str, '\\?['.. std.delim ..']', { [std.delim] = instead.inv_delim, ['\\'..std.delim] = std.delim }); else str = std.string.gsub(str, '\\?['.. std.delim ..']', { [std.delim] = instead.hinv_delim, ['\\'..std.delim] = std.delim }); end end return str end) instead.nopic = false -- luacheck: push ignore savedpicture local savedpicture -- luacheck: pop instead.get_picture = std.cacheable('pic', function() if get_bool(instead, 'nopic') then return end local s = stead.call(std.here(), 'pic') if not s then s = stead.call(std.ref 'game', 'pic') end savedpicture = s -- to save picture sprite from unload return s and std.tostr(s) end) local last_picture instead.fading_value = 4 -- default fading function instead.get_fading() if not instead.fading then return false end if type(instead.fading) == 'function' and not instead.fading() then return false end return true, instead.fading_value end function instead.fading() local pic = instead.get_picture() if type(pic) == 'string' and pic:find('spr:', 1, true) == 1 then pic = 'spr:' end if std.me():need_scene() or instead.need_fading() or pic ~= last_picture then last_picture = pic return true end end function instead.get_restart() local restart = instead.__restart or false instead.__restart = nil return restart end function instead.get_menu() local menu = instead.__menu instead.__menu = nil return menu end instead.nosave = false instead.noautosave = false function instead.isEnableSave() local s = get_bool(instead, 'nosave') return not s end function instead.isEnableAutosave() if instead.get_autosave() then return true end return not get_bool(instead, 'noautosave') end function instead.autosave(slot) instead.__autosave = true instead.__autosave_slot = slot end function instead.get_autosave() return instead.__autosave or false, instead.__autosave_slot end function instead.menu(n) if n == nil then n = 'main' elseif type(n) ~= 'string' and n ~= false then n = 'toggle' end instead.__menu = n end function instead.restart(v) if v == false then v = false else v = true end instead.__restart = v end function iface:title() -- hide title return end -- luacheck: globals stat std.stat = std.class({ __stat_type = true; }, std.obj); -- luacheck: globals menu std.menu = std.class({ __menu_type = true; new = function(_, v) if type(v) ~= 'table' then std.err ("Wrong argument to std.menu:"..std.tostr(v), 2) end v = std.obj(v) -- std.setmt(v, self) return v end; inv = function(s, ...) local r, v if s.menu ~= nil then r, v = std.call(s, 'menu', ...) -- special method while in inv else r, v = std.call(s, 'act', ...) -- fallback to act end if not r and not v then return true, false -- menu mode end return r, v end; }, std.obj); std.setmt(std.phr, std.menu) -- make phrases menus std.setmt(std.ref '@', std.menu) -- make xact menu function iface:esc(str) str = str:gsub("\\?[\\<>]", { ['\\\\'] = '\\\\\\\\\\', ['>'] = iface:nb('>'), ['<'] = iface:nb('<') }) return str end function iface:xref(str, o, ...) if type(str) ~= 'string' then std.err ("Wrong parameter to iface:xref: "..std.tostr(str), 2) end if not std.is_obj(o) or std.is_obj(o, 'stat') or o:disabled() then return str end local a = { ... } local args = '' for i = 1, #a do if type(a[i]) ~= 'string' and type(a[i]) ~= 'number' and type(a[i]) ~= 'boolean' then std.err ("Wrong argument to iface:xref: "..std.tostr(a[i]), 2) end args = args .. ' '..std.dump(a[i]) end local xref = std.string.format("%s%s", std.deref_str(o), args) -- std.string.format("%s%s", iface:esc(std.deref_str(o)), iface:esc(args)) if not dict[xref] then table.insert(dict, xref) dict[xref] = #dict end xref = std.tostr(dict[xref]) if std.cmd[1] == 'way' then return std.string.format("", xref)..str.."" elseif std.is_obj(o, 'menu') or std.is_system(o) then return std.string.format("", xref)..str.."" elseif std.cmd[1] == 'inv' then return std.string.format("", xref)..str.."" end return std.string.format("", xref)..str.."" end function iface:em(str) if type(str) == 'string' then return ''..str..'' end end function iface:center(str) if type(str) == 'string' then return ''..str..'' end end function iface:just(str) if type(str) == 'string' then return ''..str..'' end end function iface:left(str) if type(str) == 'string' then return ''..str..'' end end function iface:right(str) if type(str) == 'string' then return ''..str..'' end end function iface:bold(str) if type(str) == 'string' then return ''..str..'' end end function iface:top(str) if type(str) == 'string' then return ''..str..'' end end function iface:bottom(str) if type(str) == 'string' then return ''..str..'' end end function iface:middle(str) if type(str) == 'string' then return ''..str..'' end end function iface:nb(str) if type(str) == 'string' then return "","\\>"):gsub("%^","\\^")..">"; end end function iface:anchor() return '' end function iface:img(str) if str then return "" end end; function iface:imgl(str) if str then return "" end end; function iface:imgr(str) if str then return "" end end function iface:under(str) if type(str) == 'string' then return ""..str.."" end end; function iface:st(str) if type(str) == 'string' then return ""..str.."" end end function iface:tab(str, al) if type(str) == 'number' then str = std.tostr(str) end if type(str) ~= 'string' then return end if al == 'right' then str = str .. ",right" elseif al == 'center' then str = str .. ",center" end return '' end function iface:y(str, al) if stead.tonum(str) then str = stead.tostr(str) end if stead.type(str) ~= 'string' then return nil; end if al == 'middle' then str = str .. ",middle" elseif al == 'top' then str = str .. ",top" end return '' end; function iface:input(event, ...) local input = std.ref '@input' if type(input) ~= 'table' then return end if event == 'kbd' then if type(input.key) == 'function' then return input:key(...); -- pressed, event end elseif event == 'mouse' then if type(input.click) == 'function' then return input:click(...); -- pressed, x, y, mb end elseif event == 'wheel' then if type(input.wheel) == 'function' then return input:wheel(...); end elseif event == 'finger' then if type(input.finger) == 'function' then return input:finger(...); -- pressed, x, y, finger end elseif event == 'event' then if type(input.event) == 'function' then return input:event(...); end elseif event == 'text' then if type(input.text) == 'function' then return input:text(...); end end return end local iface_cmd = iface.cmd -- save old function iface:cmd(inp) local a = std.split(inp) if a[1] == 'act' or a[1] == 'use' or a[1] == 'go' then if a[1] == 'use' then local use = std.split(a[2], ',') for i = 1, 2 do local u = std.tonum(use[i]) if u then use[i] = dict[u] end end a[2] = std.join(use, ',') elseif std.tonum(a[2]) then a[2] = dict[std.tonum(a[2])] end inp = std.join(a) end return iface_cmd(self, inp) end std.obj { -- input object nam = '@input'; }; -- some aliases menu = std.menu stat = std.stat std.mod_init(function() std.rawset(_G, 'instead', instead) require "ext/sandbox" end) std.mod_cmd(function() instead.need_fading(false) end) std.mod_step(function(state) if state then dict = {} end end) std.mod_start(function() dict = {} end) std.mod_done(function() last_picture = nil end) std.mod_save(function() instead.__autosave = nil instead.__autosave_slot = nil end) if std.rawget(_G, 'DEBUG') then require 'dbg' end instead-3.5.2+dfsg/stead/stead3/ext/paths.lua000066400000000000000000000011351467622671600210150ustar00rootroot00000000000000local std = stead local instead = std.ref '@instead' -- luacheck: read globals instead_savepath -- luacheck: read globals instead_gamepath -- luacheck: read globals instead_exepath -- luacheck: globals io instead.savepath = instead_savepath std.savepath = instead_savepath instead.gamepath = instead_gamepath instead.exepath = instead_exepath io.open = stead.hook(io.open, function(f, path, acc, ...) if std.type(path) == 'string' and path:sub(1, 1) ~= '/' and not (path:sub(2, 2) == ':' and path:find("^[A-Z]", 1) == 1) then path = instead.gamepath()..'/'..path end return f(path, acc, ...) end) instead-3.5.2+dfsg/stead/stead3/ext/sandbox.lua000066400000000000000000000100161467622671600213320ustar00rootroot00000000000000-- luacheck: globals STANDALONE -- luacheck: read globals instead -- luacheck: globals io os debug load loadstring package -- luacheck: read globals instead_realpath local function sandbox() if STANDALONE or not instead.gamepath then -- not standalone or not sdl-instead return end -- luacheck: no unused args local check_path = function(realpath, type, find, gsub, savepath, gamepath, path) -- luacheck: unused args if not path then return false end path = realpath(path) if not path then return false end local spath = realpath(savepath) if not spath then return false end local s = find(path, spath..'/', 1, true) if s ~= 1 then spath = realpath(gamepath); if spath then s = find(path, spath..'/', 1, true) end end if s ~= 1 then return false end return true end local build_sandbox_open = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(io.open, function(f, path, acc, ...) if type(acc) ~= 'string' or not find(acc, "[aw+]") then -- only write access return f(path, acc, ...) end -- luacheck: no unused args if not check_path(realpath, type, find, gsub, savepath, gamepath, path) then -- luacheck: unused args error ("Access denied (write): ".. path, 3); return false end return f(path, acc, ...) end) end local build_sandbox_remove = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(os.remove, function(f, path, ...) if type(path) ~= 'string' then return f(path, ...) end if not check_path(realpath, type, find, gsub, savepath, gamepath, path) then error ("Access denied (remove): ".. path, 3); return false end return f(path, ...) end) end local build_sandbox_rename = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(os.rename, function(f, oldname, newname, ...) if not check_path(realpath, type, find, gsub, savepath, gamepath, oldname) or not check_path(realpath, type, find, gsub, savepath, gamepath, newname) then error ("Access denied (rename): ".. oldname .. ', '.. newname, 3); return false end return f(oldname, newname, ...) end) end local build_sandbox_output = function(realpath, error, type, find, gsub, savepath, gamepath) return stead.hook(io.output, function(f, path, ...) if type(path) == 'string' and not check_path(realpath, type, find, gsub, savepath, gamepath, path) then error ("Access denied (output): ".. path, 3); return false end return f(path, ...) end) end local build_sandbox_load = function(eval, error, type, find) return stead.hook(eval, function(f, str, ...) if type(str) == 'string' and find(str, "\x1b", 1, true) == 1 then error ("Loading bytecode is forbidden!", 3) return false end return f(str, ...) end) end io.open = build_sandbox_open(instead_realpath, error, type, string.find, string.gsub, instead.savepath(), instead.gamepath()); os.remove = build_sandbox_remove(instead_realpath, error, type, string.find, string.gsub, instead.savepath(), instead.gamepath()); os.rename = build_sandbox_rename(instead_realpath, error, type, string.find, string.gsub, instead.savepath(), instead.gamepath()); io.output = build_sandbox_output(instead_realpath, error, type, string.find, string.gsub, instead.savepath(), instead.gamepath()); os.execute = function(s) print ("Warning: trying to do os.execute: "..s); end io.popen = function(s) print ("Warning: trying to do io.popen: "..s); end os.tmpname = function(_) print ("Warning: trying to do os.tmpname"); end if not stead.rawget(_G, 'DEBUG') then debug = nil end if _VERSION == "Lua 5.1" then loadstring = build_sandbox_load(loadstring, error, type, string.find) stead.eval = loadstring else load = build_sandbox_load(load, error, type, string.find) stead.eval = load end package.cpath = "" package.preload = {} package = nil end sandbox() instead-3.5.2+dfsg/stead/stead3/ext/sound.lua000066400000000000000000000106341467622671600210320ustar00rootroot00000000000000-- raw interface to sound local std = stead local instead = std.ref '@instead' -- luacheck: globals instead_sound_load -- luacheck: globals instead_sound_free -- luacheck: globals instead_sounds_free -- luacheck: globals instead_sound_channel -- luacheck: globals instead_sound_volume -- luacheck: globals instead_sound_panning -- luacheck: globals instead_sound_load_mem -- luacheck: globals instead_music_callback -- luacheck: globals instead_sound instead.sound_load = instead_sound_load instead.sound_free = instead_sound_free instead.sounds_free = instead_sounds_free instead.sound_channel = instead_sound_channel instead.sound_volume = instead_sound_volume instead.sound_panning = instead_sound_panning instead.sound_load_mem = instead_sound_load_mem instead.music_callback = instead_music_callback instead.is_sound = instead_sound function instead.get_music() return instead.__music, instead.__music_loop end function instead.set_music(mus, loop) instead.__music = mus or nil instead.__music_loop = loop or 0 end function instead.get_music_fading() return instead.__music_fadeout, instead.__music_fadein end function instead.set_music_fading(o, i) if not i then i = o end if o == 0 or not o then o = -1 end if i == 0 or not i then i = -1 end instead.__music_fadeout = o instead.__music_fadein = i end function instead.finish_music() if (instead.__music_loop or 0) == 0 then return false end instead.__music_loop = -1 return true end function instead.get_sound() return instead.__sound, instead.__sound_channel, instead.__sound_loop end function instead.add_sound(s, chan, loop) if type(s) ~= 'string' then std.err("Wrong parameter to instead.add_sound()", 2) end if type(instead.__sound) ~= 'string' then return instead.set_sound(s, chan, loop) end if std.tonum(chan) then s = s..'@'..std.tostr(chan); end if std.tonum(loop) then s = s..','..std.tostr(loop) end instead.set_sound(instead.__sound..';'..s, instead.__sound_channel, instead.__sound_loop); end function instead.set_sound(sound, chan, loop) instead.__sound = sound instead.__sound_loop = loop or 1 instead.__sound_channel = chan or -1 end function instead.stop_sound(chan, fo) local str = '@-1' if (chan and type(chan) ~= 'number') or (fo and type(fo) ~= 'number') then std.err("Wrong parameter to instead.stop_sound", 2) end if chan then str = '@'..std.tostr(chan) end if fo then str = str .. ',' .. std.tostr(fo) end return instead.add_sound(str); end function instead.stop_music() instead.set_music(nil, -1); end std.mod_done(function(_) instead.music_callback() -- halt music mixer instead.stop_music() instead.stop_sound() -- halt all -- instead.sounds_free(); end) local sounds = {} std.mod_cmd(function(_) if std 'game':time() > 0 then sounds = {} instead.set_sound(); -- empty sound end end) -- aliases local snd = { __gc = function(s) instead.sound_free(s.snd) end; __tostring = function(s) return s.snd end } snd.__index = snd; function snd:play(...) if self.snd then instead.add_sound(self.snd, ...) end end function snd:new(a, b, t) local o = { __save = function() end; } if type(a) == 'string' then o.snd = instead.sound_load(a); elseif type(t) == 'table' then o.snd = instead.sound_load_mem(a, b, t) -- hz, channel, t end -- if not o.snd then -- return -- end std.setmt(o, self) return std.proxy(o) end local sound = std.obj { nam = '@snd'; } sound.set = instead.set_sound sound.play = instead.add_sound sound.stop = instead.stop_sound sound.music = function(mus, loop) if mus == nil and loop == nil then return instead.get_music() end return instead.set_music(mus, loop) end sound.stop_music = instead.stop_music sound.music_fading = function(o, i) if o == nil and i == nil then return instead.get_music_fading() end return instead.set_music_fading(o, i) end function sound.new(...) local s = snd:new(...) std.table.insert(sounds, s) -- avoid __gc in this step return s end function sound.music_callback(...) return instead.music_callback(...) end function sound.free(key) return instead.sound_free(key); end function sound.music_playing() return instead.__music ~= nil and instead.__music_loop ~= -1 end function sound.playing(s,...) if type(s) ~= 'number' then return instead.is_sound() end return instead.sound_channel(s,...) end function sound.pan(c, l, r, ...) return instead.sound_panning(c, l, r, ...) end function sound.vol(v, ...) return instead.sound_volume(v, ...) end instead-3.5.2+dfsg/stead/stead3/ext/sprites.lua000066400000000000000000000352111467622671600213710ustar00rootroot00000000000000local std = stead local type = std.type local instead = std.ref '@instead' -- luacheck: read globals instead_theme_var -- luacheck: read globals instead_theme_name -- luacheck: read globals instead_ticks -- luacheck: read globals instead_font_load -- luacheck: read globals instead_font_free -- luacheck: read globals instead_font_scaled_size -- luacheck: read globals instead_sprite_alpha -- luacheck: read globals instead_sprite_dup -- luacheck: read globals instead_sprite_scale -- luacheck: read globals instead_sprite_rotate -- luacheck: read globals instead_sprite_text -- luacheck: read globals instead_sprite_text_size -- luacheck: read globals instead_sprite_draw -- luacheck: read globals instead_sprite_copy -- luacheck: read globals instead_sprite_compose -- luacheck: read globals instead_sprite_fill -- luacheck: read globals instead_sprite_pixel -- luacheck: read globals instead_sprite_load -- luacheck: read globals instead_sprite_free -- luacheck: read globals instead_sprite_size -- luacheck: read globals instead_sprites_free -- luacheck: read globals instead_sprite_colorkey -- luacheck: read globals instead_sprite_pixels -- luacheck: read globals instead_mouse_pos -- luacheck: read globals instead_mouse_show -- luacheck: read globals instead_mouse_filter -- luacheck: read globals instead_finger_pos -- luacheck: read globals instead_noise1 -- luacheck: read globals instead_noise2 -- luacheck: read globals instead_noise3 -- luacheck: read globals instead_noise4 -- luacheck: read globals instead_render_callback -- luacheck: read globals instead_direct -- luacheck: read globals instead_busy -- luacheck: read globals instead_sprite_pixels -- luacheck: read globals instead_screen_size -- luacheck: read globals instead_screen_dpi -- theme instead.theme_var = instead_theme_var instead.theme_name = instead_theme_name instead.screen_size = instead_screen_size instead.screen_dpi = instead_screen_dpi local theme = std.obj { nam = '@theme'; vars = {}; { reset_vars = {}; }; { win = { gfx = {}}; inv = { gfx = {}}; menu = { gfx = {}}; gfx = {}; snd = {}; scr = {}; }; } function theme.restore(name) if type(name) ~= 'string' then std.err("Wrong parameter to theme.restore", 2) end local v = theme.vars[name] if not v then return end if not theme.reset_vars[name] then theme.reset_vars[name] = instead.theme_var(name) end instead.theme_var(name, v); end function theme.set(name, val) if type(name) ~= 'string' or val == nil then std.err("Wrong parameter to theme.set", 2) end theme.vars[name] = std.tostr(val); theme.restore(name) end function theme.reset(name) if type(name) ~= 'string' then std.err("Wrong parameter to theme.reset", 2) end if not theme.vars[name] then return end local v = theme.reset_vars[name] if v then instead.theme_var(name, v); end theme.vars[name] = nil theme.reset_vars[name] = nil end function theme.name(...) return instead.theme_name(...); end function theme.get(...) return instead.theme_var(...); end function theme.scr.w() return tonumber(theme.get 'scr.w') end function theme.scr.h() return tonumber(theme.get 'scr.h') end function theme.win.reset() std.for_all(theme.reset, "win.x", "win.y", "win.w", "win.h", "win.col.fg", "win.col.link", "win.col.alink", "win.fnt.name", "win.fnt.size", "win.fnt.height"); end function theme.win.geom(x, y, w, h) theme.set("win.x", x); theme.set("win.y", y); theme.set("win.w", w); theme.set("win.h", h); end function theme.win.color(fg, link, alink) theme.set("win.col.fg", fg); theme.set("win.col.link", link); theme.set("win.col.alink", alink); end function theme.win.font(name, size, height) theme.set("win.fnt.name", name); theme.set("win.fnt.size", size); theme.set("win.fnt.height", height); end function theme.win.gfx.reset() std.for_all(theme.reset, "win.gfx.up", "win.up.x", "win.up.y"); std.for_all(theme.reset, "win.gfx.down", "win.down.x", "win.down.y"); end function theme.win.gfx.up(pic, x, y) theme.set("win.gfx.up", pic); theme.set("win.up.x", x); theme.set("win.up.y", y); end function theme.win.gfx.down(pic, x, y) theme.set("win.gfx.down", pic); theme.set("win.down.x", x); theme.set("win.down.y", y); end function theme.inv.reset() std.for_all(theme.reset, "inv.x", "inv.y", "inv.w", "inv.h", "inv.col.fg", "inv.col.link", "inv.col.alink", "inv.fnt.name", "inv.fnt.size", "inv.fnt.height", "inv.mode"); end function theme.inv.geom(x, y, w, h) theme.set("inv.x", x); theme.set("inv.y", y); theme.set("inv.w", w); theme.set("inv.h", h); end function theme.inv.color(fg, link, alink) theme.set("inv.col.fg", fg); theme.set("inv.col.link", link); theme.set("inv.col.alink", alink); end function theme.inv.font(name, size, height) theme.set("inv.fnt.name", name); theme.set("inv.fnt.size", size); theme.set("inv.fnt.height", height); end function theme.inv.mode(mode) theme.set("inv.mode", mode); end function theme.inv.gfx.reset() std.for_all(theme.reset, "inv.gfx.up", "inv.up.x", "inv.up.y"); std.for_all(theme.reset, "inv.gfx.down", "inv.down.x", "inv.down.y"); end function theme.inv.gfx.up(pic, x, y) theme.set("inv.gfx.up", pic); theme.set("inv.up.x", x); theme.set("inv.up.y", y); end function theme.inv.gfx.down(pic, x, y) theme.set("inv.gfx.down", pic); theme.set("inv.down.x", x); theme.set("inv.down.y", y); end function theme.menu.reset() std.for_all(theme.reset, "menu.bw", "menu.col.fg", "menu.col.bg", "menu.col.alpha", "menu.col.link", "menu.col.alink", "menu.fnt.name", "menu.fnt.size", "menu.fnt.height"); end function theme.menu.bw(w) theme.set("menu.bw", w) end function theme.menu.color(fg, bg, alpha, link, alink) theme.set("menu.col.fg", fg); theme.set("menu.col.bg", bg); theme.set("menu.col.alpha", alpha); theme.set("menu.col.link", link); theme.set("menu.col.alink", alink); end function theme.menu.font(name, size, height) theme.set("menu.fnt.name", name); theme.set("menu.fnt.size", size); theme.set("menu.fnt.height", height); end function theme.menu.gfx.reset() std.for_all(theme.reset, "menu.gfx.button", "menu.button.x", "menu.button.y"); end function theme.menu.gfx.button(b, x, y) theme.set("menu.gfx.button", b); theme.set("menu.button.x", x); theme.set("menu.button.y", y); end; function theme.gfx.reset() std.for_all(theme.reset, "scr.gfx.cursor.normal", "scr.gfx.cursor.use", "scr.gfx.cursor.x", "scr.gfx.cursor.y", "scr.gfx.mode", "scr.gfx.pad", "scr.gfx.bg"); end function theme.gfx.cursor(norm, use, x, y) theme.set("scr.gfx.cursor.normal", norm); theme.set("scr.gfx.cursor.use", use); theme.set("scr.gfx.cursor.x", x); theme.set("scr.gfx.cursor.y", y); end function theme.gfx.mode(mode) theme.set("scr.gfx.mode", mode); end function theme.gfx.pad(pad) theme.set("scr.gfx.pad", pad); end function theme.gfx.bg(bg) theme.set("scr.gfx.bg", bg); end function theme.snd.reset() theme.reset("snd.click"); end function theme.snd.click(w) theme.set("snd.click", w); end -- sprites instead.ticks = instead_ticks instead.font_load = instead_font_load instead.font_free = instead_font_free instead.font_scaled_size = instead_font_scaled_size instead.sprite_alpha = instead_sprite_alpha instead.sprite_dup = instead_sprite_dup instead.sprite_scale = instead_sprite_scale instead.sprite_rotate = instead_sprite_rotate instead.sprite_text = instead_sprite_text instead.sprite_text_size = instead_sprite_text_size instead.sprite_draw = instead_sprite_draw instead.sprite_copy = instead_sprite_copy instead.sprite_compose = instead_sprite_compose instead.sprite_fill = instead_sprite_fill instead.sprite_pixel = instead_sprite_pixel instead.sprite_load = instead_sprite_load instead.sprite_free = instead_sprite_free instead.sprite_size = instead_sprite_size instead.sprites_free = instead_sprites_free instead.sprite_colorkey = instead_sprite_colorkey instead.sprite_pixels = instead_sprite_pixels instead.mouse_pos = instead_mouse_pos instead.mouse_show = instead_mouse_show instead.mouse_filter = instead_mouse_filter instead.finger_pos = instead_finger_pos instead.noise1 = instead_noise1 instead.noise2 = instead_noise2 instead.noise3 = instead_noise3 instead.noise4 = instead_noise4 instead.render_callback = instead_render_callback instead.direct = instead_direct std.busy = instead_busy local spr = { __gc = function(s) instead.sprite_free(s.spr) end; __tostring = function(s) return s.spr end; } spr.__index = spr local fnt = { __gc = function(s) instead.font_free(s.fnt) end; __tostring = function(s) return s.fnt end; } fnt.__index = fnt local spr_get = function(s) if type(s) == 'string' then return s end return std.tostr(s) end function fnt:new(nam) if type(nam) ~= 'string' then std.err("Wrong argument to fnt:new(): "..std.tostr(nam), 2) end local o = { fnt = nam; __save = function() end; } std.setmt(o, self) return std.proxy(o) end function fnt:text(text, col, style, ...) return spr:new(instead.sprite_text(self.fnt, text, col, style, ...)) end function fnt:size(...) return instead.sprite_text_size(self.fnt, ...); end function fnt:height(...) local _, h = self:size(...) return h end function spr:new(nam) if type(nam) ~= 'string' then std.err("Wrong argument to spr:new(): "..std.tostr(nam), 2) end local o = { spr = nam; __save = function() end; } std.setmt(o, self) return std.proxy(o) end; function spr:alpha(alpha, ...) return spr:new(instead.sprite_alpha(self.spr, alpha, ...)); end function spr:colorkey(color, ...) instead.sprite_colorkey(self.spr, color, ...); return self end function spr:dup(...) return spr:new(instead.sprite_dup(self.spr, ...)); end function spr:scale(xs, ys, smooth, ...) if smooth == nil then smooth = true -- default is on end return spr:new(instead.sprite_scale(self.spr, xs, ys, smooth,...)); end function spr:rotate(angle, smooth, ...) if smooth == nil then smooth = true -- default is on end return spr:new(instead.sprite_rotate(self.spr, angle, smooth, ...)); end function spr:size() return instead.sprite_size(self.spr); end function spr:draw(fx, fy, fw, fh, d, x, y, alpha) if d == nil and x == nil and y == nil then d, x, y, alpha = fx, fy, fw, fh fx, fy, fw, fh = 0, 0, -1, -1 end instead.sprite_draw(self.spr, fx, fy, fw, fh, spr_get(d), x, y, alpha); return d end function spr:copy(fx, fy, fw, fh, d, x, y) if d == nil and x == nil and y == nil then d, x, y = fx, fy, fw fx, fy, fw, fh = 0, 0, -1, -1 end instead.sprite_copy(self.spr, fx, fy, fw, fh, spr_get(d), x, y); return d end function spr:compose(fx, fy, fw, fh, d, x, y) if d == nil and x == nil and y == nil then d, x, y = fx, fy, fw fx, fy, fw, fh = 0, 0, -1, -1 end instead.sprite_compose(self.spr, fx, fy, fw, fh, spr_get(d), x, y); return d end function spr:fill(x, y, w, h, col) if h == nil and col == nil then instead.sprite_fill(self.spr, 0, 0, -1, -1, x); return self end instead.sprite_fill(self.spr, x, y, w, h, col); return self end function spr:pixel(x, y, col, alpha) if not col then return instead.sprite_pixel(self.spr, x, y, col, alpha) end instead.sprite_pixel(self.spr, x, y, col, alpha) return self end local screen = spr:new 'screen' local sprite = { nam = '@sprite'; } function sprite.new(w, h, ...) if std.tonum(w) and std.tonum(h) then local t = 'blank:'..std.tostr(std.math.floor(w))..'x'..std.tostr(std.math.floor(h)) return spr:new(instead.sprite_load(t)) end local sp = instead.sprite_load(w, h, ...) if not sp then std.err("Can not load sprite: "..std.tostr(w), 2); end return spr:new(sp) end function sprite.fnt(name, sz, ...) if not std.tonum(sz) then std.err("No font size specified in sprite:fnt().", 2) end local fn = instead.font_load(name, sz, ...) if not fn then std.err("Can not load font: "..std.tostr(name), 2); end return fnt:new(fn) end function sprite.scr() return screen end function sprite.direct(v) return instead.direct(v) end function sprite.font_scaled_size(size) return instead.font_scaled_size(size); end local render_cb = nil function sprite.render_callback(fn) local old = render_cb render_cb = fn instead.render_callback(render_cb) return old end std.obj(sprite) instead.sprite_pixels = instead_sprite_pixels local pfnt = { } pfnt.__index = pfnt std.setmt(pfnt, fnt) local pxl = { } pxl.__index = pxl function pxl:dup() local w, h, s = self:size() local p = instead.sprite_pixels(w, h, s) if p then self:copy(p) end return self:new(p) end function pxl:sprite(...) return sprite.new(self, false, ...) end function pxl:tosprite(...) return sprite.new(self, true, ...) end function pxl:draw_spr(fx, fy, fw, fh, d, x, y, alpha) if d == nil and x == nil and y == nil then instead.sprite_draw(self, 0, 0, -1, -1, spr_get(fx), fy, fw, fh); return fx end instead.sprite_draw(self, fx, fy, fw, fh, spr_get(d), x, y, alpha); return d end function pxl:copy_spr(fx, fy, fw, fh, d, x, y, alpha) if d == nil and x == nil and y == nil then instead.sprite_copy(self, 0, 0, -1, -1, spr_get(fx), fy, fw, fh); return fx end instead.sprite_copy(self, fx, fy, fw, fh, spr_get(d), x, y, alpha); return d end function pxl:compose_spr(fx, fy, fw, fh, d, x, y, alpha) if d == nil and x == nil and y == nil then instead.sprite_compose(self, 0, 0, -1, -1, spr_get(fx), fy, fw, fh); return fx end instead.sprite_compose(self, fx, fy, fw, fh, spr_get(d), x, y, alpha); return d end function pxl:scale(...) return pxl:new(self:new_scaled(...)) end function pxl:rotate(...) return pxl:new(self:new_rotated(...)) end local function poly(self, fn, t, ...) if type(t) ~= 'table' then std.err("Wrong argument to :poly()", 3) end if #t < 4 then return end local n = #t for i = 1, n, 2 do if i == n - 1 then fn(self, t[i], t[i+1], t[1], t[2], ...); else fn(self, t[i], t[i+1], t[i+2], t[i+3], ...); end end end function pxl:poly(t, ...) poly(self, self.line, t, ...) end function pxl:polyAA(t, ...) poly(self, self.lineAA, t, ...) end function pxl:new(p) if type(p) ~= 'userdata' then return end local t = getmetatable(p).__index setmetatable(t, self) return p end function pfnt:new(nam) return fnt.new(self, nam) end function pfnt:text(text, col, style, ...) local s = self return pxl:new(instead.sprite_pixels(instead.sprite_text(s.fnt, text, col, style, ...))) end local pixels = { nam = '@pixels'; } function pixels.fnt(name, sz, ...) if not std.tonum(sz) then std.err("No font size specified.", 2) end return pfnt:new(instead.font_load(name, -sz, ...)) end function pixels.new(...) return pxl:new(instead.sprite_pixels(...)) end std.obj (pixels) local rnd_seed = 1980 + 1978 stead.mod_init(function() rnd_seed = (std.os.time(stead.os.date("*t")) + rnd_seed + instead.ticks()) std.rnd_seed(rnd_seed) end) stead.mod_done(function() sprite.render_callback() -- stop render -- instead.sprites_free(); end) instead-3.5.2+dfsg/stead/stead3/ext/timer.lua000066400000000000000000000020521467622671600210150ustar00rootroot00000000000000-- raw iface to timer -- luacheck: read globals instead_timer local std = stead local type = std.type local instead = std.ref '@instead' instead.timer = instead_timer local timer = std.obj { nam = '@timer'; ini = function(s) if s.__timer then s:set(s.__timer) end end; get = function(s) return s.__timer or 0; end; stop = function(s) return s:set(0) end; set = function(s, v) if type(v) ~= 'number' then std.err("Wrong argument to timer:set(): "..std.tostr(v), 2) end s.__timer = v instead.timer(s.__timer) return true end; callback = function(_) return '@timer' end } std.timer = function() -- sdl part call this one if std.type(timer.callback) == 'function' then return timer:callback(); end return end std.mod_done(function(_) timer:stop() end) std.mod_cmd(function(cmd) if cmd[1] ~= '@timer' then return end local r, v = std.call(stead.here(), 'timer'); if not r and not v then r, v = stead.call(std.game, 'timer'); end if not r and not v then -- nothing todo return nil, false end return r, v end) instead-3.5.2+dfsg/stead/stead3/finger.lua000066400000000000000000000040001467622671600203420ustar00rootroot00000000000000-- luacheck: globals finger local std = stead local input = std.ref '@input' local table = table local instead = std.ref '@instead' finger = std.obj { nam = '@finger'; { fingers_list = { }; }; -- luacheck: no unused args filter = function(s, press, fid, x, y, px, py) -- by default, all finger events -- luacheck: unused args return true end } function finger:event(press, fid, x, y, px, py) local s = self if press then local v = s:lookup(fid) if v then v.x, v.y, v.px, v.py = x, y, px, py else table.insert(s.fingers_list, { id = fid, x = x, y = y, px = px, py = py }) end return end local _, k = s:lookup(fid) if k then table.remove(s.fingers_list, k) end end function finger:list() local s = self local new = {} for _, v in std.ipairs(s.fingers_list) do local x, y, pressure = instead.finger_pos(v.id) if x then v.x, v.y, v.pressure = x, y, pressure table.insert(new, v) end end s.fingers_list = new return new end function finger:get(fid) local s = self local _, k local x, y, pressure = instead.finger_pos(fid) if not x then _, k = s:lookup(fid) if k then table.remove(s.fingers_list, k) end return end return x, y, pressure end function finger:lookup(fid) local s = self for k, v in std.ipairs(s.fingers_list) do if v.id == fid then return v, k end end end function input:finger(press, fid, x, y, px, py, ...) local a finger:event(press, fid, x, y, px, py, ...) if not finger:filter(press, fid, x, y, px, py, ...) then return end for _, v in std.ipairs {press, fid, x, y, px, py, ...} do a = (a and (a..', ') or ' ') .. std.dump(v) end return '@finger'.. (a or '') end std.mod_cmd(function(cmd) if cmd[1] ~= '@finger' then return end local r, v r, v = std.call(std.here(), 'onfinger', cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]) if not r and not v then r, v = std.call(std.game, 'onfinger', cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]) end if not r and not v then -- nothing todo return nil, false end return r, v end) instead-3.5.2+dfsg/stead/stead3/fmt.lua000066400000000000000000000043331467622671600176670ustar00rootroot00000000000000local std = stead local type = std.type local iface = std.ref '@iface' -- luacheck: globals fmt fmt = std.obj { nam = '@format'; para = false; nopara = '_'; para_space = ' '; quotes = true; dash = true; filter = nil; } std.obj { nam = '$fmt'; act = function(_, w, ...) if type(w) ~= 'string' or not fmt[w] then return w end return fmt[w](...) end } std.format = function(r, state) local utf8 = (std.ref 'game'.codepage == 'UTF-8' or std.ref 'game'.codepage == 'utf-8') if type(r) ~= 'string' then return r end if type(fmt.filter) == 'function' then r = fmt.filter(r, state) end if utf8 then if fmt.dash then r = r:gsub("%-%-%-*", { ['--'] = '—' }) r = r:gsub("[ \t]+—", iface:nb('').."—"); -- do not break dash r = r:gsub("^([^ \t]*)—[ \t]+", "%1— "); r = r:gsub("(\n[^ \t]*)—[ \t]+", "%1— "); end if fmt.quotes then r = r:gsub('_"','«'):gsub('"_',"»"); r = r:gsub('"([^"]*)"','«%1»'); r = r:gsub(',,','„'):gsub("''",'”'); end end if not state then return r end if fmt.para then r = r:gsub('\n([^\n])', '\001%1'):gsub('\001[ \t]*'..fmt.nopara,'\n'): gsub('\001[ \t]*', '\n'..iface:nb(fmt.para_space)); r = r:gsub('^[ \t]*', '\001'):gsub('\001[ \t]*'..fmt.nopara,''): gsub('\001[ \t]*', iface:nb(fmt.para_space)); end return r end function fmt.em(str) return iface:em(str) end function fmt.c(str) return iface:center(str) end function fmt.j(str) return iface:just(str) end function fmt.l(str) return iface:left(str) end function fmt.r(str) return iface:right(str) end function fmt.b(str) return iface:bold(str) end function fmt.top(str) return iface:top(str) end function fmt.bottom(str) return iface:bottom(str) end function fmt.middle(str) return iface:middle(str) end function fmt.nb(str) return iface:nb(str) end function fmt.anchor(str) return iface:anchor(str) end function fmt.img(str) return iface:img(str) end function fmt.imgl(str) return iface:imgl(str) end function fmt.imgr(str) return iface:imgr(str) end function fmt.u(str) return iface:under(str) end function fmt.st(str) return iface:st(str) end function fmt.tab(str, al) return iface:tab(str, al) end function fmt.y(str, al) return iface:y(str, al) end instead-3.5.2+dfsg/stead/stead3/keys.lua000066400000000000000000000021221467622671600200460ustar00rootroot00000000000000local std = stead local input = std.ref '@input' -- luacheck: globals keys keys = std.obj { nam = '@keys'; { __alt = false; __ctrl = false; __shift = false; __state = {}; }; state = function(s, key) return s.__state[key] or false end; event = function(s, press, key) if key:find 'alt' then key = 'alt' elseif key:find 'ctrl' then key = 'ctrl' elseif key:find 'shift' then key = 'shift' end s.__state[key] = press end; -- luacheck: no unused args filter = function(s, press, key) -- luacheck: unused args return false end } function input:key(press, key) local a keys:event(press, key) if not keys:filter(press, key) then return end for _, v in std.ipairs {press, key} do a = (a and (a..', ') or ' ') .. std.dump(v) end return '@key'.. (a or '') end std.mod_cmd(function(cmd) if cmd[1] ~= '@key' then return end local r, v r, v = std.call(std.here(), 'onkey', cmd[2], cmd[3]) if not r and not v then r, v = std.call(std.game, 'onkey', cmd[2], cmd[3]) end if not r and not v then -- nothing todo return nil, false end return r, v end) instead-3.5.2+dfsg/stead/stead3/noinv.lua000066400000000000000000000006571467622671600202370ustar00rootroot00000000000000local std = stead std.mod_step(function(state) if not state then return end if std.here().noinv and not std.me().__inv_disabled then std.me():close() std.me().__inv_disabled = true elseif std.me().__inv_disabled and not std.here().noinv then std.me():open() std.me().__inv_disabled = nil end end) std.mod_done(function() if std.me().__inv_disabled then std.me():open() std.me().__inv_disabled = nil end end) instead-3.5.2+dfsg/stead/stead3/nolife.lua000066400000000000000000000005021467622671600203470ustar00rootroot00000000000000local std = stead std.mod_step(function(state) if not state then return end if std.here().nolife and std.game:live() then std.game:lifeoff() elseif not std.game:live() and not std.here().nolife then std.game:lifeon() end end) std.mod_done(function() if not std.game:live() then std.game:lifeon() end end) instead-3.5.2+dfsg/stead/stead3/prefs.lua000066400000000000000000000017501467622671600202200ustar00rootroot00000000000000-- luacheck: globals prefs local std = stead local preferences = std.obj { nam = '@prefs', load = function(_) local name = std.savepath() .. '/prefs'; local f, err = std.loadfile(name); if not f then return false, err end local strict = std.nostrict; std.nostrict = true f(); std.nostrict = strict return true end, store = function(s) return s:save() end, save = function(s) -- save prefs on every save local name = std.savepath() .. '/prefs'; local name_tmp = name..'.tmp' local fp, _ = std.io.open(name_tmp, "wb"); if not fp then return false end std.obj.save(s, fp, 'std "@prefs"') fp:flush(); fp:close(); std.os.remove(name) return std.os.rename(name_tmp, name); end, purge = function(_) local name = std.savepath() .. '/prefs'; return std.os.remove(name); end }; local loaded std.mod_start(function() loaded = prefs:load() end) std.mod_done(function() if loaded then prefs:store() loaded = false end end) prefs = preferences instead-3.5.2+dfsg/stead/stead3/snapshots.lua000066400000000000000000000022711467622671600211220ustar00rootroot00000000000000-- luacheck: globals snapshots local std = stead local SNAPSHOT = false local INWRITE = false local snap = std.obj { nam = '@snapshots'; data = {}; save = function(s, ...) if INWRITE then return end return std.obj.save(s, ...) end; write = function(s, name) name = name or 'default' local fp = { -- fake file object data = ''; write = function(self, str) self.data = self.data .. str end; } INWRITE = true std:save(fp) INWRITE = false s.data[name] = fp.data end; make = function(_, name) SNAPSHOT = name or 'default' end; exists = function(s, name) name = name or 'default' return s.data[name] end; remove = function(s, name) name = name or 'default' s.data[name] = nil end; restore = function(s, name) -- like std:load() name = name or 'default' if not s:exists(name) then return false end std:reset() std.ref 'game':__ini() local f, err = std.eval(s.data[name]) if not f then std.err(err, 2) end f(); std.ref 'game':__ini() std.ref 'game':__start(true) return std.nop() end; } snapshots = snap std.mod_cmd(function() if SNAPSHOT then snap:write(SNAPSHOT) SNAPSHOT = nil end end) -- std.mod_done(function() -- end) instead-3.5.2+dfsg/stead/stead3/snd.lua000066400000000000000000000000571467622671600176640ustar00rootroot00000000000000-- luacheck: globals snd snd = stead.ref '@snd'instead-3.5.2+dfsg/stead/stead3/sprite.lua000066400000000000000000000001351467622671600204030ustar00rootroot00000000000000-- luacheck: globals sprite pixels sprite = stead.ref '@sprite' pixels = stead.ref '@pixels' instead-3.5.2+dfsg/stead/stead3/stdlib.lua000066400000000000000000000247451467622671600203730ustar00rootroot00000000000000-- luacheck: read globals declare local std = stead local type = std.type -- luacheck: read globals game std.rawset(_G, 'std', stead) -- luacheck: globals include include = std.include -- luacheck: globals loadmod loadmod = std.loadmod -- luacheck: globals rnd rnd = std.rnd -- luacheck: globals rnd_seed rnd_seed = std.rnd_seed -- luacheck: globals p p = std.p -- luacheck: globals pr pr = std.pr -- luacheck: globals pn pn = std.pn -- luacheck: globals pf pf = std.pf -- luacheck: globals obj obj = std.obj -- luacheck: globals stat stat = std.stat -- luacheck: globals room room = std.room -- luacheck: globals menu menu = std.menu -- luacheck: globals dlg dlg = std.dlg -- luacheck: globals me me = std.me -- luacheck: globals here here = std.here -- luacheck: globals from from = std.from -- luacheck: globals new new = std.new -- luacheck: globals delete delete = std.delete -- nameof = std.nameof -- dispof = std.dispof -- titleof = std.titleof -- luacheck: globals gamefile gamefile = std.gamefile -- luacheck: globals player player = std.player -- luacheck: globals dprint dprint = std.dprint local function _pfn(f1, f2, ...) local a = {...} if type(f2) == 'string' then return function() f1() std.p(f2, std.unpack(a)) end end if type(f2) ~= 'function' then return f1() end return function(f3, ...) return _pfn(function() f1() f2(std.unpack(a)) end, f3, ...) end end -- luacheck: globals pfn function pfn(f, ...) local a = {...} if type(f) == 'function' then return _pfn(function() end, f, ...) end return function() std.p(f, std.unpack(a)) end end -- luacheck: globals from function from(ww) local wh ww = ww or std.here() wh = std.ref(ww) if not std.is_obj(wh, 'room') then std.err("Wrong argument to from(): "..std.tostr(wh), 2) end return wh:from() end; local function walkroom(w) if std.is_tag(w) then local ww = std.here().way:lookup(w) if not ww then std.err("Can not found tag: "..std.tostr(w), 3) end return ww end return w end -- luacheck: globals visits function visits(w) if not w then return std.here():visits() end return std.object(walkroom(w)):visits() end -- luacheck: globals visited function visited(w) if not w then return std.here():visited() end return std.object(walkroom(w)):visited() end -- luacheck: globals walk function walk(w, ...) local r, v = std.me():walk(walkroom(w), ...) if std.cctx() and type(r) == 'string' then std.p(r) end return r, v end -- luacheck: globals life_walk function life_walk(w, ...) game:reaction(false) game:events(false, false) return walk(w, ...) end -- luacheck: globals walkin function walkin(w, ...) local r, v = std.me():walkin(walkroom(w), ...) if std.cctx() and type(r) == 'string' then std.p(r) end return r, v end -- luacheck: globals walkout function walkout(w, ...) local r, v = std.me():walkout(walkroom(w), ...) if std.cctx() and type(r) == 'string' then std.p(r) end return r, v end -- luacheck: globals walkback function walkback(w, ...) return walkout(w, false, ...) end std.walkout = walkout std.walkin = walkin std.walk = walk local function object(w) local o if std.is_tag(w) then o = std.here():lookup(w) if not o then o = std.me():lookup(w) end if not o then std.err("Wrong tag: "..w, 3) end return o end o = std.ref(w) if not o then std.err("Wrong object: "..std.tostr(w), 3) end return o end std.object = object -- luacheck: globals _ _ = std.object -- luacheck: globals for_all for_all = std.for_all -- luacheck: globals seen function seen(w, ww) local wh ww = ww or std.here() if not std.is_obj(ww, 'list') then wh = std.ref(ww) else return ww:srch(w) end if not std.is_obj(wh) then std.err("Wrong 2-nd argument to seen(): "..std.tostr(ww), 2) end return wh:srch(w) end -- luacheck: globals lookup function lookup(w, ww) local wh ww = ww or std.here() if not std.is_obj(ww, 'list') then wh = std.ref(ww) else return ww:lookup(w) end if not std.is_obj(wh) and not std.is_obj(wh, 'list') then std.err("Wrong 2-nd argument to lookup(): "..std.tostr(ww), 2) end return wh:lookup(w) end -- luacheck: globals ways function ways(ww) local wh ww = ww or std.here() wh = std.ref(ww) if not std.is_obj(wh, 'room') then std.err("Wrong 2-nd argument to ways(): "..std.tostr(ww), 2) end return wh.way end std.ways = ways -- luacheck: globals objs function objs(ww) local wh ww = ww or std.here() wh = std.ref(ww) if not std.is_obj(wh) then std.err("Wrong 2-nd argument to objs(): "..std.tostr(ww), 2) end return wh.obj end -- luacheck: globals inspect function inspect(w, ...) return std.me():inspect(std.object(w), ...) end -- luacheck: globals have function have(w, ...) return std.me():have(std.object(w), ...) end -- luacheck: globals inroom function inroom(w, ...) return std.object(w):inroom(...) end -- luacheck: globals where function where(w, ...) return std.object(w):where(...) end -- luacheck: globals closed function closed(w) return std.object(w):closed() end -- luacheck: globals disabled function disabled(w) return std.object(w):disabled() end -- luacheck: globals enable function enable(w) return std.object(w):enable() end -- luacheck: globals disable function disable(w) return std.object(w):disable() end -- luacheck: globals open function open(w) return std.object(w):open() end -- luacheck: globals close function close(w) return std.object(w):close() end -- luacheck: globals actions function actions(w, t, v) return std.object(w):actions(t, v) end -- luacheck: globals pop function pop(w, ww) local wh = ww or std.here() if not std.is_obj(wh, 'dlg') then std.err("Call pop() in non-dialog object: "..std.tostr(wh), 2) end local r, v = wh:pop(w) if std.cctx() and type(r) == 'string' then std.p(r) end return r, v end -- luacheck: globals push function push(w, ww) local wh = ww or std.here() if not std.is_obj(wh, 'dlg') then std.err("Call push() in non-dialog object: "..std.tostr(wh), 2) end local r, v = wh:push(w) if std.cctx() and type(r) == 'string' then std.p(r) end return r, v end -- luacheck: globals empty function empty(w, ...) if not w then return std.here():empty() end return std.object(w):empty(...) end -- luacheck: globals lifeon function lifeon(w, ...) return std 'game':lifeon(w and std.object(w), ...) end -- luacheck: globals lifeoff function lifeoff(w, ...) return std 'game':lifeoff(w and std.object(w), ...) end -- luacheck: globals live function live(...) return std 'game':live(...) end -- luacheck: globals change_pl function change_pl(w, ...) return std 'game':set_pl(w and std.object(w), ...) end -- luacheck: globals player_moved function player_moved(pl) pl = pl or std.me() pl = std.ref(pl) if not std.is_obj(pl, 'player') then std.err("Wrong argument to player_moved(): "..std.tostr(pl)) end return std.me():moved() end -- luacheck: globals inv function inv(pl) pl = pl or std.me() pl = std.ref(pl) if not std.is_obj(pl, 'player') then std.err("Wrong argument to inv(): "..std.tostr(pl)) end return pl:inventory() end -- luacheck: globals remove function remove(w, wh) local o = std.object(w) if not w then std.err("Wrong argument to remove(): "..std.tostr(w), 2) end wh = wh and std.object(wh) return o:remove(wh) end -- luacheck: globals purge function purge(w) local o = std.object(w) if not w then std.err("Wrong argument to purge(): "..std.tostr(w), 2) end return o:purge() end local function __place(w, wh, remove) local o = std.object(w) if not o then std.err("Wrong argument to place(): "..std.tostr(w), 3) end if remove then o:remove() -- remove object from everywhere end wh = wh or std.here() if type(wh) ~= 'table' then wh = std.object(wh) end if o:type 'player' then if not std.is_obj(wh) then std.err("Wrong 2-nd argument to place(): "..std.tostr(wh), 3) end o:walk(wh, false, false) return o end if std.is_obj(wh) then wh.obj:add(o) elseif std.is_obj(wh, 'list') then wh:add(o) else std.err("Wrong 2-nd argument to place(): "..std.tostr(wh), 3) end return o end -- luacheck: globals replace function replace(w, ww, wh) local o = std.object(w) if not o then std.err("Wrong argument to replace(): "..std.tostr(w), 2) end local oo = std.object(ww) if not oo then std.err("Wrong argument to replace(): "..std.tostr(ww), 2) end if not wh then -- replace all local l = {} o:where(l) for _, v in std.ipairs(l) do v.obj:replace(o, oo) if std.is_obj(v, 'room') then v.way:replace(o, oo) end end return oo end if type(wh) ~= 'table' then wh = std.object(wh) end if std.is_obj(wh) then local _, l = wh:lookup(o) if l then l:replace(o, oo) return oo end elseif std.is_obj(wh, 'list') then wh:replace(o, oo) return oo else std.err("Wrong 3-rd argument to replace(): "..std.tostr(wh), 3) end end -- luacheck: globals place function place(w, wh) return __place(w, wh, true) end -- luacheck: globals put function put(w, wh) return __place(w, wh, false) end -- luacheck: globals take function take(w) local o = std.object(w) if o then o:actions('take', 1 + o:actions 'take') end return place(w, std.me():inventory()) end -- luacheck: globals drop function drop(w, wh) local o = std.object(w) if o then o:actions('drop', 1 + o:actions 'drop') end return place(w, wh) end -- luacheck: globals path path = std.class({ __path_type = true; new = function(_, t) if type(t) ~= 'table' then std.err("Wrong path argument. Use {} as path argument.", 2) end local n, s, w = t[1], t[2], t[3] if not w then s, w = n, s n = nil end local new = { before = s; walk = w; } for k, v in std.pairs(t) do if type(k) == 'string' then new[k] = v end end new.nam = n or new.nam return std.room(new) end; disp = function(s) local w = s.walk if type(w) == 'function' then w = w() end if disabled(w) or closed(w) then return false end if s.after ~= nil and visited(w) then return std.call(s, 'after') end return std.call(s, 'before') end; onwalk = function(s, _) local w = s.walk if type(w) == 'function' then w = w() end if not disabled(w) and not closed(w) then walk(w) end return false end; }, std.room) -- luacheck: globals time function time(...) return std.ref 'game':time(...) end local xact = std.obj { nam = '@'; { methods = {} }; act = function(s, w, ...) if type(s.methods[w]) ~= 'function' then std.err ("Wrong method to xact", 2) end return s.methods[w](...) end } std.rawset(_G, 'xact', xact.methods) std.mod_init(function() declare { game = std.ref 'game', pl = std.ref 'player', } end) instead-3.5.2+dfsg/stead/stead3/stead.lua000066400000000000000000001666631467622671600202200ustar00rootroot00000000000000-- STEAD3 API -- luacheck: globals iface init start stead -- luacheck: read globals DEBUG doencfile instead_readdir instead_random table_get_maxn instead_srandom stead = { space_delim = ' ', scene_delim = '^^', delim = '|', call_top = 0, call_ctx = { txt = nil, self = nil }, objects = {}; tags = {}; next_dynamic = -1; max_dynamic = 32767; tables = {}; functions = {}; modules = {}; includes = {}; tostr = tostring; tonum = tonumber; type = type; setmt = setmetatable; getmt = getmetatable; table = table; math = math; newproxy = newproxy; pairs = pairs; ipairs = ipairs; rawset = rawset; rawget = rawget; rawequal = rawequal; pcall = pcall; io = io; os = os; readdir = instead_readdir, string = string; next = next; loadfile = loadfile; dofile = dofile; doencfile = doencfile; getinfo = debug.getinfo; __mod_hooks = {}; files = {}; busy = function() end; debug_xref = true; debug_save = false; random = instead_random; randomseed = instead_srandom; } local std = stead std.strip_call = true local error = error function std.err(msg, lev) if std.noerror then std.dprint(msg) else error(msg, lev) end end function std.dprint(...) local a = { ... } for i = 1, #a do if i ~= 1 then std.io.stderr:write(' ') end std.io.stderr:write(std.tostr(a[i])) end std.io.stderr:write('\n') std.io.stderr:flush() end std.rnd = function(...) if std.random then return std.random(...) end return std.math.random(...); end std.rnd_seed = function(...) std.math.randomseed(...) if std.randomseed then return std.randomseed(...) end end function stead:abort() self.abort_cmd = true end function stead.savepath() return "./" end local table = std.table local pairs = std.pairs local ipairs = std.ipairs local string = std.string local rawset = std.rawset local rawget = std.rawget local type = std.type local io = std.io; if _VERSION == "Lua 5.1" then std.eval = loadstring std.unpack = unpack std.proxy = function(o) local oo = std.newproxy(true) local t = std.getmt(oo) t.__index = o t.__newindex = o t.__gc = function(_) o:__gc() end t.__tostring = function(_) return o:__tostring() end o.__proxy_type = true return oo end else std.proxy = function(o) o.__proxy_type = true return o end std.eval = load std.unpack = table.unpack table.maxn = table_get_maxn string.gfind = string.gmatch -- luacheck: push ignore math math.mod = math.fmod math.log10 = function(a) return std.math.log(a, 10) end end math.pow = function(num, n) return num ^ n end math.round = function(num, n) local m = 10 ^ (n or 0) return std.math.floor(num * m + 0.5) / m end -- luacheck: pop local function __mod_callback_reg(f, hook, prio) if type(f) ~= 'function' then std.err ("Wrong parameter to mod_"..hook..".", 3); end if prio and type(prio) ~= 'number' then std.err ("Wrong prio parameter to mod_"..hook..".", 3); end if not std.__mod_hooks[hook] then std.__mod_hooks[hook] = {} end local i = { fn = f, prio = prio, unload = std.__in_include } table.insert(std.__mod_hooks[hook], i); std.sort(std.__mod_hooks[hook], function (a, b) a = a.prio or 0 b = b.prio or 0 if a == b then return nil end return a < b end) -- f(); end function std.mod_unload() local new = {} for k, v in pairs(std.__mod_hooks) do local list = {} for _, vv in ipairs(v) do if not vv.unload then table.insert(list, vv) end end new[k] = list end std.__mod_hooks = new end function std.mod_call(hook, ...) if not std.__mod_hooks[hook] then return end for _, v in ipairs(std.__mod_hooks[hook]) do local a, b = v.fn(...) if a ~= nil or b ~= nil then return a, b end end end function std.mod_call_rev(hook, ...) if not std.__mod_hooks[hook] then return end for i = #std.__mod_hooks[hook], 1, -1 do local v = std.__mod_hooks[hook][i] local a, b = v.fn(...) if a ~= nil or b ~= nil then return a, b end end end function std.mod_init(f, ...) __mod_callback_reg(f, 'init', ...) if std.initialized then -- require from game f(...) end end function std.mod_done(f, ...) __mod_callback_reg(f, 'done', ...) end function std.mod_start(f, ...) __mod_callback_reg(f, 'start', ...) end function std.mod_cmd(f, ...) __mod_callback_reg(f, 'cmd', ...) end function std.mod_step(f, ...) __mod_callback_reg(f, 'step', ...) end function std.mod_save(f, ...) __mod_callback_reg(f, 'save', ...) end function std.hook(o, f) local ff if type(o) ~= 'function' then ff = function() return o end else ff = o end return function(...) return f(ff, ...) end end local substs local function xref_prep(str) local oo, self local a = {} local s = str local i = s:find('\001', 1, true) if not i then return str end oo = std.strip(s:sub(1, i - 1)) s = s:sub(i + 1) if oo:find('@', 1, true) == 1 or oo:find('$', 1, true) then -- call '@' obj (aka xact) or '$' aka subst local o = std.split(oo)[1] local ii = oo:find("[ \t]") if ii then a = std.strip(oo:sub(ii)) a = std.cmd_parse(a) end self = std.ref(o) else if oo:find("^# [0-9-]+") then self = std.ref(std.tonum(oo:sub(3))) elseif std.is_tag(oo) then -- #tag? self = std.here():lookup(oo) else self = std.ref(oo) end end if not std.is_obj(self) then if std.debug_xref then std.err("Wrong object in xref: "..std.tostr(oo), 2) else std.dprint("Wrong xref: "..std.tostr(oo)) return s end end if type(self.nam) == 'string' and self.nam:find('$', 1, true) == 1 then -- subst table.insert(a, s) substs = true local r, v = std.method(self, 'act', std.unpack(a)) if not v then return s end return std.tostr(r) end return iface:xref(s, self, std.unpack(a)); end local fmt_refs local function fmt_prep(str) local s = str:gsub("^{", ""):gsub("}$", "") s = s:gsub('\\?['..std.delim..']', { [std.delim] = '\001' }); local l = s:find('\001', 1, true) if l == 1 then return str end if not l then s = s .. '\001' end l = s:find('\001', 1, true) table.insert(fmt_refs, s:sub(1, l - 1)) local n = string.format("%d%s", #fmt_refs, std.delim) return "{"..n..s:sub(l + 1).."}" end local function fmt_post(str) local s = str:gsub("^{", ""):gsub("}$", ""):gsub('\\?['..std.delim..']', { [std.delim] = '\001' } ); local l = s:find('\001') if not l or l == 1 then return str end local n = std.tonum(s:sub(1, l - 1)) or 0 if not fmt_refs[n] then return str end s = fmt_refs[n]..s:sub(l) return xref_prep(std.unesc(s)) end function std.for_each_xref_outer(s, fn) local orig = s s = string.gsub(s, '\\?[\\{}]', { ['{'] = '\001', ['}'] = '\002', [ '\\{' ] = '\\{', [ '\\}' ] = '\\}' }); local start while true do start = s:find('\001') if not start then break end local idx = 1 local n = start while idx > 0 do n = s:find('[\001\002]', n + 1) if not n then break end if s:sub(n, n) == '\001' then idx = idx + 1 else idx = idx - 1 end end if idx == 0 then local new = fn(s:sub(start, n):gsub('[\001\002]', {['\001'] = '{', ['\002'] = '}'})) if start == 1 then s = new..s:sub(n + 1) else s = s:sub(1, start - 1)..new..s:sub(n + 1) end else std.err("Unpaired '{' in:"..std.tostr(orig), 2) break end end s = s:gsub('[\001\002]', { ['\001'] = '{', ['\002'] = '}' }); return s end function std.for_each_xref(s, fn) s = string.gsub(s, '\\?[\\{}]', { ['{'] = '\001', ['}'] = '\002', [ '\\{' ] = '\\{', [ '\\}' ] = '\\}' }); local function prep(str) str = str:gsub("[\001\002]", "") str = fn('{'..str..'}') return str end s = string.gsub(s, '(\001[^\001\002]+\002)', prep) s = s:gsub('[\001\002]', { ['\001'] = '{', ['\002'] = '}' }); return s end std.fmt = function(str, fmt, state) if type(str) ~= 'string' then return end local s = str s = string.gsub(s, '[\t \n]+', std.space_delim); s = string.gsub(s, '\\?[\\^]', { ['^'] = '\n', ['\\^'] = '^'} ):gsub("\n[ \t]+", "\n") local first = true while true do fmt_refs = {} substs = false s = std.for_each_xref(s, fmt_prep) -- rename all {} if first and type(fmt) == 'function' then s = fmt(s, state) end s = std.for_each_xref(s, fmt_post) -- rename and xref if not substs then break end first = false end s = s:gsub('\\?'..'[{}]', { ['\\{'] = '{', ['\\}'] = '}' }) if state then s = s:gsub('\\?'..std.delim, { ['\\'..std.delim] = std.delim }) end return s end local lua_keywords = { ["and"] = true, ["break"] = true, ["do"] = true, ["else"] = true, ["elseif"] = true, ["end"] = true, ["false"] = true, ["for"] = true, ["function"] = true, ["goto"] = true, ["if"] = true, ["in"] = true, ["local"] = true, ["nil"] = true, ["not"] = true, ["or"] = true, ["repeat"] = true, ["return"] = true, ["then"] = true, ["true"] = true, ["until"] = true, ["while"] = true, } std.setmt(stead, { __call = function(_, k) return std.ref(k) end; }) function std.is_system(v) if not std.is_obj(v) then return false end local n = v.nam if type(n) == 'string' then if n:byte(1) == 0x40 or n:byte(1) == 0x24 then return true end end return false end function std.is_obj(v, t) if type(v) ~= 'table' then return false end return v['__'..(t or 'obj')..'_type'] end function std.class(self, inh) -- self.__parent = function(s) -- return inh -- end; self.nam = '*class*'; self.__call = function(v, n, ...) if std.is_obj(v) and type(n) == 'string' then -- variable access return function(val) if std.game then rawset(v.__var, n, true) rawset(v.__ro, n, nil) return rawset(v, n, val or false) end return rawset(v.__ro, n, val or false) end end n = v:new(n, ...) std.setmt(n, v) return n end; self.__tostring = function(s) if not std.is_obj(s) then local os = self.__tostring self.__tostring = nil local t = std.tostr(s) self.__tostring = os return t end return std.dispof(s) end; self.__pow = function(s, b) if type(b) == 'string' or type(b) == 'number' then if std.is_tag(b) then return std.rawequal(s.tag, b) else return std.rawequal(s.nam, b) end end return std.rawequal(s, b) end; self.__dirty = function(s, v) local o = rawget(s, '__dirty_flag') if v ~= nil then if std.game then rawset(s, '__dirty_flag', v) end return s end return o end; self.__index = function(t, k) local ro = type(rawget(t, '__ro')) == 'table' and t.__ro local v if ro then v = rawget(ro, k) end if v == nil then return self[k] end if ro and std.game and type(v) == 'table' then -- make rw if simple table if type(v.__dirty) ~= 'function' then t.__var[k] = true rawset(t, k, v) ro[k] = nil end end return v end; self.__newindex = function(t, k, v) local ro = std.is_obj(t) and t.__ro if ro and not std.game then rawset(ro, k, v) return end t:__dirty(true) if ro then if (type(v) == 'function' and not std.functions[v]) then std.err("Wrong variable operation: "..std.tostr(k).. " at "..std.tostr(t), 2) end if std.nostrict or (type(k) == 'string' and k:find('^__')) or t.__var[k] or ro[k] ~= nil then t.__var[k] = true else std.err("Set unitialized variable: "..std.tostr(k).." at "..std.tostr(t), 2) end ro[k] = nil end if std.is_obj(v, 'list') and std.is_obj(t) then v:attach(t) end rawset(t, k, v) end std.setmt(self, inh or { __call = self.__call }) return self end function std.is_tag(n) return type(n) == 'string' and n:byte(1) == 0x23 end function std.sort(t, fn) local prio = {} local v for i = 1, #t do v = t[i] prio[i] = { v = v, i = i } end table.sort(prio, function(a, b) local r = fn(a.v, b.v) if type(r) == 'boolean' then return r end return a.i < b.i end) for i = 1, #prio do t[i] = prio[i].v end end std.list = std.class { __list_type = true; new = function(_, v) if type(v) ~= 'table' then std.err ("Wrong argument to std.list:"..std.tostr(v), 2) end if std.is_obj(v, 'list') then -- already list return v end v.__list = {} -- where is attached -- std.setmt(v, s) return v end; __ini = function(s, o) for i = 1, #s do local k = s[i] s[i] = std.ref(k) if not std.is_obj(s[i]) then if not o then std.err("Wrong item in list: "..std.tostr(k), 2) else std.err("Wrong item in list: "..std.tostr(k).." in "..std.dispof(o), 2) end end s:__attach(s[i]) end if o then s:attach(o) end s:sort() end; sort = function(s) std.sort(s, function(a, b) local p1 = std.tonum(a.pri) or 0 local p2 = std.tonum(b.pri) or 0 if p1 == p2 then return nil end return p1 < p2 end) end; display = function(s) local r for i = 1, #s do if r then r = r .. std.space_delim end local o = s[i] if o:visible() then local disp = o:display() local d = o:__xref(disp) if type(d) == 'string' then r = (r or '').. d end if not o:closed() then d = o.obj:display() if type(d) == 'string' then r = (r and (r .. std.space_delim) or '') .. d end end end end return r end; disable = function(s) for i = 1, #s do s[i]:disable() end end; enable = function(s) for i = 1, #s do s[i]:enable() end end; close = function(s) for i = 1, #s do s[i]:close() end end; open = function(s) for i = 1, #s do s[i]:open() end end; attach = function(s, o) -- attach to object s:detach(o) table.insert(s.__list, o) end; detach = function(s, o) -- detach from object for i = 1, #s.__list do if s.__list[i] == o then table.remove(s.__list, i) break end end end; __attach = function(s, o) -- attach object to list s:__detach(o) table.insert(o.__list, s) end; __detach = function(s, o) -- detach object from list for i = 1, #o.__list do if o.__list[i] == s then table.remove(o.__list, i) break end end end; add = function(s, n, pos) local o = s:lookup(n) if o then return o -- already here end if pos then if type(pos) ~= 'number' then std.err("Wrong parameter to list.add:"..std.tostr(pos), 2) end if pos > #s then pos = nil -- add to last position elseif pos < 0 then pos = #s + pos + 1 end if pos and pos <= 0 then pos = 1 end end o = std.ref(n) if not o then std.err("Wrong argument to list:add(): "..std.tostr(n), 2) end s:__dirty(true) s:__attach(o) if pos then table.insert(s, pos, o) else table.insert(s, o) end s:sort() return o end; for_each = function(s, fn, ...) if type(fn) ~= 'function' then std.err("Wrong parameter to list:for_each: "..std.tostr(fn), 2) end for i = 1, #s do local r, v = fn(s[i], ...) if r ~= nil or v ~= nil then return r, v end end end; lookup = function(s, n) local o, tag if std.is_tag(n) then tag = n else o = std.ref(n) end for i = 1, #s do if s[i] == o or (tag and s[i].tag == tag) then return s[i], i end end end; srch = function(s, n) local o, i = s:lookup(n) if not o or not o:visible() then return end return o, i end; empty = function(s) return (#s == 0) end; cat = function(s, from, pos) if not std.is_obj(from, 'list') then std.err("Wrong argument to list:cat(): "..std.tostr(from), 2) end if not pos then pos = #s + 1 end for _, v in ipairs(from) do s:add(v, pos) pos = pos + 1 end return s end; zap = function(s) -- delete all objects local l = {} for i = 1, #s do table.insert(l, s[i]) end for i = 1, #l do s:del(l[i]) end return s end; del = function(s, n) local o, i = s:lookup(n) if i then s:__dirty(true) s:__detach(o) table.remove(s, i) s:sort() return o, i end end; replace = function(s, n, w) local o, i = s:del(n) if o then return s:add(w, i) end end; __dump = function(s, recurse) local rc for i = 1, #s do local v = s[i] if std.is_obj(v) and v:visible() then local vv, n if type(v.nam) == 'number' then n = '# '..std.tostr(v.nam) else n = v.nam end local disp = std.dispof(v) if disp then if rc then rc = rc .. std.delim else rc = '' end vv = '{'..std.esc(n)..std.delim..std.esc(disp)..'}' rc = rc .. vv end if recurse and not v:closed() then vv = v:__dump(recurse) if vv then if rc then rc = rc .. std.delim else rc = '' end rc = rc .. vv end end end end return rc end; __save = function(s, fp, n) if not s:__dirty() then return end fp:write(string.format("%s = std.list { ", n)) for i = 1, #s do local vv = std.deref(s[i]) if not vv then std.err ("Can not do deref on: "..std.tostr(s[i]), 2) end if i ~= 1 then fp:write(string.format(", ")) end if type(vv) == 'number' then fp:write(string.format("%d", vv)) else fp:write(string.format("%q", vv)) end end fp:write(" }:__dirty(true)\n") end; } std.save_var = function(vv, fp, n) if type(vv) == 'boolean' or type(vv) == 'number' then fp:write(string.format("%s = ", n)) fp:write(std.tostr(vv)..'\n') elseif type(vv) == 'string' then fp:write(string.format("%s = ", n)) fp:write(string.format("%q\n", vv)) elseif type(vv) == 'function' then if std.functions[vv] and std.functions[vv] ~= n then local k = std.functions[vv] fp:write(string.format("%s = %s\n", n, k)) else std.err("Can not save variable (function): "..n, 2) end elseif type(vv) == 'table' then if std.tables[vv] and std.tables[vv] ~= n then local k = std.tables[vv] fp:write(string.format("%s = %s\n", n, k)) elseif std.is_obj(vv) then local d = std.deref(vv) if not d then std.err("Can not deref object:"..std.tostr(vv), 2) end fp:write(string.format("%s = ", n)) if type(d) == 'string' then fp:write(string.format("std %q\n", d)) else fp:write(string.format("std(%d)\n", d)) end elseif type(vv.__save) == 'function' then vv:__save(fp, n) else fp:write(string.format("%s = %s\n", n, std.dump(vv, true))) -- std.save_table(vv, fp, n) end elseif vv == nil then fp:write(string.format("%s = nil\n", n)) elseif type(vv) == 'userdata' and type(vv.__save) == 'function' then vv:__save(fp, n) else std.err("Can not save var: "..n, 2) end end std.save_members = function(vv, fp, n) local l for k, v in pairs(vv) do if type(k) == 'number' then l = string.format("%s%s", n, std.varname(k)) std.save_var(v, fp, l) elseif type(k) == 'string' then l = string.format("%s%s", n, std.varname(k)) std.save_var(v, fp, l) end end end std.save_table = function(vv, fp, n) fp:write(string.format("%s = {}\n", n)) std.save_members(vv, fp, n) end function std:reset(fn) -- reset state local reset if std.ref 'game'.__started or fn then self:done() self:init() reset = true end if fn ~= 'main3.lua' then std.startfile = fn -- another start file end if reset then std.dofile(fn or 'main3.lua') end end function std:load(fname) -- load save self:reset() std.ref 'game':__ini() local f, err = std.loadfile(fname) -- load all diffs if not f then std.err(err, 2) end local strict = std.nostrict; std.nostrict = true; if DEBUG then std.noerror = true local st, r = std.pcall(f) if not st then std.dprint(r) end std.noerror = false else f(); end std.nostrict = strict std.ref 'game':__ini(true) std.ref 'game':__start(true) return self.game:lastdisp() end local function in_section(name, fn) name = "__in_"..name local old = std[name] std[name] = true local r, v = fn() std[name] = old or false return r, v end function std.gamefile(fn, reset) -- load game file if type(fn) ~= 'string' then std.err("Wrong paramter to stead:file: "..std.tostr(fn), 2) end if not fn:find("%.lua$") then fn = fn .. '.lua' end if reset then std:reset(fn) std.ref 'game':__ini() local r, v = std.ref 'game':__start() if type(r) == 'string' and std.cctx() then std.pr(r) end return r, v end std.game = nil in_section ('gamefile', function() std.dofile(fn) end) std.ref 'game':__ini() table.insert(std.files, fn) -- remember it end -- luacheck: no self function std:save(fp) local close local name, name_tmp if type(fp) == 'string' then name, name_tmp = fp, fp .. '.tmp' fp = io.open(name_tmp, "wb"); if not fp then return nil, false -- can create file end close = true end local n if std.type(std.savename) == 'function' then n = std.savename() end if std.type(n) == 'string' then fp:write("-- $Name: "..n:gsub("\n","\\n").."$\n"); end fp:write("local std = stead\n"); -- reset if std.startfile then fp:write(string.format("std:reset(%q)\n", std.startfile)) fp:write(string.format("std 'game':ini()\n")) end -- files for i = 1, #std.files do fp:write(string.format("std.gamefile(%q)\n", std.files[i])) end std.busy(true) std.for_each_obj(function(v) if v.__dynamic then std.busy(true) v:save(fp, string.format("std(%s)", std.deref_str(v))) end end) std.mod_call('save', fp) std.for_each_obj(function(v) if not v.__dynamic then std.busy(true) v:save(fp, string.format("std(%s)", std.deref_str(v))) end end) if close then fp:flush(); fp:close(); std.os.remove(name); std.os.rename(name_tmp, name); end std.busy(false) return std.game:lastdisp() -- same scene end local rnd_seed = 1980 + 1978 function std:init() std.rawset(_G, 'iface', std.ref '@iface') -- force iface override std.world { nam = 'game', player = 'player', codepage = 'UTF-8', dsc = [[STEAD3, 2020 by Peter Kosyh^https://instead-hub.github.io^^]] }; std.room { nam = 'main' } std.player { nam = 'player', room = 'main' } rnd_seed = (std.os.time(stead.os.date("*t")) + rnd_seed) std.rnd_seed(rnd_seed) std.mod_call('init') -- init modules std.initialized = true end function std:done() std.mod_call_rev('done') std.mod_unload() -- unload hooks from includes local objects = {} std.for_each_obj(function(v) local k = std.deref(v) if std.is_system(v) then objects[k] = v else std.dprint("Deleting "..k) end end) std.objects = objects std.tags = {} std.next_dynamic = -1 std.files = {} std.startfile = false -- std.modules = {} std.includes = {} std.initialized = false std.game = nil std.rawset(_G, 'init', nil) std.rawset(_G, 'start', nil) end -- luacheck: self function std.for_all(fn, ...) if type(fn) ~= 'function' then std.err("Wrong 1-st argument to for_all(): "..std.tostr(fn), 2) end local a = {...} for i = 1, #a do fn(a[i]) end end function std.for_each_obj(fn, ...) local oo = std.objects for _, v in pairs(oo) do if std.is_obj(v) then local a, b = fn(v, ...) if a ~= nil and b ~= nil then return a, b end end end end function std.dirty(o) if type(o) ~= 'table' or type(o.__dirty) ~= 'function' then return false end return o:__dirty() end function std.deref_str(o) local k = std.deref(o) if type(k) == 'number' then return std.tostr(k) elseif type(k) == 'string' then return std.string.format("%q", k) end return end function std.varname(k) if type(k) == 'number' then return string.format("[%d]", k) elseif type(k) == 'string' then if not lua_keywords[k] then return string.format(".%s", k) else return string.format("[%q]", k) end end end local function next_dynamic(n) if n then std.next_dynamic = n end std.next_dynamic = std.next_dynamic - 1 if std.next_dynamic < -std.max_dynamic then std.next_dynamic = - 1 end return std.next_dynamic end local function dyn_name() local oo = std.objects if not oo[std.next_dynamic] then local n = std.next_dynamic next_dynamic() return n end local on = std.next_dynamic local n = next_dynamic() while oo[n] and n ~= on do n = n - 1 if n < -std.max_dynamic then n = -1 end end if oo[n] then std.err("No free ids for dynamic objects", 2) end next_dynamic(n) return n end local function tag_name(t) local oo = std.objects local tt = std.tags[t] or {} local n = t:sub(2) .. '#'..std.tonum(#tt) if oo[n] then return #oo + 1 end -- collision table.insert(tt, n) std.tags[t] = tt return n end std.obj = std.class { __obj_type = true; type = function(self, t) return std.is_obj(self, t) end; with = function(self, ...) local a = {...} for i = 1, #a do if type(a[i]) == 'table' then for k = 1, #a[i] do table.insert(self.obj, a[i][k]) end else table.insert(self.obj, a[i]) end end return self end; new = function(self, v) if std.game and not std.__in_new and not std.__in_gamefile then std.err ("Use std.new() to create dynamic objects:"..std.tostr(v), 2) end local oo = std.objects if type(v) ~= 'table' then std.err ("Wrong argument to std.obj:"..std.tostr(v), 2) end if std.is_tag(v.nam) then rawset(v, 'tag', v.nam) rawset(v, 'nam', nil) end if v.nam == nil then if std.__in_new then rawset(v, 'nam', dyn_name()) elseif std.is_tag(v.tag) then rawset(v, 'nam', tag_name(v.tag)) else rawset(v, 'nam', #oo + 1) end rawset(v, '__autoname', true) elseif type(v.nam) ~= 'string' and type(v.nam) ~= 'number' then std.err ("Wrong .nam in object.", 2) -- elseif type(v.nam) == 'string' and v.nam:find('#[0-9]+$') then -- std.err ("You can not use # in object name: "..v.nam, 2) end if oo[v.nam] and not std.is_system(oo[v.nam]) then if v.nam ~= 'main' and v.nam ~= 'player' and v.nam ~= 'game' then std.err ("Duplicated object: "..v.nam, 2) end end local ro = {} local vars = {} local raw = {} for i = 1, #v do if type(v[i]) ~= 'table' then std.err("Wrong declaration: "..std.tostr(v[i]), 2) end local var = (v[i].__var_type == true) -- raw or var mode for key, val in pairs(v[i]) do if type(key) ~= 'string' then std.err("Wrong var name: "..std.tostr(key), 2) end raw[key] = not var rawset(v, key, val) end end for _ = 1, #v do table.remove(v, 1) end if not v.obj then rawset(v, 'obj', {}) end if type(v.obj) ~= 'table' then std.err ("Wrong .obj attr in object:" .. v.nam, 2) end v.obj = std.list(v.obj) -- v.obj:attach(v) for key, val in pairs(v) do if not std.nostrict_new and type(self[key]) == 'function' and type(val) ~= 'function' then std.err("Overwrited object method: '"..std.tostr(key).. "' in: "..std.tostr(v.nam), 2) end if not raw[key] then ro[key] = val rawset(v, key, nil) end end rawset(v, '__ro', ro) rawset(v, '__var', vars) rawset(v, '__list', {}) -- in what list(s) oo[ro.nam] = v -- std.setmt(v, self) if std.__in_init then table.insert(std.__in_init, v) end return v end; actions = function(s, t, v) t = t or 'act' if type(t) ~= 'string' then std.err("Wrong argument to obj:actions(): "..std.tostr(t), 2) end local ov = s['__nr_'..t] or 0 if type(v) == 'number' or v == false then s['__nr_'..t] = v or nil end return ov end; __renam = function(s, new) local oo = std.objects if new == s.nam then return end if oo[new] then std.err ("Duplicated obj name: "..std.tostr(new), 2) end oo[s.nam] = nil oo[new] = s rawset(s, 'nam', new) return s end; __ini = function(s, ...) for _, v in pairs(s) do if std.is_obj(v, 'list') then v:__ini(s) end end for _, v in pairs(s.__ro) do if std.is_obj(v, 'list') then v:__ini(s) end end return std.call(s, 'ini', ...) end; inroom = function(s, r) local rooms = r or {} local ww = {} local o if type(rooms) ~= 'table' then std.err("Wrong argument to room: "..std.tostr(r), 2) end s:where(ww) while #ww > 0 do local nww = {} for _, v in ipairs(ww) do if std.is_obj(v, 'room') then if not o then o = v end table.insert(rooms, v) else v:where(nww) end end ww = nww end return o end; __where = function(s) -- lists local list = s.__list local r = { } for i = 1, #list do table.insert(r, list[i]) end return r end; where = function(s, w) local list = s.__list local r = w or { } local o if type(r) ~= 'table' then std.err("Wrong argument to obj:where: "..std.tostr(w), 2) end for i = 1, #list do local l = list[i] local ll = l.__list for k = 1, #ll do local oo = ll[k] if std.is_obj(oo) and oo:lookup(s) then o = o or oo if o and not w then break end table.insert(r, oo) end end end return o end; purge = function(s) local list = s:__where() for i = 1, #list do list[i]:del(s) end return s end; remove = function(s, w) if w then w = std.ref(w) if not w then std.err ("Wrong where in obj:remove()", 2) end local o, l = w:lookup(s) if not o then return o end l:del(o) return o, { w } end local where = {} s:where(where) for i = 1, #where do local o = where[i] local _, l = o:lookup(s) if l then l:del(s) end end return s, where end; close = function(s) s.__closed = true return s end; open = function(s) s.__closed = nil return s end; closed = function(s) return s.__closed or false end; disable = function(s) s.__disabled = true return s end; enable = function(s) s.__disabled = nil return s end; disabled = function(s) return s.__disabled or false end; empty = function(s) for i = 1, #s.obj do local o = s.obj[i] if not o:disabled() then return false end end return true end; save = function(s, fp, n) if std.debug_save then std.dprint("Saving: "..std.nameof(s)) end if s.__dynamic then -- create local nn = std.functions[s.__dynamic.fn] if not nn then std.err("Error while saving dynamic object: "..std.tostr(s), 2) end local arg = s.__dynamic.arg local l = '' for i = 1, #arg do if arg[i] == s then std.err("Error while saving dynamic object: "..std.tostr(s).." Argument is self-obj.", 2) end l = l .. ', '..std.dump(arg[i], true, true) -- strict, nested end if type(s.nam) == 'number' then l = string.format("std.new(%s%s):__renam(%d)\n", nn, l, s.nam) else l = string.format("std.new(%s%s)\n", nn, l, s.nam) end fp:write(l) end for k, _ in pairs(s.__ro) do local o = s.__ro[k] if std.dirty(o) then local l = string.format("%s%s", n, std.varname(k)) std.save_var(s[k], fp, l) end end for k, _ in pairs(s.__var) do local l = string.format("%s%s", n, std.varname(k)) std.save_var(s[k], fp, l) end end; display = function(self) local d = std.call(self, 'dsc') return d end; __xref = function(self, text, force) if type(text) ~= 'string' then return end local nam = self.nam if type(nam) == 'number' then nam = '# '..std.tostr(nam) end local rep = false local s = std.for_each_xref_outer(text, function(str) rep = true local s = str:gsub("^{", ""):gsub("}$", "") local test = string.gsub(s, '\\?[\\{}'..std.delim..']', { ['{'] = '\001', ['}'] = '\003', [std.delim] = '\002' }); while true do local sub = test:gsub("\001[^\001\003]+\003", "") if sub == test then break end test = sub end local a = test:find('\002', 1, true) if not a or test:byte(a) == 1 then -- need to be | return '{'..(std.esc(nam)..std.delim..s)..'}' end return str end) if not rep and force then -- nothing todo? return '{'..(std.esc(nam)..std.delim..s)..'}' end return s; end; visible = function(s) return not s:disabled() end; srch = function(s, w) local o, l, idx if not s:visible() or s:closed() then return end l = s.obj o, idx = l:srch(w) if o then return o, l, idx end for i = 1, #s.obj do local v = s.obj[i] o, l, i = v:srch(w) if o then return o, l, i end end end; lookup = function(s, w) local l = s.obj local o, idx = l:lookup(w) if o then return o, l, idx end for i = 1, #s.obj do local v = s.obj[i] o, l, i = v:lookup(w) if o then return o, l, i end end end; for_each = function(s, fn, ...) local r, v for i = 1, #s.obj do r, v = fn(s.obj[i], ...) if r ~= nil then return r, v end if v ~= false then -- recurse r, v = s.obj[i]:for_each(fn, ...) end if r ~= nil then return r, v end end end; __dump = function(s) if not s:visible() or s:closed() then return end return s.obj:__dump(true) end; lifeon = function(s) local game = std.ref 'game' game:lifeon(s) return s end; lifeoff = function(s) local game = std.ref 'game' game:lifeoff(s) return s end; live = function(s) local game = std.ref 'game' return game:live(s) end; }; function std.var(v) if type(v) ~= 'table' then std.err("Wrong std.var() argument", 2) end v.__var_type = true return v end std.room = std.class({ __room_type = true; from = function(s) return s.__from or s end; new = function(_, v) if type(v) ~= 'table' then std.err ("Wrong argument to std.room:"..std.tostr(v), 2) end if not v.way then rawset(v, 'way', {}) end if type(v.way) ~= 'table' then std.err ("Wrong .way attr in object:" .. v.nam, 2) end v.way = std.list(v.way) -- v.way:attach(v) v = std.obj(v) -- std.setmt(v, self) return v end; visited = function(s) return s.__visits end; visits = function(s) return s.__visits or 0 end; srch = function(self, w) local r, v, i = std.obj.srch(self, w) if std.is_obj(r) then return r, v, i end r, v = self.way:lookup(w) if not std.is_obj(r) or r:disabled() or r:closed() then return end return r, self.way, v end; lookup = function(self, w) local r, v, i = std.obj.lookup(self, w) if std.is_obj(r) then return r, v, i end r, v = self.way:lookup(w) if std.is_obj(r) then return r, self.way, v end return end; scene = function(s) local title, dsc title = iface:title(std.titleof(s)) dsc = std.call(s, 'dsc') return std.par(std.scene_delim, title or false, dsc) end; display = function(s) local deco = std.call(s, 'decor'); -- static decorations return std.par(std.scene_delim, deco or false, s.obj:display()) end; visible = function(s) return not s:disabled() and not s:closed() end; __dump = function(s) return s.way:__dump() end; }, std.obj); std.world = std.class({ __game_type = true; new = function(_, v) if type(v) ~= 'table' then std.err ("Wrong argument to std.pl:"..std.tostr(v), 2) end if not v.player then v.player = 'player' end if v.lifes == nil then rawset(v, 'lifes', {}) end v.lifes = std.list(v.lifes) v = std.obj(v) -- std.setmt(v, self) return v end; time = function(s, t) local ov = s.__time or 0 if t ~= nil then if type(t) ~= 'number' then std.err ("Wrong parameter to game:time: "..stead.tostr(t), 2) end s.__time = t end return ov end; __ini = function(s, load) return s:ini(load) end; __start = function(s, load) std.mod_call('start', load) if type(std.rawget(_G, 'start')) == 'function' then start(load) -- start after load end s.__started = true if load ~= true then if std.game.player.room.__from then -- already entered return nil, true end local r, v = std.game.player:walk(std.game.player.room, false) return r, v end end; ini = function(s, load) if s.__in_ini then return -- break recursion end s.__in_ini = true std.obj.__ini(s, load) s.__in_ini = false s.player = std.ref(s.player) -- init game if not s.player then std.err ("Wrong player", 2) end std.for_each_obj(function(v) rawset(v, '__list', {}) -- reset all links end) std.for_each_obj(function(v) -- call ini of all objects if v ~= s then v:__ini(load) end end) if not std.game then if type(std.rawget(_G, 'init')) == 'function' then std.__in_init = {} init() for _, v in ipairs(std.__in_init) do v:__ini(load) end std.__in_init = false end std.game = s end local d = std.method(s, 'dsc') return std.fmt(d) end; lifeon = function(s, w, ...) if not w then s.__lifeoff = nil return end return s.lifes:add(w, ...) end; lifeoff = function(s, w) if not w then s.__lifeoff = true return end return s.lifes:del(w) end; live = function(s, w) if not w then return not s.__lifeoff end return s.lifes:lookup(w) end; set_pl = function(s, w) if not std.is_obj(w, 'player') then std.err("Wrong parameter to game:set_pl(): "..std.tostr(w), 2) end s.player = w w:need_scene(true) end; life = function(s) local av, vv s:events(false, false) if s.__lifeoff then return end local ll = {} for i = 1, #s.lifes do table.insert(ll, s.lifes[i]) end for i = 1, #ll do local v, pre, st local o = ll[i] if not o:disabled() then v, st, pre = std.call(o, 'life'); av, vv = s:events() if pre then -- hi-pri msg av = std.par(std.space_delim, av or false, v) else vv = std.par(std.space_delim, vv or false, v) end s:events(av or false, vv or false) if st == false then -- break cycle break end end end end; step = function(s) s:life() s.__time = s:time() + 1 end; lastdisp = function(s, str) local ov = s.__lastdisp if str ~= nil then s.__lastdisp = str end return ov end; display = function(s, state) local l, av, pv local reaction = s:reaction() or nil if state then reaction = iface:em(reaction) av, pv = s:events() av = iface:em(av) pv = iface:em(pv) l = s.player:look() -- objects [and scene] end l = std.par(std.scene_delim, reaction or false, av or false, l or false, pv or false) or '' return l end; lastreact = function(s, t) local o = s.__lreaction if t == nil then return o end s.__lreaction = t or nil return o end; reaction = function(s, t) local o = s.__reaction if t == nil then return o end s.__reaction = t or nil return o end; events = function(s, av, pv) local oa = s.__aevents local op = s.__pevents if av ~= nil then s.__aevents = av or nil end if pv ~= nil then s.__pevents = pv or nil end return oa, op end; cmd = function(s, cmd) local r, v if not std.is_obj(s.player) then std.err("Wrong player object.", 2) end s.player:moved(false) s.player:need_scene(false) std.abort_cmd = false r, v = std.mod_call('cmd', cmd) -- luacheck: push ignore if r ~= nil or v ~= nil then -- luacheck: pop elseif cmd[1] == nil or cmd[1] == 'look' then if not s.__started then r, v = s:__start() else s.player:need_scene(true) v = true end -- r, v = s.player:look() elseif cmd[1] == 'act' then if #cmd < 2 then return nil, false end local o = std.ref(cmd[2]) -- on what? if std.is_system(o) then local a = {} for i = 3, #cmd do table.insert(a, cmd[i]) end r, v = std.call(o, 'act', std.unpack(a)) else o = s.player:inspect(o) if not o then return nil, false -- wrong input end r, v = s.player:take(o) if not r and not v then r, v = s.player:action(o) end end -- if s.player:search(o) elseif cmd[1] == 'use' then if #cmd < 2 then return nil, false end local o1 = std.ref(cmd[2]) local o2 = std.ref(cmd[3]) o1 = s.player:srch(o1) if not o1 then return nil, false -- wrong input end if o1 == o2 or not o2 then -- inv? if not o1 then return nil, false -- wrong input end r, v = s.player:useit(o1) else r, v = s.player:useon(o1, o2) end elseif cmd[1] == 'go' then if #cmd < 2 then return nil, false end local o = std.ref(cmd[2]) if not o then return nil, false -- wrong input end r, v = s.player:go(o) elseif cmd[1] == 'inv' then -- show inv r = s.player:__dump() -- just info v = nil elseif cmd[1] == 'way' then -- show ways r = s.player:where():__dump() v = nil elseif cmd[1] == 'save' then -- todo if #cmd < 2 then return nil, false end r = std:save(cmd[2]) v = true std.abort() elseif cmd[1] == 'load' then -- todo if #cmd < 2 then return nil, false end r = std:load(cmd[2]) v = true std.abort() end if r == nil and v == nil then v = false -- no reaction end if v == false or std.abort_cmd then if cmd[1] == 'save' then std.mod_call('step', nil) else std.mod_call('step', v) end return r, v end -- v is true or nil s = std.game -- after reset game is recreated s:reaction(r or false) if v then s:step() end std.mod_call('step', v) r = s:display(v) if v then s:lastreact(s:reaction() or false) s:lastdisp(r) end return r, v end; aftertak = function(s, w) -- standard take action w = std.ref(w) local o = w:remove() s.player:inventory():add(o) end; }, std.obj); std.player = std.class ({ __player_type = true; new = function(_, v) if type(v) ~= 'table' then std.err ("Wrong argument to std.pl:"..std.tostr(v), 2) end if not v.room then v.room = 'main' end v = std.obj(v) -- std.setmt(v, self) return v end; __ini = function(s, ...) s.room = std.ref(s.room) if not s.room then std.err ("Wrong player location: "..std.tostr(s), 2) end std.obj.__ini(s, ...) end; moved = function(s, v) local ov = s.__moved or false if v == nil then return ov end if type(v) ~= 'boolean' then std.err("Wrong parameter to player:moved: "..std.tostr(v), 2) end if v == false then v = nil end s.__moved = v return ov end; need_scene = function(s, v) local ov = s.__need_scene or false if v == nil then return ov end if type(v) ~= 'boolean' then std.err("Wrong parameter to player:need_scene: "..std.tostr(v), 2) end if v == false then v = nil end s.__need_scene = v return ov end; look = function(s) local scene local r = s:where() if s:need_scene() then scene = r:scene() end return std.par(std.scene_delim, scene or false, r:display()) end; inspect = function(s, w) local r, v, i r, v, i = s:where():srch(w) if r ~= nil then return r, v, i end r, v, i = s:srch(w) if r ~= nil then return r, v, i end return end; lookup = function(self, w) local r, v, i = std.obj.lookup(self, w) if std.is_obj(r) then return r, v, i end r, v = self:inventory():lookup(w) if std.is_obj(r) then return r, self:inventory(), v end return end; have = function(s, w) local o, i = s:inventory():lookup(w) if not o then return o, i end if o:disabled() then return end return o, i end; useit = function(s, w, ...) return s:call('inv', w, ...) end; useon = function(s, w1, w2) w1 = std.ref(w1) w2 = std.ref(w2) if w2 and w1 ~= w2 then return s:call('use', w1, w2) end -- inv mode? return s:call('inv', w1, w2) end; call = function(_, m, w1, w2, ...) local w if type(m) ~= 'string' then std.err ("Wrong method in player.call: "..std.tostr(m), 2) end w = std.ref(w1) if not std.is_obj(w) then std.err ("Wrong parameter to player.call: "..std.tostr(w1), 2) end local r, v, t, _ r, v = std.call(std.ref 'game', 'on'..m, w, w2, ...) t = std.par(std.scene_delim, false, r) if v == false then return t or r, true, false end if m == 'use' and w2 then r, v = std.call(w2, 'used', w, ...) t = std.par(std.scene_delim, t or false, r) if v == true then -- false from used --> pass to use w2['__nr_used'] = (w2['__nr_used'] or 0) + 1 r, _ = std.call(std.ref 'game', 'afteruse', w, w2, ...) t = std.par(std.scene_delim, t or false, r) return t or r, true -- stop chain end end r, v = std.call(w, m, w2, ...) t = std.par(std.scene_delim, t or false, r) if v == true then w['__nr_'..m] = (w['__nr_'..m] or 0) + 1 r, _ = std.call(std.ref 'game', 'after'..m, w, w2, ...) t = std.par(std.scene_delim, t or false, r) return t or r, true end if r == true and v == false then return r, v -- menu hack end if not v and not r then -- no reaction r, v = std.call(std.ref 'game', m, w, w2, ...) t = std.par(std.scene_delim, t or false, r) if not v then return end end return t or r, true end; action = function(s, w, ...) return s:call('act', w, ...) end; inventory = function(s) return s.obj end; take = function(s, w, ...) return s:call('tak', w, ...) end; walkin = function(s, w, ...) return s:walk(w, false, true, ...) end; walkout = function(s, w, ...) if w == nil then w = s:where():from() end return s:walk(w, true, false, ...) end; walk = function(s, w, doexit, doenter, dofrom) local noexit = (doexit == false) local noenter = (doenter == false) local nofrom = (dofrom == false) local moved = s:moved() if moved then s:moved(false) end local ww = w w = std.ref(w) if not w then std.err("Wrong parameter to walk: "..std.tostr(ww)) end -- if w == std.here() then -- nothing todo -- return -- end local inwalk = w local r, v, t, _ local f = s:where() r, v = std.call(std.ref 'game', 'onwalk', f, inwalk) t = std.par(std.scene_delim, false, r) if v == false or s:moved() then -- stop walk if not s:moved() then s:moved(moved) end return t, true end r, v = std.call(inwalk, 'onwalk', f) t = std.par(std.scene_delim, t or false, r) if v == false or s:moved() then -- stop walk if not s:moved() then s:moved(moved) end return t, true end if not noexit and not s.__in_onexit then s.__in_onexit = true r, v = std.call(s:where(), 'onexit', inwalk) s.__in_onexit = false t = std.par(std.scene_delim, t or false, r) if v == false or s:moved() then if not s:moved() then s:moved(moved) end return t, true end end if not noenter then r, v = std.call(inwalk, 'onenter', s:where()) t = std.par(std.scene_delim, t or false, r) if v == false or s:moved() then if not s:moved() then s:moved(moved) end return t, true end end if not noexit and not s.__in_exit then s.__in_exit = true r, _ = std.call(s:where(), 'exit', inwalk) s.__in_exit = false t = std.par(std.scene_delim, t or false, r) if s:moved() then return t, true end end -- enter is done s.room = inwalk if not nofrom and (f ~= inwalk or not s.room.__from) then -- brake self-recursion s.room.__from = f end if not noenter then r, _ = std.call(inwalk, 'enter', f) t = std.par(std.scene_delim, t or false, r) if s:moved() then return t, true end end s:where().__visits = (s:where().__visits or 0) + 1 s:need_scene(true) s:moved(true) if not s.__in_afterwalk then s.__in_afterwalk = true r, _ = std.call(std.ref 'game', 'afterwalk', f, inwalk) s.__in_afterwalk = false t = std.par(std.scene_delim, t or false, r) end return t, true end; go = function(s, w) local r r = s:where():srch(w) if not std.is_obj(r, 'room') then return nil, false end return s:walk(w) end; where = function(s, where) if type(where) == 'table' then table.insert(where, std.ref(s.room)) end return std.ref(s.room) end; }, std.obj); -- merge strings with "space" as separator std.par = function(space, ...) local res local a = { ... }; for i = 1, #a do if type(a[i]) == 'string' then if res == nil then res = "" else res = res .. space; end res = res .. a[i]; end end return res; end -- add to not nill string any string std.cat = function(v,...) if not v then return nil end if type(v) ~= 'string' then std.err("Wrong parameter to std.cat: "..std.tostr(v), 2); end local a = { ... } for i = 1, #a do if type(a[i]) == 'string' then v = v .. a[i]; end end return v; end std.cctx = function() return std.call_ctx[std.call_top]; end std.callpush = function(v) std.call_top = std.call_top + 1; std.call_ctx[std.call_top] = { txt = nil, self = v }; end std.callpop = function() std.call_ctx[std.call_top] = nil; std.call_top = std.call_top - 1; if std.call_top < 0 then std.err ("callpush/callpop mismatch") end end std.pclr = function() std.cctx().txt = nil end std.pget = function() return std.cctx().txt; end std.pr = function(...) local a = {...} if std.cctx() == nil then error ("Call from global context.", 2); end for i = 1, #a do std.cctx().txt = std.par('', std.cctx().txt or false, std.tostr(a[i])); end -- std.cctx().txt = std.cat(std.cctx().txt, std.space_delim); end std.p = function(...) std.pr(...) std.cctx().txt = std.cat(std.cctx().txt, std.space_delim); end std.pn = function(...) std.pr(...) std.cctx().txt = std.cat(std.cctx().txt, '^'); end std.pf = function(fmt, ...) if type(fmt) ~= 'string' then std.err("Wrong argument to std.pf: "..std.tostr(fmt)) end std.pr(string.format(fmt, ...)) end function std.strip(s) if type(s) ~= 'string' and type(s) ~= 'number' then return end s = tostring(s) s = s:gsub("^[ \t]*", ""):gsub("[ \t]*$", "") return s end function std.join(a, sep) sep = sep or ' ' local rc for i = 1, #a do if type(a[1]) == 'string' then rc = (rc and rc .. sep or '') .. a[i] end end return rc end function std.split(s, separator) local sep, fields = separator or " ", {} local pattern = string.format("([^%s]+)", sep) if type(s) ~= 'string' and type(s) ~= 'number' then return fields end s = tostring(s) s:gsub(pattern, function(c) fields[#fields+1] = std.strip(c) end) return fields end function std.esc(s, sym) sym = sym or std.delim if type(s) ~= 'string' then return s end s = s:gsub("\\?["..sym.."]", { [sym] = '\\'..sym, ['\\'..sym] = '\\\\'..sym}) return s end function std.unesc(s, sym) sym = sym or std.delim s = s:gsub("\\?[\\"..sym.."]", { ['\\'..sym] = sym, ['\\\\'] = '\\' }) return s end function std.is_proxy(t) return (type(t) == 'userdata') or (type(t) == 'table' and t.__proxy_type) end local function __dump(t, strict, nested) local rc = ''; if type(t) == 'string' then rc = string.format("%q", t):gsub("\\\n", "\\n") elseif type(t) == 'number' then rc = std.tostr(t) elseif type(t) == 'boolean' then rc = std.tostr(t) elseif type(t) == 'function' then if std.functions[t] then local k = std.functions[t] return string.format("%s", k) elseif strict then std.err("Can not save undeclared function", 2) end elseif type(t) == 'table' and not t.__visited then if std.tables[t] and nested then local k = std.tables[t] return string.format("%s", k) elseif std.is_obj(t) then local d = std.deref(t) if type(d) == 'number' then rc = string.format("std(%d)", d) elseif type(d) == 'string' then rc = string.format("std %q", d) end return rc end if strict and std.getmt(t) then std.err("Can not save classes", 2) end t.__visited = true local nkeys = {} local keys = {} for k, v in pairs(t) do if strict and type(k) ~= 'number' and type(k) ~= 'string' then std.err("Wrong key type in table: "..type(k), 2) end if type(k) ~= 'string' or k:find("__", 1, true) ~= 1 then if (type(v) ~= 'function' or std.functions[v]) and not std.is_proxy(v) then if type(k) == 'number' then table.insert(nkeys, { key = k, val = v }) elseif type(k) == 'string' then table.insert(keys, { key = k, val = v }) end elseif strict then std.err("Can not save table item ("..std.tostr(k)..") with type: "..type(v), 2) end end end table.sort(nkeys, function(a, b) return a.key < b.key end) rc = "{ " local n, v for k = 1, #nkeys do v = nkeys[k] if v.key == k then rc = rc .. __dump(v.val, strict, true)..", " else n = k break end end if n then for k = n, #nkeys do v = nkeys[k] rc = rc .. "["..std.tostr(v.key).."] = "..__dump(v.val, strict, true)..", " end end for k = 1, #keys do v = keys[k] if type(v.key) == 'string' then if v.key:find("^[a-zA-Z_]+[a-zA-Z0-9_]*$") and not lua_keywords[v.key] then rc = rc .. v.key .. " = "..__dump(v.val, strict, true)..", " else rc = rc .. "[" .. string.format("%q", v.key) .. "] = "..__dump(v.val, strict, true)..", " end else rc = rc .. std.tostr(v.key) .. " = "..__dump(v.val, strict, true)..", " end end rc = rc:gsub(",[ \t]*$", "") .. " }" elseif type(t) == 'table' then -- visited! std.err("Can not save table with cross-references.", 2) end return rc end local function cleardump(t) if type(t) ~= 'table' or not t.__visited then return end t.__visited = nil for _, v in pairs(t) do cleardump(v) end end function std.dump(t, strict, nested) local rc = __dump(t, strict, nested) cleardump(t) return rc end local function clone(src) if type(src) ~= 'table' then return src end if std.is_obj(src) then return src end if src.__visited then std.err("Recursive tables not supported by std.clone") end src.__visited = true local dst = {} for k, _ in pairs(src) do if k ~= '__visited' then dst[std.clone(k)] = clone(src[k]) end end return dst end function std.clone(src) cleardump(src) local t = clone(src) cleardump(src) return t end function std.new(fn, ...) if not std.game then std.err ("You can not use new() from global context.", 2) end if type(fn) ~= 'function' then std.err ("Wrong parameter to std.new", 2) end if not std.functions[fn] then std.err ("Function is not declared in 1-st argument of std.new", 2) end local arg = std.clone({...}) local o = in_section ('new', function() return fn(std.unpack(arg)) end) if type(o) ~= 'table' then std.err ("Constructor did not return object:"..std.functions[fn], 2) end rawset(o, '__dynamic', { fn = fn, arg = {...} }) if std.game then o:__ini() -- do initialization end return o end function std.delete(s) s = std.ref(s) if std.is_obj(s) then if type(s.nam) == 'number' and not s.__dynamic then -- static objects std.objects[s.nam] = false else std.objects[s.nam] = nil end else std.err("Delete non object table", 2) end end function std.nameof(o) o = std.ref(o) if not std.is_obj(o) then std.err("Wrong parameter to std.nameof: "..std.tostr(o), 2) return end return o.nam end function std.dispof(o) o = std.ref(o) if not std.is_obj(o) then std.err("Wrong parameter to std.dispof", 2) return end if o.disp ~= nil then local d = std.call(o, 'disp') return d end if o.__autoname then if std.is_tag(o.tag) then o = o.tag:sub(2) return o end if type(o.nam) == 'number' then return std.tostr(o.nam) end std.err("No nam nor disp are specified for obj: "..std.tostr(o.nam), 2) end return o.nam end function std.titleof(o) o = std.ref(o) if not std.is_obj(o) then std.err("Wrong parameter to std.titleof", 2) return end if o.title ~= nil then return std.call(o, 'title') end return std.dispof(o) end function std.ref(o) if type(o) == 'table' then if not std.is_obj(o) then std.err("Reference to wrong object: "..std.tostr(o), 2) end return o end local oo = std.objects if oo[o] then return oo[o] end if std.noerror then std.dprint("Reference to non-existing object: ", std.tostr(o)) return {} -- give fake object end end function std.deref(o) if std.is_obj(o) then return o.nam elseif std.ref(o) then return o end end std.method = function(v, n, ...) if type(v) ~= 'table' then std.err ("Call on non table object:"..std.tostr(n), 2); end if v[n] == nil then return end if type(v[n]) == 'string' then return v[n], true; end if type(v[n]) == 'function' then std.callpush(v, ...) local c local a, b = v[n](v, ...); c = b if b == nil and (type(a) == 'boolean' or a == nil) then a, b = std.pget(), a c = b end if b == nil then b = true -- the fact of call end std.callpop() return a, b, c end if type(v[n]) == 'boolean' or type(v[n]) == 'table' then return v[n], true end std.err ("Method not string nor function:"..std.tostr(n), 2); end std.call = function(o, n, ...) if type(o) ~= 'table' then std.err("Call on non table object: "..std.tostr(n), 2) end local r, v, c = std.method(o, n, ...) if std.strip_call and type(r) == 'string' then r = r:gsub("^[%^\n\r\t ]+", "") -- extra heading ^ and spaces r = r:gsub("[%^\n\r\t ]+$", "") -- extra trailing ^ and spaces return r, v, c end return r or nil, v, c end local function get_token(inp) local q, k local rc = '' k = 1 if inp:sub(1, 1) == '"' then q = true k = k + 1 end while true do local c = inp:sub(k, k) if c == '' then if q then return nil -- error end break -- return rc, k end if c == '"' and q then k = k + 1 break end if not q and (c == ' ' or c == ',' or c == '\t') then break end if q and c == '\\' then k = k + 1 c = inp:sub(k, k) rc = rc .. c else rc = rc .. c end k = k + 1 end if not q then if std.tonum(rc) then rc = std.tonum(rc) elseif rc == 'true' then rc = true elseif rc == 'false' then rc = false end end return rc, k end local function cmd_parse(inp) local cmd = {} if type(inp) ~= 'string' then return false end if inp:find("^save[ \t]+") then cmd[1] = 'save' cmd[2] = inp:gsub("^save[ \t]+", "") return cmd elseif inp:find("^load[ \t]+") then cmd[1] = 'load' cmd[2] = inp:gsub("^load[ \t]+", "") return cmd end inp = inp:gsub("[ \t]*$", "") while true do inp = inp:gsub("^[ ,\t]*","") local v, i = get_token(inp) if v == nil or v == '' then break end inp = inp:sub(i) table.insert(cmd, v) end return cmd end std.cmd_parse = cmd_parse function std.me() return std.ref(std.ref 'game'.player) end function std.here() return std.ref(std.me().room) end function std.cacheable(n, f) return function(...) local s = std.cache[n] if s ~= nil then if s == -1 then s = nil end return s end std.cache[n] = -1 s = f(...) if s ~= nil then std.cache[n] = s end return s end end local iface = std.obj { nam = '@iface'; cmd = function(_, inp) local cmd = std.cmd_parse(inp) if std.debug_input then std.dprint("* input: ", inp) end if not cmd then return "Error in cmd arguments", false end std.cmd = cmd std.cache = {} local r, v = std.ref 'game':cmd(cmd) if r == true and v == false then return nil, true -- hack for menu mode end r = iface:fmt(r, v) -- to force fmt if std.debug_output then std.dprint("* output: ", r, v) end return r, v end; xref = function(_, str, obj, ...) obj = std.ref(obj) if not obj then return str end local a = { ... } local args = '' for i = 1, #a do if type(a[i]) ~= 'string' and type(a[i]) ~= 'number' and type(a[i]) ~= 'boolean' then std.err ("Wrong argument to iface:xref: "..std.tostr(a[i]), 2) end args = args .. ' '..std.dump(a[i]) end local xref = std.string.format("%s%s", std.deref_str(obj), args) return std.cat(str, "("..xref..")"); end; title = function(_, str) return "[ "..std.tostr(str).." ]" end; raw_mode = function(s, v) local ov = s.__raw if v ~= nil then s.__raw = v or nil end return ov end; fmt = function(self, str, state) if self:raw_mode() or type(str) ~= 'string' then return str end str = std.fmt(str, std.format, state) return std.cat(str, '\n') end; em = function(_, str) return str end; }; local function fmt_stub(_, str) return str end iface.em = fmt_stub iface.center = fmt_stub iface.just = fmt_stub iface.left = fmt_stub iface.right = fmt_stub iface.bold = fmt_stub iface.top = fmt_stub iface.bottom = fmt_stub iface.middle = fmt_stub iface.nb = fmt_stub iface.anchor = fmt_stub iface.img = fmt_stub iface.imgl = fmt_stub iface.imgr = fmt_stub iface.under = fmt_stub iface.st = fmt_stub iface.tab = fmt_stub iface.y = function() return '' end function std.loadmod(f) if std.game and not std.__in_gamefile then std.err("Use loadmod() only in global context", 2) end if type(f) ~= 'string' then std.err("Wrong argument to loadmod(): "..std.tostr(f), 2) end if not f:find("%.lua$") then f = f .. '.lua' end if not std.modules[f] then std.modules[f] = true std.dofile(f) end end function std.include(f) if std.game and not std.__in_gamefile then std.err("Use include() only in global context", 2) end if type(f) ~= 'string' then std.err("Wrong argument to include(): "..std.tostr(f), 2) end if not f:find("%.lua$") then f = f .. '.lua' end if not std.includes[f] then std.includes[f] = true in_section('include', function() std.dofile(f) end) end end function std.abort() std.abort_cmd = true end function std.nop() std.abort() if std.cctx() then std.pr(std.game:lastdisp()) end return std.game:lastdisp(), true end -- require "ext/gui" require "declare" require "dlg" require "stdlib" instead-3.5.2+dfsg/stead/stead3/theme.lua000066400000000000000000000000661467622671600202020ustar00rootroot00000000000000-- luacheck: globals theme theme = stead.ref '@theme' instead-3.5.2+dfsg/stead/stead3/timer.lua000066400000000000000000000000661467622671600202200ustar00rootroot00000000000000-- luacheck: globals timer timer = stead.ref '@timer' instead-3.5.2+dfsg/themes/000077500000000000000000000000001467622671600153755ustar00rootroot00000000000000instead-3.5.2+dfsg/themes/CMakeLists.txt000066400000000000000000000005771467622671600201460ustar00rootroot00000000000000SET(THEMES arctic bluesteel book clearlooks default fantasy wide mobile) IF(SYSTEMWIDE) FOREACH(THEME ${THEMES}) INSTALL(DIRECTORY ${THEME} DESTINATION ${THEMESDIR} PATTERN ".svn" EXCLUDE) ENDFOREACH(THEME) ELSEIF(STANDALONE) FOREACH(THEME ${THEMES}) INSTALL(DIRECTORY ${THEME} DESTINATION ${STANDALONEDIR}/themes PATTERN ".svn" EXCLUDE) ENDFOREACH(THEME) ENDIF(SYSTEMWIDE) instead-3.5.2+dfsg/themes/Makefile000066400000000000000000000005271467622671600170410ustar00rootroot00000000000000include ../Rules.make include ../config.make clean: all: install: $(INSTALLD) $(DESTDIR)$(THEMESPATH) for f in *; do \ if [ ! -d $$f ]; then continue; fi;\ $(INSTALLD) $(DESTDIR)$(THEMESPATH)/$$f;\ tar --exclude=".svn" -cf - -C $$f . | tar -xpf - -C $(DESTDIR)$(THEMESPATH)/$$f;\ done uninstall: $(RM) -rf $(DESTDIR)$(THEMESPATH) instead-3.5.2+dfsg/themes/arctic/000077500000000000000000000000001467622671600166425ustar00rootroot00000000000000instead-3.5.2+dfsg/themes/arctic/adown.png000066400000000000000000000005311467622671600204570ustar00rootroot00000000000000PNG  IHDRkIsRGBbKGD pHYs Є tIME #ȯ0iTXtCommentCreated with GIMPd.eIDAT8б Gzap>&V-M,e ;~!iX:SqӰLLaS.U#8Ia}agiPHTB`:FݟnqIENDB`instead-3.5.2+dfsg/themes/arctic/aup.png000066400000000000000000000005041467622671600201340ustar00rootroot00000000000000PNG  IHDRkIsRGBbKGD pHYs Є tIME -/7iTXtCommentCreated with GIMPd.eIDAT8c` \sRHNf$l.e!>|CkL 8g9#!A @ "aH b$do5s. X|1d,Ov  :` dbID78IENDB`instead-3.5.2+dfsg/themes/arctic/bg.png000066400000000000000000005477641467622671600177670ustar00rootroot00000000000000PNG  IHDR X'sRGB pHYs Є tIME$bKGDtIDATx˫,˶#"j' e @= P_ SmY-6 5caF sk92c 7"5kܳY_Oqxn  Gۿ__ ޝ?_?#wlO?wo?XV-XWW/sſ?ꏿ:?رౄ/?8?[So[7wou < 9gm~+GG𽒷9 ? |ET;|ǰX@` @` @`  , X, X, X,@` X,@` X@` @` @`  , X, X, X,@` X@` X@` @` @`  , X, X, X,@` X@` X@` @`   , X, X, X,@` X@` X@` @`   , X, X, X,@` X@` X , X, X, X,@` X@` @` @`  , , X, X,@` X,@` X@` @` @`  , , X, X,@` X,@` X@` @` @`  , , X, X,@` X,@` X@` @` @`  , X, X, X,@` X,@` X@` `cpޝs"sc/>m |6oŌ=kzG$'^+9 :G߾t|0O_C5` =[Y#WW`Q/zcD "zƾ a{q&"uu 0x ?[ʛ[YHM]>WzϡnG#PW76;u8ɶ&vO)uw7TW95֗R\_ߤjg2 ;+ԕsο֑G26coP]-W)>GʁۯD~d7f*zne^Q(ee[ R`Lwە!u2 )0ZRߡ:Vv{[Hi6כ) %'`X>rS|i;܃oԆߴz1PPWG5SĐ|fFOir[7w]q#'rA޲w8HkeKLnyھ/pu5[NaCDdv4<倸NmJZw$`Fzy˱ 7Es/ӎhC%G۱k-R8BGcMdnz6z|q Uoh|'ѺH8Sbbuw+pC\]u>ؾfC'2 Uciu +gZ\ɧWWնXzPW G!v.Cn{QԻW\wsw PykVSP``tDߜz˩cw}RhYfIW5ϠAJ<:(o )[_LZ9QZ Fho@H}Yb~D]i^qM)ݸfO<;V8\얣Mk}N:4|v_ʏUߊy~o\a"o=S#ѯ$ b|ǽ}UEu @W}I6ZH,{;^_aVoJWuCVU~A{7{+X,(0j#+;",U߮t[5iozew_T:0o?y'&ʭjKmf?7n ^j~#IYbuʷx#lg} ϥnGJ[7kJbr@{햂/.y%_Fkš M;"ܱh%NYJ=en{˄=b6bm__#;=l%w,nf㖩۽BKFo+.MvDXkE~|PtdXH_MUxD5y [ܖrj,I|1'w c/X}7lvWqvטXg ?-t{=\֮heQrHcݗqYlVkGR)|bĚy,")[G':XF;yL?Uw7+ߢ)R*<2?P٣.VO} k [cdOcMsO5X6ޞ#&8'e.z)iv"|V|ſw[VZ2WbŊeJ:=/ AioE^qi5l%_pJwHCx[$ّw⛱|c&/dk0Sv!lMQ:[ue4YM/Pc9q21 @zpv4wxe.~>z7?77N4pM]56e,~;AS.SiFˤ9ievt23v7+17XP,i,?Z`g*<ed% wO0,پE}fFd~_0~ۈ%=( n5ԖsGar ݢ/99}3[ʊge[ռ '&,𤋮Jn֟tX&iB^5M!en7-n5gߚ)sh/[ȪrIyTMOdQh|7#xooZ_|Q]e{6u0,F]Qi+{ZH ٸ)#zMGRx9du8\F;nmdϽ~k|r_{٢f:z{ie[C{֞|P"̤vL$m%b>(s}Ux`qdS[g_lsowWğifx|-U=q|8;Y{beRl~`mI,m[$Rz葀raWLski[V/l-#nXDe.UZ|esh6@k`ۦxdBlgVs:[oz'=dVNձ^=AV/7g+xFl.onm{%Cv9úOS[iqߖf+խH'+GrlO?KpVrO;/ATYi̗ţU1RWn3C3`\53YaqVLKȡ_<(Y`&E\W.CW=ʶqǁkDvܲb29o 6Mcc˱ܣvfǛ _\5 φTk̊V3*Zk]z7.zMN6];&5L;lI6 _፤k-쿹f{`R5U{ʯ!}u#9xϒ6.]l~I*6HqlK[h/sN}1dIaԸSl{<;51#ctJ-7sC;n] v`X -܏'7+[/٫GC79m;kDVxaם-qrG?l2Z]fشxnkg6 `ltbл [2rа[kg[Yܫj]%5C2e Sl<@bm-{hri-`2QT[0YIWͪJ7=:jB8#;Zzq63ׅM{NC )K1׆\tc-QGab:dv:"X'bM6e!ʬ7s<0Tj0ъqR;VSēv}޻qcwd<{VOkY8]Nj}wyCuA9/nS-WәX'.>O-KC2O֔l*h-vVJ[qv{E&ZykUݛ`^{:W9*@°z@OW&L+?qQVxD9]Ɣ% >wV1qOUw1N 8[yV^\c.nnf87CJ] uy;ۭȜ#v6w14[{|G [X2]F֊ܐ۫NSE罷}$u7V!oScj3 Ije|+Aͭٶ't٨ۦ]%^ّ6MEYY2 bϯ B$/cgZ>IY ?ȯg:^5YF 77>ڻv}y)=헽Yf2][ ;>eaY}_1bs2UlNķw~CFtULP]k/vlP=Bg6˱G m6bG@6nPF!C 2ϹQj*Y1:7 +3Pz6;*LfAxUZiXCɇ)h[iZͰu[l}9^U9~\fs*琩=PxeZ{nwoq7WΠ] _6nvR{XN)mxp2\S-ie;ԤPs.͏c۷,fcE53bTD7vy>TVV/ k֬d+-GFZ`TjTj\M sI:Z?SJaqsQI\?H)s3H ֭i3l~jaGֶ׭#Ҹ,duBqHeZdLJ9p ݽz:3Ŭ [+v!ePk[!6@Ϙj4"DdT.pXuGqa*6E-Q$3GY Wm?&ʶ6W6ߖl',NNGo+m(=f;U5L d܊i[Q$if!:lbl/,DW-Z+ i]֔YjY& bLT`-,7Q,}Hs6еƑ1pcHXM9vWaa/ldP=gqGV[˟>#v)I˛z=Zf`Kmg|cOteGvI/έ[ ~/P6/@ȇh,1zC29P+OzK(KžRVH nj wn beqz$m/@gd)oi;.eiN.]a-Np迥1Q&;n | 3@,Óxf6>5lX Wh M8ӝrdhX7U=(~'aBɼaLB6b+YqI,2<; w_lX/歵—BQX66+ gגF,KǼo|vutyVnضc~;!br"zxQ͍~U%¶_O~%jOiYi"-ꌸMT 6ZYP?-J&VJ?--Lnƻ8*~AvWg J؊QoOwٺaBĻm9+]ܡ[IYAkNTHaa鑌pAeOjn%}$]֘/d"ΙH!j䜄X;P&&AquuZ6m[hf> f@t/66Q'- E29h/gb#)ebevq-MwKMKÆlj:}KNU=6ҳ) 0Yl`[$ %ܡEnCkon;:a28GlgX2^{)<.-.\\ (k.clh] kSX +ұ)髼Tf'ar25?7sx2}em-~?TUfm/κI{TD4e$GXۭf7:eX:KHXW~]\1Z32Sֲ&F1k^d:ZJ -7&fc%Dd-\iϝ*n*Uʺ!%](S ;o~tLg K =ؖxĭ9ѭ+/CF#DLYQҌdMme1^m뚎[Lņf8EMdYyQb$Jh7QBYT=zWCǔ~kB:˟>xTѩY))%feb~<_Y\ Ιs*L55kfBPmD|>% tҥE :vrñs@?J2`M+vk\Njpѕ/ؘebMlq1s5LwEm-`+^=Wᦻ^oպ¥0^;"myGф4h;uk>h3W&{˭h^[E1>}L1Ѭ|ϵj>vp (9n4s&fK[w`{f-䈷kYaJ&W:(p""7EbmӚ,Ɏ?aY.45~q:DZL(9vWyQ=Czg9 VĝQoՋȵ}wIE<8_?^./ڇ~W d>ݜbڹEV+D5H--~|?tNI?}O1YS}e5us _.M)VtdJdӧ΋Ǚ&Oø[ެ$l2 TJ -g]3)-d+E,-AdnJrC#ܦmm)c\",GփɹB=Yw\XE`wSL wfR-#&JFEu"g"FGټ.h~Y;D=UZpeICr8zRԻVv۬9:#['Skz_Q6*=cioDeMQ.m5Hࡡ:d!krNw֭議V!7ݗI3'|j-6uɪ.)4;2D},lqiSM//?~p}ԵT_d~C{O9?xMnI^<;ud# 7C=sO]/޿L׏//U /ϟbM]ꧏ5=={^.O?3GΑÓW>}ŀT۽>D'9[Ԭ;qiyuLߖ&vmgYBq)䐓hŖ J)[mOntb[́m.f2WgAf+޾w}F ڸ -f4<ԉ(ӟk6-jU5(W2ߎ궋:\e:߬d[;lXI,礸6;mK+[wOGk.{U-vz-b2y"ckgǻUL v a2Bt h3ƷbOOE6յH3/.iJNkǿõnd|7Mx\޿{Cܒ9[dd]XDv[cc hoSxQçOMMOUU LLry<}ӵ*$sw^.uXWv|QgNԲxqsI5Ƙ{->U%=%IurW+-ϭ"O}wߋ^ڻ^s{窪D\j|%%GBDEUr󧣎E^FIm"fQG{n=즩uEXndsYeG ƕwFWNfEcoX?7f.6<坯ivpfHgk88XfqbJ}J-]5&qLzm|dr{u lv?Iu0Z%Ȟa H$euf?Y`\Ҏs။ۺv=5xS2sOϼ%SRpڸfǎkv`6nD"Y4jvl4E1H]Mj?OιO8үM2NZ&%5&Iio~R_޽; 47>KMRJry\bUɐNr?e}}||VMܘ\MZ;J{E%r^_")󻧧?&%_NgԤT%Xyxc[3V6wfN49'{&}5k !2q-L@>-%/utmY*:6Ěi {>p:$2s4ǿS_PEl#Q5y҅V[NJ*QJjcXbԭ ֻ='!u}Ȋ_U`w:e.|kk\Y;TFuIg-ӡZפks,cô(Mㆭh00U+T eqcm'ry.p FZ-̬^|c2k^a.ee뾻=^g4Y .{Jk*'ލkձ[e]q_"M{T#h|JFCQU{,8[D^9WrIbcY4wNrT~~I?1߫CzmԼ\]_&*VCTua43'vDKI5kўA[t^jVH////K6BwWzmV6ѹcLW/ދs;[kgn[^TK0vub7ąI7"dIfj;!mqYŒclt!]f55y}Ɂ6"m`Xh_ ^ ;qcⱪڬF!f}l}nZ)Y B`{\N+gmّ+8IF<˝_[Y٬qgۖ `)f].o,y9/V^phּlm| yKUUk]MRk%CR3aUݻw>~jZ i|Z^[ :Ň5'&[%,=}p"M{ū3&\J)HjQ1V9s1V"bbr {4iRUSh%\vK!x;WwfI51si_FY*5:i!GHNyt:?G&?^뺾^ߝ~|~^k>8]幊UrOf|ZT/W_Km9q"Uu:nqk]bOw1ƺ,"MjRJfcTպorC]םCY5Mc߿^sm2kl)"ޛݺAX5nu\"}PSM*I[vؚU;z}oԜs~Ty .yDž̄k. ZE4ٛxdV`w˶ [l;i̺i ^s>d nꦮkCśxd!h%x߯MdOi_9!cwu]n#H瓈f\debNo\HiF5֢E|Xڐ4MB~>D55#4k(//4 4B1. I4]Iצi:u/~"OIO1^u5MΉ?lN-3*^LStir0EXJZu!4I&sAͼ|'usKv ^֎4IMEC7'".kT&qmm6}k}Nk!$߽ח~C18ca^x !x3CC1བྷ*Rp>?#ѩ\+û$l=QĔ|$ЊۥJ_k.Gv%V.r#hfvU'^F ·*W 2y sVeblͿ$ gQM(j8NwX_D ,4v4;'&p5+%\Ճ1+DiϮ\Ьp>{nm.JSu6#e)[ kq4*-(J e%*"e͆82L-}clTuysRP-4w=QSM1wOO׺Ç&%|U9BWkLMęx'K68|y15iދO'sNЗi?>GG]D\d9cvҰ鵩MUǰulcv/QՔn&CفFN|Φ6kk@6YXoɩf#ދfZCUg*OMPv c7iQ5$#K[<\-!vL\ҵ&wL Ec|M:S4~w⃙Sur:YJRI43 WULxJesRҤMɳ{oI&b&Uن`>ڻ'oNRJ=5>O풖ҷbMBDtr"!}mQqm g^24\\J/NE޽ӏ?.ky{/1?4Y۴`R"W:[yw;hv riMd悉wAxmV.M.Wy:鵾>ٓ549~Lsm5hJ>iԢ6N:j.'TUއzhR[^kqa&UT'Ni|2Ԍ>ZGc8U'SU1Oz61Et:;rԜ5·].$[㼵L5`gFvc͚x-u{té9*1cb=oD^ D*v*Q -cs N˦6i+ i}fdj3iSrZ3*"9ZM|>_*cӨA&}ɼ[vtɱ"f7sjU4Ku.w<:jX,,O[mĭ d8qw 0Im|br "BVDž/܈%,lW6VّoZB.L\7LrA?M葔{8MI՜3B[gԒ`ELMUIMQA!XϥI)c9N15((9 !G+xřhT-x\!DQM7Ӕ3Dp/&|!cV/SevA^{י4)edfixjzx.ӤWq\^/އ6AHȋ%5ND]{/*,Ԥs(9 ]@é>D_Ai2M:-U5"F"p&X_SJ"zi>}s%S鬚56~751:IJRjߎmQi s \&_F3w:U)ܸۙo&B;Ln_5^.ԤɆeˋ&(L^W[t'윺^s^$mngQy5Kʤzփ^'aӒfb8OY,RJ׺Χus^,BtN̢LSmXW+493O?6Mz5CQ&&NRk}:kLSh>mTrnm@m4_./u-8V'\~1$M;_]'gM*&qߺ{Su;9'ˆ<<f&YU1+r]U{@&9Ք>6HU'm!,ivXLQ|TژY]M>/ADMTUN\UUZާB86IMSTEċ ݊oƑ ݅YiѢ*nT5=ɦr*k༰RѐǗ3j 2Zcͭ;͢"92]c/S@g^jVQT7<w 5s]hChR&t>*[1w&jKzoc눩@FMrkzaZ4_WʡeWd%!úFq2cΎp`;XL$EBK>\oCD\޴3m"R0X[rn֧h{sfYf%6{ d")= ˛zNڷZéX|E"fKT]Ns.kDE7yTє4*]{5kRrfMӄxp&_.[R7R{.ܹƀ9KI i$h^i몪٧*ZXKS z}/J\I.od|x\)Vqy]ujbK&Q}; J4jW“>G͋%Bt6ruMtBM]T%5S "Ps<>a\Da\E%>]nrZЀr>rC|>> 9 ܖ'ߚ$Fī$)ΙY3N>k+:w|.CKuxLIrɂQuA߹GeN A{/3 E fmhֹ :O}'RJsN|AmLE/^D'ln~1o]}ks},_93kR{NDSK[BLbU{&9ku1`RH4Дcʽ|iݲ~oj+۳ߨՃM~QB{Z&|d ePu95m&ēbޛj#yjJM|4ޟ%Eh6pلǧBU^ci9Y3Ns Y.؛dz<;')iq:,Zsjv׺~yyZǁH]ן>=_.t>?SNi~t5?!m*Ú>r;eA'6 Re˨`JinKבMzKF̵aDS}TiX!Y!3w\µ\$Y1+:4\ۄF}|O>9ćQe׍nA:Idkι51o!~PݩV /wnS[,Ys|[~x9.TD.|m>DYz6M2U6.ҝ&͙^^^L#RLSSn#ՑgJ?V%h6IzSqõmDx^s5N1ƪ:]79/}1YDNgFrI9IZr>џOOOӹ]sT'uzy8vþ3K83/EUlhޭ ^ު-5,m|\"mβA݉SV]TiSlmL614L)癢vWtnJ}h;QĘfR)W(‡YUrZSw<]4?)^ZZV?ٖ6{L5%zQBNdUMM(ާFsrɥkc#|CL#ХtC$hBΔI)Yc*Us4"뺮rsS\:'vweuZ+`m}nx˾|_|ҺGBUYnɊ6ۄՃ׸o:RVXiø8NEvv ~!G M)7 n3ٽ$\*=QVc;n/%YCQU/߫Xuv1^y9"kۥhUMX)=v!s#5 ud=!9ZoLXܚ? .Kmsd""o_s]?>?>;ofZ]~ve߾8 Sqh:ƜxJ:bRNv̹<<< L@5I~fC8..Xv.2BލaS4x>5C-lJ@c2U/AW1q9/t֔p9| ٖ >>uy[ɢ]H}DTg" B˫cqs'"ǿDT_0`58t+5[rr ff5,_*"318w,r,À)eభL}C^r ǺIb$VgJ~* "08Α#= `H 4d{ cZ2ǝɖ6t(\cAL` f0Sa @1,J0kT.6bP3}:":7:k dIiN3 ouh*ĩ]1s2LWʘ)H? 9)4ҩ&k X=$ rѥaƌ`XͯpYK`D6\9DΔpZ~^թFwa -ڏp,{0+vAhؑ~)`Avqzʬky>ĻqBďvq . NyNDL8*󑹱Py0"D i(;f~=y C4l3$kdy7Tɼ]4yAÚEH5iu;+"sy+ƘDŽDtG,h` ;jĚ*9暚ymoQILkLJ5P^IԀREbLmYI]Pr=0Ě+xil2^ h8-Դb0`hy1oVYGu[ :,o52_"STK1g0jWkrHfUSʖ`8*4R %Ms\[o,"ï9<'$c{:ST Q)S9|V,6&lz+u=y{3mAl1ڈqwre7ҽQnYo>6PDP+0 S ʒ{t)n0m%"@JXep|Ks!VuwkUjc&hϹ.]) ~`:N""DL޾}{{@rD^Тj4.0XqI:тAn5 (nmGz&-Sy3;3۱^/UI^pE={J4{JLJ0S ZS i3kʒ1qVatpD4 Tc "ߋgs(&uv9ׯ_' u=jT/_6 }j<4x@vU82K-a"1ʁs=Wq=Oi7˴wu.fq<|l~o"4$YI 3YHg҆F8OhՑ2?t#+|P?We"5ok1붔3jL <p矼{.n1벦s]Q},Ý#hpy&0HXqC\*B̪Yב @u{lDe3~jk@gebrpJRRdԌ<53諭GkwWs/]i"{#?aDp`K{.7>h8O FL8+EZ5;!3R!32gg6hdny[+ ĺXо8.x6b>s-QF/хN23:E͌5bbqЈuleE-umթtHlkMg3z'1?[cAl6*>fVy=qoPK[mC֝Ee.4ˆ]ο{=tc 0ߴ +`|GWDPa7&!@ be~ЕrI؊ x^!r{|.{̫BR~ TzL-dz]X§ɘk)V:Lxo2ftp+4 q/~W<|IxL 1j/R,wR1O \7k5 W}Ni!h5W% Ts6px;R+Jk1|$~"ŵ *bw .SL@QQ[kkZxRRO僀@2v$s&IшQeޅLi%qu"i)4szyqaG %~|c"*ߙci olIP A#+415Lqmt S4W#q>1n_q>z^ȃ[ BN H+"̀OYb+aH$"MdzdMÏVEۣW4խ!&TI\7)ղ37Hd8-[ ȶD11,\b %LBݮFr?] >KO=Z]!31< ^(DL,otyf{7|dc:$&+l|t྿eߋF _\nx b|  h`b@BFm|y3ގ. `ܲ_`q VuݯL[V-6ʞŕch(]6¹j 2&_l0h*(F#t%{(#4!c`cy A4%P|rhH@HhkR;CkDvHbƵGMy!U!8nܢlevhYKG"10h_]k.$j:q%D +  Xb%31:Fv/}ZJ%k^RZS d嶫Yi(UOyh`sH$䐗xayy wNgD&Y1h)UUnǡH&FDoqyaxDn >Q %Dl>趖 V' ַoߢ͠_mk 'J僯u6^&A{"\ 8Fs AP>giQ6מ1vZ‚-bF}-[}wUEM-sj`p{oU*l#|J-;"aDJ.;Y~*0Ǿs_2t#ȖA_{E4 H%M#+VgY)u{fqӄoGrxm~~/!~@p]"EU~Mu!Lo7W5E7(3s9F$?\Ui S "5h*@9F Sˢ' m{~+.NhV|;j237!> O8U9v%4%iJ N8Mq5m,5"Nl&6S\ķ M,13#8s.ke ϡ(paL.\0(קF ٛͽKna?Qԓ=әK{a;24sjMtw9^TD}kTqbPZaRZ*ޜR?>,Ц3wrϖłMH.*89"7>pX\)64$+b䎀15[zYk߾8`-ۨZ&wM|C-dPЀ&@IXZ";K/w`%Q6MP=k.&_E.$(/`؛(uC0UTm|)ehRG_֣y݉dH­4kؿF=f^on˕2ϭɽ5Гdu0f$;G_ Rg#])|5ZЯ~[/a/Rc& jo>mނ9}@T7PuMH};JFaחPSGsXdX[a\kc{d{b. g|O)`l}v-vsе4ଟч7}Qdl7%~VfuZr+S2sTE(L'BXTLemMM^sڋ ԍx/sP}FT4`zˆGS[kA+658PZ/-623 ht.%8m-/ЅT[7kr= _QTq%iI@qЏ݁lz)% `OKnKs}l[=AUW=fnBJ^YHf't\{q[g # `*6#5-+b>ѕ[ e pvi чⲟ88q@-OQ2TnP[w1b8!J h, !&k([4M=NL7("k%X9G[W ۩^Tm^J(30m"rxS:Uz!ܕ:Y Rl${_rß?Bkܳha8=c7Iǹ`<[ uN2Rrh`^fe2l{:{l#6[&3O=8C|~KYD}NA ޭAk=Ϲ,|S5$<}m/s@#^S[3lAv=|+Gt 9Yݧ\x0fI pL1st6FQ'ur-";H!h+z ]"Kgy+` n8 C=DQ-JPnfxYhL`e})  qٷQ>3 񼛂#gCfhIY~ ,UO TO^6x~]' ^.*U+55its I`. k|>ᓆr6@_Cƛ>[nrUbEs-ޭG91pLmyc} X,ZeN+2%<&hW{y5hm`9ImaDŁHf񫠢OT̍a-?{+%,g'6EMɹG:p[i6TUhj[NRqՎT Y{7KB  *s/Yԩaiԭ2v3ps(  eS oEe7ZOuA )%sb,6# /?t414pS%{x8x1/v݄غ%?LakU>A_zJECifdc%2b7mݷfa1uG66F{t #s UНd mp#l-4>>"_Ef!1ns.5lyI'".\UpqHӧ>6+&|:;aj"ۢYh5{*޽Wtݦ[lTӢ5rztٷ:Hv/}&(E97lUȆŴ|)0QGkBuZ^z~V?L|ocsz.(>H@.F%AD=7.M*C$"\֔%y%kx °H[6u>q<Bd5 ݠ 9"?6GXmJ(a8<:{<8.+#Vqq7XYR\*>49גuw`e Ø}XzF _Epz5{f&ED#)-\j!Fn=f凴<wP'3sLNMd@$Q#dXS\?h5U!d%$B,T_nu]0U$r`G Y;J3՗@Fb`1)z\hB_(LY 7o_cȚPǔ7wL0`}{ <̇dqǁ6T=U&dSNH34jwYDkxFx$~>ވ{t}WL~/ {Sױa^% ,/uԙxZ#7yfFBƗf ‹Ivה:TrEOkO^hUؾT!aP1axhKQ _ZZL䚵591[VnuIG"0|^\K<CT98 4aJTGf æNDVa8 NeQY"(&)mLTdO;SPX'yJp [0f]s { |9jqU?mz&bHں ;5ߕh.:pk-.0 h扪*bZ 3gU@8#:tv5L)*wsJHSN/Ԯ2&ҩųQ5E@03 ȢVv L~|c.BѦiMP~c L  bVrc7oHʨ:xݹ$2 q-25z洫dD![ 3ff`/k ĥ&%$%\1v)Y+ģP~ ˏ""f45`oFxTk:wa%  QAc;! R̸vTf0_ ]@DHK+6/=||_ װٮ6 i]fneɯ}~-&bmca[VȀ"|k@tA3To剔YL>5޳, /YDDZAYZkl끈p=04HI-Jl BLTjzȇ?KTms`T)d{bU`HH01x FoB5-۞Tqj?A6gU}EߝY|e۹|6;fAûVj/vW]I= cph4gy%y}"d%*xc4i97-  M1'ITJjQ\5ĪB&r9)?o^Ϗ?%<"^OnFbк=qD]cpVnvv!ٱs5~FYԒwzK{bݪ*W"#l;h|EoR0泱>S _qjALtKVmZTϏ??%~}T'IA*݃` C$!QuZF׶%T"8EAJN^9I)_anvئԅ-zD4ڼ6tZq|IF6oT"  iN;'jk'Ս x"z>dsԃi$iC%yC V{he$G΁ Af[ |cgmFObGo;r*WG%H*1D03v뚗®LIJP( dooDX%c # q'S(fKrM+7@_ӠCg*©IJ`ǘD8,PKJ!G` 66'vCnv=v(7 a=ۿÚT-ဪ}vo@j8ʥ_\$] )ٟ LN=+733B زؿƛ3YۈwL~r=5܈}'Q]Pc@9Qyш-??1x U=Ƿo/Oq` 3jrf:Et#5|' 47z#.QXr|*l`JA1rЁH<ϜLt5yMCpsrF=lM9O _G8dЌ%DIڵR41#DpRuM$ ȄwXX'Y{TnUE#.D+ `~8_WMj&H$t:}}QZpQz̳fb `Y3,oDqEKاrG49#v+16Xާi/Wdzksbk'Cd"D҇}s BM8CBΓg; QP%41*f?zY%=3:h-DŌxSKSj K"\q:Nނ,=O,?Maċ=,exD2n]yi> CamC:JDJI ^!0AHj2ic?%DۮO_WӐ"g(V9qGL"|[j)k"]eѹ9(K{8F$-͹s >1f>K*8|Le㼲B|}H׽W;>,y]{ְйX(qVؘ Ro+LeL `DpL]QԠ[%qp[St) ֣dMՊ?Waܓe9㺞cYKZ̢ ,uTѵo-4c3EncB"ZsΥ*<^ %^^ q Q]"fι,Aw}>CkAgP+WDdWw2'.5 MY3F.}1f\&>Ǯbm0*Z4:D2CEJ'o ]9 wNjDoON;!?aceZ*%=[.f@ P+YGWonC̐)ĶSxc5r浖q}0[gԥ Q\KCNgΫ-&馛p15q=&I_iB>DD L w~XtUu^Z+~a+8U0é TLqN䮢ٻ/P9_MeW_(U0 Bk_[tj"Ň3m| o_8)M )VD*YX6D՘HU2>˜`.D+o$3B%+-L-$UW|"⋆m?=ɼr*~W}=XLCk] ^5}b} `\j-Ŀ0Qi/Pc^öw2S3U7!BNȍ#9 Dntzlsm O\`6djni.{bgj 'Uj"- _*MjP =ވSGo_Eu^_7S\d- VFϧ}|T!AFûBw1*Qe/agYEnkSö/,+2{7fi4莰m›)CvETh.ޯ`F'Ub+2u(h^ki.қ/M(pn_`DK*cj; Lw?'AykV,@39,fvEX^wKv}Dt`+3OgALɮG9KpvvvS 2\Z ؍od xgݶ^ȌwV2 50`՘.Ȩ߭4GcmQV#9EG, "y^ru%PP0ս4fC:4˦mh{7IwӯG}m~iOnkj 1'Z 8̼]ݶwj`7f<,adG|G?. @&qbKĿ##,3%s.r1s]QD-r6M4@]:>ۆdO 04LfMỦ>E]QZe_t '&Nf`y4>$' "cc ڄf{ql5nP8amˌhk8<1m5!w;Ƭ3'A Ld:υ&὘2L΃|$`dPmmWǠh yoF Q^2Ll]"d#Cl-g:ƵҎ]*_XiU\4: B',%hHU1_c &V5X>fO2ߝ"y;!LO!Z+t z `"4O( *AWY&ZYg*a=K~Se봑lfp>e_!Z#n=6"$KȾI[D{4 !)^18Ϗ\xc00SS!pK&Qw9jTVRiLOUW8}P41%k%{$\;l-ጳsl1r-9 8z}Im {ׯyq K}=3AeQ!5c<q]\To^"čZplf8Uu-93vpQZ/WĎf&aƯk\Wet@f%o`|‚&"RUEC\8<=Hl!??U e,O֟`L_9'ڍU+k{ݜ;fkkퟙ eApDd9RԖG'1Y#"̤FBo2V@x IWiuNb `Nx{KPKLobHnz[[9NBgJNDʬ,ɏ5n]c $DH(|$#Wt;BB1M|ZDH~p7`,r 9\_F~:Fc9yĜ D`b_\ %r `0tIpѓQpӚ^l`)ah8m.kKhyK ob}hUq4 !ؾCp>O=h>M lU6#|Bg")BR{סݢ,amMKo[FnYxΑ c4Rxf6DkBdlؑZ Mݦz|X zOXbD D|-q\x;T̔PⱧ ayyHv4DGFD7 89@cq Bqɖ^K]H$;gEtcNxa:9jATe-b=8DK1LT}X81o߾}||X;pD?߿<tiH׺Y"}gs>Uz"K՝HPg $XB?"9Fen7&c1=]"*le|0Y'j2q9(&?qu!21ʢs ~4vYG鋀`Ӣ_jcڗK}5.Z^,,ZEf2qa\0zfsh[d*ѺOGcm ilƍNu쉵% NI{H?7T # Dx<Cn &>r1r+[ `%"P=Zh[EOX׌ pׅUgCD[ 5nIx{%ĤɍtNFٿ\G Ҥwۃ@4-23=wZLlfM۟2ӉJDM)\veO;a9Kq+}gㅲm{`/Z 5amj2GCd]Fԛ\^DZ;I>N N"J/ ~SG)$R|DZDK0j??>|MU3iIy;`e2wl)5֚,(UUQKP5#R˽̀>4r>'sf`)ۍ|u$` @u1uZQ8\7 ~9/1U8OD?Ō;*M"ro̵ЀQTUtpfD4L"ym= `Qs]s)`n7%ޣ5ELME8bn %z>=]5GVE3YZSs(X|ZA-~^:ѥEY&*&97 dߏ4&)]-u1r"=Z@rٯ90tb9'JE>J-vAԪN_-Zc|U7%?m\D_B~:( ֜y^,`8UfaQg9W麂zy᫵i u*_b,VĭPv\|%jo."R-c33Wmn%<4+:mh)}=(=sZ)ag{YQ7m (;dK6Cߢ}aAcqc5׊9'y2 r\҆r$ C%; Geͥjxpz5sVEm,[HӆZz0&1qAcjfMV]GDfVqX[ôX%ɪ̌p2{[2J$+prwh()Pn0F )Q9󝈌oK=W`}xg\w)ܤjĦwű3S@3qmy)1ut|1F8E a<*c-sf5n~Z v/V[SURr.KJC#1FM/ Hk'0R w{x辐"  V,[1 rv3+sq>ng]6Q"9E 6Qp}Ġ93gͩIg"i?&B8%Gx*TʒS ㈩Ѳ,K+߾Ԛ ,&")u)%¾|@q T3sm@ P6%f57I)quDZ=7ђR?~~vZSrmUXGLS- 7'wy+YS)Z-!3Phw ;~0Lǒ{SJe)f́w xlLqCeM#j^@s.3t?@Ϲrss3c4s3Z ڴP!n3; OIgAı g{ehwp~uQwK1?GZgj̹Ď3ŝ9xF4<2bϚq!4ff{US#೾袞19^>k!!\VM֍3.jr^{:(b SZ.b8P9[_I coM,4$p"6w9'\RH Eb)e]^*˺Lmy}m~@RVGOi,C#`,L:}8=m]/_W&j~ID4P2'̙6G$.2 -M 3Q N99Ґ w6EjNC1VUr"~Ty&uQ&DC̤kRLV9[0{g#.uc`d1Gom:O04GC'oE!1GqU9BLaOPY`?]z@w{μyV=]D̜šKI9$g?!SbµF՚ƋGFJL)߾3pv#BJLSew<=}gJeFxQe gXLA]O#tv]MSs v.Q1_׫Gpts3irS_E cu]X13 Q)!9/"f8諱 `s?ӈB|~CD!bfB!mht^C8(πXEC^iݹ;‘Jm2Ʈ})qwLH׎w"D҃m4^x^3}bv N^8{Tjj"zQRʹm{Dݶ @[⤭%v&#Xv4[ぱ;(8Y8lJ~`Đ ̉L2qeH#O~8n2"&b N:G!.CaB3S Yy:1C" rĽCOu9'DZw' %RpU9]Wf~?m0*}߉mmu[Jr4Qw0u9G4q)WL_Z-_~-9rlꔘ4SŜ9q/2{*?9XaCYhF#隆V DE~^K ?Wq0Vn?]_^_vY^oۻ){jgV8UcGq&UkCK4 vY 4qDoؾ @HpVOTL`8N:#mb9=, 1fSJ]518TE2Ty_6!t ϩ*""&."&DjyFK@cqJfM!24iu!`4]m1sx从YxD&sgA^}vFRSOfZ@QT~hE3aT1|xOGC)E҄j Bm{ḾoPkڐHDB*9MZ }bkFop UyIƉsDwup%?-FYE05Q}{{ˊHn81y"L)%`tS}㌶apzB >wS-%`@ѠfJosS&f. 'rBG NN 3z} Հ2CJqYKNPrs$YfSB 3{yPHsR˭[GffĢ?9Vi2s`a˵}Y۷8_ܜa`~OSe9MktԽWIn1?s|u(,DDS dqdƂ@vR.*E /hHd8 Q-.pV\4Hs KR2&!ax?}:1;k:Wǁ{-OfDy?TMTkɇ;L+/$Ћ0!b: >Z'DfPRvsL^Rkcdyjc ){NHg}, A0h})Z_E"\ vk$ R惹;5u*z LmZN{<ӒG8>L@fhD7PLhy&bcaSQY1QW𩀛0 R1x,饃{\N2c@M8=,Mc s̜Z{KΈx\}|f,"Zҹ9vM#xF?4n"Jaf%։QjuvPk, R9eCvJs35[kѽD5{GbfQ{l[5t,T닋Sh}9,@\N߾ %9~r.@vJk[m>ԓ4FD>>>Je,K\UƠ!a( GDY|3}X]S$tg Gy\G8sw"vڋ umQ>DAķ0}fk-  00}y}ߐ0gHסr)95XT$̸)Xb"4&X|ViMuH+HUnSNGn7K#@%䛞Yց]20ok A# s.x])948S;|}FNgILind8ĿG#w]> c"JD)gO~`\SJZ#=d.'4 #Rsﯛjk)rǰ\b Mp4zN0'i5%ӑͨ~a1*kɷ[O23?Is5(='${sXι6r;-!BT,:s^g 7PJigF0(X]X8?.v:̼,KIDm䦒H  8up@~#oWxVCGD#QDs9Op` S )9d@2g]6["]ކ1r 1SO(DyJos)ӉpV{\_^ⴌDhJSn{k}~H|X&jIkMy7S!䔑0HܰIx%:(Af+3= ᣷__[}dJbۺ|y{cvSHTcu ɥ' hj9pYJf/7y40 .AhRӔ81Y4ָ.%.ݛaJp<>Zʾ;p&:}7E_Nat߶֚A< 4haŃ}YB kcyfsZ|z][mʉ/}`e] L9@knIbrp&8L( ;Vvuޤ=z" .S 4RzYv\/3\y̬j۾4Gsf̗3A5nC^?8$zEC}QoMgܤx1'bѡsO5~l镨ӭylrۥ)# DhVwGK 6@8y-ys#=BQF{a 7Q29hԣK5?e7NeM)}0-~RQSʹVE5MR 8p˾, x5G w`\>h<=!Zg}"`!dœJVjJRNf> *;]DL%*h|NM;ۼ(.g ]{!aAg3*A\hmUD[~.9mkiu x<<É=s݂S]q L"bf#53?sFv4"_r$#_B0hi}Afbbduʌ;Y }8<~iO@3oZחC媌$zYZzAĽ<zWֵYpbϦզ=pέst}{<*ӗ/e~{xlH@HDDĜRy"eݷǗ6X98Rbf1w87Oh}BOp(7B1O"D("Z3ďe\VoDPJ C; T@@Jymz_Z)jqH@9R}L۹JYgۖFgf.~Ey-EU41ij} v>=bpLȌ&?^?gM钳;3_.m;̰ۗj* U0xTl`914׏޺G1A4~%ED$#n(nz=ʹp>mQ\Ѐžx@r'0K^3d/GAǸ7Iۜ ^#"1@~tQG&bgTX`b'[>Ƹ t`J23ic)IŹx実!H(")q4 1ۭ֦nms9nŚcFE6N^x-jHꊓéS7e$D'!D0YP۷<:ydJK vHTJqCxbjj./JU Of3"r%.ɀ'S0Iw pνsSB 8'$ ^3Lr(<ȡ?-]2GI;~X ̤*/_m<ޖ=<%?ֺsO#%MR 3kmjk'`rJٹ)BDH jr[/۟߾T0;1;rJ%i~3yD-NP;AxN/ACw98YK)#&R5 8tU1@9%9i?}yUy#mqF88"nmOp^˲}?6=|нLWlnn_%"MU_akɅnTk}*Ę'!˲ČDڲ,9%c%)}_^Am[oMʺ/qvo9i'bB,=,OQA@N(ybզ1PbagUM)%PqPeaTG"&8v禌 qRƼ=>7f N#.,shv;Ikr9&v!?$F/bf:t1ֆ2}#|m_8:ՉśM8TDi4Lݛ ?zG%01 oB6j-?PL)0ӹ<1nNܸS6? 0!pZܡ6q\pNMsSWUdvWPE)Eٗ>|:ZНFc@o0"1VwdDtRN3>PbS5G"# Mے}j"̭#l))3!J!۶qb|̉r.pϜK3nDs9p[k" ""i3c1F?NԧeJm=&M@̪LtB{vmEJ4i#Gφ}ਫ਼ey(yoo/l!"6it5\2'JHRR}Vkm,K.?~9)2rC}z7U?whZ㱙s[`(&EUIHHjPT89}<,"벖 q)x[3\!#K'BfYJ;@։1蛰?a"9񩏙Ǣjj!Jy1Z+$m[\A_M:(~dEƶ34>@M!37vLgOdml|i9s2}J ~d `J4 ]'56ZDX ZG|9g 񋍪tm6z<~ΟxI#YRGF@BX|ֹ=kf8q,cxƳ<9"B0ȡaKc8&FOIC"6'ffU5&mM#SJ@Đܴ{]0vㅩ/. Z!3CUB%#f>e9Y>OM8ǂMh>bM~;f3UK9?ރ;TrTB39'Go}rRָ xJe[):hOCZĜvֻ0A ߹1Ӳd$HLQEzYu6z߫˶~{}eJ,1Nx R3crҾȁq~y}mu>Ԛl@;>Uڠ+ܵD$1MsnnD䦏~DUj/D#ŻwiA'v9C"Z e &1&>hyaJ=e3SZIdB^~H8G<>n)SgHY[N,tDAˈ`DA~qZhh M޾_V3$M¨  U$OaŽ\.{? gq"I O xVL/_YyAIվ}VRJGBԺF(.B sήb߿+c^C1>L ֏/ގ+aDBP3EfD٘.ח\ɥ[K^v+_^=MsJ"҄mv]8@.fiYUz#!!'6c#R"B@ÕqPgUuHHrf\/ON!AFiG5GB"&yKM+A%Dlꎎ6-}).J6QUq[kcs 9ޚ/k}l=QssmU6%sw:~ Xp<&8"`\o\E4 xS"BSwD)SMMB\8HPRN@+*֋a&!!'28(ASL`Z40}y}'!)lEu@8SB@yhQ9<c?L2]sou%t2(TfA A׀E^2ۉ3|v} ary u{8=;AO!* YJ@RJEPr!x.Wa#;[ <s ;oRyG^fF&#팏d#RiF`9cɝž5?-1SBUI 9 Zk$*96l$vNS7p5OD9%@Ԝv]L5LLyF=̔T־d!fIk1%ִ6=pϥ ",KkuYHpg$azP4e)}~EGHfNTm(-H(=Û"S=S@V/oo*Zk "@Tce]B=|s+cߧwIU "gM9?~̉AСZ=12[#۷h*aD&^JkO8=5O ֈy]0dF$UB8e)%}_=ni-VkΌYB%wrI*oOD Kͥ`k\~¶"eϸTR ;Jv}})3Jɟn2qIa"h|č>2a ׁƏuRDu4EBP}f8IDkbfH'ٮ,%'Z]}ٲ./[\lnC (D&5׷q)˲4 S*Dفj7p xp̭ϸuQ!`vk n-}b=[m)q;Z[kbqpb:21ʔ+1kAu!w;> ps'6ذp'0! _sߪo[4aҫW :XJ3h BQݛ*wx:eYft$9s3Ee GGN)L3σ@8-ϭ0Sfib!瞹a)AupE8<;ǟpV؎u/Z)qG-B•3+A;Y 5m_e֖}kv Zm-1\5̵dY;`ݷ֛sd0b[9=#"c5Z?N/9ޮ";/"=0u1Qf3! SptJ)gUsl1muh?2nER*L߿?J)s |c1 ژs*jnO:Z&j9^4rU;q|6N! Ӑ^__n_쏻?pR^߾1#1"ׯxA\rF47ߥEz[񈊪$$"̈)r?'5CnGJA$ژrkmmo1S`NnK׳fO0? b#8HMCZՈ, n(݈{)DLBIJM(09-˒RىR#"l\U{)EU DLQbk0|n^??w_DD%ZkTRkK(B)&\nKTN) x!^RefDM$<͞>wgPJLK Lܫ#=Sl۽)PwzVjMͣ Y4. )ueN{qRĬOOzbg:a3N,Œ8R+OfjfCkӐ=%漤ZA:)yY/k&|]?nx25jHjˉ%3j:*k )RL\/;R/b \ ]md$ƭ,K Dgf30v35U`yԅ*9&bDpJLz\˺eSߗe^//,!de]o//)j9KU)dfCT-TnG\eK*ްU&N4`\.ҶͬԺQ0j* " aS]KkUTcQk_# -x_^CELrNjF8P[2jRޯ,!{Hu!RN])>@̩"ݦ5wDr 3͇E7A&_3>^7NcARS>1Su"\wwa$HC?+>t0斶i9&TJ _1;$8O@PH;qOn{53%) ^%k}`]]֥;'{4L{><]or-0"FOg(:| LfrW3Ǽ!.t{t Q\ÊK.9mjz߷mlDX74UN)Xdz9udu'XxA{FŚȻ?EZ R 3G,T 5sDe1!RJQS*9b;zR+6"Dr6h!sx_RJ^rF4RK8Κh 虐)ryeHMV f7;sm{KN,#[GMsN뵵RjF@D˺(LRUNy`# bnmh]@LbT Z:8D$}߷} "bNャ)9ЪZ?тqf5ڠQagp8>OxJÉ~26 ̡#PC3qbjGL}v0&Z}Ժ}}}{{{  >NEU܃A8*=(W-6*Ji攖e&߾=Ƕё<A)Yb_*0PxrU4>K.%KJnoobf Px_(\=.6C ݗ%_UZONp+J?}nSڞ2#0,|*S朤VI]-K>Z^.?ykk*Fb9E~2ZTT9'M"'^͜R@wyL 춑{S:4@۫쭭˪jM*Io쩉RZvb9F+^嗟n)%i-DHt3eUU5#ZA0(ZR3suL`c\bzP]mE@B8ʥ^wy#ێ蜕7c|w]G6 $f;"+j'̊yC+6oc#_k[UM1t3 ` tX!1/VsRAp,R`SGtAw8A _zz1m z\Ё#@:`)p2qRb SthN|-Ne/B1}qR]x?T:O y5۾ 7ilGRONr<dz姷KI^}[m D25N_$̪r͘&3r":9`p*16q5䔑`F8;^j[ ]AUXJ!Dփ8{E %jbeٷʲʾuJJA`N˲%@,HTrjM5v\tu) +Dl=p3+0qsǶ1mz}}y)TB{m̙<|wnm#fSWwmHv]&|Ik~{ED@HIV )*~3uinGZ'37>mC_=LiOTmNaz>& jĔR)L!a9"Hm|w8C (OB)mGfoo(*pe))s53wN̤"Zݷ#T[ {2c ɩTrW)%H˲H̵=frJ(Do/Kq7vYr{1rdi9/|\,mWO֛.Ɏ[>$#2wMڎ} $tI&+ɪJ$Z?:|"ye0`T- 5o .lۺnmޏ#C8@\f,+J㈻RK4 E|e G[$AS49<23҇yf7y1/)AE<0i?jK̩/ޞYlzoGS3BqZKW[]0ba94@ mnm<3 3ZjĀ77|ZKRZ?`]+vP#fѮVeY]o& Y*~Z>>H,lvZLjooo"j^M;BC;vֺ,mL;cu)[_,nH \Zof>afT8!ßߵ[nI%ek' 0P`p Xj巿}xb>ȷoߎ>??8Qpmkv(3Dw{QmcY7UAnn潫GS6 `1J @dDF` H"3"Z;|I;3+[d6I;<9vͥ ĄLgk {CLw].]f67[ D| y K !wfF@`┼ se=![a萫cDd}~_`jœoi^slýHљn^|[8 `PQ#\{?}c ,q vsA-XJ‡MXj31jWU:ǶmVs_[78FIbDԈ__W/*<\;ITZa! H39׶/1mjlZF8Gc > - m<b̤/%h. Gu]ǑB80o~oblSCۃ;CytRt ЄPL̾|0 c'k;vb6$)I|#4jD3faa=vcDI۲toZ(5C1q)U0b]K5Po۶Վ-M 8`ן 32b~{ODfևj-"9Ors2SWzG;_uY~Wzw'B0W)7b&O޶BtjO4bY9z2MB"Z~# DM+` WxnPSt D,Bs"81v̼r]?p}]*R?™IUk)~@IJ5bߟU$z?>,\P}qvgi'j}: ݓ'jֵm7siōׄ$Ad pLņ|(zoh@s~1:sG/Б H:cLZe1+_˩9jN WdVԧ\,.`fC y0g*bVeE5F?]J@) 7Gd.R .֙M8D䶭s>>P(L5~o4Si-e%"7LS✉u*XdY-cXt003RO':0`" P?ۛBͣ;moX؛sh3s"m%U{Fjd9=vA 6Eù.֥_~wel3ͻ4 J@M+̽E XEMZtUp-}Eu9SsG7[TO㭈u' SxY-{o8Hf∐'u3IDsmÄ= o4Qحge f-P5"eI*ل,Mm\ͼT{c>geD\JQ0eXqLHdn@,u8̔OϏ.|2*"ǾA;&0 鑣`y13B/y1S_/2b:noH`=;RU ra~߿7fI69CSˌg2% RZ"tŨ%w8Q9_?j-.@huMN`S)B| l/,,uɒ%|.c䑳2駟폰N7Z R(}oe[CUJ00@n'ė)' .EYMPR\k<tyȏ[8tS.ZRܘ~QXZT`7#E\;#o~6S,+h0DJnH sR羏D:.ڳaF ?d@8]!FsH/Smfj'-<)nP'Faj6DSK[N"U,)hG 4iPjfq)$bqԱDL µn[ב>Ӏc/:~ۄyNXDr="#S0}+(UB*ۺ`mk Nt2ۯ"Ŵa6u>P.L:H#0AwswfZDE QFC%nHxNM|"1!.B;<ګK|:̹1zDqyʜmoᱬkG>Q˲d˚$td(\ͽ6PpI! 0"`|>>j(qf&񓼿;"ۆ@PUiQD@-Pv燹%=(w{kZF9CZHRZZdIip.>>@˦:nyd5+"D W7k8ö}$ Ț5{sxړӯYn,<%.'ò!ܗM ,Q r;f@w޻-k#u@#Fa9h}ۧπMMÆz/>$DԻ2Lke'CL<#!$z<*"斓tɽ81ǟ@L4,"rKbpc l$ m9xRٹ3s匘qXL¨sxN;TD#DWVgΧ-+GfjGk+3&R:Q5,,"<{ァ.ohZ

??< ?'5D}=ܘnj8CcaE_mkoG1Kap6$nR3?CA]3i}#1FS#.S<=oUuyi)7vYœb"1Ju]o *r&|[[d8XLBBkRKaǾ D8p8ٙmu yxBD,nbnS ȧ(r4/l7桐0s5 lB!Dqp8(D3EJ-E) w |&ʠe}zyo)Y Yu;$>x(O9d\A=t5h67}^EJs,sMcyI$L|FIK,< 7 ngORR#مZg GT IZ {)RJ)ǡffZZ:c1 *)f}œ1}^,ޥ | ضmnL1KXѝD p>e/I^b ~YV1˿>"k-m?C2lmoZXD| e&u@O \9hY7"zG0o=afԧ=Tc۶Vx #HfoZKo~XJ $`,*f)'>hǘAdᓾ,q.˺G~GHAR\o༥TMUG>Q2т  0|B9"א,f@D_Ϭ D$Q(usZyTxvM wO?Z?d&7mχmۺ.uwT5wUkU G #sƌDF@B^soMX4яiQWf$6R]{ Ncap͍=2>=..]A{{o?޳fy$!nnLL"5$Zj50L^)ĥj8Hxֈp˶˲e a160mMU?>S?jz)nlgGE*`NM! n2W({xKiU@jzNyN I@%\ ę4'M Q} yqo:xbYZ!0[[ YT30 "P7^~y{7Z8H5gUMm88kL-HyXlvwȰባ|Z SEo{[ eޯLm,{fp_J1 LY.џ~9Ժ]{N@-Q" NK bAb^bY9'L___9d.@fV9]}p7c_'A&h-s>(~݃ k-??ѹnkTYG24}<Ǿ &0HC D< 4&q ?~ikGe]%%M ܻ$Uj]Ẑ˺E~:x~]=#j .K@n{d:ar8}=#J𯙵*T1y}uMح<x5iTtx^  ttRsĺnfL|n I8#Ҁ(M*-zax)wSۺ"Q] NtKz| I 'ʖ>Fāffnz0=)r|&:vm]Ѥ~?ߎJHɂsFBy `mc.Ą=?\)֏H_t^̥k8Y -Hu[-0:mW] Zk/"QD<} k-]F,t9Ow8" T't<$3'mcw>GLT_+DTHDP!Q Hhf3!W,95=8鬚O+u97Pf:@]H,rBi)i|Z2>Z)"dq,oh8@9Fr\c\sggpe*gAD̐A UMXn4끈j^KBfܵ"yb4* arqm&#>L3ui I"h?ӷl+ Zk 8C3JGk Hw7jY| 0REibHYݏyM!Ĕ@x|z3ӘL#n}|33"~헷1A)#i<{q:lhsC_!Q)jϽ! *9vv4h`Jq:%NE|f0j'S ǹ'bgh;X& 3H{E!y>~aD$R H\!MpY;e+4r1uha2/T,#׷ObJ]rn 3s6A%9k ]m]y'l:R,?vAD"74C,9sHv0ѮoT+&/"8( )Eƛ3OQjL3i4yH^I\'i\LtüFhօ0ޛ xAE N}?zS8%LfѺHDf^d?˲oֺ;`eb`P^̺%<YOxMvN#r/K}!@Mws@t 0|nx>os%UNgIdOf{ϕkR b^pw'L+T F6jkCsOs ?o0!<5y4"B(jDCSɞ'D:Ĕ8ۆ8 [;sھUσDH cMA/g<:-IcHije#%.s.0[2zY,Kn m~߷u wq7JҲIZju*K8ތ/LhEsy`j@ZpZ%0kM[ϽuUB! [moB]Nj2tA|#&챇‰(J)ܛZJ4_x2 !2Z44f.;9Z4 ȋnDcQhb)%ɻ{OJvab&S`1 V56bI<D'6TAxD gf-G։X!,YmۤԏϑvPm0^]m6׋7^Ԩͥ K*GThL3@=m:FTE2DP)ULJYI8g!K˒+N F3#ļ,kK^$ bh".Ee])ERĭg{63 f/!s[눰\k#ύnLH"˲ZW)ʺKſ,Lzo7"5SE +#nD\jnpz=ю@Rҁ;p2_wkfM KaYkyVa݆g(a"Kj սֺ[W1ܼ!w83qx$GV Bf q<,9%)V05U;; {uPQț,mO!O4 Yܬ~۶@4i2UEse]~]1!^Ca/6YN,}xo7)Rmoꀈ34d9W3fRϦ7qLSSrag˞ڈ # tws圣>&aH6a>ȉ\n*|~~7;qU-`~!sD s4s00FLhE;!)"3kǁAr?<ʲd9`e]mJEx"`\̝ϡz)nykNBJOn u6B+z1<~4*, R}bNDYÅ՗>HR93=/9gت#bdC.)fcc) *" b즥H̲7?CUK=Q!"۶#A̡f5۶n[+BiYsϟ7 ۶Ex1FRDM-zWcI{zK]Zmɤ2d\鬒'=~x<#=?_}iCtd-"zQfAM{k#Z&2Aޏ־>>J®>C}R^x`@D71b1C~0wH>rx m@w"sk?ѺKNySm|⼐s1'{xLs%I,f?|n~ M_Xl˲މ|ea\\o{f^8CIAFI9nĈ x<6)C@,$Oa8ԥD&-s!"H@ڼ nq7q@.q|+x i8@8bpp"׿+/^ELi1@0aR,)رyK#݆59f&?8iى Uȅ@2"}^(f}Kpj.)$ vK1?TL,d<w~ [J#˕ x.éJMt)F2=)?K~Q3s2^yֵ9?-jRk`$u7G'`05Rg` #/uJC,)ThDfB7W,vi|>Lo݌{΢D41M{b̼Z=ʸ|SwbfJؙ)U;D# 1 zz@DFH)YLgBy[DԌhn?>Ȁ)AL0[~"A+A',=@Z|Zgn|뺖R2G;=fmkM4& h- ).9d[s8 %B0jQ U$o7ӌ * ?~\̚uBoUx<5NĀi?c>﷍d{>!;rwp+rFu630Xͤ\$dÒt¾{'p?89+/f{gkZp;Dc2I"l?kuF߿(f3WFO;݉d^8?Ys,|!t23i?#yM<5'b1!Q /3 /fF;w;=?1y$"5y1/U ,FO}3f&ctz]x`jǙ><0gR.œJa/xb~VرʛކݴG.bfg= BZH˜Z  7t]JS9LIQ sY1E8I_BHN>es7 R 15ib&"on~stH`ZdH13?{F哱pC^(#8q\,LÉ%Tz9cWr Fz?#"/S˪"e½YgJnf9@"+di,ځtox>Dm7L,?#= zL-" UP!Ɔ4ba/sDbp sz(i~auDm6iRnr2k"/yƌEͤqSD(qO: wnƒuđѴ|HRk0ljVpOcX K^@;f_ 2Z*S4zZѩn7܁8h:Zþn.B#hFh [i3E'f%l%m-EхōtugȨu ^&D/Qr+_@%io139Gx*}fk |xRRj/^\ z -(#gk:"lde]`t9+: XN*[LPQҳd|%Fv f&ZΔLnkr$Gv#2t#Q?}3@UfAxnʌpZ ZN3g 1ħe #G.XOqXm1OOU?wszX^)|f\B$C2q;w\L"  e-?`ZMZ½^J;|"zgG""ӏwfHOX|U[~ m}b.u1WUe|u!ֺGLYdϙn2D~Y/ESAhk)<ûGCh=nnTk1Od ϞރQ'9q̡+!Q\ S-eG5o9;D*Ke!̴2S/YA]#.\f>:gJBLegN$w{D^k1F:mjunU'' .W4ZgXgs`I{dIҘoM59iy BfH_# d'!BG|t, {T|y{[z}S5#c77b>>|0h)Zc3ERXz{d$XqRഌ}\R裏A\ef^kkk}ϟRJF^2g\D|ul}(KQwFJp1/bI|pkySeXo)3mKN(){$@1ѝOF0K')S޺5*BLh˺rvom/Urceޯ8+aDcYrهNlacf[8ϔ&[XX(\.8!Ii1~|"0!ӢZ Zk{_//ȼUwx<ҫRфg"$X=5"ј68Sa*c&ffFY{{} 1Mu99D.$j:D8Ej$-s/=!ݞ,e]r?@RO:΁=!gCKPDr}2rrws"aN2eٰM{_k!۷o!'iFĪŋLKaqԜ}{w&Z;R?3xC/ohMOvv9hI1T5 ̧Scdf:WUR^j I8|'Rr-K]Ⱦf*"Eͬ֒[պX`:+ǮsT?g xbK?NLIv*Gݴƴ\%"$4{RJ#,ezuxWXj^"x< )2K GDo= #ϹZLgY5;2:UdiP*rQ6YGyE0fӖ!@2\!,~ ˲d,CS2n4*SJOc4v,ӣ8k:DdwK`BI~Uj<Ǿf86<#qȽI),>9b~'fb)%"+fjIȩ~CcNxKUi<e#?i=Wrbŝ7YrБ8:df59⚫"1>ݜ!g{ tBTY!s,OT?aȗee]ü䨵>X˗/Cmk=FQYAED@Ǐ?ߗu^˹МPdOx\T?83ҏ=SSġD9qٌ,r1>cށGvYe]ׅ/޺eݎ|C) z?FbE-,1 ge}lѴS?X"4‹Vx Rׯ_[1?I,us# 9ܧ\H)zF3PU!0J˒_h#Qڶ̌7nmK)Va1pC{bXeoOwlc LԂLI=E K]s2m̔n5BM@*'SDjUM{ڑЌ0:\" rN/Ȳ\ư}opY%rfsyvtS֧w,G;r3iʌm3o5L3ka04ֺoj8}-ZKQS0UUhgfZRTR.y42g0")8XQ ZRf}]יj,?k6-`q𴳑)>T(dČIhVdaySK%>$6)J)>FRB#RY&W=__jڥ}[L+1q ҭ&x325%SK-4W8FoY 24mF1eRȇth=1FB!D0WPe6QsJe#:nfT֥Hm}N9#8k>H:{)\G"LZT@du]}FLDXHu?~o_EGU`C譍12v0$<ԗ׷4.K}]֫}#Sc1?g% ~ގ(?=A"Z058OtZELi1-ֵ:Zx1]/;BҶ"EuYB̪TrK/o/BZ#RMz{͋Hu]3/eA 7n{cNVbKQSU 3[rI?CSzyT{0ӶfwsrmrI5%_6TK,5M9T4)o"E a#qh}{mvqSa\HYVо7˺zɶǶ-=MC|c_LLF Rv3}0) {VHު8Ψt0u: ̑1Fs+w8sv|F9jnay4OqS"̷އZm?OIA7`Pk)|o@,̹ >rF@˺f15@+&=NP2T'f$D$F2"!Hi9E na>QK%Ditp/H 9A@*"f۷u5c߷p7Pְ1TC-AaGH3  L}D8!"~]p߷m ef Jl ̀/P2j)T: 11~&d/-ϩ++I{(yBy==%U X70>t^ğN#/&)lL:BԤf!R~?4ԉu]Z ,x#uYlw怰a,9"GZKa29&^6̥tY̐#Lkoo/xla*8X 6aHq{dw&,I7c.()SƵ8D,uzS @8p(M5 sImwcFkk,1.k57u::#ex=XKaơvw74ަ!\QZ'?WiWCZJ}NbDz$m^J͋nnLCu]vhYK]=3NdFz-j}oޛ[](C|h>(EpND۶O!"H:ef`C^GdZ:τl}.k]j)Rr\\].k҄i-KEo#2ԡ) bR@ƃIK$]-B݇^j^*0o{7U2FoK]X{R8هF@G#"DRݽ3>< nn ?O]knD K۶z?O42]<~{~|:ApNiܧQ'=%I'af,˥ֺ۾EJe9A2gpSfEiFMs cH,U"sn@3spC(3/K]q>Ӟwx) adl,@"S$[H~7/{r2ǡO8qw {juݮDs9)<]̙h13 PEP0`b C7a`Nefhf0}oC;Pg9e*T ,K^~}E}#uCz5ǎ3ZUUGDSVc<y "Hg=ĔZ%pYJ)>j/e)RF}47""[)&!*c RZo=' ?v3K)Hn{wC 1=Rg,|h r\3P"^#<Қ"R!߈E n:F3utv~<"ܢ}kȌ9B,"o NV&k %q|}{q0}de@Ro۶6(D3uT-DD$.Jg`\W&\-G91 UB::nc(L\R2wO[DLJA3Tdsb{Z r}lZS ڰ@әn(eס# 12s Ex\Dxo{x4~ Dn˾77{}}=_uxxb<̓Hشiĕs{Fgb]LMeYXdc"LE( 'pEsL-I*eY/g$fβTe,ZSnfXm* /"3Ve F'#W>B{?u:Ifl{.˄x|A̚?"pK*3^w$N3wj>u{#fb1"tfj3x,|<۶ZYL-$|H-un, 3^EJ/2u?*<R$ 2b~\PiO<_g|<ݩRj6uwcu?=3W >(>7̪Z,|0:*nw W&"Z*n7"{F 3SnAL˂Euom6?FiCGA)X j])eDS3t&"5E ,`-"0{Or'DJir .[29IeL !2RJLnZkUo$ăL6Ǚ csRHcY!f{%&*C5%Eʲ&B6ғ(D"%?ź$t͙b@d|n)nFbK˺Qd2T ,OX6LbQ4) 1":u6(p1 xp2iG'"mƝ5{JjZ?Yٳ xo^JRQUTǤn)%keM5HH|PYj:~#+SRH$0:D ca W'0<ǰa\w7ĉ#<-y64Xcw),K涵BE?~zdNXĮ' 3$D8ذD ҡn~̤G")%!&hNHMGڄM}en0qҦ6'Ýk#&O30)2S>E䈇E+'aޟfcwlVWDM aaIL&.ubaB.Hu]2Cz0k۷/omxx9ʷ+挖V"DG`j?xS(Rم7GH{ku%ЌpEfADf?dGxL"HR@ Zf(BDs$F ^.TJb:75'3ggQ2,rn9b&Rjضu]mEnMNDM3{;W6]ɵ.N3g8˺+1 lYRf˲ؔE_Gw`Z*>n{X /LLT7 m*Q׷/r4겤)0.UPS=YhD'? z ʦ){8ԇqw.ض0)̒I_.N}.!"J<@pB30ˬdCA9yͿJ O#6B.hE, 1T#kq@!f}T].23 JFiH(,8 i#Ltn6R.Y5Ǿ c|z^s{(v#t5"2S[?_?"'Q, q&/葾ܓ. h-̲T]!i4ųgnG6￯%]).V33o}ah[~j"a2- |x yd'wiec'p2dK`8L# N$,R6 L0lYYuP6a"7BpfmlJte ik:""E j]fbM "lnn,on33'HA3#8DQOL.G6Ƹn뺨`e]Wmgr P538snƄH>Ƙ2c=&H4>f 4ܴ0ǣ@vYmGwDDϨii>w RszY/G"U(LMa{]()벚/BJ[5Q&3f BYZR(T ay빜f^_E "2r 5c(%"r3D3υzغ9NҼl8 $* ܈ʧ`~nCۇTaĮ QETMm^nBOf,KX$JD[eMͲRR'ihr},DJmQoՍUc{$NV3K-fni\؇DDk-˲`noZJylKhm;`1콵>(!>:Z R&EHW}!Ŀ|}>fIeZ+8 x$K(iݦh)6;ƫ%Zc8gFY#x75BBvD"Pst7?(lh]}f@ ֟+#%~2hÌ w 3A<4 HI|Tb]iP=Kp{ۜC2F`m #vUZ4d1,9erv 3G@PT,dRVgǬ%(;mf(K2kq[4qnnj!,BHK.uVvr꺖ZA H5f .Um<w=Z36D8,iysC+d a#f۾B۾.ٜ`a:Zj)G^dO<"b4ΑSX>c&T4"*.r,+H9oMVji?8P@a x۶ML)*:2#!,뢪˲[R29.Kۛԟ3 Rm sjwG8BwD?K)Ej)% {LK<@rCbbD ! ȄdB1/jf{OzPje1FI}^+i!0c-GP_ $-21,s1ȹ#l$HTdSաɪ]f-ߎ,+Ǟo' }aؒ3Ԣ:ܼTe!u1YOڱDD[ԳϬw d:z"[m_岮?o{RWsl{Jru6TPW)2K`ibz  iR>e1z}Dd>Ro[]SG gQ)LDTE:䴊 5μmLsE >=#4k;kn>"o_R6Nf鶝#ƍe@s m?_.'ח.l}oNbG'.岆[zԺ >0>fZy:N@k˲쭵}@;i^7CD0^n׺{̞G n.p0>\ 0Ȗi94R11;xz$Km%>,.tkԪC 㘄§^~nqL s$ :%5y0>TٛWPf}(9Q= }B2M(U ٔЎaòpscE6sp s'U]֦"PMU3dC[$õ7 T aDP@{z&IcKO73X2P(>Q1d5<HWWeErwHa#_J,{۳dޘL>Pzx<0DN܎6xΈ(ߊ4F$BJ! ;RDD2>B]zO94y͏^HV_ =/@G_nZ-K4ڟU9yUGNA@ΐRJP,:-g~3΄2ׂq93p!:}*?~NM#pnS Y <^#~ < 4CfbQE\К]9|L:ϡHzՇ%t 82xa2Ŝ L2nDV"FDRr~B?6~Zkǘ#c:4 {j>Ln$r0iPKBL.Mu$2>'3> 8oLΝӲ3y@ud:oLv{V Risbt9((8p t8(Ҙꁌ#ov@'1dߛ2jN\8Sƀ,5,۶!@sF8C-'Ignu~'`H0V(=>75( zhgqWx |JdLJ)bϴY M)jd|UE k-lFRRʿ>p7T!l5Xkキ~-Sdu_nraqMaܜYy2H=_ a|_׵>}4B?~1~|ON 6s69O:;%% ČyOy[{($'$^H s^Jg^="ë3s+\R,"c5!b<>Vl5%r\{aw37yh;32s1,Z32 !ғ,+"P5`#`'^.3ӈP$Bc\/e"L/ Dx{Sw"Ɋ=Pg6~ z}n0너BH齩vׁ*x|<*=N펗  L^{M{ pӖ"O:JdCșD-/v$^϶HK߿\Fo۶>aA`"LEl)͝HL[~_/GchL/a\5@uRM;7:8'-\;SކS2`Cچt3H?5&QeX0+Zr3Fg fγ"u0Cnۤ4ץz,K ܹnATәGZIF̷K5U$H1{S-v3DYZ[sL<_5F6gt"}y½3qEb<3aJ0^}~{[S 8,wg~_צXf\`͹ψGq3s\9L eqJB)0 ѐWä`tlr'y{$D4 w9rR$E0s#Xe]A/_r؈'8oA."B\.0O8Zp!Hr*,ӓS"3w+fǭEq^NZy^ݞKe]Ǻ,˺4]/")RkYmXP^q~stHqP@r׷퍙ltpM{*g;-B%j@ZGD@2|܏M:F "цWљ{*Aē$Wv0cf0S|AZ+R1UJX/ ]94?L@y9Dz#Z'Zܷ!11׸D*Y8ZGBWG~rtBSh*"k8+|89gzi?V)sb$-m,X8 U~2|fq+Y.۶E 䤘4d]E Rkk( 79(Ȁ\HsvE홡=ͺD@DgĄqdBK4CcYʹEZz۶i(G޷L)aG4+%dH 1_&"*0za HYKkM*gg''̄wsW)*: Y'G$j@t}>[4܃HKps͵&@`K-L߿}~}f_Px.ǠϹ}q9!LWޮhݘEDhbV.i۾"3f~s@5 x_8]%}@KD_d|$R.s$(̓= U4s+W{?[o: 輳} <3"vպ<SC[hSU%'5RNrP1,"cKfe7<nA%hag)IʁVld~[k=RV~+F:GuY2 '`yCYֈ0G)Qf7$Hw#3 .C%_,Kc`JTa]EB0%48/#B}>3q&z S'?C&=8pxg~륏&/3CtufCm_ndb]1O "u<.k- S&whzacD\"!!!!=b"$`Ȁ''JBJ_L{D9 @0.Elf{xz]!xs~Fi 1LYf<S]j)ϖWrM/Dx~˩;~z1W-ɧ(:vPfQ Cw~^U!!(S8ç_h-c[pn`@$8q६wU/Y'd·1p{-f6z˚,$&0Uya(1z,,LH ť\{=GH;l[ɾ] nk{c.5w"T{t͸js#–eL;DRZfN\ZDpN4^(_Q3%& 2e]zk\ &,RFkC%dY eYJe3۞+t8lЎ|>V+ǰZ3L&f<Ul0OqNei˰L/߿}׿Oc u|RmPI9dZkfYN6҄f֚QfHLMNFMFd ² mNpPyٵiIѤ!2n 3eT'mKaw뒥@-Wc?Z.sSean$1ԓvb1̽ZTnzkacxwMm$ @0(Β )wiEQmX8 ̀#EA- uuHDH4E#^EFo:z,iB aF`HQp䎳4NH3xq25K㐟̨9= 3 rTYzcyq=58Lrc|?oeew04A sGt9G s|%Y :L"U1$-an%̆*O;TBI"G10y G Ue4u1\JFtG.pMXD HykV.umK-c ˉT"*zvj-3Kzaǃ ˺ޑ<2!*#8)&sH,5q锥ik[- BRk\XeѺ"qj2% kcV)A8qԧ871; @3&1, T}]kF@"f{}aj߾,ECRT"I+ ߞ' UEZKkp xakǷl9L-1>2GSz\Q7~p+}EUo>F_/;}+LM0[dz]eYZ~S'Z_%Qɗ:9\j=3i\!v1~1zS-bYZ1U;P6SӓːM> #3#5) FD* X2'%LlfJ߄Z83l~ >eYJ)~= ~;":~^Dv'| L,oOBlcp. JY͖}:ê]fxNq:S͍i |S8 jHne?1ޯzLm߇6wK]X$oۭ"Ƕ53AXmVk vD@V&?~L.M}ǺKREfy:/6ȌsCĵsf{yWj-˺RZkSWAHI~Zoa=y1ܙz=O(Bz8IEJ-L]"[Kh=oo-Q3͈ H ݥrWt  ޠ.ࡵ,) f"꽥yp.彰_Pk5OZ)ZcD8'~l;*#oLhD3XJ1C7L@x&125 n&q؛*aA 4Ox{:LhCjUBkI9哹2[3eYH&(vFx Ω $&R>ZCDv"N/׊Xj^/zS\ĝ=`Q. ho[RRο#KAUx@[M)A"dZXv5< EJ&]KZ+gobS̆{ٔ"’<0ӈp$daW=`G44-BMmR=9GPJCJED C>s'"#%)5Gړ#k!LXDZRkZUMGY+}X&Fou}{{/en利֥{%y 3:/%{T7#H-K\֏~~YEǸo37_lf5U[c4u.̐XJm] ^L@럿HH%Ⅵx>&Bއ:Tq..[zYꍙ1\Kmn,KY[k˺\KkKwSe.1}B%L$|=8x>W) IލX:X1jDs|HU/dؗ]={ff8ԟb,=ȜAoT0UTͰ[J|p&J3@"#!1#o֞G $=nv+Em?L~NŁqTLu#)\e&ՙLO 3%qvY6]# uK=")UP(RH+3,2XRY8R\$G:;y?ۖP"g)v#Y2Cvjαj]|JᾷN)""A:YiGCov1ϡ%cJ&53]*R*&}{>s-,K.os- e]. Bl-.녎\aǣ s3a*L t/˪m[/œvKxd7Uc${:ґ벬Ke0昐Hwa}rf`띠dDC5ŠpμhUx)tpBP s@M -Fw01(5p)AfU#2T߮D[r1OcZHrdrʑQ[O8Ks.Qd zceu [ K)2z)y޺9ݮWfʶIncu]W@Gȱ~)e! B#!}ZS,ue{tc?ySOhqRHt42rDJAܽMS{&7HbFMM)B}p|ֲ R4`]eѻ2m{pLhl'd*|FD,f&\"k XzYmge]pY>d"p Rm{>IeZBco}dƸ֞F˗wBrwչ(?FZ2$HjxCPףԚua|"*GAP}eY)߿8lnTӬa7~DA- Z/QZÅDf(J v+R/֡%%4{7h9D~J4aU͟ -Ty$^! !P2:,̃3,]Z!^S1 v^.kk[ocaiAWe}{G%1ռ{HvU J-Wtme]ٷrMSsfÿzjj a]u$*5e~}vwgG""PK5s{,"RH%'AD '822d brٷA @D r35o߿7""!@HR^2ӅaYE,afg0ңjzoer>LζXj]EThh?D~pKRe+K]G@zƶCj̱ d ˲ow F+Ŝo&,Z ffC[ zB*K^|[.Z@5T0#n:al RJ=8Fnԩ0^?{xꦭ zOґ]Iԡ)#$<ͭÉj=,M䎾Z1#R,׾s1 cH0m#|)e]jz8b@ &!+"_/k"4Zpj1r7ԛÊ1zr~|譖ncC0 ;H|¿YցY5E Oi!ʕT-u۳&ĽG/ThM'B* f EXk2 @m̏9  $" QELz%sSMV1cf_/D,Kavوy^5+.$4)٘&EHҷYz)x#Zk恄aOw}X段& S,63wc9 &f~lp~eKd9J{ZK@Sú~vQ7N:3#Щ;x m߯<@;)  &IRʲEBf9"R},'Luj)vf4ZwXj[Os5ǑPG4MSZ7XtkٜġLYnĄ".u]k~p?~1)EI0ZD`fɠn92 D,VU'3;{z(i>;{CێFpYbv/G{・DJ&K RmYP !Zm&(h[yUm8;1 3hۍ T;@8VpB@Q5y ֵT 1\lR.5 D)z\9?`^HlafB$$d踟o0aqjcfaKJ)"$\N<1'T3#o.R>φ|:<5'h1 n#"K-v&D&tr^{oRt>2'Te11Fꝳ|n{W6g:{Rڿ~Cu 9@xRʟ@ qDZ1 "f^Gh-ߛYop/^/"c<ga֡^kZe q]۷oR >$FHeC$|k.,\e lۖ̚\/n !;{)RD S"m{{<"Rʲ,f !Q^$轧I$%'G{^DʇQy`*Lqf^ke]΄mށsȑ]p䑇;].*\Y05s!ohE) 5d03qRg-䀤eoc,OCk:_1.u.NDuYm@4&zd`KB %uk??>vs3D4UMLׯ||0Q-{/U#My* @BWȥTk3R={ke]zT-*fLB"r>>m?j˲J8Yބu075j3}y3wÈJL9 Ǔx"@Ldg I5)Jy#">P5]&3  󾎜Q]j͒LMGuYQ OR㌜Ce|&-CB?=!SL`Bg؏)sv]ǏA@f)]q.! #: ^f%xb<#bhvdZW)ny(ZJ4yCHvY:G\. 1>r=:Uf}0Ǿ嚿?"Z=Nرjc (ǰ>r],?[]p aRXGR "sN-ϭ1t!"чRJ)"eP,u Ri]Rh^Zeutq]Z ZסL">9xG8ra&D$tux=n."tRwӥ"#1B$ Y9A@neY>@T6TpAGI<)=?:G߮KHQ\.KknoX"awLơb_o?g+L!"D"&\)D6pxZԚeO9syir,LBD0"ŒüQRtψ#0w @0Y'yu,R !.3uRʾmp3{>~T/!,,ntޱL"#`Y۾ !fOH'?O1'V{Z"C13KJ_Cg5cjYJؑR: eLŲ,)idabBBv̇Z˦e1l]&\"$J-0Z:RjϳG2?,CrsFZFRsK%]1]&|{sAs`3Ī[Oó7JDc]V3}\1zvaA0R$:4}ww`R_LBUx]/p0, Zhz, 1 Dp>|LsƒrBB,"r1}>RS>=Sh۶euE`9Qk@Ի |Ͻ@o_zJ;wSgpE2UQֺ.뺺zYm}IYӑ3Fg?۲eYt; = JYKgJh䰝YUudDf]/ܶYL}hLcpB#: ̩c@)eoLTx|B @fӑ9+*[3ֈID2c1Fr5HH9yxT@\"e߷Res>v)R.kUއ)pqH4Ev}{m:{OлMgIZkˆ >%2"<GPJ Bm\W"7c$ ƜOY̩s!LfH{ "m)Ku,S0&4Os˽6!17[Gnm@oUY$΅ʯ" f{g`^ Iey.c9o&$Bxyyn݆8#{IǾ-k=okJoO"ls#aP#2D%chZJjG;8 ]urdž3#)tՖjN}>tt|>OM~SC;dZ?vm̥ݷsNL?~׿9(j&DR}E3~GֺֺGceY!Lc\RV)EhIɩ֥"ڐq3!D4Gӵd9aA2-s_V/~nq4d#kʥoto#j):->S&JuC:4 1)|{2A R&GÙbD۶[t)$$dNIEPffV23$®~&Bvk;#.ZQz눮2^^%g@ >_ș0g$NfJH9DT*1'bTS:D2됈7D[,kL8}͏]Dssh)1OgtygN%e}&%tӸF$Zbb$ x o+ZkTj!>)\zϫ='Vr>~:  @)RZ# 2<}hƧ༸[˲HEME"Č(6ٓha As\sܡ#|s̿{PI_^8}>[kH!Te~$ }Rs]9'"1 ̄GknVkeD$뺎>ZfRn`"= L4$(1J0As <R8xV5!lV;\"0Ӵ2L"qQ祺yK-%xyy|>s1*nDHnLe1 !)P&| 3KL`Hl3$kS-KPX>zJ|汐#C2"':ڑ>i ܂Hf殽m OLME3R[3~_׵~>qLQ%˜̐(L <ֽ^Kxo{Nlch12L* 63]e̬2p&#"G W02/2L9@Ĭj|eGǜ0@) 2WtfQ5lCp`/; i/0M'׏`!D'tU<wAhœ9yDER r HsᔢOz֚4}F>ӛ#!$ gNZwpZ1$'2q4)Uq]WS)52.TJ`f u%2IÎ~_l1Z+9 !B*3ge˫i?ޛ˲"蝉)e:x\P%7U>Gl'!ΰ a"DBq3sY.RO՗Oόw5+)qJ")R59y3<2o%&l wJ).@n5gr+LMZB5=?!$54"de1`.ю㳖Lzo ]Edc<۱m뷠F_N$OE [#1z0i I?m?mY֟c0pωSJ6z> Lz̴oϠokq:{`0#I7yH2ǚ8sk=:Zhphoa3{>Hl 2;?g ms*Z1zyUT 0%WќxkHB[KrO?@+]Ft| ΅#*`&`iܴ Q3D9Xk0#-z>wd3mG*-y? u]9HԜ1t#fF8Ȼ~t82;uRjl1{H|+6g{Ju5UB&&b#x)V1DLљ3u 57CBL.Ɯ-RcRr4&NCThԐC,FU::!8.IRvnDLz?r`3Bl?J'D=8q :7VTDJzm]ܶ:\dL4"Pq^yc1)(򄚄3GF0CD!9wv(&F!cL)Bsi2V5)T%:%hfS3R> AtķCT lx^S}q'qۏ?>zo`FʅPv]JIAjt1s[Q&1rJF\Ch' BE,.uiPON<;.VR&ž8z6;O~w7ZGJ֗mo?^ۡ+p2 ;@([`dw|۱mh!S6u,Hj!_^DgD,Q#_x>g:3RluX%*"{q U4Sv SY]H2OL8YU(A 'DJDddKٺ>N̲d DTܷK)ϰHLG =pH6%>z$mYe0Z&rIڑX3} PMʁBH.cqd>c&NlneY"dQkyy_d,{KLdZkmۺ<:8%1)Xe'=qHS)* i&K"#AX5s~""s,:ocs/RhcGXj]g46!^HH8m6Ue"D/%;q sל(Pfx'pDC$nooT%\R"ʉD33ey{{5hO>Ld&^K~q}?UiSp&R#G1wG8$V"Yl"s-+cӠxepdNn\}]^_~ƚ9SCs5ޥZGb/ c8 I8͙433UZ7)gCb0\rt2E}vfʝEu qXP8c3hIl.{ ^L(s!θ3,HLv;/cBTHQ¨a_FꓕzauҘE8sf CEt 0L[ USDMǠS*9@Qr.7;Z?tЯho`»7#crOY LO 1ۦ T_dzZk-9}ۂ6M3S{tUŇRN)R\ѝ;jlͰHP%@ѡ"x{][2(1a7As>KcȫbUw' NׄA6vt_KĔM_w"jN!Gev{~ރl2ђ&?xסn) $SʳF ZHfgPlҘA58WVk=6]O 4s=03*Tin9>ܭ61]V~nwW{!>!IFt3͉sXY_+DȖZ2keY5\)HM:%ҜǑRum$s1Hr " $֎//ַȥj]8"FšxYKpsGCSJLlnqpG08HTG;vߎYry}gœ51G?S]TRN=Ѿc׍?R5$p[3RcL E3!?^R^?}}1j~/RJُԗf 6L!3XB͓sD] XzTu]{8KηR %&@ QٲH"*EEMs8rNLDmoA8}'|NlG (jƦ?>?JsH0뽗&F=mjGk9$CY~M)zω2m\nRPm@pĴGZ6C<8-G;Sa1D s^ LS"j&ap)˲2Ʀ\ @,ψ`,J_/CuvLf8W;fjuehƦ{"`Sfb._`nD!Q:;dW:l\DXHQ`dNk轙" |6kk &!$9--4qel.ڍZd{R2')~عfN Du]oC>beLuYFOXt}]5d@6$H8חO7j(YDՌ\r]˲%ȨCh)eDL"V3ٌL ynooOaȬ(4.'!.~=У29QZb-\6ڐe- !")%WQI$*VZ9,۱@א[XR4v[ېgm8Cҥ\q<^j)}v1m} Lm73Q%"]T hoC yȺ.gx"!Krp [o= I"31H{"#ltdQ;1Tf6DnD,%3gέHeaB`ʱ#ض\Re)}eَTT'T!.rJ86iYy,p\Amh QrRޙ9%e6ǍJ2ks0T**5 }gBH)se-P\9D0}88\xf˒;S=j# BLb A+x?`vD3gH&Y" U bUz<(yѮd dHVlB[TFĐS؏3Ϯy92 q-""۶qRRk]|u]FオR1A-\rV՜q8c-xyM#\! pp /)3LDsxtF9$Bf \{Rƾos@m{{-9a$)RF2'3(EhfKZW'w|&[]D@DrO۶sșZ뮖rٷCr'em |ƌ_oNhqwri~ttwH .-N|K6-saf MDZof8#D\D;əBu&l !8sgG >t '݃tn?8q`n``~ t15&!˲l*"XJA1:N+C,nV'i8PK0%"w$s&Q 3M_8KG N@{.yj4vk_M2٬\A_A39'*`mœ _qk}^u0Q˙|Ok)IϚ0{穻2&){G8plk9EyVs"RJqiJH$$!Z{WY@ `/K;A>wu]omOAg5\0_A 'dfųO@PBpT.H@Z3Wpmdi&!\rK%_ۙ+&0D/֔.6pRZ =T nKYo~CsNaz`fئEmI/3Gg.9G "jbQ.i")1KQgk5%t۶VS܍^wDK-|߷ Y|A~jRu}>YVHGW>b;\r'xk-(v[1"\߉)~G3Ra:i'0h;Zkͬwtfr5z9ox$zġVaG07ID3!' AZ #wc6RNOOeLC. lm%/uy2^lF3Ĵ,K\DL1r2u]4\5gbY ET_'UCB '@1DL9m.skI4#mM}>*→s{3k9}o9~XhKɑ "vvQOia#!*̔Cf6g?ɜJ<-:G#}Ǵ8u:QI ,ySM;=#C"q3e-w7gy@}xZs&f3xF/79V$ m#2ېDAGtG@ ;šE蜲 ĉsffZ@ԔAWPл(D n"?iXWW6U~V3bhn.F] !_WY!1HT13kءʜ| Gie&fWubP2uęTG3@ۿHJx4^ub兀2#诉S3&Dᘆ]6yK3N__OP_t0S@&~ۤRAwB=(dD0ʬLZnEFx. (it bdNV8QM<LG- cxkhCň|vc콁[)3o뺮p?F>k)&NpǺ,???Ye.( FλE8fG& ZDj QsN9XVa,6)3/8"h*9?Zm1Du5́_#BG ~=wo H~}o)@J,ȥ2'SuLDj`?"!u9 .>WfO>4zGRڷJ)2 *R [o[B: N-qBa:"8=C6Dk- NLĜsHJj k)0_~sڶbv[ZKwu]???9%ZSQnj17Q*{+LKȷ6*!!]]_$U}PєHD ZAǝH9=^^1:>95v F-Bbq )ڔUƈ D=1"ct#V:=$cC,Dʈ'CtnlfșKNC$0st%۾X~aFwL~3Ȑ&BTJ67R"|ͪ@\%2֥ F)b%;5!hLDj937 Ds+u팥bD3J ]p")'seM}Emåt+^}.6-sJ`Itnȉ*HT OtA`|yr!&-%'%1ec#3rbBctc}Fo ~`_W8m _ʳ!^`͓431rWcP5Nn">mR/O/prdIc8Ч<(FTgi (A%"P,s $00VI@Wlkم>_*eFhb-KgqrѲVf~c0b?W 2BjK^ENmV)(Su*0*R#G[̡~]2HT Nu[\k#4)%w"48y)+Ay91W)R ZN̕ѻsZjI!~")9fs",ǧP騛C܌8 3kexBDcD֓_R_[D_^_])&jDS`<0rB~ ̍RP~(/5$Di 6Lz^`Ĕ\"DQ1FkfOixs.)bLvJEctӔ2%VS9B@lRB(9Ȭc]޺ȘD LSqu).QqUL\J[e!>z"wa&ӈ*2AĒn2nGJL/E}9%۞rNc1zs.R6kɌ\|jO)8琣~ϙ;j^u|~~$B@v(tYDaen2hf)ZorM$FD 2}+'8!\)$3km8Q6\&xg: όTȰ5i'ʿjZ::1?l^dc%w 3NZxyѻ#'쩵!0tp%61T8z`ɐ̜Z̔K (;K[T5vȜKTz3ך! 5nixEďmzR@Sʐ|H=ԠqBsdYEiamhvǐ82r?ό*uu{?gb1 a=g4,x,(B~nn.DbwP80)wW_ w+% (EՕwt 1~Mȝs"m11fHHnnz[{oǎVQ?{)UcN)U3 :,Qm)9󏷷۳ww}j1zBo2K}_ooo47rNc#5RV>8ؾpF-9G73urι~8紀C$Ŷ8eĴ,KNLj.19cDw#>ZJ),qy}?eZjZl] QE">ൖe)u[{{}?jQKٞnh6uNO 9C^HbafoooD$jL)!y}X*1b;D, OC̙0u29;*A$)yS{!TZZK?PE}0p7L5as)5dGNS/.ꓙ]r"x)9%@>FΩ"2!9@1}V5&.~z}?SdMnkkG ĠN3ZN@QGsUq3UeRl0v PQ.E;u*fJt/`DD(RTM/}S=i6Lp>_e+~W}%I3  P:w(>Ud$u-_U=+\;~UG5kxvm8%fw%g~9`6 ~QG!XL?ߏ}~uCb1w\WR(a$j 3#= P#I"z=|gn|xma pw,2뫩}J~~ l-v3LX>L@B3 0Wsŷ"0q_rʵ4%2(Bf2Iݦ,HՎEЦ`f sZ%u]| %@㘙6HwDD)s,*m,>f鼐D܇~-q=d}X4#&C%5ư!y/1r O9, "[kjk\jkm#@F$H)}|GO+v1"o˲188' sWRmO1O)qح&!Lq)+n6!{s8~a>S)\Vh%DmY" #B,˥B *ǿ9)ٙ2[vj( Stq1zjYBغ"q#@D"4蠃r.H4QЧ7SMɁ} wE@p_lAsd@q`J-.ƜL'!:.eG20z"( "sjz&.<_|+5q4k͙_VpS7i*uYJ)L^ھͨhd#3OTCM.5o2 1|!fS pmqloR8LjHj"uY=E%p,q$FjW~~"+ dgGf%|M Nï[mvwӯ~2Rޝ%~q004#6r R/%|ZeEMN̦RoKeZ ]|!dNGO11wdPۏ0@3oG '6s -- '$dzAv6&)sBZk]ulAf:ODa |ko74W 5p"c.2ª7ُRLhau@/%ǔ(^U{DAB=`f$a4|U0 s@|:ZGawUKk"fvrO׈l PURVEMԘ$r>"2!2R\ R ĵ#s2ay8!D׏eJo)( -D)Sw1$0-ox}AޚC<Ϝ,%`&SR3NP=B|Yj9rۍ#ϟXJ9Zcbϐr)Cn1Gvf.:Rvn[DtSFwӞ%z&R+ pG稵=Ҡߟ ?O5SR$s@! m ŖL(j1"к%O\RDo3q@ACj˩H J߲B,3-Ċ* m}7)#H$}@JN`^MFq:͒H)Bu _Ό:Fq_f7:΂UE3}Nτ/]݇X!n`59ܗZsZR!L2JND BuKpb3.ǝzCT_Kg*͑1<@^!SՈh_ <_ )# YJ-uYTkڦ_)2hN2— ~uI8!%zC$L˺=~'Qkp__78x| ~iSyU&^+)>?ߺVx1_D $p@ 9D&=[KL`:gD$j*j\' s@ʹ[J̼ ^L807pEO3JVDgĄ1U Zvh-"KI} d9x;[ə5r3 q{{}Z mrFtdti#x ~)ֻ5I$ٙz3̪!)ݣzjɊpt\313ֈzz;J˵zE3u!<|Y@G֮VkefKh3Hea8f%[&ooۺ-xK&=}PLy!!"\ajfR$\D(sAXͬzDqÝE+GkI1Б<sfYyx~yyٶ?C1DjnH%gxnuKTECGu݊ L ֎~J)RD$W-֎L.ZkÉ=S^C8 #"2lxl}YW:T{ԥ4o/fiC khf~^}}~u-j\u>ߘCvaS@$=qL6;DSȅ, "%!l[Il}PIcxX 﨑˶#ݧ|Yd G>r"j __i6~DA{w&>E>(1[ɖea:Hf ;D ɀv2 MmKa@HpUw5d@o1@o~r {gȟZ\/&ٻd8Zuh)%\:#rPU{oKa怤fa@ @\8[ 2N0Eqt,7˵k@nmR#eb,͜:wc\fo{mJ0r&+ ֢TGܣcHx^Ńg4yrOB7rNΞ8Č{dP:~d Es3}FK0i;p%0Q@Yxa 8轗"`S1µ+D -C̑]M}Ox2KZ͋rܐ/M6R}n gRCNv3 !>HBb&;"f9V?7ߺ?~ F C xlt&_z i[*#EP6|u~#,,yt[q Y@/,Z7.R=m}Ě$*Y#:41Ӏ9S9Q4gBqz 0W63\1wwLgIS5mńZ%"{GZ03fyB+cd\m?V# ʣ&^"㏟?>?~熉UՎ˿[3#'F"8Fr"\FF} 7[ׅ)9חDZQ s&$2ZSpq<,EM a[W _i^.\@Pu!rdRKLT{bzoe-BB3/k]ԔP j]u16R2W̳|K9 pXJ^/"Ǒ8-2쥙 ',z r0,z; (Es @ݿn_myS9|||>4-L$Bs3kLg<="vW3u_jy} Ѻ<j@3Z&|HYC?ߨS@ D.j S$BumO0cD\~BUpя÷hR3>F~}yٶTcWaL3Yez;j-fnK)F9rCD`Qig}p/8I< k|fh%g(nC'=vDz.~TW~=UIw δWvsG FGӓp|'wz7.B)H8ֺ:zfs A0i^L0z߾q쩫Dl[ĂDyki߿?4EHyۻ{Q)u!ԥN\[LGtBf\F`bI㈻evpbZ譵0cAwI| PJ)ﻙ%g60~_GA`"!HE-l]@{&dR)٬hh}dN[a"1! ʺ HS^uF'vZ3s1,ۆ䟳?zg˲Y#Qj\jh8ZgH>wL2TJq\uPSD0${ݶ1&,׈DHDze{_u]}?ֺKkm(SFxFZDJgN3tKU)_}ePZ#9@@BUK6)eِh咦@*. "-jc^./MUojC}]/n_zyysaÐ}¥bDb9c,ff."լ1bvW]r}9d@Bdp[$ # ӥR$9v|އasDm%?G4}s Li p.ACwbzpeY Aog޾0=K;GGN4Y@%COsUz;۷ >}uSf|y"cZ-<6yR%Z33:4gxrY8f P[Vq@o`e~EJj-rR 3#gK$% .eϋZj}ٶZ蝉e᡺#XD`DRE{ީ0a 7RKS>I'gD|4oSuJxwEgR3] Lƌۋ>aHCƘSy<6g%n1xwɷ,çpW<qwm|`t``DD?3[P3qՎ,Ws ֶZ;fKx"쪋p*-PDt4\ 1qIK[R"XU{|2N=Yz L?:3!LG6L&bqGasth,uh1C9UɩG@˒pA jL½u7pD,љ qiAJ7.1t]/ԏ[& b:jgD'1./:G??Zˢcf?Qw<>2C$X3.FxXXslY#-mwfA"Nzb: @ @b:A}*X>uHSMl6LP}rn"A&(~K%L㷻RLe~MBFЄD/{-%lpZJgJlfT~WGDnZWf5>?^^]Uwfog8~LE-f:ļoaI`Rs'&}ߏc_ H˺2~8Yјŭղ˖Xs`a$c^bȊR\7ubbW%u]tDLI7d`p&z<S>M? avς;`C^e2v;"\H =4"g1 >Obdfa"9 OJ9> f, BP"zl!L#BEU}h)1|z.23Ȟ;18A1!f5pXBUz誩7D$B_ѲfU5w8!ag4qǹ¤4 Kd}c,oz43X!—m;XgS ;3(>&\}䋘8eVNLy=_r#t{<}z3czAܙy bic/¿q';0(\`Sg HjGliBu]uy\ֳ*%ʖތ, 2 v@Ҿ+=<+s}}!xW۾`)82Rdj1=}$N5fqrC9 0 tpfG0uִĿ?<@(uE߿4Tge<1UqU8wFۺRpeYaB؇* Ee̼. B9>~||[ EdI92aD99tp$19;"|cߏ!3>YwQ^0TO])RKAܞL{{@b;H+XH^/c{[:%YS[2@3/&hVm[ͽmCV7{tXxݴf-mR?Tk]n3/ ¶岮'Lf n/C8X ҵ5VrFoVK!.c(Z]n@w ZWsuqۉh]Wd d{c"7Df J6}Dx>ڈ8ZchBqHnr3Gf-y)Rh}2pB%=L)n[MnB#hS`=RFf'ۤV殔\6Z33"bOajSΛ;Tw0Z#AKBfsbSnv !B}ARJٿ~Z"ZN1LZPArp:M.<"O>we7&R2Q+_tjNX`9>>ut7ߝʼn'ZrRjV3Ù]lYTc*'1|id;M+-a8)FD g t}DGSr ~b^e fX-Ez}UշmfG,,F{̲=kZbfR5о8Z찱|WC/U': O9Κ#=1?̈xP.OZL-Ev̲%F{pus'$azvW΍ՍqF[uY5G?`zg=+@摵KfF R,[~1Ah[8ga|'rh OAC-DWSMJZS ̔/T!cڟm6siYNM*92쒉#,mk][;t(mr^h.EULJbZ]ߑ)/5@y -Be]18m+#R;e@͕RV^JDy1t{ Dq;6kzKBy,u =@T `W5!ip5[ Ǒg[a,Pf,1K 5/Qfo|rіrBW˞yN2s2 0=Hg-l(Lf'G I-Ksa? '6={Iu3> B!Z.>d9C[CM1λ,Q<(W^ֻi-ւf>z2“d!#SEL}sA< 39|#bf2\ K:"@\̐GS,kEd!ILzfU*_cXVHT B@ĴeLHhn/˺.RKa}`FGb&+c ̜BBB&oHYneoZ)u) 9Қ)n8Y[$S3("0sf΄OIC*,k=a';O?GMoMN{ AxևĶARk>P)bfzy}ߖZHw~y?jf.4%=n&hf,"jyf:TMSi8 'a!" DA=WJ!rt3Hp7fp݌13+s[']$KjD_QE "M#,1K4Vf}_̑PJB5@<< C 6Py$%dY6lyPbfm]Wc4)L8RScH(\uReEU#9[Y(*KqHar)"Ho "|~}AB{~̉2v=1vop[~̜v 0"1sS#)]]5XHaZWstf&2N۳21.h/k v@DH˲8U3\017S&LLLuZDthk] -5wWi<,r<;?!"JW>5gzm[ aCvtu,;˾p,3pf LYY>񷴺} 2znHG-#%Ǖ0 ǜ#oo)wiZEDkJ̥0A2)@p#„!ǡ:PJcM@#ju9}#"O4D*XCg͡"j ~cfbk).%'-6¢001L S'fݾ>?j)Fw1l!kAs:)˜0Ļ?g{RF2=ӯp>#ũq,LvA".eY_^6Fn@$~^hG[ja}R rv1r)=.;ڱ,бk"jr;{ s5h2#m#3=ZϢ|΀O+"K"WD,~Ram[o__~3@lMJ] _[kmۖ;*e!>X},B}xyy)¿~׌eQqh#q(К~", 1!(ƄL2;=;B[4i8fwV/"NphYxN0 1#ZÌ GySc17,r dn"q5fܩ:{©-XLM R{H\ ]uIkg3 bGb>Gr0ח3+R\5_{;6H)"_vFDRLdJz@Pm؈t~.֎\mY>CM۶kB(5%WJir4EJh}ʣ:0 {ubU 6'FzWs{'MzlMUgE8`'Q-iK-YLC 0^z#\z)꧙1C?n.@cjb-" % `}O;0].ҽ0Ʀ3N0[wBj!@,ZqeB~ϑ@D5xrI'?+tu~bb1yV B`TQr#ԝjg $L|Voq:nfK~ yvBG %hgT=,)\n!@LyN~F<\sjN}]D޶wPֲղҺ///3!ʌƒS1"K?ZڑBS}DZkݟm 䯙8a=" xz&"m=zVΜ鯯,˒XeGceQER#?Rea/,e.c )5TD}دߥFK!$/SȀ~B$ޟyV! aDTp-Er,k,lFa2ysZsYoRYOr-L?c,zg(e6}\=Z7Dz(!0)Hs.RX‰=ͅ[ Q]$3HJPAZ0SSIЇa%k5?51Mw?[xgi 2g4̳J4RF͌ό()@zLK-RD M㶭g«1auYPܒ-rYuw_"N7!$;Q'9BMsd!7uՌԮR$Si s 簚I10|0q-PL%Gg dZG|L)Y9}<8hK7]sD$-w3`{][w)c"Z$+"}":lR{6KY1߂b .T"4w&2S%0O;\*t֚_Ef,KU,ML$Kf}1&q2.}x Q:_sw#2 xaxJB<# F˄7["2Dn߅#_~A2설fG0KT-1SX&irvۉ9\5o ~H@ ˶D^2r9qg@'cY~tD岽]њBxsa6vVJle[/܈9AoK vۮzv47+EJ&ڶJY5}v>M]5ZJ1ƹt @YcFq/" \"XD:qDd<Ԙ0V~}yc>rӇBRI{ffc,Ku} @ow)@'UKn!F"qrϟ9en123W#լZObOh۾TNK=_X"]CÁ,u}Иiqޙm &wHQ.]_qψǫqOZ'MydIs3IJsWԃNR0S5ˌ$c<B CUGk1zes.;?m+3Gj0[ZLPc:LCL50.81fri SH\/xC4zJa*<'As(i $2@S{1#aVLZ0pdq.-/x_yңҕYm(tx"5IB hH'(ߠj( ,oPchS/ϧNCz"bOtmSY8#̜%=/Re1TeI+]>ci#m e@@.LI#Ax 3&s _|`W#}cZA!;wKS,]njT3b1->i]e7+Lvٶrb&&1RLOoKhf̷m!-Cs/"m^7H"_<ڮc1|?0~]j(`#Z8 ~c@@Bfՙ3A+QXirLn0FDaA'7S]3nf>x'x )?'#\g"D BT"Q*\Gom?Cu !e[?>~r#x#ח8v;[ϑ ra2nֺ\fYd&a)Ĥc Q>^F"v $[fDu]~8z{}%ϯCsda?^ew-T=͉@=.{F0R1Jغ'Mˊóp"hN]A$9MRJA@vm* ɟ#¥f:DJhގcY怄0먥b?n۶ޓERJ:l;'lGH K&d Cǭy|}~.[G-2D>S0ݯ/"\Rkm1t283  RU#ǻV PFGa W^1J!TI2#CU2[=r7B'Q>\gDAtcXjt5|ÈeGkH{fz!n\j-RSm' @އ;Z1X1oh!"BD n'P* sW;՜fK-B;aǻiFOVY$y{:K5<1X37st8S`kٟdx!HA֎ CUR*r +oZJ)Blu{ ȺTDTG=%%θ^wT5d2Kغ<-@jəM-i =d1Dlsnw88M<̳ ?pZG0`|V!X3,tޡWwۣO ~dij_Ryph>U3)⋸O|KeTq`N#4."?mЖ<<π3rI@qD3uhgt'ƩPUӖg kx>5߄z p^V7Ùo 7J)aKZh.q1 sZU"]јy*Rj]dmT~ {SbX nl0DI[pq"_ef\J-hx |[ {plξ{c]WPUd80Z!D*NaRJQ ~E<S~f= fS F|ZS i_HQ)$u3 pVi]tai)D8?~=Lũ!b*K^ DT>4nHZOUNjQ"EDhiWOU+uaC=y[zqHzT"bzUR9Y.L`:f&16QHH)O8zDijnp/3TD98!c=S)A@6eʉݼY/E"D<þ] m?>>3/\]c>er^[;k6SBL'ԒG( ݶ#G.M; YUVOZ^ӿL2pw;̅9(I7JFvmZ,VFTK)te^;ERxC_n7&L1sGv>v ?nu(04%*lG ;Q$̱hn~6yȸ*3?>>n.ϣ-ۖ ifj<.uJt( !R]9xv@81yFD?>~mZsz@RDĐ@ !Dov3mM&Zюpp"a`y #5ΓjS_>@/ n晟졔% ZK)ycHhGkt3ZT=P\ yu!rg7YqvdKIΙDU85OQHc("j:Z"xb\BĄ׳0޾n0 S bO[vy{\95ŵ?fCzi)Ze2'nk&s ևp$f"cZΥ['_4v|~9:MU~.5/;Uo̦/i>Wϼr:5^nv!&hn5&瓈khfOf6UXZk%!Mf:E=tz]16GFj{} 3ihb+1*;숏}oMu|k-","˺跷C ?Zܽphe"H/OR<@k=uL[C&g@UfBw&nz ,Yrp$7 tݴ&1I|<+!_V׵:zpgR{l:1FHq׼R!̈́Y"rq<8Ur1zϚ![Z:,O;NP0ᴯ" 1\I}WYi,n˝s y>:4hgT̻1!NsCgoZFM> /R½Fs{T- TlD~zcabGQ{cR$N͌ޏcg$b";@fAB@WwWF3CBC{*gH,X\d1tߏ0I64עE2nǾ3Rkbf)sQes9s}QZȈʂDOQ\90"x;5j*!T]🨅"f O44a((Y^I5gT2mLM$*ALR QQ@t}LR궭o338 ),Hp=elu[]k܍N~b,@=b@€ Mm6fR{ # bYn2F'PϏ.GB"?~vw55Dg̤9H5kD ~=ֳYD&e~ n9iL1S5I fۋS 8IcW0N\"}1tu3/KD䡥,RcݐdO88Ρ/ \^7;_cԕHg-?.Rvu 2R{z{;8쓚ZR3kb,r#fn,8TR[ Lu)gm,Q߈TY辭ZnHҎb"3j"[Kyn-V7!q2s|J2E* {H1,SN-?1uYAvjz$` 3 {Zwo=Fw3< ƿጝE4"=ֺ`EU47UUT3Z0,S:պ!gƥ=mXH|3dAXr}3E$J3l֒]sMt LPE*ϸ`⹐C'F41T5:QYoES }nP(S5ՙ02F&nח M5`?#"s`5}c<@:qY0S]Ja:"#4pΝ"v~ܼ[0NbKǶ@4tLG+F-%QB۶j)1zٶ>̂ 5LF ,Dj۶w9maRJ); "VM}.Rey>J*ER>*I(戼ϻ$Q:t/.oOK#QR f1 ]TϝtRe~* d}qmOh(|~~R+s}P >8ϯNw`̆"ߑKrmgIÌ.\RJqvH6,Ĥj\@N#eYM,Kq7p~ïF2zry=ExVhe2.脰ݷ۶m||!x\R\3R 5,__D$E91ِ翉e!"ֵ"R] }2 3IpLH%"4rP܀KzįߟLȜSDs!`rL6B:9l̜_c| ͸on['œjo޶81p܈Uu˘&s+"Pgbs) t"9^˯f&&5~:v|E5.1Q0XL9_sPhZJIq4!HJ'1.L5z#%= VHݙQ ٫ϔxtպK):!ReFjI"m Gn&cBl=q"<ϣ~j|dOt”*ԑ$x\̩iX9,N>~vɣNK )Gkw zYY/6!3x e]E"8mCBo*vwztg-B]U=Kx]8oi}Gsf!ķۍubDJ #/{|D?a4ȅ2 b^D2=m۞ϯ?>pSs`G,bjGkU 3$}"AcS4#8H0f촚[;mKy`s(UJ1޽}E8t" */&JΫg}lK1c?̔d/q 5۶wJz} ߩ3,;UܦgMIH풉 {I -̈́CY#%9RDf'M !R"`7s bsRN@8GeR&G'=]c]M{m]vW.vVۺsccy;J\5"=ADH`X9 6G*Lhzd$~$u1fv|ٺDdh6c BncxUK)Ex]w1'to?~||}!YolMD&nNr0u ym몦j= {pf@lۺx疳8ceXPu6*Ǐv׿mĶ9!"yDGM-t)c}bku Z"`h6)sa 'B_sn_H_Hp&wym̋+3\:rp.,fnf7-"ocY#vGyD؏#˪lhF<<߿~9gP!'wZ+jVJ]VB"UCv-TZ f@yT2vOeuus@ 40w&\E{oByUj>\pyc`@W }_t@3 RdoL܇0 Yeby 1kh!%5nb&!LJ{J6Y8t4c$%U5w+ѸĤleD2?Sqqvm]'8Y[:l:BZ3$@m%zWpO|Hs,p2 MT_M0ywle ܶەxqR@O-e- 1p+msI6Z3MY3<&# HUsce*5г:hrO:5z 0Kv9C]j3 >T1ejD)<"I,"D_lg,&RMU[ׂRHe]uY{c߿cw|-J,X>>ޑXGZtSx^jN"~4нL0ZZgBED"O[k~cN4SMPo- u5z@69}=gRގ}߅)UVKi1 ^K]oQ%DD$"i7~֣ФSL͆I;Ut>DD`lm 6oqyxEW-,u~"U~7PS_d37{<.Lhyg R gąKD DA2S+y sOׇ&Դc02I6Zc]?Wv+gٔ;jE2Wc 5@?~|}~B4ǩY& AEX@05,˺j,HUG1 /RXemq6E9/@D02|EyV2^҇#"s%Jb~EN^$֚Gbr&bb)"2.󤍘#eKݖ nN8LiI$}ܷ~7Ua64D\1c1= j~>E:zb i]vw53'$so[xQ e>GZ_vuٻ?˲d& 1Lխ緬CuLҐ gfi9G bGxSԝ=l88]=SE(k,u[uYh0@ M.Yg#Zw H SnUBc{s">45}&|=e1jm0c[)B˲nk;g)Z ,*R"v6u%&w7][g{뙶VWُ Aqvs1Bdzb^te!9Q7YKw:we3"-.L%Xo|i|UiZs 9~tPebmT LB۶c?=!޺0H1sazrRmmNNZk5Rw/"ٶh} p0]!9Rn:("f>lGf>OP5=)lhȎ.e ϾD$̹wAjjN<BP&LLD,y!q6sN=:TaWev!q3 !f8G8{B@(1ZÎFv!9g) U"V{^$)Yh6&B9]CDWKѤ5oP8V9֙XfA> ` G|mhUvf-KHy@\T {ddco*sݞLr%pC77Q1oVC'Bb "@)eLwo]SyP. "S6cEwFq"MMsW:xFܶ[L}*8-+1G1@$ȭ,cb Yd^DL#ֵJ)&F,/)b:L[-5JrL^wLDf|>݃3omA*!S}x81CZ~9, @ts1MUf EbRm]e"l `@`SE6 \cEi+Biv.u1lGźZ瞫I?EqS7ݥ׼d  g"O2N.D2s#ly ˜qPrC \4Jn5OY1>9?c[vʹY̔0OAL||A784;EӜYo9=>UjO^iZ<MZ+Hlv㹏v(!3,zOwfGj}&e,H@Iߝ3 /µ.v\P N|Ec8C~W=JL>F0fIƈ)*B<ÁJ-%'y#VIUS$ 1ά~g~Kvr:eQb "flsj~s{$<_ N6 7 <WFH/K-":!R!+-P#5YN8$6x; w܏f)MKBf,KEZu" RJ IK!d6xm]W&h֖eaf1W8Rs˙5ДKNr"?fĒ0[:a8z1'HR'F_IpŎ\v8sP'e2Nk<^gR&q'qR&mCBwcu]H)c5OBD][~izI}YnV{=暖 {d7 NEF![~ʺx<\[D<ᐁ'LK8R>z4Pd"n<6⮚| БugKe"8s`F[5[krqC];Yj!}QЪ|-"=O%s.r ydklmrÛo"!9R-c5GTTӷ[ip˺mJ'mtERq4 8vG dxڠ3"BReUU4Uxh3˜?ؖL_-  @G|Lu0CI)30ŬGZ1Y3hϿޫ#pw Ј}yOf"H 5 C#rs`:?gN?e)em[azn90q&%IxMh&Ʀ9DSC%5DnB!e 8yYPSKgpyR%q~iCU"U2#.j6L I|xd^#C&v0 e)EN*z1rJ"}PպuD8G0ǞCG|}k_hGrk2Sf#tHO*rͳ .ɗX>^/ 5[^~- .\16WQ-N*qsmRlq&(fGF%MojDM7{>E 3!QYܔ”݁i)|&cuJw¤ 0K"{߶mt #VY[J)LuY{)enN]j)Bǃ MYX& B:ZFTa<49"PUb~#b4 " @6J.E$Bx$"0W5˔?_>kZR1`:R)L_?Rp`Z <_?m~ .q,LΒ |m#ϮU| J.W.ՕPMoWj!1ax&wWNةFP>;HT9_jscᒭDC \O.3 Trx0T)Ie_\L0,q=+(tևGveY|Լb h$~=D($XCSjn5S i`R5 3nǑǗ1gpR`(P tB /?BLP c1=~?TݎFĵR\ _ҔܓN Lw0qRnR-O @(ȥ,_"a| Ev4)rFbX80X*ސQr /%oHv*TRWk-ca1rQZ71Q2P.~~Z`qLɲx0aomhnRf8}[glڢp>!EH~QdIH!Ν,цQ {a% C>XKK^uϿtŭ\AѦS=0ϨĽD[ qY*\ZD |w"Z;,E'Us0~*Bustxm)R`Pa!.(eΔüƒ;O扞KzthJs>H?x 0"WzfŽmm;3|T%"mm8Oaf1F#+{)UGOcJ"CvW]?1IDǏHZ1TṔsV000DʞS3mZ\~eWe~O\V >!g\P\rf*8=|$X(I'Cgh.B=2S*ow)%R$Dd9\HI=03#p*6Z٣cHNǂq7CL2 @ĔanZF Qg|Ǿ9{Fv|$EBqQ\pBpQs_^ ks̴>nȥ=:%B}8Ơ~O#?wA{u ޞza-fSq"Hfa+4"]Mo~/oJh=3_nٺK)fG sC 8<{nfJGlPY-Z*{ me).i)0Vw>>8o~{sʘg"lg-%ùonT3O /ߴ/fly az{l´PL,{_ҴAD{ǡJ6W VnʌuYjm6w{>""\o뚽61q0fR/"ֈ5r;D˲o fQaR͖٨x#nXPWu&bvLt-k@xiYW7"֮GZݐDx߭mQKm}r[ouYe<9?yl881gnn;1U8=-51 ȇ3d8Sb\P3w[,j Y<~y%9S?8ewDRd}eY.s۶S*10 Yߒ2&TΙ 5SZϾ/o'B{hذS 4IKpB=K[+Dk:v0L /BU1 nH_|}Sx$ULdi]!4+TqyDXO#Bz*2cÃ吇{5JZuvsB҂0'V#@)EdB \'m8g9sWx﷕8D8MS,9$N#iW30K#V~\]'zZJoǀ Yp8T . 9r(ƚHܶ}ߞOoeKO֚fuejI9O^|K3 #V25 ̡ '%j)1n$9Zꛪ#QE oY |ώz3_13-x4"J_~YJv=֖a)N.." X̞}77">ӋFHy_ߑ !ug47ר./_~||ힲv[µ("<{#=ϝvkx}[:D"AaϏ}3.0?i$K:?z&g>Ҳrlmo}@p3T}},Aݻ2bA汌Iہ &"NDm}x6n+1?۶|)MO 6^M \ nQEAX,.o9C(򘩈Hx7})K`tB?~ uϋXD7X Ow(vgFCi|1r%#^cgl _#& ?L:Gf!|~Od tvjTq pGm]o*0m]k-Rjb3jw~::Oc׀BHu 3e \H ?d |[R63t)=Ϫe@EVpq uHD\[ga"f]s@qZ]Rk`nEVNs#a>:Qgf]Cduwu]rikmۓC plbL? 8Btw|&)Isc4C1`(hzUJ9f5f8q5az߅H$`@h&B E`$!?xqN٧ш'}31JAИy0 vi.h䡟 "GመDD sVKDd%M3FDokkL[!& n4\bT6E6"ֱYsbpg=LOiMelqb lo+tt[OUsÙW LL R)RDύ ˒ mH1ޗu,_T3xdDBӟszLhDNO/ {6w?cO(RKS""Xmdzַ}{{Ku snp,̵B!ho> JoݘHM)y61Y̗ʏKaKww ܊ay2gT$ϏT98V2m6HP {xƥ)sR³}b"7U:7F߾}}2x.uU3L[$ DjtTLHXHj9wt gF -G'a8uJNh\g\lIyJV"='ŧ)mZ5<ۋ* 9ST0 Z'7UD0:M_}]j=f0{Z纻0EL֙9q:.$ #Dx5ݔL!/oowUK\u-Tu GM+;D$J'1QfG5.7 BX +ӈ`Zqo ]wKow7z..qT"D"PS6lc"m}E`$=Ϧ"L3/R1`bʯ|0BI3" O>6$.%wM'֏=Q9>;yZ|hQx/?OB)^djsy'A=1g*y)3fmĂh|~zSÑ8$/>K/mY=W#)rTk8U-tf`٬7na Je!R)x-Hfsk ץR"⽵gAm[g%#=wGD?RmR]x)}']D|yopuCUܘ)=Ϯa ~<H,yOGAh{  /bfyz̼$dWkM6DD)̥Co[wmND3;ƅT۷w5s >s0h3c7Kp n$7&Z#z}OP9egj7YsL|n>>k4uSO>.Yqj!¹)[&Cm|9`|+,ʧ%ʹ稞j-E4(dHK)R?YV̒:S6  ]'.̼,"mCIsj4),U/r qt?om 1PeQU{)*e[i].m]"{cR]3'4-LRhn<wD7e)۾G?ܜ!bZ8Qk˯n 2cBL!0%]=epe֚կ?-D}Ka1bۮZjR)=0Cp,`Gz"ù /qY$BH"Y"Fwέ؋.B~ԉ5ϒ8&^x?e^1{wfp#"Ɲ,&\O_:5P8\Oy2^[&\qyD @4Y"Ի"q0͌ *,m<>J]e@Bc_ym}%/&>Y'@N{n[jwUuY$] @DOAmZJdY`cswmڻ0C@oܖZkۍ0pbRk< n,s3 ]hgo">>[ٴ H:-ʰ,dמ!aH m{&>LJ' o:G0#˺sC`./ow3{xɗzu[Ʈ˾o`ooo+FzRHxogvLP01nԵєJ}ogo-jPB0uЁ.B&KyΗQCPL;sk%>1K\m8^.ŹO'ftAL #;\k/_~n܃MzLĩR'iXgT8D/uYzcIJY+8eY|TT ġ p;0=qD9NuJa @Z.a6]j̭3 b^)9K$a>tL< Zk?`)v B71k 6+N@` HŵPݙ Wc8 3IawaTdlJ!@ ⋷*La 5Q"hj˲ZWTYMg"zr JY8ӌFHNLƙ{ǝAkZ{fOĕp*{2b}yM *>P xRNG* \]½EsX)]aaVUa^z nKF)]r ѹL=Gvg?᪝}⫢<5gf1 LJU'{l,*mܠ' D' :ZXZdm϶oR3xpA|}A(]:ΕRw{ zho. 嶷?VYцOGD<1Fs:uO'Zb1 zvX̜EnH,3@hjs8gU{)ۛn6e%aZQdI2 07,BB7 R^{'<~OǭusA]`Y׌h+BtwuR9@0 DO^AđD>oY~sSo== w /Xd'C3p%g kv4\j"N(> sWpCZo_ץ2jo[vwcB nVx33T7Ș8k&#PX׃eqsQ6~gVQS-RXJ7Yؓ { ~O)~cc=['DJ0!S JI[VD @8)HW R+Ki%l|'#}j=A)\3&xn=K-j 9z84J. q@dwR,UyPB`̧IA5Vʣ¤T~J6yh]uu o6 ϢcrOn%0KJuEi$E)Q'XXƱ`5/$kp )|@™ !D/Ε5ZcT~DH>"<yCx߈P2OTb{>L|]͑. 1wCfu$Dlb"@:ހӨ8= _44qIuM}U[km]dkn 3R["K;"otXcB8T7kj?~(|Z+˂v_͌}[3Z+[œeړDVJ}].nw GevM̿ /Kkt}k]ޅ #Pm{\O{kG˲"m"EX˗/?~|W7am{6웏0VZ }o 3 7cM,{/uJ-%nΈ7$Z|ws}uk^'"KV&.5f|E G1ugJVbax1IZ\M@X䑞Ng}]jq0uma)1 Ӻud'\jH)݃SҺ%P!_}o^13J ~;&غi~݆4W\ 酪WK9Cbқ5uDDRz),©BZWԇ}P{:l[n0s~LaVRM-I=غ4;TL :|R ɺv-$D6 ):7WٖQ4xQfR2]G#*!R+3j;Ӑ?"Fbミ;>i=*C '2iF\>΄(QL/N" EĵjϻIiSWz^6d&`8ҿG*'"]NMO"$Ƙ8.Aة8K@a͠UU!Ab[HuwFadI/om[Aj2PAGUj+9vƄ/4rBݺoj]V uYDχQry9Sօcl\Gx-0}]m3yHֲ#=2\$[(ft|2'wbFetɬ>s~Q E${W*-]!ҨAL24&n4"Rp]DpU5LjLJ;~m[[oHtDaL/ #O55܄y)R S:dHnΠOd~<.CA?a 2jb؛zR[ܙH1|*>5/kh˸2|uG'˕4G.n.K{G}]ofE瓈RJ~+"a%_.3ĥK Sh_E<\ix0'$3lwǔl܋Hz, [u:@[oh;K1'N"~:7kTu~nt߃>8;( 32ReY+LSw$"?-9Da4.K vn2ə¼ʹPA!wD@?"_ {d".h+E!`_)-xnϬQWrޟ +Y{(< EUR_v# 7FiA."??R|RM‘PU\ws\U + 8!|"A甀 ~9`[Wt|Yp5MQ鰅LhEq :gJM֢ E80q"@A"5g #>'鹷}[W)5gEuq[:QAdnE$h(܎jm^O=?݁qh u8d-|<axYn `{)(%^jg#=uhJϟ?~ݶ}cF|) v[{oDpDaj]G a<7߳B0{̃2SPǦ/GgmJ9L3^>G@DfSØ\=>}R*IxB LvPcd:Ę/G@0 DXr=zө,"uY%CuazW$jTjc΄H,Fֵ,gK ´ tS"' uLH<-_S3lx>qϗjXF ?~H'X希˯#B@7껚a#ͧf۶TϮM3%)0;Y{kJi"Hr\Z ρ\ `_fxp錊-]ocLys˚p̐wq,<܂Emk"ysyGvbWgܜ#ظx~iARD½5K@ 3""\j}>;31 24+!N䕻j)mۅ4܋۶%s1!pK;d ʥO]VD!l)f>r.:&/rR L sU - gf#w˴Ԉ9)12-mDL~=Nrw7$='E7>m0,*k? c7Y26F\ j) ""f)_31@tMfI-R}d=3eYTW砞S?S"q_ <?G,K^XZ$Lq&&i+`r vtq%"&.ގ)(WD@|rY0n_s瞧(,EPgKPb6] aG,pH)_qb_F1|GBZr.)t<`KSjR*s8 3[‘y wwf@ B"ePrz&1vMhZ5v˗/)ݶm5TQX(ռpZWgƊҙz `7C@b1:giXx1@2D4C0krWOX+u?c>`J)^DOfD]woL}0!\nøͽ홪'y3s RKx;'g$h_f83%~je1K2KaDrENdN!zBE|PTy9P>N~@;ds_sL\OC4S/C%*`$3Ӆ"E{s3AfXo;01"QC(E_,{kv%@z0 G{+qb3+·vPf 3(B rj=yxHĜ{tp/ |g1`xW_"U5,*@/S#Z Mz̫ P6HdiNͺi^??i7=X]Dmv~9l:,k֝Ԍ܌!ݜ{WW}UAsߤi!ɜglal@t786yQr a|5!0C Ss Rk.Ӫ.LYwd[yYQXokO68uF;1heY}O9,_"SKQa)(!4i.Rv#9@j5HW\\ݷ8fͯv׮E_GOSC?N~h1n^տ~Z%ɭ5SU3R!Xx.A+13K[ºrVW{ V%"Y_0Y> t}u9{.TG#gxh{eWŨ貇`<*ʃ颓C1D "avr7CB&64'$fh xfJ@b^M >z %2Vl?ݽ’ OK\Rz^/|#J)ܗypT&;prO~_/5"I %7aN2geɿqh"":D\ɏD Ip&E3v9̀K0EZuJ4`2iz]ǃ`D*̵.Sq)\h 4㫵]@ȄO]S{8n$ʠeeG/Ej)UZT\eYʾ7fzˢ]d9";D=c&44~m߷ 輛m$bf ϳ%X2$ d XxvUD- sʲޒO3>gQ{GWĜ"'4s@* eiM[˜;xjt?^9ojLk3Eu=3(L(uOs3r>L~ ,{kLf@`Ăjp;"e<+J2"h  aXI&p ]g 0󳱹 L{F&CM e\E2"&GfJ_pSLkنq2 o?/rK09Qk w/^꒍J&QvL.s BEK%nͦrdlxt{x݊}-0*۬,Rk}6I\jM1B۴JdȒ6B9ӥCJ|4hhdn) /ӡ~#M\ й0:$$3(榚DSbyGM b2Co{yK)~˘Eb,,KK] P(Bz>RgLufA nsC!Lu3d&ĩM!Q)M-pfDN9WZ6t匑ajN,0a|8tHq>3' 9ܵ7A Z3 qxkM0H6X!m3S-n6L-{Gb"r2CC/OA~Ú6 i}MNӨRj1/<̈\ս7m}]]U+/37EF ԇ #N#3;.EUi|Tj.hn 2Fܲ,J)em \r\.ۣv<磾˟)v$%&h݉AO8O*I߫O!8l=~t:|f"ݩa /7cY3 3Sl&X:S%ܵFڄxH3'4pHN:dFg&wYA -%̙P43IL%S 94iidtKmsc7~|1S1Fn Zd,R{r||:eºܙ,=jbr|-kmL{6q]ΈDQӨ!7T@f"W>zY4Ik벬Dt^xZ;̜S2uTrb"M4MS.h, ku]奔RkkR>rgǧ @]+"2: "@7q#.h' Qd?X> n9{K,0cu)S8182qULJQ2`jjuwNLjG}s<@%FXǠ0Z\A诿n֔XFw$`o94i*o%_~u5tf"uYܬ)H=b)Dɸ4=; Ĵ/9_/'i)ٹ"t>j)sjIׇ1n%iZ34i 9 =Zel{\+eϖ?Wͦ ?7[ ƃڠ:|Rv83$ZW4 ݑl}_ue 8Dnk#$Ц!y 9\x@ ~hbQ "OphS wlܧ⇺C<"LGtXqͩ+u+CCMCDB`#PG?56UR fadJw !2B؍ar)yZ5{Jn`f  Ky܄!q=ʜC-7'JDc]0X(E"0{͔A-:`$@hdo:8!~h2'[N{8X@1e,͌p+[i;Yցi{)}ъr$\یHG!oVXbd9A`ntV@@ (ݜ@yUEmmK\ ,3Sb}<ԵR za!;(1bx," 9g>tJHĿͫ_/*2iJvOSNZcD h̋/4뺘i^+nWgĔ*RJM$toc%"1DШCeyP|cL'=8Au[N?$6uS9PW}<Zk9#n  `>糪u%D)%F9OzQ?ϑSUAq smicYnL18sN)f?\׵ϯ 9\3D[HGhxb9:g{r3)̔R931A9RATsʹ{]ɥLT{κU~E_?Lf ǭyA *֚\Z]a>͵8!4w%JVNjg֢~9,4!Yc^B)c]ktki0ޥ6=}؇F~X:lc"nPp|WN>ͩ:s~R{#ñR)גY0A4 4zanWb #EDn8P03 ɺӘEvxo$h^7|88֏= lh7G7% yOcta$lѶ:;Nݱp4X*8P}#H@HI$}2;86Sr"B&TeiMfDH#@m;byd-ʌ#)),- "T"ș %jюU * 1s1 m~|9"5D9qSzo1oZj"z, 4MH$"pSqJn,@%[s%(![mlJrʹ֊rN%u]TZN \wU'b$$R*SY6h ܎#z<41ӷ3\. J^|Rշo)Dz`đfNqWU`NUTje"WL|>&.m; )NMYTLmfwHz8o!x ;+"?P OS};r?S>`o#` 1'L!rf@@qXebX)…TjoDPkDSj"8_yYώE+8QחyԌ\rNDi*+A~9?w9;M˔sum =%$<|&"VE)%t%)!iN "jfiȢfbD7.~ll"˯\׺.ZJQiڤ57riM41@UML"ploF2eNS>4]dӔ*UJaT K%tDyGRO~L3w ݶ6`?O9` 3E!Q xRFh8|FSMD.ZZ8>fPJ)%y}\Ig1BrcC訖HA  Z{܇prqFǴ{sed„ ƠbkcDy]40NH2A<x=a)K OsN<}LBC ?},KkEDjt='Z+AipYڔR1s7L.:\ I5R 3Hkfʜ5Tr v_9:029P=, F]}A,B=@eY-bҀTU6|lTeYLD 5Q@O9 U=e&cQ5N)qZ3'0%` 4s蜥5SqSUH+%G937(7f}oD1#m.hGN{n$. dQd(PC\Fí,M(O]JE9"U2uИНz >3r>B%( "Ήy>UR#:?Rh[ˬ6)ǚ$&HL =jVކnR$f3 >J 7hfi.bm 7Asw0BBv Dj xs|q؄w[&ZF3b䜘Dǀ[m"NSjuy,j*D(p+)c%e`\rЍѨt^wBbfCwUě aނ"A(Qђ+:U|~.4emrbw<`ź]koC$Nt #a- SRJ9<8T%hRjjĉj-K].PXc6DAu׾7OӈVy*!9].W7+ex=D%m kvhCk`X*!zNO'FD14鏪FY{UGV 4[&M{p]8r's!mbT嵡=sO{(Yj @D'9g<3Td'l: ~:!Rͬl9%׺Zj&"^Ο5y{{Ҽ2chȪMUIy]k]i sfiDzەF'0\xYrI>#Yn헟]$7) &^/!<=Lԝ 1qkX[GoG|8?>=d{ isHB@ttӦVrJ8J>\%c/I[mAݳ"'B4Bt0rYr&3W&fJkq7$ڣÍ{"m`=K`2@8Dd b LliSc^塉o5˚R֊5fž|KRA%Sɉ=D-"1{k-&D)Y#ݣK3ÌimIzKa3Yfh].Z).m] k]WDLjnG``GC.?(bϯnͫȽ=xvPq6wsre湊!v #NeZeȟS▷āƯIL9s)6whrJ8qzjmfrVa3ֈ8\kOaFէ!5y%%8 ,pJ9|mm]+snz!@2UQ{р0<׵.{)˃ XJ$N)Dw=Ig-xg9 (! v^'-:3Ts^Yߌ%޵L`i vH ]/S.]Vѽ*z8ƙC5~*93ںF!ZrqZe) z(ZbbcОK1-[kuSBȜ˺Op4ө2ԺJ%BsGCAn}.`-⪗t4`6$q"BƜAN׵. DuQs$rjk%s65fDi5 y. Ց q*SY͙Ɂ4frlֺj}#d|>laHE~~Cvy) sNibĭں.XJBLn9gT1 NJdniD741FyrV׵Q A^[K)Zj-)V;[5JBXfV׺.+!^_^n{b +"#;ptrG V>#7po>;wCFjLȘ); s O ۗ#G;Gw[,DzF:M c@@uHLqa( gv"t&!/T&L }Hht6hm=tfD޽C7}y1 1N"̦Rz-qB@+0WS vѺ!LG |ɹ{t$$,ejk5䀌pHdI@raRrJfWˉT]d"e=|7q/1j{68l=ýpĜ`B4AĽ}qiwRɛ"0P9穔uGĂ'vW}𩝭(Һ@G+>GQq# ζ?D/mU{_g;k.B r =w_LG2D{%s61CvM,LX`!DRT#ZS/(]ֲaMfaFD?x2 <K"U< 3M{,;qJzS6VFE q|9[k@Bt75-%M9Z  1124(FsnjfZSJIJ}o@ADr.0vJ%{MQA@SU3BL%%t̉ȡ5ѵPmIfh0Q56m/Fl2\NȄx,MZӧ?p!z}{{pSJ >-!H@yZ4}J)벨*3?KM>V]O`zWA]u"+Q?;3ԎPػ0X껣!|8M|B\ToV0U3fnF]߷'F)!Kk@)#."%(/Z5#"38hi:.nnjT7y~bpsbDuщU#}?4NV9|e*kUTADyYwiYW3|e3#sk|9)/ ]ݽigSo 8ztRWBr("O>&eYn{LiǮg>h M ?cXg}%"ٛ#{ 8[&N9%u &-M% #>3UTJ)qZYelЇ8<QGNj=asC,ͷQ[2)v%)oItj T l/R1jȑ3G4 nrPjAc0{sPÚrЛ `&%RΉ!VU,|RFH%;vm҂y2s2Me1kz=DE$LDdw-9po<3쒸{\qg>LI"Vi"ݬSIYZR԰Ӝ?'˗MS0ZRUu{: qQgN+!t_jq/-B;8$BهSÈ 3C )Q&`n%4nRɳ/̜T ffLh]k9N$"JhTMlV5ЁYW|*twN`^El1J@Kxcq$T?yq߃D.+??vEE4ə9m4QS&dBG9'5޽9Uf y n po)gucu4嵝MN1=<|ofB7v~L1:PE{mZD'tS]@tMџ6NPK}2lf?o5D|bK׃S"bfVU |>*Z3Tk*1\nn98iVGҐE6c>{#}%uYEDJh`7vHeÌ`>8A6w$MӄH(*"MDT2eFĝ>3NS.FkNي4\EY)1].x¤~j]ssJ)'DV(%޾{ؓG";֨GF:^=W[Gó=9] pzD 4صχ~{$0c_  vdP7hf"qf^Bo\S]lfn41! w@q9iBo`)wtX>"o(b?S<$)3a2m]b*ZJIiS]bQDno7Uu2s:~ F%=RRPb8:XvޭI:O[pƀ=è?|'!#*b2`ffnT>LSG(-=EZɹյ.e;:kmKӞ䮦΄t9M膮-%Jk"mBhQ nD"EG4?Di+2+ )qJ9lLHCfbB3@fwl-I[Wp8al3?8n337DA H؎}ߩ'(=[B]ʄPw!N4-_a4ɐUAVWj&}=<=|# sɉ1wE5 QB]H]wCѰ3M&$Gh%QeE"ҿ/KOe[_'! 9`F9zK)%}P7i暘t=Ot4O2g-4tȃ~} 1Ym-37=c/_irwiLģ%@L@܉nszwl[Qv,-9s$JEGbwF\2Iׄޘ8 SGΩ$J&Bi-VOww ΐPtie?|>?ڞSw(iI(]L0Nv  asff|:Ħ..!SOJR\rJĒ؂ϫZk ˨u)Hkwf%O2s.wfDe^Υ^<0oZkPo3KT)r?҆2;i=aCIZ{*&o 1~uz5tV_װiR&m룝Ef@_y8cws%ty'\!b9HME4R%01ސsF~?Υ֚}YuaT (QLu㦄9ߎS!)3zq0 G3$/Fj҂EDŋIXĮ Z="|l[8{;1 bեLcnjH뛺-Ϻ8c;5po,wzi;lc`R''Ҏ DBN<‰2SS5{GvQaU@:XcwmgCN|k6M%T)8ۺSA<$x[bŎp#!Q\Ƴgj"{_ Ryw"!>D FA;$5 =IQ&@&/>j*$푀ɁİUѵڤ7ibN"T5bzDBb0 _k?B_ݿ1q]2[G R9s/_GÌt o"*ND!;%3"\[v[n;Uyn*-2M۝{d1~ZL?u:My23`󌀏ںSN7 EqwK DfWi+yjm"ʜ5&BuU+%ǧgp5r֚Dm8P`A~T%[u9;a=G`r|[ه'"w3 eaNn7c:=ўe 2rLLzyQDzRJJ9Hjr:E5 |Uťj;޷5DOI MsƋwB>H*Jў3s_ˎ1׸vī\BDH}yށCv" E"1v/wLRbt xaXl3u9Œ77sBsİuIN"B2?3Rc].M:k۹ ('.*Ĝdp[4ؗR7i>0x_fPs4k>:w4pwLh̥տ /As }R-"!s$Ҷ{v Kηuu'D&ֻ}U̓fi^]4U^'DYO8AnXTg1sCOe'. YIۭ8JΏ67*_q;QCfVݧmnJ;%̢~J&GQt;q/L .O{;EB<|+_3$(^j3Vh-ŕ֣+>f9sQ"c\47yc2^<{hC>z3?p QUAT 9u  U#Ŝq jUL.j2imHD|KkBĵ8p(RZ8T("*K9'QnJ#bA7>pot֓1{u7 sbtD^sɅP6sf-n̔(4n&L0.^a& Lt Z<@|q˲.%\csI~CJ'IH4y߿%KBaǗsbU2ӥ,ؓzϯ i z SE) m)ۭGdjZ Oh]U:U]Z͉kNˆץX~BDǩAg6:T{V69xcw99Ƀzّ7ωsJG2#"lo!XUS;jFqu-ҚJkk_K@twb1 _|O$J9"GIDrh(sJ!VES òHC4iq$jgEkd|8 ڵ],9Ri0 ^~O5 c )efQ31n4Vi;xSw@JiYVbޏCTGqD"Ɉrǡ "Tqd!9C=὾p !M>PL *2&' J3u0O9G7:vZS6f@DNF>D3nHÝBm1suQcnIDDE4/t{!3QF?(pZM."ݍ"u'fwXWN)a&jNf o[8jJzܫI#fDSGQCDN٫H}]U|:5 UEOiɺ-2P6N{ `0ӣxqX2RE8dC5+شx[]eQ5D*F̾=pAOT9yZAm mj"Tt;|~}FYyMfu>NANaEuszDxS;KkmۇĀJ.Rlt}ݖ3wYW0'uw18K6d^W-Dӷ{Nuc(e#cNl1`զ*;i?Z]mnqOf쐀~fd*ͺ/ڜAU5~wC=JO0V0f Qt93Qm$WޅHUR$N˺w3h ݩ E*{ F%խC5C'b,=_"]S6  63^ó=sE}CcH9%%3ECQ7&}cq1U\3|k%!Nt>yY7։~iug KZ%VjgKqc{q֟yth?!o.w93{NP1+HLld*0df;RL2m] (1{d˚ywcZajp=MXgf ቦrEx?6)!s[sapƗ%DC [m01zu1:k^ZW$5a_s霗 q|Ӵ'ꉖ\n?;^P;qc/;ә>>]<ʼnwDn "0Ab\ MΈZn J!qV,-6<&h*7N_>>x ڙDbR."&\tFlm~sZM+@H1]Q`mH4!.7"LL-ƒ<"owBw&${SD?$;~R0| yB5D F8f1i89(K5Ĉkzo=qe`hM1c6GsGB5&KYLQITJ0,BNΜYĘ8"pi KN)8t)eYn9̪k*юzJL9{ vg4>VU 1r:)>> Rl0c,$b{p%Kw;-N! .|RԽZCʡ8GeCJ)A$Xs_Mg tX~gl[(͕bϟj߶}'꼉9Uќ_MIy=zfVZJ9A9/YU:zm2O, +n"_ו}O\T!Z)Dd۶[Q\2,RJ8z)Qkm}E`f0AJ)9eYgsTe)q* `4"x)nf817t0>sW5攸 m7NM4xQ(}?"XjtANڟ_=~%I?>F6IAs@bpSuQG>r.qP1ˆr֤"t+RjT;p]< !.!=d(&H})eYJ)M4N4I9>j%!˲qF3 PfʉA{,l̄ ]rb4`s$]3  dVSd*/cď u=GcaO>l毱K}E5V4}#qxdhkJ)~IK>:|-|1qG1n"c@milPfR" -,NJ2I !{vf*nOض~3vCBUͥ*-uY۾mK)}~N۷9G RS@ĔR"Zx|}~A0HeF$ŻK!45Q8C3DMLǷ@-4iu]yk;*SM-L\Qs.T kk؃ۙs&$Dm{lL__jFUԁ:VXmE]9>Gs{Da0*]hs\Jbc{wkR"Y>rr.chL[@dp|0jK%Яz{܎oap22nrpz/M}qž}}ΌjVkS_qdHޙdvbo"y>ŸK^-g]πߏm괫amzk;64HvjχDz1{)O©dffAi8&Ѥmp! z N&e>3 ,XBrC@^jx5]|~tZq};r5Bgre7P'RI,LTyX|(f*As@vk!"@Gct\ zF 8FoNzY9B #x"ynaT[[֭$z&˄;hj|{A+HX b~#6e!^q{bY؇gOX_~||L R__x8߶-֔ PU۴Tc d),Xȝ^jkLڰ/FL4uݷB׿|Vk{<*bҞ߹>DJ.D=FE8Dj [qԣ49ᬝt|6Y2t.M`Ą,VPES;v:sيcHK*BT*?o?ĭ`jkG=v[߉ZՇ5m=q"ĄFVE$޽dB@WҖTqPppb\L^$W)"mmKRv-qmo?>EKy{۰og)yKYV5Q}?D5S޶[JmVs甛 P6 PQiȾܘmk o3EU\@N\JwfZv3ĉ9ZHL)gUO‹y /nsF!?t _lOO5\re| .]s^7a\&M?Z%eE 6nx@Ze2YSQQ R*--^wtt|^$=\Pi ^Ts}0d;>=@3[jVV]UVm<~xyAf /uuuTJ͜9 ! q#ymB̦<|pRrun÷we545Ç'w,>٪U{ \J*6 AACFv1Z۷ҥK ?zYVVBٳgSHEj@֯_|AB Q W<<<(((H%%%xeXXXa~~3Qp N+=P\Llٲsjܴi Ç#G66wޔq㥶Pت۷oB[nILAPl=?׷zo ,zkcdhǏ]pANl=zOus_}b"J+Q+Zٳ/nbγӈ'O^֠.j(Ԫ:@Ԯ]6܉'RPSRR*g脭[FbϞ=ix=XXЌxAq[( cRCBBmBWM~Zzu N&9s&mL)GYI8pAoJܷoU/`;;c fYXXC!'Ot=lْ%K"`Yw^h_=7666ѡVpg[tt2/""BaddI2K^"+C)G H% 7>P.NFEEɠD:|U ¡ +gJ̃+NK&OAċIwE-#BS>xo &(29 k2J!Ɏ=*sҚofF({ک0-]P@ܹ#P*OQ0qDAF'(4 7 3y^z/][;.6jʋ/Q)RB'$h?H4L/:`0w\A|0FOcPxõܼyIB {I 2Ν;sƍһw KPbtΜ9q =z p-P8T{<44[nӡP0BjYŧO$ ZhO%(/SNc`PcPnhrCh3449y5Q b@daWLJLL,ČW!^ƻp7CMyF6C`ľ> 0iddt[hEߌ^\uonQM8(Fs2qZ<k׮PQ{a6`V˅1]궁$%uuu7o0J+ ?gQc @ {|"~'?Ԅ$@~f5"fS℄1MM>JG8:1^{Aw|&ٳgmױ܉}>>i ~_hnpty1&9"`y6lRŕgm `i"+c|ʢY{ζ̡LIuO'e Z˔kڡu/DDIENDB`instead-3.5.2+dfsg/themes/arctic/cursor.png000066400000000000000000000015561467622671600206740ustar00rootroot00000000000000PNG  IHDRͭ'sRGBbKGD pHYs B(xtIME atEXtCommentCreated with GIMPWIDAT8ˍOUyϹ~zk\^s#JoľLiQmrLZcTBmQmFB #%]H4cYj!3)43͟>}<I<_trgN-"F+8S|q78YCT-ҍ;%Fߎ13=523=3'ĹǷon6-^v Q1o8)`@eIr˵պ5ڶήm4w}{e3=Ek \UǾ<?=Y\۷ ,_d oD"7$WV{PɑoI%ХBX 4/@GCIENDB`instead-3.5.2+dfsg/themes/arctic/menu.png000066400000000000000000000034401467622671600203150ustar00rootroot00000000000000PNG  IHDR szzsRGB pHYs.#.#x?vtIME  ٯtEXtCommentCreated with GIMPWbKGD8DY 6t{IDATXõilTUgެo3NK7JRZA-Ⱦ#PE6#D`00f}ZZ{s=^gH ehF(da$蔅>zLa+-+S3"Ax( Y(\[UC(AҝHm=^l$msݟ\8rOIOC!so9ސn[c<݊)(9T<YI6 Յ- [PF=D9nWʌ(>'fYJ zw]OrZDj'V1CuՄ =ȁvPSfz[/8!$ywf,8.:"nBgY]=Խ`ɃlߑCPz}qlvI YL̍LɋLWrtdz~׿?lĂ^B 0Q󲙢) go[ɽ^ǻK3ZnEu: 0Hk0IF t?q׮;yz*N|}%+~5b̅/N^ݸ&-:B&%[iEþ29:0^y~[ً6N}kC̉.GO]%ިYxu<f s]lQ!y}%Ox`;zE+.A8#whY|VGMs,1 19- ZJkU%E_naBŷ`"`@^v~p~$*FhEaZCJĤPN YMިM4(is\P[˿B8&BY1kE3Җ~m`E^-9!W Ѹ $A`q [lJȩL!mxm;{`@iwfMr`7 K}kY'lMVz)&*N-hvl_mrǩ5{֩*ZZьps9l(3ޠ}C H`9vw0%g Ͷ#m'>ׁ:0S$=!Ν0xba Ex,B.<#e +:w3Jҳh:%@u@ b;fZ}q9D¯%ـ1 <`xJƅ<:*>UD崵cW&_FRqjFZ#@,Nk~d9P~QG 6zcM{B҅'$ 쎼tBҒ@i/%O.{ӫuvx݀GG1(tǞNFD1ܶ>6(Ż;ogOUvf;q!nڌ{-Y'}F5!z1+E?oOz7̿1vb1p6ԗl&=_#y:ID2O-^-XrJl%M9Nazݧ_)>둮d%_ah J,JH 1D&M,`?&l bA4?bRw?ktRпZw@0V1FoVmN U#c f5F4ݶGN_FV#vOKH1X) 2} =Ӏ8C\ 5a<^>`W:90V) DȣS@K vb[]{罗f4?fO [5`?CjYd=έNJ~4:!6Oiy'+v}:[Zp,*#AbnOͰT-C'^օKe&W)㤫C' ٝf >6;R1H9*ƌE&J!?N'eJ<T hO r5Lp,:)J$@!#n@^XަtL@1=!|纩|TdcC jF} qӫjO rZJb,K5K9@ TSd`+Z-)f08ZBXuٍЕ_to6uhmj#48&;*dڂAōԾh|+D(8Asר't4\˭ ͹+nIӽA=|ďEWP_5o P_W;g-Vk :묤)涺tSO~3Cr(eih}hE>F= Nhͱ;Z2ɖP8a0mD#ڊU H@FȹQg+]!tYn'<`LQCϻx9Ƅ B2B)LoӔ-|W1ʡ"}<Ủ' ?ɖ9H&G91+FYz3/tU؅EEa `VDWa&J[]#)ypeˎd(+3`JxL6xWǎ4xdٛn6xE,.S c7'5Fb"Tluk0paXff '-b!0ln!!2Oב 36$W;&VƒeSs$ա4hu6Ic)FH)EOќg!%u$Ȕ`HG^@rͦ՚jwvJLFɝ GFK7d*3sҙJYtl9<)KM 5k/(̽a<$# +-nz\#-b:3&beP t%X{+{ xKȐ8+$Jh߂w DUD(הt%S1ΖYlڿfwuSf_vWoA DuEh3GiS W奖Gf!]xK?Du4,**>;E[;hg+9geVƊ^ǃ p!Bjq~`<zJP{rdIv[aJVX}>l%A*UW!Ab#]wG5U9gƒ#r,x VF͘ekG *mjd䅜X/<`Q+D[?Ҕx_3z3RopE%4)z63L0do0j6'ri<XщŽ_y&y|UlLRev&_ C:bS8"!Bߓ}pٌPZ ` xa4AmAPҟ^EzTs`b,雔9f0.|RSLnu=6-b"r&w+>K1 H+1Z۠Yh3ubxGBk[ p*UeU0|EWwXX4ߴϖz:wfVDO*ʆVaj+r7e>hɋ+޽O丙&iM21 S7$@.SdL`#Q {ZY)s#@ѨSX}Ib/<%eN 2B&ʇyѨe$|IQoS ob?)lkG,.2e/-:HjXwD\e $9ԢwN OS3͛"4 CF 3R/h^"ICx4/u!u t -^TXOkԹByXM[ ]ٟ -0aSCKYt?44IP)Pto*&!kLXTiLږ1Z!,"`O_yRM*Af鶩RYTѝUܳ3ƸVblR16}gXfG(R.=+Hò"*Pɯق1Ǖ..ը ,c)?z5s IH6ZCAÊ#*3!ʬ el`D@-Ӥ~s~m_ȇvHy$^;yfڊφR vWOA( ^=1Fë\ܰG n8sV$R *VYV݅&JԛMv+imUy8TxXvtY a^tbJpU 'r?%}HziVe@·9'fV- }Q.C&جcz*, b #RXˆr+ ` Xl #q߄yM'̵̂S+ G> u DOB.ԪE ^/O+񦈷+h~kc 5\6u.ɐ5ߵTaY#-ejU`i\E$fE fEe 3!j@_La>2=M?`B-Flu] HJe5[8*&rzt%OU|ۚBP3#= Y3mO &^j|W.K=ؖX!ϭX ӸĬXٻ!SVb޻ 0<1 M%r L4n]#RY'32͖v4 6F1P1ҌoBks0֑r3&122TOFEmR"P)J+ +x! |`_ˬV:BVf$1?hp!ӠD]@Txz|°N*$)ac2ojn7ɈjW͡fca~5%JՀS%4T#2l5¬&R4 <=m?SꈪHs{uUHnCԌ0Six3~pf3fժQP),O`5bJ9:bZBD9 |aXQnc\8 ҄vL1!3q%d]Q+}6CU+;Vi#e]abr 2^p5pZHi*yTv [%0ķR9}^7,^ ]29 Zu5:V%"ڇ4aV{T'Z9c%i:'id?Ji6l*Yrͮb e*ElJ'ٵ",@{ `t  `¡7 -ef_;V`Ϭ(7KsnWMQ'5G2,]ֆP ak(&}kDu^0W ) N0g|KJ{`Td)BXo'絴yyXVJiӱZQD0=wP &*"ݵ;_8p):Z~@5NġEi7iFRVMSvy*X2"6DJzċIW e[0+͒44iJy}fq,J⢣eC1B{Q!Ztɐ*.b@!=^:XJrM.:qgyc`.m\=;egf}.uBk6z Eq ci V:˃4VX7=X6u9r 3l$HEl:å1lN3㈳Jl`zVCfPdžR*GT K$ŪӑabqКlc s)k'9S;ѥL{Dʨ YhI,O)9$F4-lŘ%r&΋ڦڨ]T'fӝr_ =ø* [тRa,r?LH~Y<ݵHВ-,=6N;aWmҒ1T$\3Zk:FVIK&objI.\YvD5u+{f ;yc\+a$beOy:.b;:A"~!`,_ڬo&vtEag-DE<3 T68*f{ g&/M(UeIFJ"5^Jc ޮ0zȽP!Ў9)0CDž锆EڱUt.>Ei-T6KcjJsH8ni-`H%hvejh*dٹi,Pu7q 9[a yZ?l!=*jtG #8mY뀧ܠ&7Xf{UX liYvhwU?(|hiZپ:b, 7È[=V;)Q^^O+W\W]qZ,Q,Ս(U^e#SE8j1Qu톦LBZW (ýHۓ=\%X8y(18>D9+!u۫K/]f K&0^,GA"RM87ָ*аȀ ڻ)gIHeSa[A3sPE?2¬(tajEITf,-KZ L-b,\*[|,VyЖcwN:ZDʃ}k,0_eJ BW5Tʽ{d8~Q y8yeݽ o]ϹJP7 :V>JՕfTQ;TV'L .U[7Pȉ ޑoGUa$7 \"լѫ}r3|EXtz)-B?j:-#/a? ^u@,pA0&(Vm4}De^fq"la4eш *GO &7K`%kNr͜@(5$V ^pLk⺫c, lSnXkƉ<".c=X{/"uarbC1G zB{gķtIf mW}nENG:CњV6= sEfݨŞKt'(0Tt-j"=P[TZic늘"Hɼgc,B ?<01/vKFJk"D+QyfCԉ"B1ZQMݐ}2*e5ɞBL>mĨ)^9FB+ԃtun`lP4^4h Ͼc,M+|WD˜1)B0Zde*U ˻FWn)p%)gUR?M6M!, p66(&LqQq9Vvzg](]){cD]) S4}wYNG 9VFCd*fIacIŐjFEVlF|7LU3dǗ%T-+VLa&kF4v,tr.#5#}}s/OQoHV(daQKjZH꣣v͠vH~,QȅikBuh 0 guAO˳e8jUr㆝)2ޞtC/{%m[>Yg'`pn{әߺ[|̵-h>f>9&MxB۸˵bdQ"`hλB2e jKkdfꁨBz^a5:XIUOhi@OTD~eJX\ Gj$ŪlHVҕ["YBҷSւ҅HՆF}V^#M7D:!GWN,n4Uc5Iڍ1MLgHr j /rD1&aiTKrI|cEƕB *V)r7J -n$-3rt ]k6~8U`&9e1u%XWܰ@\0Xtk ۙ*XWc\<@:e}IO5@W`e*a{ZO뀠hI)t1ρ͖*ldg Sc-a!&Xj o2VBҪB|i>!Z`u*sNQRSc$, NI b/+F\ ,+ߦ*MCMYŧ2mMqD>cR 'ծ&;,tra, P ]-]@W)[(*VuPVt@*HS/TJ=TNkrxDՍV*YF XdXT3:I%Y4]F\^=,*X]W7`=]W+rRt A| U.zu/XWqX >tXX:ʉ9U\xZRCibp#\eɥV҄vs(3cwADIȃUi)c@~Dw0J$֦14 +6 EXfQ<Ȩ<*}WCRJHcB2V ^CIi#8=k5*,aaZ$ڂ F%aAYZ@ KjGWX ip0k$J4]'Rt"ĉժ["Dl 0E©(X UىXA/`:=^,TQZ^50"еc,ttdUCҢցXr~˵]}ʽ¡,mD|0ˈ2osmt_4>8)JW:7Ko^_`gt_Av '<mgb̅V:裏}[=wxxw<Xħas/zpϓ>/=WmxbWܺDwl[G>>?/O~xϿ/UY\ /O|e=xq;>q\]pF 7ZkF8S v`w"NǑR_r mx}B+,[x]쎇?u}>{7x?`^;G>> f'}hhx ߭/?p⦅z/=;ם~G[Gu σS~tTv? uOtg>u/};_7w^z8>? \[wq=Y\|DXn2Y9rJ4IZ19+XfܲUU'`[y߼q Xp_XN?W+s_-?C9N\nϼG?鮇^HXy|k{phgϾ_?ow}~w3_kfgkv˟o_W_~_o??~?bo~o8h~a; Wװo)hx]pF 7ZkFNqW\5XD`qt"]Ɨ}]a[?O̴^vsޗ| xT<64<<tǶ6sőcܟ|xc~\{6cq}?ηw_ʷo|O#?ao_W=>.EaU6 ePP T]R X7nG0 Ï<Ʒ_uێ8)'ǚ5;W5|C|?ϰ&x]5ϧDΠ@WSSSg Ճm7y1N87#8;n޺kV"ϑ'|^r&<<X/+6߶rW܂(px-É+Wnіݲv hfp0l^XlݝwmėsN+WlĶkWeahqE6. ۮݶr;X6nسq[c;ٴiںuUvmݲO#Dm>O~c/_W}ߣ?` I#S| 8&kk ,8ȩ=V__  W8mGs%օ9۝_z;{laٲuw߽,<ơo}[dŭ7߳~[߸?֭7 ] (W tV{=Y$v5&n?5c0OY8޹ w_Ws0Hn7znp&n^j{{k.5x?2R)$# w =N>ю?N:3f``wg)AjI %DNeN#X!gy#`],iKF2պR_ i]{3CWwSN=ko|2AW:nqW_uv8k3i5\ZX1zeO %1:8Yh>fg7,5p}4=ey.7;CyF 7Z9պ@T$yPoxT7=}qV$+jhjD qǝǟy \z[:mGqQ؃mؐ8O;ۉyvb?SE;8qw t< =3p$N~̚ rS\hcq}lx . xHp}-rđ8+őcvY8}"^O#@m+ĜH"{]GǟprV Q#ޛcʀKaGkbr8crf>7'_b~hY.&enp7J .W[6KqnDU֯ߍ_G94T+STֻ-X): p]P3قI$ S}h dJw̋=^PHYUu EcM]EF:ZW_Zs{JwiYabbв@`W^qKq &ʞt(%Qo_D{@GZ(UjIw BBvT{2ѕ`;'%`8XU:ց xynI X8k~BP#\OoE"A &O?37lݵb. \?/:ѥpLӮ9g)N7cun`x`m{ĽPґRnp7ak>XrLkڝ^0]à  `"*0UepX`7GELܠRns X \cXU90ҺRB7IRTȳ =VkUHuQ*+y&~P)U~`٪~D$AU^|b4}9pPy V*;bhʲT^QsE]8,XA)(h8 bLv=n >f aJbb]n"`@I+a_m뎻\׭꫖c 0Y,v8\Q4АipY]Kw݇[`np7Zp@-okEaCCvrEx*Dhf@#)o37#U@#*9251V~E,۞ k6+pLwǟ M&,^\V}5tUU ?MUj9zH4aK6 Z` ґV ` WV!*ʛz̉eQe|ς\/m.!u7<#sȃ'm* TrN"TSixssV0HWy`V\e X,>Cy+TCߵ噸XȕݵO~嫮 O89ˑni;эЁ0uBk;sļdnbu:ZĺeC; Ub.d#R}Mٸ]nQb}m̘iHeoA!~ړ^وlj_^^%!Xo¾g~GM/nO+Xū2p@hvPiW`ec,Y9FlVeD HgØ*VpeYDbљ c0 b'աYdK;*\(N<iQăXwVXvBW:`s@Yq8K^}_bF X8@$Χ>gӂcļ;qEɼ}`M o#+9n (Ȃ#y[I<ygC-!iM݊ 'mX#p-5q#堘CBL)8},\iX؞/}ʶ C}s#y,`ٸʷ06l5]X|4PF `(Uv_%9E 'X-s&+`/ 7o}eR}Ѩ:uĊE1{:a={ɥA8rB< U&"Xm0,+(JvANu:56~kMrw&١#y졇-)W@Je-6:tFϯE.z8%:lP3$-ވD!4?om=1P1PT|WlNe)Ow\Lڙ^+s~װ]޺ BZ%30\{.hF 7zMiV )mn{t@G t#XGX ,,XURQBq[$XV]K):*b#A)5Xu:mV`ɀE*)cK YNێm?.E8FU4]wk0 Ijo~[?3ϜAͳ͢-D؏3Θ"kg>=aɻɉic %>tgMW&;=9Hw;Yd&o _tlE tui8}Ω,J.rbӤ'}Mw A2w7O]=CgFK^g \wץ>ᝂJCkG&y"w-?$CO:4p nA6ۂ61&IUo[ܝr9Gk.fj'doي;Ba璈æN:ec#N5S=RpL.p-5u#v=u=03e ܷ; LU'd5eoPt;S85bٮペ۞yq%vGslrق6;&cU[-ѠV.&HDZ` 3,PaHAu\[&P~Vqb鐟WXRzHGԹv?(B`93R=9x*j\F \ ,NA-<7R@sl{6 ~H\߽ |Sq<:u@8۸t`'0v\l$;;'vMqv?eë#v cI]0!'39rԟ$2-.0dmQǠw;K=ϖ>v+{Z{sjH6Ԋ09o u{s/D;dj!MdE]z؟>F[`D'y^Dv%q"{y;]{ &v:T׉xBwE.qPdžMq"gAmF 7ZkFNcicLAuw0,`W}".EW <4'rhe k?=`Yq[6Hx4[;qWhې/=X(7zJ躎\i} )}kb>Hu˄VG ^!VuC$ Z c#US=Z-:أ:oE(T:8:Vw)ҋW7AD"ǜplz ő81= 8^qp1':y_'&W;DcY'WweAؐ+v-q }qq#!8+9N,-ũTBNr>ɅpkqMGb{őNq'c㬳;wt{p6x {~.Ɖ&)N ^ q's넀_6'wq 7Z^C7B[>.ĉ'x:ʕ$5WlB|Zq7~+m1/nE V.05G^"K*%(*dhjU-D* 8t(!fV}ׄ=M7q0 a0|6vL%kA]k{)-_lhuQٟng+a";6:\Z\HIzA:ʭL!~f7Lލe$aߺZժ5 sPP+PCw-kßS7ܷStu`*z"VE"12=*rVL-K+wMYlO9*/oK\V`"R/Iԛe0i#,,$bÊd2 n]|E3MA/<bŸz'KXw%F'tW7 t0˧:cf;!kTV9ܑ~ˆ_T(J2+7z͙p09RoTcuچAx  H -XӴXV%3ש+dWK:*!Aa.@ث) ̦'84kgLB移=9f}7+ob̅8$KRoX]2MC<χ‰ZAˍ+  sy랁ϲ HՊQ֥i?pm0?}k]AG:`pjN,hȻg_yTbXEi]iOªɍn_jc&YB$a,$,㎃|/Z.s!B'qK/}-*b%RWNj$|xj^Jp |9.Q=C] cX+W` fj70"JfiM) oᆱ> ɔ'M6"Sur -K}k;;&ځb[sӏ{~SKPEjX9)3t\YfN>°v- Ĩ7Moe(Ce%Ŭi7"e81W|pNb)ojʍIC<kU[oW-d|k]vE}.''r&VhaP6imp!cIr\iYc!XӴ,&c6R2+!6']Xd/J6La-@Z녃bXNN  zKud,'dG fxbZM V[TNri;`=s8B[ڤoAn*U>> .զ"5\3}Hٺ)R$e y1̖‚wwGS8^!l?Q1e SΈp:J}N5 dDa,RHwu<5+.C*ɛ~ 1X0B;6Ex%9cb8iWfΑݷCW;T 7&Nc5Th;+Q` 㭞zxgof mtXo(,ty~>^7x]w ݗ_-+Z3N0뾇? f}hC90(N+H0HRf2B|V\,Pve =VL\ _ 5GT~1xDˆF{?_US o(-jS =X "L$ CC҆6mޕZ]`A /&+t3|ӛ .#Ff^ixoXXiONҁBxP/0++dJ0VkO QJV̷U$zD^W\Rjk?wZFH_\<]4tYi6ƫ*{9Xdg}L|a 2U^NyB&N.H #/ﴕV(VcH6&Ck΢ml ćBH<ܲe/w?o9Z>PEXIaS5#̨= K0ʷ󤧌2WȜ$_2PEb"u+S0eH'mB颡1).JVq-i2AQU;zwxbQK@2*q/YXFb_)"3O7S'R+k"ER jaxIJʽU]?r`UH(|[#8B[vz>& #[[?g>  zVcz?zm[Q aR*MBCKWl7VP{1 )Z.epX+C~b;֢pgLVc1L(~T= w.BPq.$v|Us:pSկ~9X\TArĂS4V$X)zP1jfyۯ@ x")3U$8ߕߣvb9P1XR:֫ Y Āш7D!`qT$s IR@,9w@DkL/^!hnD_7mM{~_A7^eXÏfͷ޺qn|iP!Mm6hRVe1 l!ܨ#^%Do60jZ0 ţ5X *3Zz/>!Yx[TD@v](WrvH n^|Y^!c7"ie&B5v; XbV0KGp<+Rb2bPG  wkU3BzFdBM;Rj+HL9Xeʤ)Xxxq ߠ"vD P13kByb+]YjLؾ14H Kpb j9Y>tbZNUWjD U*TS7)l2`{QD}R`-ȱjӔZaQЛ҆X,YTpkMͽ2m!t1HN-D dBWRkV"(*τz[GO}+1 [3/r ɩg~o|O>L Ug/ET7#6&a dfS:W"qD`; u+-x*[1*5PT\й 6e8+S *(^>/\=Qw%Rԝ,Fj{&ArPƘK8vb@Yz$*MLe(5.F鼡b 2Q%ҋNy5~'喫fIYE? /?0 ed* T uy|Ua6_bop>ڕd=X<#<(Ғ3-sbUeǘfTPGږfpDqbJ%n%+_d'#舻SjG Mg2!TX/(5 -'QD$XkFE6}DAuD%qz s7$OJِ!X6͜jInw%05#q9 ukrU([zԫT.&hT7Y(Ql,UqL^ J"4`H )'G~ &%J٩*o% Deo RJBڂû?Ye5Px-|(:I4xSWXB.H0a)h1%9 f$4tu"=?? GN3chWN|*%*\/&腤+̩K^+*|JblaA,΁2zp0W(6* *PJ>/Mt+B"SZٱ5eEۨԙq#&*>o\sU>:2jXaݑBQWbΛ#3Z`g׿tH7iHL@%J 4;#<!nr'}ο}n?#4b;"fUs6hL&3%,1[m$s:L"cwc,A+KPVz*pŅ+/(2MkQXr N {\pЩ6'Ha*rW.ޢ*Jhs{s#a9@NY/h,C**?ē?R됯La8"'ռX$LvP8r+?=;Dz#qeaRwL+0ά ư212C+@TNF[Y.;T f)鎍vv< Q43#Tw]I(\!P{kHЪ($l6mf&qkM*s;$EM8> 5ګ[JC/~; 6zOY1oJ TPf'qmjQD6ƖO8OX"3w@PxQ]GK)2SS(5 0& 0,ϠjkB^Qڱ8# `լs]}ji&V:LXwvEWrj|So}Lv/0#RMke W]$-XQt5T,T "x&c)BYD]UpY|,(OTYAzBCB> r{O )ZfˍA937=l==|YbB<8<e8mYɼG@2C6+"1`ꎚZ\鴵 tqjİ2Sڇ!E3t5VD_wUoիE{~ 8E5&H!n]d s_ީM-OCԾyl +ɾvh`s{ ՝{Ye^&,Wp_!@FIHy;o7ں/v88CBZ<]f~!"le%]TJdc0ZphkTX;Вs%rѸaI(f1Cq٥7xr +-"tn 9`Svb 6ӹ暛ֹٙ^c %T@@-FFU``_ErPGHfڶN5 $d ʳXdΊ!/2iՑC-]:U`ܨ %-ZJѲ3*]kFO39eG,Q8(4M|Z8"׶*9Ґ+|Vv_.]vЮNP9&NHXNr,`+\鹤zbAL#\ĺ'F yX`Jf'<`%`͍ϽK 1z+!yq #k@E xIefe8$LʠUP>4e" !e8u1;\(Qzlr 9P?cRVOv9Iס^(q\X!M'JL|;}fpQE% Ja'VKFRc%4ux`(h|A.c+b.y6!^jl):f{:pa^ªhbcQTdL^_!O/\] 8u0j@B&E4^`uDr:,JiID]x.[e%*F #BUՍ*18wƗ2,(+G"_@A,RyJӪ~4pk_wm+WlW2Xo1m!147W=%=fffЃT0U+ZSOCM "FB$=Q#Z R50HyR`[;ZX ,"tßW/|3]QuԫZytxq֬9`}_~qO?s K;BR!C+k#`qqjԡB@!(FoV m>Gcol)Ci^܉#?ؓD*cSe] "{0UҞ"[zS$HmB#pY\_ʒ^4ZQN(GȨ}ՊtPu%FDt.\( - hAI,a~I.u3^ [!8XAeWh8:dkb;DK‰5F&S|+PjQ:e '  u e,[1^&I&譻,B,&iLFvD~"V""mpYx{P]OP AWV I Z_U2:sEv>zW3̥$L`̉UD$q ([kW+) T;VG**V V(3 d|B`cAbA ax /׿m *| !b:34=KL T,?ZUX.DBOsAr@ WCH*X,bX*C‚UŌhjgB1 я|F ׋% Xw9-v5oy,Uo qJU=ЊRui@\*ǼΛm0ut_%eb/9B;2wK) U^aʆ "= 0㳧;]o`?Y UAso =z0SΧ>bcj4zG:BRQuNj y%L1nu}MqXx,E-?늼\BCt@UR?*F+.¿efϪDN:mcXY&wCGB# w+ɧmBhh?VG tA=sU&G.JFĔG2rtq"0TWY@ S+ AJoBX?? 4tܱ'WnX`5aBUN}vJ 7Dϥ( 6XwfW/"e!]h>N Bg Eǫ!= ESxx^s~9>7{ξk|?ǒciT?X$vn@ե4v\Kŀx9+l*wsP'zP##PAxuxky57{m qMJC`XHT@U+bC~'X7n|ϟ-mgDxga&9j͸viyaZcIbƅNLXO2ytk=oJe<.^UT T|pOrW*7R( 2(WWH+p]j+Zo"q3hJvk4X%Dy0Uep͍ǩX6*vSrvMDTEm|20ù`kaUW9X`(ZGXy7têR扺 &d}e.Co&ΐ*Ul*yE`&ͻU3XϹFNv='`Q~L \E2LjkkBQ'Ѻ_]Bϻ1?6t˳NPK ~>ZeQ)K}p镾yj/JVǁNO ,{Ad6Xf6Q>.Ax4ڒʖܻǹ#S { `CLrMEtEt'N'zF5Hwu. VHr<'*݋l-H60y&$v+$^XڒF9OY97CmC'eleRlFYV#") U(0Z`<+ti؋|u~5J o“0_ E 6Nv 'SiX ry;X,h+EyKhyy5Smx5yGɰM*03Bǒ@20꘲>L%ypUx>+c;TArAW6ŕYVDVeZ;<[,fͭǿ8ۇwE+'efW5C2:\hͣ;i6=3"Vbhje>? +$X+POf wCHW "UϦHab%zy* 'KY[,uf ږq. ?x_AM&|_rLQ*8HW @W`‡tt=Uv|_92B x`\nSЋ%&]WUzJb/n(\)Z;)Jk[El^H)&`wZ` Pjl֛H*y}Bc~+Sw5#4cQb5.ŢWL0K7MݕTL b ^FqÌJOAukSݕ>ŘG9ܟDT_Ms$'C#9A`e#y+iy~ aB`!)fuBf`uBb ̥РE :<Dz/r̓H\\na JjBMu.;+\ *~[h1:X`X^1%L7AuuE +  iEԊ턄PL v eX.Luŗ7˟ ~zLpHk.LNVuoTQdD̑@ٯccatTÞCWY)LXˋ(9/% oc:zȬwSzvT5)/fhƋ޶{%W,Ҽ?$V v߲7BXU"J*g`V|fڻh$&Œ=K C)^HrGэkE.Ր#T["b}XZrӉU8 cYteX` ZN׎I7w<>Ma\  }SDkGHcl蜋-9|'$`]`]sB(>`x#NRYL,JU9jDVl?~胿= +.ԌqS6kaj5eE\A c/צ[ [ :ILDP7>8ޤBă{yW)OM hT5TT&uW, vuͭȞHl ,>w-R2+zϜ:HШBfS!x&.J6^<sx4X?J<0+1hp2϶4htjl2Y"v扁"S{m(B9WɟOsȀ-kvO~ #r `"ܓZoZsw]7”0Lpb5X1XzW1KsQny cOS_~_;qSaլ<=5Dx^L V3B0~e)$e$cu\U@Jx v s@oLAVpR6^#9S8<6%/F-P^`aJFFZ랬aڪًщ1~bd#55Fh3|<5Wt3X5{G %ҕpE'$YZ[Ӣ%SG>굯y{#d+@.|tDLCddաfMNx9Yg#O7pYil`G@:(ò)ϾrIOc"k- J'<Gc5Q`bw5휎Jʪ;3 @ MFTjlDЊ%F6%ogD_"KoBv䭛>=kJ.t;.Xf]wl ӽgԩpH*尧D &fb>',#] ˯ G`mhؒVfX1 k^O ?.]73X$[8G@$bFj%qwdc2ab%`AqwXWވw$4Xz2y2ܻl^~9QI1 aև>/M׿{.8u1ه f0YQ`>'`i*rTks,k^'a, o'-5󃯦*wlIRhEv*˞VWIoMF4Sh YmYVEͲ9[zJnkj6;ҠdﰎuMR-nESNu X3>fjJbr7zGa%@2a=g`H bBIto |[EuB*Zeкu4$Y~9Th #nܙԶcKY}?%D4 ~63tεF"c֙PZL+0.ć@W!]XS*kqsiX$ul}ۭ> Yp?HrYژ.CVeB5^ܝg=Πu;jQJVd B䠪(ӀdX5A[˴&/ij{pePDo4!br($͌*M5p ~#K -5SXʡ.&JQy.T&S5Š=c.ʭM`1֩e+X9J-fGkA#R`֋_ mj%+`U9<Ɠ#usOֺX} cbpfflfI3PDK޸5q;dfw4]Ļj*ZC>[[0Ux 5! +6"}EURQ ܄8B?߇ @<} ֍7/uNDE_UTQXvy髚`gʖ7xXbQnU_2k1jZ9`RCL/q{[߳)Ŋ__ɾ%knX2M_)N֨"k g撬๻:BG}Dp/zD K[9>  *nv|vvKGо`Aݵw[F=H] t `wtD'1! EQCT3Ї<戡aG,XTSeRKxIvzN B:SHwjx]ހoCʈ d!{.j<>{ yA;duF=ZLzi8]7jVH/No^`gmN91:Cফy3Һ?)UNE 2+9g`qئTfrfKoߵ % %B,L_7%pRn~>:l}CEQzceb{xkMWYq4h#ܵVTxF`}CҢ+kJ.htW/|("u{ g50Vjι>WfUZ[QȎ0g,賸W3jK%]͎W: ۊ@vt], b,-D-[f_+$WKll*Nì#Ǡ@5fIpJ#S}h1/ʲY#Q4ݩ⯼2}gUC·2XpuB{ [tngEWzI)Sy/?*,y5/Z_+LMkV+ѿ$P:WaX?J,2#:B,{`UN/]/"F0#,9325%oYp>mE-c_:.̨M`cA9N[k)rƆ7/'cZ(` 4X!!"kމB-bXDWTwIU<$cw>[n>k`*f ؎4Z#bƑMQGb%W!d,Gu3&Vvn\&0EUc6=HS=s d`YBYX,)BmƊ"]`GAYAX ;!K$ua64Qf77ovIVFlYj g8|Y0֥L"rvD[n0QܵzkJ` "/*|mEN85p.ZvE M[zAf$ia,TthLd"!plC۬+`u[U1 {U6g=+fP~J+>:N: &hXi_;,hV.[){W_}sZ$J(m e5Q9!3ˢخJD/)/9]n<+#j osH}H2Uū}7 k4?bD8  ! *ChZ.؍sG͐V^*6r&"m$.u1(>2Ct8p`K@"n;XFkd)9eat Ɗ fAHZ;/%leU)_ 2D]/r"B^6 -=Vk9Vv6[lMG==WLh%c+{hE& 1( Lw߃`eׁ #6{a}S q1xTz%Bݣ Hϝ@R :#τĺpri| ׽O}o@%NT^>4e)E/GhU/[oS2]&n-&8Qe[`QֺcJITY4J%1zL:v@\eCMU,³]QR\k"J|&}Q \@4?󮢣t~#1q 9oٷ-u$1dZ I]E 0l;%33,E1G! A,\1p]HU3J3E+u εOxiMKY@.j"֊2d|xNb{0WF97b2p]j X!z5sYh]=Xw5zB ,2yamTԉ>fe[FJ:撟0p B7嗿>9=?Z.ts,8Pntass ZˇC@,%#U<*Muő8檜J8S\I@p$+6a%QS]b#8 R cP>U4,*Nu<_ {d]MN rC@vz yCᆎD81pG=K=R0AhҘYmNs(W4-K!:&5᝘Њܸ)yâG. ǟNk'E\jc)`3cЕV̔ -`r HϘsG`L_Ic+<Oz< Nʭ)urp&'*,kᮄܙ|k #y{PAK>n`mӂ7 Ǘ<:&"<K?*A3rAzY .䮔zePbfLf,Kk:ҩ'#0d~صdʍ&Xg~IJE t.,gٹ&ܮ3Rg;1A:[k|{_9g o0gfѕ\wr(l+JZBʇV#w Fh33‰xMpl.x,xN9!1~O]b\հJL,Lp"oѫ*1WAmYgF=eҰnҋ]NMY"#@? ;Th |UxKrY261=$ӀONl>,&p |ӭй#Rb`mȑb'[dc瀺ֳj-F$L^5N=uƂ,=t6jIDCm ;D 1!N&ww#*Uȃ )#yl}teY?-GMͶ~\–}re=0Bpj6U÷^"w+XYQxogk iՇF7=)tEj:u)Fd+8t4";vjߍD+Xx&$cGtO'Bϟ#Srlb] @WW]&h%dcSJa0Ei0i^s5(ޛZ'D:*L\).#&7TlgsDsNu ˀ(^mMn;!B]$}ZmAM&2=q\ڟ, h0#:.*;OdHbFC eQY*&* p÷ыUjXzC?a)eTLfcD3%Y2XR"sCa|A$@+pTx@boE;*D%Uld[NzfC<0 ϡW=4lD=Q!j62+rmqT֢Qa˸CJNXQ`u8,`P7_ǤE D½M VؖpWZ6 рX,ti61O%դN4YZ&dyLG \9֚3(&ffӲgcg^9.gqrrJ7^UPe\۶0c$Nm\I[U ;;*wWs\##w;Mv[g/ pjީշU#(UN>Dk3 :'R]A 1%skҖsK2.˭Bg[U yED9_, 5+h_ ]+Vf_yWl#g%[q:MPHFMV^\3R)j-c265%ꜩE]~8VyڑQkXhLطnoSirl:F& L2Ukl#5?ٽx5EWZBiʭO7 "x @\Bo 'CYp_¯\:rs~I+<)ToM9 *yKS:e{^i|q#B%cW,uН̇X-03+ݖf ;r5"4:}w#쾓<ݒ> 6"@{'kMr^r =f ܷqx[c- t.0nF!hw1np܃g9W/z!! P B Up0%:SZ4ߜqṆ`P=u9`~?AuucRgۏ۵1x"Fv5m/mh\әB}`Z#ܐ!&D_5|O_P8v_O07W kRjBk O G*~":|bvſ{oVacZ * 얅%:ePbQ+&W#uQe! Xw*d;CU!׽uEE)8jjuचڭbfGo2:C<:/"&tYGl Њ;[$E'Y55zL1 +Az8V X  IаpNv+AGfk h)R`c]>.G dԝgJDva[xok~)(ӥ YUxt˯XjOOf8֔iDcĂ0?H+$rk7!B\<{RGz}߱\%g6M45+RD%7#谯c#\~\ǎ4Ik32SΚ?z0`,\ݺyݒ`ܓ@`WV12^0KS_z3Zih he(j;%j9{r_uel G㔉u<쓃X#{jvr zuaVd+ "NyO@Z4X1Pxn#5$;js6ֿ΄Т$޻) =@ ɹhc՝tT۷`we37GWǖ%A.`Lf8?WGtc8<{]4!;y2yׅti׌s#B[1璯erX?/f ^l6JqVW RJ^>Dч,(`m`VhHDU;A& 06 e[ƇOs8gwIUF;"Ѩ-W}/ }7ncG{Ir$Jbհ Xf/o_w;&g նG[Fh& WC/Xvo$yKE9A[糚Qk.ٻx˕fYh谝~PRC}2YQ~QpUJ#ŷ`:Sɭ'tSb,uKHb5$ \c5;sȓ_,gtp_A:0DX׀BIUR&j-M;Uix4zgjibaۑХ(#7kE-8dSH3vc۞>a Oxf` *4=65FMNtOm`] 'Ob=eJ7F;jLe];f B4SG) XJ5;STWjR _.&_oT`ۀؘł%2g4|UI,^秉oZn-X}M U D9W݇֘mlO $jŒA3fh#_[Hz J#NcHt⌍ $d(t =l5?q"fQvM 6߲b,Zs 9ݔ Ē1{266<ݠ;HrP.U)8 pW\WUW߄'1.B2PE\E;K5aV]{?o{ Èmo>ԧ{:j-c'DZ)fb+N)w&g6bK3觾Ͻ$g:b')cej29zƳı*zG&L"Kil49N*,v^6.a9gmZ'USiW3թOFBksz5tY{9Ol5LٯUqr0NMяQeM1)i*A;FvsnVl>H7=:)3ٙSOLQa S(lؽCZ@b벲99;فTreSK(%NòKa.EK$e3VS AbGsG!-u}dd(.8 n ƺrdSr1pt= {\*zmo4"Do|-ox-0^ 爎5:BYCvѡ4U>h~- Ͷ2# [I՝(/6נL1)a?z%hRyj$Vbe*#ɘ9hx@5ԕu@r }L]eJm Z4TheY V3X ׼ (F]2F3:b#k>}y>r1»z6+SέQ:h)ͯqlb%Vyw=gkTi :9l_s*Nj&./9cnXv0pCrD]>N~ K<$"pѢy; iXw~'^{h1Ϫ֜V6E M1޷DzNjQsu[ yom%g^,(5+s@Sm4p0sysAh bqkJHUVxͩmshf[fu~XEQ/~$JjmF)t)M]9B릒ǖE4=zPky׿=k^ F30sOm͈8<˃ER}2O-o&WWp¢6C\rV<׶ #zk[Ƿ%eřrux?UX@T{ !*,z;?@+ G:9T1!Z:N(qȀ 7=- bwG9E~6Z_msdSmZPƥPlZRʋ|P=,c,U$\ B{s!+%=KejjW\*GO>N%Tlk>V,]~VJ.;AqG U67ȩF.Cc>Gx :꯹/# [ s*.ޑN !++mݣR79i`yP*# UbQV~]/(bSg*)15MC;>a #81 c `VPu!*.BȪTyZ w|\_CD(rp|lE xm5K\w̸M[r9uf Eʪ{j'Q\1ގ6*Lu`[~uKqNsV{Cܣt3^(ʕ< dRiL]Zg C2skgjL3\Y>/2[)KմeOk۹hFɓVêO9Xs!%Y(fAFwfiݼíz ½;2y\M/?},JI' &zo2%?S>W>/ÆE&|iY_+T<9W`i[DzG gőz9ƢwW㡎ba"I?5Yl}q#f徫@;\S0wԨ;hp>شc zoK(0"3p`Ϡdg.=]+*2qn(rm?͝;ޣkf`ylYuSsgR3;JWPӞi; kp:w.YӍL)w"uizfGWc˧+Z8U injh,ޫӱ? yjh/_h?V"%Vq+sP-2@J+[ ʏlt(;-s&!({~s^`١rT[,h>??+ug)Z,<&Nܵhh &oly͹i4Xڪ+=h[c5ͪlHn  USVQd3PF_]Xb󢻊X b)Cxם?@;FOyoV'ZZ"NkdoGMv Mv~kCDGb,tס{_>җZb8y*8|J!㷾`=yW>}NW57C4 &۪郪67d_3/Ӭ~[,1ͶOޖQSיy*2u^YBϭt y0m`=kJdS՟ q ӄyW AWKvAn"8q%@v350fC OKjM6.嚹|h4ּ}R>In1s슌X,T㢉b(&#?֐Up z90*$I5˼Zk+!|3a+vB,8;b{/RhUN2Q 7ڣl1:OsFi=OSH=e驺Iz+-^ē+$͒ZX?h`k/v 2r);LUǂ1 (m1X&M_5fdmW5yG1QKaf,荒Ia,]];GT#`_c|u++I,婜T۝Ε-aFS\, 23i5OKO㵪z$ `{lX{Uɟux hW?//'>9bk~0$wlx??(OeΪ<͒ŪNP.B)lhJ@(-XIPbJa*fwɦ\:9Zi׽.B@VAv` ,+֡fP_Xlx靧G0XXi#‡=2~ǧ=U.urS |8]~&,M5}e+ %u{rpmR ]423UdȾ \\!/H+F&AX AHS(6BQ@7%qLMb0ը"ޥN]XWH@b`{ؑ(}()\B̾[1jl%ȣBu`oٓX>caWH4X1)&@o})|GQ,QkS{\tg*$sX걿T,0Y5}c[m6/> C]:ȵ k5V_PK$ˣw|xUݬ6.`|c^6y()G+4+zp?PVMQ=B#HzAXn Y!`9~2@Rb&qi㶝.S$AL3H+ڙaZd+/H/ 2Uj2z]0.”e$Y)q/GG,q',xKe7}Qk$A2sQ!ֈպI0 +/ &a)B6FR^[ 0+d,Ex uⱬˌ`,_ʷ0DL@Қ\\c3LN}mUBh_#O-;)snpqq}U !dt/n߉'ƳTz~f5b:wlGBcJC V8c,I$pl|R+j8$Q=Mgwg2(/wMr *tI11$a{4|, 4=]VdR@׊S}7`}?؜z+XE¤ǟij+cǡԳ;[/QseLWs;B Ϫv" _0+F1dwޟד2-9B}Dԣ~)'UxX!r%SMeh`]i.,? ^+l0O:.kYvGEQ[_>8ءu=S9nW=ш@)MnlEWA}UP * %96qɭ}e!xe6Ʀq' N T!ؖV#1keh&?5Z-oQFcY^:g[޺sCL%ķEkebl~g#VO[wAEHWO>}QjB]Nx-0Xn=!3p`Wt'fj]9˭VB&+ü]N{<49*aro9Joד Gl  aEt|gp06|kwjGJR='K,։.P!ȳ~ſ^ #B83tM-O7{9u",0k".FVz%:%RI2OO ,5 n8[^V$fЕ Fe&N`>IVJ-<뱣7N$Ij,ȥaw1Q3K|U*T|Bn _ɴ7NuAz-l,qJ9k_}(.%VU֧Z23fz#Xjf̍p=Hzիn|_3~j'Y7ɾB i|4XKp2ňNJM/#p.I(I-;EAGbh.[gȲ+Jg^n v4пc< |o+&cPh #b넌z\x} _ՈEoxt,m.*ܖ="'OҨ#atEENRNߧ>.m 13=J)5lE١-cd_E^nD\\&f4m,n*" UBՊI[4!?w")(uܨw %,)@y@+H݃ #0 f F 4p(+"ZY [iJ*^rD )X!`B) Ǻj3IKT@ni 5l "=q6H#ҚewZG%|Q  8] uNXhJaN"Gp2o-x' Z6@H[6CE}BS+6fXaOnͲN`- +o0&f/-̅`WM#>B>f+zc)3de _i8!bB5hy~媫v? UXe:! cxu,v 5K]F8 פvV){KHoژ&U Er˽(tD .of?"tK4T 8 r;/kB,p<'`-pJX+=ĸ§"a-@ZyBq&QT)YG eE`Sh#8rU\]/dB]x=L4!GU5^؝;\(4WidTSq.R֘F!Kydo/^2@m2 u(%qƘrtHQ6TǶ1T=0FD4eLN!HXJ0XvlD]i%|4IrğE(Z6(:U9K4m/]OԶg 3 +Xԃ^]Z P"KWSA|-=P?5wIˑ(g><9 רXULxT,А6_9XBv,V!AGVgGY_>,mee|wr<5eDñ[cMHUMQ jET'PDuѝ6ӱߪ#"ˤk /U잢sq֊-6);:MRwsAٰܵʼ˰wZStŜe![DܟҨ-zTYGrQXhdK4FT|*R*Τ*EnKn'\720g ;rC 8+_q=:qW AJaxthg36JJh(mX"Uv΅ݼJ^`AM$p`DlԶΈb37toxHoq"r$Qcuy# 䨩XQ\wjߍDH,<B!VぬHQւέT3WmFZ!]i`Q8䆬?+iY.k}1>T$|bD-V{.MVPӫ) ]I窗eQYn" ^'ws!%*%,p`L[` .A\!Xr+e8>4Uc9 E >movfGE%z5&Њ%ݡ.9Q.6V ^e~ X\T-uui˘^WꛠzD;3j:XI?n<'˥Q$6.79fLF;b"!Y۝?m6qDP%Qg >"Ya|YC K~agM V7g0Zm`xʓ+1 |U@W ,~DxJU\.3HSPF}^0dbt* #B8yP[╲>èB $rb%AF{J+8_ĔmY.O*>ٽ2*ZU-wr˖1,pK\P&jqIw˗19ׇ:a#ʹy >0HH F'|Trؤ|L g2,y{̙qkfxmF%K٫`h ၠQp_x93l{=l.`†n,0XIl|y&(I;tHHtdLr[l.exZkw맭Ek~L:(ؘ:- "ܡ*t9 *WyQ)[*+2X =01;!7V2$'=I;M~cN`ۅ[^}4q ,ufpp^։҂Aɡ'ʠ,ʂ'7׉$݄~7wRo51sg9|mtSڶ\SYeS1m!Dp'=T-Wď&r}GI $dLp,Occ/JvK?&6:)5ćPsL*iiTѐktRF.ÊvA&D+0"Wsm@(}Mz~ֳ|Ϳ~![1U\½rrjd{4nDmcM}S.GKWoDÞc*"|jZëAPlI,*9gu`o/.K`BFabWGn,uR(vncX^Ԁ19E1_.`W*A۳td?f{QXNӮ몳LI^ڂA>.&!BZazB-1eB4f[T>-귒=J.;6^auyӉX!VL2r4:YqZ o<l3lP(^mLp*[y[l;-(a!x&lWبH,4[M"#a{{s_62k{Y5JWCfVgFpOy[}WAa B=Yhf6N>"9Az&\zZb2NE惡2pZ;륯 k9NVtw9Fo{`HhJmc76aY"ֆdR&3>;pGZr n -B ~YL J-Э/Fj& ObEedlNau֘<ƢXcIG!1R"$'z,vf`ZR[/*˞ 劌/䔊z*|<5M=Vu6$`,ȝ Z]V`ٟ v;`8Ew)ҹ׊([~ؔN=V\_HgtVdP+> j5F{T۠ x̽;~5nD Lm.<C^F0XQn0x+6((qUz4EXtϻK+X*cxRFF:O=k$rN|u]9:7c{2]S&9w_NE=Z$:`륨./FRuϗBli+\m5gVm/w,] ^8;ު`ϱZeui^<[^ŮbDR̅Ϙ2ssn%/ MдU Z5%!)=S.ds0XO~ҿ LS`C}(6<|IJ32F/bs4g6G]xG+`1k-mvODc]Hc]ێՋ B>?N XJY)'X2߇0w2EU6c+զEWm#R0*)td֙)c/%̃Ohb$ SԉKVk-KIg/V`lmV`&C*ez&{,R(e3QsUJj%y+dž<ʊeI?eT]WzkEY:k,ĠeR_ɂ1 aCٛ6 H_~Mq>JM7ޘ33q+[@t<ɧ.J%h]``|H`0h!FW1ЕG,~vIbePWT\&4"Uxf;ֈcw-Qw=${V6;<$6\Tk1]M} ^mCliE OXvÄ.$(\X BRg߭1)"a& Və(<1MMlCf.C&"ʔRXiA  W:}ݵ0+VU6 #o><Ǽ!sϏl0йH5XxڣYH89ɣ&q'\HJD&r_f[*L'~fo/C4j,bSrL <#CL^t8W-h#bf!j&"BO Ekt+oDpbiiO &:#[SX+=q>"&DkUx%br*]+:j-E ]k'kZ'fO_PHb#QF1tgwHhJNT֫C} `UOq+F /-除LT2^?mHZ,SB%R>tfXC(j8rzWQghv}'dP{Dt"=\wk-YZ ;`wv!mI~\p*H0%\w:<ɲuZdIz1zX=_u cXWQS"a=!/F : ή}Wͷ[q4Xf"cAd&3 LdZncXYX>yO\U=gc0NЀ0k keIWmtorFy49RMltѥA+ݷ;{QTFoO|ƙ!^ݚfn͜-Hfq]*@b d/%<$.o_΢+^ N!C0腿 `݈6mJpaG0j nyILub¨c*y'#HډQLl)eUuzvs6'l }rr7 jx8!Q33.ٕ<ȂaE󮼓Fj̃WHqpKXWB;a:DT]8G%ƒ:=jEp~(cRI\_7[`3?njѐ"E{̗)Yy7h9ʍNr>y⋨+ʹ̔BV>y2̳ѱZu9P?AWFMǥXQp` bsq ī$} ><Î[z|~4ljs PDtW?b}~Rv$iq(/z/JsH3pQKRp%!FQ%IA;RL$($3F%ΔF۹!Vfg4Ԥ0lT-K>¶4F I= 1 +84Z&yǏXW8eQ  8d[&zeւKoKT)jT̫ ̳+"93 IS8 ̇?|`]{ǀw0YAԅ"rN;=1s@McC0XP,KG٦Y#ua Nv,ĥ(iX^مpolb,<KE^<"SzyC$S@`5[+0L1 \wf:J -`(+ӛ-0ʻ VC3!z||2g%A]Z>(-@Dh{=1,vk{nkc5YIC g% %**, `$f%35U'jeo`ETso_;o5XQA fᠱ#uw lr\M Dh.Ɠ9Mh4ܱP P5v5o Apu}pm+}QDhuJĀ/nUrnxE> O0dOs,RB"^6X3"H򌮮L'ՙDF5˧=}EetUykSx(OE"TURiFla,L"[ir %N{3ԎrlaTnN_ހ,%L{3K~2EK[9f^frbMS|JH}S;P5>[FU١yU |ZRkYɆ wowc .B,l ̣ &;li`Q@3ߍJ̝RwŸjdaϭHkaqޠ_h2XSq9 BJB#.d?N z= `Q-< 1~/IOyo ĭ5,M|g6dv^h1vRIyy!6HxI{"2?>7EyM }Bx,-n\i[ WGp,rѨ&w_œ3Ȇ: 5Of![1j/d[ݚ6Mun$kvlvIwxk?ÞQ4],quܮVSjn¬k955%?LZlRVA%O;ghpyEnxY؎׼“{y)(C3|lHf  %m1O W)=c`r8[32ї\vjzVw'ZdS ,A%+c_  ZEm{Μ}Qo2WD{$}n&+3awkW:UUZ>CpKWY y;UFJuFQcA[+r}=d|%24x˯:=Ɇ$*eI"vL|B̤ݎ6 j\㠼1mYQ>_@3 fcED fD+ՐAM>kM 59m!2:Qehפ] 3)vn;&̗=8 ԩ[0"җltbBF,{ۭw8goxozfaW_'%D=jf"{kqc&yhcW4@Y UVfH%XQW;Xr]KEL,xK_ 63+*= m~ L.ԬLSf=;ي:~ Ui7*P8ׅgzrM)·n^$sTVzr+|=%m\4o C~+R05(7^M KfS+VTw5:0XxtaIڅp^l QQcvU誑p_JQ= Glݿ=u'L#es=0XZ %`GBtwtl _Sbu-ҏ"ۥޛ8S*dz̦w%a" 6LK z])*7yFFp0DItw2+_!CLRv׾#(]>֕7< ֭ޑ_,KFvTEu>/|C۟Bh+)IUPI-; Oi,-]H֓iKS>*j,yݩj[‚JZ'-IVh*v-HL[Z'lQJ#kf?6RSbA͆ F*uҰ4BoZ}lBDzx4Nӊxq1kr:ƨc gzl@599_r?$,X`$Or/X@+4:r̵@gygHդ+1puH&;[A^2?< :>Mf`{ h0 * !UsG!Vy1V&k>1XĿQ9Vz}s/79VAD`OoXIiۆ/ 9u zZTL:ڃ¬b# {t# -zI_ udhT11DOԨ^i+oc8 ]V$(nDkVW$TSYp1HkX7(r*UZm ɪc,aV=PߑlqmO6Nne8 ;Q0V"TdCSZcq쥰߈hDOsGW^9qnPݲ5Y-c<3+ige8ՠ_'e4I: u)_gq8 rMfQ#F! on@!koC(Zq7I`y rO>75 XIi2TAw4kҊUxDf3e4n-4=t ySUhZ]iaVJlpM/k#m|X?(봽4Řg` ɾJj3FUW}oX.YXlI "Xi,|T /)`&1[ḻuaLd=~j}K*vTc)khcd@ E*P#B$" K3<#nM:A sU7!;BYL ={X${5635Ly~6Ǜwh0 +X痽G;ޒgJߞ!=\q8,js9?~۷~|ǭpbDx\1s.sm8z] ESwM&B4Y;o_kƎ}g j4iR'\aTbrvXū涴v?'HwvoF>ɆA(Dxi p]D 쁎-RLH-Z c/~=ԓ#72+@w\^ $JY)Q%.\ \"p0'.;>pn%qU $ZLffJ HdI*(;U-G9PO>>Yaf;O+ \wr|^tHK1}6]ӽiz &O4VW i Rλ <:|i0J]^%p,nлN}p7Bglu*/P O|xpHZ& Z\u cən.$9 $;`n~1zlItdcWho3D( Yjo[TI-H*u^9=odnw m[ţ^Bj;|Uu:XfTMټ/Ktqn/]p:rNI[wHZDTE:1K{<-pwy=T#`\s{@(A0`戍p?R"|nGom$#*(QU8b{>zY79:YpB#{&c2ӀnmkEt|Wp06|+\hZe7@_baPڲPɟzoHr{| b@7Ùcشj%*宪 S.?AM2ܨ)<3=s˹mA&a-欬m<]TS:=.P}`$=׳Z"IQ+߮č \-*ޒ~1Gs5 .%HX=hmny=D*a<]Z@([1weEԮHz(Q7B7j^$1P ɜ>|xW-E -MN3WB]t% zJbbasx/7v8ySe~Y>8r+m`̓bxy%BgVn;0*q$)GNKv4п@ňnֽiCmѼd]5>;sg5Bnn(< k+߇~O}H JwAu71~wg'?D[.D9_=״[Kp/WVS69mZJٕ._ezfB !CՍpek&} Ϳ[6_7QQL3} TP +-TOr(n&hG+ Ԝ%3I5b @H,t⏍ )4}, 'GE+V*f[M άz X[0(7[]Z?3C!t hfVH;'p_% LU%pGd`C=?pb JcK|2bK?w~[ys #qcC:Odm.]-j Crw%-I.a#нSR>1⽑dِŅ̫`-1dQ1{'3q_CfifX<255怠SfmW+ c9ĕ ҡzX:n$r; W.ϡ#o0Ţ#.qA]jm{0:wGyww`1@b+J'3 &fU?OP$>_ "Q,bLeD0.6T*zo^VPV+;Hٮt̏!;@_ ĜqXƫֵZ#qh~G5_ KdnT?2(2 HeExatؽ2? ϝv`@B=EEve_G |nԐ6ࣀYC֒Q.Ik{LW{ۭw5)+~s4-axE:"MWyįOzzڂ GeKšXMUEt*uXjk7~BF `w'I&V 1H޹gŤ_#j""hđ`kM>r,/6[ts7 5~]o*qVVr>>[!U QmE0[K/}Jk\dqIձ1nXR=ſ,S(eB' }䐡± 5\Eq\(E =s(MzQ\Eh%,{`жG5͙iuZT2~lTBAvXpm%~+!*Yf 4ڌU Vfg*t6EzfYT(D1wŪTkh+n1ϓ&WHCk8^Y`BX,#F ``ʞ ש,yW]tGbfɃ9`VܺFI$uy9$t|n(͙!Çk,axwow; S^ɨqJ@EV3.@\-X{b.H}P+.,|9ek _oJYpTu;<84k1}T>+)O'^%q,60Vw圶Z/aAM8g3xדlpeMOoNXأ(ϘREQ1RYC AW*g hrGa xqVY;7PS_Av9< l8 /S\@*`(hꫩ}e͆3,r\\Ά Dw{jO=%⪭X@9:4}>;Lt[T?FnL򸅸v[D56zhK 2ANJo;;bl_ڛvK`Bn41|'i%e5duhx7"j0x,`=c`k4{%jX(גٳm VDeb,eUch13hP8/;g :+ӱLԡ1+/=*Q%gcxu 2S\ sâ_ƨ wYdwoo8`>ms(/6/۬PRG>r#07 Nb4x>+4 !X`0kׄa"BRzVZV?&3k5XY0{>UtkE c[>BqNy&BCv)dHh a1%ydN |sb)\@Wi>\v kVESɁpz':O_13qtĒf ϗeN[m2|6*Յmis䧥s㊨-U2'M,24j[i 1AgS ;G>ir&S17pé_?bԟJlVdU+g”X\40'&#),Fx"Ab,3Af* Yj#['kbÓyjvBRt  d亪[}K B!Q;&X J ]?*(z5E`#~hq{*3K8[",/Vݒhٍ7)}͍i*a,\xWY'nFIl2m]7;,8&W$^\z{-f"b8)d)n GY~E]:=Ga*K4-y] ƬRH' Rwlwx74{O|cbcpUp3{K¢~5kˣ9$U:&i {x ph0R3~Kh"jbE&vd!Z₅^W¯ЏM`٧&%ࠂ%XHr$YOcv7#Kd7Mw@DbJUz>g|SկCwD8mB7s gspt 1 f%ӟKnK QgZ`”@+k&a <1RMI Cvx-`ac.%Zg|;m[Cn􆻰?:s./xӧgq'е{;P5"ǚV~5L ~H7 7F3kMQ4_$Z fu^7Dg2 tVQ,rC{>m756~DSɘQR3WJw9%qGW"|+ބ U)h2O@(ox?^T%N׭~%J, Nm.Ƣ逤qBlhqL8^ć0"V͜,唬 yt}`[z iA>bXKD\Ԕu^tU*#Qs:̭ BnI%-iȣGJ[*5< m)Mļ-CFN |OA 1Z-`1Z`ĀQ+)S 2@jnT6DS#,G=;xԸ8["5 aTجnw{N f_N*p3a.V)ZAsA=ܫVLh6ZyS,QGq nJ>ZnbuҔRMa&V?~1 ::]-'R&ļ\Rxv+EA*S։%C޺gdIpRk3TNJ(eK+ttsAg `BE'g4+N]Ȩm*5%i|fÉ{GbƏΖ"7j'2yVφ(!HXTxDFlHn:!*D~ & Ҡm៤/( 춠,`nsxm!Cmaξ!LxnVP--,@Q>"\)aJI(玃|hg=P\S$_d9x+n?|D?=+9/LءE׿/Yva oKb ,tn?BH٘n~{`~E\K? 0Qӏ7:qj WJ @W`!4xNG*˰䝻 5?8?]q@Lí|}>$ʲ*8A]+%JeNDH_rr:CF,7gCM.y?jEEcAK8Y&E ?Ȟ0+?WIn5%xϮRO `|*NbD>? Yۀ_|+@G0n+7k4DyS#tR+Fz۩bw[ d]=ssAō`ztb#H$<ʘHbi=~ [SUXx y>Y Z+}#d ֈP˜vW#u^aԇ巚yi2 (V9lK$XUwVl1\AsYn%_5wݹz}Wv?s_qm#6n|"KEIHhHYݰ0<@8uZ*m1`omAk8C]->?6Ug1!QhDX`4&b irʼnxF1pyϾ ``k?pid~ |QpX>5XeOV*%(ۍ+rsG" fT Vb +c]ylDP(onD3!qM؜]iXVPu@ՂT`ǀw0OApȁ1M7O/.So!.BNL j"Vqqd{h'(s0Kn;U*5KFQI唹y P0'[DG󕖜%d3Qlp;ƌF^@sA_!`9_ 4}ZzE 9ǭ9IvT)$b}<`35vҮ ջ3 z׃Yt;`)]~aKYoB8@.wQq㱒 3p᪓>]O]IY뒊#Z38s1"z׻>|GoD D,*LR|ef.m$6!à PDdxNtPG(lcByJc?-ǟ#c$MEfOE ]-<7☞s&R53n%ӿXB֪NGh79޺Pn(Ss7.T&+y>GTh9m1bFU8/yQ:BNNA~&Đ[o~Ze2O~?1 XUz|+Swn +=?h*3JWc2^,ih`:<< }+UMYaZԳQpʗU-2(BH@#Bxnm,h)aTy_Cթ6Q  hYIf?\{C~ PPƉҥ. CICeI_NF˦uq*ǔRfAή8؝0mGl,gRK E!Gq:a2q&XK;9T!f,c;dJjpsL C-P}i5oά}㜴 FRgr.o?.PKE$К<^V{l{,4HX$qaZ@f l"[ , =c'[C]$gEIO ͥWmlAc9N/2sd{D{xъ/ c\1L57̎pA5]S h${O9J 5XLWzD8=3$b0|vYp8d"nL-SΌ6ZHYSk@NOFrX*I`G+\x1 S…`j\.)yI }课X`UG|65֍_<.4"UPg]Xq5sخd/'&t+VoWg"HI-x@ U[T}oyI:QyIqGM<~ X ")XXû78giŎԍZss0wlV (P\+ө:Jhe+A9$`,y&t<,C?.hRu.N_70L$kgc7珦rhbl.걗DUD)XlDi^Pb@T%JB:,G1kXR USLT(WXyumx/OYjAK,K34f$ h.S`AsrίSU%fuZ} kkG_-C| 0;UKTDQo<)g2gՐX{؎ lgw+eSA٭j5 tf,T\_ ,lI&Fګ$UБoc[@YYCԜȇXɪre +W$$bNMT,yNdš:b0p #2"Y9'/G.PQKrۻ4t8%WpZph̪wຨ:DAvlSy/ $iv!pϱITgsvpyJB*~&('&KXaE%*!(`qW|Pw%ԠIi@=M5n8dH`Cs$6 -g%ҳ8w][k@4?|EbI#aLӅnq',9B*ז`\ȏTJljDŽl-S}8YZ4 +uo]JaYzR) *!FY!Vysuibmj2I(ħ]/6O;UvP(䠐;pzjZŲBI?F6Ea @'AX9<8I"aW]|XlzgX=a%1WTwRVsY;H݈zh!Jݞ3 }dDX id%L3tPʜ nP(~ Jax^5²m f:WyhSNqaUKo$+}~PW4o.;8`U_Ќl0!4l36t >Fӆ,I-%[a3ˆ+_f#K Z}e^X\T}U ES=G_S0sA:b|h+urPo 'E@fĨ%6I}kW~ּm.{gRёmic-! _PetZ7݈YSq4"MNtn*0k}zA*h5*NDɛD693#8O-||.tG14 v=FW7JJ$qvRwnj1]kiiFFwuB%[d5v>/w1gW|,YJtPviK "u-$x)Iܴ@W!]W'UK)#=M72E#&"]Dbgqe;oFߋŔ^m={P[BcG ],e6e91[=sOy?A4.UR Bt;BE\`W;\7b},jJ1&o"#}OּUWf zf8S'VtEmJcŒzdRC>.{\1X&we^v]ФW,P|d01ik6H;ܯN$JllH8Y/""8[j{ p[r  aSKs {e@I?/G /Jpo@gP$-W)b:TV/E oߕR{ q`AH)U+X¦X}e1 9h3D,BGze6H)R5X uR!bY-C-f&U0w/xѸXIJ.B\]|IDvkuLBt_=x +%鐿21!~ydD)6^:lRܚYK^hK"<+勌ݵng)lPFA32%,1T ϼN7gnRYgNY:+!o 灕tOA@D ÊHg[}#kt դ/5"prM`n?Fn"s: 58*!+NsSrag?j eebY fxVj B8.dx^7s;\v 1 HrGU\WܠՄSÙ+QX\[֢Wn]nC$(dƬ,o5rJh0 ]7!2u@VVRVT ^GҘmQ}񜴱}o̘&mJ8"TB(fS&5`JhҢ jnR*G]~ݺ2`AYR4,h$#¶1FrV>"9hV^8TbFr;cti |?`[5׸N&ua T!(Z~eJ9XtxA:㐃%2_.G FHk)G#ƒ1QFu\BÉ`JbdwƎ5kg^`~4#NtE8unOU+,[c"Ls@ΐJԆ|TuVtsK6>da{~"gџS ( * s>|FNKzCP5 0>sK1ao|fP C:XDҬ*zmynn#{jfEjM X,Ī2 YK_')kHCYvc@neBWsΘ>V-:kjʇe}Sİ4sUCssì^:GUF`=oƇ?Mgm+~{П,Ȱ#BeYb(c2>6lE#5ۦnG=FTU=4}]g)qM2@+(g fpkDŕbDCr!chx'iޡGdFh&.O/CKѺjLYpi?볞9 N,XR8cM|Y, Ū[tܒXII4^Hw@y+k;$yMţSyqJGaqk+*p`鄞-wrXFҒ,L _.\y^p-p!æo'N}O {;!.^;WcwGODo.lU'4f#pE`X?D&h 7&[>\'=ٟ5S4_oG2qw:z>!WA/UBQwUE(ZeAcR'h1mԫ2]=pdI%Z&'e),YgWXf.<č7[><~bJ岜.Tf2lCR܊s_-H=TX_xV` GU h-rmFtԗ+q}57\oSOUo>/mL,T5(XcƝER VĔ|PbK]֭;W~&+HOyecAYYk mvNZ_9G܂M!?OzxB^"hPf-\怃8M tYf3 lFofo2JmtY"ɪ:<އpGDx:•sR<|+x˴f,s|W:RF # Ȍ y߾i|6VJ vm:xzF}bp=z^s tF7Ux6fcL.[D\3 G(:]4{HN\ޢL&'G(2YԪ@膨m⠥= `mibZ{"PḈ aE2Xxµ$5VṷqâʞR{J/Vm.b̺ .g;!F~hj]l7jEm[~%.j[qu괵rWeU֠eX jUdm&{ p*5$*%9(`Vkz]r[&y4`݃> bf(a/TRfa(]0:! q&A1h{OSֹu: `yww/QzPX3+NNQϘ-#Wb,rk3LՍ` "}Ҽz,hDjxyK_~PuqBJZcH9N?a*V撬MtbѣZޘSlwWM*ecd SxD`. 0ӱQBUdIzbK ryb8@T`WR2VA&F8 LŒ.Bs,d;/`8#BoRwPN40N͹-^xƉiXGxGZ`~b2l+8em0`VzhtMҶl5aBX"f !;듸8sw/eM-X{іCI6+t +O\y$ iVʕO1xZ}eve RHc)2N𧦝mOZ5ؿo}K_'_>[15XT)¸ @5BF{dhcUhǶyVo['0 dQM-]՝ObV [ )_Vlhܱ &*+X[YW~DHGAuVqfB7tꢰrUcwHǍivܕXa=WYpg4S1_՗`L0&{8=<-O$//5/ENG\ oNG)4: >9-G0]᤹X z7ͳk%*DF7BY\|f72S&6,vc2Cc9XG̭UJm1ؽjx@x[Sq /&:Xu›Cζ _^Em=|OF,f&!D +y$W&㌵9c& `kiudc㏘ z~\4r FQ>6`H@EWnW.qEGg;\_?K o?/{,Y羈](ہ  UW=}DWU8%\TD*Z0RX0H\hƯ!?@]>7Rٍ HEN~^,vI&,q+wNF59޴cX 0"LÇ~b;2$:"zK~tw1,`8)X1mh~2cm<(G)dM H!V$xWhI}_$,UK!؁@r!gF95:!Ҵe84s!0pYfpsά<+\rU&vtXpL!L*04R/_Nӿ}A.klO:ڱBL >W_+$bVӈ$UU\1D -kԗR0),cH$S*TZ0oyrZpCgPh\8<9/tXEj`aѪo |Zt ۥ]BP}iz?ʹ }0d5X >Y1K)>s3&Q@|v-u޷R^4)[5+jvb]pu 5 Jqq`<эʉk*;W'H!ؽїJ/R:Sվ E\U򗨼US,; ǂa0:63XtzV&~1ASvFͷ`}?g?c,`=7`ca#܏uL <}ck+?OV,,u #~dKO3RNj4raE]C}Yc_`eUX > ߥH,"Z睹`z'oXFdX*56ZBZteF^0OaӶ}iFK# ͼ3A![iHeжl0S;?25"xԴh%We(M{#Yz@{)!{S|"ptt :?}!q,F_eM~uZ@":Mm!y @0,b X3\KگnUS(^(ͧF9,šT nmTn!XvI Z5ޞ1r>2]YY*s%XjKق!/ۑaGiT5XUEImM~Pjy P  ,#fA/G`sޟFk_lSװ.S [^QٚB (BDuJ*x3LSoDxM'^Ӟ zrRn;bA">apT<9%g:4"D[V"!4جuZLV X5]D4 V)ausFl(e|PmW*'pyfx';VN|DZ&cQɋBlBy+t:Nb!'F搐^h:ŐrbXf*>8He@W RuĿ}T53A&i_VEu{mmi|":1he,sPG77 Q>h4ZX SƿppA73Fbl@P[k<S;K8gsT|=gV󩜉vpH5, B}o$> ׿=4*р ^KvHgb)HrH+x-øХ.ylЁ6̪X|p^#MVq)cQ_*Ux.!ea Y`y?*j܁at|; w܅ne  =PݾUԱA"烁0_I֮%2]@֒vMij{KҾ1: 5SRtꏈq vb;1UnfeWG3b7g6B"XnO}3HoGܨr2-˳kB6R!Vx37Y[ٕ>G3R7R4D|n\ࡧ`Mlp5׈;+-IՎPAY% _w^;4T = +StqׅrTX$TqE5?>4f4zPd"\55ӫ]k̿U_x+6'lHHAe@Z;?* KT7D\51͆C;ZqX7MbQ1Z*MocV|eIo<ƼشS s |p#G7քp`0ֵw̦wj}vb")'YxrwdꙮBFpB5` 6(K̊")(R#ږd YQOm]5}%:2{[礊Y:T3ќ)GS++(LS*bdbQjLg0&-bk(tr'd,I"wJa#TGh5_V*}ƴZycIPgj"kV1)wy>Weru3F[_>sgB~޸;5|v^f|}"wDX#wX .BKpn"*eqUɶ5#X41IPncZ(-@ d\4*ߒiJ(%aV*:Z˫Q(***O !c .xc ۰4nJuRU65<[cDuUz9PwƩH- >#B$Lg0dR=]3t#eT9lVI*Pouf ߌ?mjnC%h $~(ڔ>85IYXŔF56fdz/x2M|#BlWhvTUYjN a>YB/DKcG;VuvnܚԎ0;U1K5sKgwEzx麵hOBGqa»唧XUc5F)H': GᗀJ j5e_%g=oW7QOjXzvb1kEй.*3Xf"hY(yE8J^[>plt ĂW.sChVL TwZџ&qn;*6xE1L%#R1}:O#r`FJFH''#UuNl$3KM[ToEEt+;WbN6E\k%0s3mazY:P[/YI'20X|wYr  W:l0N5. Z+nuli)ѓ%GInR+%ĎqB@FA[+2(3XcIZٝ;@{nrBpMX^i`|]c;JAp7'q_LILf],\G!_vFWPB^a5hKĿq_oX;$:&5!ݽSBji(USzM`rl6J5.,- ?H6)C^з^nu':[}T[ >oGo]H9*,fY^^)i\ME-(H>3VNz+eQjȼvA'X\`^Jsc&&UB4~qpXٲ$Z}UWA xCX/B>ERfZ_̩sM([z/MρBwh sV` IXU`])h`xog5K]ߗ;JNYw;"w`!՟nOmdJ6N)}ṴfsKlUrV+1ctikUNfC2~au9*NCևt+В!j*K_aR BuqҪfX.!i8kD$ 9t2T|iLh5pK+U8 ,zzM0x#BqM­ h)aT#k\c3$~񳞞x.|oA'=E?MHSJ"!PWI[IFZ8>Y=B](Z`e>?tmX×պ`Et³-F)Cސ46OA ۴-H혷:0\\* zK{9CqVy[ZmZiUJwnH#a|GӀ!r`0WEsB8S7_} e$8"Tr~UMCNv\ˡ>%i9:AX@ 16*I=WcnHht}24WNZem{H堨uuKǀj\`Yq=lk5( w+`4d6m2ZZG' )Bt2* cZg-w.e*Y}:ĝ>qh ~= EjK;~*mV)7^0I;+aIKf nhy%0t@mɡn=Nӎleȵ$ rDV;+#%xUصfoP"uTCw/~wQ- Uzǁsۡ&@,kHjkF2Թk:AF^ ]#FJVYY&y70-5(+K.Cي8Cv5h$>c\$rGm0V\Ņ0eΓy` Z Ēr#?,\E'R5-`1-P0ӹkI!T돍[VT!K;f=& >dײ_R8iQMu-/Oo¯b)NںtI2[ [{>(Dtyz^k(x,y UΦuvk2.).Xn.kU B`$NJf^*W 6$=ńC|BLH,d!rO9:? yhO9'v[AWp̥BNK\圎j]+7:rNع1j{Nw'V~c]{80A;R<:1&'S cr t%#:B$u8, ԴBn65}HGsSqa,:L::rek%5Ucd⬐`|,)١fj`/*cLy*t`#ᴴ wN+ŮCF|>)-9NCWpSr\1+1:Ȧ:noTVɰכG_Ӱ' !_ ;#Z7Đ$T:*|CJQ;`[!`R:JgN_^3q#n7F:,KpЈ֜s(̇$R5^@du7fHuHݪM9f[Si sV?j%Ilbz U*̩4J3Xz72>?QՖf8h&nmHI컗$ Nji=2#CE3aYIK~aZ5kKCv˶j?;W]Z!nz~|Z=6e&UJ #odv.=k9@  }3amVHQYP'Ю1Ukm|\5D`gXP&B㎟lNt|?!}NݜqDH/@v< Lj4JwGv:졫vdh!y W]G}~Oϡ-aXLsFXЙ*8Dt{,rUF'i:|qJ8M;P^5^#p}L,h0$r6+FB4c}kױWCnS@F5# yhxpkA0a;Dq{TU%$!@[H3K~ 5qئVQy(D,YnaGqG7<#cAn7L1vx1&7E.¶.1cMV;8mQ+'s;,PprkB`6xq?"TuyN eHWِ)}4e,+h9X4q4KDd vvg>'_CwwW}/m-|V'j-!+!*q0fmSࣃ~X G!j;ߍTwC>"HZĕֲort[BɥR`Bn1ߠmJZ-Ͳ5&?gcxF:I3,/60VL+0aЭg'R8/C{;=hpדUYYi)]9zm>vw b;k>.v%ƪN\Y'oWՕ+BTϧVS:fCpE #,h7k,=$wdn$ i7T Gdp̭׸@P%ń_v|,ZL$,U: "]ՕPzA2T `Et|Wp06|+`y)iwHl%njK_OEFɩ5ǔ\!td r֜7Q)aS{gTNW Qm=k0ic44dB.(θm+ y=~VodjO5˧I!ZBR U%mޛAc$d3d,f{lBľI׎644c}Wڰi X~%F*`<詬ty"rԵ(buź44ni㻴 N hP-,*mGb !,-l|vjz(TX#1:0;g~Ppd+q%{G+u?)<;7/,X`5^W0XX_}Iq w~? CWfISH%*ۃQ12a;˺q9<7VN+j 8$b`8}1_cL <^BԹp਒s=.*\<'`ҫAnՈJjEpy]4{>>w\.mp j?y'tbX-ban6Os@]KoEm r'v҉Iŗom)V̡yPS:'P*KzRj y,W6Vggߝ% حMשf`*geL(1IxBڅb679rF"[3&}%/k qؗm0ǚ^iZLM-)l>}\X0㑻 7?OҸj5٬TJ3XSn4e n\h&(? te[d[:5Ws kA(RCN\f,j * w+gS%C4C.\wq}U9`yJ v cYF~$RCmA-m(,9%OZlsDA۠U˪rw(j/J9`qx`]SpuFgg5BnnPBAόC%L%l!rXC8wI\ܬ'Du*3r)>/T{\R ?;04RBh%Z!H÷ŐUI_#PAiCc5x- )7d v( pPYQ%xhztX>1<1Xx|fbM ,fF jXS"' .U -5?֯Z &N.*R;!rhyuiZ, laD~f,A]{z$ޙ8L4,Yyn>a0XL2l?14YzEhd+l=4n=kWyq+J0ʬ4Xm~.dDhs^{ =  Ab%۰ЋwW:,*rv+xCk(PMFc5~^ 2;URLQ@I݃~hz˯;X ʠd7%9XtIo"gnA;lV|ú0dיAQ KoCtlz 9bP.Ź$g4jܬ2$8.tnE3wN,_E mX~H"eKٹ"޽+[Ϝ6 gw95)޼2 z$Vi/1+ ^ZQD\_Fca+ߒ\:hœ݇`'`dޟyW k$&<5dXNk&,k"*wU -,jl&wml[R`D&~f mЕ7%<!KӞ zrRn;*">*vy'.v}*vK`0"FLl>Ҵ{ [N 5Ȃj$ " jyO(PGuƯ-Y`:s@ ɯN-˩-b+)|ʾԇ5 Q#qusS;NUee]S2XuX̮h^eiMܒt*JXӏ W, .Az g4V(0 p^ I_`!DCzݝ:/C#am[~~neRY IΩT}T ((E} $ 2 "n~]K! Vu{SZgպus3?3?aTcV ^F]:56$%Ē? ܖdנ{S#NB0Vгo Bɯ `rQnB홪DY<W7A3}5X3ӻF9{H1x"&2I2k~9ՄxFdM=9+"q cԮ3GIc5붮08Ri&n3PRgtҲPмˉ(ǭQ^f\,M+<;eF-KrѕBZ:Q'=J`yR~(\b+ @vU0i͔Ў>.Kv,K`|~O[ܹ%û_Upo09QPqeX`~l9'i(7XkcU"70vuP=ٝYaO_] OyjY#BPVބǷ#8=Pf*U;VnΡ#B{ RɠjJ晱1;iEMB{42"blō~c؟;ɷSiNbVb=(w]M_M*6#3 ȒSs-٬BوԬ@s {JHUϭ9eM1, T*|w2q:)AĈ=<XxRP -Ť9V6Rk!rW_ U9P&ӦY䎏W{ ^cmVvuy\cƘ.k<&CUT:#,;ZG6+|!)ɳA=i#w hB]N^`p>UItRhշ.GuQ/w~ YpO}Յ-g".xsWqR﷜vLRw|j9N)\jn(-,ǚ%tJv=37%`; "S/ȬLi5qrj6., gCksFQa4d CWy"XE[)jQPCS[47%olپvJ7Ne2`|씐 Cku:2J9rjw?]6lgO*9cQĶN d(25B{\ȼKрEU52H,!=3#O|sƷ0""#lH Y íÞ@\(߇*WǔVCMKL#+,8;Zf=5@Zg: \t! ھk%`,X;u.9;>!6 $w`X!_Ԕ,(k~;4XdD(V"LREZ.XmS]ûbh")q*g 2龔(|МvX+zU`k!7Fu 30@pYٙC۲K.QJ^.TX|p$(r(slz؉ܿo_ "Ɍu5"ƕg.TĎΤo3 /R%UrމT ؒEaa̩hpUhg +"R`w"1 #h;ȝt\v٤IS{, ZG@b}[ KɝU` "w,2R "-#Lz=+R-wO `M̭Ѻ+!Q*mWGM<[ϛiX8o8#lҧ NU1 c `VPup %iXT侓XњgQ^hf+]`|>I9\)#}`S*C9XLm0%%"qg*d'._Bh{X=N| VX4K<ciq8r!#ƢVJ`c3)D;%WW(ʒ['g\7w>Y_?I8BZ$_oѺ[C.}%9qbqAWXfTVeمʔ8@OҪ^oŽΧ={{o RA-a]Y)K+ O!iN@u,X+=JHg8]벿zo3XBlY|጗yCmiYjHVT4wQXA5dH(^Ҡp3̓Ry { `, C8cMӍľtn,BFB3%440U JEQ|:q;Ptx4ShZZP٧Bկ:tS^z=r RX6%1"\J Xֿ5"p}eQi#9*Ic/i&5rLXzXPHi`:)9ުZwy]xBVcFfg*eʇ{"|Օ"_wbj=MbI*,`js7bKf'¢]K>΁hNkSfPH6^o}$)<Q^'w*)ʾ; ˆ77\z;+`)@+L Èτg窪| YUK%fOBZ DU_ZX$ ɌWFXC`uՅ5eC*Oi_+nl3m'kŠ4n vtsZˬlPԝO p+ɽ<ґVT|ݠW w52aY,-Qt]5 UzB]rZIU[H;|!zft؇ƃM'S\eSg vXE!{}rx*}X\IɆ|PMER՟X܈JQ:ׂX_x^wf)8=7%Dxzrb"oP){^Idh {99xRG3Djq ,A@BF띟~?bnتݨ0LKi[5+Lѡن Ջ5SnlRq&I)םԄ܊`]IR-s 誢K[.x MNL,O07JWQ)72B5˨l>!kޢ=ؽf͊0ƻsVI+" |!%,}!ʙ}%SycQ^7gX\KqTKK^ L}OLqo (aLGm'UGT#D6EӔ .6b 4XY_ sP6OBmmN׺SyAw8!7¸tkV5"o1!G|diJK!kH9wsV$zYj!Q;֛WXyu; #oOE9L])&/~};6,q2F=`[[#-!jԤR_R?5CtPOdj{rERoRY͌mo븂tX95GNs ^rȹdɰgξѨҨr,X*p)Rp )YDN Ykb3,R;!RܪZ1.TuюgxR `tƅx*ôo_؛o*V fU6`ʻBobtZ8e&2XSFu rJc60kF6|9°u2A,Vn}BsdAg rϔ26ɰ{ j'18E-"Lяd4t$w#@kUmjV⯎ Vn.=;. AY2,q3ÄA/Ь`׽XK}EtM'RO`B64^.[KS2;>1&*44  d>Hw$K"%ouYʴPEr8I>XLSazgl#*P`c# \2a"$-|ivG_|A/D{rUTōb!rr m4 =&)k *ЊhsU'2 ЍEo涪 `PHLCƋ☛Ɉao Vs1ID2tMJG3[wo$YŚX:e7[16Gd ċc|JfWAE|SK*uIvB|nkQ WN7m Uz)E(҂V^Z&si %#16Vf^11w_Be`eIiLq%f괔 H Ygkx]U7yc({ň|77]ϩhC&//_Q#,b*I],Ɲqe=AuWʤٚ 1VkBkG% d>-4gvg]:r @W [ A 5_ZBGg"m%;+7`Qy{{tz% Ύ7s)gW8am=Ou`X9t3nZqtS *I,s"sQe!ₒ^uOΤ>.?(Z r_xT! g1{ F9gQߊkkN,xMl,ת/ 357 QJ(V^P#,& Z~Tv\CqB#H0@WK x Anx` ,|,a[`D6|݁,PWab1MrJϡ2wXI3c#VvQGRjK<Ğ kh$鮤Ic^IJ콎dzSggx OĆ@Q%tkLYE7S ߳%Ys單?YJ:5D^d=uԈp@Ve񳩵 .O01L`!_`-ՔP鸸/ V ,s+gJ[CV"} _k4X*0urGlvWK7sMJ!nUp:":J6_vuyV`׿ `IJ3sVFK/ ՄK_e>_]X}m3ΌN":f.ۅ^`t|I:F@b͘2' ooXC>躲pUTt1Ydr"#F~T9.̶BjCT\Tum,"lBKPAV{aZ{zk*.ICc{ qirVxtPzu*+;WC`C} z /Ͼ t͒|ՠ?*,XQţKb:HJL\vO1v<|2U.A=q2܇4xma/XPx.gn:C WS4%3(0zvByǻX86(86ՐX,#~|W0XPq&1cQ;Ȼ[#*Bjis[%mD`I^+W$7ak:ZCVq : k0XI9/;"ӱ'_HqZ̀FD v2MB&]3q:vEzϽQCOsvz:H5s@p`ˢp28lz kHB| +XJhBRDXC.+S }O?OVkC` cIx)G3T]'7bc{xLrX/b5+S?к!X]b%s^|`+iˆp~feWVpTQ1`Vs$24*Y4Xt,.FQ~x/r^nYh#++-TW\Ne8M^8Mmھ0Ȇ 1NH^n9\$TuTeie5XKQJؠ8SI % sQ\ tM8;4 < gx'im&5I&jExZϮ7ٝ(|.bqt6+ƲJAe.D_5rG}" zÿiUi®{E( $E TZ#˾DLgcdZؐDdnygHi6(>Oy54*<ƒ|0`MeՙNtgE)k >ԈpVCEf>o|V|ҵnN$YT{scwےa;_ YSY#Ct8+P&߈BW+OT"ۖ@(FVRvȫ4v`6l, [1Y%TM?ٞ Ʉ@a7,C Bw[v!F;x&BRycUU5pyڸ,$! P-C,3+aMJBn,2PWe*(")s&27z Qq` τdП C?"̴zs]6AQt:Xu珄ah7Q6cC߲MVq%T <Ƌ(1aXζXt.%ɘit2̐+(! "a ?FTEKk$eeKЊSur_#y;ᓊۤv)kDw3 Vpn`:VxMtE!z*Gc4ɍ&3xq #\$Ctmy`,sX}X]%E8{C P;\&2S© Z5 ⭍%ָ3[5^U5y"cp\%U+Pbyhτp+pTx |U@W #)?3υyXMxTSˆXd##_˝~VJJmTk|Fnxs"݇BfT;,Q#-*UTg]t%M1m 9w0+Ɏ0VJ񞔑Z5 ˚y=c0RsްEs.j)0)Jr3VS*fʛQֶ]qiΏ#L'^t_;.8 ۑrO~p_ugåWQ7*7{cA'Fݥf@X ZA90VL3.ވp2ڜݖ)8)!8Qp;[>P x`,eJbf"rG]zdJrxq4J#,,4>Χ?m$S;x*ߟîJ*Mʱ`TSQ/͋&IPYq1ьoL>SR'êTJx;}r3Y?2[ |44$8BwD7 ?uE7i 9[WhԼ=zS*c!cOUyD5K+#< '?bZXRYP [`!q!yxNKmɖVFӹ鉦s=KQEV鱳l#SW:Z(eyǙ7uIr[>o I{jvK`BFabxӬ\aBh8z8%GWAx} v{|C!9Ue6x:-жw&;׶৩$ )y)Jz{uf;z{x9pO} M$XQ"<f˛u۝xF`l`qB啗\+ġh]6`X3{2Qq < nG,6vDW` N.j2r63Z)22D*Ah pU+(XS]\ϷqtH;/`စd?"}Ԋ?6NǓsHZHi/Dbm6r0S/Ъl?d3x doggjBGQeq`ӟcC_W~TɁ*x֙+ab*J/x"tA8`aJɡ!pX\25Ӭ(aAfFָP>KR SU$6;~",nɗ7og9 ODW]>t4r\ML =ۃ,y}\$QG]EmgwRxm㺢61qJ:C9 L2=5d۰pw#^w590XW_}^uo~Çd'1`.n; 6^J !&z@ݦ>n0@22l*wԫUdpN^:椝 Ts7һ"j{& {Ǧ'@W`/K&~ΈR-穚ilՔ͹cwuw~lJ@D/Z%hlwyqlh 1 v}?"pp;o| 0% #B<*xK4Xf<7^sfFգ. }EBS1\I2`TK 3{юǥ~[v7m%"n#_@Y XIn<9rqr3Nj"cqg(Y̖)KU=/xda) K.Mj^&CEWZiF~$E, kV,nOo+өUgRr"lZ:/x׾knQr(]ax,lW5+j3iOkZء `1rD$SFgdj1uuS[EC>^i4ppֿd>2+>0 USVQd3LL ZC4X!K8#`KDa|7aؾҹ Ryg1DbVE}e3;@"w:N2Z\tLsWǺTc^A3@W:7@НQC~t }(+T$\V1 Hկ~v^"t <,.xĀ+Z[X[ƣ?O˚\\8N3R@jP;BUm=]%qp LѣӀ(ѝ +ǺxOBuwUs`]:q^e!Ԛрs ˡsGJ̘*i&N$r$SLs.*TR>Arnmd37Ms1#$|X^(#B߼ ^YR!5T7',5k: ݈VދtCH+?au&1M0nlN*51Ͱ#d|\ bH{kHIg]O'x;/jg܁8VCR}Ӭ`m½z }]UlBeeW!+wЦLHpoPY`=nacJ/k QQ~2Яuxnf&jҝQuϦ cO>7WH\q EM1'<2˰"{QXf6*蓼 oTa>FC*[6qfWQXIuۭw@kF a(֊R2M{ӊB`1:cMjt֎_u3V^6.³Y;~ũ΢bDqcyB {8VCbEWdi& Zz̐S-gE*.̢8EH6 &e:tXrz ׮)c/-rY޻NqBط;Ǝ#cc;m AZ_Kf7`߂ncq-y!ˬx1.M|QH]ݙgH :fg/<'  <֮vԼ1=kyCzRia,4Y٬Óu_}yno"}ꗶ#lyaۉ>?Yfe~uȈvãf6xQ>@.buU;1(uNoJ Yϳa!}ڶ6dL$ͺ.3Jl$<գEeZ=t Cʁ ]#)3%,Ѽ%2nN]4 )#?VSuAJKaK] .]/K+^:oB=Rg~800XX{竨)>hY-˥7=:l` ז yF ۊDqZbN:s+H %ͬ< Z ކd]@WK x PlAbL,IN;p.7ص}mʗ|u{븺Ub*r[H /Ҡ,'=#WpfGS4nfUZ/EV3Ոڑ), chaRtL%QJ>d[E421j⨆a̷%Â"k P\oc)F]KiI͙`k9B~ +1f`y\ԀakG8]u#lXlqfۀ 3ԧ^.v.B613Ce3 J6vlϧHգkWLN{Ayb^b2RV[5'J:My#nͳ+4\8}t:~1*Ki02{@\=Xf\nK׶USEaq!iĕdG>fzQoacsR"f"rG'FھO\e,* 3'H /^5-G%?k`trF1LJu0R=LH&c;aqfs:4u]CCeb v,<(beב; 0p!, ,Sڵ`c7`ADM"b7}:ۣlL$?Rڍ١|pZ*h8kHu{EpڱGSBwӕݻ&wy<|4TqQ4x}Y3-̕8 fYULG}=x>Q%x1N&֪95&;uM Om֧Rja1 =eX,x'NUЊ۩taukT]EroI)ۊk>f$L~s5pBڟX=}jt+Vbbv)en͢ $=5"N"nZLؠ(A$Z3COed.LKw4,:F @_!g,JQZ;,.x"xˡ(MM7 EÓIMY%N@Y) I.mT$AlDeVǬd:]|CbdNWh9U'p~feWVo}@TAFCVbf}屦)TfP?{`p> Q%DwCYR+E=œV,"4U4(֔VZ`-EnfMҖo~fIqf7WWҾ$@~was"h C|rÂVi铸VV{k1Uu|"|])[l6$6$,{ug:4e;SByFM2Wy=1\ \ F*Y0 Z`.) R#9U![UƼ|誶eg?ĕB{AwUՐ 2| B܃O0 X!Bv]}!5h<|=:T!?pł{߹.B$UXT54ဨj+ r,^;l7L0Ϲ(P\MiPh_ _=)֒vV߭:5Sɳ>@<@4I,61 ud7 k7ObIwasHGa^s\xd A[/Kotla "GpGԫL㙎2N*Qx~X*("20*hT?a/²Bc2#@Q!!_0 _X~.1X$4F'ͻewX?so@>1&4ceH1G|e&Z)4VA&{jtйB/'1Z`jN<[I":MtRyg]JSȀ1?H=C! y"AI" cvOVm<GBW `™,%S gtW n?\sT-r+*ffx*]Wi[j7r3T_M `tdRO{oEhn v4п܃7Xa]%MeH6It#'EKN[:m_Z"% $ü#t<; 3>A A.};)VŢjVR5`5s+ k~pD8X% >}4va7v5+>#dE23*E gO)n^l|!.)MX},, ^sk.g( U9pPA|VZqy΂WI`[qԴl_8*CtJ2`UҬr [ݵ9]{5ml.&Og"pW U =|\#,Rn>0XڮeX$O>z'oc?ޢsqVA?z hەAPU3 y>Zyk9_opSfy+5j_1) nrtF00Ky rIyoTzХ+x+;狛ə1xh`('2XXpք0o-A"0m6P.,dNUs*ay2,0`2nW0p y_؛;G+sc N]È+X8BCNc,Gi#4vLze//+_ycxF4_VbXkpv;cڛMw3N}vbF^ 3Ƒ OjVԕ0PޔtXjg$IVT$_tTgMz+I`E `mvШ:L'a}CQ3 %ҫ0#oϣ+aוIG,~e тzC~ Uz30=?iߑ-7 ߎԱj}>y*M39Zc-v2rN?(<;שPcҸ<lCN jcKCTn *0X3!+Fc#/+e7#cA.0K&/Kw|?vۇ/PA { wDduvMt,i) NpЈlPq RRY*seo%KX ]E ߝDBC/DWt>g\x#7Uzv2"ߝk2uc*uxu DZMs{c5/Xt9RۻLEZbvHC.hXTXT$VX`QtwfJHb9%{lܧY3Gk+^;8aCñ B7,iS56Sq0+ ~6gtWpoE{h&J*RՓ3 D+jøCˡdU}л *GQ:D(SYJw+U C>:nΣkJ[zlT iy▚ZOW*Ehq#I[0hHB%H@{+ ]1Wƻnɠ+.S[|EPt] fFXiԈG\ gN+"n0;ei^W 0kwc|;+,QXR= Cw aqa! V7|6 Ao`IП`N;U72=vk70d4&O.wzY6!| p'8{Վz[qU9)ݐMy:Մqwa4k4#~w&ρ} +ygb,5"q:SV3QVss,9,BG }Em@X8ͳʜߧtYS0ICe$9edgꯡ="ŌwQ`'}ݭnPL'247#b[Ϥ<8PXNK?Jֱgh-7۪bS~\X7f@>,Bb)^jwb<,.(m[[:V46BBMxtEsg+ a%*H.U:hj ~Uy(  `?T51O>1wi|bؒ4\wCʁj, U{O-H^_L,U>A[GY|uꖤħiӒ8*7əܭ`3fIWroʝʵ! )}o<守+UVwU>ӊunT7QD4GфUϕX%#ψ 4wZt+<-΅$ڝu, ab:Aej[ u:[yOD#iJbA7c)J`ʰSdcL&fq. \ Oyej\B&-u]aJ7`J^ds  ݔw.wC='pȒt#4gaLrlw:)j7$ / lfHX*Lh` :}25Q[q a]Y1! =o4. `M*!WhH[qc*it=FfPn@@W :CVT.?!D gʲNCza)u<"!?(Id&(#E<,oXP\~W J=YODfƜD4ӎ|xOF>]s8Wv:`L X].RГr oI|k?"\-6uSSAvO ?ӿ_}Ϳ$wqtMd!gRKjהU:1NXˋ}%R.qkf\KZͯ@\^XrPX#I"9&'$UDaJpp"x=qv@jNSqWr 5/vɭ )U7\8\(+A+)RQ"+L Wd({F|',e$>X.~_'a]i:W<5bbpngJhLj`g&xD' XZΧoSg=B0Vгo Bx `A2Ѩ,і3A/!0p`&Za e."ڕIU/Kb( \9ғi/_N9WY*cU&D 5*BV6CUfp4 2;NKIhf\"-bcyGfv˭V:œʏ>u3?eȭF}!aU3\~Z[K?ħ |i*] U9x]jvML_x:e+;gx ;q*u&;QWB~M~Weڬ Ib'\۠jG(Fu o}7\+rp6FH;St!]e;>۟Ghn|`,n yH6O`j%D}93)}Z7=9!d_-槐4f0;u^qk)55<~!˦b߫kwE+{9*>T8.VhpEJ?%iTwU1gm]P}ВDu2+Iӹ?i#݂ 4U@Wy̮?'/0XpfxR{AF礋0 ?}=??kG^휃Vn%AU#)ky{^7tJN:jw@.h1YQjui֣[ TY&L$lQΰ"]ɈFxdHd!Hc2$VGYy:&qzD8<³o [6h b'jˡC7s=Zq M-̩ʌ+KXBgC(|H,}_%$,4X}K~˚ܯlFlIDqRX|SM:()u8pٵ0mZ1V.iHYWy |r*]z( VSnT[— ri؋~M]7Vmx{R *SK ZS;ĚW[%5ml\%gN7Fݱ4r15*!+PQH5ၩvô\J#b+v϶L X#A  `#lCXVGR gu*2x>-Y^Jg3 )g2+eSS@CQ[ՖXGIw<ԣ#鑝902~"$ӨNGӚ eɑZ>@?R0'rgjvR`kH2&EȷҼs&Q<MIʧkz^'!!X!K9]5sV,iо`1"$7C$htgc{0s\ a׽H3ċC46|qg&ǽj9\gcm^! ^ɾXs?,g=hKW"NZ]2*Kqd:h+ѱ<ԄܯQ'eie&3AgYzX,0Dc ApBTqvfSBajЕ`&w~ !(O}p0Ԛ.:1gMtd A2egpOLѭ]kئᩋKNMCQ`;:nGWm&,w'cztTKϦi,!ɊjXnۜ}dtWx5”ذ9c2,xU+7wUpI2Yft!cTx 0lqJ9o)3tV1rq^F9+ pvHI J2XT>Oۄ0+ '݋G| r5k.`oFz7)RTrGx&$f"g7} ׿;}֎ ,,('FV"b0$o f[ۗZ)Fb8=.?Wv^'J1=_$IOv\[;X">GŁ:\d:h31,S-,+~l-4Njiul5$V˳92ٶzsqRj]$z0XPܫ\p]eAM㟻B4X[ u<HF=4,T:Ĺxb2.:5mڨTI2XxƱaRC妲zYXйX7Ig!TehwA\KZ4 #B<rxwv|>aJ%3+e,\E]]squ`}UgP7rIa{%uIŢ\?*Fd 'c:_YR]fYg,'sG [u͔ O$BRs#.k & 5w(;*;ΜP.W+@b`qᚊu*&P|[+!n dgΜiNOs$*Z)!ye"˙intom _nlB8?X0F}O*)@mЙo/=;^kإz諄f1"迠zo#A\$a;_D;Hz?zj&ʞy7NV7«`}2,+E%Ԗ&oݘbtz#;/ d4Rmfq}[u´!ź?XRN'9Bk`N}#wF)[DtE-pіBkSc(bW;%LfCYK* }(֚j&de4Rlpzǧ\^Hrg`A˅EkF9X\2%И ց:&3GᠾΨ]A [V% 㶘囯QݖG +W(Eh WxS7pӇQ<(>v$?wV)b}S̠p$+ `aDFbX <`LZ6 .Sr1pQ3x>3CҠ}n\)UrFDٚJtTz5t`!LԨ}p,Ɖ&3ȅBT;yeGW'[a'1.9 s"kh\Kz-{7,s!&'/ɮ: P *`殇-)1Yfcޯ,dh;㬰XZ5ueeZIo)*f2/4=qs[ UD&HBA\U8#b6LtU'(+{mj'z)aSIh UYY8+4\8}S 5-`3Xj~80py)ĎKF,i)T8eW(o3ջ>ex~-{L=9n\N+?0v 9$  *UuN-`opP̦g9 ey$&w-11DWn|54SĎ$n |'x1v([ٖ.yK.f4@/|ꏠT=eq;P6n7kO zU7 ; 7Ι0"#he9 ~ KݫLǐyZ" ]/hl:ǪbЖ9^.mEbǾ]7k:"]ȮG>`F(0݃0+h.`-do0NE:/,uhd "wdv`5gѯ:Y _P=v 7-yxW/7e17jv$Ͼ[I6KR*|5+!EݎNmqE^EX,Tw Oi_O۵;qDӪb .Xl ? 4+ w&`lsr!@))ulx+39)I$H%I6sk{M@Z[;`q6TbTj2t#T_9*鵏is6&uӇ(ĈBPS Eu #!!^Z-Q1`V 9X$t"QsD~8cEIւb, &+9 \'j9X*+mq3snK=Ф+kb\t|0tURtu:[Pf=2JfwZ\]ƕ5LTe5e8OvZ'+Z8E'#Txx~QX_Nk3  ]m[sO5/P%,mպ=j2S"6k.W]y-"7( 4XpP`1wc9!K]_&0*+-Fɇ8MG-YU?=gs엥q39MMpCYś>;aK|a8\( y ]=,<0Wd;a{BpXw[?ȍ@_ e/ecRvܨy[_,2|B֘ΫiGT$&[eU3+_q@WǷU%MT&AeNn9+̔?l1g',7aSY-x g g V]Y&ifҶKV,)&`ec7(- 2xm֔N$+İ\a+%͈H_5;4Yko`+l ٳ1:T;ͭH2ƺ8t]pP׆w()saM[)r׋Pbps@LԆ}~,V#6.J3\Wј)EH]Ln]`G23ǖ ۋTaL3IKx{z7FXDOI.J%Wc a,/=Oÿ%I1 uTߟT!E=sQ8k,*Yaלg(ޅ?%)a'\_T5dF*4ʒl S|P8^+HPyo d9tǐ]`aA:]MNX?qomU^KԇsJW䞽B߃ - DЅ$(҉ؠzUOQJ}{Ͻsε18sZk :g$SV]^[y:}cv94S4+8# 3 n"my7tuX犠h$x%hޡx#~v {IH2fk}*bQuTϾgNo-# 1 X7\+ O=Axpq/30VEB-ɡ .Xvu% !+ϵX0} 5:8iUP fProx_VI# c%,.g3N I$4T;&Q scU$V+YM}7%˴5JrB?:~3(IiQheG%Wt¶ ` .~ f ^#10d?[,2ZÅ{-Ht ӸI (+2v\W+z"2SLdٽX.:#%i:_`aD*@+H݃ CP|=Cnnt<^ޅS']I oԯ\CT6XUCH\Ѩ7+)'25Rk2g~zpYOP&AroRyJjjDNnPClՋLLsѝiKG=,vF6id\nm]%͊u*ƓyeU+w&Qf0eS(Eh,Cg P]3cAH噢R츈 \  V^_5e"\>%Wi#! IJŵ`ƤږSirxlU/ !18ڴci^H'9f o eGDxo2TW9!+~)&ʊutR5?M^p܎kW#qվ`JJF+]gvͬuDW)(69UW:>y!I:}U'+I,AR~+"0{Jg;#-f? E= 54*%9x/`V Y*pT}(cإ(i7jt0QTڊܹS>ڪUqi5*PRF3n1پkhZy)]L+>I$ѝH+^ﵜ>[9K wBh%Vo3cϚODNDj5$6@npb1;emT"aдQ5SrkqNc> 讐T+g4n B./T4lW "5Snje`_.GfH=:0t!#¥(b7T8oa,b#״ƅ bL%[n7 sws~# oծ ǃpB[B2VA\Hθkem34ST]SE5E$ - AT  KsɐXfKl :A>?"#B=::~j[΋l"_0 QJO-|UBW㓺M}-R*{HmgZN/} c<8]̈́QAoU@QU| {f.2Oѷ&z>X_Ȍmuښ$wa>w,T!ۏqGw~3QvBu^W0XGI ,@4hŵ3p2Y2&;)'FB~NI dagmLֿZtw PlM30 %ujы<)qv!:TXjiZ,laD&O%|\f*<\,CeQ~>VHr6H> 47ɟY}efAX/;׺U\Aܹ|{)V,~8X+~)o}i0,$*/uM62/8rUBɆb#Ԙۉn*i̓" lglE_EZA7T uR~iQƓie<ȾH̎69&,oܯ\WHj0 !x2 "wXԃD"!R*uwӊcy(PS9IEx럠70ּbo1?RNvNY`╕q[)I,$t"8<8 k,Ֆz5aB3kWbNZ0oroU×f5KڥHl[i|=F C*gqsj#Q2RwU#u aG+wn0VnֺO$jK%d8bOwtln6ך+ï끗(xVX՜ʰak׽crw.ql(2'׬U[8u2QzٱN!X9cne.yb0='6WsnfXs%R͢zG*`c_8BNjc+ :0XQn0.WY!v #x"XjOƛ?_gW˰&iׅ-)͡ {+_v;nP謩!ePDMI΀p!)/Nl*qّCDaBu, `!z" ;#0g*ػ SiT69rU\u^ X ){ʨWāiN侠'%zq  M6 GS-'۞;%ikJffsyV X i \* xnDhNF[y SB訯M"wV3?yxgc~W}1?Y TVU#9jtYnl^tU3 rk2g A !Ƌ(>ɉAx0KzHk_L*MSwG,{%꜅<û5U:=n+Xh,==T s ԍ N- <0ӗBNy hY݆!f-rKkRow`A1C]\:2Abqu ;p.i>膩:YS19F [(&;3[>u4wܶ[c=Hxu"풷].hT6L/+x;6%e;+b`$Ĉ;w0,閣Jڭ񖝀%t9u- L'DUoN}{NFJ-V&,E<ɒUKEWfY6(` 쑟ΎX[1Tg2S^*H2Io ζ!5 N~8hv KN“=.%JbQ5^Բ~xp͗aت>.rU6D!-8Ă[3YD]ʓ@baSn^i>tU{/ҝRWmٜR9 ƫթRY(34g?WLiAkS[U_Ѩl3CɃ  ./W]y F"MDJVnAdXN2.n!{wݵtae2wW4&![PM LE傞Q!1愊D".ZGP+E"2||X5lI{:ŋ>4R1dD'FhZp"AcGgܐ*Q0O!hcjw}0V̱`֢Z,SeZtH<J )@*pٚB54Nzm;8THvdm^>5 cv+K/w܂7b\tE`kU> G[4I1o|ۘ" G 5eOHIfP54}"bTܹΙ:_m1Y=I˘Xh 8VNhȷBf32hTtz<"*2FȕK=" L0? [|[ XFa\(Jy 5-5}-Hrʓ t Ҷ9~d?qy+`=ꑏ̫p[¬<@f!5z̝h!;`<@B{_`ӒW<7٘3+:CG^\YjCwe7 k.c0Uite.`Ѣbg>G_… #”2ʟ/b*h5rpPCWIG+M)LB05D]]>$sbrVfS4;j4U CRӔ*0 i*P>-bbhXY<o-п8i.iMup:@ }y'T9%V|8.ګk/ d?{'r T\XPwcAPwYBzg\Q+m:':J!EpH- x2.%g=>SI妑^H8P`ѩH\M O=-Kx[ P!`Eqk{Ln _s̭@lK5z'G6ƚ, VHmu95?mU?Os58T2t8-{#SC^(QԊKb,8DQb{lU]>: ҋn]v)3:rp*ʄ,&QBsw: Bu,=DkU9:芿7-8!')qru^8lltS_} 93.?7KyŠin W`%O1k :> jdA.,#e Ǘ,=GkYpܲK֙;Ie4MtAfI;2 썽0!CW_p@}x Y8L="VHe~^:愤W*̄d#Ё<\wupLVQ+5sZ[˚=|`l#\KtrIs,i˯ c͠E}\?H( :h6fF׼_u{Ƚ `tx <4 gl\ bɟ6?(Jhʄ"}oDKEAa)gd"1p>8/5&@Xܵ4!_A p0+(܁%^!#Ho92m%%tqȂC(t3weK3˪d$AEH?=c,;pgYNͲL<'7 kUgF^L~rfd+ei]8T_c^n LrA &yKyjCs6+Qq~5<[WxXp O þ:.uU2#_1T de NErUcG_ rJpt;0P 䰹 ɝڳ $ECZ{#' >Ph;PDQ2LZs 25_G[wg<~*Sw~l$`pG̮4ra9[sGz%C)IkHOuR!Y{)}x9 Jv(9IK? +]ةL;*^/k(:=TvɦaRGD_` @}ʞ1R<2F$Rv:9߾"h"?w@ (OPœ8Ra,CH&Q7l7h@aF5y[]gxU< ZM%ڣ}mMki+ C̘!~+}AqXތWFC}%A}8Srlt2HBRC3Qd&EVNE"R⸨]7x]vRQڦU qƻyuq[5 uÐU|A9m:2桒}BUHS>Gk"&۫[Eh&Wr2 e5`Neso`Js$8>q2κUpj"|r$!]oyի.O},tw "Umbo3EUHSY|/Ha&U@W!:=#+ ֔(U{u*/Q+X7a> ǎ~Fez`ɀX#ooe:vwS#OsvI$U%;bbHz_uBi@zR8Tq_{뭏&ɶP\gs[ 3`}SA"\"d|!12cnU"chga@(o|'SŬVa,5LAkTNGAq16ZA&|t2 S)?PtKZdO{A=EoS4[it8(Nw\bJL'P;_%*P`5F8ΐ3hLJjt_g _`"$>~babt;[Vie%mؙ3=aknMc/Dfgbo<,Y2| xB{c/oz%]{]Nݩ?Jw6Oۆ4VSlPkk?^oPgw=:]͍'&ՍGE{2OS2a v‚*Uu' bkBJX9w!O)lν2ALX\&خ_zӛ~[וwZ0| h& ]F\&g?5nw1Q "7np=аc,ʇvi6:cP֒Qқ5)ڙ4lhB!UR!t x ;Yx/BD\NHHRr+jL׹[t :3L~߸ lێ]cѱ2)~jE.A$FeOTd.^Z!:jOþy?Ns!?Quv'{E >Bz^ozE„}oŦVLNWfЋaU5 tB7 ǬYd+#}篁wFWS\L|B 1S6r W`oK_;d+XԱρWxa󮺫[ y5f^E*1E28"A$uѲ("H:xc0`4nsn>>0FV`וWB\)퉪V Nj)+}a'|~,Q{蘑Gˣq)ș:[錥Nr#h+Y'D }㬼6˸h_8(w}`Ӵ4~v+ZxVsבB]+h0|RĻx..M9=&J7NGxuz^cHqoKY&ѹ/1"D;q֗_Ifax??`BwmdO9#Ped o' Dj,v]phY9h>fֲT23;=GAYA`!.+@+Zw{nLUNQt=:\f@,";[+ B5$wl*;+)fUƨiuՔ8,:Ib=w!WTRPHJZnjaI͹\3fsG II2 HږbiuO1.DY&2_4T|:*41Vq'2zc:QK!)F <돾\9DŽ.`G#t-J}yS>8Z2w]䶉݊` \h?i J~JI+^6Jᱢ:|jR@TAFCQ䍜xX&0|w`D,ه'DE ]dBkܠ5GԙIɜն`)vp:?u4I`kӓg`B=]U3="5sM kj i'D\{L /P ^}:Mn&ݹcYY8OF?R{ZŒԼ0pw|| oOŅ- CL6#:ee ?Y>))Zo-2 Vq ^&KUݓH?<4}V'UxX!`9N'#>KVX{B\ᕈ X\0Xq=MǼgX+2Mż+si [[hag/ANL*`Fd$٭΁BL^9fNq5)eʊMT{*|]BWk *5# °D'szZO pVNb,NX/g%*+27&n8A/W]MZw}conַay^  P Ra4f90"L<{@)ÙuЦ]LROI`SWT6}b@NKB%C0W_&8Wk,3+% Cj7yV0XD%B-ku-ƽz'>DߧqW ԶS Ңvn<݉msP%qIM-bNRr eEL-6RF֜kgxzmu@5̞y׵ &bAZ[;L5-V}D]zKcָw ^y|1fޙj`HdPhi)Yy ޼IȶzlN?we[?o[k"e%." Ѫ-.ܖAëi Ȑ5wNmneJ}JĐX&*#ڃ- v]!n3yʚtQM.1|5v, i+A;"0"ĨzdyK_zߤb$V|׿ꯅ,m +~~.Iǜw&A"QNE"Ju -1:V~,ƵP.#BF`gTy r$+^#8N$nL|fk #lH8)ՒˊFV:Fg3ý yZ#x)4*s=:ԯ.yX_!}PVJvG%B3umȵ>yE  >TqպJ9d3[Tjᅞr_dǫ;W.byT: 0(<c̃e68fci7N"C:YL[G-`Лt套 *Å]+QT^su~y9` YB2Kec&ljJkzΚe:GzXם۹CmUcۜ\y{FjqDcW{GY2]l&2 ;Q;^E%.*\<'`Ոb";"Xp|IOJ"-_~> ?+ [JJeH,ͤ1%|z1k}[[fǹEbYyn5y 6dGE4LsBqӿwiz>1 |kZ c5|wy7&jGq&<ɎyʛPgBYܡ ْU"lGz/;nA52%HR"-6;?V?Y]5R:wX4!di݂Vɱ!owf%Ԑj⣠L#g jd8(W~ziP˻q:QMn"fmW,@ Th |UxKr^eۙ*vSw`销SAJh3?p4-t&sz|`<1˽Ah~ `ngC( 5nM/"[ż o,nM!5 LyԼӍ$D5'#%T2iC5ETn *0X[B2V:܎c"4_F1ֈΜ:i;!!~xӍC!,$z.eFI^a6EU$ 5F²HdO5Wn$wX"؂u.neʀjRjpz[c&~:ŬT9ф!FR\>Z9D'ӠfBLGl7sn)Էp#Ϯ! xӲ1Q:rj0haD] vJ+PR۸` <ƶ"^ؔk 4>3`9WS;7EHJ^")W xǨzd6r |#>냡+pTx@boE;dDx,@N(k``-;kO\+1"zށ$wÛj`?ez﹕e4Bٷ jh9Iҏw&;[dT k;Ǡh9BPIb}@qevB4+`VMЊPQQ.S^fVfOhxnT IlDW"Yĸ`Y"ƻ\[#f>h?1p7^=)lH|;00j`JG>mh:Xx+MC)=cI>fE&esnԏ`5|,Jig1&Fqݑ]$dT MjvÓEV3TKc=\RhrF縞y`mCƯ}Ց*ǵX׸HKwEuBGڔ%'k.M|%`(Ak0anq`!-k r8XL+U /ɝ?cb>'5klU,(]c0\.jZ7RVz~yՇ W_bSqFJkQ8eNK,Ԕhm  G:١Mrkm&yٜ{03Jj ,ƲH)^*ғ3>>75h֜f+_`Ecλ9 X''c*PYxoĻBpnDW k T^uN#!v_w'߹O}wEFftӰj-6S3D㫥#E!Q="/^o /pD2h,Eӹ:nlL>A3FRqHaka+ tpx+a)<,!5 >SQ7"Uh|ʅ 4+ƂR"9 ;ABod5@u*IN!&X;DFlΪ5vsRq5wU{`#ڨ !XXAϾ3^f8*\B*[h\{|(n.B~|cJ\Q=t~}7?OrxSj%>']ci' ʔ,EhK3 řiPq}jUSU5llU v3_~u@MBhTlte~XGPk,hL\tjtѹUUcgç3}e3`p6 #g OҪ'wˆX3f 3wJ+@PSxfO˩b4e5yb^˖Hc]={ؗ "{ ;Y`Cq1;wXdԴID"N*iEpo? 4U;@)ڍ Ν$\Gv ׽ $.٪, 0,r^VXTIXfU`Vfg(m&]{?bC/|VA”jp3y%O=ocH2~<nXW p EO_i]f!B͐"FB}A$"X]6Gw;pzG}GP&-!|gROH >QiV:  ׋,`ƮR ~D,St 8Dؾ,TBUi$e:LᥜdsfnGN,8([}r= FTՁ0 „zZciUcH÷lS+o:_]W5c$7Fڈ5IO2XZ]gT!Y׷UVwYrbLm6JڍlKNv}LH E¨A,@7 a*=M1ֶ2P8$-U}m7PˇUcaDdfȠi'/enc,ԥWVDU+q` `+0XUoܥ"%9ƵN Sǯ!7xݿFSa^ Z*ČeNFLpݙ";Wec|DLf,<4ug%FA<>RfI aN'=".˳ni*զ"ҰCT(2%[Ë6ak# 8R/*+g0=bjȑ6fX?K9T r揩ο5//`Q~D8 5N~߅+0X#RO{"mfn=K1 zu.\g: QT3~0 IYK1L4 -<66#0x]7|+Q#ͲG3bW`Q4X7,6U:xe 1BOpxϭw|Ћ6Z5 QjSUvv Aay];y&.\*=+e9 V]>JTܻ+z6Y ,hZl{7Ch;ɍakO& $!&=5.XUZNRUJPn\ӂD,t!`?I/1vΊx /\ь虅fǀ.BPy+D8gD} o![橬izqpi? 33#5]+"SٺՕ6؍RzD[iN'u}l $wGIm`X? H Tw?۝y ڛ8,[5bbr84E=YtE5A2Ec)iy#H,0X:=‹DU9a1y#wDRPbgm b6D^"s b^vľq< 8e, X~pXß  t oDL`un81 ޻F__B#/lk3H: $r7KZ)u5#vW4 +J| 4^1 #pE߾) Kl{(4|7jrq$hF+'dյ$l,q !|;Ң%a~ѻr,*sٟ,tEEu&!Uy{"ZfG:紕:>,U&+ζGn \3 E萅ވ-4X,$c`/ՓW_K33录*&Xٴ*LP^VծNwENJF=:eH&H=aGӀ(ѭV~c]z3^k1aAi2\PU[,,2`$Qs{%+)եZbjL(L; {cpwwrlivגȝW,+BSBtGO_ ;?߭֙Rx_S}oO$_%/D(m%|+d#,ߑùPfږytԥcB>w[J]AD]ABz+Ab!јͩO^ÞȂXȰpzLjP6Ћʕ>gRB\ױ %:PtB&.|N,Fk[}g++c0 * OF&#.{g":Z}w[}'>"icǙD'J(+UR&Վ4hԗLהgٔȠrg{n $O"Vhg5Mb):dDž Q+Scu2!;mB;V~PAD9c[V&VMIyV"+Y݆qN3:kFBtw|u# NuHH2r`'Ԥq Й@żU.4`5&/U1;U9X`pz1 Dduʌ!)Vٷ:@#*m# )edfN>]D-޿KC»3Z( [l7kmF,BI4լ@\9JQTVn:}WXE^bJ2R̮St11"C؅Q"܂!fɃ* 'Rz[“zrv5.-* 6< 4,nY|7zv&>'m:W 1to'9Ƃ96fh:f]ҵ-ݒ6.B@VAv߮+އb=GK<0,G~Ld0,S" ֻyӟ'W)Сj-tp;TŐF Y/iʠOwb^Vx-XΧX2`G^g/,Ӑ.,Rauw]O~Xc~̚1FJqӦ~mQ*J,9tV)V#t%I{`5kQM4j.tA>!X!2m9,1/=;:{UJf"-xݲjjV)a-w%"<^M63B֝%\k.}Yg*XEqK`?+hB@CYE+IWɆT|X,^{ɸ+hv ɪm)֮C?6l; ڭj!21c5E6g8^:om RDy<BϔCr듧 *k:嘒)|Xe(OVu^aIpbe ;2FXqگcAJ;x=!m+)6,% -ǯJ5WЬdv7ix { wȰ0"LI36swjdgLc[!Ŏܵ23'<ס};K7%zCՇGAYA`-Eb舫t@Ӽb+,g3ZBF|O<*Y[&s$N_Je&][zՍSU:V#6t6.jk+DkVIҔ @B+ ) ppn32}8@J6ipլ{" jiGɢuJ X]ހ1ښ:ĸpWV |q>=aBf^&zD=mLtt ܡ U9ۑJcoCb對B(,(" (4ğM R)@W+4*-sP(w1TM m6jPc CjH94^Baګrcv Uh=O YbC{m0gfč+țƶ د{;\ٝeVWžNKQ8Wv/mҦ#dːkV&y+["ZJ3J9*2G+ 'GtF:H| d|פFb5X?H  htV%EmL`9)!cDkV9{ `?WE;)"spcYS8m=r6{=Ga-J3X#[_fm۠ s@0 }`EvyW_,TRw r=vi}M@n$N02Ȥs]$eZTSEnR/)XSBSP[$u!&WUq9W `e+vZ6uJ|̬6W*6z1IHse8\Ә2a77v9#0xƗ59Q$VX<y'>/ NPP2 ?ԧ>?&G:OWtU"{k]FIֻ;a:/N=G !]1(wx-g&'V` -b++dՆ;ct;U㕠y ~;XT}Αw2*-~ǚPpKAm3@T %l%2.Gy Þ>AAM%*D44)" V[3k`3rRm1ĉa XMJ$)q"tLR'vӜ JNVeRY2[N>lKg_M$U7Uf2i`a8R Uk-ϪZ*ccrVBv\ ]Y` 7r`,T@=wԻ7 ]{!f+*QIK TXe~L0:}֖Y)?UNgw_v ZCwIK "UfdaXS` u,*{D~,p^O%Oqn^ĂחP~!S1 7g?{douHCYO,t5JٔVz} @K UKU|C96#y0REC-{]9`$ŲQA|軪ۥyΩ@l+:Q1܂n H `%eƄ.DCd¡m:uF6r BW|,[{RE<`$b{ >OAuw.<#]4 )6OSk4R.bnh$cR!!NȂ-),e9 / &uir^ W1pn'πLCk~?#Foy Ua>+\[Ʒ.ѹGl8XN﮸H~I "wD+}S61T)id UkE'!nf:,qKe@#BuδY<|L6rD&y@#xg/V)"bf'(jynt(5GD\Φ$)24QңSZ*K9BiTR2ŭfўN총q'1LDN~8AJkvLJaXw~ m7#I>O`mG;cNA+{\q5Kx'׺= ?YZٽ;YFYL,JkG;̻uؑt =\n(z#[v++2pQL Ƌ/~Gnx5ן>ZR<b2>n`qȀjd mӶug_.kW),l/+.qft {eXu3p|V;'BU2P7*Xq6Ju]jqW B1"dQ]ˌh<}KG]|$ tE{Pj^Ts+bc,洈kfq =FX 9RTĐ d K)l>g+&M* .`]Kve]z%;Oaj{gy˨tv iwfs2AGkYkA cƂ^Cb n#aL)TB{&XBR/v\kPKpoɋ_sf/ <glE;t#? kh_XC!})wMcy;79B7*VI V.K(:PQd$k:*.B#5qinH& Os|z'ڷ,`_׿_E/zk^`EEVX?>xS!"| փې3 җ/["!N55.bN9^)IG} [[Nf) o_'F.R/:*lE N^QFǩʳ'r$vIW2B=n8g"cR\.kBV;Iwj+7ƐʡU ~N=_G<x(YHӎv0{K/0Xrz#ur-d4`c;RM5e^oY }i~)TzgIrjI@F@*117[@C k ْ[,!{ԷZ^W_~^  \ky<_ra>7t;`##]ל2X͌ѠHJ4`p6z!a9AE(6Ag#ڱuDN6m@5^1EV7`Kw\TUH=븱i!`jx2!̘u@Ǚx>V#-]o%*:.*L( )"S^y=7'˾ )JL3ӁY9~sV[Yvrv*dV/A̖yQ |F1֌ $ *}ٟ}U9X"x斑^]ѽ{E.ެۼح[\XptrW'UỹPNיZzUՕY5o%>WA\d~_Ӱ^7K.xW\_򾋮d?NoLPԱy" w`h%ɋtR' -#{nO+zħMS>X +XAJ 7Xv5[]9~),,LP`8'eg#[cĊ؃^ g\︷V]B+C:`q{GM9sf65|-BCfuIk<&S18,Մu=W| ڋ#JJ2e%j>̼ה'WCd2Oak4En3^ՐI]ik0 hvrJ(F6Bmn99X`FwS7_EuweoVJ Q-X鿟z H`"=gl+`*qoUXiY6V `Xosi !F/:NEDn?imÐM{J޹jd&,u\W|BJ<ϊic ?anjjִRmv< I^HjM޸NU>b|XK<EP["Vh&z8g ?*="]jFqymli! _?;Zb%7*X`)gPhw}A =σ -3oV$Z|uLPvBܸY MWB !PYpeh^}°GuɻbM ` _7vJZp`ֻ{/;Sd)ZBJfGZkz;Բ%ꝞH w\b,0E3|,!pQs3V Ƙ)fof:rg(]sIgV1U6'G[9f(=^NphJFh*ʾЊ`{;at " v<;LWn 9[UUB=b>:c!=.o 6=:J>[~0uTRcѱy\O-dhN&uᢽە.X.R*^7nՎ2nxSE+2GW`[XsJw jӰϧEʜ2XKӨ1>9/b`ӵA( `1n Qdo 蕭2Hf?=I)5!:t3I_Y Vc0[5Ʉ`XnA.c_:C -K2Fu< W8whh,X ~Dy=m6<űBA2=); <ԕδsĈ+bM#Z*{;̍|dUvCVt%Zv^Bj4',o= l?)*xޕ`76U)C5K| i@w@*Q@>5!|D)1jfxgUt:4#ЫΏA]uڙ <;vn]W9Vy *T>_q:z]}zͫ/}O?!#Zn#=WBt2n`eb#t޻_WCHCe4VƚG`e1 0CxC#':F Y̢:hobzڸr_XK SPD U`"cXZ{ :=$Cv nCBpcVeJxEXCNj١5Xy^ڽcHP+eϤ\|={gKoz˶:H._uы^ts2$s؏"V>v.򬱋3)c>0&zFqJȐFA.ZKqs`z[T-ٳ.ojUrQӪ9#Ĭ-@T"(lv z2 Fˊb8iD?ں Tv !oS3Sfd'X$LTs#X\RB7IZ& ]yW[}8*=% v5÷8T22Q[]* y@E{_v@)@~~t|ʑG>Xin /LXJkyOwQҨ<[CGSVu@B3Iy'go3)mn1`z˛Qy+^fȟ@;WzQ7\,OraF3kj1"ܕ=FP}׸g5YZɛxP9qW.("oM7sMϭa$ KKųsuP~(9+~XN*9ߒe91bDFMo5,T;*ڜ%sNp:8Ҿ,R4ǣih:$,oVa BLwmnY7>i]FfRtH1y<Y7um ]&jv8_Yuk9]$]#ꍇ _˝7ݒLuk~yȾf,}u*[(n AS^ʷ՗pH4ZC?R`> O)G%puMV%JnlNL,U_H@X+⍑|'׽5X;R3=5UZ+.I‘? #~xſqU?#?U9}xjUzzU $8%dAXUs1АXi#?ܪT!mn l֒)LD&8@bz `D)_VoW Z%!EJ7t4Wz#*o;5(r]2r+uƭ@cUdf%&8/8Z?0A'Acu"ېfh3(4 k kcVG&n248t_rlٮ[`(@dBR6Yaq睟C$2w!a !P(^zDϔVMzNBJZвy(AdJ:pE6zvPզQIctÈ9y'~ >J3OYsܽ1_Iy} ҃uJwܫݩ욧 8#[)Y3E?rKR(q2ņE_-zRCy$𰦶 y ־V!v>'w$M7J~0k,!Dh3` 0A-:i /x_ߠ? ]m3;#U)%f`j~0+kwuHZ*T ae2`d}E! ,3y$|7䦘=#qUk\%^y7 X5cIn3pVFͰJm۴la%'u">j+Z{JZDuC諾(s*ʰod\hlюՂfo CsKr>}ae'ܾ A>UB~"{Ȋ ԍCzpsHe"=ZRDEZT.TQZ-QZ9GOdQi8%+DxW4 !0X-*]ja(׿}N/]VecCIA?=AZ3j/GIp4&6ol뢢i1UN42LuaaHt>~ =YYdUU\>Uky;<N$\B)ڃ6D<[Ai_ԕRLѱД= 46G1#nrf{ ^ 0pbGCuM"vMz#ѳ"6W\ԫ 5O3R3SNٽg1j~,wIȩƌ)aң!<"?b >' ݽn7Pxb)-t9+h3Y@+0X0];t :,9(=ቓUjC#!V/4Z2y\#45lltf#1%Q1h=#(:r{ Z`!\`|Z`ȞEXUf=S&xm]v,T;SXitG9$a'w "9$3ݗcua8]s?^hۏU|-RY e!ʢʹVvR ԏ{wLΫۺ?ke`s Ê( 1X2Zy'k'b(7eoұEy<f F_j뭉d"w@6 ݰ]n׷eFΩ5 +7JmvUz{rW5!Lt2A*N[Qa 0XrYg6U]yכrg;cO{Z &9rJAaƈ.aSúm`ՆM 5Ek= ƞ> C"0Dq"fjeP/CFN۰ͤ Ħ }:z?s!]H__T+Sw.h ,.eRY~vU+*+Z",. w1?QVh7G6f^u?K/} ˮ~%oKcw o~]akMbP`U+@l`=O a%fdcW;%:㸚WNJb@z-̷j⣅Fb訢eO[3n#sA1]!6;򫮺裏Spn kgkQ mrp `=e8閪K3QSja-F)5EK mN  5&LRJʉZ&_6{Kw eD)CPPP7n| Uo7&6s.9#gU ƚ!ta i1b1M%p;DÞ7rpf#JBUd}Sr*^a4f߰ "ts UzA/#?P`Ux["#3O" AYIc8jv'Ɖhr 5m;cmYb` fcHXF(}D&Zf%vh@P M;s+߂m#41]žS|fېfT^s`,H9D=DlfCYU3ښ#IS:/2pfLhllAZhp27C  4Aw [nxeYlH|𡛨5bs}&d%r"vBpCvm NXS{ xX~mݩLL|8Xdcܗ $K-¥,+ `%<Ɩ pgԔ%U!i&lJWuy-$V9KȠcK{廼TTVGǫU|JcI_YtTmDF `|-H@E  2X1㌽K?H}c,3ΫLOlH5R^ž9MiP9dLa4 7磌 B^u~68zN8.<{S'?T.NME~'><~[@WZ+xy$%'gږax|drH}2ncE5ne1VdzVRxp-\ZtGJL07+mT4#e@:.왝#2#ڿSԶ!-(bc~aInCPXO64 yZ1s%r7F@^jhD2FDsp4Ks:ə4SI05ݛЙ=* _ ̥aELhoy1J-nc,l; O|8sW)*OB"?c9$)nC:ënx[!H`vc-i#20frgmU_ը:b.!J< $[ufd%" `?4;D@ ꑒ^ Νj!(a,OdAHeK,($(ࢧ a^&iahѱK2=EUykZǞ82Za,8yEU*Vk/S ЕD*ƇS`A\F++:FƎ8*mlp1{93oF sIMGWȨa'rkWX\@j{krv %u赎)KuE+R~? &(VqyGقzG}؁*WUݺX*(+$Z)`7fD {/uK)8첰1)bRC-RĞiB*-x[mb$urrHii2)T^ry.4T r*}W +oW\!65İ gxu:p^eQ,[5%ǦȻ<†g`ppF?['w_`8<Z`T+38.'5`] Aᱬ@: " JaŒ#zLThb<΂h =$h&AU\g]t; b tjJҫ ԉvP}{NWOk˼T-JUzդvhMNV ynP(9֟ G }5BBQ2?F$$t+I# 1Ns31-?PF! !} -?'?ޏ-:&ݯiQ63ǏuzU`AKo)!FcFׄQ/& 1wɸ`V uryqjrw_2Bc|2jX|"uJ8 `qlP^r2^/C2E薋r. 蘭'fEU|FȐ2xrΦ% j괳.+,,:rz@w:wH3@"r -# ^:*i Esiw%:TQUWR%KNen:UMI4\k\`!çn0 L?Fluj* }C:^,,iB-@Ua[0?D{BXDkRw9E,-H9߫39Z=|hz(AS|k]_?] 0X !+E2RFrع&Ԥ,[/ME5? xh7&|_X񤖔4G>p .>찣mȸ<'zyW[}T<탫S2 z :wh; Ub2. ;6FCgs&m$ocRŒ^X4e-Bve ט}ֲ nvZ>{>[yI(Iժb*aI< ֺ>zʊ$VW6Ol1VӧK(g\I"~SdO2o*- y~'n7Kh h/xݕ.[`F!ۑG+LKaGM_"Dא'93o, h XK<!Y~ޞ ;y ,-**po\ vyCj9D{$ I+*c͑4-um` iZF~륚%Q tI<N'ĬLru1/A#>g̲AgooP15TW8UN]W v`>CE 'ElQ w*թřS&"Nk뮖̹ddt͹!8jF*L-W8,в^px=K |o:ݹe0AqKY֋^($t]i] y!{7ʫeFAZ\2R:qTza:9ØAM-UkSUGz3f`#5_/")8%~g_ҟEsum~F1%Zѓ%2>챑Wc@2µdPkb̩eggn<%oVlFeC CTiB" T{x /dx&WMZ- Z5 z~S+ҞnE@g1m#Rzʵ{D썈DQ4",꾱?/:QQn;f^kAfTԶ#f=S;ھ TJ-W:9/4SC[˙IXR})k+k"8ߵW"]S_a=iky,.YXS(|^{E ƷfJVOI 0_jA7˃VLf~m"LgtrQإe0z5iQ\Kl`EJ LꇩxnנVqLnFjCԷpܱUy;~]{|근W_wG kC,;n|HŤ)UѻzT8j,OFLRЉCV(4#0+ڸTjptcuz!eXcq(p9pXV+mkFFL5?ڳȌH_T"|#c(="=93%WPu/m{74sf0" 0XPU3?*t )DŽ`r-W7`g.Ԩe!6-# **iԞ54 ΠzչW?ygz-ԧ>̱C=q4Yy.]zݻ>I X-wi R,DwCi`~`KWg ff< :fEŭ-ݓc㞅1R;99I=c*eR0a ;}=%LǷcnC4fP| ̲6S retHzxmnļGRWx0w^*su)r沟|+ݒܛOUT=C9!We``bD@r]N;Dϟw0 X\,[ xR5chdv6,)>gҧo%z_7EH'K9x6O#4:W1Gݐk|ztf3%ye5O8h[ 55A .ujY5n]-UocY6i%0Y ~XXnT|DugXDm_Lc̳\z-DPnu׮֯ btp8S~>`50d z]X85L9O˰(JؽH-K弸s8;>CU 3Fhg:W%6FOzx`P׆AuDž&@mGqLQx~zXߩU'H&]@>쒖 hc|͑bN-ZuZ7 d+Y__,fyEth/ 7QaX@\^ g+?N4Mg.T| xy6v|k&Nb Uj%T8N- zf&mCzxNC!,h+oʦA7İ|A8TmkP,j_^Fpn(t];k1BShzbX޳ Tq.Ih 3),UEX*Y tTˮV,Zpڨ>@N*NTtG$WBbgq%$Vxp135y`,ݹS#0BI,R^4*9enIy|}?Wf8!%kF:YrnEYIjGSGSOYR߶Hk:R-d"I](XI,CHtbX34K^H2jsMV~ k _Ʒ_sm!?q(b cɫ?! {` 8EL3TտEX-QE25#] S N +SSZPV59[:A1Gxx^a]Xd Y\{AB;/~O_A*'_|xJ! }~}1͒(2OTұ? ~?Jޓa4!L +7o:dYgl@h04 3sȰ誰zU*6+-P Yթ_߶+/IЅ`>.Ci:dM Jl׫"w,`P#BAw?h`.7\op5  *w3pa*!&XxO_2Lt5["˂VUI%j/~ ql3$6=VftOh P4X&AU\| 8MO^Ωa#C?euVG̴uŌ LI{:$ފ]FHP;/@77G tQcm3܁!Y=e-q<eCIX5bJtyf (!ujͪeN3 ](̕6 X0G",:r&٬NlX5HсM7b9&&5i[`i9 5TLhn_K My~V?;&d3=l1h˒ lCyyB}Ӟ _qǝ -B 7ܰXZM=:& Fgb.Li{w~t"C@:4ZT[Nv|{ 8 cw+K̠dX= cfH*x_wq}i_)yL^}&dw0 b=--rcJ%ϚocT`yZ[#TTJR#ƚZ-j}fHvKvóյeXA^so?g>U'd^-B.gTê?`GJ">ۈqFuAҴ(NU$f,m- RUV0c1DW%S"hk$6=zC\gk:hŤqp`@mѴ}Wsm&=1*g\-,%꼩Ld8wөh&HYi_d:-*a.Y29[F\V2`κ$MTj& :/لiu3H=ھX4oy~*kzj=8G^+L),[!.jFlnwCoUؖLA2}/h4م_}X5e{l:*tT860ߩ!h3x[u#)o'iR@'HW Y+x!x,\kQ9* xP?ه vƭѨEVP8lH "}P60Ex]{!*fm¸BPp(*{{W/G١cI+9 <5ypIJc.Tŵܽp@C'LeMVz%J=8,K :B[3oe= } *5ν[VW#Ji~WK3]jCR-i˶nO+Զ:E;ɀpZ~Lg{e_+"F5c' _o3x59 -HRf5),6QG[\ʲѕָ _ 6|i'X'0ڏF7r?lw1`SExO*y[/ncS 6k_?qߗ`uF; +-z1 *$WeE-T,@㉅AL7K2;Ld$HXIR C9Z:a.K\'IkMF̓]@ ߸#́Y8hUQ( ^]5rd٣kJ2ONNfjnfzҴ 7c?~VjI8;O?+X`>Cz(P52rmRG>|;_r\|:5>8ͫLE#ϐbg'#w OpDFe~ +Yڌ:6g>g/*]3U>5W=g4zS'=yN7kFOhEuΚO=o@? ,Zfsx}8F g뷿`osǧgk( Խ䕣I~HfN"sJ bɕ Z@Wgp5I3S 縸!2{)Q E*K6oTj^ иkr8?VStBCWe$aR28u[D5S%NqݲMEwykYg ~ x?찣<)O;=ޡǟFJ4;a(¼Atcxt !'luvPHr,wqk_2M酁f*D׀k[T5yvc5#иV}tEhKe*#Юk`IhcOzOU>:en;&Qu{@@) <"o_k'wbB29G} |5rlj$Vr2}Wkd"כW[1EP35C,Q\b~4x˓uSwmY)Pe\gSfy1gUq(R[jeQ]R$bVU%.h+;7E~peAċivNch|R.߈K?v`WeFf)!QJ&`,g(\:ϱk͓CBƭpo&Ÿ*,Gbo,:fi?-xA N}Ȟb6 2!F=cw99&!tkMa{I%GA3S@)v>/;mp^n4,T[v5Vİ&*t :هMw '=)|TכEYu"\[. /ƖO|]`E 7=ٛ(f; 1mrvB'e,rFR6!Y "ZWǁ!L/l_+N |?ǥtdt V .նNt Kuƒw'rxUlMzcg헼6~;!WWn-%"9*u!pQ`>S >} xA"y,Rt;`AEɏ | {^bo &6u",%m+ @YFYT+> A;', Ɛ9KRvc @T*BOpNIU"lFX6t ?iK%֏$)=cJ E32>SU%7xjY[}"g*N0Ί(WJ>@ x w/.Kb8XnNE)B,L'%חJ۲'mX1@,4ydM"7 X`Aq%đDwo7\Bu^8.ϦP1:t@2 0"ug(d00M0 w[.O}Ӟ)EEzKi_Wet egyOƑ"vbX]ųd t& & U UV`*zD9cpc ;|mTEVU?5RE?QYcG#? p&NOy\ ' *hFUW47y U 6 x;ZyxԠ"1aR!QhkyQQ`!.6Z)֪ɘWIE;Vǫ ’O~XRQ:L;<MS]<6kZK6pb\):n |`)ӊ{6XP%pXu+c d?Kuۯz,.`3PXb,X* o +IgAٯM:{z6O;O=߉*b/a5F kt`'A$Ym$(Vq6mbMеt^b,:04goC]ѕI-kn+b:$yiφ 9U #;`Gn4Cj1^N ւZw ?-0VsevLYi ۏUtKfW*dx"Q _OzVFmHOu#̈!\ aBKuءGA 47~vj[@~”b/bg5le3pi09Hcg("d8WT&S)Ht ʆP&YxsgYIPծz `#f.*E-1f7vGg?5`Z i87ףa>?i^K[V2־6⟑IcEhUl5YW-t7{]` XbQ/GrWphUd7jB<4[ ݱemKy$N$əABϱ, 3k&C{tHIhʹ%gyQSȉv©6Eku1cD9+$|;w̩[g =П*!v,˷ZY^?9a%C7GVm/qcg6iH47#t)OM o:使2,K%,J76>IFvI.Y#y⑻;9Am6y^DI WpS*Jn]XzB`ik\f*ɁU?YaAbq l="%!+ԶABL-PJP9=Ý(DZ"Pbk1rHI3G+<XU R4b8h=7&qZ@t%oF_16K7R,eHǎÐz'1]GrFv#gzѨ53'ltLXg_0^  gH m?Ľ:-:IXaS9Ka(^  {`V2>v< \gj!#X r(T`85aV&ƪdGeͥD?G愦M.U$Lr Y23E^ O{3ɪz`w2wEAap礓Na Ccl/,`0Q DQ38mdxMZ2Qbo,paPR1DAU'v yf=" $CWÎKbف a=7޹ vh96ìpKb@͑X:w[˘&z)~X*i@X-,S+;巾0V`J3c%˄$%S<.ud; f h!1yWf` z|ˆp`G;6:"HVp$vaH+1G0#w4F۳◈?:A~Jsw MBan661!VlEIP^XYaa;G ָn|U nS_/C\Xũ[, jZ?³qF08/R]HI"!)Vs<ѕaU2іÎ0C]%m<{Ah *W_UL5q,kj=Dt߫+rOlc.\Enh7G K3X+7 Є5Lv0Og> ڞ&!*?"Þ<|Hoa؏.ZJ>8[7P;jhUV;X@RkcZp _詟CQMa Z:k'}\ /Z+in`pXonwgjlU/~k"Wh~iCؐXVba9"l,gxrS*!V颩y͗â3m:%8e]n5 cb}'MSg z,9N;t=~ ,sZU+U0!?A,%RɞcUTCsex6iq&G1󐶦>U#-SSVȅG=؉`G} ZhA;YO&>Tn/xX"ua)k!,VRH8(H-Ϫ0i\ޚA,ZŎnʓ*$!AMCQGfd- ;nv0 8kkj[Z>4__gKVbf^2Pʯ|R!꾟ێƩX jNQM{ȰAPhMVU׫>]#B>SxáĘȣc"0uf}UY)XO1CdpR5mvagui57X15cuu ]J,hyq߇M5b>aMJ b^ڽ݄{v1Y*0k0 d]zC;E6%ùöJ' V ,uTΤ7w9&&b&4)4 z*YaQQ(UT9DV`LV*sS)ʶ} VTu^ od=L}Cp?ןH20X}'_s`PxW2)d?p".V=`eF?51@R\Wv 'ҙ\ҟmt=HJ,\.IY*e} b:U5[ won\u\DFRY&*a&PYU?!0$!<jsI/z+\HdCAPDvw$\.0e^xzۇo+6Q[6{6+͕r6?1S)BQrUo)|Z-jy,v͠ZTRpɴiwFԯ*\BMwe4oN0dQ|cMh`c; Y<X>LS wdhgPt [].fw4azd{^#蚦 =h+m)ʲ96pnH»p.0D倂))I_`DhE+B)tҷQKu ٜAs~`q-^H&2MnM7Z8]RWmڤX4v(so3F(fmr$x# ;VQwP,M6W٬|Da){,e{c/ S8EcB X8ʌ5A=\ʎ:ؠ.(qLtc^WM&6ŏ+TՊx`}· ~UHݸig@W`M ] E]BǬh¬uѹXqZWqD{w"?8 ;P v` | ⅀lP+nPMO9ijY"kM;[Rv ?Ͽf _M/"U5R(Xp!>RLCqve=Z P_>.0<.Kmȱ,uB̢C[ku{wZ^ %^y($_5m:\a{qV~Cdw~(l8S6- Z'`n옹gut6 uMnsPPR4>a >qw)3j=.`r9 V.at:d\ GhZp4 ?ӦWSAȔ6x{ bq^t%zח>q?b }k\s]wvzxp[0g2X`MĆ䏦KX74B$J<5-," |0;v?2E}t lIbv=+qN;*s n!*&ط4MY9FX֐a+l آ ʏt:+a&X\| ,{+$'Ϳj^lmӑ$Oe$0?Y@;cY6ZjWivIJJ8>8Ls2! vtNUT-_pNUxQEw ,&C`4 Q9n{ip0/)rfg ):s +$ANZ xQņl55@5G y)CrZXF{e.<_A2'iS͒}LOCq6n=m~U IIAP(ACSHe5 5%.Ry[tDkhj  }:AFFP+xQ2}אa}Z u;#~ke7PRwڻ hXѨX<Ӥ,fcauN+&;ĠV V"S97 tVY)mMzMO2@4[Μ"\Q p0ZjwI˛YMTSlK~ :>MbQ0={%IQv d~ JNXNjsX!4B䚹SUdLN!AoyXW믻 :z`AO!Q B@Wzg1:L[LHXNsp >Fd:i I5cH':Z&y ִ2d"ĵӘ7jFڽ`?UݺvWu]~ח'h6hb \`Oٯ#!Im=1H ÉT 607WS+2t]-/GY+tR2A|l.+AU93 [*uM5,b{U3|J3Mc,ý ˂% JPYq;f>y"j|l4yIiKDW==:mm.**P]u՛o?5Gt1~Dkp.c?%a4dJ,r髬.!)7՜JDqi,cq&պ" ?bMŦYÚpӠx398$ZW{_fֺ7X%%` ̜?MOwh2g4Z,?Yu&Dk[(1<oNJ/|[Ƕc܃5"ѝT9x1:G'$!mMCF+dQ~nN`__ǬT=n e(XeS؊F|Ɔ҄Y6#;5MW͑"T2j_q7)^v̵S@l{?jѡu+ou-#{jarGg4d1X=/%4mJTi)`+nt 3XIMp 50Jڕ')XSc3X#`kw+Uu}j'^ cI,B`apy)=|m ur% Kpfbi.>H@I"OgYIiY"9j+hQaң"ЪWFfNAY}\T@20}U蚡"*MJURa D߂a1s!u. d (Q#mvy]$BWLy"렣;`ys!{B@  0XzܵU?˰)тkJ)x&j}FmR|1Geg0.< &O53a6>~au9fUxKO8,7 "7N&baC|z{?W^qTyNE{RC^YQЕ0e{;)wbKV3W:U]wC9e1$*X!u롞Un`_Fzkr.҅ϥRblLclib{OxR /gDXM  9l om@+3Xyk&[}mܓg!8*-x):]`zP-B] MG_kJ%Vv " Ǒ>XpS9OŽ<@aTZX7r~WYQ'w| \􉐇vp;Q>]¼ 15%rmEO o-j$TyLu_q`,wcxTfշ|n''"=:{Qlʐª_74ۑv//\L*kCEk V-7?E{x"\i 4n;:>grӭ9ӞҴ,Ȉ'z-2T݌WTVA>Aj: -uOV4XS.EuH /_&'h+-C=j`1ez+_Z`I{ݞ_}pω'V]ZN įC^z>0a,UT\){l/Nsn9L00oAal;FEJ͵vI wC ]1`%lg2ƲScQ HX|ETH1B13p.<ǁ91YBte Z+?ܺ b-%Zשg>P|`s,`!6тtу"®Ejw) JA\H'9Q¥(JsV3-ؤFXp)fxU&؂YF|&_[&AUYw'io$#E,b%,``M BOڰgVק7?h!pw Y!Ef:brOJ; iDl\zX%ސEȠA~x갯adfV1t4lD 'tFOnr:E]*H(c M,⸜8}7$g{A݅z}9R2,O1S3 q*![nVlB,V @u6 p)D|X! VX=ZVJAhaV &ղA_񝵩_U{nUPM,Fa\VrWg!GJ]+TG WI*Kf`?ٻw{E@ulGg@W &/6HCStdKuq4sF&[\<*h:1Xʲ#m,T_&RIzDRM^(B?"qǯA6 # cE q DS)?&4f 7,v4\jDvI3#`fj]6ޔ"AX a_<L,]ŞP6B|j5XXO:^s 6XfA4K 5Ga}xg [.JCP r5;=J+rgf+T9$LBOK3al95Js.*e ֹ{\C8?/e)=:AWnMhP5{wnV8$3N]rSm𙣨V"تEm 'd# V^!fp\;'!ѢF6H"ENCN2IJ0Q*l Pca!S.\ OmҞUj9K(Ռ[ܦDbвTQ ëk-kEOkҦ a,}^y-†DPZ٦ =>e,6wص ksD^pՏ~sh'td ~|@-H9H >5"mz`|-5ޖS$ʘD&4I6́i^e?EQ_Y k2ٷX)P ֮52# nrV, T*Aih )4A~W,wd4ݧM(C+FIEl8 dCj_\ \*uhiqFWEhX{sE1`S̈́iS!;Ǭh4r@6_ Ϣr ;Kan TأXF*mw񺁮EĚY1&И[uQ=jS95ㄦzȘ%2xKv wzQk4 -BX`UwHUXmTW@7|CK=Q_V?[Vpj\wl}!P<*˘ne"ndsK_FcGq\!Xg)vؖV]Zmt oC6ú脹ar.Й;D3/iZ-'wstfֽ"'5֨n,b1Νɧ_.t+OXRw VN;}$"x>^{E] 8RXch`&0|;kgpfZ80ΕmhBLy22D-KȊgUIy|[ٱyFF2GrZv0󝬝Y+c:{ Q9FIP^7KXNǞ JZַ[?z>Z0rL(N@lvsP+L=H8^ 34y7(9ц녅jRYѠa/[234($mSD-Q2E6!`&Ffh"29L!0cyչ?8Q i)"A:7~s9ޙFeI[FY1(2d1-/"1\wKUb js/5L7FJ*s]:O3')5ԛV@O1.}N r7VšB  uO744vʀ,8O2Eji `y"X0Dj髍T/G=%5D ː̜uHZ$zZ7hi+@+z䑟} ,TrB2769Rwz1OQH\ 2.ܡKDtʒeI%ƚ>Z-6E5W8~馢BsLEaXsK<)qM*m%tB Mqʪ{KV}] `^< `Mzcܟ.4Ƃ^$Z@ 4X`V]VUE)JvtP%xR/eJ^7,_ ;Hr"3'BVe59}3 'Uuu{sW]{:զ?@ * |~QXpb.PnP㭙nǟc]eFݖ[CmLN`KIjZED,XAWJT×igYܲȚU PLhxF!S_ -vHaNP>yXΩ) a;Lz/7'$?춑<8 󍽾ld8-\׿("JOXÑ%cu1VA-L5f -h6 0H `MeL6Do6XpPiXy 9^JmX:c:U-e|Kf:VZP0T 'q1"$M*)[hJ^DzfPA82 :wp[=ӑjBQgIFJ1l7ApWnsFȲi):HT+zY3`úpɜf+Ѝ'w-.I$+߯3StY^qK;vhO~P%Tfp-YY걃ZZNyBk V[, 7m5f:0eXiV_[8Ft #< qq3w!*m7suw~kQ4"Y8BJ481%˛L]BtoP14f0 Y]*|U$T-4cQ9+ X*eKajo?~0zvos m Zz"A27@STypUmA/'F{UV0'~){GpOa%U+DQz#PNPH*~Lh` dkw`񢠷H6 h[PT.Hw6y*R >Ѝ BX$sA牅MWRG{e-K7'?`%Hf0MO~K\oډV#a[JEEN{";5-BBdvHhՕik~]y9QTh抯Vg|JK]² nϵM Pu1YF$(FVwD!~jucw:<9s|px9%Eye>y%s)m}#ж'$Tn] {XͻK%np0⿀rEmb-J5j<#ȒXsW7a{tu"2epd:`[_Mj T;YJ&/*-W-tkAvQ[AI">_ԛSC'I7,gԹƃC"7GkTqhVīXx# ݚ5s|% mo )*ow)Er γ}_|,`^alѦ2  h -Cr8UXC$!Zz|/Ŵz $ٲi6 :s!C\5>4"|Sxvgs5MͺdnZpc6NTuFX 9(8$-XDVjzs nT88T ye5O& 12ڈVlDAڸk&5QT^jy2Xd)? eA =1QM\&bsfMYU-ʹ6C+G"Wjt+r/.VZIMDY;c+<)L@_(TݺhNh=Pv_PnTbu]өt*!qKM#֞)l7A*dg)5quD$ ũyX)Pխ[`ݲX%:[J}o @fc#-ވM"ToY$;A=ɍW#A<c,)j=}bbukDG[*ԢrP.ʝi1 J+5sRƩۙ8f Ң("aN+Z -‰{RвUT4v RȞqkD")X`dTu]Z[t NZ>ظÚMOY`MR3›u6ˑ3RUpx=sEh(窭rp(NH)vvH`۱ 9tfT5X v(kzzϡXO NxFE`X6',ᳪ7\<)5 C[m䕽맵?]62b9ڋcйeΡ,@Ha>ݦ{BOJA.ž7Ky;'6kM_/=.y)iQ"q\,UK'ΗK2@9KRj/кcs= ,]eYCK8AD5 PU "h u 'Y VsoA=KQS@\Jј+($`,-CQ l#3M F^XMNXa?H8ed$VMUO{3a˝xVTvV&̊cb0k4EXhA XmT[%z#8`aK8_ȴ-ar1 1v3HbEoUA;m0yDFѨ " *(8EјL&t$t b8d쯯Vծ={s빪N:Uug}^KEd#aNJ,x]R+]͉`Wۻ DOkzVۙ\09(j-2O(iӭm;ik%b2;o15 "7.&I X: : *'B àd@WRq1Vwώa+Ydb<,aiQA"h!uջnB}@'.ދFwoD]D2LŌE*֋B7vjvs;1,Vܨ ’CU 'EAl`D4=B2UÏcx:FREfdO0Evi ?mxLxЪ좣JYTԫ r` t_;ϴڮX=j%F.&T'evd7JdH*A`i£Le): E`!eC"rn0R5KC=׭ LjQXyC-g*-Z.6-qZF<$![m 0JAi9Qձ{TZ_8X=싐N_8g 2R@Wc8#g{+9$2Vg*XSctpz:Bg_ Q{4mbfln# )^Յ8қ*$"A8eQ^B=d`e񃲗c=fS–ݾ}Z0XFfДIN{%3V餶~j .s. V 0FLta/DIHIfIbzJ F}ξҋ@B526Ӿ2EA#쮃XM%l*>{"T&-ִIFP%[XRIN&}7ڗ"&w_ MBh0nѐf8I|mQ*^F᫅W-Ѳ E[Kɑ kxi2pUe<0") NERA+՝ʴqbB"%uhdY,VѬ]YW;UV&?Ī oka7z i&jc͹Pܶo]?U,aMy2)R˹S$cB`VZlj;jtֈRrY'XݎRlW ҁ:bkxBEUp$*` Z_t \ʺBxxs(nӲP_а+.- Y᧎`֫GWTc&2T\ɱAGFB + $ ̉u)Z1-%%j8wW4,zdbO`E'əNsptpjX& )B}/qk&:$#Rh@aݶKU9N(3VE(͈&iFRS[r7 ;(f&&Ն2صq)a Wq{Kk;ujUoBxb7r:G5Nؤ sP"ۯe nHḩ5WeE,*+%Բ־4+-[T)|-4:2Z!. o_ ⳱[ VVpADFݐsn]qKtއ#FJ%#XIH*KXZ">V;7hKj))=ôB{E eof?i5Ѱxi:} ,}?QoM`_/$7LvgG"Xhu0o:6 ф'(Lt z ݻ up`Btb<ߩֆo`yEIgg܂hǷu,-[vXr(Uy˟,Iu3 tAr I c7sSUcDGx/Ķ&t'1C/ dc 'g\0gPbPnk=@bhV&5m4i֕CͦtefÂls:㝀n3/5(Xs؎c D!M*qݙ(r.IIc\J8 yr<#Zpm38X]M FTIAC9"9u0{Z{F+ Z+'ߖUB70!3p *eF2)"d0w1)JJnoJtt~"jPY |' zYO* KUkTʈ5hΣLlL`vB*٠Ti_Jb?[eU+ȸV"X ԱX)RpT>pMTɻu8U$Jr222'N$kLn&KȋYF7syOi M*i9uw%`r9XBkc]ȪD{EQ֯%}+:M0eyF[X,aFTK"lOܵEQ;][kBEJW=ljH:W UU%E$.k"XV\8@{5G>tа|(S=)[`\{T*s!]S0Mi%[5bF PzA,FzHE#(x5Cƪg~1[tu 2rԙLRRг(WkS%BƠ*Oji4'{R/>>/b ڄ|<*\/2T[5s#XM_\WfYV l5 W=egubq]w}33dgoӟ-O^Js^EIx98֚.:Ŵ,ΛYj&>O `9la:v;4wfcf_s`͞7Bjv9oi Ib>I#XIky&1cO\ݽhk:%W2.<>z* .ĜtXj=5eJ=UFy^ 4knciK=TTe"ָ {+bdIv˖uxgYޛ]2yDi OHtR.N  FvXTkQ tEz `uO"QXVjb f/N^9Dwiw\&b#<)Nz+N'ZLр5LTtZ+oFCl#5hcVe T1`FVԅ րSGfy Њ'qQ!աjFc61Bl{r謽LE鸜(\AOHFP%u$k4/sK5 hY)O&"X`OyPHR*Ea `QwFu:ZVP/FGtqI(4y:[0kls&M<*pէ+\B.Ci VPQ`U~lEbCN hzU~ ĽZyZxJ^%r GfLyiLd3+Z`9X%!%u%,ZQ@yv Хq5ܶQBzWuέןXtu_MT _q8/wbXXb81MGx uK=U ]ecmU8֬uY~~ݠhuF"`4FTTUf>QH޷e w4%jVZCtӍUcyhs{rՕYd$zBe!M o8J nD`4:Xw/Jx rh$L鍏DeC(KG\uƍ4dh,Kd+{BZV 8+,dH`M, ZZIklԊeՆu3.b95r?8*8O-r zmq?]t ~ "XvpV$5uG![L;vX,k% :ykK8eIW}6R1l=!wETõAwPlQ'[ ,gV:v9*%hɫINω&uk!EJ~>Jana+*EvLgWO\tǖt\jP! X2+f`dE섀;10r#K=IThk}9`8XNLVސZD%N{]~WC f zu;dMX  ({ԅ6?VvUcƤ\=$wfR݉s9Y@Kg&iVG<5*IM% iѫ '@_ ;Ǝ|3_z ;Xj]A`Vc97b <g>CD̍Q#⪮0lhR hTW҃FfzBZ,,W)? w-|VJ=b5D>+!*T$=WY$Pq_5j$R%kH%Nk!)dII}}KNk>\⹻]vgl$˲`Z9̓X*$ qN( xb 6#BxA*VMۦT;6C)|E#>R>y %Y4d2p1CR5HkLBm<7pvo-̚)J{0m" >Jal Jj.YvJrb6Wa&+Ӏx*'~:È]jIJkX*0`j`ނ3F8%;0iXwB"1VVP'j`e$w TIXUïɳCpdt>.10t0$jD鶟uCܖFAyvuj^ѩT?K+M`}_ăя>מBjX ] N(/VP E%H lQFPN؄VÛ?jͅaDQcU i"l3̍C(T"bmW!1T3PjbPE0[Lú0*lz >9(j&-I<[KF/AF Bޭ%Zi.<2Hȗ ?U y&VU~H䁀"O/bL[3 w"Ù Ƥ9%1J-.;\2&chuKj J v33Hee9 j'Mw<5S>+yn9XEPui5*36UG Ғ`~go /C 4XpWɈ(+~bib6bTQ\XY"` (t.~$`2eOZ(Pۚm B4,ƫڷH^+")yHt3=,?XXXz-bE*q'rV/jX=*Doe0OC#ZB\ʣɉoeCZ0ALfϰ#D`MRth7&B`^g5rݥ*& V rqKEڧ EYBuoo,$>9ں2l&+qEǰǁ LmUvij]`6lًXҮS;_g?wm7 YMXVXqd.(bR=,u8S5Z$] }*fn%`V&%c`2#YCr aNlɑ KS(HPj&3>ZE,5 Z*E$*N&VԀ-Q߿v,Ae*M(ΖѼкTOZYfS&A T-* QWۚ`7"ib~LLǮJJ&0AksyF\;sΤ)SM:X(!ts,ZmiB0d;ېeZ B1VwmL vuiQNP2UBPƇ `5*v}"2QgqU5}{?*MPN6jߘ8VM}!v@7m-WʑdwŃ-j2h;Rq,k>XJ;[[z՚ V9y@x6H6t@A#i)"Mp8pd2xϐh;8fHWl՟UG nT>]h696_$[b3T(u+4upDZ )Bai~*^UIl1Gz [:;=,>vU~!Fo|__+VF: 7]r`g@^QˊT=$oe/>K3%_Rͥ6rT1]#XޕeS)eT:ӕzY鹿)E@mT_W <,]-c~{>W ,J:YZD 9v7ikVU$+J 6'lR*pl@WVa!CTU<TѲeR_1_#Qת(V*2,U?- :ÜqnL[/d5R݇L5;21!)+t8ڟY3Y;+:"+(j'S=&E51AȇMUW_O̍ys1m4yDl9MqDK * CtMo9X?n= A *1Ae%FNN0FC,S;n]Dpq:=z ;rDHߨX{_ $<⒇5DuǜLߥmB5" ebB +ıM~ c<̐NxR6 =j:99)7 v`lX.#>*iŐAl]a3o?p'DP9pmt~(˨&I#X|©(ˍpUѪV[ ѪJ m::X9SI,HfiA6UZ7"@EHjb,uD-# YdoZ{**gy"`]zɵiWH B, `Өg>Q(h'`yaDb~h_-8dhӯ9w" >vӓp?+^ % ?8+`YA`=O=UH6-*~ewntvTwU{!+: կSصLl]uɲ!Tu'gkj+mX`MTvCYþjTMZbx˧?vMx=PrUl)Ex]t6JȩW|znʒWceY6=iXΰ& ֢r`oXHXS 8㨴$kNr 5m2ZA`sνA2BA[ә|ϵqfi횥ZDv 9B3Vh]XF#-k xqǝpox[wW ~~ ?xC(50 Hq,=@n;l^ c&+% DQ[]6|;*m7hVKUy`ͨ^Pr)@ 5uY:݆z@:z;jU3n25mKNbPRk#5`W?+`r`! _J%Vod]I]H957vCf 20o-ksZ U2L5Üe8OKFg? Ě4-)׌Fc:[% Qe\g zȈ bp,}6Ec5 Ԓ q(QXP߫n)y)ʙ%y#[\q˲ͳ]*LRtRsx/j+o  vj#_zct*GZx+.[ k6t'$"@ {^̺YHrc26f/xcEU0w\)VTMV$ P2ICį}??~7qmRQjDi.EeB2 e#=W]%4 [Av̪>T87˲A//ݒw}ǂaWڻʰi&rf~5 4-6>5#N:ʅkjDPm8qhQ+˽d K6ֶiX 7߰ `(UU\r(KXuPӚdJfm۔I|*ƾRz*%z4wfYJۏpES.2 0rʙ{[><h&3 z6>or_|1;i,Kحyń p䚮Z-rv( 9$(^J?Ye&,JEqNv(=B,x?鍠j.G`E ETڧD,kHW5:c=q݇>v ` ^MJ1v++je"fg[Ao;iȼ+1]Kr!.]]i+.gGpʆ$O8y66¼i41ί<ıBGP6ρ8܈j43ąs VVZ,^X:|]w{YɽCBe)GTZ ctr6t@n.ۦXƥP$ZWeVtES %k mJFXz?Mh ujZ?(8/>V#D8a$ldiO;5V]+XԟAUΰ1rmCw7(Z/ ¹pYPEDmŃ dˇhTz=QDҰ,9 <6724taCB9Q艀J] 3XeBǸh UFT2K u?sX>vjnKIyYs0WY]eyzA䝤7zȑKQ; 0͞)hTG?yt `3蝿ʝQg\rn$ s-jkY؟V3X;o#.Q,uSpǽE;Rh>8XP¡}꓿o]K8XEs3IvaN`{Ҝmt.KuK)LBf+T;. ڴ~6^06)Hլ;mBW\%-OC㷗IK:/HbTJjXGTũVdm'T˚AF{])%?"dC-8XpRǤr~f)-hvN+~ cWU~j^pO{+^?J>'ԛt}խfp=x͵هL&˼kS$+J>XDJ:.9pV Re``ms4f, 4 n;D!mRroU]Q?{n҅P7+6-ƛr?z_ D"LBNjBPƔeN^Ki&r|,1hpUR\fAs벁9ev4^>( 'T(6&X*tU g]{U] jOz1TPyȔ+ڮbC+2z4)"mnڕ.Vu5ųQzVjrs\`(Ym iv˲5H^xфqr'r7p:c~g]׿#-/ 2 aּ]t%*'Z5p|TFm1oC /b=H /pjUZ>|Қl$j1]a@VUKRe|}p TvwXn\[,QKkZ"?o7\{ҁW\zP["n̵fҊXq#c6S[/s!t5R*(϶pD ](Krpդ4wmAU6!VM9x"qwN3-ܦ X=ТO&v5rOpg>uRRRp~]n>{YNs; kzٳlIMџ5္w:rZ|ߥVH[# naqIܫflPiDwQt-љdUUhv.P'$d?+!T},,Dq%VP&ix~ւkb* eo^X]/V24z%s4U \ gPBL6BZp5Zk#dRiЗ8 ̣LhV!ܸ0f1h5- , CLԐhN[zP/dV \qʴO ~P,bXZnVyB|5~$Ge),O&F`)9Rk%չXASX6pXHw";; XSVe\;#oM/ŮB"G)Hڨ5ZetI]ڣ*C.Qet|ojU}X `ePef㨤Yw_ϭ| HG(&,l%Uo. M}- G'!r ˭'e.qǽxVn:[nk2)L6O|`GxCS')׍TƼ4ݲ걣&ET""=U2Tu~x?ŹK81{rVQPDH1ώ>PrOUhJc7~),W7N׉xljEXj3tHiAr7NW Q`PbjvS{hZO[: HWt"~lK4DZf&fqnUEat U,R7P6)i; yh[]1EJ\UDvZ۠Bȝ&92"jL[WtʐDU}US.^L!<2ܑ^$:[okFbPLh-ˇ"H,=oVɮY]BK(dCYj(SbcM,ƊD~`Ѳf^|`(<#{# ®F/)e d_. d(. zշvz ۣ`uڦ-ՊLސXቅ[ǐ&v8+kc .;Ch$H W"B!I N ۋ\QmBviJ1\;1Jg;Kh\E)܍[c Y"I:Z.4 PKVQXˠX]7 e3 #m&t*) ^4Z;>|5-;sү="v=+v}7:& ,9{`!3%,'kBAhts/k9k TZ'aKP__)=/\{<tC+}b`AXTm(nU/6Xp?B+q^ҳCbFF~.s*սZk4z?*D" ,_~gjjMuK)J*Zx|buY95.>Lu\!HkڃhϕX*0RFFJ  +C5B67\_\X\#Wa Vغ mG/PWD{="+ek ܄Ik^𤽳aS2ȮXtv=ޛ]%W߷X)*e :XrUXx j<>z EEs%5I+H5E`,O_(` m1vFO7\fsm ]qw!~ 't`S'߮Z*nuS(PZ;ZWvz4׿W_*<3 1Na/HX!a324wḳjR&p*I, i +.2߈&|p1p*eL7śܫkHKr-"ScN;9r. .oVH-1d@ O"t0;xqCE'X6|w=plȪ*oeng`Eq8Sر0[}Ai$=-neu1SXgHjM+!'ī{i>o;*u[[p̉ZG1>tifȘX"¾\S`%F%`/. .h!#/$6 όDhXg dVZԊg; kՒ΋K/F25*8u0HTfij,{6Z%],R|/XqTb +oV`9eJk i򱄢im)§NiFq^Z(S D-Cqkw-Z/BkBڑq$xZge3&8|.-v$SKip?CS|G>cGA|y%/e%j"L^Xc~y^ߕ~Z'UW [^wNLWv7:]i%O= ӱZl,^F..ޕ`?8ri^8x/ u':x:m9 z$q />CD+t']tt)Jo\ÏNwt[{4ݻN7trތ4Lp4s"r$n!|C}1CYW؂8T>9O&"D,p-ezr۷oQILK s2-,<=3!B3qX a<yN}ނ#8&NNOӞx/?ގC>sp(C۾ބ*vF-83`O|gN#Z:db鼥_ᔦ 44%쉷Ӟ >[R_Z._7>յZOuK8͑IsKO9s:=i]>~,z B&؎CvF'h~-|@rTՙJ[nM7>? Ԫ_ᇤs߈S3󏍸z᪥n:^┾,=]M>83ޒz~:.\8雤ޘgiH:?^MC>4`Oo;F6,?Mz{6ǥaIC) S7[Aiყiئz`/WӐS 0j=T3) 3R?! {O='B~=i-/EO^Sz-@Eg@9}Y) S N8w1yHj]{"XkO%1mvPeY/|~F-D0 @CDl][;`E+.]WތIA.=x[ ο/ν[K7‘wp;>8v%׾mGlǫxvnAlA;+r7d'_sWA )O>50ǹ}暏 y !V؂%A\{0\}{z;b;=#` 㦃k>7ni7;#`ci1ؿKfah@h-q8%lƫus%sH=K?p l1]ϻMo$Tzk=յ ] _[p|p9W?Wu=񠨿ԳK?J]Z(0H@1q'GK'^~l !ܿi@rRp3* 1`_<It }SA&|p [JpqoĕuIW?]  Cz/ވ%;[8`8N2^]xb)</?$8+wu;/8xOOY!Wq!^u%/,-F]$qP>vk?_/ ,5p2-i Nމ·+KyfEB[Z[)P#Vwe}Z_'ut Þhݤx 7«7o8ԍ7܏(~'CxzFv7\-w}q>iRG4m^]O~8&IO󔆳ou{qp49fy7 49OI-6_ ӄn1yesWJW m%uKvCI-uӞZOuVc:uoAA׽ .q89o~I' nڀ)^x5>Yz6(Uab?Ot$1W۷O+8QVn!&#H`҅(Zħs+>鲦 r+>pRhW= -.7ZVZ1^M]7ArO&Ƅo`IX &̔L:ltii,Vbxæn!bc:Ud雴blWnA鰸//L[ݛnk {;^: /ݟ?mWwv~D_u~;_ʳ8(@Rw/=" ӞNڦcOO/eX{A;UX, łaTXI Xd`H{X =nwG}_Ϗxw i'11^cpp {؂P؎;1 vHGƃoU U$L-hW0}ILGÃ{o_/7owO+^qW/\so`Sg{Oy+=>gן͇>ҷw^򦋮77l]'X8G01(V@WonŠ9l=YH✠"I4v\4tMuyīxM1_|3>?-5M'#:}7$7&,|t逩OKGq9': ;b짛@>mX{w'o?O^KGNo]>cUť^>E_+}7؞N^WzwW'R<~};豃7\n.knW} \ D+`uq}1vK?^ƒt|O wPx5 ۱|_qs#-x ԰g?;Gxh1}mw_rɻGu,V/}]aҺL_VDWkOu'ȯ{'WW;Mg7ut3Cа?E:Q錥 uz@3zNc:Nx_5<.{ wŴ1SJH_(=Nnёޛ~]zo<0*F4zty-ї^'} QhxnwvҫQ{};leW_o~ҫ2z{ /<I09VV$7%WCjr:\jfjVV]HJ kt2b1Fkܲ 4RmK-iRk8_u(Q釥.ꯂ|BLjc_gmxuЛ%[_Yz#*)jI!fѤ>Xo׳P{"ֳlHM8bZSK.h\n8vG'8i3T뿩ۮs=+ɸ;ATa1X] Bz."%1U0}b-V.V{6#ʚOum3KkxUq sWPuvi"E"ifr WaBY-\zn*b]NtxXpr𴝖誛rit ϭD*GW_r뵷 j0aBbnZ )R,4gZsl/k9.X|ȫCϝ<ײJB pY8ll{ -Z7 wKc pRBTTmRoڥgПmZ綯QI|1cM ңn"2 Pu->(揄T4$85"1̈fc~,=>J<<]=ԴU`m;@\Lԍ Sp2; βsG&dyεZy#VkbҦʈt2{ `m- o9U:uMkoۨW#b;730v\E_6N$MH% Z?,7\>5 [C &saа.ȥ~ oJ]+ eRڙ {xO07m#{Pئ I pvV\^/P(MbsV[J^q#nߘHcu&1@jUO9H' tZ3іۀ_hWC\mfnU ښ$5q(g 9R) ?{4Y]ySBԡXsc=T8)35Ѫ)Q";Zx>E+e_IZLuzĢ,&Cnlm2v2VuTq=&UdpL.z AjV#>vYg[66:2$!6ë@WI[,lc=hpӽp_Cxona5x]A]DTv_f*֤ 팷"h̛,V܍BeiR*g#'j#UTi%Ɩ$V=fXۆW.ޑzڦ虨ش?5 ]]>3rzV-Qd(TD}0ytYݪ[ Դ3(tL,}0|-EWj!ˆU'XŮwI1 덫5.ӰVwX_6ꑓJ9=0H!1щʣ7gG 4L[F,Cͻh-گ"UcgmCn^$̮7wyKUN ,L2/ӯ%r${G,a7m%$,2   Q c nd"c@LVlMTLkӅꐲH3MS|y@hX6맼؄%>:.Sh`^;Y4t91dwjBΎ.|EVQӰ&.K_SaT>k*^Vcv:bt7k5O16it%EfYsh<$!m;I|f0Vna)#Ozn]a]h5"^Dbf}ګٝ34(+%UҚ3 Ri#% ĘJ?&< ǝl|>idg_Dh;z[P5Thv]UQj^Ʊ\dV(ͅQ-V* hQ V2/&KU[LAW6L#QVOGzIPw9IK;cePѕtSNl5DrXnF'0XiHŸT3J𨮟wEPVx0 i2ՊW`9^!K]{dI._C83q`Vב y +UHfTjCyqѶ`~ssBWxFqTCc$*Cka+Fok%XvA"^ֽatS̶T(i FdYC%C6CQ>Ȍ.%2WsZ&2j~f;`P#f@.1-[JubٮQLlYu4%Xt'z1m2 3fzq58OQZ![,H̛teɈ< U]UGj(kqi]R^@*<5a1c EJԕ%fBHY Z ݒC\:q\#y@'؇`):GEQP*^gYo^r4b,X4׏aDQ"etu*~K.Uz(Pp/2Px1YJjJTGf &בDvyvmF6ˌI."f{Ѣu.()tbҸ$8hu`MYMqƧ0@=+ v]P[87Cj!dP$N aaV)|'ɤ `T|ȫ: #^OcQ5$*URuM0'T5D؀ʫk"߳_k-Խ|bt؈p̒ZFm3Pq+b ȩ'޺׷ױZupk4,4սJqI6Zt%W궖ƍ[mo D1X5﬽\Үߔq&ǀ"d2ảKyh5aIC,6˼PH $^xBQ.v%V\ ΢XPO͌#MД*S?R,^سjRpT;cxƇ6\Bڱ!]o*ә6JЫgtER+1BWUC+):EV*sQFhIVKMPXC36'ތ{2N΀u3t&0Zˣ͞g]S~61? Cfc@|iVbsѦIA=' S'dj4P`/Rq38kK&ƌ+*舱ѪTQ #1WWz,9h ע+ ljƽfnѬiaܴn9_ T Xo7*)p`ZdϗoPƽ̴" źӒa}hOn1 _xJ#IwV,&q "0Gg-rt@`e2ʲi| *U3 ~*y,K]c5}弼pPUpJLoDDEHǪ`M*k9Wђ< K*67:CX&Ur&^Fe!dP撰Uw1RQepۄiF0b >o-M j+o,Q!ܠ W-ҁ"Rqe9x Ja*X]=%C|6(0F]$"jdN#"L2`r%}MOV7L'W FB:,,{@ sLSÁtsTѩJ)Gtu`LGQ()5 #WYo(H$ dDY$Kϝ Jk :@; =zbf$ޤˠ0hj4sNƀj**ʌuVq|m]HT`Ֆ<4 74q]-DPh&l(TJsRjx2ZO(&gL6eV*kyMn7M.ju<-ãfͶ6Q"XDF:^Q^1V0kx-!Q։2y |lڸ$9$iMyK {Que<=ZETieЊ[T6^Wwv&c; M} a@t^`e%ς>hfZǨQH}aLf"Wp)rحUgf%4aS0P":兇+sjr2j4ZIKLr(}r|[8I ,9;6,z6]IS-bwYr\U2A*׊c]b_M~62f%L(p 𵨭koGB )X5#*DѿYwwLA kEߑе$K&Ѳ!.?w5>[E󜶌#-9"_*_S$Ue)Sy}fy۞3.;ۨqsZ9\2.:,(t$Q nS!]Q0R832|UnP !ih5aЊEՂ>eUe6ޖ.֬,&}P5dvR0"Un2[Xh۾`ʁt2^yUüV@jW$$XVq3m,ʲB}JtS5a,>!V!p52W8J<0T P!(%NgDJ]X;p44x Y d֨da =e:B7K)F ဨ̭3)j.sV$dQĂ-Zhh]`2 M+ *&'+4DHK(zZºBb԰fznJ.1R)HgA>c`CĊtկ IܜD"[f`)zHlvZVtlKTႽc:Q||^̣g+v@y@K'ړo1l)>ĸFh nR}KI]Vym,`M+~c]mڋyCnIqj4;RtH Z`Ud{T)E[8j(pT:S@A > "چQVCHiWiѤeN0 96lQJ'gWqլ2cu@515&.RG4JY$Y=[\ֵY1j{9WDuBW* e8*8Jr.k.fwfJ: Di55V<$O2GL$&-d9HuI}7`VXUƣKtC2AY}%tGQзHŽ}lK?EQFIQUEW8e]wm V%c v"^1݈FtEoJ"`/I#Wj̢BItM2ZJ2 ֬#~l1*.kG msViqi+ϥ1[l$n"U&`EfqpH"vĮ_>G>XQ6peqA˥I6_ 3כSjиT9* c#jtK1J vIIWvTKԎRA1+IRrd^`ѳj{ I4̡ةtUha#ݰ>&E8K*r\t!).k2zۓspIrrd3MA%0^rHیK Uϣ͕u\]UP1hs]{2C-yJcㄠ@u]0+Y'䭗&ꕎ 0r,QU920ϒZ> *p+P=hNI=D YrŌ 6J]4ߎ-R0FD}\GCqQ??IJb>3))>ڞs=BÖ.Q b-[*ax.oDc* ֙%RroG[GvW*#Yԍu[p+զɨUKeXtȍ>ED5pi-T)`YNC`(E`)WBx?.W:J5fIؒzY2J-ڪV9rBO+rbscgϼ4@@JYC8vf/Pc2V2Ͳ)^e㩽|^mz#72`ʏQDrMXi`j/RXCMRۢZVvY8'KOHuf\94=]5{&5vh52UM^PTqҞ*Z6,ᮧaU,%јel.CȚ)qa)VH{ilEG7Ss=jϕFĀbrPmhkOMMJ DsȒI2Z`X5+а|z*7l jyZ`tٔt)A׷I1aBЋ NX3* ]PY#73jk}Lf95Kఅep_ZzZ9ڈw9ܬkfL>kvYJ(ϙm Xr ɒXCtB9g$.ܧ:˷ kZTE6D } RLHGV6ߤXAVWyLU&_II7(v(](ƶjM a/C2E[OǑp)EH4X+r&ENvpK*G@g UJD5à_K ,J|S{";mHh% '7 %?e H4]JH$5JhjZJ+,lD=tyd{{tйElmH8bH8"f//]O 5MMR'Ƥve\ZO,U.߆a2XDAnцW!Ae VC^yeNDZ()Ov ;lxJ SkХӆDJߒ`虗U&#`Qz,' 2>8E^TqoJS$+Ҫ܄ȖҐծVJCKH+q3>3Ƽu}CDQ9e<4Ap9N9B8̘pTMJW|@D8 2-rP3t*"V_ՎEzlώu&)7*QjJK FL@^>PCڜkRYþhr+c˸BΡUJ6Մ`B!EXF)ZɒABtټ VX|=߉5ȟނtsˀ,00el8hVj'pUj6n%2 &R%trѓ_`9[vy%Є)[aNa|}OsϞ؈ Ʃm{jfT}=DnccB> BvME 6nx@Ze2YSQQ R*--^wtt|^$=\Pi ^Ts}0d;>=@3[jVV]UVm<~xyAf /uuuTJ͜9 ! q#ymB̦<|pRrun÷we545Ç'w,>٪U{ \J*6 AACFv1Z۷ҥK ?zYVVBٳgSHEj@֯_|AB Q W<<<(((H%%%xeXXXa~~3Qp N+=P\Llٲsjܴi Ç#G66wޔq㥶Pت۷oB[nILAPl=?׷zo ,zkcdhǏ]pANl=zOus_}b"J+Q+Zٳ/nbγӈ'O^֠.j(Ԫ:@Ԯ]6܉'RPSRR*g脭[FbϞ=ix=XXЌxAq[( cRCBBmBWM~Zzu N&9s&mL)GYI8pAoJܷoU/`;;c fYXXC!'Ot=lْ%K"`Yw^h_=7666ѡVpg[tt2/""BaddI2K^"+C)G H% 7>P.NFEEɠD:|U ¡ +gJ̃+NK&OAċIwE-#BS>xo &(29 k2J!Ɏ=*sҚofF({ک0-]P@ܹ#P*OQ0qDAF'(4 7 3y^z/][;.6jʋ/Q)RB'$h?H4L/:`0w\A|0FOcPxõܼyIB {I 2Ν;sƍһw KPbtΜ9q =z p-P8T{<44[nӡP0BjYŧO$ ZhO%(/SNc`PcPnhrCh3449y5Q b@daWLJLL,ČW!^ƻp7CMyF6C`ľ> 0iddt[hEߌ^\uonQM8(Fs2qZ<k׮PQ{a6`V˅1]궁$%uuu7o0J+ ?gQc @ {|"~'?Ԅ$@~f5"fS℄1MM>JG8:1^{Aw|&ٳgmױ܉}>>i ~_hnpty1&9"`y6lRŕgm `i"+c|ʢY{ζ̡LIuO'e Z˔kڡu/DDIENDB`instead-3.5.2+dfsg/themes/bluesteel/cursor.png000066400000000000000000000015561467622671600214130ustar00rootroot00000000000000PNG  IHDRͭ'sRGBbKGD pHYs B(xtIME atEXtCommentCreated with GIMPWIDAT8ˍOUyϹ~zk\^s#JoľLiQmrLZcTBmQmFB #%]H4cYj!3)43͟>}<I<_trgN-"F+8S|q78YCT-ҍ;%Fߎ13=523=3'ĹǷon6-^v Q1o8)`@eIr˵պ5ڶήm4w}{e3=Ek \UǾ<?=Y\۷ ,_d oD"7$WV{PɑoI%ХBX 4/@GCIENDB`instead-3.5.2+dfsg/themes/bluesteel/downarrow.png000066400000000000000000000003551467622671600221140ustar00rootroot00000000000000PNG  IHDR 2ϽsRGBbKGD pHYs  ~tIME &HmIDATc\xS{kS! 02000Twk 0~@$`1ME6hQ@uK=od񟍍?AQ3k~lIENDB`instead-3.5.2+dfsg/themes/bluesteel/menu.png000066400000000000000000000023711467622671600210360ustar00rootroot00000000000000PNG  IHDR:sRGB pHYs  tIME'$tLtEXtCommentCreated with GIMPWPLTE))0     !!""#$#$$% % &!!&##)$$+&&,**2+*2++3-2?..500700821:66?99B=}Uo9Uv~'>`vqN8 "aӝ"iFMtPSԒb򠄔_M~IENDB`instead-3.5.2+dfsg/themes/bluesteel/theme.ini000066400000000000000000000017221467622671600211660ustar00rootroot00000000000000; $Name: Blue Steel$ ; $Name(ru): Голубая cталь$ ; $Name(uk): Блакитна сталь$ ; $Name(es): Acero azul$ ; $Name(it): Acciaio Blu$ scr.w = 800 scr.h = 600 scr.gfx.bg = bg.png scr.col.bg = white scr.gfx.cursor.x = 1 scr.gfx.cursor.y = 1 scr.gfx.cursor.normal = cursor.png scr.gfx.cursor.use = cursor-use.png scr.gfx.pad = 7 scr.gfx.mode = embedded win.gfx.h = -1 ;unlim win.x = 34 win.y = 54 win.w = 480 win.h = 500 win.gfx.up = uparrow.png win.gfx.down = downarrow.png win.col.fg = #cfcfdf win.col.link = #ffffff win.col.alink = gold inv.x = 576 inv.y = 54 inv.w = 170 inv.h = 500 inv.gfx.up = uparrow.png inv.gfx.down = downarrow.png inv.col.fg = #cfcfdf inv.col.link = #ffffff inv.col.alink = gold inv.mode = vertical menu.col.bg = #29282e menu.col.fg = #bdbdbf menu.col.link = #ffffff; #dcdbe0 menu.col.alink = #00ff00 menu.col.alpha = 245 menu.col.border = #bdbdbf menu.bw = 2 menu.gfx.button = menu.png menu.button.x = 742 menu.button.y = 581 instead-3.5.2+dfsg/themes/bluesteel/uparrow.png000066400000000000000000000003321467622671600215640ustar00rootroot00000000000000PNG  IHDR 2ϽsRGBbKGD pHYs  ~tIME ( '>ZIDATc`9\󟁁?8"M] # tŌXps'v0$Flě3)s'v@5 N /iIENDB`instead-3.5.2+dfsg/themes/book/000077500000000000000000000000001467622671600163275ustar00rootroot00000000000000instead-3.5.2+dfsg/themes/book/book.png000066400000000000000000015634131467622671600200040ustar00rootroot00000000000000PNG  IHDR X'sRGB pHYs.#.#x?vtIME&4=tEXtCommentCreated with GIMPWbKGDfIDATxl]$IjfY={#>QG>"@G`w+#L`QζTWefEx_lqI $in :眙 I̬̪41J*͜c sd|z1[$ÃdfJ9Ơd>zc󚗛GD/@suDT@>qo/3!Pp>G=(IUR,e;= 5~赿IJbGN> v4o=/G<^v?Ss U4y04$4`lh4J9moiRi>jPI2ˌ M O@f30c? t苬,3X=|9$"Ͼ7z]Ur7IsΒ{;8^IWA/Rd9R~^#k PCkRr~@24QRejMfn*FrODI=PUps34@2UYU^xQaTUf?t I\d4 0F&+6Jѓs95_~ԻsىU*ha~VUc9gU9-3!3L{ 8gIA> 2Zz"^5$ 7?mT !Y ߽}9d"$iNp'10se;gx dqq{ 3S8g^x.A}+ `nF^sV 7NyurV8I {QA{KmY| CG(i*TYt`x*@:t+D>_{IcCfi [{ $59V[=S9;2ygGIZfl粵鞕ǰ "KP{g XWJ)wdwo<%Nv_qQ  Ľrel%0H+}ؙddVN@*uR@ʠtd$%TolUo(B9c ,``,~]?}G͙+u]1A1HWRZ'XvU^s$kA=яJ3{UyB'w] `wDaA]7+&ֵP_#|ZYW;`F̟u˗/ffnF='bjf8eU.t;!5ğ{J{όjAH+ܹ~uPtVikTe {$; i4A03dkU5缮<97+4RZNI)͢oannApk5Cw9uAߏ5fRgýJH+&H""w9$JۥcuIZ(I XI-U9缮ﺮRV*w%mv[Ug^uZff af?߾?rqy{Tc׵RɮX4۷o?۟˷rX%*aOxo̲dLjϺ̃k)J9a@1lTĨ:Is9g]Sǯ3"Fsϥ*ND#!0cwqH:Oy:K#d4sr& QU!eeaԪ>QUUJf69Y]wqeu>}_?aoo?k^bz&kfO9:y5Iw;#|"aNm#V>*άѯ'N I ʭ*$QdScp]qc=#5CcU$00D-/Յ{?ޒ:6mx<3to~N[J2kuc̼˽6TUp;g]#8䜻q4^$pYU3s^GvƻswFK/ޫ杧.nbd~~}]ȹ5t` @ "[CoaX|" k?I)1FU^לs1F )繄|~1Fg!d4ws^ F.Q@*naqO dV'g޵G?277*33sj^5~i*]v\6wӬKwں9gjΜ=9oz><^;c/`77(eҕ||Vͬ?c'xoU9 u]ꎌ fEYU~7׏_+iM:묅~I_43ܻ8缓*U<{1&*+>FАn5?hםV`fo3^)a`4*YW-( *LAP&2:Yv]Pr) fݍ"q0AFcV@yfùrw'RE8$ )Qt΅ivBcDDo n]Zu8d7r=>%) jJ׬sOa*"XY8gTxftws70cEPb'X8\׹4Z0Z-nB;0*J]t.?pA0*R8@_Ǘ_?/z_wSU|>+Uz׼58lF{KħѲtu]I[j}"2.i'H ^AyKӲldC(4x@xSvA|c nȈA1y'w.4yRtV)ލ'57qTr$l\-N-ZaG_9!s9%BW$2J+auT/;cH8g_Q9guMseuM3>NvZU{Hs2p=e-9K}j=B@̜%=*a~]ѽ}y{iBE_.TUzhh33xy]gf1f7Š*fVלlZg?+V1;sμ =Rn=a*s SE=bd&1Ff5; 5jGu_81kξwJN}gg=xPr7X egUcSUH)y^n_ow__p3+.HN?,??%(yUq]y̏n$ȘU u'ILQDvh^csN șFZҜW/Q$:r]vBZTT]7L:Ut[ Y*3snxU&ѫebJ͔t]W϶< ax\sj$v07c%SEGxa?ys " ]WF}Mͮ80R+sFҲ0̾k=ޚiN@&$bA*%x1Z7:vcHeW{htaS'D{d+O1% %c%e:9b)=!7꾯-PfcmeuǬSK5qjsl 7sۛ$q9([{ִ BܵQ0jXlmkcݙVWf` V\٩Q4V593Ӑ{GO_߿(?b( "zQsw %t3;ywLއ|LrvTME e ݓTUFkMB!O2d:d/27\ YPUխzamJJ"BPU t3ӄ"&k@TV QTAq:zE޹/m\bd=z/@xVyX}բ<ClZ[ǐR몚8«P7_9g̏E^˿8;Y9f\=; ڱC,Ntw0$j%xz HYRn0늳|XJ#1U{ψm&q]O~vn*%%ҔpwW @-gCXBDVQǮh^~ xSk@؉YD脌Q &xvۈqC2ˮ|9DH`x#z3m؜3spc:ϳ)=J=O z13GrΜG_5ƨ*7˄^PwJIC7٭w~v w9z6;0=yW̼}MZe8Rkޜ.Uѣ)ի:Aj=92fNgNVdFW/>~qW#"Y?ҷhhrl)잢QmD8 S*c!PUf)|.=HϐGlʢK6Ԥ~b' X9n+>H+UZD cK6ʀf,V\$Cs/h d/66gڙd=YؼP[j[R fnyB5J7kA&?/uA)8)<L77Eqc0wdvZC()Xjy 1`eɺ Ȝn7. 'BR)<HyY(_UUpǜM6S4ܵR"OZ׍+%ΰ=B뺪 n-&ݛT[!3A挘c 4&e[&fҝK"r]9/wմy}HcZcTU,&s:SKa/?||yZm葖 ޕڝ`S?5OoO_>kA|vޤLtJsr1JP$VTk8F@U3}ͪg_W^[޿VbCD SHU5]_ẂKi7qn46Ši{1Fd^ FFHVW~``gN3'QRS|R$wƺىRdf56望#V%کE})f05ֳ3a# a%}x_F8nQQS:!W2:{3W6x?>ea!E<ʝ,ЌWZy6,om/kf dXEWj Y9!Qw=c9-$lU i[X+ƺǣ};Ң웋{7wiV7;[9{ ( vtps^n,Ug F}hK$0B`͎Gu~M#î*%s\X<+i*M.䒳Yq|h)ְ͝|KY7Z .yg+'mn 0[IC)milV n` ]z)x~+cyd-^U\6% 'ɵ)@S U(ތOkt9KU*\`%Y-&2+}Qy#E߶ڌ%aLS Hə6K QS춠E!1ؼE;31,|F,]^L#ꆳ!;F5__j:n[G'I}G3_n>S4FfNFqG XR՚>wѐ!EhVG([@PpVƈ27U0Sߛ@YPbVeB/nUhsrUAt_rNj*Ux8VǤ@;hĈ%9ֺ]f̝T#"3^1ƽwm`pS%`%<"do+еĵK)FES1c(+W>:<AuNiNg'U7ݷӷ?{GΫGf+I9IJe5' 2*DD$F ]nTI,VKv O>}_^Ya¯]D#ܶ(՞Ѻ5%U݅iHu2'z&5˛F?{{,0I, mL(s#̦׭6z4|LN0:M1^F=;,@Hc lDʽl ؖ$][7Ȳ,}w.cDӌ%1˝͜|qB_I7䢹 Gjh`0)kٽW,Hk% w?«ܽ|ZYJ mb>wO᎜X5%[oUB_}%nFڌ,Bn{VYzM6V |k4+Ng8vɜ$h5s]gUgl,acZ|kdFkfˬJg 0*r8d' 9s]=ArAYd$gܳK j̺m5mM ceMwA|G(%IZ(&D-=ۺoLǣ)b^V7J% #U/[r]«FsuXXW!kОZDY.j\mlN pfn4AǧJ䔂wtÚ]sE3[q{lR,i1Bw1IQ/;@xjѷ.iN"&ƒ4?tb)'(K*B-MɊX5̫VCt76 hQ&΀@ )o!U?\5+2')]9ixq8Onٮ*fVU8wu/YeXFp[dYoCL-yLO1JMnD+Pqftٛh֬*`0ƣme g}Re}'_.S+bƸ ,zҨn/ĕW AW%޽}fŏ) cEuZ{;iQYoQ{\3(iwb?Օ^B#Ы}a}kM%1^E- 0rGj@C #= *9-= 3tnSyjݗmJ!j  bi6e7&i&)ۼ +eSKU9r~XsvG\2/L(kΜDZvV- t򒅁-՚.yݽ4Fl7= El[HrGN^QBbmWX0+1bK@#~DOT $&E sR4ˋ*de@ކj ,U@mA.|{{a?w1 .' nO$Lݨ`]%m]-u`fiw"yd[VEXuK6ĻMNY&2+7v a7(c,KLU VZ:H {x/i1ge]nl-N!WV C9 "uofn8/n׸:K%>fn!]H.a񶄸T_HF[g.^Ԝj}6l&gU;Ëj~mASu mqM}Un +6_*LJf/2-vbu^n %Z&4"$_ú.1̝pW_ JRV5CwFT].&6k]U ºZ;s;b,Qz3Ujw1-MeWtwf~:0k3тkJ2:X9=ގCts{TaY$`]J鯐n< w01p@čSݟ{hئTmgsYXnn}E m B¬Q%A Ћw]9-ϿΉ[]%?Mк .m?yL=^[p ?YZ1TSbgޮLLP4=t޵mE qܤFl4 S-D#2qZE|K9o¦E.-cjK~ gb_"WsVՋo鐒)dg\5eSFͽ0ˠ"H (#r`mvb@dYX@2r/&9y/G["`c^\16θK!,P+l+h;\ΐLqլye-'J?trTxQlʾ_ϟooƚ'B` 1q|< Uj? P]iq]'c֠3۲ᩬV/<1T51Nj>NJ6n[@UL(Z۬dC{d&}'*jѣ&ntxiGSL*{mpoJ=!ʲPJV:ގv{{{0sC`(\o*M%6]õnLӤB6=1@awvvy㺮Y8͈*ETՇ,ᰞi8a9;KZۙ,rDĈ;z$GX+KUD4cÇ˵HrZU\PBobG;mdЍр7k]ff1ltU%J-U :s3e2-0a)ms!Hd Y>w:D}TZxdN;[c{ͫTFsZ,Yp*xھh9vCEg9gf{X1YHiRi50\vp}G!fRjZkLu9cK{зuP0ٳas2&0`oӆfou#cl<9wqTe,b}ޮk^A&(E%tUj&. ͙`5i" 8$\]PKm]}TQ;Oh ` NU!q<38ޯrs܉ PSc(Unuڕ8Ւsnu71YueY,.bWVjM"HNU{ic%J1n>*0Q%xBZZU(xPn q ЕO, sffS=BF}wűȏc= >Vé̫ɆlmQ;oŕ/#H?|Z.u}P5xm}nƲhʻ +tVEy1RҀLCt+8L}C۩fSUj/쟜;[rkDew lRQ|q}jY1-&|X} & `՞KGhLSuY9!Y9$)oF 1br4}s]`x6K֊pDP ,hBΉ,>9W1_ uUTU)8ql%_5B1avY;^ [0;\ euaJkuu](FxcKpSiǑu]v]g[usV,MTjX`2|mb\Y(Io>u5;Յi~XcG~qwa26t &K c>O9HuUZ k?C/lZA,11I~6< pe_6\kCAf;PAFkC=fsk%}$mڣx9JȍR4q]u`=іQ%Rf@NHF!mȍ̴<1;;YUCR2ae Gӎ[RB 1rzŎs؛CdK8WgDcLӪ XH:O6U,O욪:ɧ:ԓ-F$LaRUAȰ\;̥9Vx?'Ϳeޢ5a+`ٮ"] 0Hp 5S( W$ښ&;Fpᣰ>T>,SmE>yZʆVݙpiiS_ǹ3:3441[B;,C/8{S6s7y`gW' wRh[u>2S7HQC각j-!][{hsxx3]VX;%.oE2ΨLb{E 08)6E3yoeVSG~NonKaԄbk4 | FVNt]2C汒3Eǯ l YU|eWsoB0v9Z7Oؾw[a^sbr4; d|XG6u%)3>8qpއ=@>itj;"~gܪ{-o43Qݠ|T2KK4w_js͖PoHw:_=P/GaEz }E{\˰<82D[^t{YBHq<7z?j$78)>d9lΝ>q&h2kR%$}7ô<{A!-Xd07il\p]W/6iACԭo)f!,{2~u*X`vl[|Hp@3-3Km|`mKܔu~~"W̥=rݕ$Tyϝ>LoyO+w8$KkRvy %Fo,(7?мn{ m=,-vy]˦,kyv#y|{{sx]>hyqY>Zk$WI97fqy4juGYEo9rS/i* 歈nz}vΦ/*W`67SU&ӽ`6-ZѺ;jo =5Uh¦zh/|kF%ܬ"ᴙF+hM굲UϰgdU^ ]#eb1+D?]#>E"T4u^qDrV\jUUU#r>{ di yŇVۓ'Y.\Nk nr"U0L) K%L (!F= dxTw_IyMD2w՜B3|XN,HD{n:Űtk;{}jp &AS<@<)Ǐ|Ȝi&XjE@ly?~^GDg{Ly#H:֙䙲)s`M$Dkq3Z*eRB D̠O%'*(0,OIa"$`HKdGb&Ҁʎ10 LjrxE d9ɻg4q)rjsx&ZȥW`؈!q9aڿJdf(d iN>ު:53Rhw"RT [nTc`m;)u(cHdߦI9UJ*n˗5׏(Hf1`+D@&#V X}O@8v<.*My6Ӡ@yNL+ [ : TKM_mQJ|:0 7QPTY먐qO8.sVF;17dYuQ]`?[h}V ̋GQsCDE.L{WRVaYoZL=o٣'"TRg V<. H bZ9W?MHBrSvsM ;Fe*>UWZJ<]ɉF1w1,s 'Kf| ` UT6E/> F֚T[6t'.f{lw68؃;d:J{?a",ҟϽT$ ~akmӝrsfX/e(Si$]:Xg.e.w×ӧ8[|VEUp:=BH]&#"Xٟ2Ϝژ"*w΀ řa Ӆa sg!~w fN7:>wdLr%"ӧOC[n1G!@5c%;9q*;ˁ1ՎBs !/dVe47 qQU9@?,jQXHd˷HTDZJ{1kL4(HX@x[qf57zݼiYOj /yp.N5=q*ރdNϿ_uR9S8,56=ZQQ &2栀@q-<0 sakswsSf݈"æ ȭ[i>o| 4Lzˎ妍"g\3'2p:kK"ܴARE1̠d ]s<(&i,жMmfԶ^UTtf%"j*Ǿ=q؆Ƭo#IDZCaPa7֦pg$"'f; ,S3-zk6FLw! ;tU'wu1MUibDDma¼Ϊf!5CX",DT[Cyș˜Ғ$$6#}HfLR~ԙh"&MnuEb<Ĭ|p5 `D![Gtmg2ӄ A8NYbv&1T6p܉Xh61TxW8>ۘ.c 6"|}_?ަIDGS #lpP=N mRuf'CΑ2SaeB,%Iffei y-[D;OϋMyoXcA&R`D8!n<-i҇Ŭ$sC (3dhT9 :x%3c64J֠RQsb7Ք6#6b%#nf!(Y-Ib>)kP¢EQLLG Fْҷ ÆFY~?> jMf-:ϼxzor#<܄dcR35'm:h)`CBZn[߀˵ XC4XH™X1Jkmۏg#) ЈEDJ,,(3HҸeEy.q4IN*pM Eb4O6n_|J3- i\~֛yխ慰o`1/{?g˿$Ψ1{цiI ۬Z^89Yێ/KTsM7Cw%c0oV3돨 (OA$dbfaۤ`4NǶq;|1ZkJp%ok"!3L~<DZq\o7FΞzR &nLx[pzꋜ~4ߨyCoa] }qoz˨?(c۶_~}c9Bu9ʬe{8Ž}-Px|bTj^V [Y}%tUoۛ3ea0nJ prr|V{X6"ꛋtu0 C>9R[8JLnq;"Da^(r R/0D-;7O./XI֦ u6g&XrrI;KWdk72U6+*gȬ}P4OW巢O͇pݾ3?| Hi>]*ӈ-v!x<Qlc ;màWRU:N/JrlKRR\RVhoQr”1q'Qi9w|$f>h=i]XRJ寑Jhm B09@ ը&M[s}^5Viǂ<,5s4%l u}%@)_`U> RMZg,D=L ne>t^U®@I׵A#dPoX$^ip={}Y<7Ô[]x3/.nTG~ף1̢b\0ғ㕧sL6*|:szXyZ%d&ņ2h%;j${k{Cэorई`.H玤—f2SXU>D"ᤃ `˟))q##bt1jD/ i\"cFDDHTu u0-&=Ђ9 EVi5m!j "Op J1,l,d:5<릈3*;U'U(MJPG撽1{0yӭX,>T*׆)Rž$CR'ҸE:V^jutXuxW E2 s xچ W7Q x1`h'm_nMmr ]| [uOHj RzDj']hVKOTcAqޅ[k$zS:0a^'Knbz*z=g5EKCdytEZzoG dbpilM9" pSЎWksxٜFݖ94kUTl&"f+19yDZǝC(j@Qs4fPF:u=TnwnV tO*n4ZW6OW phhxS0-w6I4ewΦ6u[6q]S-1[Dr[ի"Po9CF2<"k92$k2dgf­Ӵ cn^C #`2mWUC2XTÂ()ֈ92"#M7J} 1:nN6窞hnj3 ħoU`șmWlt[:xtS;يpU44?M$2%$!ќLNJx_!E%IZzkbv13#^yQa|3 fֱT`)kKCu(|\_e/mu"˴lR{j\tfXMBf-+i3)5uc \yG!)‡ a#(D kg~A¾:j=%'QXnx8`Ƥ H z4["'t3c'p7&tĄqP>m 9>?026,XZkE[ W/4,fp1&]-fd8Ny 7 9ִo}?7o7"wr麵O=0m{Iׯܟ{W=GShWQƈ,=mquC2H`Qh?PxK!:pesj&BD ˉ!%&x5\~¤=qȰ"!Qb27YX E |Zrgw^fջl-dњ83eb!"cEMC$l,o$JrxH^#s.]pQi*-$#ztv̈́&t0PJ1en3ƭD.C ' 4myfMXX<&%DܣuqrbҦ1h6"1 ]+  oPUܙXl&G0XqU4Gf]zWQzZDZpI@ᓔimm|]ýyxW#^fR 3Qu!D8+@sw{IMn+~xѪ(e i?)>'X uJ -dhI?GU1 -ƋR᫊ fF-.!7;||x;I0\9W=Ӎu(wnJmۖUcudKbvDn窛^UzѢ(u3wl%SMG_/L1G ƭ5QX9 c*+pZpzgFsawmr$rrt,% n Q-_+s쓗vK\]ED^HHQXOՈˢUg:e+8dE|_Kz,c:g^ݍ~;ÑuC0~II |kW௪m:C33$ksO̜V;Yl"6[MY6<:|⑱# 9}HWa~sO~Xj%Q1<߫FښR7SS*[9QWmk]a .tnl60RDr3=S'Dט nęj d-fhjŹ%"ʣ+|d9 j-qB^}pBVFpeԞ~'eOi/z=dMbY}%jrQ¢(VYqXLk0t@PFo1VW- Vje|/eVԙyPWPJ ̱hPCN?U+Mq}vA 0gsU˰[}a<\ǃe>q?$ϦTNZw::1œHba4Yy: țeZ{G".g}Yɬi}JɃ #(gU[,:+_3ȓgtM۪yy_VDUx^Ў/W⯊βyC|ue.⁡,=1RN‹ |}13Y&F_?,Σu9t%*"šm yHl,8 DAKA>H^D"_LU@Aj:[۳yb2Ķ$3M|SipwYZpK5{J9fBD7b-X\o;T߻0p>R#V{0"]Oxv^ VYOKTņl|sEx(#\)zws jS|1`)+^r[koa4b/AdW&Q i@0$E)*8QcAyZ13SQ#eq`eM]3csV4.&i:҄G?Z7vy=a]-MiK@p͍0 |jZnn(joQKA^x\ !Ϋ:}ZqĬH 5߷̭6|孈)iE;%k<goO<#_+VMު"ou4ύimoѧk051nbj3yGjsU`oheLp0|zQj2#Q@w]e &8l:^rGk23FSI5 d^]LU>+e}n`9䈃")]@Vmp63Y~Ĵ6L Rb'6˘8֕Q{ͳ Jz5d>r4PP#EJ13Ys̓3Pv_8}V2b:Rݕk{|BA xES'?)264FE1>ӻ~l ٮ5ˮ< Qy;~? ^FMo:/*W ˭K<RUג? Tjs{QxDa`@)7 ÷6Lj3\ ԎPǶ}m;d2z2OtGO}( Bٛbc6Auղ! +{I3V^ɝun4!E8ݖ۷jRrYuU'H3Lsc2!wl{ƏLBv׃nYdG@G#xb^0R;'y]@ոphW\zQ\*3vc!(uw23ݖkkmuC6YǨf$zb  KEuO/ϨeH5+LWFATTYq -ml@ZHjD c>_`*v:1MoD 1nA-4W2WZ9ᕭ:/8Z+BpIG ό2f K(Q7$\Jc֚*+Qn#Hk Q,Ξ`ZDEb 9Ջ z-cؙ-P9!JjC|]>z2ΤUzlv7lWk+B_e/c-a!Zok*,NB+iLL0:8$'꥿S'x 3b)5!}HA>}}Qfښ|cc~q_igmMMXԤ~%JxܬIޞ'~o(q0p!7˘5UM%(0,$zӹYE`oC(s0Vj]⠸۶-)6wA`nۖD9P&0k"f)BYݬ{С,dsk ENLFA̲rRр՝cl[itK/u +[h4c}Yt8AY*>qɡW`F. E3`%Seqac B*WN%aUUz 1<Ynac(|GI!3wdEM[t90aљy 5^A'F\iOΩf99k[zIOquP;-_O83Tly윇}~Ѿ2NSm{&7e G&bxr:XW ٍhAZj AaaL``)yRI1IƼ$bIȍv}L+@U5%#Ǿkkșd=mjWX\aSOYyLTUi@0~zL5^`߀dم@xMM_׃dBUj1LUeA,<(AJyί&yaIPs<4N~_s+r5\'8GQ֠θSsZ GQ ͐`w K,2T?rZI5 5w0,@ABҘ syYg*2[JwxEtZ!̐ q9_ ĩ\S;PzE1EVX)_k1 ˇ5wMY>2p0ݧqz[>ǣ7ZɹO͙Ù"Rg"x쇇nVՒqhB4-| { e u t^QsDR0HeŰX'HrT'|`DSpP_RPv7'$9&_sm6tgr#QщM57@6 2J3$Nr{ZW~]r?KӪ~|ϝTQ`ҌYno1F Ur9W!L3fLm}ʧƪ"1%^]_#q8COAJ 0!O?d< XQ~[X- ĭ|VP1h7oo @WAeo' 1WZcQ<Mk Ȯu3~DAɚ/!O喘sd}C7e-ך6"-{:j_W\%.ndXNmCk]=Es\k7ZS^:Y$xܜ<פ`(h£o1ݳF-B vљN.+< cZLfN"j63kC3u%ȃz]7-_V]zYOhb"e*fzYڲspsɮ@Fy%ھK\ zF DZUGO"Di>4)m `{.K J?`$D*ⶌ#|DZ8@eyj3(ڗULÑpJXb؟JaNB9G X3J-x<_~?oG"Ump&M35>s $pǠPpc+OlxOVS A+fN.;! ;e( t]hGh TY#NIoL[l($M &'ԭFgu\='qh*#ho9M9$qQudͮx5ow4Ǘt@p$sIn VZ w{1rFxFɀ1RnNDG(7k+A#rt/Q:HDwDf3ZaG$;9 AxGQG>jD_x<5[93!3JV>?w}M ֙vQ|RR&s)̽mlx6A` aSwWaMEFKU3i-D4ѕR>PlK0cgjcG [zm`S')17ΦOSq<[pi0ڹ6 iҐ޴!e))xjURbI}ULC{c?YTBYzFl$ I8Ebof5j#,M>_z* s&1B[ ?2D.BDZONURq5=* Ӆc=a.=aPHMȈBW עE,4nİcl6p8)2DU{>7ec1BiS7;wIl,lv@J ,6bcz޶Hoҷi=0s!a#Gj-$n_q۴5yQQ7C%=`Yq"\! ՊT7>m y=($Us^D@TN,}ڊ1l0{JY)kYfd]CV5d]f.xX86AD9b.Sқi#x*EokL+LM 걥s>G2KT>4%ga&""e0ba퓭Tru'ayc\BХ4wYwbJ3Ӄ|.YGW>KszNZbosǥCVYa4fzqqK?8\$#0<1=wdW7tH^4`qw{@3hhzCPx rcݺ<92m`J;$"q4vp5S TFܤ6m"p7S"~ ?>oe &/_˟~ٟAf@[JO[k4N7-7/*&Ǔ^ }vkejjVTgfm!~/VDs V*a+ g5, ^3*KK"ʀUm5(eIB*SA6d\@~">CfC-^̬2Ҟ~1fh\htοsK(L9`Z)<#{; RLo<ڜHk pqƉ{Cߘz_Mb֬r|}ߦp'Bg6ݤ!VC.6f}vӿ\yYZedzo5] k:]a4B` "o?uUຍ`Ŷދms3p b6& )gby:\6gq. 6sKN7Db$ ^eRWIZ "IiϘoԀ1SX=V%D9 i|(6| ^ݓK-s&a5\^s^b[7t#|-+KfD(G+tQRebf>nX-\ﮰ{Ӊ/>qԪjx3ҽ)O̹5f6:EKrնbaJHrG(FL̪IbJX~1a, % c]OuBp;^s+TFDt:Zќ/X@lCf2U/IK\U&"^ d%,+\V͛HSyԶ>>]j>""q eJB0S_@ʢ_%Ky;ܳ |J# UYXV˱$xpabϬ}mB 0Uφؘ^?FiL)n@ "5{L3֊4^r-n3T΍*Dd1=/*1?m۶%Bz9L9qkF!e_GE`ͬ ϴgT! Hov PsQ>^WެX_|j?iy^~U;(%pEILO|/p W9[L\rQ73ĆU`}3xiknV&d𷾬<Jj%>}gWK|Umv[x iL M}%m{ӳ0`;/_2pQ',ecouaawCD RAN#qq#epV˸{&9Dj3%XUׯ0WY6$. j>+뙬 bIU $' oq/!-A!f4[A5USRiF`Rr8kE$3wUU BQDjĈȜ^:Wߩj70C;_Gw ~ &c|dV|ЭzԕbKޒng5}!_>_H~Woj/ 9iPS kwN/jzH/4Xk˩֊J+6FU}sN^s{ˮ{QTաy)bq2cwJsZ'E#&(mz͍ܦB>mWٞ>Ssp 0!nD)L+y?f.KSx)Y.MǤ0wIg$$e_UT"YsZ倅c 8BdϏ M2wʻlڱ}FIo8B7%t,yd |ƘymgHYYTuʋ8QGCx)c ۸֭9}$1N ffC9&|ϘƛKضuFUH 7&Qmmc}u8YKs2Ӝ.* q19O%tDb!b7m(q{&@Ȉs\zѡl2Oi3<I`s3s?sʁO_:6tom!ޘ,<|Bc(朔MWُ#V ڎ 1dxU5gϠ=H {;ĬcXLia^9fu:|^Ec`NbJ48xhg~X_ kP`b$&{ge8`}rsfuR "ps -{wbën,MV]cmV4K_q/2"Lf r-5pG$ ՗DFtxP4W a  BbT|])f* of, ib2}1e>~@EH, e*]`q^>bqqVnLV-ŠV|U|jM]{IxrΝM};]PȆ 6vL_6UD%^4 ."vҮ KwWSL 䫲U+YO`m[YϟmE2Fp$ 73{S@3HWI3I m8JDNSq"bc\Eb?hNXp3W19'$fB$Welf6@&fF qo8lWбY Aқ5j(:f!=D<@R!X ~kclVk%<"q<[N]F=u>U6Yyu|x mn * DC!4!|V(Hrv$@eslDz8ŕv1͕_9B  Xtu5WZeoCMK; ilxSlk=d!$ȇCGАAxpˉMJhs3wS ^oM׻-ĚjU9ff"/ug]j S!"LZDm siμavDZﻙDR hDiP1[|hCҠ42ff(*rښ{c+0%]&KyAN1BN|ܓn!V3Qj4db=~E̳+p?Ř=,hnIz9c=hko&!O&/SAbU@5$5>8\(İ<:Q.>yK{nw%x̬~}YW%)a-*A:$Z5Gh9밄wb]w<-vuۖlfRD7XV`m.9>zf1'b*B¤*6q͗H_8e8, *+uetUSw3rqOAg}3jjhq?1,S\nc4ÂֿңzsէmZ&V!)~k^Ą<La>%C$C0n" unx ANy<K,˥`RHEVȽܪ)=:GB e?ks*KݾineE.qrXEE+X)DQ5xp[If_7 ⊛P[r bef'e$Rb+y1;۶/3wIXTY?[ ӊg0x:o[1-'ūz)y6n6of實_bg? yc}L%z^Х_qsyEKhީctHqD3宗u`h-20|$^Uu' %Cn׮#TA!v&vq xs$W'F4ss3yG_\ %ȕG'6 e44i=yh!W93fRcV4%f,X",֠q;(>+{83f|KͻCzL,E@Mfߦ"VSXJBQt5Ju}Q]$ 禪տUd?RN3~.&4ݝ͉u5.÷sۣ}&>=Y[JǷ1hϵ9Yuq7ICؕ\g,/uy=D/UPa!װhr5i23) qlhFlcڙI}xJ[ÕHU<%$(t3^X׶߉./U܁U8,k*BFUKUG%w$NC 2lYM6]r)%8T< MY]M$9I)mk8W[Qm 0aYI}v(=;LfdFM/^@ٿb!2bC7:`oi6]1y#f=]74? 84yBc 1ds(( 1t3ucb^p@A:JJk!"EX b]"m d/ᖘ?Zm݇J% cT3o"iڂD\2[h6uA{_<6@aJIh[]E1ō7l)*Z-*a~|b΃E)C͝x:Pί.pmmc;*A!XF˕ L-(xd5>KwmMʅ[c#enHAr;/ɕQ9bRS RТG-OeI(\Sʹ,Q!2ש7CYM%ιU:>fyp{)A$!Jaw,dfA.cu4Q~Hx"B3ClC$dx]85ZEq-p"c ;Y)K*z`hŕBDY{f^-D9)b<g_,C]ǫJ=p %(I`ƚqGrbSZFUE sڜف gb摝 \^EX"u tьqwra"Z63-o=_"ͪNSz^UR C"9zN,L"\3-ּt !8/w.Rzī}T07AZ$Ī;|H@V$]̔3wAv4hRL팝Z9 n-h^ZD"h;z3Á%Z^F .++J+,t%rf.Di(RnOZl:+RN"Ό[c:SinO0#'[W>ͦM1[~Y<I"smׇ]IC"2ȏ6!3cgIFS1. Hr2}  ~ T%nrb!Z5Y J UWhu>.Dg+4yIY!"<‹y d"z։g@2] {*;}n7 y3tI;:OMsU&d[A6q FVPE)E煻Cnƀ,'`~oz>+oG<[XsmHS94D2t 2)ɦ pwxQd1L_4c8WҀܙM7r1ZUy'DZaNchlm8g"=C" sd񭶝VOy6'2: !*X鑲Ewn3O"Sjf^k=ViZ ^b6΃VE1%EGủ ,PFIj Y=j9+J{ ^g7mziHYෘVc vR2{[Emm\ZּeWQ>zĴ;%2T 4d}XnU{!$i{=bױXq4ocAA:>}?TGB*;aq/JT#s0U*?Y|d}5(1Uc5Ru4\_O-SCc~3¿I~L^3Ý}>/|YE/Mx o F@zIK|6hrSzkG,yȬ6q\ӽP_d ]R$!пrp*KZZ/V0c ["%[ ӴVZsi>'Vl$}.͎槏1#[u (܍5v0ihZ⾌IXtT8Z-{Dtj+^&]L8EǐÔ7]Z"9lӈCUh+.9E:tvIINLN'J V̢|2fVsl_E8P!QB=VQ!ONUY D,<]d޼lke3=le]ߦCz sp1Vģo|@lJOjQ`_uͪэ"kS{B) ]-真ZWN Ӷ!,"Is VVCi-Cj%Ni GiP4<w}".,t{opw*YGm?iNg?7ro ?3v*g/ߤ]W|kˬ-G}X_gpJ&0wݸ>V}F+J=pX$-xOb풨-c?A"gvu 3\&QO5AV!ʑ3]w9,)FFJH* 0Q9ly)T'9)%*x WRRcl6/}0jr|mkWZB;x#i dQB^}x=z]i@P _ ]Z1}v]bl LD$y; u@G>Qx [ Y|?Tsw/:)I//*s2obߨTաn T7U75?v*s _t݋X0O  u\ܮQxLtFR|^;VVƭYLe~ozEr3A [=Y#0ld}Uě:8}OB`R= Ռ0Aj3T[syMtH c]evtr6o(ŒE%BAvq"THM5LAVuCd6hw8X٦kUԯ>FC܃oxLz4j:L,L۶'mB,gD$;r{W%ܕ3>IZLTe(1ǜM^ݺD *-F 19')Bcs0$UPwK<' %xw/J4&^wpA"$Ĭ Ql#K l;IM?:n t@UT 񗪊*f"r 0DEx|e<Tx?48aЗ;yjBa3|A6BqIN 7t0~}K )\dRc3yc'fen+[>fNFaBnӘ2mNwmnteVu:(V,+}݇z5GQGĒ]csCO/m*#1bEHC"%,HD8@E\Ea#rJ;ZZsNѨY=+;zu66" r)Qx3W>=HT"Xbirlmrұ{gfT Pxy1J0dOP Mcl*.}hhjp_]*#^E[{Q扄e:MsC/kUfq8;q9ei^ baĬ`B(=[)kUٜ"h! \(usSt0JJZ&Z+c[U5IEN `A4pj)LPwr"yx0eQ]>>Lp, \)F~B j,PjFC@ P8h隉2KCk5%}|Kq ٞ t}`<̫7ϝ*L"3mE{EfS ?LPԗ07RkŸeCupp˕l\ H_9?m%b_r(+քfN4y\0Оׇm/`,B* :l$. )\L[Q!# Ti&V|ɸGTT.xG􏴍>v7|7>C8*@XJPAls:sNMLvԝ"PV Cl+oxg]y%&fѳAL,J wG9S0$v;G>B7"s 3̾$’HDS%JE$VrTp8OQ$@6%#tNg녧SSV*}>9E@Z^XgÇlr {ȴEƦTS!s<%=k"16 f6xl SħZ0{Nik"J׉[xL57,r^e8<&S3Ȯ^KP)bǜ^168lTyݜ[UnqD[vN=Qf 8IA1?ze_DMh%*e2<*s*z-Ta܁KTfCB`9ޜ,VJU7C>=iȡ6gEZF[4|$' YSIʊַș6,E4Xp`=X ]] LABa7s!{ntL@BI}rd:iQ>߿sNhA T@w]>T,WUM.os.q#'V*mxEٖN;+qͻW,g)̌p7!NaX(a"U^"nmOLlMiOĎN kS1EV2 /Vm2u@?5R1cl__QrAk"D䗡Epqmw=IVKDNzz}};d {*_R`wl;oۆNw.rEMyN"3)nVM.SHuY ~.Dȏy;bj}*i!mof)y<,lCYoOԏynТV jiYDoTRe"{LV06k$Tc#p8w'/h! 酓ţa~_|{bA>H|_fK{mzJoS_DI30 iA|׎|dgnRLk)NUL&^TP;,d F2c%(aøKPJ/s hP3g2Ձ4"D[R8jxrIBKdZ`ʫ-4\t1rL,6"q%9DQ$̤kvx0}}\YsqL}nH> yxmf1ƋGW{(D}o@HN!<*#ۤ $sP鎊Q#ZRpz5vjU=9 ku=m͖b փfέjљYI>9EI_N*jҗ VPTP޲%Շ>9 IPl}KxѩJHKuÌ|9oԚ㌖zQ6~1wSRl>e$$ `OaOjA] mɒV.ۄhe۴M;"=sHI-j묱N`vqf[T{0;rE- }Ev%Ff֚c(kvߠ`Z.a\3ЃX@u WR,BtsQk fzWU7g(Y#ڛZL!RΡ p|}yf}*?䩝-{CdrĢ>ezbv@,(E=N]|j$xy]%|gΰCI>h2pxL$!>@f)#}F)\@6r Aُ?:[F|ZS8Rc;ٵIM-as)띈lV{73Xd^FqE cm#))SQ3HXYU͗<\"~*V]OAW {<ւ㦛fO_cSOmkB]/zs׋(*Tf̋Ω6x=<-|e݆P+ߌckյNWoh.@&t,kD3|µƍ@ Ĝ:YESQf}{8\jfFqI`YX\!Lɤrf}4+u3={Z7쵻Oms5G3 R5ce|r,A9҅ ׆0GK_|l&ZaqoVU٢"p9yHr+{Sn\$tc^㵦v 6 ҿ,>㬖1oEC]=E7%;C=GCrЍq|(q-buVՏJb"(q\[\| [mO\EraukDqᠦp.x!m׀oȻ@DxD>J>B7" %,2s0?"ݝ^ KR{& + ?5 3!tЏaq̓xA_ҳHfe Y{.PYbmۄmrŗۈ|???iRcАAL6Q 1fm۱ςTY{assZ sen \~ҭ;3u&p}UZ)%*wɶ*3hM:CU7d*4-rG7aBU\쳲w_AUfy嚕k'Whpm)s>uWkx%/9WOng-eT8sLRT]Vws;V'e!,\_~; /C+&A!'&?6Ǐcr\#sP,v֪\(h] Ʃ Z@q^ ՃuPzK5[RrrP^=hRy_o^Ev%ůscx&PuX *EP<1#ǭn9XvJ DѠ[qQ TC +ܶۖn첦Qu9IQb˴*!%kH9"w`~ Ag+ة̾Kcln aJ`?? hYI;R-#)^4s7C(+Ⱦ"Je~-Gߐ/&gd? l84L×S^l:x&O./z rQ%sjE&bXCt>b !'Rv^_S+3֜"ܒژ2U֞3'u v1^3&0U-kM_LI_F/ (pI#"DuyiDAWܰ >`Sх^S,,Fھw|JW\{{AŒ/X#gW?]8b?tj̤(m0b%I^e ^z[d8*dmJL'qϝwK)c|W3#8anv |S}}99H[6)(p s Ĭ_/D24#"lUf V16 pJii1 Pm{i8B蜡2B`c EX"Ab;Zz6gn}zoeIî]`u#:+rF|$5;ݤknۨEU%^'@1=Lx+8b<ӻQ(@D R逡71&͍.i|'rQ (S%ġ#UEf^dL;!!aM#L6:={fp+oKӨЪCIs΢WF(=2 pY`Ep-oќ1&ȴ13ʞd̺ r,;g JxN^=e[975ےe!uHu#=o w@\ÂrkÓV#IMHa: 9Z~ua JZnWI[32,aQ̼`!L;yt]Ǚ/L4W.> _:)vZ}jL%grSřKC;_s݌/$CτG'XU|MD(p^{b9Ch;4s^ب$'|gC͍zKᙸ,P{] v-ϰPS+$¸` "Ď2);ny<WR{ F0"wpwy= BֹTS`"7\0͕t81SXBHH􋶗?8ր͹m/쓪J$a]C뉈IA2W)껈,?x&Z!1I#V~& IAv70|NAyWfTG:e>8Ѝ| ͌|p܄<sL 6)hhiU#dZ^p }zTGd[cWڀ*@Ŵ%J+e,ha*UmV / uUma; 0-dNw|u6+ATr9q|[uUdGkt>;%C7|m |GbT^r`iwkl-%dy4%K?oĬ%$CRp_%x3:Py]kѣ4U0N!7N׋5tTev3# #mv @KlUQѺ}ƚ s2k'>打0qQ0w{2O9̅[oS!.7)rOd9"U<+f}'q`m_?^_9xAH%dHI͖d1  cYghuޅ/"<E&k{L ,*[a^wl-hZ/ %*2(4k.O7Άd}*[ض35*BOuQl>ϲ8U:*D ewy#Kie #g?eF6/I7rOHQf0S8NR@9_[@k{69\ir,n~KP@+r3tW,6GW"yL#˒Dbf)(ҍ!{\sG0)yz1-YX$뇝ĉu"%ԜO͚"/Q'2^5,rMhEAi~$TllmH\T |E52=_z_zn/Hp!9ufvw1z[N+7K* Q(T$9 {wUNOwT퐶"9:\꽖,Z;bӠ1MYRLd0P q{C쭄N{Ʉ Yxy?Cxi i[pF/"YB(BtE COjn@(OC"4ɳW%'Mpz1 U^Fj۶ oqwbZ(>Kq2u?LU[Ip=gD/aԨ]Nφs]G i{@TI0]#M`9]§x~]@i _"dFhKa#Y-ei%*8땰z/TFѰ[ u3D:/|3=8Hwkabɝl[/|.FXgϑW Okm- t{íe\1qBӧ|lֹW`NT01`J,ľzJB܉~5vjc/ 5NK?f\1oF_^'iYr=kN>J ឵B/p|nM7-zQo3/8@ħrHt2>J툡bkx| u~4.o$bj|`(bo BK^hⳉΪ*c?;FSzZm]-t)8%1{-A*hGw%tңt@DŽIQyfƌL1#tǵcD4MCoIEϗl@5{_UUDcĻC]j]oﯗ5z{0uARS uc[w[QnNsnWMLPȍ$sZ8*c] oA,۶ݕf>Ʋ3‚ƪ+0,p+gy;GhBoEA,AnSK$l+Tౙ7=t%sܶ-ox"@OVB 㱛(=eWWKUK5D6@< efC(H:(gp.4Qq~BFozQ3.kL3'P|6O}KJ,BV? &7BRiIꪳ9:(DXtfG iw~Cu,Q"tF}'ݷB+)Z&GIa꺏(>7p r{O-qR*Ssqb+FˍEzk4c|S<*MOXe{æ=1s_FӧH܏cz㾢\&hكsD@,duN(ieSk$צyZBznqJX3OӗJlC^C"+uUD@c۪C D^JF!,,x j"s7p!UU!6&|tڿXm*Q(OҽV1A̞v,Grb5,`$[P] &֑p=vbQV??fw[ T[9+{+} ?@! YXXky.|ٟ-7|x[OOlP7-~ەbˍ_z'I0'*Z j,I(o?ZXyaY`L3ygho-'{GpOeإIG0̂yf)YPRӢn \+r8Ȕ<zD8VZȊ٤*  A%&( 5Bk{Zu2#2 !wvd$P^ݏcyKrbqi P76/R0H0/ ,N88L::2ƍTQWڴcRElb*KrF\'=y^}sjkOR\Ì_/oÌoMֿ\1_i  .6ı^1Ea`8+&V3X3MEl6]O j$JYxАfB@p:Icqt&"1}.(bqyRG(%,)a2›(=u&_cl*>g˧afGpbr(WeCҷhÑԙ-5 zfH.%TKי] #a{yPL۹yEpz\,, %IZD6U 2KQ@W?m:cAG7"plG! {K[ ”Twꂏ}ga`Hǰh: ʼ ;EsvV_Fρ=4Z&Um5;uٔ]U !U_]g=5h<FE dYCk=73ruLsuDyX'^Vh=KJ1cwdPEO'/6(4xq0?R**Db9X0#MlUf E6zG#-0Dfn54;v+6m/W iD&U MB:+w}/mofΦ\f*wmܬ{}+$*RDFbJd9 Uq32EXz!RrB$fj',cQў>aݫhJZs"[& x.w̃ &]9[0l__~X4?=~ޟ8|k|2gHW2@$1YM0VdKo?D.7]փ oZߔg;4[%W?_]ԓjf4ѵPjI|"rM# EU{JC Qͪzj$}q\J: 3U8GOgLR6KI~?Dj- ĶL0YN ep@uLwpN%,rvfuUYS$TɈc^O_)9םLX`?~렇^վGWkR5 )CTsx􅢪! b& }.v8C9PWds\"ǎV9}KZbƀ#݆_.Z-9a2-Q~e}^'9D`0F8`[՛m_ xFp&mݞ° ^5wFϨOox ߽jws}r;afqBݔǜ7%Msl;^K뛞m1\B<XxHC|)::A&>/<,YQ0yf>r>U▭دVЕgǖ)GHx}lw ED!uX?}p>! n1o#\kȯ˚M[ggJ?Uۦ]ήK)c-ZH9S뚴H陂%" pZACpV-c=^{T}tc1"O3s7z$\!N F3@{| yhAңr"xnvy#62$( 6Zi`? _~,ֶuwI^7J"y | I^|D ='&^:x5H䅹fPMyэ 6c@Ct"^WJJU%`>s0$l"`&.uf9NN{C*dDDך̼TA2FUzߝ4!W BvLu$#;û))X03\ &:#z(2q,%DŽDoܻ~ $A޲|Ѯ%{vGVoU7D۶1EDї{לramq  YRMŢgEG,sQV)уlN L$~m&]z2 |8 wv>`SnIjʬ k w S@1^;n뭭O0cjV܏Bs3$%Lc0W:c4OTCX `O{\kՈեuKv"η2trO@&_LCә"T!P7j&IqwL_#w8,(䒃vkQ]-{6vZ2Jz{FHMd!!1D4?sJT9U0[ wwT$T\&n^3'M9myT+DEuGv( @zFTtHl@sS1sVM#:+e",wΦo ̬rM;gAl]qT&Bѫ"딾'u_?u03mz||:j! h>` jծrIU%@5P<%>_"ܽdX&%fwc+>-v͇}Wna 0xJ mlw}ew^|>IwWS@oJ,C*y!MŘ(MEWeVNq=}dly~6s<эjomr$?'RN4+%{i+n} ?s헙$k )-wwȢ 4@vD?wqPAt=0mW tw.]WfI2$)/Wg!:=ZDxwuQNĈ,yuNh8H*Θ[u? .0u䷳;d2NķCH (_nꉿK+𤃙"RwvQcVg1?}pZs?~\ w$O'b=8C@Pۺo#n{/T{:}r qK~QoBh9[ok'##,jq[bS2knoGHoY0(V}Kwt4f$RP PqsC"ẌBc45B2хHɚŧ23;ڈt`ǡaw1ꂨ=ICF)\!׉jW"ȕNaDTN! Z-=B5L܉hO[TL0@*R]shBP ($Vc+:VSnC@23Hvis ᠼt|F&[L4}qs9~FLѥN.|jlj/r {ۙqZZ{Y @=N(VEfD K̎.NzJDz Z7SDcZs@|fxKיQLm?ZKD#p$FN,N"#:&49nèa6Jw%!EJӎtzUvI0 .ImO`Su~JL?kHumV}3lͲŌqAĪ'(uͦz0Ӓ#x<?~_xbQGuI[pA\kUӾ+ENܶ*%>LT9pSAL 0QK`m#/x\a{uK#n[7v7\Z!KV'wnmgrHGCNaFٯ)_fܵg!lp3.-8턀~p ` 2 _ (C/HӃpc0OQ SQ;9(8@Uw6<9 iLhO&d[WbZarADɱ9}4I {r׸pIOCBhkejr̈܈`Ԉx hr?1:H<`?^@ެ|*`BQ&R4θ?Р 6x $~&)ADfz}n__m* 6 uu/#|V}؞8Ɯkscfb>x͓j<Ecjc [ĵ [Z̔_ywe"o <7ZUOz\%ux yA"_ʿ*vǰwZY7"**R&H.{T KKˆ+6@47(\ǽ$V`OõD Ȏ:qS7^^` KmB j$:\ `j;lxռ Ɂ~S#UB"3sZj ;Pdpe!.%mwSOMTX1l#3d6DDƒTLtܣ_ǻjќsyF5œs_4+#tA=`f^I|=NBh i+'KͭL{7ݚa55Vȿ`o_AkJ)2gt7z~ʡ΄>hO Y?E;) D۶ZUj437EÏ1" Q mqNµp01U19{DS E#gߑpNaD"l+M 䔙YMZv5eJSpk yf0Ɛq<+۠ W2jDCzct6}%i]t#ܶ {)} ulb**Lf+Hr1X\?`3!jڐlWDHD_y~ǿ=ˬCui3FdOFkT πq1VZ. dp)W*v~e\b>t7$PmjYXIHC3uY4 M0~@;NHȈx6sũY9Q2H4uCx1ќϞӡ^7yw^ Gkџ7I*6s!!`zD6;/WgH  ؊e% a$* >nض90^]D$PZgٳ]*l5^%V.SyFLT-iSٛ R^ 0Xk ~J&U[ڻͧ@ XS="o|^,+rylw f69ԪJյc@-X(PnA8D y^3jˁ=#FAS9>ɉ6@0U2>Q@l-AW\G>X%cW;e-u^l"4kFgBbϾ7|gr3Įʘ zɴb`QcyX SQE,\d`"/{7*蓠/eßj]UY?9Nr1ؕWܠY*AK9ܕeZySEE|#BCfvNw~W @l1 ޫo?<ÿOg$&2RG Nse "Lj RwU3ڑT1J׿D fC̞ZC ַ]MYK^HŜKG]"7ԻQRMqY4W;9+T?hTV~3bo-UsԯAB!dy-] *-QnTQ)L܂w0QK1KgEL<,[RPƼ0.)ψ;|b=A:֑@Rq7N"2Y_:*WY:4OǼֺԽs7AkYR?:ގbm |$aT?TSB;M6QؼϚ 9___kmLsc,emgN \gfZ2VqB)ʻR"w{KăE %i9.DkpuofB pnݠ4WG-w =T\:C~?YĺΣ;>ٟbɒ~?#^1Y6UcA(\_ (qql.T4-11 eXtToN"8i+ꅅ |>!aӾGvʨjlDT'ܒw{IM,D\}u!dMI~20!]r"zK^/"9'o GdRƇ)2բGE5̼ #tLx?`]u;jHaaVNfGt4|Gt}32 ,`"J8jea|dM7;'0Yqj?g"&qAC ZJke GUSrokW1 1dz\[2k'tYĢzR$W$-Ur*qӦTuPm۶m+\{ז5nPV=h޸M/RWFdH43 <$or$FAo*Nai01%K矨]S[K|cF7$~yMy\sNJnk ŔN/܆JPd!_3ȉuUK@Oۦ7|ǃcTxz>9n>ORв{õG>Arˢrq7hN?]|wdp;vYde?ϔ]sfII=w'pNE7(a"V5>\-\.pgnDe|/0( >1[3:Z:%"'Fϟ:H(+!=9L=2HWTO>:1g6X}גλ' A[kGj%F<"_jx>:cʸFzSD%?c#5xC?~˿SF?6U1ZA;() ]D<,%^40`"S̃Ƚv_81":} J_fTAUh,4 Lacl$*5HcnHjb p]].rYkǦ㘓!eʓ-!7bN z@]ά @,նm7ض 4Qgm8֟gcw B186c̚<N8c<X܆suM&b[;",<[Ad%iLz̓(cs,g,- D$fԺ590Q*ߍ:l?;uƞcP6@(#qD@`uЁeSD9Š!Nj/fA$1ȹ@.*cNE@P9F^p(`慡UVÍY7"TNșVM./hn ri8i)ւM]KW "Ct,.!1;S5&( $D 1Sl }1<2\F4TAl(3nclDDSp{Ϣby8 fSoZOxr@A̼ RA`9l^T.oLd!("͚H{H0g b_{~? ~o_CZT%4>CR犈јB Cb|St~͘r]϶mՎ:LcՀus9z|̣97Huws}TCz++÷m"ѥT`W~iEX.Z5ضHf9:5 _Q7q}0^l3!Bp㬖+۷^L8,1qe촘4!ʡrfv;ya%2p8&`T` Hd(/\<\p*禈=N[x2FE W$GMVՍpQ B_Wn͇y}~x#%qH/q-rǮIfl8tTSS6uC/ZwA Z͘6t3%e2YII"gJ`0rP1G`&H ]0Nw?z2is9ț7Q!t:D5gB6Ɓ22ɮB;*hvFu=2v"u&O@D)ig Qm8ӓa&߁YRj=5R2,"] }7K͉~.%&vS~jwc5uu녁 "EO*c\ k>BƯ%bsX?o`ډUzD ifD$k?2毫_d4Ȁ 0`]:1DuYUJ :m"}3;v'e$ڈXϼg{Wϐۜ饞Vտ:duxRo--yj8nmn۶`%Z0XkOV%JޤuHkо 3Յ4^!AA:+GRǣn'qr^(0zPqC*i&|'=6Gۡ #hD猃Yih` _zp11SAcT;P[߮g i_^! <~bKzStcU!&M&C`/ WEb>.Am/zS7:cbwӍLq2uA ~qX G^⎙ ngSq. 4A@@/J;#Q L3N6Mc߿J,B"v=P q8h^ehX5;vMS D Fyi+J60s#rTIl̢n bI_2  =U&zvZBNRU9 <@ԩEG&zRQaںNվ41AdJlN/l4iȑ?ʋ;ҏ} ׶w( bv1UAy[bf"1]ѵ2E^%T*D#T힡{+\i6_D s[DOKQk5.t~;Hqb254E, xO)>"zs Pwvi>ĩblkR{Fgh=!'ǭXľRKwbF+/UM۶^qfAs{)$W%rƜ8UI]L_=apfnOl2E0@BPSSFYRϬZG^S^5]?1-ҧb=xV1~+3Oߒ20ЪkxxWD#|??ܒѱQն @hr%ޥocL;7ѕbK' CK&faq5PCv*nR@xDpB m Rfb[уԸGY`7_K7!}Rխf*Bu1y+F`Wˉ>fP"vYפ]@pp/[vEhf|lh>nY27!Bh0È|.03J)`RFMII(kw])*vpEӴ> KhvY;tsNsCJ d6fP<-]9!:^.4EYUɹT+3$i828y^һGPR.X * |/)Rwtmn.y"i{lvo N7|urO[^jȜ-63Ω\y{=ZaVA=4OojUgA93 w&D[Ĕ w)\47Z]>1;L=Noɞ,h\XEqn&ӴYU.k?}򽿹k@ol-t'޾ل.I$d&1) x h츘 G+ zd `۔c'qn[蘙|9Ĉ9MO1Bj?rka'C7U)`J*uF,sQ "s],:S : 7@ؤ2Ț3Xm/y>U@T Pc}}}Q3ED5]nP/ONQWէh 3}%w1U]dvPqVCygpW>Gb59H3!H۶UDfU#FUd e#EzzWD(jP/뽠6 kN?dwkt;s~_D"Hjc%,)r! ;L#X/f U绯V46?8::hL1Zr lśxϓh.pK,T'hr{>Cȩ8O<:t%8LU#_k)ó:DwaO܄}h&"Gק c$3ޣHx&{ 5k'KݓKA4 !) r! 9p0@`hqUɤ$Oqx ˵ܣ $&bFb׍df&r,f }ѾBMDAB92 n()s] A1W3;@T]~RDa>k-3)o`@&<L^N$4CMSciq8ڋ?j2x۶LkC~ `c>Xu"}8c cG&&"0|m+ |8)L;<ʩ9y /.}y}}׮9"*&s @jI5d$cvo0S`Dp<,1<^c_J}t8c$dt*ZhLlsWÅ_?^;?y$Aa8?sȂuqx~XKD1b{?h{/x~V23"cgf #8|d㓈^TU%z-|>x<%E DKc+ِ*ah̉$TלLٍFDӅ42+JDD!ixiQ /O۱ m3-d6befO*s?qލt(bx<@@ ` 8/ZC-~^4'!,SY20b0a`N(Zx3{;D&osD!kmLKU'@O7Tcyx PRtQlw||. G"a/Q0EA [P]0K>JṀŪjӀTG8BΈ}20p$}n}< Ya4PX@%ް1nRq!#: . A]bWB:=1k#~հ5<>^%8zlLT0H250%&d#"q!;tAͪNe muZNo81=lɁ qc#n4=͢q]fDp-@Jggn#,B ?L@ڏ1.Yk-]c7[B2եFȔpÐq2"D8u.a@Dx{d\0#@c*  d2&aAU`Fbj#Q?kfc-LCi۷>cu3@ɇ;śv,ny"1mGAFΩ5v5=5sE\\w 2<ê Qgkh?4J7r5`N]7e˖ąt:4q:+>?;'vYMLnwѕ:PhCge756Hz1g `)a$*0d,yPĂ@dM^ |">)C%FTlaOnLbV3 Jp#J h^e2ADR3cL_|BٰuΥg=|!Lt'=$_U.W&V밄l^&k ]wp"Ja+P[p[[hWMy9T{7jkt+tES P!ӈM% "Vsx5XqCՐC}\R9eR53BR5b/ ¾&ku Q')i,͒Ј3Eٵh:\3u.v$qGNOzս ^:샦z.v*>n5ol^ߞ\6+j6*9 WČd(To7xDH0Ls!hθh"5O,NS 71bK.).t+/W xriP}\g? j \3+4zÝf$nGֲMtnog+_8vd){5d%߻'6ON<"pZ ̌N~Dulotìۡ}ocuR@48ww$ iI7q0"$Ge NtőyT' y\W?g\8]vB8U02 hg%V9уiaM % Ĭb=E)q,Es4XWݤ[`P* (|3fq'ATtcv"KhTүU@N; JaB@eԔ:gg8AAcNfz$# o۶aIAomfaQ!ݘs? 1ZDח4` @NXjXMByY/MRK=A׭{>:o7\^8}3~ǪC=FWizoLNTnH-jL-7gQʡNBp57khPj PdvGJ˯vLJ.;񥉉:Scf:9ХXM G}6}]]hWo x7w AB@5*U-R`Yju´(`v45Ck j':VLN`}5Z+㍈tEHN1LOjh?wr^.kJWU<:=ڝGZv>OۨQUUW8 `W{[qo :.ګ?q_B4P 68l# !{IKų/mt"LU5~D=D@[rgfwMA* yTuqhxI*7Fn2+esH(o`_}xtsoXKQu3sk~Yxlh8 -,cѨj g6#7Y;]4XCIul|&=3XK&yiy)(=:DLF`jW@cob 쫟j&BXjNey-2Ɛb-^3}<곤ֱxk;2=u_||鹿}:w] <7| c:Ѡ1mhiFꢫCB҇cHؚ|̣ٽݕ&̣jzf7($"#$<99謙c:]NS=Q]lf__6]Dc~vHD/̋z7wʓOQ2\S9RnE*Ԣ%"FZMYyxSbM/NsTњzA|6-"zo6>EG˩qPըjgKޫJQٍ~ycs,Alss2Z:<0MɱM_3L=S!)V!r'IP`k= |~`-.|iɤ; >Fwɼ hAx|is1p I`T> ķh"-*˫ɪګCL+;Se6X_[!us[^˙9stc泠W>ut[v:/j^9椚8+-̦bd~*ڇeN"Xֻ(9bQx'5!bY[cR[.Xy_ofhח6as&,i>Gic e1_FfE8q8>9mXd ]f̤  <&qΡ" yMj-k 9iV4mtU"Fzz2S oü/3;~S$/j[<&I؃f-q@y&̇69' 9FS] 6~{}P QUv(LMGNa&f6^|\vQ=ϋ% Juߪ\#ٵ1 _inØw0O0I<'EpM6-Y_WD|'Bf cb3boņP1rL39aJ~q{ {6']&J鯗*1 j~"QH}LM~t+o?dYd I}{2! bm>,1^yJ6S`e!@ CQzD]9KnksNܜҋ黾.B6n7} R}knCmH+ 9"EA9!8ZPmh I! #RhN>}'7b҉M"ǀGXDqf3Nuկ1`۽Zkny 1q_9Q" Rbޣ6]*" AޛRe0{IRAsp6i"2oٙEqD4sw c2& 9mXZ;{oʇMm`kXk\5X*Bbɳ2wJ YeL/ tۢ6ɊD[PN}+Xowdb#ӬD@fͿ"'4ײN9f }²avD$ U Zk0ǯ_`LU߻#l$k,L*ʸ125Ul?c`NJ8ǂnVc6v̈́ųGf9!y0nmDR/~M!nt%On>gӢvdE4Cm%{ mkm:6Z9'dgg!4o@`Ld~UmrEn4apIt"(7pC#F}̯}ͦC2ETzHS"cPm%~R_kC)c%vǘŏ~#" >~_m~I2&DڄO_TIM|0]yWK,Yy]܁kmϏ!^sKY^h)".Er="7˖yB,)n- лHxҷe-LUH'BI\QY4H#/m].dYj?؏$oB,"dS>)"zY6yryN־4==9S@%Or$ QPP_&,M`<p&2bo3MpIX~bwvn:')yC̾kzd .֘, [vX^6=Ԭ*C;xŜk65 ;ۜ~`+S8z͘7r2 [-}»u)(眴Ss`39X,(YlRvuP& >燮̱4mW{Kȋ=Bw8Ls;fKLLqhUo7-H*THev[kB] Yr4!"bC7iC}Y7f%cl%ƃCw1Z=ԉP`=q`!+}Y#E @麼?s) BUܦ쀵_(L=G$oi~%~`k4VTUFH+(P=溷瀕,3"4~ ?-(uh^, #z =Q HU ʸBc`v 7g:2%*}D0zbLY> xz1Z {PkmX݊$~&lLJ V?~bhY>Ahm4%]!D_w0 $"DhL3{rJL&/i3ABAӗFUfzLȕeVkAkKB8g ㎕Tp&7Ja>n>nq>BxX?Knuai[޾Y 7h~ŒjRI?;8-%kf@׳lMDU.`DX01QIM[SxNr)3B|jZXcTWTb k#U}k(>JM-?帎\{mzpjG^C-`S5>]AH xT~8MݱCT6ih]UȦMar^sլ`XY'K2+,}^l[Gn)Ak&`Y2l;"=pT9*oT)O{8Uw*ai{n$/k|U˴EMn7R@|JhU@' } _/TŝY^Gc`{rmm,,'x\񟪬~}SeMt_wV_ڱgz-g:<?Ͻ#'"TeoJO {痱 &i9p trzj؃U#¥(GZB?xmRrLy9 !VR(7ky2#P%*5|4CqSwjt>ux>*wnMuM@"N+j29w BȩY|񝳌 sឧ eKNI(piwc̙v+}JjqTZ3@df9+, $8VU ),갋 *-9WkG<^J#fUjQ`?eR7:@*g?_|γ +,u샞1G\!z[j1n :l9fS=・A$N* ["B/^hJTjih*v}ж2y)r2ւof3yWxsm1JoOflĩh1qR*hUciոzf{2w-dnV79CFR;߲roᕦF+X>6&Er۫uqv7]b>@7"#v}+.ݷf=HN17fD)d>G_y_iN[ҜP$Z:I/x? o S=fnvK"sv6;:+HR 4%EE meDGҖXW!r\)teѿڟ!a`LO˜zb!{_v}ˣETD9ǂcN'%D0R܌H}S=/7GzN2oLtEkNFM" W@2U[^y܎DJ <Ɗl:6Ĺpb~H=̉TXChGo/ IU<)L,4SRbvsaffni?: QOr\U[X6 '=ρ2m┃2 s?%,4Dzsjg:Um@VedvJ@ X~h 0 n I ~~6Q^\6mt“K,hɀ<才|}&H<ڀI9xc9}hK~=hT*>^C5D>kW%,,B'ZSHvb 0k*B$xY"MU ƒUs1]g\}0`|_ep1A a)D0o+KyE蕦!r{viGq@F$(텱 E/ga{Eà tTf g71GӬ4=:!)E;/)X1y'rDpkJKUR6N&\n!9-V_$K/կ1?h_ ˴>@>Lgu-z)GL=LX1խʦR=lwۄjg7!ۊ~eYܓa.2'lrqS N8k$.c ۙCtCA&3`Vœ?=30xthgkTncЂYv`~LiGc| p w1sc"C)14 Y ,,C3?> m,wQ7h8 %|LZ'VSqMlj~,4UU5Ɏv^":aO_-_['4s׏"I~a{PT2L1Ghߍ$@7)nz(nfq ;RWw]y?i6o/,x׫z_T.Kp]ܼa6if܂4pvU,$ii9 ŽA~weE>_A$rݥܢ71C#p\)͵G8 )4*\U$fPse_{(ʋ*39v7JU%@RЕ?H<Ƅ愋j+d$\ "B[[6.F5n0rGi4bKpd„e<νchSp*V2.mT;uH'T5KAرi +nhRu`:B-q7Gqhpz<cT=8~ɳC+qJv`ȳWɂ&pA(\Lj@nRʔ*pO DPpNlI땀W1"YZ o*P"Νe7{z:W&0Q.6 .,2aJAGwVgpa iP9KD4Ӱ"iˣZD{Ou>و> `i!6f#18:#L3NyyH@z`#0( 3j{0ZEQ6pQf$ 7i4lHG-*Ć*3(s<0 ԓ%Uۘo\C#ShX<ƒќ&Wy2B +dGdN>[B׋/Z@'+8KLҙ fB1H.\I>"_0ݿ ieA

yo|N#Xl-x>m#^ӂBmw0F-}v6ml)HUں5d.]ݑu,DB}Vzَ#"؆jw 'Q'yh1tfQ-'kEDcݤ 6Ow>mzژŦ8Z XyQi4vq?j@D fSgı`I,{h&gm{:(j6qD )\uU:{XEALLAMѮٲ5E\@a1\]IWRU[L93[?R#:Pb"1&`iWسÆ-LYBXS3Q3YdQkMEƥ,+1}+`78.¾XG~NvU~TLd W ])4f"KIK$Y- e ,Qþfi"dMeFd a_&Xt0T+Y,5#'"ن!M\ c.SL &"=̱,ICݖk*EDά-`av4`w! ")|Wǫv 27Nnga̾H58 ,#b(>tjffsr,Z3JnΙ>nLL,&\*u5"B1|FoG'!(HV+J(40p4ljx1߾3n$6b HUGN3J<1wk8Y,cHKC.޴F[C+͢,$c/]]&(æ;'&CJ5-,̉M#?FtH7!H%Yp6tK\ ff;0G {\]9K_A>[Z#( ypMq7"'( sCnHo`;j5g-2P0*?hT#A,/fD ^j 9n9&@ Hh捘" 0]rn}Yo)*rN|#"~&G`KYe[#4ՙE{9# t fߎ|˛w>퍥\pkG0/șgL\]V䗉juɝ0D5 Q8YP_. G,1Mͦ&K٪3﷔/2dB@ivZEqA+ KjTsfSXX : ^sOy?o<ؘ׼H2Zh-Ť"*ibM; _w^@3-< OjGb,E,.EPh=nfl(Z K!!*k(ֳZ3KF_{>M]n .h8^ޏ9:Uwy0*RSj:w%؅1]W$+і*Sn\04رEng"ׯ*zhzJ9*?2>O?~]|f^9ًXax9˙HpjjBa$$/n5?FG!{EkRZkOPd߯嚻cw |*U:R4'!$='fpv>A&aR4mLfMn˵, N9^W͉yQ Љ x{Uќ.4_7)gSuzovxr=fCsh9/ޣxXhE^ƏTYDɽ@D9]S~ն_"O ={7YD0Qu@Y UpI:(a!Z1@72mR0+yw#*L ĶT N1m2(kħ1hy :]^mH3pF74*pm<BIJC3{N*hq;1IQN<&+* 5;pM97 "⓲)","hoTz]}wqOYRMr7DOq/֗8s=~'bEz"Z?q_zSeZW @pAy-N\E7s'=wbFOt֟{~ֿe,nzE®uq5% r{OHWwȶXf!]@Y7Փ7~,=r/ vw "RAHZL![Lض*Y0d5av `˚F6i#]/uSUӐo I!QqP1yXop7<ȠV>OH آ+S 7nQMӠ/9ޏj Tܻ},zڎu|NMڮGę!ЅRY׹Rge-B_7]jrnf܏a%Zᬄ(#0$j!%1rmƶh+ޓےWC<'a8bY-9N;w&{ܤI/3 {$iAbQ\V_ƘcCC?>=Ž]zݘv2^$uwْN:OwC-* !"3U;l 7 cЁ V+./VF^0_$Ǧ7홉R8Dt֛Ju㬷sr$p WmHLI>ׄrJU0{) 2ݟòH<>b1?Gx߿n+_r86%rVpVkp{0E Η/9OjmMxl~4#ݎ/l`3MyFn%3fnEcWvF$nIJ+̲a&@Z[f}4nBzN&r ij&B#OP<8wDv\fP|7cdfM]L[ q, h)Ջmk*Zv-R\Ftk,JRY^h?c?-| E*Ԓ.sIk΃˼7龵ZpL:~_?=,K6>9'y9LGΉkeDx;0\ve_%Qe Ma1<\RBN~%Y@̝T|Gգ߷`J)c5dt 6hPn{,|p!ZӨ(' sQu[Y4mB Cq|!_嗇!gmmtݐVjs0+U4U$#0f0ќSWibn"L惙[DPeV0'"fS`QjF6"@ ٜӖZ)x_v'z^.Ls7jM J&"¼ksS)<ȤI܃#d 7&fmDM;h. 2IV#傠ڜ;xN#ail>13Q,aMUoĪs`"ª@ gf2OdȐ9HtfŶJ@w0u/(9ZSa@PW61?wHVGa޻ *-E)$ǪpJkdLܚ`ovQ,ׂnD]bv B1yRn^ f(}]!fޠ» 1?hSfnn0¶)*P0̈́&fnkvȣ$ﰥw"Ll?fa7ښoǽ EuZw)4)?N ?==c\ T2J#ļRTMTG~SBKbiܷI،;+dUNɳ۷9w}T yds1wIˀ]O o͘:jk,+M.zܛ(CfMQ)3q5P"n߾([ 3+07^DK]rͅEeڀvlSmn8gCsN["&Nf17Qv(weQ@$,TyiUCwo2kvb)/D~__ l57+ x˶Z<]rsq8Y9g wXYTaaЦI F|]Cm̢Iga"W%J"|~ݮxO'6w*X,uP9 KVA;+e9 ;=|EpZ,bZ8K`5 w2\S*L>Y%lN<c|b]9̦Mf֪Un瘐# }gmnA&$"X*)=39ȇ@:XA4>1R?yo1- \OB~_&\cU"w?z#,ai4hR^@%鋤&[FgsOD?^skinnwK`~9Wp1Wi× VQ6<\6:L<1 FZHN Qص嵬=~Z/q7L2~J6! v+)<%h ,Dc O'15!v\L+0thܝRS/rV.rj$s[@|^MkPU%1/1ea5|:0mc0t5D~eIф->EgFuK+_{Fv\QKIOT}ُz)Y-ȟosם|V`T:ϺGpS| ܌9h'b}lk(?3Ԓ,쩅/HMnIWbfɥ &L4F8Vzq`760v %(KC0㸂 WDpfVn˞TRk.-C0<,v56czN?v{"s"/E];1˒E% u7WdQb#Hs7"m9s7m:{Ef)܍(Z_^XVH3 lOvקznvI+_s&;ZrY+{A*W(čsK}XoldA"OtRbUӂ^^ "|[4TDW3$xM%(0ǢY& +U y?V' /Ѥd+3{ka0i_Bs[[[Rq/ZgX-PT$u*)v~IJacK(ATkn F$'3a_SZV4gqj-?1eP.@\I& o W%!7mǽyM| 3V ̜Fk70Zk3ɢ 2c.9(:ېyɍI`36;YDܢKLT o!KG]9 JpBXbe\V=p|ˮ." +볎M?YR7`Y.}D$-+\,y> 寒9_RLkH u!I(V\?"hA)HZȂ{/~muZp h֗hFጞ,A7[Z|N"y8v# H)N]nw!3KXɿ"{|z"sJ [q\`9'|8!GFW`RLa+y]d FG럋*£JDsL&|mNKAwXs֯%VyQB-iAfLOu`sr5">XSKVZ@\% 1'A{E*3 ؄pUyNx5hME}:qWwSfXSW LeKI&k"O 3vJe=Bm+|%(=uZT ֗I!0(‚EZɉZMmLo)blF,< I0ǥ[{S* GSlcܴcp|A V!ia BhT~ya1ET5t 9%hc<NLltQUR>kfs^վ&Drh렯 I<`.c1'Y@;e =L0nSo?? ;کW\LU6}ʰ~$/_g=EVJlzƘ"m|@̸z*m)Iƀo9Z%(23['DԜ>~_rͩH\MIL.4*! k L9O|:63g81i* Pi؎#fѣr y$!T })Q$ yHLi@Z2~){EY%=NH?l"D$ =f ff^CZ^Y.E݅8X6sڽHŰMoQ9A>ާJް2Hf-AVxWW hF\KŶfyXPYZ 4M^ybnfe}Mۯ9'9˙/2ƌZPʭowk54 䃉Rn3ʜS%a#ak-51V񸘜{AR~{Ջ'O1VOzci5 (*HSPZ\GnffvF(B '9D 0CA M|o *SUͮ0"޺UXS%BȄL(:?㫽~šA鮽Y4{&d5 Lu7 ΜfL|RR=( QL cՔ ;s2;W(CA =xILRԽީ(&폝QnZsY=gZ[7^]}nwet}4d9/gw.ݒ$90ȪȎW 4Te8 #%*2~9ߙ}N)M7\5Ly&㗍7]5 LKUr/ڱĴosܯdo\{_uTÏr:3F7@c\Z=WCE)"f풥RX9.\)Z=:&75#Wm]~Ssb-1 ^זV>"@ÞW!,"$& 2s;wFDX&gp*eR(ݭkܞJxPbR:lDFَ_3)ƛU X4\2"QEp/kDCaT!~LL?'t?QOaݱ@n o+ކ2c*+{_=#dލ$_SUfݤ5U(v`%cjfWIGFJd֠f 1"AčHWlEy&?773&3uD ?D4M&,IYMR8Š\¤MMF;>*mVfAj!l3P80|[~}q!=*șfaQ2F2=Ue/TלṮra)E0+0a?dB2()`OԂ۠cMHJI 4=: G"%5=ןj$*+3U) (?)!"FcijFLtfB"J_˫U](YG8<[3X2TDE2$SQ&$R(MtNH-:+KN>/4Ed2,_?bRex:=fҹ>VPL|\ dԒ$38}$jTY%>R#xOå:w6M*dKokC&$]P7S=J>,)"Yq=ƈ U拞7|qx#;. EK@7\`ZPPX7_+Aevg4xx%za2 :|@$m?|pt&,D)SUÃ(Eu]#HLH{Gw$~x1#P- XƀU0chvBG6z׊Oiu) pm%"3V'3H̜|C@3ȷ]7g9xqe)LΉa;m[|wYѠY8'S(d7&v4hѰ= yk 9+|J䭋9Àgtv zv Bתu} >._kYzQg6Xuhb(-̕AĢ8\SZ9׮КL)9c+kkN^eMdMID&b')1 oN3Ս&ﰏqO\ 1hV [9W4Лk#&)ppu&5bߋI?TnSY#P\΃$Jc=uw3gqWF?i`DPl__zv8 5{$+c33:N+ߌI^k8QZkJ̷n5&S,KNKRfI$ Q"aQQgUcW!!Y =Ϥ1jvpn2 :CV+_3Ƹ<~GN$h|)cψ`lɫ*`BVcۆiqXLO@bJC"|E8gѢ(1#߲fga$MI.$VK5p3 ̬# hgZɋw՟_1HklV]w5NkMh=}d3숧Aqy&AfFEbk.ADO~9!ί z+4vD)F 5=(BU+҇!#y3A,y¯YA^ a #"8J}U3iJ'߀,b.D,p$p^{0J09FǞ[4$fr74Z4]73>\DL"n˩pTՕ#%IY8f=-djמN'I` [b5ަ1;N1)R17O0 -˼k4 oNq]y!' %vX3f U UZ; {__ϔ&v~Y?JmŃ.3 /%X(^JMR6HTDoo'ݳc?͔2'DSՉls6O{X2v}uͣ"Ț"pQUSS]iO9p&Du! 0yjt~;w8-zzc|||<σ,o&{de!m ^*{h { 8ݬ1;U~,cx|]?w$/S̛Qq;=NYScif&C4&bX&%p8jG(9T6G5]a|9ni*(T `VYV շϹx{00,Ӓ@) Y"|"a~nff ԓL"Оan-bRp&x.o?_Z*?oT8?o{_>֋kw*F Əޗ5ͯMm,Wt7P[SxS1:lU$^R 9C`[ʕOevw=;)? IK @K}ܙ:0qL>,ucPzI{ u, V܇0yYnP_WZ@bZgldGi+w#L1Y@ndj̡۵\ ;')􎌐 OPTd2gdR fJ!j*Agǰ%5MFLsݯ0VYΤ=/snn7bDǸr-H rJRbUg;G|qS# xK.C#lj4|v:z`Vfʙ)Ei8TcXVgA.yBp<7=)#ע8s,縭?/oNUV4#H<%ڴ^)4qݣ}2xZ2R6@N!E{F?EZ]XKeg-oUO{)"TMcZ*nk(٬ݨ.p۽梄RRʪӠt fMw&YcwTkp6鉣8>إiKTQ) 2;ȍF&*NLšʜH\-Fj w 3%ӱ**1 dAD0Re$$&,s\ݹ:3Qs!x۔+q̠]B+uPJ藨IdգD`dRqYSdcy SQo &O\1F"LOjD1+ a)"*NaAd㺮5 (zVo?T2%<:B@:[AX'@CTZE\ny>DPATݑ c(&19魝ɬaGߋY2)"ǀlrĽ 0Ŭ$րGA{_ђiz0}DbއY}I&a+)3g^I(fπs5̬"b+/G2B'PNf=UՈ%`D!cjJ ́T&JUݏ=fwGPc[15A} Uٙ,DJ9"{d'vI9534(KV,=d&53z(=)P8ZtFh )~ 6= ޷ d-B$ؒ$HzB=Ss .O3fD q3X:\w+>OHc"3qUfE7s՟FfUq}l6j_Ycl!gVdeۯ;% -Nv!8;o%{CO"Ѐ?8|\;{bZ|«_" 5<]1QIT@VWJm旎 [JOEJk܅S px]%N/ (vj),`ZN EFg!ejc>FTϼ,۷^T ]d6]h}}WƮVΈKaY&OtTxd*JŢLPk: |EII;YeWdh׺kW]5gA8 IHB239ck9J ^ ;`^ 3v$"=S-b5)P_]c-Y&k o9'څBM~ .,@Yl$ RF?%"757N zG!}~=ITDpDjDu}Ilǝ.a V=W HWYFb' Qf[p( "{Rެu]@vY؉}ˑ(=?#JqZr:VZ520=D{[ XHq],W!5#<+HDDIUCD͖qFEyvAI/"<(LQ &ZHR~>|09a7]-[*2I>{ .0N#Jr,%5S$6w0Ú}U( (I5F"~gٚe¢H҃YBbF}qEFLQ UآVꚃBރɃ>~|OlIyuCUE52/Pm* Q&ܮoBE:Wd1Ha@#i4)%\1V*Ǜt")qx÷Yf%VTRylFܠ$ )CJQٞ59ϵ/_7ueU ȊR};YE[ԉebU%P DEbZctd$x?sqfmPJ͆V9GQzۛv\>'`;#fM{4Xc*ΫiVҌh( vf(9=UǑW˒,PizrW3Fƙ9bmf1Qw<iKҬ2 _c_z7\i0c3ЌK}]~?B7`Tq뷨D6N7Tk>bb^>&68sywmJ냓 1~ȗe !(QmD@./~lct3c,|kO|58쭘Mԙrw#<<w%{\&J$Cdw/wwg*D/_.QedYhI!:T$!1Ttx~P. ƒw 7JVH[I3IZk_UVuwZs<{0C\0D2QUϿ[8C6}g^p0qZű;@rNoT!|RDIQ~o+>K2MQZkֵXTX;/֮2l[Bp,LZA>9rJ=ˮU&=+C~N%{]@o2͈L{&0~1""7lqՅ+O_ { 1s&x⯳eғ!HKYYz;D␉3Ã_BM->JZpOwW^J?^K ̔S/D.Bdw^psDID;E֦~t.F'oĶ:.EQD\ݵ57hh#`DFY^Q{TNBX^1J9i2,Pz8`Neώ@i"<<l&n䙑$׏co1Ya|sA}7Zwf]lD82LH=TE-...x]!R3QL7X{`KW8)"{x>.Og`Em;ωeZ"M`+͕2 )Pt 73kǒfw>Hm9VթXic#3S"!GDEnC`֜9qm!|I5`ov%B$U("ϫ565~])¢jj"r'aXJ+gge{ _KGl_20JZ@[u^ 雔ְ/o_ޑ]omk;.IADsf*Hz+<=q0deJUŮKQ!U > 9G[\Qĸjj"*VMxYa&~oQᴰCMS&eCW VfL kv3u05$S-JOЊNSs;yCr׉ TUeIv;π՘"jQ߳%J,(Tby~krFOnP]S#ۄ򺮶ŇX3i)Pg6X06Id\3~7O I#-P跏#]taMxEHDH'QxR JG/Mc3hb}YJ2Tdix|'(ˈ#`|6U\ ͣ0&ܠײH?\7rFg$LjGv>2o3=O)Tlyo"Z;0yv SU\HS=\GK<7nMmDD%g*~ UGϏwRT:ZPdJ#ZkSC9};&7D]:g 44[c,l`RcLXJ#{<\4Qf21 lJkpC%`=IiJ)I뚪"ݍ8c7<‘==`dB(^NN2y2"0'3B_ q$Ɯ>,"9<=ef^!L͚~u;t]FyWDꘇ.bswGw*h:nZmI"!XiXkGq"sOkykb+nUICg41U(ߖZ^茜8=c4=TT|ڤ5kѿQ{Sfu]Dw/y~}}1yu+\PJy"Q2&Ex\ r3p,kExɎ# + Wf9Նu_ШwxߏM<#~ߠJz9o`BLWG(=ڜtJr鑔dx(~f[3G;}xkP2NHgpf|[k^ԙ<͚m{ -|mͅ7hQ%.|$ʺӸQ*!xUf<@=5E8n,yx4I`:at*;DݚW[-_QfVf^Yʗ֑]U%ev%2x=5=#htʕ\שLr.2r"syG_ui >ӚA+ƠNȜbI1\[x^}VܿXR$$8_z* (R 23ѬӦP;cu*ZA9ܲOFk35։JU,Ay9!A @VNJ~Fp\T % wEPih DBr &u<[iL2 wT^ pr r]2\@]zȷw"If5Lb+)B)"^ )œvŒ~&AL͒5maf\muj53ǹQUvK*(2ӜjiZxbůt335_Uq1/EoӿpqO-lN鞈Ͻymꔲµ|>86"w+'Wl~B?~x>([K ~'ʍӧ8$(W++rTe{ZޙيE'45#ÇUqOWF!N-AP/>oCwLdp½ӟY +?CUWl[Hs/kD;u2{ <[$8\5־ؔキo|wyo ˸Wj÷3M@F;U|ԿSy Px{bƽ +1ݬZ!V<ޒFޕ4zM>Y몪ܰ_ u'V0`0^v{>@h<9% |A.Œp pG".,ܔd \j8Ԥ`& I9 Hzeېwv|eD5VYcw)S 7)o"CP͒I'g*>TMl1.rXNH!3!STQ`LLB\_J}XPq)*1G% =ѸkwEYtG5D .X U_'Eޗ]7jYhBqߢdKXAڜb3sUْMW rܦtv26cQDudV"=8}*aY)g[IWZm\a S 濪Y6IR"}ix$&J#LO7Z5*0)LA`ߗ-ˋٞJo}q;TJrr WSE2u\^ŷ0Ľ)T5] )&qM2TTL{> TDӛ{8.9[k W vŻ/z߽NS 5Ye&Y8Ti;OWfa*:r{E @& ӢYD^]Ǯ:Zه+ݞ7NBWN쫿O}oTr{ yޣ릍ȬeLH: #Me$Mp r䔺D t hTCdOn_;_iV ]1 XD"¢h!70> %~6kf:UAdO'+ܥtu:OL f#5E$v~M!5'y v̀!R牑'E!cB5 /˛gߊ eԑi͂2^gniF 59yakctsʰZ*e$UZi\ bDZ>ǍM;9 ]UrRU \˜(w(3qE| /| ѼAPfQ0]v::*)1?&AmӎPkM {؊BdvLy)"|[5[- ҙ0ycpX5ݯ\jl\k߲K*l$TR!75"TrH][쏆꜉Eܓ7ZwƢl,JU~;[Ώ=u+m:9T  UNsg,j3E/F f;7KP](71{9-;j>_#[~J8O=;k*.QVI~[rpRT,”,ymNI??X`; ݴ4lľu=gSn9aFMNLcɊFtǫo 7-uv9yŭS-8% 2eE:yT*Fk#0H$Aδs{3iujuj0z@Uwjd=U>9u[@Ufq@I9 P>T!tC_񽿞aK îQ\pe6\Ϸ oe{:@/㽪֓">CKŔ>g͇ڔ=dSw"{\۹nָS6k6+I8k'ǿ2LU0}3&hH'p\2Ze;O/жRjeaWmhP+VCZk( /]ek)x ZIDcF%,4 b5S f/>Eֺ[8 (]>N[t,pq}D˟XZ@xS._:Vti![|C{U7kFH舗g,~kSb* A{dfy@W|nO (5 V1Ϭz}οo2%Cu]y3KA?>Wnu$K3<D'Z̉FdHe)n<["&"$겄-Ld%BیɃ6~FIY$S 2={\ >fjJ+g 푺g{Y9ϊU}pR ipM-TZk)L1mhY%g2h0,օPEf4)9{1 {BmޮI]?m&j1x;Zr+Du.̢H"yLt~sple|^vIfpjdH6.?3,5l==#hul D#O5C}H/Q#\(=a/EyF 8?X۳McT~̎:j?*RJݚ3}}8'3IB"'GFCz>UqRz(vxNﰓUDwt/faf3-O7 .[M[Qoryc8qSXĽG8f8J1ϟ&vG?OqG8p!DLO'n"H2[NMe>E$%NJcI1_*馭z)&G<(lABM*19voin2)AlJ|yf"s.J)$A7xtvxYr  b53͙@,4R!NitSDf2l8=tBD>Da,BlɊW^:pH 12TFW1fqN$)=cDᮀhY GY2GA ҽx&z0V$>g84&JI#"E4AÙX\DX320"vFI)jgD/NF%ӡJ=3^"A!$R$r֏T Sa-c+Cy"bC"ųhhVpTvfRIfl-jj9uJf,'e &?׿[C&GhLF֔G/Az>wۅGᮦ3Ǐߗu Z=51mw<7XPpǁ1'lM&VK ,H[ Qkľ;KV+UKyVE?u=,"Z3 ͚u=<* b>'FPD n23Sreq`x!\MqIu]tUQ,Rѱp=TFJ§Y;J5M&=m͜BECS,}R' 4acD yM`s_<-;kK?]>ZC[6ǡ"=*J %o_/Nޚ:OʽMU߂wr WaELRp3l cɂ_f0Jl`o,,'e9S<矟DMS+=hL:}>ׅ$T#D U\r3f""ez]=_~WԷ_L75{}M'nM<Pe \5ؾF-]w2'c%Hš qO&e2TQ S#LALuZXRX5&;<q+~B.g Lj67YbPRA<3)9- DO$j?e+ɒ#HSu{zyA6~X,vUO'Fۃn?dfDI!Q#H=\LZ:ET%%j1V-rϡњYtx0zTc@ѨS5nl/ 15+3$k9P~TUly~O0py$xT֎N??O^GHym1M ^ZXRuZaz#< "";{kMwMR#TiLĬ܈܁bD\NGۘWfRe+ ttI-ސ3G h>-c1Bcg@ ڷI.4';3UiKYBZ a"H: xXV_sx'MniMrnǷԏ2 uɡdA-lJwü I%21j>VW)^*)XSHRW>@$B!y2(ډQ,p[y\5Ux])35;#$SexKYgSS!J=,Wn@DPˏPΌAߥ&BrH)Vv.Z96΃) qc|$ZKHeC?qD jMLDx2I*QRԪrJH^"emmLoT~7 ۶HJmPOefińmv'}?wZ2m`pf@-_sZk{_ _+#@U!]53f0mVk]Y>*ZgOiDcg]d@L=%PCԧ½|4hq0C&J#\Ye Yo 2Wּ;(Rm{c XR21 ɞS[5_ tUJ,#44 LHϵr<}&T/?~׋4,%ko~1[- rf;YuC{6}j.awt8%OaZs'Ad"{3xZ6ɽ;yEWGj~(`Ng@]lzlM: oV2f0^cu@e<ၽq31*~n-#ϳmEV jYEi,y(fFJ睷XٻX1 1F{JO2?HIටp`uӓy[~"֭ _@9C$Umzdaإ R3q8E\noD-0z%&HB"SzϳGrm[Sfư)( -MgyD M49/2״6aٶoGi""V҅(dJXzex134JJVL,+H.lfgޏ'T$kʝ/.r5?C;)[a]oh<.N{ё3F&>U+8%\xgsUȥy\Npn%"?mAHEԻ _󟾵UOoOMm%=D,3;Gj<16uٴEUݷ~J:5&޶che"q w#r(׶5Ũ SՉ)('gwIe0efh]Gc5 y cZk>̵6'TzAT6x? &𭵈>x*S耘mݪL6F# 8D4详B#ܶ&b3oM.ڿ<ϟ߾=^Ǐ+x&Tfk{?͌VR-WfZSL?Z*pN3SZ#W 0Zf `}/sFZ10X,"U;݌G gv ?UEż{xкFnflHBཷ2mq'2 zD6klBV|4XJv  .ࣹ;v.,F\|½)9{߷]qE.߻a&f?~U]U(\ .o)%YIBazE&4ac;1obfߙ%s1ԠʨE ]yKP TE_-$* Cs3Φ hgnhk"˴{x0T@ξ2/ ig".DA#R# s6Z/ aAӏ|0EQ_\v@# g8=)& PpAB. T8 fyz!=#%a QmdH]RLÀZCSF’8NK!ﻪXyVS*=Q6O%%y)L=n;$55&PPL͐ɨ^ LY%P2QAMėִě)0Ejb]}?8.L B )UKF`4igYj݃J=~Cs1D} ? gcco}\UXfƪ7Uy8dR|$3bVE-_T *"&<߇eLO]z1( T]̥;1V(#|@FD~S#_@6 q_΢F Vu}@) ^Uj@ Zղ,&c/Fe~"wvA ;r6|MՌ1d=۷L.wV2n潚Vb^NHz2`!6"uEζc@ir%G,P[(5s tP<:>䫧ڴWLx^UMȉ{l+}-絘>7D %.'B̤|<(n/'[lߠ%*+yp;6Oz]45WmJ)5u,7IJkoq^Y|ҐG[% )Qy{{*Q%"-c A$C$p1ɦ?->N)i/WU2w̙ai8Zgp:J5е|WMl; p̬zzMk xbJEfqp`L`lYZs[i[Z `)3vm}; Wl qST55*grb6Dc׼SK7&m=>`Ԍ; l<ЌQA2hH(, #b\s"_|cЖ*`uml?i~fڳbxx2j4HkXX'zP^ޞYB-NFFN-awd̞K榶v@1`8p* myCDXfy /@}6NͰ%=fv4!n|sp&H'6WA(Ɋ\~x#sBiXEj2U 1{'$le>m1tbJ;+qj9ʅZXq^K@ҙYb*;)APkEFl%mk G0)1S6, 'lazB%?3VxgQnjUKs Їᓛ3_$g6B5n-hʯf0^"+,U;s 2oڊjRj#: xYԑA8P=N8VP&;J!$' Z 8ܵn`2 xțXд#1@ ɺfkn<)!ːśtddbZ|~dR+ \fv ES[NufA ژy#?K*asz&ft]R"8^x?34i!:?IW9 ^ lR,vz^~3q } R0=`3k`۬tܛ(IS\k&BK.ɲXKG|VM#rh]Ia$QšgxD܄m0[tTEpuDzDq_=FfSPg_xtG*$ .UPZO,Sٶ,=HOg(,32aJ_Je&zfDŽ1 g ˪Up%儵 lo}(+~q &Xgi.`(4AUtZ{*پM"0Pg]@vDzuh* @)"$ CX]ogRgE<:} KdW0(SaS"~ 44X,%0ť1mߥb9<32G k7Ft"}{7l֚?[ӶiWۂ-k; XU־G3۶33 ڻ+L"@,+rk4|Q#BQ3@/!'vfmd"=e?YRϣvPTYZt9zjrOi801kgHBzwj7ôaZCf$^/dwzjzg vmrؾ}@:ZUm$>3V ֣i1l+~sylmS4. 8uE(@PS(j;f>КWAL vNSNٔ3z2U성PP4I 2 5EkO-.nJQц̌.mtZǾ7S{~l͘2gv'g.:ϳE."H-irq5ry.p6 z)bD"Gl*8saՀWSe=uޝV7T^AC3S=(Dz|ڽIS Lʶp8$ YW9S gr# Om#NuSmJJQX5y̬A4O!*yBVf3YGD[hfzR"m@Bzč`ӽ2&2ZɒnHTE)m^CѶb` s[qzR=QRD B7&6*!lz{?O yҹpikgdo(hT3b5gffn`!e5yˣM $Jw@"%afS%UNv3@*dSV9¤^k Nc4iSqCkoAlyt p}߶?9cDt+qZm$#*vLH b5 <Ǒ"mq`sh>{H/)d)5I{jv6+ Ӷms"Ř*~Pkq{ hⱫK4f%"bY8Iє5S_,)4\ HS3PЫOG鞽1 /ΐ< &+<=25YhSsDQcD:"!)!8tĴ3Hc&BV:ܸnk6pmU "lN8ԝ5{ԃTmfC ItP-c5[ks 5]uyqo3hjBDgz}nkM픻c^q[MD|a(x) -yNVԩoj-) yʸʉfUbE\8Z@kU7 M9Y&RGhSn&3asy.7Τ_[lhUlSkd`P$3$–\yhzܾ yMB\SK9 0I#GA=el=7,^%N#uoc}J֥CX8V{}ITIgϊ "8]R\j8NAAҽG{Hk \*>H q> YrYlQSDEI{9%|[P39V$[kbaj=2HXL)XI:.<56k)~#3#GȺ#QbX:0eƜ\K*lB=^[ sNM$Z~aA(&$1k+hV Ry}?weQ.WC 9o~ڗZ3m[Zk]+*'CD53,[hBք‰P6rNCS  qO\N⧅Pg]}kX+hvjW(Ӭ `Bg{R"&y֟x$P2'+\*I#הP.ή^h艀_IM T[GI(9ݪ"ij`?Z۹ ʼH&PT>*727%R~ֆ/"jjey}ޏWM䈏*2}@zϷs4n#5cO zTDGf"ٻ}={T[{C٘7Ã汄\Sl~ íIV˚{DHy:(Nm$Į"]3#_%Hۛy3cpmA9MQ5=醇)Nw& \)έQ /ZLҔX4DC\J{ML3O7\IAڦ'XJ S z1bT"\|DݩB b$^_5 %>_WI2mSSpWT%q/ iP˟iL)bXE\8@![[ylOri6kjI_83fáK 3n ~Kd6mK3s_ھf# 񥥎#wAE4͚{jqXw@Хq=ϓ@wW'k|tPZ~J6 "`m~m-%;=pL1;Nҙvv(Z߶m^u eݭLMw516Q4%+rkEmaZq>׿^ODBU;sm͒tF\ &6yΫ&ūB]BlX5w7S "Hf4V^ \u3 2 IvW t:c" ÑtڊH3+d :y{#Di- #:aچ0;OCRØ\$,^0doi 첥D~⒭88AϜJ,ņN:e ҁ0MFdwC8Y\u J{=sےٛ ^U*h#9`7R`kLnV63#;RN^-C#NɦmSFd| B_hޜ{5q™pf7 {8HtFEVKd֤ɐ`cJhZ3gOϞ4ÀY$hIZHQ~L"3SdWҠZCKxaQgũɷ7Uzyq&}O鱑t䝹W6"Z++UP5er۶/..lL}Lm6Ƥ@ 20p"zHa3$=MGWrS{X|ok͠,`6m*'$I~(Z lqd\/)>_Tg:X )`B!J푰^1?49Ex^F?JVk j^;36)7ebUaKGD*K28$\1'i0.T;* 1%LdJf<{W66[n:~4 5HQWU5pKy,:A6'rǔ)9LC<3F؃ oz%)WwA":pk2`e `t1F``8JJ3勵(`(d?B:_jxMYCf*տ u%|*VC:)]XDggLV=EE/4u:mc֦1rkba`hV(H !!f@钦jih9w> L3lcQ@0&@,լI)5Jvy"S-NƜG+m̏X GG>[e>ť}= dKy}W+ s9˄˯կ:In"a^ uj>iM^ }Hvbhpi,fʵ_ETS3c3op⺂@cI@*JvYhXG{+ehΌÃ.{ddsa<Ol*Kk+ΉK5nظZP ! KݶM$w>FOGs+(1oYMфχ4sޢ`yWLòsɏ %|{V~9HH87JfX6r$D 8a8Qa1uyrrB&jƗtڸV169Θd`QZFY){.);=\D5>Cso: JɨJ5Q 榌#]Lm='2?DAY񣜜2e@z&6:vYd%}Ffa%N6E,B}>f1;ʑ`drBeUbEU'@e㉦ZC-'U3響}߭5E٫.!mll-Br.6q@Bv¶m=nUE<ˠ)):h+.ZcV +聺9Γl߶%%,JJ Z_QZ4Kę25Cr:OƺN|b{g~X9Єh?πLلT(mvIc+>fy+&hmS /,=8d*̞=/TypnlaTưpemȻzF03yԚtsc y@UX3V.Vj.@A!y= I $覚jD$P'IP!e.,fN|}8W5؛(+9fPC&I%@Jt'DelXaK :5/Duy*9 ʹR-^ĞШBuLpݑx[A d?q}+zuQXb&TX[kJ+_ͭQ}~Lֽgn dy!ܽn "X3)i>44yw߶VGMWkdч/F&w_Fy 堳5Y|WM#^c:Ώa'|0{W _Hr%u\i_*-354 >8A?yede0YǦ3l{ՃװBf?Y/xygmUɅ?x)L"T rWLÄ4K<HỪmlz۶tu:fm%p=`p_4+lF>ojDO>SuyFi=} ej,Sܜ^G~7g"!ҙ^$"ò}W[^Q4B#1-kҾc:˧H7 S=|0lCެȠ .p ,%aWp 22 mIМ8LMJzY05f~b%FΤU% qI-EtZ83 CVk}=N6S#j0sA!ȖAw ؘ>F c+7- @ni{'E}^,N,ѫz62'\GMrf0ȕMU$׿Qo Bpr՚!:_ cj&>enu$)crkcc`Yk[^G4 ;]5kf$ ;7Ȍm<s@Ln CBee-iwD|ffJ3Åj󸵦wӈ~gu5,j׮u:Ԃ ͊c;jf5#CD[_\dGK< -M G~s&ġ{U>WR}kϮQmlM:̓=ofА54@- B#2hewq導4N4lrJJ~ z(\Df ZB՞gdgߣ\PVHMs,>Uhn.ʲgdJHjQSБ5$$.p/> fU`E>p glj4hƖ =G9CX\NT\LѻgF o њzjB$r5D}p9S#R &yB0&ɼK=c[h͌J *͹1Q)Oɐ`fU6UsWv%<ܫ{Ɔ=E7U0Xu=97ٟpw\ H7`fFˡHICGm-d?{Jj&GqF 7Y(Lq($ci_u9X! H^1*0"5I4(e #LզT<P 3gm6AЂYusĦ"bC)u-IQu<&yox|WK-0( nA60NVC>!,G%qC ㌙dȌ(U[ϟ>_f '^aI: l&Bٌ 0e]X+d6Zd)D'e$Xrgp$H~V @ 5K4#<#SH)H8%ՒDU|䷥xT2LOCQi)'ؤ τ-y`j"+S\]ّQr 22DR#ۚ'aPZ j"yY5r24aϪv6LƩg^ޓ _)gl&g~zw0nUK{P *MsauF6MR)s6"e65O0[f!ZHEhuJm~r8F5~)e EH vzFVH{$'"%6TLED*:Stݒ$ɍ3fsή yךۑ3$3 ^(7E :3`V&%ABҝ'4Vp{d_n }}+u>)^Z$]Kۂ*f3D 9*|Y7RLDd^kd3BKNAoo#3 (2  n9w+eJ,?⛜!|0E(aA+feKq,vϵ-tA^ޙ .E[ЮVW/S[(huH̓ñ_!b 8ڣ?:iDjkY ҿFvKoorKf:I3]t2{ ̎CXHa J_{ AMITH1r.6%6wVQ327vO]P-c &^'Ǝ,xSihEj\/H#j^@ zV_^U-g^@B%y;<). /2' +bs=V|-fc" u.SdGDƄ<l=k~PwC.f H I_;\đFGe.^JauYF%WJɲ=@ bv?|^ [F{GqYXdIϢ|r *r=6 y8 OR[v9ewx΁H9ÝmKr~᩷y-Ljtu~Ȏݳ .N mf`EWݲ*I3yZJD:*uuRP{pv4; zy+Nhp6Ȧobq|~H⋠N0Q> Rn]:<8”5[Or}QQ+n8%4m+ #I91GCIr;@h,ArC[{]$%`Law-ż z\UYK~q N WqN}Cꈆ"9h߂hW)A^Fj܇<:5<4vU0_)@]fVA8Qu% )ZZ48lDUB[(B "BU) 'O_#a&ᴋ|mly1D^CjLFFd?30#6HA qyj8B![AT788r PA*_X`z_ ,-'q߿:*7*ra3sr`nfqr^&"/y]תy^?7[DcɮPSzpvr3ձßp6[*i6f5~zP/a@ A7-T/2 BW$m.R\c Ŝn -#d(Bc03rBOoھ1Ó#јk}h wC.S.V~]9[ڑrxlEwt\86uW3mK6Hv9~<{U}]js[rwb˚gx۴V0^@Npml^jn~̂I8(|Pmww>k[-(1Y(W}NQ$p!:ƄO8q3Wߴ9/lsxm`fc\iTCOn ҅c7:.P".=_Wy7myk("lZ ?[1BI&)e9ӽ<5JZ ut@/wbDCWa< ȡ2?lnܽ"wB%_AaV\!$(c`''y~A@OkEYH$<\Ɛy`AU`]}Ixp#b56H.BKfZILBuNf0~whm+=XU{;)|ED$aŒt5 ~F¤XYS܃u't#O*Yd$`6D:Pq"ҷ<0 MI&'`7t[+Ⱦy_/{l:ԩ"=` :խsfd勝ݼ Ɣjcua3d?)T:`m`>]yBAVШANj:0@qw.Z&|k D#v~7M/H0ʴ;R}6,OJU^}P`/~;p:0ٶWy[>6[_mJ1&&;J)-裡M}в%l*Q-bjw)CސB[g9#r mo-)_NE2']9ThD7}ܫ1 ]ex A6I- #h%x@Ub$~zL$en6wd2D9dDkN̙݈r&HzF` DGA3?]/R"J0g6*zU Ad&uCzIB̢d9nTLj M4QqT'$v;Qؑ;+;Ӛ-a N(̵uX.fy0-<~oZzܣ\]Hv}Az4>)Ltaksɏ,Bbaz}/O (ᱳ9b8:p"=bN9Fa869 7|[UhaqBK_n=\3/#c@2&o|Bs91Ғ6k}2Ed- l ڠ}t&(1P$Tum ⢵Mm~ p|9Yʖ{*L9Q${,s1v͐s a FwVn?M_Bd"21 K;-s~>"Z{ird /TH1s/ތPf:z<N9ƒd ++T&(Ž:x4a#ZDvTHw%ѵ֜/lfn.8GEe @P?9!yj $Li ;8pA!!gPp;?Ĥx*s0vF{*] A5L2W`z!%qEw#S@RUn9xu_&VC5~ԈV!".!hrHW8QC0KGS4w$LB<{"1 c=pz\]=ML) v fGmh''r a"G'p$16ZؠrpGՖ2:{gI8ٲ-5$08KuAwOw Ήsg*Pd.'akcyYHx`9ש: mWŰ3M'$"V$WecZ"I#,|D'|ȓdDf]':T,#\\y&g *vDWZ9̛dcw7i^m+*Kسo+S4d=RX՞RQtetBB£G^ZkR"{}08=Ex-7_iX` GVM9dp Yk%%-8"Z|j+Nk8;g* wSƒHL׆߈9",Q 3X.V 䊰da]d9 v39PeM~G \+0cm/ Wb+x`0|; AG`nG00Db3]Z(UϲС,s2)_/!PuTQJiw'߹Y2;uW:vdR:F {vu܍0uAT4~^3;䘽c\C By(wVDfl6D&(9Gbxg4TDI1D6?vSm9mnHfg-#`{w/< l{u2Y@SX;qt?[Zg9$p%"q?W98 \insR@|XJ7NuRe |R8{{lΨ=0u+SHTkTz ƊD]<-| O!',&?!>L4-{IGKr{*CpB)z%M;>ux%~eλ?){}Uoӡs˞zqC e#~YGq.pmR]k}"#~V 8l^ c"̑jr!2'&ܗ|6* E,d}>\Yԙ] GvF8۵XԽ:E׍5K*F91|ZC۷;*~P6Ħ2 1QI M f>J^cT ߏ{T"VW>군Brƺ}tQe]?{ b~T/vD( #Dz3|PT71WC\ҜklKe39S~^ 9:E:H;ygWI-I-P{ .Lh[݄oNKqk1$><0>^k4-,A0 nRդp16M?L@>F>Mcר-MuNB;ul7:XHD|Y1Wm8S9ªB9S"rw9/0#o1Aci@o R%'ht &T2y ucӆ_|K} d4U+Ɨ5:Wp`zI4D9Qͼsj~5U "[kٻj6EE˲A-\#"dL!1Uuyx r\^v=t&7MX)6)*p?uADyI8I#X+vVHDľ6oUTﴅK KXϗ'\mnhDoaR J<$׍ú087wfA$8we?E2>baڂR'jSsyqcМi_,bYֲ0E lx8*;!3 .Q \Li'!ZJ)Eb4_Ƶ 2G?UsF "7t×W9D~w[n^|r/[jͯ0D/U\Rvh[`eh I^-k[D,JW2FMG2F hBJqN~~T5?#㴭[ÚP@?5_TU: {/UU=Xs_3ޕVCmn,Rv9hvB~KC!|"V`ݖ([" `fpML ,'xE9( O#[ Yath9*FbFm}a܋Bt z^U5()¬8̈́ n]&|s߃_p|O \ъLg[S S&܉bFM<@*Mća=)HyZ2Y:;"pK.3W+h<<ٷno]!j!3t` 6ש0D9 ۊ9, #Kgs#b+}Quv =T[B6ztڱz9Ey݊-J&`"Dɕ Y5TA'?50`LdZZ_jնŕZFbq?a~dҞQ g0):#8;xvv;t@9{ntsIv`N@[sRN=nLVJRڻ[/{<ʴP1;rЭp[6))]PQ^SuyfSGȀPZlЖ^ ;On&Մ=d Y*>J?ٳ]߹w࿻{"H,Ǎ 4b]t3w2|_o5tCnfTY7 )c 3P GyDB9399 &di}k"|qeWD|>KTo#ڑ"z޻RrIvLvЙm9 ȘvqȲ%c1&{[KA-WQ#4p[f>$ <\y$72Q5, Px09ymܓ-/OB62(O.ͅYBEJGe[64 '+$dA.6s\XYš BYcԡto:ϥit05"?i[v^z5&B%'|4C`c*5$Q[ '"] U2[a&cH5]@VE9@nnfn##{#-ކ=0W`bt@yr!o5#1aAnL\w5Zq[B45Jl`j4vcu*gm=2 2ΛPo"؉-:3%̍Eʃq ޔX82II_68 Os_ [;pՁDsAQ*Hj\9Va#W\4JzsGsNOѿh85CHD 9IJ;*́Q$t9$z#Q]x֊,u`'?Z+5еhgș8v2#E4V+[vpgDP®'ݡn?σЪBܩjhVX~9bRa^CsUuR#Z& D"/Isq*keb=WdK_A$1kGca^8\Ya+L+ĆUI?ҡndD!j!÷[`x/3 v S8l"f 7<sAP`[&•ؓ,jK7𾿿_ U )~-\1wx4.9jڃspeڨGjiTUշ`Zi ٜ9w #B8W92Z+7 VUecܞq\KTIx-!L׮.yh $JIc"S(h*S^N_/3&Qe'XPX(W@ &eZ'Ds\xC2)D,D ԋ,2 \`ىȖ)$}_xU a/a]"90P<\ՠIWiSX,Eec^eɍU`0usDQTnKf%BRB9",>Ҹ/$0m3ٽ~eĖQIkMqP1TYIxyze授6@/LźKC\A4$RLxF[$Gx#0ե7M _>:(\T8I&sY*^U1NG$2BH*L]B%n Fqr4b}YTCVe^`AE#BXa=;vh4.]̝LDj~8Z3CU&En U"MW{Y4Qp@(/֣nAz!-\~T~pxRDi!¬cSrN<3 RcPv`p6s5X:ZCLtTeeC?Ycĵ?D뱑{HJE@C\}u'hk3gM qw̹?Ώ" pϩ.WИxk:β_C=]J"fɲׯ?Ŏ0UԽc\X f{[5AH3 Kƌ-}:R Yjr$E.*G5ܧG\K ),,BL eĤ*$as)[D_U]d dB|Xѩ O blK f ) ML ɱ#C|OaF1,Q(SxH s(̠Tru[; ~e $/qDABk!f9+qVW:pѕ,N ]Fف}D)$Z`Q| U~SWȵM0޸<=+ e_smzS@_*c5+W)]&]G` ?d-E$ =Gа[y])cRDyiUxN[Շo,OXe3aGvxl (g\rlJ nJDQ UsYw+qI"3]שC\tu߸G?mV^q~GĜs&D׹uϿZDp7|_KzS"UD$ѻH\e+F,Sƒ;zvԃԅQ57tiSoq.~DCgfzcrf!m(=7`)bL8`e"PcA u9*t3[95q4/mKMBm(Oߡ"2X|S|0;eԔ%q(k} <%:$i}N) M|I쀶q N[babO1(!IG<Ѳ%2,A5Mn}qTb|u*Oũca RD yK aFcJyPJXo!Y̵Nަ;( 4I0HEss%Xx)NJfH6jd(֜Cv={ 1GP۵Tt形ڭax,nZ\dElz'Z'_"TPE]4Nf6X_ԽQǜ9p0Oc!qS~GUs_A1y9 k @RceHT!qz:я1l$QFyP%Vv29\E^3Bh j!"*bW/2>-H }.w}Df-oDUm)"c^/qb:AȄp!Z8|֒|-;afҙoȏr^|Uݵ5zO$Xn˓uQ?nt/\ m{>'z_8=EiC@Ru2̆jqpt*׸2E8ĩ y+O'Z>;´; eCSіV].;9P`DYZƭqXBK^ E7~Z!9)>E]aQ u k bp.OQ93y&h^]&U!&A8 y\9[h$B{NO^X0GPAHEЊKnvA[9=p|$; ;W%ۣl Jx ,t(=pe8ఁ}# )鉍4LKYʝֆȬʳB_:`FI>C{%LCL'I58ך_$l- kYIJbշWDs9a7ExAq|{7V)Sl+VvE-(Fy$'=f:י@H<e*3z繏"YK{@6:OܜJfkEXp h40k*@m:zE H93)dWc|N/6F.uV|Ans.sD,}"FaIO71F*2ǫU1?1:+KTPL?d ׁ1mZA"}D!cR@b~@j>cڿ>bY,Z̊ :T4܂JcW Z5'u3|qm-W! ]AT1/!]с(%e-:j͇J%=Qm~55ƽo!Ԧ%:TrV+Vl~V'A*&_7ǃ4u\ <%6k Q/%|#΋hflH;$!+V}V*L IHGh ;hNcTJOS$:E5(I_n!1%"̎UqJs I^ gdQ!]$($<馃P]JsTJ#Q<-j~ruC$ZY Eٺz,γWK&7{o~ÁɡKOٔ,udN)yD -DI1YS,9&AQ2 v;қV>PZJB0z,4(Yu?{'o2Z `d8kw:0sDc@WCTT5'B-jëq٘%COXFƙ: s,2#t&Vq}cy./ ?rN׈*Wfm^=V 7lbCmC :E~eA1x[X5bBͅ-6"q&16g~qx}*D(XyfWOhA&NT.:rR)}ODJM͕N\" FlYqQr$ F҈]kuc7gw?zQyŐ1ug;HHO̙h[x겾#aaf1CkQd!,1Qt9zGFZfM>qW7oGC rkxzΫ!& 4/JegvJpLlwA@8; r37:̊>5mtO>%\e{aaN%+pz='f^0TJI߸))#fKbn&n޽r]%nM?g3K_ۥ-Z u|>C2H *"_@|.Cw5Uk^,PnA^¦+q(Q-;ntkج{0) _VQc\/c/ @%!WX/spqy8-wAuKwCw'Ծ;xQ}f*l~=k,Lcwϧ9XU1Δ.#;(!pI>G"yl[8Hb&_ ef"#5h`zs%Y>KH25wvokYBmP^opՎ[PחRldFN;!! 3jX>P{,2FNr3DwNЉ.lR'̅YEZJ:FAAÚGhxѹ!=g li緟ͽskHsugE=fP$LFeLݑ<#,cXxx_8Xd 3LH,ޒ"䩹%MerQ"qVo]ab]oTŷ<~S[/`7 43 ?D:-eԐ NzV,zCց٭83SP2=dCSe#o՟p] p-ʉ1l:zC 2_osLʹWq}_TGIKr!f]I񟶁Oit0wR7?BRDaATO"W s8N"su-&Uկ V{92N_ 8RRȬKkTkYٹ>F kw8E'34Ӣ+ SF"  NISX:Ϫ<'03-:g+ djdNX<Ðkpdo$nײer}+wUq  q 7H EI9zͅcK ͮ 0ttA6"aQRkxN NIgn"nDTll¯^N!"cD=c;ϬTt 38,7B ̺p"-3) *|aD,K;#B{z;8Tuq|dl}gW"#LcVѐY6AwT[ވ c6)3lpx>F60wx6N>hϦ*_=N"rA4XșXՍ)4 ɠ0wPvEEHЉ쌰r +/E*e9ZCd O7efBrO#*A$Ys.Z]JJ-N dI{$Ě#0cr58+jі<ȆU2K)yKS #A. B0C󀄈 E8ff..]ŒD q{% h6zgoQ9`adLeLX^eߋwyڸшx;n"!":]X1>c`F1΄8^P5y #my)y~9GHlT$G6-m᜚Emݟ#v}M}=%u}ޔ%ly R=J{fQ.ؑhf;1* M) #e<@v/Szy8 IN2]Xh>4mUZI|+nAqQ<͹*Zf7UC#d$Am6Rgqfb$X4KwR匍R@< m*16`-5npRd\=̃A-sG}̶3吸œcsW#pV2!.JOEW-DEFp#blQ5jL%Ƣ@'sH~0BT8H*)8 o.vViN=|t;$7E3q<"0G&D 9d鑱N䜓[\M؉>F1RN# LxsT<{okTƐ3S rA$PiߔE {㼮+kHnwS@ X[zȳnjiV$1B>=PHCq}}aĔK̩N,1X4sZw(o}PϗKYT뀙y̜KRkI*gF ]Hz~֦:mūLRZ̀܆)xUeŞT/蝲;D̲` F\Y_O'F2&Y/gKFNw.kޕ[nn-E6|e*DZJZ&hegUa&*6r}57׺ ˴!f^%+Jŭ4R{P*yW`<+żk4<=}/Ms/Rݿl#m,|ӻWU]dHH\=BE\k~6fe1J#?AS Q'e{edn*V(屸{vZ@a1lE~_yYLҦpE:N͸IotjKM*BfJrw#"m۲'G%ؽD2jF?Fkqg6@J E+f aLzֵ61/qXiעGyO|N(Yu^q<_6=o`l#YDr |%=-|<ᘱA3m%mdY`v iҀ}%#^'Kڕ#7#=Soyj#}޳HOP {yޭIB"nclȞ:4T;V ^*fIumb\nr"cqa?ٟ*Pg5A%0+ض3*ut@@VRE)8!k Go`@dFxoZq5cA92cKgEKq[3*"4 DR{QKEJӕ}z0Woo7lΐ[ok`x xϙsUŧȝZӦ-7Ȫl-X&FƮ-6;L ).9=wOe1c4flZN:Qd|}Vey9>\6H$LeJ7Jy_F,pD(z'C&{G!6eHw9n۵ TlTd7<>|i!\C%l{"cz%Z>G8"jgrWziff &`z]=-' JËi=dlPrG"(u(>b+$*q4s]^ TI5"}rt<IQ]=2<ΩjrykOºʩM&Y.8{b֎Vi.wPHzJuXU5|j+90 um1̆i6=rcZnޯ4&mᵼuC2W ػ1x2b)K+>TrQaHg53KlZ8BD1Myt; Bf>X [;ڬ<ș|N>Ea>,z+JJz V/Uݏ_OgJQ PW"ÖΉ+{8Vd wnni˧q) 3kT?3gX6 ` m!"Ӭ%%r]Z1( pq1̄[faUeplXEb nvoR]"ɍsw:??s;Zݽ ^ ;ӯDyNZ# d3v 8M[L#RL-i1R<<~waAU]  ^Zh쎪k|<+u.'_ a$yKTS痻+iv&<q^nԇ( oʂڌISH>Qc?Z3` *3'_nFc(Qv)6(]lՅex6/ BsFu^g;[ 4 x>Z{Q 0E*q>88J6XǏ>"WH˰\E16ưJuC"6Tm wZ*4U"r;DL~I ˂=QdFur8A!_:zc2۲G`% ">]}^6M0*Nfkyƃ1x)Gxf10| ?~uY"`)"'!޹FZ9~UD YD;&<]uhX엸 ˆpFDM5jO1#6r徔|qU9ui$1!O;xe#Eߙ¿>wSh* 8"ή`;g0$;SG.Ϝ1 A̹'_2A+; H @I&r_IR9t`Yy'b9=MG*X&3;dJp :*E8!Ē \/+q͓F>|\J@IkX6dH Ev 27CAզAc M>3njf َpSuu08w,~ή>|4M EF7 'dOHA$M5|aTyt_;'*6È/U&4l490zŠm׃_( Ѓ#q3!!½_r<fqA7<*$F'hy!!#\םZiʔ1󙍙lɒ6Kmpfoz[@qd16u.`+ث$Kg|>bZ>ye`8HʺSi3hҮ|>2W鯿jOK$"_َ?x]DԴءߐw?639hȿCz0u]0s390]HˆlkM͙M)!bQ`ʖG XXEJuṶ#`JWGvg2oL yy6޻Dx]ȟfC۞/z}?]^q6T, oAaKGso;g!Kfj^ڃԸ 0>0>I5?+UG{'5z3GTyV 2ZddF$.> vvp\PLvTEirh*6L(pڸT@DbmIS*Vl8.o%^ݪR'3Yx((X|= pF:E`46-sd4I91,1?{8y R3@#ul w'77sHAϤDҬfvE Vք)\^!Rc0fuaE876Dzt2j <[Wq=k=٬"ȑY?5kwW*=U] 6>8M3HD4tL%VTK2|F<*3Mf_U<)?vzIs\-vm^oΖ,xZk9@V(Ź6%nebe}.&"E߻q[< pw{LeHd^JȨ@rB8q+߱q4V];4M:OhIDm$>Uٹk5,lcw bxg{if&.S|>ͮl ffU/o 3>J!d,ĩMrtN8 "dBv>1a)nf6m:$;(@fWq\98#Ğ0oԉcW^j?lk1ߩ<Foϸh=$6 Ѧt¹CnY)1p3)yb\;4]n^W0EkB`xU=wN~[՘Er,T wT 8p +AU&'eO dJ5 "(!nVɼieŚu@LfFc@Dqa ȰgT?lF)Lն bIx&·eD;K̾Ep5LBV!;6#7/vGaMuiQb*E*(V4qмH&Qw劵Frqq5BQ|b,)-¯|IR+:pzm rr\r1,* A;P#4H[Sǀt|grm{퇙'4ޚoaϞ|JҭړYκGP6 Gi N.aSp]8Z6v[~ٯ|R2/=Of&*:c*ewm,&"&Kñ{Bnj#l]̒eMxlC$mM#1_#hپJ\Fa>wq1N@Ru^CG2"7~Km\Nx7~~zϚE5\@,\JD SrA3aANxb_qZ-@Y͍Y-‚%Z٫wxiڬw:^ȧHOV0sd{r"f>$..7h6b:#Ttn*-Dؾ*I؂KABB ]Ƚ}@F\fǑ]U/MG3Àr^6\9‡;1cspx_F0""\ǜRsnaXѹ:a!%\e-v|Jc@jnLaDh{&NEiHe߭dEф`jlE>,{KK$t_EdL2Elys2cG@Cxxr*WV v,;'V7޾V@PL3DkJ|ҫ2s[b)ak^- }3̽]!ʬ Zn6cj|{If&O>ʽ FR:MWο?CL[;,+B zpIU>OcR+Aga3c|I>3BZw96Z}3loK^4آg 3oD2gj2jd )~ +*cC*o?EjIJť}8n0>@tUГY [Q%xƨܘ$,}&a ϔPmZ`)J9 pYuZ#^v3%Dvo۟>"s?? 5"j #B3㒝U_6"HwTR6PtAVcB ba=@eiȬ\l'd Wtt1-HCX56$f>@蘼̸^agΛy/^љ)^w\NPr&IBCw 6OB=qÕ\WgbYܘfe?ɝO]GeNY31#|S|mj,l=#G[Xȕc*f-.AB(#naJ֖ێOm_" 2,HXbZ1Fv̜ҁt,rǛ0713*KwQU/a,3ڂ,LN4aH1P+fsf)ԔB<v4"~R>E!ؽT :1w^}K̈́x-<#(:@3Ҽwa67M/LT},c c$)t2 j.hXW.׼eU{,A:ל+IhJh^r~#Y. ߝZf3OZ[V*obeBX](4En3|x ;-e}TEb +մcp+Vj ƞyYyN^<@F۲'6|soqi^Kf8G[ɬ}z {u5TڈgPhz= 0K&K&|_ѯ?~G4=1z601 )]Tmaݏ3_~uQ`815n'qh;<Ƥy>uZًY3ՙwDks+|+B$rxFGG ___;"ȏ?~R0 #aLK&W{İ>"3<D/%xS`<+Cz?&b:`)f'Yqq^ _?GbKJao sq6Qk/Hݣ@ltaD5ȈC `?~ۿϟ?WZ;hIs"b95TyU!eNؗ$ӄ| !t]}͠nݛ'=/Pՠy}=Gߥ5_A;T$}<M^z08 NV nF)Ҽ8jfUBMCcٕ*Mvn&%ʜ ѱVjRkZr0XxBc>|Yҟl4/9c(l1dn|gz<#6f HuDr15a}~]p쨴dqJ'pWZ6ah_)lf,xy9ۉ> K -. D2CT*v[%E}W| wI>Y.Lٺ3=X7L-=&Lk䙝T=㋂y6,̬=[e4_UPK\q5 0ʚI ,<6_iZbw\ğj[,߬7O͹j0S8㽚0?8QW=q'CNjT#f8gÇFpRͅ%#)2R'"^暄~-`-]㏘‘avkp p ʤҴ<`)h qdb!s{t'g&iDLC &I T(ΨA(i:a\zlE.OH@ >9_K}ӇWWemܖpwe敪]Me)b궛RY3,Ѹ" aV9puWrp#2q+E#Bs-F&WQ7 k=ĬOL`ʩ1( CR45 š],dacJ|)zk`oHB;yEAn,ul܉glS?@S**.*ʯ0 QeLٽMm:ސz)^l/!:rDK ;Q>b5*T>oD%_2m!ߺK k֮ T+Z#U-&n*}IB53$Kgn\ixy4"*XdGi5f+Zn7g}fvmERkT213`s䏨Go,CJ>#ֶ }u:QA2!.Pwx`MBf+!eAn})`0!̥MSؕv+8P\ߧkif|ր6:d=4(Iep6vu `$VGc.]pa7LE v3s,b ۬[V2  eWm@tDA@6'5zCx/.KOu#=EAř^vԖpwNVS`n+H y8" 'DnNp|AE [/nơ,#lHJ@L`T֙U3SX˾Yyp+-1rp ͍gSnwBq~&gѹG3dlwϿo5R]sҍLyíY\.Mxؖ6FqF,٘_HEΰњAL>]c *3cGw7/ЫBBΑNnr[DQ*IBZѵ1E8p:Q)vߠ "nFR fEۡ]hY>3d]5"nFD-75t- WsT`[-"7Td#-)Y+cad#QY/(ڧ߂|JoUxX$|Gr3/S, Vdɗv k1KT5OkNnPvw y~X;W;!߻l-blwԫZy^  g Ne1% ܒ7yNS^njLJY$O BkG%c]Ucw/DJ|hf ;M[,颜_!j'P^{SFIߞXrՐ7Z 7O5N'H`fO#ҽoR[͐-HX+wp,M%gћ9&_`'2ㅘէr(=୒S8|D  M_%3F7=Ah6/Bw pnpʜ%dTuҎRdl"%9%(QȻj+ZU,JUZ1Ϣ$U[77mAZ݇;{RWWߜ\uyVx{r+i>i+Lhhg{5}lKv}'4{vh0gޅnAA63A[U\0ݳL١=t#|882SO.ugPYR˪g^op,^7۹Ϭj>M%$TR(c\{Db|Fְ$s4Rh{BBDQk#\4@R5,wqo:d@g%pӍ2.*y"ӽZ3I"i '': $&sjG _qByyNs(g(3 [ul_0q {~MNٱ$ܵA}8Yf}x e\sۇ B%؅ק֖(dH>L yPn3-JD~Y"kk* 5I/JX*g)-uG p' 3exJGAƢE$^ Ț(3ޝMr\c{= n2O`+CkcG`Zjyudcnm.U ޽58$"j1޻ KakMUHقq1zfzbKR_ZMbf̘ъP8r z5uǡ*W˴z6kgۤ___ff1z0v\E)1e -Xu9 ʶ-l;E Cu$s/fA]KL0k -Ru_}ܜCg: qvG4ºǡ85Α"c`#OaN> XwPЕ^U,Y?$wI|4R:`JK "?`ɧm'Ch(&1,Oݣu[ 7oc睝8EzۊN[3mDdz{Yk+GA}}{c{%x+Qo D,o;BQD434aљ!|-_[!"-/Hpgxw4GEY|e8Av %@QN./,":I,FPqSY렳V )^cRASRe'5m= +P@ <Բ}55j!ԉ3d`e1~細ڻԖ5w?,C8{N%֝N uTNmld?I洛d3&DsfOgHoÏ?OPGw7G;($U9􀪾F& c DfA wU-]~4zMӦ. DžHszܖXD%7%!_q4UϹXU=z`aa+#c;|n[87<ǜKrD/\yo f"6hG#h3˿k?=Jk!H&̑9c16BIj=cfap\PVagDP=hhfZ0Evm\(U .r!") š8U-!_3$=\3cz+h!,:!Ȭ-,8 ftx4/A_wM*i;$=#܄yԦAʪp}](aL]cVwf V0j(GJD2 E~č$}{Gr?&$a΀QALXK'P d'UGljX$-b4~yCY-|<铜p$ p#`^1u>!A s / #, ji^!¬Mjb%0Y{0wa%q!#Y)adr"'r ݪeQ` *j,B3 &_߿~0&>K&$< I+E 1gǜY10?%L _5"̳q4'k薸 qCA"S""L|/³lA&(hGdko9TU11F:$+{Flis@x:Ӌ'W2&-O|$w$]m򯥧bĘL7$)b(%2EvvWЛ7u,º7Vr{ ,tS*nˢ*EѪ"(QJH- R*Iss yH ǝ,ٹ@+`Ca9Q= .}#Ɯs_3 R,Y;py8 QyUb t0H}9^w#Ve烱᥌JT_{5Zמ_0LNS^WHY  S6uC_ @am"ᓮ:MOg]f+T\)cX9)9wglLx[ J`2b#ѝA oAխ\8̶ir@H7g1zz6Qk.aV!zޖ")BujTqgaBّ;\&:Ĥ#+*A+ 5+~x=ߋo%?z]w*nj*VXm)ʑʼn,V~8GT%9qR~ddʁJDpQ9,>R-W炪{A>ZGibkѲ,iN<1FSm|pOm*ɓ ӌ !-zx<$JUww6A|$yo%ěd5cn-zUIc n_ϡĊiܡ4+Z.|!3uI$w NBIJn;~iwV-ΡF]8<߈x<$waC[)J23|mSՖ[+c}O7wy9[KD˶T]z"W%PfR4E?Nd򮏜;2[>67EoνgGpmgGpߓ\(Ojp%WNEl$ZI{"jDPm;'*vKSwphUa4tfAJ s|䶭_ګyf TST9 ~ZY)NlRzrcU!GF_J2)ոUH͢<aW*n??W25nA8];S\ixVط5#}38 T11RM|NY,>ƦF,43mYnعRw1jrS>'k':~tUɈ!favไuNhgw举[99dzW(}ThIB.Z1_c}, `D]aə2_]֘O T8[o֔`!9BϺ0m[J R9w&V`32"plB`fF̈r鯦¸LF#Uy2U}]s; 'QDf j N3=o]]m&3~xRQybd庺wEzip 1%{Y_`OJLh'F_MTm^Q)Û!g#@g$iWz"YU:EWZo(d"M$$J2琉B VnH]0w+Na3Sߣfi}e9A(IB)7k ~~q[sP&T$T"77ʙK]Q>"\7Zcjbʇ=%*&Jg3Ɯc(<(Y*z23Sʹjo3N1w/ #P=sv㭿Jb[YÓ'ڀj]L s*uxI"6Y.kPjͻ?q3mP%(x]bi[}c}D6T]=@UX y5ఐґo)5=hU<l∈t( u| }f3imY4Rf(9svY9ƗjeU3H%Z ֚n3g&)c.ɔR@8C'(6CCaȇRWLcMR˚!޺Y(PrŽWHS5} #p5royht o `H\lǃ.uѼ<>Ŭ5cJnsjVzzoc~Us4 u"c3\MO1M5]̮y!z ڳ%\Ҟ_)b")?~11O"@4a>_ސ]0C*if???f>1cFB4 's +Z F L_$.3#;}Xf6@#5Pׯh!=׌lS1G8n8G~;cfs@cj_ngt:Ƹ̤5Q91^d5MF Bz|}}]ץ*c\"1.s3Rm+ŞК.1Z5i"дqf֮k_ޥLGknJVN+z^{ E6c>ē[5k?WI+2a)kU$cD9> o>c 9E5ƅ?w+SwgUZD@Rb`^ kdJSXOFbLL?ȋZz1Q DS5ѻEOt,Yڞ:WM4e#s`InaHJ[R!RtFh{@j59ȵf~/F/ȁ&t]1+M$s?|i"3d('$`€ЗdHS&`F$Cw#_̚$DŽ4#}g:g>c@ddɓΆ5Q5օ'xmyj[n tF,KsGp`",=a9%"c'OJv++h"Fq0^@31N\?)̚l{pC~ؕk5W8lǡ:f5?6E,KIkw?ϕ-*45O/L1uE"e20T"A&f?Vg2S> =C!MU맷~VC&ػ".g݄]K U7꽤Dqh[֌[2}[h5JBs;N=݀nەFȒtνV\б{ C~8 pUQm;UlJ>1GJq ۋ00p&pQxiLa\Ԝ.&Kp7ACe=_ jiTP"HIqOL+LCz:mnT^Fht%Px4kNzV8YB 6sQ zāsAr4xRH&Sx|'bjs4MXH⪫:j˕n\]HIYJ )=P*A랬i $ӪF{ FzfISe2YT USKtruut+fn2h)Е玼] J"k \\° G7@o_o׀Tj`GWM޽Yi3# o4CSfys+"+X۩&VkohOLRϰZ45>LR G%Ȭ5T[kѴΫD] ` Y ": "$$KXe,41car= VpVƻX#ӕf;s֧+#qQR<}fx=LiM2hR.H&!>wY||ݑ|wRJKkmݭF{d'D5Jiݧ t'' M?MU-Y4n ęsu+saGF{η|ֻCթHĖWp[cK_~휃MhXإ?\gjzX\ ][!b Z}E;h_s$Lb.kjDԴ5MIpH"DߢV rI޾dwnm Xl.uyjj]N?(A -FfZoVUZ´?Yki\ r*,Q#Ў\޹Z q(W]d~pj?!c%"Xr?equ\Զr!9d1& Vxamߤf›ek%4ΌS&IBLp#ÊAR[4*jHz5^ LMGk>CL\}9Z"R>W]UP$л,0ծ\>,+WRBi1s`k'cXF[k@Ad{vW%}Z X=Oc]UX&,>͌{*TKpYcf;r-:Yi"X켺u5iV]_7Yv)NR@oAXwFy~igkv3V9Xp1}^/3ϧOGc#f*NZGqM6Dt%&VJ^k]uDy"[7Ypq]W|>/ 7!?1ƒѱT\XUi3݉sN֦mDUKP6h~~~vm}agP~DΛ=<4-3Z2J/oiof 63n-tgyf,s4kruK"Z|y^82,u`QYB5Cnp/4;P~㌡|<%* ^gL$vFf B]*౲،սZn3;`N5Mψ9=w)ګƐW=8cި߰q]"^߫Տ̘hE8ո@FĈ31E\-OBwNs]Ǿ1'OQ/ϑtoRP$q&|RA^>9Ҡ\My-0u1~Lrv?تj*ꯞa(od?X(%輒i_aO!9򊘉wDj`zF|< >(j1Gmi ZtX T CiYY#EĦdЉSZ.iƘTVHDzy_gS'yA]qœp[g|C3h!)4=NjF–e§8U ʩ{)x\ּU(&*%TӥQnygkoq;+dUm>7-#BλS=/i~^?___i]ꭇLg[oc2֙{yomW1^qMQ}aF>.X6}fbrbcx:һWk(OW9]!P] Wm&*pZ11g|B1ղ?:=g9c* ۝Omç#b(aR=p޳cc4H " JѨޛ^:mP7f,4DuS4%TkGT۠@4Qk}Fx8 tGL"'j.S}> "pWgc_D}f:95,=f/y6$NxRi}޻;9*xM9Vsz0c:/>%{Zg(B0cɀ{"(@1b mͮ׫ǎj̩2C 7<OSH?{Ow[-RqE: IS8{YaAu]@ [ %4Hxd}zοy$C9^PD 0*ìKtULwbcy.Hh\5B!-X*"OJb:yT]!=DA2(=4iT@dz Ã_""RTɔ 4\}W/e"bj{ R5NzQ5<BgPP2pehXepﰔ.*&%sF$L ܑ<d0RejEk~@"aQ *Ҋ,jz$B@M mj.oMlwnf2Dx {p3.Q)dFR2}.jm^ӇX ܈pwa[(}#BZVVz샆9^泑hc{xS < SDBwN)9xO#PޛQ) 8r2BUy"Q?^nrg TDB4T[F \~~~T@,&?g4՝CԜבpf;<"̉CD<~U~}_ 犱ˢv$7UnT9ܓE1Mf2){쯜^M=$l: Zf5jO43p^:Jּj>XFjeTS2y(D8]"Kx A9c*a%"7e""t)0Y`Qn% SzE;3 0?nˁwׯM@}U95: "Zg*O3"R, 6[Z#˳'ugɕ7zAMG/i~ew<"Z#'-An "җiaYA̜k{sb6_`._^߻1NJXk3A_¯sԯw$܋W)FُڪNl7M{<|lhd;̕L1pKJ~[NwsȀIu马mI+L2vwIx/5[ e|8#&wk7eԬGulj*Z^bMLk 5H>Uj >dD-dzc,N s3 khq(ͬtD6&(V,ljFeI:N9݊qT{t9Lj1M[)8w@^޷uhK6L֣KĄg7*!sdbCX a)}A @H"|OW%L !P7|^Nx#%g-p @4n vP "\&к@dYLJ&]EL$aV|(gi(,b*yXT]$\u;P޷WsN_Ҡŧ!ؘuv3sA;NIxB igmcd#b\.kNN2T101}N<8*vG&b*,?JX5tDu݇fVZ>:,yw^uSȬ"sNFaI[r< V|ZiĜs>hXVӭ:ڿ&\IsHeYyD7.ךb|<>F1o4>O|{GD5Ɍzl.sB {-U[]}|_ZB4R쬜":L]Q5y=w]{f?8T޿~ˉY_m=)benyX1n 2 bZ)'Z~*P!MG#<`jߏJxT^͡v5M[6Luiy&QWG4Te TÅ Ḧ,okJiL41Lv&.V32ftw idAeϚ(^e*ֆ4zjڣhddQ-J Q0M+4Wrc+V"$*i)vC-/WNX!Ȝ+躊nd¤əã:rꈧ5 1xsznGk-#3MC9M WK0OB|jQjfխ⅜tNͬ`"V|<%h;p@>[\{4VZ^doi'w3ݻIC<)8{!޼Ś *rj1- o)w&\JPycRqm&: r|>Tֆ;LLZdS$]Ejg(Y+*&!05P{n֢*[H46?$c0D]vֻJE3x+? H 0‘*dՠ ZS̗"Ū)QYڑ XQ],KZ3q+uJA΅BBBnWb+/XqJ-Hx ʬ }D>/hw'G-+sɦTS IO/nRxҫKK>aPE2QbYiGZ"TVͯLAML"R"o[TlnT (GFBN%SAj L$;DX u zX">ljBDIðȩ fW'Kf4,g+uVcBA&"{K7EM?ύڕfC[(ET;\9% Us{S?af๖'m'c'gw_5 o[k9go3KmH2㏯1"U\*s< r oΙ ;mi/D%<Y6t.ssRDp:})<-#mRoɓ+v2`գ7CϖCwfK VvEd=cXI'zh Zx8ǩzcE?ۥ zdL|>dr*]4n<ؿ>02sh6^@D-=O惬*d̴‰t&NW+J˜#BU b>@nLN{XҲ=H.I\P_: t0pPyss{lrP$™r HQ,'"ґ/ɟB߱8R`2Xq ĚDDR4rWE )tDD&f0} -sWKƒP 5s´C3v}{P|GS M5"zxz\@S"*Mg8Q1EDŢMBa2c"hA! 1)Y057Shb=gkH31kH?x790xD[ g` 4ӴΈh$1:9C<sH1=%i8=z.bKO :&OC)J l\m{yCkɘHU@D:"$ѭ!R! c^Ad EuEp3>js~ׯ Ӭ7n/cNPtE."ktȩ'8zIoF>AhA?*ZwbkZDx3 sxw~Y"Euzֆf.t/ {Ɛ 8uHwr-y1* #oe^L^HL% N^~܈*PGmI])RPǣ0k0;zM*bѽX ={jh#W'ZgA|i)HJWYnQ2m=&^% |n2֝ τEbG`$ i&HKș 1#*̽i[( Jym$dT Ɖ9Pg "u],4Tj;uFM8ДWVMtìB/IY)$Ѡz#d.n*AAu99R51Rb2a"#'=Q&y5|Yyf!ue z-rLLulZcƒ(%30EC$.ȼ`F|y.&E_ASN@6i[{s%X;ff&R9uƶKwm7g$F+[iK(s:RSl {^?m^aGSU$U )$l[J3Un7;?U<w]ī ]ixRh*<`HI+ ;JTS̡Y7 =,Kuh[u`*&̺j:[:@emKJ[ST qav&}d ,bp0oܨ)bS?qqJIs\}[{ᖳ ǯoLQrWOM|ALO{;v)@!>~ܝKYHˇ`)V$׋R1sac(]:Nc)ّI9ySL>x^6)8 3K(yld>E jD-%{XGZWY;okBlj|mup- B)TBɱH [&1vbq1oՍc֚D\}wEyEx Z*%ПWr~>2n7/יZTר*[Xu<ݚ|“鶉Ldk #- F$k)J~* OUx[~KF-;xdx>87 }"G~uRZ m鞜27/H+U?4N? bH(R35} X)EZ\13@hܘ"pδuA4Xiێ$v3aɝ*Xg6Î9O"@F!`ex︮ÃR$H.BJG"MPUl~ʰZyd!{ [)(HX=|Yu]|HJnʹtAq*[ c?Jc>!<R[&d4פGc}prw?|86}'+0%d!4TMUj! H; =W4^bd_dFĄ~ȫm6ɇ []E kXk@KqlO vMÍ,"IGQ !;]gM|}0ƵZT1GC94;~xe_X ;ϽE"<$k1FUb76|po9Gk ­W%zVW@`+QUc:[Z(Hը*Ev}ZdXz!iF&D*@l{" 5447\;%1z%In$I.GV32̾ݙn2a^,fF0~ 8Dw8G=s뷽d:10ܛU2#RO˭[?/P10/"1:Ցc ?~AEu[,$]U{gfq]5 (3Z袪y=,0SZ7m9Eݺ l1‹`M[݈ڭ5*]Xs̒VTqy{QsLfaaeֲ,6h/s9T˔u"Y`м7Y'5;Do憺bzKTؖ(;Pe=6[+J yE,D3dmW8^[762XUc<`C1FYkczY;&BI%O)rk(0>QE:Q^zݩi0w>p}Bv%姚_M͢F5|ErXv'tpT\$/d0%" cںIk ^(Q?w`bg7:YZ0a6Y:P"yIk+sa٠z) ,5`^@ T*h^Kњaj& A6 }uv&%jۇi3P͚钓?ǷEffQLYxz&1HGԚZ(@ }]8D\U#nvi34of^h%tw/:YFN$;UڭL/I,Bef(pތd<blZJ9 #.c\>f=b챙5ח\012"^G|#%P~::*b-D#SW/9jȘ lXO0DMa#B2[oѰ+1֣p>;A -:Oev.;ߵ|X1To`MQ]j5B F]<ng Mͼ*g!6A3C*2JJ FjVBdL27-|Nv$fĆ:.bI͉^AiAfmʟ J)ףw1kCESs(DmAVS49T&6 ) Q\RU"{.Q"̻yO3dfkZӅewɉ.,ydBmDۈz(71 f]wq}z~1p]ϟ?soGaY1DZKu! BXRP> cL45"^׸R!ӔSRP"y3F4' ..q(E;~:u Wd DÈq{cp,rkBziGJ*IIn8Tnr2LZKF!&95FkGz,1$d*@Ms f7sVM 2%ȯ 4oø,n.冮 %Tbrcb w=љ, D@y"ӈlr|AڎZƥbS"Cu]I~$M͞q?f_3tׂ@ؕ{Dm,CC25B1Tnf\RH❎ GʊX!lHL]nv#KDn=v!$*A\MU03EBW6yR0w~5VBg*{4l;,_]g^I!Ug\|fH *9{d[:LS)FLר*1PD@%@!sAWTLg=i#bW?9xE_HzD0E )YMB1zq{`"5/WT UXn&Jbu7 av˵{! al2l:(G|Ib':wh^݅*xA0{θҶISu Sn.=ĸ )TIRfp4NPיs_2r?v՚b>3S3m;̕ǰWSX=nw_֎࡝}b4טDe $Q"tƘ1^4WN#'jvߜ !3rr ȸ ?64T;G+uk׷ 0qs:bf_Eӏ_}䷲t͛~z]h%@RJ[TkBvk2R;|0^xɝ3v{u!s^ VOmŰ.Zc2z ΑGƶNɤe1`iU= %u8\"W'1Vc.ٔ+3qpEqLj\b93&Ǐ?W߿8gf[dL ZAʳ"l0Z+ & W %/pNkg񇫉8OAo91b0bY[m^Q_2<;X83O <3D]ړgMɄU ŗ5:Qs8Qh71Mj\gBY2 {ʵ}}\Y$-$:we{ʆ# +O+fk>㊄7BJ4= EF΅%Jêuwjoݕ_?KU^W@}H88f82A$W}.K >]y FtgU/러.$.Bwj>v= ۬ɰcrvTP))1Ƚ^Xh[I<Uxu &y1D}k]0]5\- m|͹iӳmIHIWh:fi[شY~~ ul3&$@X9]u0AF揨`lcsNUfc<\x̩T\Q]33~1iKE^sTqO.C^,Ro!5]TV ƈ0T%o\$}ߝJHj}&<F|N".˝h_F*[V%/XC"shs0Z )!R"%[KXt8-JFS*mS9#7\z>)i)0nW>8a*ky:LyfdiI?_FIIX(#lIyL-5.5*PS(%Fܱ9>|X^_i !s!X sQ mbu0Ŧ[ȚK3wD[YbZ",[2#qWbUA=bhjfڨJK:f4mf!kc֣bKaBE1W3'(TPTh2IfiPs1::%#A><`nԛZkHEj-2ZkyEOF_ϟ3%p|}i "hS۾u \|2-r~#ۚɈ—q4777S9ZFg~ CaĢD#+f:X'۪)+%""?JfMU-`o]VBN3hs5&x9 #TC0&ЌxzaR'r| W;}KFĸS 'βdB~ K5w"MMݑc؈1j=ɐpm"XV!ynwGz%*xj2=o9!/%| AľDkEoRhyΪ$;k5ɺ1ɚ ꇐ)fVKXKH_3[ ( XmeY:o&8sJF2 Ig,a9ղ ;],^ji9e|:݈`-WrB3,8MlU [nn#BaULjWZCzˆ4I&!Ak"]]־BU,7\7:)Hfm;}=2S*7fѭy^3r(m9Mb}%Dh5&WR"ֵ͈:29M .tZY _Tɣ{H"{jm)֯F9D۴OKcL 9Lalnގޯ2ou@- ff_m)fv]UoXǏ{gQ@@KHkv3 %eW$Gdfj7W@3.g͆- -95;0 *\YSysҏ5kE딽͎4KUdLYȼ; f9Y JGNNp" Aj][3T[K2T]S0F-sR$.h=U5P+/N"|&h 54뎊fDxRMs)I2֜K8x"UҼDZ-U"@7[Ş/ _=:ZsUkbt:5JVH1+r/jΕv @b.&nsKͯh?9Gss-A=vDqggUɪ:5D7 UX![+FIܚ>tHH qU03\˫Q " 4S I$ƅFJ|kZ)1n^s`ySryk@B Qbh!v/OuT,'I2PE:OŒT Ѵ⊦g|uzjn׸8-Dn`I KSW_AwRQ%Sw,NR(UrM1<[Dv]j"8o dEwa1a$0`\co5$O!> p!DbDka捏f=RX--jY烻n1剶vrgׯ__@{#w3;MjU }El<4G;p#5B7_[c1ft *+"sӹjz5ke׬=C7PjȩX:i'fvMN؝GD~L@EDqȥ`!L_WX{PFjO[s`6a*47{ cE=eITt8EjwT޼ ˧"1u [0.*fvޖ^iBTD ̌ ٴUE#Ǔ|n-Qg <T;lP5șTĵGTY@9*=z:z"woЮX͠=h#-阍z7rru1Zkyyk+?Tl ȜT:3`8ţNIUrfZV? z[pg-#Ơ@cp3kf^iD1bm!UE%2IlP|bJU-9%8Tsc֧N|!6m˗bRD3I&WZkz#& gE.~qXj+9NM;lQcʎnO,y b& eׯq;׫;&䂤V m-=r"Q'wQ?4g둓v3t}'#~ʼn Y͝4cfF"螺9ߖ6 6fYASu񺹵zYyy~dRUw9 JMa;_[3U#nMN}TAF>eX7:k0nڐvm?CgzfL!k0o*Ȍ[UT\s Z>"<QD(Ѣff­f4h&fcOϝo$O &4d#Ľ.5&6Sg=_H u.sP-f_9}uˌeMX8e~o~q-_Tb)LGm&*K4U L5U%)"3Zأ]|:%12+f Hk~Kٮj 1.i^3 ^QGrɳ\-D*QfdXfM>twQ$ҍLvP]knfE]M5y3iqJG 8dpSܴ"ƹy][sy轻y_G/bz=?̈s3cցA}i+ @[dJr2CWM^;yKZT 46NƉPESoʸU9Ha=:$%9X0Z 4UfݲAD4gNRrr7~iPVkMpCUD;>};U+}.Vm佖NBkVY&5RQT?"Tl`߈wv<+py;iiIRd UktH>71(LS()C)|=L?Or{}Cfh cdo ^<)볱e֥"AM=Nܛ$27G(byU,jEx^Uun^ݬȔRbSBaLTgXW7U۠ε*01Hߤ!ҿ`3Gf6\EbAͬ&Yj#YZkxW}Klx@0`G.FD'sV7UQLl)XU)1Qu{90;Z7Stb=x 9)48Lr-)-YP0? Gd[c?QL,Q94SQpk$n@ʌ^9׷w"1qBm=$&j^r/i\ɒ'j$C,m ,#MVT{WyzkdFϣ&1=X+ %T6L?kBLFMl"cg2ܔM˥Hmj J۝.1E+Daѹ=Qngl|ahRVbn@DBKn.=XL 8eTN+g&?Dc.zss+UIHMjw}r퍌ij5"TM$rWƲ`2^HL8wNy[W9423/Ƞ|_cggF>CMk™ 1܉Q]$7g^ټUw߆~KDS }~nJ{u Gz g;9"1uٳ__M{)|́#W Uٹ0 ySKȌLjƌ][,K 3e?lf"Vr3]Z m)!:Pm0Uxd+7&x?0pԴC6m):* V_Xο AtT\F/kyEŧb- )4 P5$T').S͘4UCV$Έl"WH[{h"oiqq iݯjMdt9`ji?HB½uH~*__/l~~u\Kծ GoY|# ;ul!bsW?7fp*;Oإ^*?OCf}fRSҟɆ\'%Z5sH}`S!=QaAJL-Wg}Yͺ)wJԹ¹%Z;UQYeg81b 1.#"o&"L]6Lf#|1kR(**MF mGjDHooΔ]̺߯Kͬ2 z_pmPbsrҚjM&V5`"".XsMHZ d*@Nia% @2Lf>CBfDONί*Aܮ!Q{8s?s4WFDaI2^\S%/|CIU7d*$&uaRƠ'/o㗙# 7@/ S=ٱĴ}q:isIItWmݣKdͽ "B[ Α* sj5݄qʸ2C2U+b#q\wTs=ڊcLT[9P]4 fOНT5f'|6m Ptw1՟D~k2x樯?:fv^OxnyovCiv`WSH9@]UW}lF _h@ SWN]Hj;rn#S>XOr ^@)oۊsYqf;0f-5g1Sq̈́<2aM=av E0|GSpv]vV'rtHEZ+@;K3'8Mq(F/ )0Dns>yzFݝT0멦F2 f;=8W)Q1I<;w]+S#+`f;D@Ljz8=Bҵ׌2T؊gRj{ d:-3OPaVh [D'f@@額;(e4 tiضlQDlƙn_P*y}j/ =_n=9f*zcٮff&v_ g3nkĝl]Rbc4߾Y큆aǏ˴FWU([-[LGvS/fMcRգ!r-DD~h41$b<,ٿen+'>($GbVL_O[f0JiY;z 7[-m~Xp[yP\Õ@ YF=7,gV[6.;w6f'1hg7]3?P=!lux_\Euf|YbEv/&4a 6b3sEd!aWWf>=,A~ݞ{8m 'GE|g쀏LA$&ICVpuXdyBɎT1#\H^JJZMS {LX )ϲMʙ̵Lk;vڬ|mmJ*{fU+u7.Ec~DFsmXs:qپ?^?yAVOKHɼS<+<3O^aBdEjIn+RK @6uFkY rD[?(4A/g梖q1ΊCbѼ\%qxNvձJ>]@,J5lR[g=6ǀǔ;B*J6Izdk9[}mU*"2XN.&Ĥ _iPՈ%+n dU&f+M&y,%S~.ɌMq,hp5#SO̼u5v:_Z.澹[{D4s"ro&;FUTFp𤪭F*n}YR<#Œ%N$xiE\ӺU%$r.oz4X\zX'g"b$:}wMV$}]ϟ? o)vnԒFGzFyn.]³Qe_Տe>1vfjQ\5L5cӼy-3l""J ,[H_BkHdSN9}:mA/5X7KMu];#Rp]Wo&{Tye7yA e:5ؒWP[W >B)kW?}bSoy9^} #+bF1mI4T{fr`Sd{'h6YV2r&[-| dcM՝11hy(m6)7I6>6C愲ѪB/oSh$0yԖvno@c3OԪ&m9ļzKoa&FAt"%!X)GwTk{K3xwyvoVM4U3MO{kw5zݝ\uS3H:h}_Q^/T 12lq#fcl\ޏ^ e3_PuUw9?d!hqC3z^9+?뇹K䏯/IMII{u$$ByLiP=21bewIcCfCs߉%*Bg4prI 1e\; bL I.%KzTBZ#⮆ @\4!֜DSILdH EuC&KĖ*!93=J)A;#{`J}fTO_sòMN['n7B9{X2:a)kL\18%qβ2Y͐wuNLe i3ҚB"Ԙ˙6b4PT*5JYL 6~.͙.+@|nHSyZy rKs'VR:Mwko޸"Ll*9u`\#;P-npT ҋ A(OHB qѡQiY}ɸ20fM_rD]՛1FE<τwH#̬ kTC%즸MJV2]$ޠUgéd=(-f2L HSzVGbUQO,MqtoX\nįϊJԎ8Μ)5eέ I=[3JsZR$޺ 7P=ZC#!L՛[BYݖ$7i==o9[NsΈҹ8zԪ!A쳼>9IհM' OVk*89'  4N6g< laYz0L*{+%IIgݜ9؛{v2!m]Y'-d-T#VS60t侯br1J F/ܿfDyKUUu]G E@ş˵7k+_2ed 뼱FqG_>p}[:̪ o `>]eݓK5AEn!'CT*V_^-@m;RY3G|ygZj@(gzmfOĐ̈́%ݿt)oMP J~`Fpy*E8j蘏ھWn)~8ChK$rǭ\==V$Sa!f`7č=NMEd'{W]Buя}gjW+]x:ڠf:j ǡǂ/><;k1K1LD+er҆)"%Fv~d!ub,a"%9FV1҇ݕ |u# mJ(ُ<s4HHȞH+"E/GfZ~4Tw䞌 ,ʾ«XbsH1lgU,IPUWw{83Α| ks0_;a97|QB7?F$g8jQB RIuZ2BUbf#8fVdἧUjGeYlEak4jzIU̱WQ}ɖ;L0|Fzh%ZxU6-?=ȹ}Vb)Il],"JpZ\RsHƇʦBpY,5ZLJ|,15=7Z-4PmUp'?%2*˨a+ЕcyAe”CO2ds#f"{5sc@1HAHfV>Nl.3.ʄ>H[]A:lW ɍxӲ݀_o\"}Ѩ܃qos3>dM} hsjYJQ*s(v Co}dUQgs"ȕ 9Co&a&A&K2Y+g?K"Ȍ4lm(n"JQ\ںrB׼lpfhSxHўE$T|ʭɪq~D GM x6#R׋=ak?ĶlN)\8!94$a(":)= oxv2lN En:(#~0C ."Jn|z`d'{GXDz Vzq|N;dpw~$gM L_]ZoVKKxiF|Q@0NnQ c9CC òbv3ԧd!-UYFCžDRKv3FoBhѡR _M%96m12VEáLJw| ұTz9[__?t+{)=w2tdTs[]iPI{9S}ɑq8V|ө!Ӟ&S竬lnR W3Oʼn7/~ k! o)q%Cȼ#+ xăh S4CQ% >Ihf{/QT; @|U9*+5VeoF jr(eImiDj*D.ʱDȱNERX [Q{ )&D:˳fR*h{PDHXGe#!Q"Za1(I;,R<,Y5 ,MUX3=/gZupB&~cP)KV=;3YT3 8dD" ē,t@xG/Emw"\벂IUq&Tk3%!kKlN|wj^]s,6;@"r R%Ӈp9 H!oQձ,yfs},}Z>K^!iRɉjZ{o'k*zp [r.,dFvm7Y%)3C@E4ayWp-$\ |V#bW &z m52ݞ!LCJRiD4oXDV;-"_arb }yoywMŲMle9ܧK-X;Gricw[PGML ۪l"rVr\.wl5s݉_D֍Y1sD8A4p@`tSg4}:DQŠL+s`TQ/`Bћww'̈́bz.z%2*6!u!8M9 Rn!{i?BE.zdN.U.IW൶QΝJdHNTz-Kc!mHeywg48AXegߴZ3[H=ccnDcHܼj\<(WxL'dpls%Qhm~l}N_­]M:RL*iFFReqnFJV}$MEB!B[" Lgy{s;_9ګ@)*PqwiZ7)ᱶ\ow/ή\(̰4ӭe-qS,s =&:1)67C9 Ip=׋sZU7]Ձ_1|V&/-* Ͼ@N;|qQ(EhTeg<,(D4oei8 8` ۑw!;4& uVQ }z^4iuvTٰf涌P8F`/7|9L_̦t`z%/zׅF18~9-٪9i{9+!'vJ\ BPu9sjPUV;/1\Ǎ3*Z]ɧ Sdp 3QugGP[˜3K6^!5Bzk>*غ5:9`bBO 1e@nwi<0΅G g$y2);7q!f tb 5rkRnUb Of>g:,9Ƹ다쁫!zC y} GpMqЦAlsjpq*3~~|߿y 5{|ɸ* #i-! 2`v xۢJ*>kBU8t,89y ЧJXS0 Ƿ]q0-vhDL8t8 :L*9@c}Qazȯ_/!ܷTz-ueMێd@4QС`:d.ҠdA=D敆3a Rfs0\#KXVa57~sYECpk5bxz"Gt1"8[q "s,4"fͻ:9uZq8y8dOU f*W7뺾n7{bfi4 9d莯sPb_î2x,9]!`+OdDpypaT܏qBW$Uxt8{y$x+ep*THFEZt(#gr>~ c ~/cRh,?#mh ^K("cYiqfI#5pWEF(ġ*,D-hI /3\6*e2YBAf%im"z0DRO䧮HuaRg`"Љ>U1D2$X 첦n^d>,;9NՄt8OL>qGܕ¡)jhTD8>)!곰iBB3DLW܍p9ftLh\u\,~TOsFsJ0Jqy 2\GDT*E%yΑMP-~VWxșU A ٧ܖ%ZMX5cgW#LG0Ead!+ꀧD/lVEEWp3k&wX Yu]Id-ܒR<3 7eH䟨agH*4OkPDGBOa|-D16uc1ngi:Fh "n0'ivF[&ɷ9]yeFsՆ:gkAfxKV@Ȝ̏h=?bՏ.(zKu 9Ȑ9`jo5AKJ)^l}Z#5ȪQIz2 _}}ɻƬ k^iۏu#hx)ߎ'lXȥ, zr?VT$;v7-GD_K-m^LI#=Yi]gYWJ=}x+Sփ("iTw÷%ST5N-zyZv-zr:n.pРIph\2:@:҈f|gcC4-$|>6V%5eݬFQ Lٺ0ZDUx<\WD*X.ƪIkѫڦ8(1nږ$yrXoIp}>ozbmG=aI1ðRyx"[ڊTceWĤJΥ*27R>NxRh!C+(>y $졟qA`/g=*E (*jXEjp2"c;{vI?ꨢgŶxMq3ةR䆖!Qܡ} B0,*?a)[1P4E=}2Lt]<tBd ,Ƞ8NX8gv8!)`ect6B&F(/ 7O *GX]$S^P1wapsa! -"BӅ>"Di67k NZRM oYo!0e ]z!L%ra A}T XPܢBvo|wС'"Q^ﯯJመsǑT2H +evUWɹSNAx{݆NJY:RA:}kuJ㘷\ ggm~ZO4cts"ToQ\9o2p M*e$Ckشěۈj?;/[xH;9(O\} eӂ˒yuW)CZowqʻL{5Ĵ`bщ_OҍpCYǽ\kQي39+wTѮ9sޗ/%Y͠@W'O0{`d"ia8>fF[S7BDht(VWQ=B;V[7wYwi.b[NSo+9ՌBC`?U( Ç*}o9J[`{np6)'0$$fsÎ-qؾl+9tUMҊBjZ]HScy/vgrb/za@&>cjg=sZ="M$f5l- ʦ$"{H]-&뾇ߝ>qV-v*=(ȝ2Yga6x5i-"]*"ylyvk+PoI%KN3]Kk}__}ަO&E2:aqkLzrus#045bt-hwOV8@?:?y 1]Y^Ef}ARb(VﰚM\l-ICg 0*h1~DzM`Ĝs*ʛfk'jtdݭnOTQ0炂#?@}uN!<JceAUոU,9[D)| TlIu߉kQ){]Nr$tn;T:xe0lTVub5flYFy;2XZDf!*eLN8|{P'&6!L'Kp3Aຮ1~zi:.U>wShvgJSUt {͢i$r?U~*ơ'En撒YLw4x51fӾkƐGVȌz5))$9dLHAx.״yq}Ĝ1Y1݇[n#YUp 6,ﯯc>TӁxy~MZ_J)(SC1Gzٞʮ\,˗9R^gsQP%~_q[ x_9 9gCW7_ǩfq+c׼rPw[:A"f΃˾L[Q\ 1Tg =߯WښGe,^f7>ߢAl; *ACA@شM6u_=m(4#&gE|0sӨ"qr^SFxE~1—B^}ڕA]8<q9mCzQ]DKRQ-dޑc|ٜF\F+1*g3=RQ9%1jQ3 ‘SPEkӔ̈́A##|ؔqbٌ #j?$M*EV.ܴ!}~CǒVl8R7G`@pȱ3 ŸY. `+cxMBa=pN&{, GN"v%: 8~Ms a kxZ;Kx!rD#Ja#3AE(dpp[DI.+q|H@*/@2ƒPq"mXɗL ^iqDDHѽde}C]bM[){@X 9JZ+Q6}0  LkG8NtH2+&E,K̄,17dV { )17ͬ}Pj]TRЕ#ф՚z]8>wvL.**IeGoT8w{Ӛ1DN7O$Ɏ˱N(*cplxRv5ۦd$9ZGpmEց92̝ UO];D\c l7=꨷XG--_]0|돛1}R(ڈzH:O3;nnbgj~O -PQQEDFGO_Pc??4qM[_'DtB.lծfTNnw:0,,XB"~zSV`j5:K۽4awz"2j|Uz-܋$aٮӲpΤZz قʳrpҙW*39 ٵ|7 3#j`0  :{tQB~iuCW>OcSo))nɁD13a$CG(r>CozTd@^ET؈ PM%iZƗ"ݩ +8d7u 7 |Qs w ՠUPVBZ`zu.[I٦) w>^V'R $KgL?;PEcW{J|[ r\ZB)ceऴ千GIsI 膳JJ.!2ׯ:q}gic{.Fu×8)'ɖW[Z)c 혚;1^,P| 7KeR_0?YfVOkIHq׏G8sMS-yOLC5Ӭ( ?0̮ Үr6ܝԾul~ĜPeYf;P5[y"}G'===o Ҵ`os:D]282}q ?JGʂ%V,ȼ"Cd6iV/vYVXM eݛS>F3SV"FƱ/,eppOd~8Mԅǘ99GؤU4Q9`:?WS\pSJ=j?~HҦgbVDfTga#@i#ox؅741NCs꼎/+(P;29iQό2Z = :(0˕ pɰ@& (Ԓ:i?1BC\Nwyѕ%II,| $ޥ=hYJ0#bgH w[QgZDb^ 7Gջ~ÚIC=V{MEQ {=ƵFu[ELq quY!tŻSoM?+c"O'\mvYd*)J%TO"3:~B-en hΉsg3X/jr+դk{[1޲gxOMqWNugE)XQjLS$.)SdN6C^>a\R*[R橒N~Nƪ*׶\ ޜ7WXPr}K蹞TnnrpPj3fOX͞&-caQu +kDl'hW)#C3 t?@)(ŀ7jp94foX7;YpGkSUŔ &3Blsߗ][f(]0V9@DX @; OwBdw8:Q2\̹③7AηЍAL^~`d$.s^!0ӷCGL:`tRi)"6j'~;:/'Tx>ҽ%"Y[+KD%7m\ ٝst=뀒^WKPͱٲ*aQ"E .jv_0UU+Ӹ8@8 iےuզ4#pwl0 w%d,X~.mwhV$֔1h6-MjC+lL q~SH1Ne?~[PLWΥ{^@M|ssz~fCu6J!4[FoǞzy3! ~Aga;U!nM!0F*H~uMaM p'`BDfJ{bo9Cd/AM?O,j% 9c,뺴yӯj6˰V@҂Ȭ:{ɲqٱ2VGzBD\HR+`Z Xz(*-:l XX'lږCq7Hљʅ 19mX%CgS4Aj~,W^(mL@̃{awDoQ)AE1аWTL|y_z8o빞w(Rzmuup,hA hCz[x YZ|+gnec$&xy.!ZHj-!#1/7k ;o8!CABs29Yۥ5;,z᯿p$ "DITHYf0k1Daf.qscdrb 2ql~}}]gI6C{XZ8|CΈw|gP_s U2eQ1{~}#A&rDxIVzä-/-RԶC:Q/IY3u,qw)Uw0H7pe.$I#J_3M{ lBm2b$xG˄2H*ܔOUTy޹qȈ=Ȼfe8Ih >MyʦGnJYYCLso!ne9#r$7Y̜Bpyv=\Dc,G %f¿jTMmL1=آ֪wdՔeŭki=ɛ"jdĕuֳ]W-&0}fkR=|\VgVԍMB( Ȼ0礬٨w[My}.W69"vr~=}j.!ሄO1_P~4d lN3vWm{ ۗKomo=yf\5oeeS%OU~4+ְ t3ɈFJI?afK@nII~#n F#SEop1`9";OAaU7#` 쭶*ȝ9h E-ķQ\IZmJGiNߕc@jCcJ~S}c 5N}j^[UZΘ=7HMopؼU)2  D̄G1YMNW~ o-@2QgWΌ8f bx/jI7#x1`}ψ8`Q})K䞢ݒFتj.ַ2Ô.LVEHa)fH2fe ǒW) 3OuC ZwghiSlt!} 8%]cu0X9Ş{."I [5 _Ɂ ,a ؤۤ D^<,9kAIlNYV3 =}:p# 2$yb5(0+8!*%ma7SjEC.^\_ӅՖryگ'vdsWcLZ{` tCI#3)EU0[c8?-nYE&ȄMc$%1|\wYm(Ņ |db[YE]cpҴpw (7t-(~07cSɋ=%U*){Z9[V׮ pT2` 0Ĭ,irnB! {C4S#Sh_\ba=8#?؜CB K6"eԎxgvs)em.>;B8YGPP2luj'*SO\!-+*FUP $7;Dw:,_ G?*|6 G[2ݗ7YޤRԶE bD<"Y2:͗oJΰFlJI.^3mo!hZ풲S_A"Eq-:E3 1ݢ<)^-J>S=wAӻ"Cs둜.Վe;~ ]cm_y-kkѻcKUp 'qOfݬ;hǃ7Ǘٍ d%VȰp\9R"z]ugv]-9Lp(~dаv?7)G\ 2>έVDVfjGd^o}8"՚>Ƴ4D|B֙iڵ&CTQf5U0Pn KGXfnu^Dd0c5s(%ݪ,9RT&= "J5RDbZV]?cை؍ڂpg,vŇUuK$7RmXK{D {ՔT|A9)-ǃt )O$5 V P,ݹ ՌvH,fvjF:iݞ6YW:0k#yj>t<ϐ1PE Ì}1B@PH M Ha'jxxe td6pyhg/ӱU=G~q2t8xX1FDsɱȹ~u?l@eI*At&\gT.~ZVP?{ ґ&&PP]buMr?XLpdO }g^]3OZ[ՠ} J#[CƲuhO1m+g9.7ԃD]ru3g|y(\,w㚀}lꙅ2bWa{Fk7E FRf}fRfM 2g|2ɼJ r!9e#J2Oj$ \`n$ Rpn 9o߲|]d f1\[ pQ*u6MF(,2 %T%b^OѳT`'kwI Xzdoc@0ʱM`93 3F=#uVa,oIS^WHէ2"a-ir N wndt0j}cae._W"k+!wF_=߈R=|suwM2$H3LS׼Ŭ_e@VrD(nyK[<iK% }ZdzϿ/4鱪80=Lcֱsʚtӷ͸oADib9ǀݷ8D*%rYIۆYgVDncJܔ=yˡ:RVWUK3<~.2<xvKm Zљkϼ7XS:ֈ1<GHC#t{>Ï3^>CN }RpIa. M]lLqnT\^-_CF& DHtLss9Ӫ3RuϯW }8P3Lb^|RD5\#M.c_AznH3ƜZ H,$D (``'&3眑v>"׿lqFG$-@|)ׄ񜗩qOH,۠#&:{q 8~ǜDcu>D"1jx<@@+\z 10c|mi<)_ߏzqh{oVyDf\<s>cθy&f8PNq3X%V<5cyk q|}}c<kNtcafэ+氣b}֣ughkNf3( w&ըd&L&K>^]%}[&P<[$SBԭ^ւJpnc#"l5RꮪCElAlJ|xaلpbZB7m ww)dKyk^D2N 32E8Ńq/9nnuȾ}c!]U8V0 tԺIhaf/s׸q bDV83YfpqD"=U,! t.)RD93Iݽe33akGhMȶv꟭o2"P7KWzG2 3Nv ]s⯶ʲi"vt̲ɂm5@B!:̵06^>:QM:X$EW *ø溾5aA_iS*Zr}DJ'd)ܷHi^ [˱"o%$֪\-(+=]4 `jR[+)m{!fmzp5Uc(rp2ȄGAۨTdlVFv@"Sd(frn*,\DYҒ.ܴLĽ[=ґ U"'5-38\$T*2jR1GXVlI6 m"%tPb~ MX:˳Lg/466ݘ`jҢi"- ,0cZa8 c3ʚ紀*V7DXLޱobTb.2/N} Bt$p+ $$y]Q- +Bݭ,i0}*L2 ͧxKZu1'e[rD!K\S9e}g4 ޒH1l#6Ƙ32cHMeGOD>1}B%S$@z|>wՅ Vu#Ct{Pf3h4ڃ%tt7{MCpLPИ9s1D4f ?sڀJ)eKL2ڵ]Zȓ?PoePi9R>[5@!gޮUkJ &"r'Mn9\k%l>.\'z!7eoa,>?b]/HJ[n˃μ6lw27_gIgo;ȣ$;eR0ÉXW#uʴJS#ZbƧe@Zo6kluXLh7U5`S;\M*mA/;Frٙ͜ےc'7hq#@ֶV^֏2{DV* ׫̰S?ULv6ARitV RY  ˵NA5g9(fSHFc\ƋDCDrD$H-ͳeWRh8Ll9uK`ԊjCj}Z%tb[ꭐO%&D݄٩-$ L*rt!?, '++StHlNZ-LBzHÞH7^j[C)~Σ~^Qss/lULLxR&֍wa!cUa-\M1FB"B %N? w@~ȫ_^iTUF LK4'5r]$OeG ^3_"c׆r\Qa}j|Yf4)ZFXwavDsEFUC*+]&-b`V7>\[&;[&1Sb.şL+Bf[r򺮖b!{ӹPe^6a҇[Cwuewc9vZVP@R?i# V^Rjͳe6 5T kF~{Zmȧ}ù+eXdV{p/WdVװ "QXnQQ#;E7M.U&0,,QS> /`TcyUn'%mR{mkK\uwpS%4L&NYDrY?,{v?8J*#k^hkp+]%g1EWWca*QLIb SIe,="&Cfy薞֒a,e+P曘sqY&ؓ@@>tY굲f!enF KD| q77HW3ُُd]UH4 ]ޣsy=lIJU`++g"TzC|P-apu8r}U0:uJ8>],Pymj0RecD\MdrsASղ1 6lq"-'dM6}42TwwŜkYm}߃3vF1rsƠjjy1y&̎q[ޜmW RsutDnQlr ny=cͪL˥%oidBr]h#m22`.[]VA:?[+b U/N SQ9԰ T,$W~EsD ׽w%7`?2T(ߒ=zCye$+` 'kP&:RRbH@3.zT瘈P@Q$@"Qmfden%nf<&7,]S 9~ |W ~EΛ[9|PKBV0/@PdR=T r!uG)f}5pNq=X< mDJXU;|04# 7b5ʫE==ЈDnM^ZUך(*?GIH07r" bYA"_̜*wP&mnf΋gmusz2ݝC*x~y1S5"v90C4|8u?+8@1~2UapS4q j>2tgDƁ&3a|Sh|iTLbQˑP-P;/^3T%1ϯ8?3Qd)}P7!HсTH5Ь ڀࢆ+kvȫKP*l^D/z)(e !喔UtAQud.iݲ.$j5u*jI@u+a$kAzEabR"953/KOC9U>zwg{oF5Rq*C!A؊[' IK.Y-Ĕ AS%EVxQ>/P'kSQJ~т!rȔQWrp rHFӱD*hEC)¯T ).T\5}@ӡ,8Z(:Y3΂sG8 fTWBB'z3.H&e|@t-C\+۰#JI2LqKCu93dY3PyVfRBcS+t'J^=u6LLRL*~X3qZ5nyS$quwEH d8NcJEj3sy daTDuH,TU?ѥ}sd vG)-"̪;zqu,⧐'B *e-|FF2;t*W.AF4La9z6ܟȰ21gIp8@%\/#jC ֽA-WjSkn u$"]F9R\-|mCA8iQ l㌕=D=DrVշtH"Zq=QURӫB[ӢJ,pYinm1 ~ԕb_?lf&K%~0(Zn=&>3f$% woE.m`&EZ٬j{v+lz<~y;½IPݥE,§T>fp>R!$t5%"i3[-1LyPbU\ʆٸ): rMv9v Li(.AXY1 ;,*c]skO#އSKNI^/UN[cQ\M{>w.FRh,(_y@Hi籦ʑ/]4pp)&)X7n;GR+cImw`Ԣ# -{&d]Ul(RRC/|z9WDVyw@rC,&Sq>*֗(2!P ظ9u槲QMDRPݾн`GX'@TRksxDI0^$" / ɡº됺o)*"qi1猊DFG h{h#@Rv'[Y{ ̘`JVJ'cA\,E(êDĆ֬~aXZCo|<o' AYw7~h=ifG *2T]‰Ck "~~Y^qGF~CJ.4dIb۝7 ,*!]}\G[jN-^"uEкwՈbS"-aNH2 פ9W?m'Y6 "q;B;}UiboܿBPRDi>'L6Avѻk3Z4$F`X[:*(U3~>O߷Zzcw[d  Kp܏1fCG}ZU U|ȪըdJvRqtbƼX~!sִum[߂zowc=43$16{2V(b-"}=K>~G*Tkxs w&-]<{5(^1+M+ÊBb ~Nn?Ro|=?G[̪Y2FwbX{uI#.7{Za%M)p@NX4 HpT&ur -8Sd&b=mVu/]{7ު7(4U/1:4 ~,sQ}~o7VREFjz4G=8\uN[5c׌Tvw+} g*R[y;%(󯷡=aEIQ *Û04eAEL,5 & miA1\ԕʭ6hKUx @}CTfDg>S ֿeWFz<89ƈY%uy] lpbrqW·1a4soft$I=&c*wI9($#!ZiV{nS&ߜ.cdȺUG +ffZB]G7'i&M\,+G1]M*QItƳ{5#WUc))J}䯂lI1çUW;Xµ혩=zcw齪y9 ipFץ]$RW:>qhPQ5b.4]Oqjpwq>v\u5v:}eXZ>S]OF~X_,sNދHyMtPZQ0̟k!]Cؚۙ~tFo뻎NƸW1E3dgΎT_mʽzUМd~ͨ6S_En،SR.JxEԷxC԰[ADw^^_܀b{E\.ЭfCy!,|Vq b?#t!ʀ&4r>=4ZHu Q|nDӚSI!g)c"rAT۝[jEZcfh "ɱ. K;UFjV@C-`majFR`nPyOW^ l O3Q{ĝ_??1E5{Efć}u]1BܤMܾe}XG1a#2QP͘9^A}Hq$ V}U.x#D21H1 ~8se;^_'1ucDĔfNgyB5j߳*ff(v]Lwu6LWd \bIgDq1V2k6}`lv*w.֡`D"Ϟzs;\i9<jRNKDBT凤ZfByegy>>5`u"P{$"'G (vT2n 4ʦ^*MT1<cL5Ȭ_vIN )25+10tEj^qf:ׯ_Gyj# u"uQ\HpCMD>˘4Ĝ" 3!ؤo ]TT8ȒUU?RZ7Ms63֋[GL ם,%qrX ߕpi+[ pIX#9ѬA Due8l"ͻ$Ї>ϸh7.G(?iVdWYx>ƭ713jyFb ?1 J;VchfAՔ66%Ԡ HwpBcҒf!4Zn*)+?Ls^ v K2! o\IMZ D@կ wnOV~ GTXh[}ᵆ䌥"~ަI{]{akXYǠ)*siBTgץ*3ְ35v̙\4"Dy#aνab0k Vz ej@.h߭ 0 "Nx(Å"לCu9o<9_QV*uJ qT,bʴT:pE3 D\kHTBM2%Q`45QMd9Cӝcٓrؗsf9#<疊㘱!}[gβjrZc8rD+N% ,cZK03%cFyKD[^ӒL15 $BMpc@oz/^ߴ3m2 *$x U5YVYP8ǑeDr1"h1vjQiNR￿UtLsHx '77v@C|<"AktN!K/$u!R1VqP3h#OՇDp2\aqjrպiWDN׳*jv12sͺ L KryBɜ33N̫FuYfu]u}=)FHX}Fwv ;L|I(HB+hcD!&CURr t^G_5]Y9=B3ӈ)#ʗ9Ԕ4Ƈ:aVZUd3t8F(2Q@ KH9;]נȐbkjA]Pw1 [\ʔR{fmDݧ̷Y7Ng\3@LyŵmEQj `ԣdFbv|(D]ibCup#0IȘR HFCmTbwDgH/ .r{>#gK0<*vH&%oruթ KDZ'@VuT┤HAKeƙA, H+u~R)]a0̔ s<݇oq1;SR v,l ̘8ƠfsMx<~q?!j {=Q}q|fDA\xu/|7YOvsUJK6;R7F٢J8}dYUo~hrfy5S%`v+6qVr>VpaecGVƏ9> Z 4*[wV8yi-1. qNͣf&dߑ+4^tAw+Rm491f8 y [?kP,f6z*w.-,[5+tS~s\?q^E[15%[p)hefIsFcwL9aR!dV@:L3ܕMGͰ5.UO5^/v>wfȔ<_ OptGܛ-na=Y1+t|HE$M<8|A#' 3j6UeZ(9 k$] 0[MT~ ^ػ+"_*BY:ݏ,Ux1{23s) TԪF1n2<" U9+S@8O13s^Y)FA̔$Mp $Xlzdsf5VH;鞓v&15*{D0U^} ^^tVZ݃$((Tr.+eu ̖[)"y#gȍq׭4 ~)^t~8r,rENUv"Ӯ2M˖Ǜv[[{t!X$ToU;JB81YZHL 1$jj6!*:k~݅ PL$f5ӔP1Tl2Bw?J{AH3{-UfԄ-u;U`ٱ?&' &[pQrAȗ=dLH/6[X)44RUӨvQWe3Œc̈́9 > Sf(ѭ4*ڠIFBI(Z4svՖun$m*’`[FBIE۰Z22b%-[: U9_8;^/wDZWN0@Q;fw\JɌq ʐgu2!g2r3F7mݵ Eajy18-s C=yv hM{0xTWi%8& bk;& 2&%:PRHb* j]mC "<<2!@>ZTE r NFBG~+˽xf6qUI-___mBJne|x|yNtqj̜1kbslT#|Y^-6)]Mҳy]?"z}okoGkyERU\>Tp19{>o9+]ϦQS?s̕Tn\yL6ɯzDn$3unM5&43#.λ9dekmAV`Usj]Wr[HIV :1Jު[`#et;9ֻ,#; nl:vyt(:Y<@YER5z?g\S#ӎc3V22hc3B".1([.Xz;ڔJ_gC Q7{5D56=y !La5RH~CsX 8T_[f9'K]Wj 3833j -)pVOD VgɰlҺhkD9+yOP5ZYVTպXmjXqԈl]}􏺭u1kJF#1,#\ݕ d-؛ <1眓9z*sކpq1i.!P%AmL.& tXα.{+ #y]_+߲ta&s ʼ1kA,ew疾$x.YxljH.+5i >!? ??8"08D> ?N L`yc?Yb=)!9dKA5Uay)LݒST??W\_ ߲n^v\CiXif5KUKdp9$rƋxysV> ^ϯYaD@f5^ȃ5'B=^b/L:buEζc`&Kw1Fj \XGJ́TB/i"tGS~_}iNwƸm a͹V)Ua )dK̩CR3wl3&mP[?\ung5Ԫ/HB#hmM~>MfefGsx9z&/W S5B*5 &;Ŭ4GF !xm l_<1L}_43DS**5:)OG6pSMܙ&O}7|O7\4[?Ny[Cbvi=,-8SfhatVڈ!xZ+j!ŌJbRETf]qw?2^"]lH\Vqia֯w7Lj@%yqDG"Qvͫ{p8ϧql,:l9q"0"C+%/P.u߅+VAj`1F)~2Y2&%oZ`w作zI-/VZ5pBbNzE(ddjknWF>/4[S N6B;UgYZB ͹roeߋңxn}`%oE[e]{U2t6jnqk)*8.:VCHT둄@RAjFO!j&~U)K^|>u~|)-;-QZskS0Ps# dMFi#S`ZK#h-!KE͡H05ΖZfXA& Vk(:Ua#DSh+y|$ 4\\geTf_5y[e5 C6&g]UK{ K{)XndH#:WւBR@&:](G{0N<"buyC$N=kfRI|H=1N>T ǑSjs Qr" Dp])7/NR$/u; 8 -y] L2q(-{cG$fԲmx)鮐0%9ϑfx^q$acKpy.[K+p2&bkduw8q9Y#l.|T1yjb!xgi8w Cͪl/xCUW:~?d:Gh!p.X.Onjnn 7λՆN:ArOJ(:$- "yLo言)F|ֵŻTaWlXD0sv\~w9=.H:3}{7jz>E %XE-61xWz -f¥Q(afgHN5iה0E]."q ] էpK'|j]7H=W%]zqԗdo& U-sd,7<] ż7$E 7/t֨!W @(Jwws 1Ĕ x$SHyKЭO*ĦkpRٚd<} vp___Wq|AA|iNokJuY9)AV ŵ8aAlFAO-@kUSza,Ej+MgFY]_*FA}"02)mKqte۴%KA2*Yp@QM3AHĺI{IDP5ew\kCvRa^P^,a-xJ]GT0BuTNZlTRE GXC,֪zHE2sYb wׯ{cjRJCi+043R_2X8qa=W~f֤ȷT"]K)K$j!3G) 9JFF"\2ݗ13ԻjD[ }}+y3n΃Yأ˩VVR 9OeӜ( J¢20bk 84z)smb0I)"b Їx?5>*nM!a8th/h`7uުOɿ6l>ON7}U?%Pq 3:TItBbI/-ut8" 3#j["Uy.;xxU$2JI za@r }Չj`X!8mptkQa^I3/TCowhި^tGK,$nLS^ ʔM>cdΠar^IS}W܆M+۴Vp>q+:5mf ϯ/2{.N'eradB0$@KȔH)'XJ %$g$ټ^RR[1@ sMIR^Aح[!.Ÿ:B[ d׫<1~YV^[zY}&翦eѪ"/E2 W(X("VFw6?_ *菙\oY)NB(t ]E^VGZ>p_ ?_Ar?4bǜx>E^X(v t_%4!"M,ҁU#ʬj&&p& x'b X!*n~K@Vo=vKGߝY@n]ϒwy͡f.[᛭Ө؞ʒ2y<*#n͖QǪ/Y=|T!}47˴Bs3?f$E)6ex'XXAQ}=5!Dz6#ƑUVKX]1f_#lkGŨ;Qm"mߍm \MbiL뵮ʬzOz ,.Q}ûLV:E^Q,~6_HJ&xW[ kmVQP!̗h/]8}H[+T䫉dT;@+߃>LI$ČW3z/Ti'" ҃Z '5wղn9w[X̶+6(dFb)3eLY"'Cᔹ"mW Ħ$0q"ZApQ︁7%(s۵_+ʫX4J `;); jbj//Rn PF4|rT>:t3顼ꝵ8{ymeȜL4UcJ*GU!vcD6kIcJżyƜ?~1,JhJ}ܡڑEq304X-="IR1Li{όlCUԿj*zSVwN$'88IlN3o9׾4hǹ(%dJQ5vK+$#pmHEDF٢DtG0H֌x3!,Uf d' eM~8j9V:E/]jgnjHw.u{.kE_%!Q:C\џܑWwrPj-3Kl?  Hf jbl~pnYSs33UXfwgX^GoxQ:gi+hmדL89 $ʤ^FiDF8@.W̢HE?,'k* Bz,moB‚9'!,Hv|fL[nyC=VGD2ۍ2#) }3ݯS;ETQ;YH(JYk@ YQ/ff1藹/_`-/n~W D6-D)@)!Ѳkj b4\;ѕu@o*F7UubHK+Su<-v*T̚!g;T'ɫ4ɅlԮ\h LB,a{־,"ase#Bi6Ɋ("}hGqR 7; 6.R KK6 _9O7|<8D4S&[$,Ż8]E#ǐj*Y[ۦZVbݩcsΈz^sqPUm$VSS)bT#8Vs+ .sh;|1ge~Vg4"\sr/֓(6TV\<\Yׂ t-N>mõ/E㖍~Z1t*z[]"v-n_<~)1V̢0oܜݨ&(T)h'}Sy̻rYMfYwUq#R6q%eV pzkoҮr^-:>dʎ)#GRjr=\y (*vB(#KڑoA |":QTޗ"e="T:`y%Zr6,I:<)ʫ[B`{lKZY: gs$>BAh1T/QKw3]ք_^{}C8E/t,I!WQ)L@"B#E:K"iX:qrZ0A"D,$NkSS'·eb(y/ƶ>r3+AN E,;A8(1- _Ī{Vا$Rs{^ũGc @ͷ͙qT "7PB%'bysVlWZ.fYs"#m<%7Ҽ=1 !i0b@8O|8Q{ٙiHMo"^3 ٧ |>ty6'T. iGQcP8Zv*9C;HpIdD-| w2Hy΀$U3 ta_A1[++3ifffozYl:Cp̒A I?c4<KQDt[ _\C)I CFF"AqQ>@t1UţFp (\D$"-1D|AZ8d'ep~Hj>Q:UN>O,KTaaEDLXc$(1\^˺7(#9+ViAMd$N堒%TLX17"S5) 0_UyFU}JW. :c&*&@ ,_2BmvNxQz v*))YcYJ>G,CKAe\! e,2x|">Bˆ KIL'XPpH AdoP NIL`"$K QrШ 峦ҡ( r4T 8B*ˀ̕r$UȚL$I N?虓G2(^>&Ȋ%b=ȄŬ6۴JL R+hdnhͷN 2sS4=lO+@ׯ_D^6j4,ꠗ|ڇuZaOmx,X6ᣢ Yg$fMkn'!IL;zZQ2qhUHWA$EϠH2ExMT6זX o=]*FWQ\J `qwMP:Qda[mZ~MtL_?يׂ4#Qݽ~p*tEp2gK.t)3bJ"Ff+ẓ0aed=Hd=Z{}W:=%m]kH4#ZA#"؃ʔS J@_{AOjA1%3)dUUFN[!~s,foOFDE ՓCh֖zˀd߅5%\ƙ*})Zu`ǓUEC0]mww-`풻n+Ft@XF'jk[m%Dn⋅ r?[~6n ˔ޅ&CEl$DQϪ7yly]#3\›p[ׯ_5L"Q!abҥLXjkfyY-jǡo6HR/]~_v]ulĶy(Z+j 8cOr3Ryuzl+0|{YYI1)|Ƀ6}|) ɜ\mu[yi(-)=) F[ 0-ݫ.I\ I NZMiU嗕JQ=m 'J}0ʍB8&RQDnPu\23yd2Q"ѣ>*jNl.$\aHJX$3}zس\@%s\_drŅGP+BWvɻ=o ډ:CdWW,+U 5zB*GDrg?΁np5wέ˼T T%noYZOsM82;m Hsn88С4\F޴8IAncy].eqBFp2z#L,:&Eސd2wZ90B |8# (Pz|\3@I+,m:Ke/B,`̹LY`u-H5ѪKy=Dvr$G3̎1Jw)Ne(|I=)[%;[p@c\Ktmd6Y~cu9UpD4#~<޶=z?v4`+OALqFe9qS^CǏ"SvovP_Yy`*!{ŽcDq4߰`] EL4Taތwg lUbЩJ}gƌ-~iV~ӆVm UCߩQ]M;?r  p Wɏ''(8+b!F[G#Ո#"ʨ ⺯i7:k`|\)dGhFpe!d ʖḒKIKTGzX K~vIU(jn2+0('1C${RQt"=)DTv &f F-q̴&,?ʡN!oHedYN?C9ݝ*n{(V-+r:O3{A[| 3'}yKH){HzXjzW޳դH k<ϡ DF<$2sxeJRqFy-yZt_$-1IW}+bVD/[:ɠr˰1TS $jaQ f.8-( /ngA;a<Ӛ֐^D؋Ҳ}Q$ar' r<|:^ W4^;%ڡ"YlNU5wJ"t&Ud`hڬQ[OY &#@BC(YU=`E\[&*s1x~:ox7 8O}w2ʽ\1Ϸ{є|:cVZW&Q zOLcڥMCؚQ wH8:^I',Eҿ`L[lc'px,3 I\嬻q K7'j?4yu ˷6:QU[UMv\Mh=•YԶP;xcu  s\K̬ŏ0bLj޻@'.knbݧ3܆K%7G0m.ޢś>aP|1Pwgd1!f-}UWy)%-f_aexɾD!9!%0cN;>2Wc"Lq( aoQNJy~yNfaSL'0 C`n:N 'I'cA$y+D–9Oy<LnPIQFqibQ1(2ͳᑢDl<z'Nz#LI`4"R> <}Nǯ'hN@p7K2y8`aé̬xN`<6H-=f39l&DM*i #><_8f+S#YG5 ơՓJTS&^5ǡD$zwQʒ#￾<$s?_)"$<>V]@LQҺQxcU?!Sׯ?*Oy@"ݙ*ﰙ*98O?6WU"&G:"~}笂@{3s w+Nx!Mx>fB"~_!*!3#,DphƤ(F7?d3"~?yFUTWBTwOH"-CD,%bVJB fUg8@BaTBh+It \eZr0vk_a*ؓL(%%wdgΌ @z-\n!fN笫f ( 6j ˋm]fu# &s8ʫ "ƅ*٬K#"٪(343%q*,q"sLas_~^/%b)/3T DsB}H갭'eqd#k#Vx??Ps?"BL>dtr<UhV,BV*Ji}bVu:ZIfsǂZkͪb`(ܲ\QEhqTBq$dM WK|5lGM0|K~#Sw_2;E!YƍDl]6K?Ʊ6yB$/?d/:t~N1W322Ё*Q5䂻10QO XHh5UZ y;Kͳy4Hlfmbtj/ ?i/a񌯯UJڊcgr`*[d%9)__`dTygxg_\PABu\Wx`+"j}F'>/`͌:lhdUfG&&*J*^vM g]-nq%Tज़mdժ$ ZnJ ff> *0 (ebR̫e9̊/jaU- uߴF:VM{?n51#lq,ޚA%dfۨV-#%l-ulxSr(I@ P&&2-7V7`VW-`ep̘$Y>o3OM'ڻ fp,Q}<ݭGJ!LD=EU@T八ďМjf~8X/q-տoU"w`DQ#o--*{K>~ߘ9z>eFeYxImf&VW̖;9Ś ~pO諞S'GЕR"(脁*?B&DT.8_j-9IYڂB7wnn&]2L0@Bz]k Chg"X[y"1p;U:8gpʮ!$Nз@FcBdY׶,zSrUeߩUmnz($=.˞ޤ-Tݬ^t`UN^W'"pX+8yod߯ߢh($Ek+ pPOJrp:% Qt D o]MlN[,k rMCH^RdR*ln-9݇j.~;"RD]En M̀0`#I7RI=[fv>ђ4'f8"Ⱥ%qQUt",%WPUh"ѡ~Vcw|$y'ߥ )o6CIT:}$>u:!43`NAVPq;zWoӁ;n wnnX7Fw"S1UtH2 DAŭvq"9/?SM6ψIn+`ѬMkQ~&e&i~n`ѶK@ݵH%JANNҲĈюOM[FL TNA)y+\%z?L[ֽϿXEI ^Q'\{Mp $6WQWRodӥR" 1d]g#"##[vĎ gH˺Bd|l*"dHRTy""sv]~~Ϯ2yzPBzc =w}fGPaRS(vA4@ȐClB秛J;=":i*Bu&MqU⭴k\kXHϟ;ɜY$YEq{bY>M %\U+,B|HȾY+:_/,WC2=K9J@HpBB:`LbfVyuQQ}vmWÆ@Ȇڼ}6$bGI.$ JY|1ZjPw^b9E(wV~j˴)ҫ~ g.3f* )ަafu<hYhӗ[_P)ہ7Œɂ2V1z&3l֫X \dot7te[HDqyldžTP <u9Ks1Ld2%)&+J8ӓ DWPV!E$I;%vSn U  Oy+Z'L/V`h8:pi-ʦi8dqv*K҃c 5KQQfJ$&&fɎJs0uAӉ 1_5(V s*'D% S$£o5t'TؗHPR^ZzpUNz˂ch-25.k ϹIse]ܖe33uqpwo6Պ~Y@{\$aRjHyd5]mWl" R[l%DQ8.bУ զis^U'ql %_։.DlVvCgcgCE& ެ!VBY fUI.J!LDlP†v>hYuD^a&=*- ur7)"((9CDYeQ|\cRJvfnw҄s*cčUo=!L*]?י% e}3+>a9/q"rVVU7ELupaLnsg~P.T![mǎ¬+>ưCvo'Bˈ+pUz9ʬE{׳* nEbzQYrH #)[RօFɄ"f t@I@ҳ 9ܯeѓёnEAzP rj[nc.Nڌ]' ;}b66Gz'O76Hm-beڻQ3_(YX3C'UYww#f7EfF\ny1gCo[^߼LsW:2(X$=QXfI*!3cN/KѰ!.7Gyfcq&_uqVcdPxist w yւvX!(Y }0ۜ/c~J8,c"L }|Xh/vOVzʶ𕪍;9jIUZsa;Y]`uRf2sa״k@ TIW<Dž 9&rueZqW!u#m y<%6:R 䕑:p 3Ei&]QDiK$t`g1pѽLqhQwTV,J[PbzQeGUǣsbwb7f97 Vb֊kG׼O/2]ЙN4rxvE.pUW1tK,w&q=hi${Ӷ8Iz<1 ,ʢ>UjDd:2*'|JoG2Xo`$xc9<_NL<(%!IȬ#;sǴLG=j` 3ɜY@o~lrDxsDB,)\ 2wKʶ+%$+qSGd[3S!*DB7Fat@>$!ebJ dd)+ߠ})ݔs3Hl^$`1X$K0%6&TCB@ɁØ>O,DT V&>1 {9Hk'`2#HZ'dNޭ s}x?ǿMMaZG|y.,M_֌NDG0H<_7k뫷cZ2|}:b4^},3cqt>~2+(!Ql֮ש V k|>#B`OTU*a\N&2d֚_W'3,kq_ Zy~}Zkm>__>X[˴E\T")S>ԮˎC5!ebG;duRQ>))SEiyf6{;58̧vln|ݝ`2dR1fA6BCm ۶C`7W)>>>ݟ'?`PNYbPk Y8#=LubSIm iߴz`'0n7[kJJ76$G`a*r!oM RX꽋SA$2,ReA)hb jSasw_=CA`2jr&,¢=^fIT AuᏐ6r[lqL L*+Shho:DJ7VgٮmʨXRr0Ff上m4f[z󩞂BI#2<]XK}9SeKc ,F i#3H1q)\m-'4. sfM>",@;'H201 S"VJԚ <#|xhf=io|΂8bf Hy(tC[RqWz^# τ6iUn92tpG#ngz55/ y2gk}*CG30v_g1o :Erւows?w{H(vD]Z_o{n۞ krM72&,:?}']kTM!mɇ+&8Zw'ɢ1 "ƕ5C6xC @WTz\$z |䑣F?q}W9搡tTZ&IuPAHLF"]ԲH>Sƫ͵TKYq\ (m Nw7"(y=ldm.Pxߪ+:=*.,PSIlQsOzdv[+7|.zP6{Xdk M"F :ž%n"'"g:?Q{,4 ^Sc?*׋Jc&o1awhXk *NSoyĈ!HFX\uP-YP;ab;*CU3ֺ5{^}?*_%".Rq Z}xOr;+>"#)z1T|fPZu#⭔V( ?ɩڨ5$͌+~v1t"pz*jB#jWTAߊ'$j2fR3]j_#\n,jp+x?_d61~ SÊ<:X࠵,r{̔zYѕ|s&?R9ϓϟ??爠=$SgKoyZkc5#T73K~ަg5#B'g3χyjщ&*owbzX1 xD6"H\P8 P`DZg 5 $TեŮ^,[|7* l:=c8 ()\t&slJwq@) (Lr~4 (:ѥ}.EJ`UILڛ' QJaO3 Q1ZUVOkf|Ce:c)3#sc*3}oHc\]Hzp1Vxe_fvf6q,p0Lqd8³X`&g!"(U84val&Sle|4b7[d Qb|j?ԞUM @L ʕĀɐb,h[|>t65JX51UXR΂"oYK^y-%ڿr0%ML?x<H_)Cb ǣ7-0k<߳5Xf9 cVti d\L5kK{[f2,N)~2ScfIFHAn-B]5e1("f}W0&5_3Se o1K>z5>_pQuG=*B@xiu= mQUq'$li ݇i9lrNSLM(-(G6;82/s'zt7(Q0 K)=myS|5\-d|>$};dl<@ب "=|P` #rY||UlspsrPE vࣖ5mɐjP̈́gz⸆d4ծVKtSw:--}cN.oI 2"E5}z/Yu15gaٚ]^='sb,j3Cݗ(SCh!\qZt+(iXi9c 5&=^뺾|9xfdKdlES 7e&֤e3Q'%yWˠ)H3LjRH➡s" 1n*4PƝ:{qpLmr^{,@=E[Ii"xˣ)?_hۿUi ؑjڒDY.y5 L[o}\g&p]ôe&Uc\ePcCy#t=Da穪:ƸqgD1XQ.k |vLM6M<۸.Ihk>u|~|zHޚ5 o__}<օ-y܊}q4cZ O GyDK`}f34TnP3%k$DXc1$=328  9R丮 WAc*VUJo`לڨ"2P 94p[S3D5&LE*UAsKLjWQ8C@$}`rImrNhyl" Dg bIޚ)iI9 u^/o *73)P9XF eTD%L1"" h2.Fx= bXS11824\Gt.3R)s2B:HjH 6;>Z$hj->>~wT`vxdfo?zֻ̀>LpxD늈z d33N4'j7շ(G?~4vHV9~>?x~^zf^HD ڟ꼯/p]TPX~|?>s 3%y+kt[_v4mR/QR&ښ_CD{o0Un8ޛ <=2ųz1zoRRMn\[ "ʵߕ$O:lL&jST7vٳQQmO&s6Dbk3 y\?::kD'(?8Z,]s]jVYk1/Z?Q7ffyA4*^W-H)1lCT #C__N+ܣ/նASSĿ޳BoMIz\.Ƽȳb,Lk/a(=sL|ʈ4zo~f^|qfqĊ渇(Qb=VNWJqjd7bN7Jg#?ah+AQ"!ٻz0!qZfQ= 2@^=eY?2FpT:v#VɝNU]A .Fp͝U.z$)rY\xcٰL2xY3JvR̘hC8{Mh-D/WJq%Tf Y(5I3T}(O!{Hr!>?mdM28TJ\ßT7Szd:jKQơy]>bR  aĶ[1U9Mde,^l"eIݚSZD.ߚ$%_b)Jn<x9xt/ihE'%,G״(`-jX©#cLɳ`]MV(:. g*B#QƫJ͝;[+n]d;HOpFFQTvt$-a><^v8h%ĽBlX6-wBj30f9J``> 6#Vb.Ɋd U05_ s* LʙwNJ|uyM%Y>3 QWabR}W/r"+A9qi!^IچcmF/,;oº$@6#PuՠEXW9tNg0K跺!q$x鶪Ffw*+b4L~޵b̛T,hMYU_RGMޕٿuuf%{^73[r*Y {i8 ]!h1z¾*ܷn"(k0c1!K%hj3)&ҦQ39GZ)wȦk /^ m*]P #^"*- S<i16tn \`sq-_|׽=L"3{)f-%dZBXZOm`%7i["C+Ƚl;SUt:DzUz I08T<|qp+z>1P+!7zp1=H4.53x<*Ms@hQBdv+=jj#e?iII3ߕ_D{<4nj9VdS.#Kܰ/0(ze*tmnaUoQv2y]2w5DdR`չ3 hj;kaq/Dq]'hREJl\jS:kȋha}*?urˆTTZZp#i+E~T$+e}KWDguc\Y_WwW=)e7Wg5%/7xB {4Q,|BFTTjnDcBp|kAËQz[[TY<%)[ 0y?\׸Fi3(K!漯1]qub FnA+3Ƹ0+8ޜrlJVM-m'B&0JZ]O\bq@EsQn;mhR,qO}"K92!YQQMlp=sT9e/LRi6')E}XN5KUE,T=թ\f$VgIqZc@f|(DP[iZQfTrd8;"Fm EAR1$;^:*:g51vḖ$Nحz "C0!!!nhrr܋3*4s~4e5Ŷ7q;$nlt2 gZ{aW|{ ͲH$L]/ގ2|C+Y`0mE"jPoYT*#T%Dʅ{$š4ʠD01 D~%`2PON@KTU(i*W阈ceE\5].kAY ٻU)7AqB1P>@\WQ"/,efjج5-̈́U5p3͜HzK" dm8l }[337,EHZeCZ+}Dl?oU%xVkuui]o;z u"%Gٚh!8\9"p)2Wk5"q̆I Ie{-9 XbGV`JiAOV/~u+]K-"G^Mb^uxF<[=B%-[YGC@u4Mx)SM2=FD(/ (*b%dFcZ+d$|F[)nʛGxkm@hK@YҊX&%r(HznI&p @4uoٖΪG e,CQL(r]: 56?ҷm! =6{I5^>ciɍ#x Gp`FEձal\hu=;+fxz:Zw>Zft"SfqE9*~pe_d/L :ꙸ:3\S埇(-+Cj`Lyu۲̄64Hi?zM ٪>\3eCKC{^*ujk-9Fwo$7'K| *EEUVAwVv u3dCBY6V pApȄq DF[+wgd:q0~̖0CƁjl]H-ɐ[ü`oC̬`fL,f.5U[eeg2>Vd_DqL@&9ȍ$cų[)_u [ ,$RiS9&NMĊ>"\o0%YA [尨4¬t(jD9Ϝ*R+&#VX'fǘ(mZ%kp`t&jYs[-w8$a3gR0k >@# 9F}9Nq{no|˕UsnluEjV'Iרdz]_Ǐ_7PMBMv2^NE)m6X`XoZ;/zfïx2`ZN e#hmؙ٬5ɨl$haj$zz]G6t*F:~JG^k\$ '8>?G pFCUfs\뀠?4< wZ+JSKj3Bh#jۻ3EEBޮ+v֏ً2Q! S1XKPdD𡒢kL1k2T*  DmѺ4):Ode #FhSLyZG]~I* ڎǸ :|(y}T,ZWS2<zl~d1 A =|YLjzGևz}>$ǣ_DZMW+6?Z>32nGk;?lS"9"uS&CDKG:)|)36"󕙏えFgo?w LhM 5 $LIbk\:1SܴO7 Ѣʘ&Pȑa2Rl{AY=a&ck'jB.BBMLSJ>[3қuinR MZ ] &1!v+E5Lںd)g <ҩi^JỲ . c }i6Z1 g*= Ե /屷!~izBW$<`lu@L U)͖MGmb[99/tK(7hޞJDdBpzfЈ!,Oɲ6rƂG+90e 4vz$9K}|Et Q񨰿Bjt!˨ vCJuY9ИCϙH$󙤿TS"p'/>׸j̒ᬈv6IGfϯZ4FD(mV|˚"ξAK!c:?㰀5 ~o싖zZG?>pVk kMib͚A$ EitgLT4k?e}:mYo X& YVLjMIb>T "FhH{ aq`-6uyw"O鞔`ԊDt}ZTfm)whip'ү?/jD8>5b e4j X1Sc6j/BԤ2c sCX%"]vxW=EBeM_y\W,l;">d6ǧe MٚDQ+~D?|E3cw>d IcߢiiML[i?t٢hiboլ-KzZ>"iԔ5Hޚ)5G me]T\%Yt9̺;Aw;ccMxTȲŧ>!c.p]qu&dx[ݬ7n}Nj1v c\rX\wF2{9o7}w&6{48<}duQơh~9UN;&‰m:u߬erofͭ"cf]ABK+f3ED*O>Y}gLM\olUЦ<pw#Hrli$> ?ZqNo|=ZJwD"l} oSeH2)ad8R*4،Ʋp˟?0{r@--EGp]믿eR")U=V8}|]'21M^BW?_ 6_UjG 6Z$"f q J[e9<).J}F5J+TT-!ҬH_6(n{*|%=[0i޸Mw`!_ à{{~V J^)HEy#Α!ؐTM{o:gE!Hr,cBO%įQ Fͻ`[G*rK8r}˲TKo "o(U˙ 3]Ai)wR۷yj5nj'=S%i!TUGD^/Ti֠^`pŬOæ"ZF-ýD{ݽrYQ*yS!fzۅ88oDi*1-GqrG +R"5cE|;%Dxi(|W'S>VrԷ&][۪{%95{͚]SE(79pKg$#r%b\\o9C4V@J SsY!yW^ͥW%q3>8fUߺ]p{ 6 ^\ZLU!c~9Tw"T d^j^H0A=&w*f 6߂+hdٹpt*{?o٨+eS^y~LH k9ZkpRQߠLiEe?5H,\K謁ns@L)$tědZ9WBQSԹ^NHY%HȄ ,iI.f-c"p]`ύJii1#)b/Ϊ"̂<Xͬ\#uF{jT D* !* 㕻ViDWjNj[뀃 kjRJ&zֲUKlszpMV.:.͒Huà*O6 b/Ir(3ւGUho؞4iχny,XSQ+XG<-47cs"l6M*Z܁T@əH 9`d&KZ8YuҪݟBM [ԫo:)F v0k*LcfӜCn`uDV\AAq2{x_m AQj.P^;〿]3FY3>qig{KIy&e. $,N^2|HyL UDWs)IH)qkh9K1[D<8iL^ X̒EZ"=.Hn[BF̌Ϲl wTʶ9(C{3N JWeYUL4Ǩ1"1r-|ipJ=wY{x%JOZy/9|?Y3U0EsC}3s"RazV3IX`u`9_:1R P=UX7Ro+9&,.yn$u|^OH1[k 1㶌*ūd:坔X"dI9Vʾ4gϋ 2}EDeb[Q["D`j͝` M !@.ZYDcїYa"upB1GoG^g<`oO-~}/+&VL6ze7Úwlu(V x#U5\aPń/翬u2#ƀ]k@B5xfCMnؘn1}jZt|V6ߑYR8Wx hb9X{|G jK^'bZCTY;HXʅM2:#Szn~,G z Y([XN|:CԔLݬBE= Қ@ 92 BrBMT2hC,G @d" yx!D!+1v"#YBhVZ@֑뫩fxv<%hHi~WqORb7EfspE(Sal?3kU"? Us?2]Z^C%a_<M*CUˉ ܬi@"c9y~SUKe.jNQC{J S`#TB4!@iSx >77҆\%< AyڪtqDȄaE5ګ"]]NR#lAﰭi i-HP?Ik2Rpm*$FXkQ@5iŲ4U҂5ΐ)[4kfFnΙ6ʭ"h((z57B4q<6tQ1n'9i6G mP|Jg>f Ӊّ 3 c\xϧVt@ +rTeQKX<7ĉ-1BpjtoBf9ݦl޷oKd mjl6Ͻ3/v]\-tK0/W+~ssDkm'K,[FB|A@(kXb?ܬi1E*hUywH_T{kgnO\(t8{! _0 FۀChқ*UWDA/$ u q(248Wkftr1]'ܓB虚R ,&^rǭTS!dDLTpE^3 R"Et XxF :7 Qhf`r%*ܣ /굧 mfp62[j8jQ*h鞒 ѕs' d8be#1LR17)R>1 5akLPv"B9x5IW3fW۱vZ@G1BPnUn(L9#Y- lփ^W`cdIr$=(`yzvF(\o;u2-HIUw7fc t8yɁ⭏zo=$7!は CvDs}~t)?Ɨ@}qjȖHm_Ig,|NZ75[qKX O/A"3Ffz4$^W:I:°d7$udfqߠ.B(}{ʯNpTNP|{!#¼Wɾ́RHC YP {,QbK`ϩgKܜN8@xyD[?m̷5iHJ\6Cb0oVMS"Q:1}K8Uob/XQ6:o<Žq-zX ntŠ$+HUH':za ja~ƴq<$A"w(o*[VX.@5W#-inWia݉ nY669zonM\cDH*sq}y%6L, xMTZɗԨ: X79Zy'" hB `)pިY\ȹ?jg# YWMâk<0 SD}|]+GF >eX+Tn^6_?LNYӉ}w CVa^Rq3ds_K8oqcdz:<GK)ўmuMPps]BLUhi'-0f[fQd6`3!eNY VcbyMUK{{UѐcV u>xJuh,64(ꍽ2PM:"ʈQ7{ncko0W7TP2ޜҴyklĈderQrq5??h_ 쳁cM(z{׍lSm~aɔJZ%Wbƚ(F WJO] Bm\0@bw2{Vf[ٳixO}tZr/_,c1Bd1&+7`xo~˥h_vC-a. coJӋ\955WIeXqFm6Mc#Ed˕,1^{f!8ёpî#B9rKkW.juTL?a?0]ι!J\TD' iwL\3?({V 1Կ[ݮݵǨOɥw 2-%6񉱈@)-~P絠/oB5%XpĪ%qJ G0G,Әf 3ZWJ )V[WQrv g:`: _3(cAqV?ZAUWK=B>QzDHYx\#8F)CeVPgv ξQfK%m4S,Isg;K}Z2b=#Gj)an86܃{v}rueJ'b Xy^J}|A`*I,~r/*+Vky9r$5"ԉy%sM}{VD4]yzp}\=jeUxL,""r&7F;^iyחp2mvgU;PD9g{;Zb@Q:v] aY;fMAڥtA5[?? Rʛwݧ2Gqdޜ3L1k0䷄ O9 Ħ^1Ktf,l']VIކו#F4q22ƀ[S>Ff+̾]y;/|MD+$.oRFyjYye".Oʾ2S];z'apDŽL|TDth* 3Jv88=T6Y">Rvٚ3 -RMsazƈ::"*(#FBD=ňy]$> u&(6uJ{5[X$"V4D7yHDBf34U\Wìv)~m`"ؼ6o|_(Aj7>fѤǯ_aW)aL!%S=`GS,0gx68Fme:Wr\AP){i0 i`&CcT1q}GG6)WkRZ@[fJZNcYĜLc/TYTi.nRbm[(=jGT D5o 7)'P&~Yў,%%Qe4Gef8Hs2MA14hDsYwۑհ^ԍ.Xвn^G4ڎU+{He7xFYnQh8=yL8̧ψ`p>2y}|\cG5FH2rrjZ!ͷN99J uˏS,v_W Ǹ./+;5:/5g@gL&[DfGYʁ [,'K9'V1g HfN5_3'@xN'ͬ=@s*lbtE3WOP9&ٴUKfʢ'랂T7n*BS&QUbSvKmurfOc@㡲::ͫ|#|tdkXҪ>Fϕ“h[BEinninzvxxv#tk|8Q:Z8llZ*HO<:\hN'joi7 FlVν+nCd$LG}p/Tg3-Gh5Z},[6w=q$twӃ+"c^؂e 1˔وI@8y(t}pG "+h x.UXA4Kc?k ^  {;ZłG){Jh#t}:g,/p9n[ ч&hykl~Ρf!:z5UMWܣ.g{#wn?6Ţ¹LWtXiLͲ}>S5Y ;H=i̜:Mbʛ0uT+ͻ9ˇ&j$~_9#*j\m };kIml/ep^?$$kpo.ӡUܳ =\ȃ-f)yE[$5S$^+, Ƕ;oHv嚣-/d59U_5g5zŎԕ*bɼ7*}%׮2pɋ7e{?oP_9ױ3׶%b+lXA[KM}"[McHY"l̈/IGssG篻 O!\(>鍸@Aʁ7 Tp% &A:R6v=t #LQZS?>/Xβ93s"]y|e\T^@ׯw e{l|svz`G:Df"ET ; Sq3r b]}bF,N#sj#[ Yq_YyÃuÜpcVendY1C;u6F*uq:%g>XenS׳x\ Xg3ĩ^3_BX.wzhC*)lXUc = }9;rV;o 6{mK‚!= 4:V3q4c*h2TrcΈ-]h{5P rV ,}VKEF84WWYe\vJcGY?^fjKJ׿)߀psŷ/ĥm|\*sk[UuGH+[9G5)#RHSgkP[ѲvU)^x37BWusOH,Kܓݭ 5C0" Ð*cYDh{' ~$("bԎ:v?擫lguԊP.E2)c\um|t,:zsֻkEf4֬}!g cNwsvXolBz(+ڒܮ8;%P7FXs甯6Џh`q]G8V𐿾Ue]w :aSw܅L3P7ltյݱ3)ݲeqܝ&f{|v+!L:R5V0u7Yt3gn_1J>4˔ <"7n6Y10˜RQycVU1*1:jɶ fسMzs;ݥѳk#׏âL{ e쿏0 3& ͥ_ \o3bYU5Krut^ʏr"ПU(*?1HkVU9o,6϶+}v7O72d w{ZXBq;g0:IQG8'O(l+-==PdO{qZObݷZ^԰dσD7끇Yݽ(q_-!Kvw{]u֢6!QȐq  #فI- 㕌oa#N2u*14^ \3ψL9W;⩵j{}&|S]*(?&XI%w`". \%[ DDwpOjm4E177BG&)%۶ M?@8B=Xe]>Dt< (}cg5oάFYOE:oQ3:+"*33m n?1%'Vb `OU0\ &Rcc{x 5Y_$!Z[j@k:kGf0O/d6BiPm,Q.S΃L;7(͵| O^HZ^yPȜ1^òBQpLa|e nu>)x-ꪪb4"Њ`9^U=zX?N?W͈pX0HsjsлO6F#g8#j.`֞=9=:HvfnGlfs,s ҷ^ƚjűԀR1OqьIgr~Wu`vYiaMEU}c@r W.Rf?q:9p[Ag/ڧyI8p]ޏZ81%XPDGI_`#zT O,kV- 7Zɂ夻y&قMw+UnG-jU 5dwʵ/~UO@^5w 3V.d&OW,L ;4 JƈtY@Z/%v$W"Vԣ{]A>y ҹֱJ=G?/ARFog)_? GA2FR ?{d.y3sa 2ؒ$7-W _^A&y?\OU㺤&6g^Dx1"Zv霙Fᵷb{ qjIҎEZ>Ⲝ)P#0XƲyuByG6~2I=햨L|co~} GXq/`_Z֣SN|X(37(+1r6<*32+%ʬW$(Zb%Ǡ*4˻=AaV\* AۉP-S1l-_hd_1TwK(52ifkbЋW3+42r__e]޼{[鹬TzRY:5jDa!E1s/tf-a;[W=X)QVY5AJj_p,"lTI UYX\ujWD=K1۬ň~^KUrZf47'TI! V8N9;M7%L1RFW:!l'unߔ;$䖔E`M}go?2kWnTӕ.S)4^;.]~2VyٵVҫusm)0n̵`L{\c٧fM\_deN|y [1*֊ù:X< "|AZjP:_xϚV *Jrsi;+Xn].6.ܠaYrsi~BpfF<,iV:]Gfv?Ye!ozP]18XIʂ,'Qմ94`gbWo¶#W7 aM޴ :{Z{Ϣjxc5^jerURu/4?;kn.ʗlx kf-Q+=Kb~^)3-L= *~Kq9c߿55d|:Qч.}7l\WΙs~ʚ0QmGopTFh~8;~A:=1Κ3Bx<2}_EªwV0*42/3!Ֆ;|+>|fwojbʾб (+ l4bUƹh6>2G VO̺1K^q#*nYlܑX9Vݓ̼[m|XJ]rUNX*z.@3QXIr}6P1s?Y\cJ u~*8&S?+# Gu7!Vǘr?V-󮢟ġ=Vn@h9^/ 3~z?_~_>ݱ/!U20d#Q>ag\>)mE)N/:Ȟh?z}*&?,!ꊪdx@6}v{2-IEK.|Һ]u}M{̱|̮2i$!JʺInnXni>vZwvxa1Cv޹^~c0yA[AT}pCegk -zOȪz{=M#Eqh͍ɖEҖ(Qm5cm>Ud,iY ;?{@~F|La[`9잳HaCoOHrU̼ƥxUϑb(6]}el5t*#۪3 wΈ>zz-eR㚽w2bb+t3j~}\/!x m* Qp]`!)+6(aW,mX3q1`i4h $i(CGrޮNz{twݷFu}_Qj9"d33X2 w&9Ea6Jpp0﹛; ]|Ox?1-])3Z>*O{?;- X';Ö3JN^{1X*:ŏVzۄw/ `fsY Por_<ڿж~ϩ3&JV X4$άSxFc[yƾ>Q|nRⱇY|W 5G?get9 Mt%7oZuq~GhH :|n(9/`/1{gd)V&vPe+R硥n9za=Ƃ *Vrǒi~ Yŷ?f$K zR3^\mD:3o1|Z'> If7y;s<gN<`e>s4c9A11R25x#E wԜZr Ivuxl Ex1FE k-ktw`=: /~GےvuT2 j*S%髳45"bIFUY59j˧Q!؞_|gjaV&oRa1ZRX&uZ0A'@<E461Ƭq]1mfL 7qd{O,v&]ꥈثᏊ fG #%-ҬGPgv녉 US1J^K6ZkJ6PdzGv K%zZ9YIw;z:e:@'!v}K/+/wQ3%Ew]0\ 9sY78Y| Cy}}Rg`]/ M`wI1DSa͚Q ]ݱ7 [/X=Unζ5/Y;%F(&ՀL XJѐ-g7a 8(pl\S8 zR挫j®qp%.([œ4v^ma;7z 淗i C"+>RNjаn`[kv 䍘# 憙 U+S8Ҵ#^j]'A-qC6gѥ0`=ɾpW$Ba6Ƙf64^?Z︒pT?PmO9t_Wbx$8)}׸5ƼowxsCէ:$Y*2`򣱯BRp?|?RW*71z}՜35 ts da2`;Vl܄.Y9%hYU[*)=R6o@UqP=jDZ9Tkʈυ~ZDjo)UUlȲ>2؜S0-[Y2}Ƭ,m> 1I kqcM} fjE,.Ygo`v<sWhߏ_~ |um1umVNq@[ѶV4&uc;%Z!ナK1Vl@GxnH|F{hE u}1/Vs嗸d0"zeU3ء`sŶV%Q{xZge9}vbӅB):KV~fVʪ}C VfVV7z)QpȀU&mt"'~_h*Wp+xee YVy_5g"#6Yˮk+[AU-"'*ܕy(÷e| F鶊q ^yH0ÅrImծ]9oB•^+`T>"BfGƺa؆' Y7Yr5wJh'cޕ0|N`aT`3dbV!\Jk#YjTB&K^SpQj£A|$u5 ٓc˦`rI0j9M)\rm6uFpj6LȆBw(5MI~{|f}yXK: L~ >5K$& ji;ᡮ jSd ٣*>Zր[gfZXQC]0-;$_HW}"\_,`~dpCE/e k­wX̧C?>"$iը-W8}{&(Nd_5IZX5 u-hAqQQȴe++UU+b1t[z]}c4zLb@An_ 9yփ;Dօer'(jhϞLN:b\'u}___{7[>4XqIڼ~zuo`f:_7I? |0\jzX*{gLji B,92qIV9&Vmgc( ٸZ'w8k"sJ,Kma='e12sEv\1XEKsw%ӕ[Kc 9>PBT˄^R D15<єz=nH#)4=K>)RM!rln}Zy6ՍTևR&&*}l8zcsk}KŸnPnNQ)w"'5Sn̙׈3~Ҋ̷VÚ8Y0A޹4H7s:m=~hk?D0K?+54Q=uLIƈ~HR:I$G~#"n}956͢8•e$Db*}Da 80#>rM73ЭSf{д>ћ @T[1M165T&h#}%@myL*3c a5ѐ^{WQz]TEջ51ZitHЩt! Q%TqnR眎jk=q9㺯݋9+473I!5;jޞs9}s}xxejʿm6;|$Or4ij{ @xz1j t8p(L.M(D>n>,)_sk@ŵ2ԏ4OOЏOs yR+2RDL5YJk5|<*'Db*exi%rl/0.a's"?r&9dϷHܟaEv$U!cuM,}D-m\[v1vZt te9;r%$m6Vk-7W~r\= PDlwcI.b1a*"!%*Ip0;ϻ/ՏP8OtE`Xygbo]ͮq9-/|U XG-.#lsenElWX+IQ`vQ֢Fmªx}2TՀYgVn`=nmq1:gڹ2+Fsfsk4*< .Hg?;=W9b-Nfq:y\-L;Pa@13rn4&y;˯6s0(Y$ ov%sBZJ#cn <3~XwR*`^ǎTrG03u]cu)J"]Ÿ4֠SLPt76lsl{P7I:g܌"讠  nκS嫴~n9mR maߕ@mY8EYsRKb1kJ)6jJiܮ(@y6[mlT@4,32GWվ['kbG}}K9gKnhYgӞ3Gښe}m>2;jlx*W Y\beM/H6bĮI\च!2`bͭ*jV[Qu;NU=aҫɷ 75bb[n:]=.j;X<O|gDz3Mi2?> }#eHGk{$nFpQ,GPH^bt L$;njgw 08舕\UCGc;̆?`ǁ9F^ePoԐYns݅gfz7.˄rXy7VXԨgfcLĕKݎc!|t炱h9!>w*O9d#;bLaGЀgT؝$}K Z3Qnyqf톰'3QÕf.z-U&}߆5=0IaarشU̥KY$fs:9;fD7ncP?֒3} ,*;GLےbqg/v\=fa9"Fwyh-LV`H "9[kƶhnK~)R&y~m\# OSW2S0̑#,4σfG>ӐLa"v`EWfg5)X|oXk?Nhߣ2`hE5SWV8wu z7#3h}1ȝvcL+/Qei> ҍU:fΰfpT2&()thF׆XKdݽ5e:lgI& Wb Ie*l71[ zꊅ)9 ^O9ucp HK.c#~>/X@lGv';=m=Lr,v@_7 .D|WzŃe'ø# -j]Nɏo4-}ȈqQߪ0Y/'12 >s 5t7a&ωF$yfZ/Gˏ?Q;d{.{Ζϙ4BVn93^#ϙx]> 1E1|L)@ڵܼugkS/tEUX4,c\mN Yӄv-2gƈoTj1hJ1LOe[΍sGէX>q"⊗G=^_-Ƹh̪+Y!bbs Ȗ{BޮF<aB͌WRu2Խl s3;I*ʫXZ#Uz3vz%IHՇC"e/f}* Y="UfQT)\tc3yfkQ@TS )l|"Ih */z Utu]\KFC `0բO q L\^ Ep&҂@ Ffl)ĵ"r-T&_4n xͥQK=͙̩Oi1=Ēc4+U%,L8o+`wb1#tQr)DGp;I0,R%*L\-ß%(U03Fʆ;a1 ,ƙ+i E٘DrXm _ R^`!D侔 HvD,H5?D^SMoD$u.KR~,?D\y/b݆VFDII9C;pVI3 ogv9l!45s^ו뺖h!1Z{s3IͿ'j}:oy蚏QfuCqﯯ9Zׯ_Dp o&N\E> ENzәf2rDh ک*ku]񞵯j\Y5{Ykh!E;I.Z~C?Ɓ-ʩ_+0d-`^/N=HՏ줎}nDĊJ}"Eh߳! zmh>[0*'U'Kݝ5h'Btz>įXBZ+cEr76\DoSt")!f5,߿E?"~jo54'T T)p2jPhᬌH.fcїA8iOMֳqhiP6l:G.( *LRq&U&_!L;`,NY[\=Ê0Io7saV0)J@w\Urpra%&o (:љߡ6Tnm pLX!PU9Q:K'"]E.ldӣDƊFPctd d-_$E UKRZ_1ZLVٻ>k)adrĶ?#Os}FL\=یW<e/#bsNx3TV-Cϛy$mkjt^ anU N2^2b3s!MFgH>2ż"RO93bG)GV%%cf{ϰ̝RC~&ioBJĜyږqdܶP>XD^ "I]&7)2kk12i+O2oR#KE3/ ,dp"f=a^GML'sUws{?`ΆoeA||mU-;Øݱ#SSHvwb ?:)z+:÷T{= pS v!{@-Q&uѮnS?ɐrIP?yAZ\m%)I 4Jl}+Qgvn(mE'9l${ Rf'8&FPͽ6?:t9"\)$C$ʹO{4?+$p0)3x.w2K9kYs\&-C`pz5Jsrs*j<i}&&CC{^yH/?QwjmlgqCr̍|]_a(<"Lyb5tT*W3Ie5tMwz4*Dv>\6"ERYsPJ:~OhZל5j;EHEA%Gi*SUi* HUSNfDYQ*;5xxQ;T27u▉L;T" RiFԻC9;3<+3oXs,ء=?"_p|ff<ޮc^IeHRPC%xD7ߓ8u64Vs%)z v~LRwRt|,Dהݎ,f2vdrZ"bj hШD 𦎔 EG  Ijm I`ܼrBpfe2";ٌX3{VJz#p%PATҢ P*Se4u_yZW9=$wEB#)ފmM",=Z7kzG8AbK.Mj2;*f>'D5J7\6maΖI7b%KH_{%y+A tz\U0!".%}G@d\^ug^'8^dƢ"h*4<@(#`Al +V1r kXow8Ƃ1~^O0_o_+U8+pKñ"1Q7t Vu_,BwHE40ۿf(/`U&0owMĔ/R5UCfdfTq& 1E-D6']ߗ&53uLzpk*jV~/τoKE_FJqk!*׺=HMIm9rZWV6ZN295a7f1)iG*)k輦wN5"ZUUL[Ǘpb]﷪1 NN%.UܢJVEZs`jHʇK&(YYkUUjxĢ!< ^{. "rL;(ƄXjj&=>ZUTN[ ]gc4_g.{F [' 푀%V[hcx,f6U w6vC\V.H*<,3oycΘ™p #ޅ!tN2(ٗ3;iuǢH'P'țT֜QՅxIRrk6Kief„r M1[ vef$"KT}"܃U5拄FׯKe!vM* {pU#Ĕ[/3sHG5nGAmy2]g֦6DlI}Wc^fc>\3Yz]WvsNyfT KH^We)O !gD{*)="&iׄdBWtKՈ<mV> |l.SGl;Ɇ_Ą^0GU7s3TAPZ5s)z('}J&&An6p2(-#Tq凖;*<]2<3kE#œEl:ڈ'L}Myb-q.-oUSzwb~RJ{f Ф-6jZ Bx;r9Cw_15~6`--ҋ?#[\ܧ*'(k]e[a6X&.|RfsRvS "lpf*,1W,$,gA>5Ohm"U5믯XXrqRY͜8R9NOoZw'Wps)p>gd؟Y%a˛ չu6,/ }@#,*tt}uB!HUܹX AkVJA/GmEky>]3G Fb4G0Xg ک|B ekk"J{G"Ě^2.2M0wg0ڼ?e_{D|It_r*ך?­) -,FR)hnpnە;<l˲˖C -߉/فNO:=leďO5Vu&8glAtT쇟3ݭq2i{FZc1(!DȼtxB 'ӆl3K cTv"ӳ!o ;&"YHY I̦xjUv=ڵy&(aed"x)DpFy\y֌Iv=ϖiGN+HRV[y\s}f##G*`1̔#> _"LE.ĚN!bjA#I) ?9~yV?'39p^4JՕ%jyVCu{p^gxڀ)D lB!k8ٹD!, q =!Dr4 .Eε>`qBYȱ™9 ]($F<[hG%0%?H[Ogŏ˫/=HU3# t+8uOnBy?ڀc@x$h/}Rͅa;=U4kίk…+)sE#QD?1 j*}6OAֿ(9yL{A $&U ^?g`kS}|Ign"?c?d׏ιX\9,jJ! 9k1kc)lf{*BW <@%D _B3s⡦88)ou|@!orޱ a!h*8%U(-w$ Ϫj5oyE=BBȜy~2( "[>)*=EPQffXju4ɣ*|XTS q%ѣpUڭ_Fe~'q=6$g)Xs!rZbb<ފ*~zH֬%Uj*$גW+<2-GvodsϋG ꅟ6"Pʹ@"zrHR+r@StyO"!vLF5fAyresJxqD+phy{f[Iً) wTssRGbEĠ.XH)TUj5Zg0LuY1F '=Us̟k 32^UŞ.HX]})|q[X$58Ta-Q{,%ܩQaCb;*&Bm~)12љ(fY`e{_I|缕bQ+I"0ek=閇{͞-|3D_+/x~u:2[Az} sÌ^MT9I[sv od:a謾֐w&(Ýb1+I"6{^"+"CDZ"DD`CH~e>ȅx̀#5K#aZ81}ˡB"{AK#}+f1VE;BAu+h U;,3>RaD:YdĽ,=,s9lXM(w&$ݸ*;X>ؙiEĽ~^#[Mwv&A(qm6r@IV|ffBߠezQu5SrpOI#\Vbdf&L}OELXu3d[<|Z_kn(\2@z'fB@W]%:g Y{XN%aV&6K%~}/\"0H}]%taAm _k(1O/٠K]Zvd/X+\ ;4&W.sLVHpf X(=";[$\=WȎ U`>'rJRIܳД;Rc^nL|1q OP D6TɌAp߬F#ibXM/DL82$1y2< bY,^?eO  bfڌG+Ħ& DE&&| he$=p2@ ƕY=*j 9#e/9uK1" HYKPv}<5),D>v,Ε0BSX2oG^_WR9+?X8ʳCTď~]TNi*5{ttE`(1[rS"MYa*!=#K=C 9LD!A)|T,PmIB̈Ae+"w=h RɅRGjx{8B wUEZLMrV̉{|=gx0$_Y%>CT3Hr%쏥JKD2qؒ)U(ac/x:W5G)xdbMp*5ˣ_β/FœoE:iNaesw*8?,.9sb [̑kTV1VM}^{ V055YT#4$C9#d((Mu<8 aP^ϝcYj"/F LK)URaVw EQBS(Ri1 n<2Oo!7~zć9z Lt OYKZ~-l>D DkMe %VI`²Klv/AO9?O? LCWi]gf\i^JBJ&Ϩ?FDKOA}DU\:wCPCBBd45amv%zJӆĜm{`)l"aYe~O.?n,ƪNJAz? NE(V<@XO4'fnAtIzOVܶS? Sg`YUҤs" f<Px)87xflE_/afND1*듷aǜjsAy|.iKY UkzfEGq1yƵiFa3 P\j>($Zliu`2V _X(!Q hS#dRGyc׹` J w s>k c;#V3n+q6V < ?T?3֦SeXc\ˇ!"# C1ѧN3'\̝FDD+(Vє<[cSǴ4٩3=4}?q`ܞV`AOԭ=jqm `@2U473JE=7""0#Xd32rՉkIP~ʽEf5]SW|E;bg~S ?9ecf>jzxpTU眥ȩopxN<=>(?7Xk#?m8Tuao 5+Yq"WxzΉ&ʹ!(81yYa- g 񼞅upBvhc_ݪj#Qq_L+qԿ`1(A-UP '1"٣wWVIXE@?z`d5JanGFD&ʋEwNB*6n؈Mz?1ǻ ]8{O\;?^0II.w4lfctctE^s{ETJA)-%c[/ASfxP6r_^ D ~w i>`݃`PBr™aͅ˳.Z".RaZ˨$8"Ju`/';iĽ?Yd>CTJp MfEƭ0?uP%wI=eË`es}c 3~Il;Ld8< %޽0(QT( yBFAyq'VG`XieT{|*#Z6•+sA!Ƣ@A5|sa)RWO1컳j:-+|n6q+@i,4/t+BTTtqUbsO{yt]HmE(Is'Ҿo&O['HG0 HCT{1;r;?.g=|uNtܳ{xh ~|\Ql -ux飳 pTߠ i\ED'1$0 -ګ4_KD|-*4ISFƝ)|&dnV锞u㦜(U"R^%k3Z+D%y`f +aFf(ˊN:_c\9׺K8|9d!yjiJ;WO V@_'[5 P`6U݇ERO(4s!:*ܗqD|=OR֜ es"vJZ___;ZRe`Fq]T=L}o{y}}9XdȜ%3^"{!TIR lSf|rb U_~}+oܹ&1݀1^p'0hߪA1d:byɲy@1=z V\C>o5[˙MpP04d23͵r#]H{o5hk)`p!Q{z/c^f &!&3]Ly_`evs^Xp x^曎D)0d-i:[x]_wTq]j5\3\Zƈ`1WFR {qGȃCDs{9I(Z+^Qb  KP ɰ3US\Q_ŝX`"P5sBhA̙LRL&Vf5,4mf8i~X7>nQTj2최LP4a(CKSE\UUCk| 0 @oM-@i:rZ "k]E"[+i-bI(`¸wq ,Ao 0f]5pD̠o1An)"gޜIf"yFXnHFjo#.Vo&5n]_LTzs sjIb`5tIxI#T |&ܽ.9zwGAk1b[ Dl Q,""@*W1tXKF\-gltG2^SF7#;fsrUFZ$KR&D"̉Y~)YLYV`W.Jᨣ $,(DePL=)DrrF5ש9tަYGZ$Jk;LH4{xq}<^EPK/v;$06L:R#o.tKm=G/~Ej;QL-_8̄/P/iX))ʞRbx bfkOld@DrT/ u{2T/Ss^+?1oV~"{]B4at#gYcTJ>W@O1Fg@dm2/RKcVfTikvN_[bZ.kOm;YmV##a'~uZv8>"1끇M> &;Hjr63#b ѻ_MZz{R0s'޷J#Vׯ_ؖo5%gU2fOK𡾖O,I$Iz,"jYսb/XA04Xp7UE=zfj23GUTn dWJkGkt 1p&H y1k2 uLX5Ӣucw}>[%uqǚbcr;;$(FXDLwRIO s&"c績_j>֘>6T(Ͱ\ĵn}Pm 2j cL¾@]9%ff@e/ }7|EnފQ:JҽH< !DzV) 2U,"]7~d2q?ji0,ϋԌobF۴`/r5kJFYMֵRh|jLac<}oP~O$XR\dHYؙ+VKqg5B(Vǂ4dr*z9$/g"QLEy@@F@e rR҅O4H3)S)*Z&lőd ȉGPN& AnGC%R"]e!o=!пj6 c+ʪ. љ!wIuip[gɽQM7J|J{_UN5reϝx>& Aq4"R&~q6@bÅ I2 PH`n 1c@ߕp&2F*'盫|_jY#䱏;qf,tCr]^7(_JH`{\WYIsSDBW? R*Ex~]UR53n;·:=jy'1PUM=vYq_*ǃ<|xSz6Nc̵qK91bbfJ&Hu}^}Ҳ`l(aڶa@WXN[Xr[t@L\m{6:2#=o!O_lziޯgөCؓY^ `t%E,NE2.q^Cm 7{m0S4Y@{汝# !TGjʼ#|͝@ &R_?@GaEQI79KcTڬ2[L =3Ye)Zm|;-Ԭl5wv-4p!ŞrD{ъ)BAu'rY{*g/sa="Ԑ󺮗̥L{ ;47g;"m7lޖK0yuVyl=<H>=g UCr?>bH $E};Bک82GcfWG\MZУ{Rm-f7kd[_YK^qwH[̫_<9bwM&1|u,Zp/ۖ5¿J#HgvTXM DߦQ8ޟHL̐YKLMSH qH_9`5qdZˆ>BU\}r3S* znS]P݂RP|`i],3K~~($fsnҿ\Yɖ*L1i(*KТA̋&(쇙GU@ՔF-wɽub 3o׳݌Rx5^]0:{5bbInL گw+a$Hd^ڥSfM#-Y &6=Il8 Q-Cov0/x:TtS=k[:l?5}>9{55 P}. PR(UYS81qw 2'663jZ"Y8KǻN\znnꋈ\-i9Au]֚u] t1L|e**x՚1$p-3{x%/m)y@G[ #+hZrjh.L8Ux x͚ w=Uy FAe|<c11 $"}!PRh֟ϏG|f8ë(LDhv=0<I1Ly]#?ϸ"Ad׉J$1CfX2 BInGk6}~E6f:jt?"hf eojWD`Ĉ#Y Qb% hSSQk{H#U S5g>[ ǪDR]JQG4D0%iԓ=OS@ .* TIOAkkbr'*Cm3|% KDB2Q[Uj gŃKܵoTMMQZ_C < C| !j\tR-P BBZpEP }` 3hHcs-#)"3 Id5QCHxt>#CKLpZ#k֚)kF@Uc 'dBS 2ܴp> Q+ TR<*oAjJA9JZ_ӟfhFFnzbAlSQ&Hw?_ǏT!<o~LJKV2M=u|`o+@ۡR(k ]|}t=gBX#U73_.f& lLPwf3<^&:ja[xPܣ]60sozDE*1*k+fl.%noѫ5mIyU^d;zפm##g&KER[XNЀ6Iz%U?\{+@:Hld*R+9x@ @,w,j))pݔCЕ)XsAdːq޹gPF}>sDdto[XpˊY QJJ# 0fHe;;^oBn!J >byQ26)R#P;k:j(>0?펏-o8{&bǨٌ%ݗj|Mfp~ˌIY/L,I;5o*%UY5=ڐ*E Rф{/͞ k,3-v eZ#NVQ& w=~ӑP5CĦ\#"kH\ʼnOA܉KQ9 _B1I) >uuS4Req]םtNȈe |ݨnS'5k,@զLSUCJM ë7Z3V*e3rcVcOWzרׁTgfdkZw_׭q"˺Էh!Ӿy,l|y֞8uїJqo7f-Vu59^TJ,}V=|߅hFҜyon9/~u}Od-\"/4 kjP D oRn*[S: Ǿ}1 $GٵU|^lsDU1-w@ \.ťvO X4kKIY~&,9OKFqN>0Z%GNz`Y-/~vx<_"r'%~f-ndfjb͸0y>mx<~}>k/IP8 BA8)Fi%U29TBG!ҿ ۮ\Aȉ-C=)cdʢU%aU-<&ζKŧ3UT's4mkmYCTJ5:n*+b#*]4QTEr*dY~Rq/c 5ϪsկkT~6{Zٸax_Ĭ!r/!O_yJHQ54Gȕq,>`уS{>wtgC{# ./1e'ґ@mwnfAǸPdjDMH+Ct_f۱ښo5 fmEPyAEK&B^WX-*(oƹKY:2v]6Gaΰ1Ԍɦd sH`(l?Q^!/LNmXq\ B*Q h*7̊BiؼGp]F-4_QS""uM4,yl˒}^P)~1gւe BEQ^IjCíթN ̄D*oLntvLs=P "Ǐ=rxAFxvgJEvY"*hyg*`h;VM;)s,~W vEU>v*jb-kh>wAs VNQwYk'\?x<cs_nTIϧEPݎ") Xc+"L-˄!bD<ղ3D#ҰݎDH٦Er>]3#$<ɦ 6wHηҦV#BmqfxZ[#riXMd d$2RZEN]MMzj(6r n;{,~ KẌ{(ȍGf9< jF6q4U?`v5_]:rTL]\A]A4w$jР<]Z1RZdL燑="(2*nSw6l}%uӹG,&?*ڋj݇1^F+j PeJ{=15H"[}^_93̗ wѷޜ%qI0_8T .05dFE]da0Rf>D.EH O*ϳ@0ZT8yϭ 9*bKfD"eU6S3bl~ `$L'+j 2! j8:8dEgPu*i;Ҟu;j&t5N,V\ݝ ׫,:緷=TY3ewTU]ooS=VЪH(Wv-|b#qLlLs$\8BAnqM" Vn_pFs_~˦s5H6  Ӻ5 UUZ^?dfrFZIZӆ|y-;Xk)j8DtjRmc`JGŻI=7U Zϳ*Fq}H7/D΃2 (={[P}J:c&v-C5MFJ,=koS<#33w"}%qw}-)b9#9=sHIJ$Vv;V+׷Kl{Q1f8T,`&a(-xC;+O K8'SP囔L^icN< مw//=-gK\I-sTW;@">;~(' \YHW<_"S(t>YJӳ}Jw+SfeVUbdG"?3 i -y:"n/73֟1FÝ0HB%9g_gH|{?gc`vQDŸ|>ZbIld'$FHS-Sq>??7WI!Iy%Yh~Iӵ,nnA΄gx"Ԛ "FtaPz1CC`rMCz2<ϟ?wj;a&̉,2s]?>VEyF +`|RK}N23#LHd !z)(vFffG{^v{B8K(Vme.5YD4M1чہ#7&QĆtKQDB#?T̓35KNơ }EXi܍#cHM9п.8pe֤RD4x~EXG|j3`Dh3$GѤɔ5Tq>~ϟ?٥:h!*2S+p&2ڷms#-H lUH\~4kѩ&5 BCPbre)._}d+͍x}Нu_\ rfgæ>-ͅ߅TSQ:1}g'kEm+ achH<1ixKZK:̠j:Es;VKM̊9Α |"ST~]f&ݯto^-vnК^[GKxK)G]W`zZJ!%ƙcPSM(:YH+$ n;J7nƽ=v&ZEHePMsvf+2%D,JUߧpՈ$N%5ϙ*qF^[[N kqѲ˚&Zad)۟|S-{9ճYփV]5b Iz?<3Fk`BLvwR^kNM(hc>қX `?Z+WqRo5X|P\WHQ`2m«vSRtQWLL;k(crirL档ۃrxC_Q߭H ,-mRpʹ *7Xʩ}:>!EU(ؕ)n%)HXQ*/4tOxY=!trJš%: y({ ng, _V-v̘ľDLF7z"Sꦊ4j(xpZKkdvdep]ߗN$[3-B&"#;ei%O e) Y :[.`IbV}+ՠ&TVnf;kh$::zAM55*  "1"{bD[1ԞVV{9%!HvଊIq2hDzHڵH!YȷE&`g`މm:=IY&͚…9{Y#ˆѯK~lG*ƾ7mZf&/(}RoGyZ'rDE m yD5|W^ ?XBdnZwV Ä/$l\aOJd3Lj)Qވ&oaoM%Y5"9Wdc}NZėI2\D9ZլĚZt{JRu콳@Rݡ?sj{JqWM HtkM4nS0s%pJK|pSS|qT oV/-{q /!",ËxbFDpAn{@dc8>:V{C+DmmXf&Tn̩uG+Bl J9}J ^-e*ڞ_l]t~L;\E~v/f=1}_7 =^%Lͻ#j7Nh?0\Ww7JKH D%on˘_4Vjyr;׉7\Hx'</U% w#2E=ߢ^3KV|Cb6·\ͮY./Kv&jRdD&r p߱\ guM`=QQechB)0+B QҍfFq*x98{B YD R1ӲF'$G"Im0LwF@L>(e bj8C __~||Gk@ kğ "ukGX蔐E,iZk`:S"~6t=TRl˹Z1V|쾗,:q\9Fc{|wOPe0*P&idYj;O>{7R,:h7Ĝ6.{=־7@W .G@^f_'0BUe6Qrɻ ωO L[Iʔ* M*.n;Wcm*& 3M|M-8Y'UCb:-J[唙.:lތәBTٌ,?W`V{@m;Nj?=F?#kK5fsƭ6CEb2'D9@xHDx=/31r:V(F0nw;a/ dYU<}ʲM@kN!",#HC @P: {h*_ZTQw27]x̰H+FޚJQR=r]ÆpXE"gc`ZВJUwF& c r/"֗1˿UgD kŐ25VI BVc^9NT<ԡVv6 Odj n¨Hbh"mGd@EYjs\w7b@6l[XUrQ,7]Q_74=~[C^\(eR#H__OFf欔ك1͈W8k }M|_X&DP=3"y~=Lٶ}\s"z*ErڐU G~ֵ/hUqH٪˟kw{A 榨*lBPt\4,F\XYzݣss]J)a8z9;c.?Ju-spR/_+YΔٹasBE4 j jlwbq\agȩњGuT˒To-Cܺ9ez*}Y/Tc^7,x/rEٷV1cf_ʧ7f׮1юCػZ:{u[=`9!GS)n~q3jaeeu"5Ksc^"{~%&?sdw f%{ w\ h#Y$Y)nMQ9DAL2%5նBL&Q|d=3iA-pZo@ȱn6WF](.^L ,1|`VCIu-}|i `:of" M! A>֐F{F1*L;'뗪~nR#>KQ4>j4& S۔`*pG!E59i+!@xQ@,^>|$ H)'uǏ?=ZkԼNh(([#'*B9/Q}~=㷏4q)rPkFBr ReL1P14,54ɔjbے1Vz{#lH(B1!b2TǴމdHQ5eLDwFDjL53 DWMhFRcsD% TLsJL鵅{;qhk-hbL;d ޳5 WV>8hW5{RDMEIJZK{fsŎ{8ڗ cD0;"4:c(Mzs&p;`j?1v͚%q??GiOp I,\%7~!C(oyF"gC>z4"ڙ"|]~Z=c U_>ev4fzFyPZ>zDkԣQsXy9ǸDBB~ r yXRx@"-␑ДC-#ҌivPT2^LL%~H30mUDa&H xb9):tYr#޺]tO.?ݢ7 gafmewuMgN.CU]Ş ;X|!` E4|]UGڱ `]E)& H}y5fEL7_-NwڌY<Πe5k}ffEUqlNNNb%;2\0S-y2NhJh׼)5[*S7pwa4r7Ykdspf.֎zBn:Gʏ?~}Z#١JJSo8_b&0/2c.iƔ:'0A2!cʤ8P7Clݑ2zZ3[[VF k8(9.!˄vLҜy%۱{=soeP;w k1/fL "mGW0 #tqx]u]Vy#05)Ex0Vj=yzTOw=b6XyN F>ۖbolY~{6_5mXyw,.Aj#zK%u_9v20~ u&ywpn_tM*y/mM靨`!! i9CVg@zdb$89PE܏jŇi>f yvT[жCb6s͎ʆonMI'TŚes7E6ØOERk-7kߊnoI1_;͡j7"Vs1p 3q1|KB yCx8܋6n cff܊],[ovRv)^E WHqh*֜)\[u]~ka|A!2ţ_ cͰ㒥?1oqKNlt)cc "CR>I`,W_Ϥq5z,T,&lo˛֎5"㞜FQHv3m9긔[B{jѭ Gx!Do#8ǥS$ffשܙ"ئ"fcM8D[g?S{1`{O&Ãb&4`a~]Y1yb *Z_kю!"0f08X_Jr^ϡ0M's z5nNnڢҵ$`y>cx<׀`2T8v*`V6ao f:__qu(JSy}0`{lֹUH"%e8]̀{hȴ(|zW*jã.:1Z4Br#ckٺ"R?BUȸ3<21! FkE\nENCљ^H)@ dTg4Rh%CATLYTh4ѮD5%ݪDY'c?Տ#<OG\THkDsvӯו֛;#CgMX\;9NPV2eKUN{meդZ3hfMQC"Qq,q 1D6mq#pHrzӖfj&jZ#)U/fjkF،HA/DsdTu0(u2b UBS bUtMӀ!~G}xzC%Dn$*$YD c1ȐǻT401R8S%3G!1xG\cP_ሐJ<RhJhOO=G aKSM2F"&zy0"%lHR`z}\r`Vy] g 4rl%:lB]2ӓ vXA9TB 9&HAt0#J1>C FɌE!ԽdK'RQȸܯQr쑒т W`֛3΀b^CM1^ 22gb|>5HjPw"j tf@]`[spHASCM w.5`FRõT $"lrf! pdMR[݂9,bRIxQ&F2xeyjBᤙW5!c8 W^{f58STFx$keڗi_:jYRĸLQȤɪXV{ !Zm9#nRPvx:j^۬!=5ؾjj[TWSuk_i:UF+[Nh䝧ZAózIIp@8]C珠RDHf nx($"u|DF6jF$XbiU0LU~qHA4H"U 9h9h 8R?oFpE* w\$"ڌ {B!PV͚zVrg |h%@ s{s.Jʖ&btji&Dlȝ!vm". ٪Fjf0V+ʒYOaXgMAFadf} ~ T~&v!vʫY<#y^G7U$7וD&gˌI5KuWDIό1q$ 1(hҀD,ֳbA.FS.TMj9e cP~Hʳ_ps}$@87U9,LMQ !rB:(DXBx}1>bGE4U cg55m@R{EPB~]ڴvq]PdOïPqLM 2BkrSXௗL-xzYuϦf#4ëL/=8@b~7U-rJMZQDrG2D-dϘ;%:H y#}#'*@fceBjb+#|L Cýd)T%V'."rJvOx%2#zױ!dTnV̘͜[K ٲ@e`f$-ЧXsȊ"{dR fDϖjk}ƒ)6[omӶ%DabJVyGVnM}5'RVtnme4ݗ~w)pkߴvTk< /v7jpWkA%nLjuhvvPw \yB +joc kXҬU˰zz[<;7|JKx$2jY/gqD ojKĭ ($vX[ }GTD8ڑy&*y[VQj"[Gh3+W < ̕JpYwQM-1sٿ[É=:eNQT# 逤jSHURUS"y]LQdh!?_֞+Taf _nV)3˫R+g22LLJV8|XٜwnnnĔ|sQSc*ˇv e*U7՜ԊyƦ ,[d(  y!!*HI) 45\zc'9 qD $M-Ic2#6tL%ie,gUx*fq]o̤ *p)G^Xh~xB"V-uj: oŊZ5E#~`LjCMUœ}:f[3ma{ݔGfLa{I"~U5)Z!7{{Jx 9ML5]q~ԛf&_c8iM^?O-L,%Adf][r~ on+B})T9@/|hut砐o8/lAF8YԱ]K/u07^Q"$h-im$<b UYE(lI׆jfij"D; jٙ1AL޵;uQlf;|݁= n~ cUՈˬUn;ōVٹ2SLyN 6ww&3jfY1R3j"IyffCG" J>\ ۜ(\yzFJHڛteAA}%U!=0wHRWRM,@lfL[8D|b 4WvqiQ2SR2F+iSE(ǟIx<~7twTLp(wf#`GD)MO" 39ipRqp+3QyJE5]>{WI8v\X8jSJD>w >]ٽ#>=UJTA5>EE5 Ky}pu5L穪1IpRb_Z뽝[ɶ]˶SMp1m(uFf} DÕh9w05"F֚F'j."8hE'3x}LIU ܍YK͂oOS7(Ք݋x|T7zSr5QF8 3jZ)*Ve&omuz8*枿JtWGU!G,nH͜$,dFȫr P&D)2&Q JkVV5iÖI@\v#(-DEyC%yG$K1r] ٣?ro8uj`Q% I4l51kb_)kIl0Ll3%fݽNC[(QY@L j@TxJ'HȠw}kDkMT"Z[* Oc f31"YAy^jGIuv"! ;s5ZUU\]3ZDho~Hޏ`*cPW:Ja̤FdM$\` 5Ͱ@D*O22|Xk4L18,1ѴEݏ z ɇl#g o, |fgJR3G3X0+TfxQSwVluwJRT\nWk2,,<_ tGPUAqx}Tn1JÈ PQI'}t:bl0WVTedty:m*ҡHHjSGJ:b8$/|y=9RF`:|K B>b2HVBoD"#uْΎ]>nż1$Sv{Tյ܏Y>+nL[fYK1}٤ҙj?x7Ou^qlOC8Tf墺|F2"e%س>k!*:Ax9r$#yGǏ/њB5غTs}^7#<|;ne6J @UVT[C  A>(2Ī"(a#'i_sٶ>Hs!<%DfDA"Z8YkI_e,X^е>"MXIB{fZD9~6|1rnEtx~u=Ӵq"wkv]i,J ݺjGjSю~*Zibs\SEXk~l;HJ%*$\Wȴ)٢r{%$;l*߯я#=5#ɔپ!o#`Ms\[BTD!r>#4"޴j9.#H:6{IxS/ )3ɘK'[L2eJMŋ1SI̼]k [1<| RyBhGz"v]3)vQJmLu.Dz#,CDsg A~ C4>*E>ZgwE߯O^H)UNd9c5UMC>=%T)dD(:daPziKN(L@G-<=9I&x\Qn|KZHhQkz QyǜQr%Xo9f#j5Dcf9}%u#sxDq誝_<$?1;CՐwZ `#/SԴ7W_Uj*6RblL44DxEf)k%1u 0,yhjgZF$]S,+`961J"*eϜYd?T ְ!UEQrS"Bg+TGZ(lľ;97:<nWoN%^ ˊ^ʩK2է?eQUo..jp| QST .bQY쑨+k_uQy8վC{"qƏG>Io2I_Ckz<pv1}MV zAS}j#~|qg  tv /l> -TF.ĩ=G,gLN4 A Nuh5"n7yW~afѯ_8 T\,2TgUIjwvdkKJ}x<]4/ZL~M]wn<3q?L5E[DC :35žkf*>T{]xXJgZ`g"/kKL 0ky%zJ֭:[kN%F=鵶"Һ"gr 9@;hkR$3 snc^@ ~Ï(3P!k '|e.@)s1d"lP_ U҂U$ʹ5HBŴ 8"J{g3SczYkfp.k-HM)E >]FE‹ЎIO3Br !Hf\[n -}& _&+{zyV 24-*wJi!e%N%M*JP ɶFL'Dxd옦"#i)Ⱥ8OFeq<|j|#B9t>/LM*+.KUǃr[ W,2v\=se富@f"~w-*x]r8 oIL!MU]7;OCŒ0xF0Q؍-{aKޟx6b M$!v-{J@77^nXxx]!!HQĔy-rT2EF}"N$|*d9r0O#7ȎWhˆ?4CEKdn5ƸŎkHI\^ l1l͘E433`hrA~}1loy'*6G"^CyMjAa$RGOCd0Ҹ@ vxUnPGXu^zSwHheɹEzy$5r# o*pCB榼̓C f/©D`ќ=l!Kac VOaviz^ϧJY7=5m0ڂIMwfQJ.-!^i gGNy3P @_rJGRf_x)2ՕPUfxv5(jVH/vOoA3J /'DHAmSy5WJ5v$ה91cR]|oPC3{5aUr!h؞͞0ܠ2S ے%޵'1=@\{7 Y/XIzTBX;G16'Wbo˩6ZHA_?{0X ԩQ\Vtkop"֘]}G}zezrOmO˜)w}vGEl%;6G­oO!ϔڮV%!Y~CP <>lݓWL>Zߝ0Xw)535mp寰%QD1.!B 1U3.gMTn/΀Y}&jֹHT1/~9ݛu͋AGHx PJ>&,$kP>_7D}Oίrݤb?_~ -[d(JV,K20*~5g$*ʕ'z 9Hcg2GkZ[Hy +l!" b& H5,*`&jPgMX#s\<} # Pjx֊*"pg@x=ݓIkRX~G^uML5IM?_|\Q_Iģz bZ џqIOCE5ZZ7ʡO!`F}\?nfkzY߾PYkPiAvM]oS(U S˹ ȋz32f$&mFz\WF5&af2Ӭ:ߛZ\}=ZjkD2:˂$z"iUuRU}گ:e"ӣw{d5FLUc vL~<8gDNu &fpM`q&QAw lgUQYN~@͌cĖ2y ߍ;uOgɳE܍[58sͿ A#Fc+ZI0}cEC]S>U#606#v;[kLe[s17?uۿǿ?ɬFnPԏ-#n7l776t bĤaׯW'Dngf5 5P9-9#ؠ$=w'+HVN$wzkmEw/zeq9yNٟXهYo q i*5,N߲C*}+s1.0(=K4͆4ɔt+2BGy(RƂ&{oK3mIdNMVƯ7OW# 9pUn |RKW{T DRү?|eS{{_YIa-"QB"Ekd1D-^ت.0x#qW+ׅ #Kx*Tj?4r_jY^1TZLUmH pA!LX4xuNwǡRq3`Tcil3.MN)B_z*k<;bRt5'+~tcЕ@ $GOLG+1q,}Af‰,0ca.HJI5R'K4ˠ jyNF]΂ycֻxxZ;Dˣ ,L< C?~}}yX)!y`S~un2U#DM܃zT-8CEweq%"ECfJÚ%]Yk)VfwXe1槞 sS3m@85@f6?NCZQwCT,s)]?zv(UVFpNwgzX7U +6LM0rӜ5r52|f}K"H*Aef'm=mU/3Ӕ*8ER˗W* |_]KaIYM@>Woí!D|dHu͌h̨PM4\t?j\RI YRUA3) ~UEfZ% **583!q^m„MmB&R:AFޮ|ԡ~ѕP뼉XwE2*VKCTLdC`VUq>|ZCujM )Q1&#v,4M4P뭘iDB1eGJuZJDg6"%I)1bHmj2AuT}UdA&~hTBe1K.^bX38d5HoADOh9 ohܝS_wWðwTQY\P덱Q4oIe2!V:t>6LZÞ+orX$TKk-"FE`[*{u] ,e~GdXY+Wc@zk7{y]תÇB!6}j܊)r3(p YtK8a24CEJo|hsOѮv U<_&h]nENx|wr!?S3hq)zk4Uɰ8WKתq4"?kՠAkО5b1 c D#3P6,Y|>VA)]V1NUfT*|s0L3JH3*y3ҏgWzEH~И[Z[c>nr^ì'&>)[>~<13mun{u$+o1dd>ilflnVj3@٬1ɕVqI!= wGeFGJJk}ңj^c"2b0Y5h h*2j4Gſt% X˭Tի@9bU-<#u "5 t:7C , K4wn|{_Xi#L.%?$ṒqסkBrIWīrï~"G3B /ôf 4f!s 6Ik=T=f1hrk\#DE󒻧*>u|MMPjICO /]`*fnԭw\cEZCyM3ՖTe4G8}}DJS}<$B,oL)B 6& 's :b]`ۨ`dtyl92.&=y##Z| PG &b3@KE2#1\ ^뺎#3쏇EEBWEa1}kb󀮪*wn) p O͕K)6)9X|PtუCg XkU UXOn`o j}./EJ}gƱ|^;q^/Uy,?ȷ>e\r<>N \y2E,g&(Ys!D\~:@u?DyѠHáEy irȄy%wgK& .[E3g֙{Dz3-A2R(*#*1Ucuu /[ث#A(< dSr`zPګAT]e.{^STކrϭaCuhjN!%uf!>R%d3n&<\OhXfK{]6[lʛ_jqdH1 ԯp -+jOL8 p&RC!U@(>ܗSN6(C]1NNO͢-scocy P0z&Nkc bhq&!*|!rؓl8}lWfY&&#w>UĴ[d^Lk2Uhcn)1އKjXLw\Yc *9p?Sv^0c)x<.܀7= bӪYϔ'~]TqOЖ;EٗXahݽL`jW,ssQ L7[YLlM̻{yp Fb?NkAtT#p5a٪[X|D, PfeW*S?)x. Vb C{o5Gݝ 6q~x. ̞ zkʛ|.O>|3D"|lL:[FĠNMYnʑB"vQWk-##2"zYgh9n=^M`aC%Mn8xD1.97UVYyF,(vZOp_[!x^0ALLa $5Pȫ*Sj)ЉޫJM0fE[0S! ,Y]REN(;u j\sOu3,aI*,&CZ|RZr}7&+e dUR؝ DB]{(m@ ҋƞVd7Q9T3H1I eי>|Jȷ[}w_+h][者\uD#A:s+LÌQ`6$fwd_vx6ndY\BVxFDJeL%M)j |3awZB2Tf}/}I SJ&2Q`: ӚS*j/@5}*ޅYJfƀ2׿\쯤NJ60֚Ǥ|cXST&=uEx-C%&x)bVK3$dSAdqPT#*ݖڙH?쐿6-VI^7c/.ߎ8oq횪wGL$Dl )2:tx^#3|>t? R.HU Ռ;o7e1W^'5L${QbQnF_֝σSfz{Tt!WlP=, x\R1/$J22v}-AoY!aV) {{;5G6oWGu6S2p3"Q2F[ ԙ̩#'2,f/]əM- l ]du:Erf ReOiMO֞yLk 7ř7{QKǘkn~,zTw#*etwI,qf:dy$I t|ATs.툲Fjb+vz/dObMjAV8FW@  J<`5)0?1TMy`8(|w`Bvzom@1Q8.n߼9fꇋjPHm`^,IDk/@EGsgfE]@KzD+v& J.EbMF"V"1e .eZ7+93)įrc|uPY1F.Zat P o{hMkT2wY1. v8Mo%NWdZyOLH(Ѳ&d,TYn>HA3K@V 4YsOF.Zl|eζ}DDT;3Rg9ao %C:JhO7" ]Z%h3a8:u*RY[G&zJV*c0(d,1Mj:"ҬE[>b?ٶIVQ-PEiRN 15Hד~wp+mZD(>¸k\"pw5{[I9'p޺VG\Hx>⎖CS$=f*fy]4NN-WFI&.񀔶꺩޺>& ҕoKͺi3`AH])'`6K̴[&xs)Mʺߒ5Y-Aݬ 5"UJޕ G2dDM0#8אaR3ADT#6FTAժ7aÈE{jߣ{͏ 4  YTIΕ^4fHSvr&o $$-i NyWHF엍?}0AnDB/k@c?_K5 ʢ̳ɒ/&Mm-#k4ajGz7WP.3onFX6ܹPJH xGgX [$GTY E|w=w2af0gde23OB׈1 AY Hѵ 䀻@r#_fךv푙Y9U6uUaq!!M1ch{z|"a__d]) 3z]da6TDZ;%Mljaڴ!:3\3u1.Pj.LjoѰqBTEmjS^ 57fE]F͙9#7IlG>ܭvh!ڎ3xJ65*) ɷL!1Łۘ\1C5!uwS2qķӚlҺfcǀrj&23l-kTRMnsNo,g5bXE8^c p]$b%-p5f#5Tx0Ϝ I}Y.Vv#F)cV/!(gp+prg}Oᤌ}f@ *-,Ղ&J06FDî~h* 3.*Y31 Soe$jfWAz.{2ؖ_ e%G50HSE!RpJ|E,5aAՖ2 䣨9΀[T침TjR"z}= p˙.R@}0wU`FإL*ue#`epJ0]S4s"#KiľKSqbIη9Q4 q(ϯW*rsaHc^q׆9 \$t?<&N—OWmVК]{'_Vd5P'MnVrr~_F!aЇ'}@i]iզm^B]T딐j,0V:Eni;3EB 7Wm^?z9lޏ'&C27V):4u3#fcEiWzC'4K~:Z**1}Fr5F*6Ff{i_ X~YOv3YuEE~dvjY+ ,$ ncǦ`ڻ0' {Uq\-mJ Ni1c\燆^7 (|^6^׿?9EsavSЕMXn>;z~#>8iK1,KXI`&,s%7>U]#WY.L%\ ţPbم ]nW3 D/Aj={#)rRW bĴanUvYyz6f&ۅCQP-YaoRκL(m8-ĔGr-IO䒖n-RbE enkzlKD]dH>M[~IMX*%RPPm啣D"1. ,=#cP& R}c]ECLh0Rw\G6L;86>LMHhg~Yz2\;Q߭-Tf9[rE"|~*39_F kuxDջc\+`?sl6w{?;ϦNp[J{(&4'RBCهH@ZbjHYT,ރ6`(y^toրyQ e%OZopy"ݾ*}Zm3Wѩؙy Bjp6Țͻ`޼9``+.WL&gT!z׾L*b&w JVp Eֺ7^qA}}!>i%o}E!R|wEN*n,SnHܣ£kAƸ^UL_~ djD;gq"0L`LZ⺆dwTdE9 Nr|b cߛR_*l@B8T쁀\7Gh6ĽV!IC^/& ;6FVfxcvv&u1TdXEic䬢=33?h@̂STKte ùϺy>~4r3xg:@m*GAB%5D@C Jiʂd굑"7u-QRfȢadNG|n3#@Yu7]P/&+srGXwx/Wg0vʥ\@{SA0S!fxꇱdn&&N+ugEPͷ~=7RWnfG0ۇXGo.$?g)}h6R!  JhuR=cjvؽG;#< ih5\T T$R QqPju^h/{RZ LocMZk3Ň;gx2Me 5saF3hn*-A>O)WEmVWOf|Ika2BzXL|ioj/d2v{ ޕx/pߺA 뿾ofN ;0~ _*\@iMg# F(Bjf֛93RX^17i]\^N= Ӛb,#seWGDSm^TYlw,ff LU_r7_[/J)%rv;uv[,xEDU|-wO,HUi ybN1;GȜ1Z#o~dH/'fl&CN=LR$Q@x-#)ͮ(Z/yXZr*0+eΦ^H ]%gi7 ?>'=XIn ?9_ʬ뺽i U{F06-9Y?!*hBVĻ 6eM$e*4%pGFn.J8#g@cu2x>qy U)Bhhjwo1 ;bJ9"L,sҚZ7|\DżFn&m1=]p+[ )^-Hؿ6NoJ픥\QlCȒ\rjhi=︇-e <,V}qT3.JyY_>D ߎ=޿2a?迾~i<_#ҘP6Uu%L5x(&i%<'ܓ7Pj1aT݃Q \fy/wȈω o8$ȌQyffPv٘"-7XA^ϣzxuܘ)u]!ׯ9U|>KrNs˟H[ϯi̇hGkcXװWQ{F;Z+P~/2:̂fESrR,վ߯jJ~NdG_ݺ>ԃiW;=[D+NtP\4ټZk]fc`Z#Y;D<6{eqZFI'xq=)*V7rbF$d;|g$N ?Uծ7=)fþE=@$::Uy轃r F > T`].kQ5{dsڢ#)%.L>wGb9kgHTƧjVw_[iY:!~LgrH(qLWȝsGؕ1N3TZ=>ZɰxG!T d!ET?rs(n#@h>3`48#dWY<,-Wᙡ 4J"lUZ4s=5)0Ӵc.< Yp|TeJZx9ON5^\:'*6, 9ff7p*&|xb\Wò拾qEf'S; 5r`:@T\ $xR6ޒN T@  0I RnHX։>G[\D3kfa|'J#}Ih1ќ{ei{8gLj'rhEus&5֘d@{Hן)GuM͌H@ss+cSO 63H/`QŮj[̆R{ݠBI1zzG#e㼮TvϮmVe%(oB>q7_ fQ00ĕM%sͧ)8nT˄PvhOm^D$ukA E41NO~>>#T!)ZŇ@2Wn h*oS&+ 2E YLNP=!⬿"J9Cu&qg3 4Q5g+H 3;+&.ŰxAiEkY#|nׅx~2p)~ q Bp4#U"9W%U*Ybov="mAc~'CO_Gmt!Eï{3뤔7C;R#]C7`z1 ጠ` 'r1#KL)^0I7Cv$}ɀhNA*%wHĺe/SBeJXYx0麙Y~\y\6iӖL˙|~뗙sb؀;0-"\0Uxr$sS=^+"ZɃ$?K>b,k 2Z7\wK2jDqR݋w K%ylf`|g:#W"(~@5/ǬTo_r1rɴm:qlj4'jW {~U<Wc))cִ"9044UыqϸRjxK JXk]x O_?sk* e&7m_ᐯԇbI(@m}R|\*7mn4eKĦJqRn?#'J6EIdèi2ZfdRRGLj6? sTV$$4NAL.P1h9_VnA!'"n.q,+0MD¬G>pfY @7KnL@cK6ir! :g| 8D.T4˝l"Y7:3~"9JHz~Q$APQe&"1n[Ȗg]ʒP> u/]fr7j|nr*V=е!s"w[gUk-m;XYJwE띤eo',+iRJ䉺,3o0cϟ_GU~ <042uF"%K``~Ml#ɒ1?>XNF@$PNl?cx4سc=Zj1nJza\`걛Gasiq#ۜG̉n|Y<ΡZ310C,hbc{ℵ&7ۤ-gf>M[+B 1纳ږd4#if.nm*wZ.#bZ~-:}aNR__Pa^`BRL~,`{H搊M*2 ;V$–0hG?po#y׼oo߲}LT)>5@#w3l`vo$y4Tu4Fa^!2|d~8C)9fw-̤H.欖Ok|$7.XOm4+$㝟URV/nyٳs=iu.wg\[q`eBETrn$&A"ʯV{gx\FFuUîUTDc!̆GFe@x]($}W=FW蘒ƤԴ&BB=Il+-IFzv˺OwCeniۛ ~ P.,6U&B\*@3kb[SUu|ٟ{Ŗc]Z6P^8{֚Y=SS9G٥f+i 0S3dbu\WY=uZ|;&yM4(pց "bMU1N[>`"#(q><:m!BTY|GڵӕǮ'N!@9UbGQ_#2‡Y)MO4MOnJV/V ~fC,3bv4'eDY`r4 ]b){ɔWύ[!+QԴ,r`{DM,?A` B!\l I~,-̅]9;*D<|G&$TJen"e*y'2Z4"CJ"|DO''7UJPS%(e,lS{Ӎ)V`U\{2E| e$3)J$7E.,(j,6l[U+<ޓ{n.(59"y]UnS>T\RWN+}j<_na|<7Zoz}gkxТAcX q{qI Aҭu>_ezzI9@3b\i2ԏ#ߵ(#;zNVe:ޚaܑ9TIcs#"ц"Biޑ p߯q_jBs֮|}?T^3Кkqv_Ux]\v*'AB;Z74q Q,8ugF!t\W|j~]ΟN$enz4ApCiq|=ill ucc r{~?OG;W$vRU[ϟypPU:J akO3]r>o5EhYM;hQiHcض{r%60r. &5ĺLymܧﱠ҄! W"v%T2 ~r^tm{<&2 e _3鐘) n.1Uᴔu-s-lޑ#60e9[rKIہsc\zvSw/3;+5"¢(AILPEq[n`\@C u|ʽ<ʛS̵ObIkɀrfeZT7\&Y˸뼮q^a'>ոVH|ŝh x蠓-a%QX;YYX^W!B0C=!5qikq%;c>o@GWU=_$ҷb31pi>?;h (np+UQZ`?e2Bzam"ќ^{Kݣ%"eiszόl/B;8:{}.f78$GKeds2&mT- %ۊ0=itǛY#Z:䉶99-!RQO9MͭSw3 siHK 1+ٵ͟-U/Ize;^J<ǒf.Oo}3IHz7w2c.'?LJ.:-oYu=yɶ .Iʾ9 _HP$\$3[ qW{;w#Bwti3di*? ' JuyK# =`$ͮMku:Шs#ev4;CDF,4' l&&e/=S.,0v;p@BƝ }Y6A[Mfpʒ|{κfyYQ5EO=zk#7k r@KƞW1ϕ\R 1rZψǻ~kwM7^;[j/lMW>2wJKfp#b&LluSsl%_I~Xl>rXe}  D4FC3 ˜M6@/`pdVU8kei!A\ Ah1c\0#* xP<ee}~Jhq*dLRzP"~4$G.pYSZaD2xcEf{oZK_R]g|&|%1&!n#AժŻǗ%=8|7cgB;f4#tdw_>󣪌rEvy! $[9 G<=m]U_DF|Y;=d 5[6?Ƀ4(@6 K δC%gd0z]4%y9V)I{)m{,POhߎz|;4 ClK#n+su( D_w+uoeWwE lS:,#q}U} ,Oli)ErI)"[*s }DE2GBH"f&B0\VN{ʜ9 ȚJH͵Jh9qjP X87K3$cn{\vӚ;dHD|`1Op#tz:$aA}ܵY,d#X#4'f{kGuV:sdO>9)u5hve*vD¹-2֛Nu]f6d-RA/-TK+35NS({UH3íi b#ϖsסDL5ܑ9jh\B= IL=E8GF1PdG% h 4)ySrTk;OymY5Ş1b2CZGFdQ9?cM׍`pw䮋 #ԒHOAS#+Tq^!Mt&)M]nfLGy33A+E p5WKz&&Qo˴^Y}1_}FA ™44].wE4oE9MO`|Ǟ'B6ܡi[@5MGږ|R 6;T ֕ws*D5  V 22]=؛">,hMiP2~: R&TY |IJPoO`_!򄕵ǭTGƎ˅ <7M0fp%s)dL)C8?,۶9;Ӎo_EK FN#_5VrJ9/F|A>M(hm˨VED4>e 9d~oneU= H9]fu8#eIQijqY\ogm;.P4c{l//{${rfh6Hv|JQDx<c<1Ɵ3rwu1Ջ$ڬ1|^= d e5=J\ýDpQ٣leN5rAV&й9 9_I[p8`dpڷ s%K:r,͕h)dݪ0Hk}oH~Q?2239pQJE.BNЗ%vťQヮ>'k)R|EQQ_̆mHU! ɾf\H4ҥ&p/ATc]ֱ5ҫ Q^#DjQ6[i}5BvW]9Om9Xc'ښOf.ꎼKyŶ4J4q24Ҵ`|t)Z.@ؿH55|,քr'->n F ~4,!0_eq0!~E4#*, ݢ)N'2eھ!z"i _n}qG~󏖡*s~H.љH@Ϧ`\8`OkhXbآ(XR'-PS}쁨^ 1GNlP*D77/Dk+)ix*^-?Ma -+NT$Jy&_+A15$*~}![Vnt|=E5^_1=/"Tb tQW33x`˴Poj4ИܦBUq<XZם1n (a.ڎgc%D%T|{Wm #;z.ZXH 馤hS 9:,ֿ)lq]65"RIx06)av%%ו$]L Ov9r<ILPѮQ)B^X8F&cq}\ˬ,'~<A.|!4" >Y-[1Yʵ1>DlюSՇr r.hE,rW0s{Ҏ/W&x+-<bK$EiF aLU}JAY,As^%&Q)# fwzG}XӧGDZ % Pk &,LDT Gn($Z̧Jx4w-|[Cܴ~sD8]4"*f=[* $e]:nS4Ʃn$]b(YCވ$ZBR˧Ý |h" !̳(i Z<3fa ]5w$/dCG2=e%7<-12̄DvH};+ve_+.)^K˺EL5ka @2}ii"J 1Y8#DR4O'TG Kv0ܥ>R$'wZ2@u~D3 vV~,Lw|W>յijK9ELHGk=*a=|Dܝ3ɦ:`=pDeĮY0bR;H-0!0}wc ٝ<m%8oXF\B캞p2a$_fl>kI9Z(|ɽM54o-"L#J F&Q{dg my~\X.J/ y^Db9)isi^l!mJLwB O!'Mmo',1HAm঒~(9dg0X2Y\JTz4W̊(e񡞜{usW^%1L\D=b>! wHlV71o)c#lF5 h\ )"m /d»=%l Խ`'I1nPskE63 &c_CX'gͥ5(:ZZ?ro %cr?Gnf 2zp(fNjhR*19}уwtZ@R ÊPP3#¬z2ULs>,U3p.,W`魫Z̬+C_wf;3nNN,HDn,s&_o07G{\Z3%R8u#P+=[5r118j #ۢrD|V0Z&722B$(jz86͇/ >w'# |8_$mfTz)0Izjd5i9kÑ1=Ch5|e"h48!G`4/HaAw}hEܣI3 !&f\xk)EÐ<-fokP6Ij?ܿ}}9a_d=z,skStSPy\*Q\|zީG"(@ao *GXc2N7dKAa oIDm\͍7JꙐӞ.H !Ēn#]!0U{رjDxpk6i&( aԂ)Jff1v G_hA\({YJZ![&(bUǶRRKԜ?~jSobj:{%{~- IT\WYJP`O=jBT]:O݊傾p 铮`8WG88ܷ֪jo[+[h3s B$$N$Fe1sր=j->zuԞ xڀ'V֪J&E-ʺ:̢cJ%z$*,mּk1`X)"T%W_>==ZZt:pPjihHT_C}i.2\["8 3gZ4}I blNءɑ쭵Z "{w"X`j~A(IbY t/҈q'ǠNF6X2䱔Z /GCķ633UH*;x6\4.޶|g_Tt:uLֈJP6ETIc[Y%|f@]!FsA8;Je^  O]z"ck"p$984"$)alcWjXY3CwZ˽3 ?% %z}&&>;tyɃQ2`R1uЊAc%1e3skEB|FqnuxrČx!9j%pC$;Q3&\L1?@FhQ: v>e[I4Z47bpM#w71J+R9",PДoL3T-ěO~~Q$Az^og.dPLINٶmeV^`c &cb4-v՚[#6ҟgO*/k n!8!t= ,],)FC7;4RjU:v#e . KCu%t-5<1Ɉ UUւ1ai)5Oz"q B/-|ZyE^,(Aq_D(Z ,ޭxr 0q8VNތ4N$\rr7-=R1' Up.,EwWϪmf[ AޏK`&;1/z#6*9fL(6zX')Z'lmkNBfۺwv%"bW"j)uP-ukM,m]Y(<ȶ]UlsYr\Y-ڵut1 +MHDryZN۶M$w)@ÖY 7b 3!$ؐLf^hD57/^u%쁨E |vQ2ֈ `2Fp1"\zelQάbs"ATټ)"ڶ3]+lFxXhH[ P]ڢZk=upۂN煈%q,RɴJkb1 r^V#N*8@ DD׶Uf8dA!=x ~g#hd-HJYƣRzmm'G)tVW{ƾawc(CCTX'wo۪zz!v]d*DlaLƂ PX5"IpAe,nJK4Bhl%Y|l Q>M-ij< ZDR0 vC@Q#'X)Ao7G\+PovxM8zNZlSP.آ"Y]Y۰Qy*ZRxX:V~1ƥ*3z@glTP iԓz) [F|J]F6UTÑE#ROĂ &ZZxE8i%w(~ra"hYfbC։K(#*϶e9ޓ "3~Q$``p=o[fzCDڕ!C 'ࡸǩ-;΁8y^! sr#ᅙ-D`aE"ĶmVE<7WDIURĥ]WR.w;ty|\.]*sẜ5o[RbP0HK3e#f^wvi,,<ʫ0CR):VGu9&-NQM̏ZCp5'1Զ۶G)m8.Wg, Vs"G+H)ELZkݮj9&0+hx7"$G {P(]]A/n] j\Jp2WB JT u IEw.RlDA7=Aq9P](3F=nFOg*_Eƃ}w6kFC|ɚ&Bn`u [kxOG\U؄\Te?XBge{%K Q*Gs3ӲDN)5Bb۶^cD~ǂ\1FX`l'unf7 qΠE3iDG+wy*=G$V[_eӆS,R !%(Pˇ1EȆ>ɽӗڼg)2#Nf8`r[76X:/9y]#bb%=nnqLQyZM4 ɟ͛@Nm e _FpV̘}{0JLB,*p7Sn!9ܣ+}.fDY}\Z)SL2&$فTku>e!E`w2RgE5H;j6\aN]SrF۸sg3SIwoԩHߜ^GD&7npԥeqEK:C9fs3Nٍ fg1&7pe O鸢K0=nVpgR2[ #u]OZ>}!iş(¬<ΦЍr3pAm=ct2gQD|e%*pڰaҜܻ ex4z< |FsBDIITh2 L=v?Dsos8xD椞JƐ:b=0p o#8~3g9"(uhsRf'ơ007A}z@!cdfk-'9fÅmYxuYz?IdTA!k}\$*, 1Ŷ!U(7*GNkl*1"}GtEf2<##z\ﭿ69߽Ku_@?W"~A`cl6|}Fi:*0M]AXEF7ͷʴTq&In$2@mqHAxEӾ؇PMPڇ'7{@w2|A uh0LJ*0pLEdnJhD1J$Yɾh0a(3sEݵY!G (tX4ex2yloi.:6 3]i#"j`N*!. PDTi2 1E/wGϼ:d7'<$utxJqN|C>?oG[l^ ʁZ#RtPtZ*޼E#|SU'IzGGNFxb@͉dû/Pǭrg0MypoM\wMG(NSH+6n0>?*t,AEͧc<[_sѱ" UUԝ>KyowF[|0Xfd{_Uw:;m|zyaۦ ׮U}T0*IMF3F@}^*RW]"-xw6+F"ŏm8)wys%S%7ʑ#`zMBZ /(s!hu8SYgͷDq"GDiɱfODBXo[yP(lmpђ {,D#da^ڭ*+JPِ9 AA/bgVt8-+jF~ xt []4,BD5駟Ow]@5 7A7.p R 3NZ=@$CUWV7}@{w e"(H1{)Բ, :Zni)"#LŶ-q [|ZkI0|o#5v߳Gp}9#y6GrtuܬR&/#:|ӥ)t\<|7o7 ScqȽ _s=*l`ԀC0MSZ›{+eTWPR&9{;"Ψ `m(+HKNp+iYHiNs,ܛ:38vƣ"#ϡ")` 5pԶ Y^il='@ KVܖ8#[* b4y 0e 6>C4;K]l: q-ooH*ljE?,m}ȹ}c^O9v2@{ <%c5jY:@QF4/ 5T]5 g,g%Ch (w{.]EI;4Rh,ݎ=:0aOtRYEp v(0V99>/x[gU؜Vܔ99MA0 *!oFXd1DFR`ա}cVgwD15xD)TB1QkmefΎX"[n5am#(>0 0X:™-bǠGɘȫ1JʣYcZJ؀w537!K9=pF6ly}49?LpAp[F = FvDab!y:<,ܵj0*-bZ؉#kpms*:F%QURJĻc'p7.# vVjrpzD"}ܽOFACݝN颣8PωPZkMn[&3UC2JAY+\5^/ Ddq"1j-\̗N539 ?=]VEY ,CquIE0; Q`-bVC8ĥ0 JWޓpH)亮E| Yb/쮚 ܰۨr0dL:g ]"6| wmoa>L<ߩlwB™%cEpA1t(xqkmuf@'FJ ^Os!"V =*phx5b6 @4R;v<0۠vah4!ZrD9) `RZOHe2! 4RX)0j|E?|UI\#kOa0IYm6e'Ij0%>w,u^zyRՐ6í4؉#-BK擴 |E5<'7tfʒ'2>ukV x&T<ڙSΉB셬"̆-lz={kmW<[D"ˊO: G.%ive=E Vއt,%spxBcV鎛+9==߰O.vȳd4H;(y㔙@rfN 4b''|4jhޜWLf*LJLZfL,*ZH.[$ysBiw[P6’Z'_DN"RF"D3qC@J(!$y|>d'o o(SKR#Ƚa6PtvGgcRD;B#n*ީcIFF r:y1ÆFFr1073]7IN)6%#3|3e K.MTyP\qF7Ƀp3ڒ~U7ժ8gHQcYԾYL:#9(&jpwM|o[d.[2US&9'}OFH"J)%GfBS.<DT>Ë́8F3SR*5{!~ ŬV.u/)Ւ&=+ZZTVVbj]tl2w&놲cۚrw={}K"b[i(a/ff(UfI##3AƤG62z[A.Dw#P_6`&yƸ0 I] 9a+nDbo-ˣ7o|({@s 4WIݬ٦&.W;{b0ĞE1TS1dE0ǖAа !`OLy!oexX( X|d-mBp9oe]%f&l^ 3[+"ZYYp8I}0s'T~LwKZ2 W epGM1pyv椧͉܈SoƏ^c(vqRA\ IAtqAx"nfrvw7.ጃ5\74񈏤m"?`rUduӮVvp'1:! V!cև'5NY`3ٶ2F pAs?5xjG&IF:stn>m 삜US uT#С ͺ?Z", ZPtP(aN[>fRkHDk] 椣Kן 3,iKte"O듈6o\Ykv;I;0[mʻ )".h^K]<Oy9>2<%2:uɦ;Xq`$/iLStl乎T`u\ށQA爐}*6jJYz ݜIpކU03|/jOӝKv^O蝤`N0Y),ax}?(az8 30B̽%n}CF?D'^,A4pvC'ԏqH\̢(? `*?=+vI,ls?;$L]l @3#Qe.QŤHaDk%rA+Ͷ MaFEZj<t )f 4jS3s E=+v\FBunӷ3da l8mf`Pf6,D9u1^ONͬHz?|oFMpU6H,9=ܭdӓ1)k.,Akou[2<"^7\mڮ$O\.uU u7p,>$-;mZw g2Z@Lr H\˓-P/*"Z|:oݣ ekk,Rk崠\׵n~; Ë;**I>,.~|0suݶ[<]lkZE[k8s8:śfɇصW*z\׾8F"Xeߩ ˗/NERUr:U=.s\(0OmU->Ͷ %BUdC 5K)ۺ2sѤbiki}|K-y;зk/k{|[u"4EZ$+"Tʙ=L8(h]XPޝOwwӲ*hCfƺnhٶSںniRr~154\QK5k~w~pW+O(-j"XkTrZro芰 AA.UDj!0'j1Hwϒ!LBaI $IJy4w$0 7e#qӭ\4a"caA'}uqf z !ȰiIa- O3 U2rE3n\қa-@uBNHBUdҢ[VԃD:(6,l$װfvfqC  8a0w `'Vw0Kr PŃFDTög&**Aiʜ4pmbN>y <'+ q RT]6 &# |xnN֊Bkd$Q•b.ܫ@৊H$$\BI$3D|$C%4Ѕpdw)H'Pg Do!AAnPh+:2a]% o`hNf8\f5o.J(&Jq֚cj!ADAj8:k`&/as@/u!5{_o߾/??OZ|{w$I>틇o>Dow8sZ9Ӽ l1l\ʲ Q񳜋D f'_>䓟wgx'>Qw??u__>^)A.;|麜vp/,}7t~|?j7?R| mݶo}?9Q?O~ W/~GdAH7mP2 Ve N6MT~o}|~>z@,)~{GDUUOן?<7oZKif}k駟ezU՗/_~駥<w?헿Zџö_#3}?対G?dc0 *g!Hfz|O|q|Vjf._I)XEfDұf}pagǿO~_Zr{}ˇ_J]N#*8{]Xȑ)5p]1}kČ3eM8|*`Y#/$YOkYg\B|f]3[u3z7!a:0a4-_Zjr06"Q`34uF4<tIԪI^4H*ci[',]ў_B!e͘x$#jத!з,>("rIj\abσv1Jt:}6yw(i>V)Cn{>E:ҚCU^3Gv ^yh -+pX 2C„Ι>OGc'LOΠ;1cʡ9X2艌YIjU#glA0d.U՚sXDa~WD*Ďb~{節NF"J  {[d}XWHh<ou*IE'u၌zc%MHop0wHqh5˓Aged(T.F~񋟽__}ѯ}W^}_|-#<n) <5ZilfQ"Dir<[]xqfա&܍?o>cn_????Ot>}bWQwl,gexd|yz}?o>>x~w^~;8z:=<<= F;? j=F“Ffb4ȩ{wYsfٺ^TEzZ ّ@Uiӻz…)"ן}jU&o޼{'_~mOW UX pkI6LYU%)5!d̊_/_jw&*oS/ 3Q4b XX㾵xv@zFoܲ:(beBg!qrHU9ӪG1N>R:h458؛ʬ>Y^*$ ڶmmk~'?}8h5WaQy|l۟ſGOa6KD*K]9:͹S욵˺F_ևKryx$,,|>k}y,/'1! >bnƷ?r3S&pc~ȧg"Ir{8p^W3;23{ߎЫs|Ի %2N;5P &5 .hU鐵˷@纭{盂sPT9+ūUa??{86۶ZZRJϋTfnf۶ݝG7r,B$1w_B;xl/*Euzƾ7_3+D& ]|8%tY!;™|{.^݇|4-w%~Inn;_ x_/|xۚHtZ.OHW1QKeYٚiU K,j)1O)j:֗|\8֭;`6y 2AY4{$.ߙŔLy8r¹`N4ųW:.c^?}N*@&=hQ 04OyaL>8f.n'n2ъ"Kkȼ#|\`e]vr&̚14X!h8c 7$6w.Xr\ 61m 1qA's=D+Lt,v%ƒ 6w2~R!s~ At'"{i4hD{R0|&ƒWMp4Oͽeow8G8oEkΆ[Xi2N9"G3Y _[mcC^<=i5 IњmҊ 8.|`E:t|<.\Wɩ\~վG=@otE@ENE<}ZQBٻ/Ce"bU-<(gxqЁXoK{bR;R%-8!ʔD iTh"߶p'sԙB_C2@63߶,&"Ÿ 1{,\S=ݝOr*lы#Pnnf|w=E3:݋r"Ń3AD,SB4K Wbo??09AF4hx76B(|B?Q&nud,}X<}Ww'~m3QuM8M3'p;ǩ#1 ,s><:ˡo.F{čȳ|2?ε@Lo| [G_t`8//uݶm3>I93(Nچ拊3׭5 ¢5=/4LDB$Qmaa.Jô#"nFČLJd]o0켛iDiA~f&"ZæIW4mPXD-GZuE_Os9&{gkI\;Ͻ#d G! 0#wW{rG,"Ν4]>]]}?̓;vZ0y,:C3m  V^h ۝-SC ) >\_IĖ,#*@EgIT3K`@dvF5uA5R>\ 3=?|&`ƶBkF1ֱS nY)M_U9EQE7=>`-~Zo䆿k.+?v'5[}@$Joe_CT2Nԯ:97/n=k:[ƒ9jZ ML,(T/ϰ&{HrHTM !>M#Y8S|KSm&%b0D+qՈXEXg5'YiZkoP8L%2 r`%j3T;"JSr.H"G^; FsgZ3k)(D/eT2%Ap[6Y0$Fe ƅA/A7./8Gfܦ*~IkM4d*Jz+bC/]˲P.EB3Pby6HF&0r@/R$Ki. Kw|٦e"9o@LRPq4}-b ^l;0ZC{W;% "yI]stYD%CR`&Lj1ap#YnePU 9e?,imFĴmCDtUV?`fښ~?O~}~z$'#u c=nЛׯվ[/~W}W:7_LOVN'ZW#j4]DMM@ށikOh7_=}D@^Z51zjs+5#ba 3hljhR:8}i\b u-{/~Yfzg (&$! !=B]7*A0TNHYcN4~2FtIh7.rk ϦWd\Xa~[޴ZNbgaQdX"!RI/Avڃw[ppd[K7@IaId&-hXg4 tF7;8u3VP$E%ģf2@Tyg ! KuNbʬ]3=4CRZ=ڱ';cj&a1:vuH!9KŨf)_7="-b閁<׫nm~.[g{oĩ|ۗ?Mk(,%&qC&F8NِP31mۻϟgE:vu$c4'9i+kѹL,! iY -gmcװs:'#ZkTzGTrnPӊRU89#͠*K KgM1xs$T(TqdŚ ip)CP,: _NmL#VN(,GG6+"9tKne"kXD! W5vr+{łZS, .#IX㜭wn Ǽ(po '41@"ZTcNLˡ=e_H]4΁rn(sb:Nd-LW61Vq|Ag n5̀5Z6UMÃ=>^>Oo?W<$g;I҇;(1ȸ]U+\JkjgmuߵYɆ ?&dgvGPGgaa%[b*QTnhm}`!e^Nַ|+o 'X{a PȥA qrLį #"SgqYK[ 1(df잦/ .bEҕ >ϾiDv9স] 9Aj@Λw*=j`y~ rb>kKz%O/O=;.ª^,Hî1 5EǭV>l?2F%`2fU 7suwdDM(Y{q h1ˑё sdxz_b58q´ZzǧUKDjB6=f..=<<.A< X~܏1JџOF>O_m4"FBʮLM%Ee;LCahF6*f.[ѩ:~-KtUJ!s>wpĜR&vE>-5]_7Tb_y6#Q15XN] uo\q3lbf+JuZBa񎼝q ܇#%D>sHx;>C_a%HyzZy7 ̘)J=O@?mfPPLDS- 9w,n[yj;FáW}o' gqA n͍֪r_4,W2r$]DTA<6k|蛚#Rrf =zG$6M)et4ݚmf( m֭>Zvx;&6/Dg`I(ȥR?+uiTmx5=>=͍@ݏm_JO?/M5iˌۈs!pSm5fd4M?Q]k3|!҃A5` *bÓȜ_,;6Ӭ-db_*+bĒhi§XxoL 3Ҩ<n1xc#sz㘧 MO?9#2zyEI-".ږ{^חk{{+S[[LUz@YH"EԽgI=?feT3#@-9KqwBLQEP5r},JJc`XHZd2ZQ\U4@1*rdXȄDŽHD-S89v%eTS$EHm*PuM!$EIIGNޟBBЊ}л<ʁ_|\D!pɝBk($: "L~,U^'33sSyw8+I<WupkDW >F&qEpFj!^,-¬&{KzTzgXR9Wգ┏Y3.aFMv6B41ERJz `h!0-w*NOgĢwFZ"Zk"iɺu($r"jm{H!G/I.(~#@1̉:4RTIԓ7SYW21sr(c[4ϗ>Im^;/]3:js6,4 )ς.Xd6}]NyRZCnڛ~pm3YucUѠߝ%=DBTC6W2l@tbrtU$ RW=BFW50T ̖ɹ)CS "BDg&.eܫW Jȑr=22l[.ftՌ1*.gNZRqV5Ε 7%`Prf 7Y'$[iKOgiᅉ`0L0Uּzl}p5蜊PY{̶ȒaE`=E0'[콋jW1{<`_m}黗7j_}ߟZ)CT*M =<e SUWj:Rߞ*궬3,)daK3W"NBތ ԕ)Z$ab*&Z2s=3-*6'-(oYseSRu55OSĜdD ϹG[E;Rpqɒ>3,'ԵˑNJ!#ẙ[nU .gpOS E:HE1iL@20 fˮڿ9z'yGptdR/,F;KFl;ɬZ8.lXELinD>yOJ3c0k@n B$S$)L~,r'N~m .qG1rTsb}1qmhWLjD)S3";F[gن5a82m@%6ͣE틯1Q˒1Fƺ:-[,-'S I BT\_O^

ĀMs&XCca ~E8٪kS5ɍ Fay^#YMI asᕆUk9̭|,&c1`0ʥ<:CkH %랑Z2!;5i=SP`E4޾)rFc$qBqVqPɩ(9i``̯q#O#tE9)ɤJkuRQ~d6eL!x4!vSU+Ķ]dPbb&.Ж`% %DFG.bLuۀgIe"PN {ζ_F #q~<"]uLaq3 'y@i:ꯦӳWʵ,j9#L{yQLJbl_GWw֚5+)G\.[ͧߞ6yppY#vU%=;w_hʽWW~|Bgxz7_7ֶpWS="5=*˹u86({8='b"S$,U<>xw\NtJ<̈Pm 4jĈQ a.%qP4J1RiGAX hX܁`rOVA MjDkYcMaN1FzIeL9NR_u-ק9T@,]X~Lzdu2dKpf;1F>``Z5EJ w tz\3z=T`<0U "1w*,s1UD$<WhF/+5NFǶҮ! z9j!TU# YNHt MlVq|!؄I"HzN,/V*<.O%Ȁ^ƌ:RQaԺ\ )Ѕlu|Kvs(K]9@RowuP Q6S,pV.f9L!L۟G c6ODVa[̶b:{oNHLo=b\ߏq?> $X;,6fTWgLF!Em *$qYP̎TN$RrHѫI(:L$z&/:ӧ޻jeE \uTu tWLW@Z+"R]v ͒/)&2*9ٚ@jp\]VqĠd"蠊Hw9D(ɲ'Ļ'1b-GMK5lZ2õ>r7IH+r؃Cs ]Yi Gگ eN"( ) >jY y RQXMj*7"0HU0* if ,2LU;ĆocpCHN"G#JUF6H8J-AݤGTGKw)j}6&$6:c&Z(MHrH&EVw>r_Yb?U"7:"GS|ng{?`< *OC`xmW*-rX8f#5U؊q0Sof35?ş~{oF@-s NɗL@!~) MvvdDcVPE SċVA# \&w y`floG=FV_.[yY>EG5Lp1LN΄AG*ۚ/,=&|:3$m22;Imx)&3=%Iȸpꓩ`  A-KXMk-/IvO=[:2S )ƛg' QĉK~2蠢J2$ }у<8whWr/RK&$۲EMeٽ ]s  G1u8sՖ'1!Xۮ %X)"⅋+^+=Au+v26L8:It{tiX?iS xdviqOoDeX ,).CX)!W/̔i=NPE"ﻩhi:&)rNҫ@U鑚u5XD a"c,E/ٳ_{_k1aYC1Ӧ(Ջ﹍f@I\fˉh ?8(\gsaϩ]z20BH=::~UF xjs1M9zL?c|(1ViRW8TVj-S-Ghɜ M/yJ<ШyjFi}%ɏC4{(`kNMÔ6Egvn&A4Y4k aR'Fe2+ 蚎Q$Ekߪ拏);ATZ#cD6S![ky=Tb61Mݪ*8wLKw}YD1`f[ W{|u1A^tJ+ yg!uYxOI ɥ~l[/[xnȊ*gnfV(_SG!,mXXT1SCL׽Yv_L $H'iENU޼V"cRjJ%v\qflf"9,Vj`^7$|kjdVo fwx$R3Dx4FD'ݩ)RV&󸂏ZhPv+Qj?ߜT,E4$"Ykj1 *{ d\D2fWӍ9m_$".֮G3—jTH"zM(nRk#|xzJ=Yqʚ/S^ "2}yyG`[*Dt.Eb NKs&C>/<d(Y4t~aGCO#YRNReQDe5*#9;X[0mbYFd΋2| "AEFU;c {hk9TfOgONQR"ΏSFNkDM\DŽORb5F _j 8nl3:AId ݫJ; ai'y UfV^^NFY8׈{&{=z0aMW):$DH;C@[1Xo&75U(ؑ]W![z8[YKR M%INfR󗍘mUK~GL_0ȼ|=\DȀ G,6SGRz4=ֶ`kZk M&E]2j0syܘGZ62(S9\+%;e3?zɱ UzJ|<8knb:d%NZ82~KŨ t ^p*uAmd4,lS3z˰r A$kT"wa@wv5V_5LӥBFEq?> 훷0K\ʁiJ~JRx11Nrs&H>T1MهP3sLؽ _#@>%4/؞Yr(.VQ(]޽{?`9=Lu䆩sAaQotŲDF US3ͤQ&2b;V/Zkf{vqR""lkmSU!]u|CӨ8J$<#záL꾊B6rGvCbV@~jF̣B ޘTOgnRTUkM+(TZDREv1,\](4;%m$5䂊6f9̲, >-6j6RUʠ{w_S)5rhVqexd 1%0\$ݒw=b G{MTN.wƒp#" 9X}EA*wz:^ڜ5̛u3&]/חN4m"ٶx({b]Y53v^e*q?>A!}_u 7"'hݻo:tϡF& ||/}̈́s wQT[(!E,)[)PGMj.!#|R܅rK''˜a<= xGhًS&`"q^ۖѲbu1 ~5`fu xjz6G"ff#ֳɁ #3=mrtp'<\Bn0*o(#"Z?JX6Am@(JI1DthCZ$\bSpZDҫYft]D`JUm =sj1&} ,,|ذq$fJPR Q/ү$5(MaZx{' gٻxN"S)Eϸ¶}}wSc-Z*r:Lf d1!$LͧQu""I4T FK,Hb'0Z9əXHiaRGr]I\CI&SF5菍\1XQB{!zHBCN75"cOk<:[Kg H\nݳ+Deޒ Cr,Z EJI"w 9 !U[E;y?3VqVG-FPAؽd@*IY058̚ IH/N|fI2`pZF2F㺏٭x.">c{Q]E}4Awɬ}t*- 6kWgy{3l7E/1sJmFt8#o hzDJrz*#iJ tFEz#Jyɯ\]&!Ë1VS*!x=ckI$z-j$ܐ S[S ꀛbq,wsaAA<G9(p ޽YL]Qf'QT"V6kO# 0 F+,VFI_FZs:H5̄,uHMvQHɾtA1D+7, _ 7{9͛qh~e}t,7l^v<\ypD_rܶؗ_}oۛ$F?; O_^^3=o/1[kF6aER%:e'OS ^Ek-]՘*g8`?sPDqHB1JrU`.̯f [R2v&3%#UU~9kpYzj~$ׇ `dȚ M4D \b1ٗ8 y#t&džsι`|Sg@&A-_~>|vy2S!<.M#@kf٧oG1Ӳq?!b;ZNx>7ODg3#Aצ9qOzr99drs& c9I]с$QM:ι~LsD nCSqftuuNl8GsD>`A;ֲig;d.3;M3g2fKC瘡'"˄W99Zkd!ĔRr!" .?>.GHĥ/d2 QXr~qB)$,)sXtIJ ER|u?+)+DUxRϮlF1\ 'lFTCfC'Wd=U:PW߲'BcG8T1q뮠 CWIͲqZZ:JF6뇥s^#YZk͚L=fD~\;:[7R~܏07۶ywgi=QgӇ2^EZKDm ٔ0at/@{b{wF|7k-\9ˋ{O}uA Tʼ+q?Ȇݫ50|L GU:уN8!T`L!s%GSU38& bM/[VMkIFDPumR2R*{V3 zE="4ge0F1v` 9]rArpzU!fidGy0 te2BO6^YXEؚ͠bԍRE@312cM{ER0c>0"YMZ) إW}lm~Us}`|o\z'M?k waߊVQUB{&ؠ]B! 8a7AYԬ5trN3D<>>eCfSG9އM_^ZikfC˓Cȸ6sOw^.K{PKC]+ y{߶Pj\ݩ\3&Fݽ)6 l]FSM<֒_1!mӪnUTfGvi*B{Ƽx8#۶-sٞ9DM#)&M'7c%W)Iy)nﶦ*/]͌ T3H{s0 {T_M7mPU1cH%0+[P)E" n! Msa֠8U %a,دDl[&|FxC:=s I(l9 *GW`"W$"a]LTP$:]UTm 3/ .P0 WQ!ٓaaFJ{S4]ᾗNX65_s.M"%0 'YHI䝙!"v33 ș9YYcXYeœ`+=nS%6Xj7]VxBfyzua|/?$K0{y^X=?_<=M9Z'`/p}*jt|ɖ z-W,1{Ɠ%ԍ|.·‹b%ܠL]f9XbL !DѴ6ZՄ?q}™lqH=DT-ةIOfj~x.@hp$jBvCO O.ϕݪ~DY\rLD@EwiD8Dt>#C-)E5CFi:a"a]I\[tM\\)]Vjp+RͯB>3q_IufrZlh3Y^W9Qi JY)BLTc^5^O[5X8JF?dr-x C%ANSaQLxD*D0%; P+ n̞bYS2;L<ϛe^NWPO\>B:~͍Bt|?g?~8O>$(F9*9g_w=MWrIrPSkBK8LЇX'K>Xki\\ S]Yy;9h=3Rno6:6ɝ&!P.f#6Mh $R.g.Em@~e] #Yzd 6P* Wf ˆDL?Cbp0+QQ:[sSL<ǛYRBD*2ZrYQ(2udE 5hOPrYƱHGOq鍇"ݵ hp8uPbM@8D>vQ V.*O T5+SR\e~TOC Oʼ3]K8/PѯxLhA}c~*un:~]|ۊOǟ>/Oێ߬ ?ϡI i"伟ggHY-l#kX_`GX÷X![:^ǯQ&2<}Nc@r#wv||D|{DI~}ɛY֊E˭]Z3ő>{uא]9tD^>ypȺf:BѴRĽ ל7VqUl\MԔhe^&}9V=M1*O=97 boW2J mg C("N[@޴>+Y>`-$PE L%?8@\T]F[b 0O@py\SԴ2u|fL1b$ MNb^o4L.S q{#D IEoҡkB To\ﵖŖ֬jp(ewĔCJo6~WkP$kjQ;T1\xO azdBN`%q!&3R ϟxghU2Jh$  ?U13H avE$ 8 `Pkhdc (ژ X2b[43s%_b*1fӯ3Q H>}橧ǒ4bpO",s‰, ˅*B(4j}ZBR#d 8 I(s q)g|jV*/Gf~cCELQ>;w8x2DB"ΨN  ;2-)Mu0C_U0"uWguߒ`xn1-SO΃=vg\Lmطo "s Fݵ,d\`؉ E)gISù;Ǘgw=;zmuOH8|teh5|Ix42A3v>D;O;ޤC%>4qHFv!ehՇzi]k燪)BCPF(%iؤ$dԲɘ4/S!k6DM5 0f*7 E*L*4FDhw9~IFXv5fӣ-&=n>ՏUUeBi`VWM* j&&5m5leUi[ TtShK *sh5lDLwaPm^ L t-YRk Q9nS3;y-Y`]|IOO'MjM3-/cqk(C3~D(xÊۈ sˊ`,}<}Bmң-፪)*,)CD߆vB^=WPfR +%~E&@MU>?'Dq³{j(CP( s,N̡z H͊!Uv)jGpA&C! |n^L!/rEftgU[`[g}0DMUI@ym`{VVRW_[pjWj^LvvS Fy[MG{XF=Yq 5Q kg??ϟ!y#6Xrc&w ^u,4a̖Pi@}a6E"1T8ϓGqX*SA~@%=pb<_SS[ڍ=ׂzy@NBv# [0Q~hvPEmZږV]afl\*T{qck#2f?듺"W{P3B_)"a ̔tКC;c23Ԥ q2Pڅ]Q|V6Sn:Jѩò{gYYUĈdTcZݳ黝]9^BcT*Wr\+KZA d|=zi$+FX̊ wak JMAQ@d; ҎD $=N!!ooy~Ns|ps}r-QVu'ajwh:}*(5=h#WK=-Xvx{dTAb;-I *YwyaH5L>$Kr˖_)(jk=+\S%[NR Q'nG0zԐ7\Ƀ@Y*X1c6mim L#w?w(<|X;l @D xXu6?G&EƐѱN^0ɂH%ooﷷ~xSGbVѰ&j# kZl#"Ks/)KNLPufmʓT$O*GZ-U-=IjVAN{(k`1 {FܽDG^ "DvVj!I ]@w /||YB!$`8# L'baΚXQ)ئj%,ALh)Y2hՋ{XeHjSaT: \IewcVe৲^:P!XU>P{Epg*.0H"$f*RBB! Xx b@<%NPVrf/η,qlX.ϡJ:[DtJ?qk,w7S1l+"DIT)1DtqCQ B1rKq?gDOO&?1QS9#f?bv^f:~U~1Y3"cCуifFgƇ$?C@TD$ΚB:&"Ȋ`j6d8aE)GpFIaDN`t?\ZI]!Qjƻ z/tU:5S+Ͳd&8I`6lqsf4E"9Qy '+E6)`jv!ՍP]a/(2wKy2`l"aO3(v{BT/ՌxaB?xeɑZfkPHL"E*5=@LRrA "GOOOМn,\EhAg@ay*B ܳhEHePJfFԜ |!1L[CX"2Ae= TӢaj*8Tw>LHd s< J@ L&">AB545$j_ a?"B$s!)a7av >ۆ@~2PW:^ǯ7&~u暰S; :nyy)~HʌQ⃶'hVDY`NuׁkUz?uE7 u߂oۄconq65pwUcԡBP\N-DvoU٩x^Q56b=P6P '/7|*tpg| T乇f6̬BԘVLȽ& KFF1:O b*xrUH݃x\p60Cg6Zr1!b"qa )VBY6 є-cq ]&z488/P߾""3C?ΐڏ|rȶo"lKfZC] $,jH,kq`һ@n*\[c\7L`g#BժH—eYw![ [ k:\7zdb3xY`ON&J$C=A|߼Huh>īz!dykw~-0ۂf6Tpw@yQCJݦG)`I]=T2³cY%P`*gi!}9\kq/)g/%S kX7EJWJl͞9L-jS%c$6)%9~aDzټ|RAt_5_%׃gAg/$0obJU*~7 N@z tK-uF/ZfMr͉6*~Kff3hhetf6V @09Xev yZeNr%}UUvV*ś-Td"P_="(kAmU|ptU"+!Ь\xU+x& $ޝ篟~?`MQfko<#)&* d=75W%1QY j&) nu_'1B4c^xnux]ҊV3 1l<B80!Kߘ#IU}VEn]5ġ:'ãԃr(;-{' WX%csBWè^u<%DKDdJ FgٷnX],>LF 31e^s@\%Ho /Crӱ>k8"i,RE)9OB4qYqYY y;e)GTld?UwĪW: 0`csEe?00'LZKz$d9N{Qs>7,@!GR{LE/,l~j};I dʊ{(@9$8 0n$jpOvRY $H-ecf1*d鞩iҲ'4So^MǼdfPU/Rmv u=c/NDwTXhR{A B t?>??Q%J -ӫ0X̀/#_*&ʭ譨f`ȁ 1gsBnGw|}Ghu_+]҆[5C*&`f䜎Ǒ*i" -H@A@ҧT4HQ³qWi81SS]{KV'$+Oeד(I riK!k>UtҬzKV5:<˪dp{J|@Bsj) lXZf]+ޚ6S!`2bbj‹V@0kvRDDYDw2 &pV%/GMT6L9 )%D-p2Ω [D\,' V"&6ƒ!: PuA`N(bEQ#܆}yy6Q?p%(^,%"G@O5J-2P"LIh`@a?ϩ*YcB[^"<8SZu`uϲs2Rv+V L$lF{'(͝cf>a'ȳHBƍt#6{@96c3'JR/ ADIь>^ӆ*j :D)J6yIڻCtٟ;%`(rC6P݅:k󽏩io)c窲**c >trk 628ϴYȵm)e. 0kc+svd蜧Y$3p;D@DhW.SgVTL"|r'9T5> cWkXkg'R rF[ "Py`IΤ*?O Lu\Ď1?6!F_Yӏ~xƕ("g`~^$V_/m6>wZnw͢7+4솝ۮ(1n >͟ (tr{ U4Mx }j#J/cOsg0YνQx^(5,F@l$raXϫq\XkO?Df!!kIz6+ Ad+TTT|_^{lK3{62 읳[ E$} ]jD.Fv7ȣ0rqKkQU2NB@z_>!BӨ~~}rE!za2MmWPf` e_g[HN`3!L$*I"ef_8ttU>Sc#ӫR+nYf`@/  V,-K:GHx~amwjVJd?v?_:~G@ ǰk'W洿0 Qqj pQCtDaiUgG4*UcV%2PGlw-~OSl/Z)YL's[Y}iIL}2'yXU7ε:\S@Gz"Yґ1P{ Rs̘/:%%"bD2Y.UF8[e۟+CH:K\M[eWi?Pdƶmiz@܍6r]mP4;ET8NZ(Ⱦḓt5x 3 1?83CJ[X!bP01TX]ZU^W0TfuaJLÖ OK^UȸַD^1'd24=ɢ<(ҢaCeACc53C$ӑ(dM~T/Rfq= * r0aq&~zxnr>֌n7,x(y$u&=AȉΌj{ ^]5E+MCv7Uo_Դ42̈^JLYpPaQ f>v,`MGPU~}mذ!"8T C9{0;7\P xWxuңr!g2 Z"D<p1:穦f=2YO퀧۴XK={0{qr/YRpsHT41OUe0S[̴!>,ÇpݻW˚v99doEv t\*ro2Ltj=vd ̜41bё J(gә VrL@JH*p~-f-ChG`WD5+ àAD0I:^u)> ȉpAE0J%r {%H4-Lv:9K.o:[#֌[N8enbR3 2@ (ᝁzGUPelm>~h<46jkAͨ*Ra`O53-"^S~K֊JJ bMgJ:< ebsBm9Q#g!6W̅jzӏ7Q3<&6Y~總!rB֞:~+e$Ȉ'>Ynŵ"21P`ZM]!il޻8+ꀈ${^<8ci6̿ۖ r -1<}UHhkvIrlՙ'mbX'U2{< B͈dd·p0L+'3WD=D"ed_&ԎAe)uc?PUChR@dJyL %&2x!ŦĻFFJ+hΝFJDDە6~:}GݶGP "2mOyY˱});`@Ba*?av,Q<4g2="f]_i;Ɋ ݿ}@tK2;q[a8WTUH,Mj8 oؼ ^/25szj!jx,q>ay i:1IzLjdyeynDwcseQ[)h+i:[iфo8繗MG߿`xPl`9[w"ID*X\7js_Ty{gOd DL0%+N`T^#Wf[K$l*2A 1(r (%ig<"qclVV6yՏN+ եe^HDjPU*K V&j (6A(寺<(([U!$ g JBtBDa"0#W^](SE!9秸p~wӕIz<^4bo k24g=W^!? j{v-dmIŖ\+4S7ezY14uf}˾:~ s'J`0ƀBKsN)4,9AMB,Oecbav^50_d{r0OR<kSnMZlgȰ?j %s_x"o|-zI[bMnqκWoԲ[[tš`S4AڍI vK$4Sg]%cf TAZE̫" jMRc/&>hС A@ӊgfVTGIandSLj؂* ڋ h UupoA&d vDeId)q]P}hU?_y J ƹP]HdAT:Po,;%1 Pf&6\Ff7'=y֨[jIœ =Vٴ]D%(qa)i* 01)NAB ՐEf\:Kl=ct;TϷ{ ;5^`el۳ QXY#7"a9߰@;3T$lxeCgB2ץjEzV ?W0b2t_QLȏuN(9a_'J1n i9mq^xbjTiY /XO2-Av T{BB(,`MUD,!"ބ6Ak4DC* !)TSGF?Y TnT'Ǹ騅8]fl0|;BPfU B$O+*3EOpNfNu"9ɀ$*3kI0Dƍܴ%˺=aP2:d:ɫ`RR½T+TмX"LW\UOɲ'QDΌcxlM*&5#k#䡚U8=trF.ì#YDX7ٕE#<1vBمDcx04W"&RPl}ϝ ̫Y2Ä#<]:4^ղˑov3S)Hӂgtt"͕e`Xh~5S\j}_ӉIn: @"I_ɸ@Of葺e8K*:g%C-W0Fi?ʧ{p'k˥2I3,[sRLoL[yKHl\vqadWUU450}tT*2gƨ0 ERZ܍?P['1w yV{Oddt8]DCuK;Yv%(%CʤtpT`1t"SBǦ]кXbR_&2 Af{b(T)A9 $MOzF@ЦYI'i̊踤jdJDqĐs}9ueSE Yu_qsI`wRl=/?ld)"c ?nRkx.sB? I˖g* ۳\{p]{uPx6ʞN-Q$LCBаxAfn.n]r#W\˹hLR3227 4(c~Jm˖u]\0DxLJ$9WxGʓw%'z%h"Lm2C[dQQǼ?*e BJ40z j(i~ $BiOsWϸehDyR±|7Ͼ˙ \yNQd<-^X~5goj1w$uy}\w?`lg 3r0A15OίkM?b{#O?gRc``iľ߿bO}Wu[_??o((d^ Wj(Pb"ff1biE,"/{ ܗplZt=qJVZf\~83wM>7ZHVRrr߱ 2[9TՑeKwΖiN/;DDeA z\x$5A(؄,kRə]e%QS䰄dZWg*ջ^K[{ӊKk^ֽ><ڜ 67WYX-Sh^KxE=Yzj ș$HURs [%>i=K<"Qqa'Zs54uA2u++`8o~8 |N-`ת9Bj~&E9ÕSW4aq @2?M3-m%gVℯ8HcԞK-&^`.dfM4"YߨBp2'g vy'ʲ|+F`9 h+D,B&4qXĂ @xP,E5QTeJD)o3+VE2g[fL]O]fH 9]\ >s `Gx[5=3G%H*4 ,.AIu!6$iFQEH&8 sBmk6 j̉@[jճ=2կBq_JWW=֬I(ɳ<]\;GOO̝]\ҷVWX$6U<2 Y[ꨜ%_o-w~*v1ƫz7Ln_9&̘6z%foCb%H*~sy%Q.xFk*XukJr:/ġuUhD`zY )دղb%)r,Jv^&Vane.ug~PH&ʎP5-65c 7+Sq>:FBM-Qi("sNVJ̕Ǯ9A*k4l R5Cpq!va#VK^Q7t)HހL @H ..6vÚ:ܤεКI;lOفmPli%eRYXJrKĉl$_M$ѠsoXn5W㓈/!{{ҏU#~~+1sT!QzI1 v8 ΚNPUጽ?s?Oa! q!3<]l-HB8'y?+VO?43+ZbMNLd8"MHy~M$\!̀6]DKޑKI=*GBhWrQIhA YD%4;t5V{]I$noqoU7{f("D8|AzփBE!R鞪lY\o*+;3n;۶Y#.D5_?J͊u#Bk=`Jc-?ך)[v%k2@V" @ wv!Z7IGٟh< HhDĀLx"']9OA+3dRy)2#!L0TRoA/iD$j 7pә'-=Wn5b LjXV6e b_wfق? eڟn2CQ5nvK uN 4W LF̙FrhPas$[D 7 .wV`3- ގS jOCs3qв.z}j|9)># ̂e.2Rw_$P1Y9G|}D \ K)ծ>w_#f5Vs>;CJhxSfmtB>lg;xzn#^Zl,Ջ%*ܙ黭Y)[cth{@Xx,7*#rë}Jt/lpC{O2%4Ћت*Pѹ&Efhaa"Q-; Ҝ}8Z!̀ TOE6;ww{峱\*~,*+.Sƙ”J&J*z1YU T@AUPu6&҇4orw0ۯ'/ֻ%^y+=Hznq2g4"H@W~%'05gB-" DX#nh*ֱ_o{}s&Ơ?&U-MGf̐EWNNq ) >'yWx7mPn u= /PK{(.]N4wg LS%mX#Kg5뤛g/X~5ki/^{RLe F )4{*;o}g嚱Z WKhT7(0)ߛHNmzx[5ӧ3Gp]îʕ^flJmh\;xtKXȀ[[F.ܰŠwW j)#UB Őej9XP=nf7m҂-]Ywvٸh Ki'mq1`Az<`U;fvqp_M툈nu+;>#*vENFw %X;EjNg`_kc_WŌ8}93"if-K_i9svVh2U׷t(T^>pX1hV{*ΧSXާ{Cmq 0^ 0ο^k?@7ܜJliw3ݨ=dm2ǻa+LؔB]#|x $|U D3ħYm H&o,%)lvwxM>]ūd)\5 ȜFe*fD' D-10QEiobK4GZ_~`Ƭ6k.lU)'`8(%dGe0zU}i]UުEjiLʬ7^vB܁)ݵ߻+ތE1wTʙ0cNܵ}ufktCtn9}k6e/?ǯho9~=֗)ݏnXVl$3{/휾AWu~$}"^<}Z5]3lf.VUemfG /`1iLo񪱾ﴫjKۉ@SA[&jVdTr[]˶T秿}*+EQOcXh4f8h4|a,!6M5 3惾{iFM;Q ь~ ^5d^7\+-!ͱ'|)YPVaJʠ%nO.*P]RykwtYuz@W9H:+Zm@E{ΪS*!|b3{STu D|(a˷<="c^ooofq 6E_VZ?o??)۠[L,}{~8y1#{>ܐ9xy<ۛooN:%HxH+%{ɡǑymf\!SP#.-"FJWUXU$dFd pnUhe9Hqل ִ@yI;1#f`^5W;(=S`Ǫ+vɇ*dj%I KhNz> = .7)S)Ā0ʭ}Gr-^d[+j<'$?F@ QN#9~>Hr$HW CǠ=vS㝐wd췺v)1OT .5/:*S/YuB]bu-vض*.rsq#6dD3帇"^ٶz(xul%Ұ/ӗтv(nmRXx_7 ݒBjS+o)-U={fLCD߫C2s=h]s 4|F-LVRb]c{s{͋ %a$E3VЏf&$NkR$:` ۴x"LXvB:bE['7PYꯚ8,[ZWnݒm3JBd37'D%ݢS8Ȯn~+e%]_Y+mҵ,4B ejFpFĜuIJ1Ÿle8qp{ nΰk8E (&fa%8|!|=_Ǐ^fa3^=Ҷ$jU9c</߼ߏA37V'f";ϫߙXUx석&EŢ)yie&}opQ_e[ǷmO7lxfVB7>embx`@|*7&w!=5܆\(+i`$y,ibO7SJk), R f߬pr,j$:%Yͭzm={p&±\]wYÖ*\ql;A*p$dBYs.TQiƚX.zi[׻J 1P&tFKL=f a`ιUUl$J#Ge"ST_F;#qmC爐[I!us\E՜mƵlN eu>>}{f6 H=C@`U㲊n2L@%VIi7(QQs)^o=,krĶsYFlOگ7܀1|67b~2xYо*^e ~6~5/NUu*'_c͠V 'ͻeRasNf$IT`Y_FV%b/jT( in +ux#3\VPJG-21{eSm^#+[9`h00 ܪ:z4u,)IDR[ཌྷD.tc*z_pnI;]1ƨy9*tGeXF6_+V?÷eX iVTpX=pwH(FRv$)Df)F :R*@LPl08)+<*.iV|0V63fNXՅm % Ghysp  /n&Db򲛧XiC=(|{>ݬbXe ^a!IW-~m @tKL]ЬL%sΌ?3‡שHUyZIw@?@L.b13f/sΟƣLXq<0>QXc1_{1\,SҌJsIGzjbt4'Q0f&3i_v-GlʂQJ䓑2pd~H n8 `%mfEB ""f@i ΜY[DBx{F2s*(EavN(44-JnϝOy&mnT+n9OxJO, z ۀ `!L9 ^(Hӻ3s ^V.n[ÍwU]eA8Zs> ?d&YfHH3V3|Jg\-LT&,9O y(T)s6br7>r_@dWuÙ@ʹRRq1|2%:K#K:3XikY?99<<9'c QTn+p?׼"OH)xMg[zU2/dCYi^Y,%t?=lú+8 VcSx()\D6pt0\.#(P#Y\%,/m /Fvf ,|fLXC<_hc!#"H+joHMbni@W68aWMv*gsIDkl9VLgfݕ%(5̵ivJZ~/ML93? `]U4QRz;!^A7a,y1,5|ӨmCxaSJp.V9 ]ɵur)̬AxS߭e;I73ٳ; Ixyfm+Qn m2<?\/侴=!`FR_':R&i?8xktBN"faM"wUmٶu!qgTܿs*_VR92ȋ ([R\$ߙjKAi3l/JYW~CK>2E@M7N=냭sL 7޵WyD̶"i9(!eW[4*]U` 1O/{Tuu-N|(WTu]8xa j_]426ǽNiseDQ]=e,t#N%wB˧8{z0բ~ ͸2̲M+ܶKwS@/uB%0̛ȝAY Y5([CQ0"4iZw7Ă2VMZS%TܰSWQۇ5V< i2{^J1бSb% KOΣ7uK ;gnI~h>”{ -5=K0!yy vB>"uL'r%̎lݎFd}Dvc.ܽ7F"f$~TTN͹<hw7WW!xܿvX[*S$#B"hH$dkJ/س-`u[W1xg_UfUP] Z@AVNU_PƼ! 8ZW$Ge !bϭ=:o?vd_29{TFk'pwm~_[yEE c*kܲڭJ.nYSu 9?Q!.;tiS$ Oefa\n{:bY/;`9lzE^ 2]=솜 O,sNkmŲ[9]o"pS &e 0 9.ua4)_~~<_wIX˟!bsjKA(R(A"cv]wR#_X~bb&b[{ P'7hMdTIazfFͥҹH[p/k[BBEoGݻ}A79ݔLx02Y%XhfZ812 Uz̼Bnl Ŵ׏FxZXPwx?'E&Ѕ8f6@SB'dn%osXpjܸ"'dg)g(D|@pR6Ssjst{Ie־y 1lӑz`+ V8L~ M^i4w9SLeKT*Sl-3\6v#]yV8Ģ(ؓ`L<4CIDS"I(ܔ̼gJ{^$ x|hQfJaCW8lidbDH,HѮCK3$„RQcbJɑ U'9s=*'fHr3d,n!1(eO2X$˲0! *Bi^j 眿'c%s""![fU<);9iHS܍6R%h.9sE\٘b#S޵sL `f3bUڽZUl:(lcVW ߴ.TD<ơa.-vO0q]QN7*i,4FqEu TRC[='<;xj]fZu8tlg]&I5LL{ްo/#pdnONhf~gTC[I|]A)qU;ĔskrlXCmRn^Q*4 u,D(Q_ʀ]!U֥&`25u="WPlCM+)xGaN;F!&a68ƘY7weHWV&tECB`bQ.]vdPԕm%lx<8ܪd˜IX-m[oJKu)czU#>aAȨqu)X߾}{FX6Deou|_Ǐ^`~zp7q&P_"w2|X@KE1"o8Ú\@g%POoх _e ,/ [o;pY-,CQC?MWwֽc( P.Ues| e9˃S=̎Qj !+|)+7Jtd2ۅv_wO9Gi*#I;hJոaP o[z !u.˔%QU[ y{D Āufn#Гi+woH]E=IcVWFE-: f|GJ燁>>>$l~\ӵ'؈] [=@/}t8~,I@vd˴~D 8$kihTDP]WNk!{ |Å?}ڷV#&m;6EǦu|?~~vyu9d )bY@ʵ|3_cH:sXѼ"ltRԶБ9ElsTYN%؎ = PJ.Q 4*jDlnpA}3;3 X$XD%/|V(Z|֕&H(u/o7Ҧd朑DߕE!rew)v7) g19/U>AD23>h~I]k W*Rʹd4fn ϊj`Ö`Jf!FfFܒΰ5D/XyI (H9g sw7w3?A̭!CH 32V:Pk% b_Y;F^"]/!v.ի-[.sbΏz iHs=’4|WVpq9/ADۤ X_w'"{)-+cżRY8W?xR%YleRš[K>DZ̈-Qec|ӱ ݷgwC-K_p ?e~ޜLɎ#a %kG Mc ͛,Wa{fMQ+'?f,sTsц^3avZ|fI#'df&?(.*J=g dbqCT{VaM赌+|KjKR2]!uR6V"I3^yUD*H=Jb]U9^"J%26[7 ( $.ۅպMrԵ~kQׇ .5˾)[)L|7|Q\ЅEg"_ 4cJFd7w:=Fq^,#mkhUTO 5s6:E?n8MEX>:u}yڠ"ա{Z+k.[#U)^/^و = L7rc ݎ ]xnb)./w^D& }߈H׋CQ#6]#2 w^%C|.8=ޠYV1,FUJi4 :TrjDKh(8fx %1c!md^˫ɾ \.ͻz[I"M29X0*-AHz_)ׂcC inց 7YTrOh LSWݏ].+srΧ1v ༕rI ۃ') R=<2Ȍȁr2*O3|\uϷb)U}p˨-qQ¨FZI$9m#3tG8s>89Z_w"} 73C5fV͇x<Ɯo~f|{{'3>˧rXf "yh&ۤՏcw: g2Cb, x{mˈ{n>j w+T 3;Њ(S&J-^R## ٚUdFiOi L3`eHd m [0Q4yL^a3( w:YIfcD419sy=1+XB4 l Ќw?H0g Ns`fQF#sx,@dr13%E }d%JGK>Lcnj 1v4I3وJ eՏ9*ɥ[d4iT)deV-Fxw=!!aTec ũR@d' sU(z"TB&M飀 ݀JyÄ .&g:dY5)!bL]%<1hq>L g4aΘ[|X טɌױ&n nC {n%?'.q[bQ䚏Lg.|>8fpSd Ap\inQpރك#f"exY~7\)Y]3=+z 3t{}ށX5ihffc1{ϬV7=/w)|UDafbvLWFdH^Y>z{Y O=Pe/Ѩq ʈ37}7Er bm] [ΛZei۾sXZ> QUBՅeK эZ+2kS ִ_gf :7fW\2Za+o<\>-eHqgq^uͱ[ 2 I0̈{zq${gR̅_"뎋gc(_P^mě|ۡfRiloy)h)+6"ǯ{˯e41#sG Blu|?hu%;;G[}I{ps·3{>y>[x>GT &!?ZvXK m]ټaӗE΢=%@.:#6lfeMN}*k_WN(cF| ۃVUƻ{ɕl yŢh 2Ԇ6M1C=Q5ZYs:~ %BaEjƋtKal`A gnGꞗ{SZl$\uΫ.ٗC VM^wAtٗ{HÍ<' qdhC5s#v?뼸%->^0ZG3!S6X^Uχ%AE톺=2ʎۉٯx<`&at܎i܍VD7밌\yȻm+E.."dMI;&̴vEzh E#3#[3-DhNfefBY.T*vܗ(,[~Մ%>-UoѲiE|ϳtL:,/J2Ü4ϹTjA"aAzB)F," ht˘5]'IәK.Wqm|zׇ{n#İn4:nTn'+f{XW^FG}|/WUfY{D9C-x7 fW$)Spj 8λu{c8gV^0vM' mQ(D 2Y23#'6S,^nzM\CRE~x p?$?L:YܚƔ 7/2# qhfD=?x<G 3 LC R{7:IK Bߙе#Jl&yW (D#{Xaw! Ľw͹*50n4̀$o/EhBdfG ukq |JnF1]/ފcrZ]+A][ǣke d A::i=) exsǯcwhZ:pNtw58#Rw4FMfYOx]{bTI("m6 F0gn3mHSBF[-c p&2A!y03ɘc<@O;ȸٗ.dy _mnU*q5;o[TJL@ڈE ҺOM̲Ҝ~Ƞ8J)hd"" 6@FsNg{Rl$1Uӎ|"I֢I'H9 w_Ss1?d#+T8y""PR͘ȴ2;N sga'6:P7R6Lw-륯MJJeK9؅^MPS۰r0s Rg iTvTvVDIugL]Qomz8}z&IM%y6?JoǨ9h#EˑP'kً3S7*q1,kM>5Ry%dG]NQ7RS=Ú*{u"s _,M,=&^/}^۫"+-Y&Xb׸q躱h9l\dڑP u|_Ǐ"~ԑah"BIzՓ}ΙkNfĜr>s {<ko{9`mY/mt[`1m>[+֤W(gz~ M?u REٓ7hZ_XI˖*aͶNʶ^ep`J%!swzdB 뀣D I( }a #x{c}yNxZ5mpy>P" pʉXhWrxty*9 GULQyᜳ+S\g@ϣX._KAg9h]c&#D@h,F͜ [Úmi7uʾw۷nGY )?XԪoH(#2"sYpӹWd}UkTr`\.6*GzlO8h:~ꪷoooZB l7}-騘Gx<ހckLbLo~.ҷqG o)qi6fFT1<ҫz'f1wWqmn f|i^5oR:WlNP;+ߥL VvD1@%D ( 5w>;^)9}x{S'F"~JV}481%TT""pM冰9JYdRL+DoF|5SYny+i[Fe-E9U VȢc@m~ 32CYVl{_ɶo}2Iei{`?#V[V-4#AggޒRWUɳcG[^JFGUV@5[R|x5<[D(67*-id%t  1w X6FGuw{Dpb=3u>:ES#W+cnbσ" }TvR{&>Fq㩳W?n^ĔPT#"хYWٖmӹΜQK{yIG,Hk2DR QwRw}OqozջmU T kJlADER"!b$J+\&/e*TU 6 fS "BQHg~pg0C3 +ttu2F&}S#őp w"i aLDaT7#U ȹ6-2)Ý&neZ. K,B3a!(ĐRETqK\eml0:\ʴB!6m* Gz8u5OKDt\!_eE_R+ӵ+Gfv)FP%v! cw*p/A- 4:Nz4[ިl"}#ܝnTmN{&ml2>8>c@Np;1d^EN\Q #fudk""I;L$okAՠĂeZ\)vV9&N^@1"=!0#cH5a j7ȶm*G롲DۙuR9&ZDNHm Ï?BM}EIRN9$a ܬg-< 43mxpNNrIje{0=07q QV}ufouyL&,R9d,#\.i*we(,Q- һ.XJ;)!TƦgnR8-9܌ӷAhMJyqюiO<7.ch67߅Ɓ0i2R3N>BZmf#5rèH[̾Wx *-5k [pEG盨̬uJؔ*d'{k P#mۛo2r|q|ǔO{< [&DgwgXE(9ጌ{UսOu-K \} r^I]) Xd@GSʍ\xQ?Uzvj ̇ΚnW ] B%f"Sv$Q*Cc.|>уͱu$ZL{rSf2#x|(%@cg c{q̆סt$Ak#)8zƩD5"y@gSq t̂ {fyF<8V*  LZx@~afw3kMaamۤw[G޻*tS<;K^mr>xQ_.o޼y;>Xԇ&NH&Mnf Υ &n۶Nt:域Nuϰ9X1VL ^Ylگ,U ,cJQ;{w|Uk^ K~XiDP"Y&7C '*ҫu<kd*o8*VӜXIQNJ { U'<_@kJyw_~!ZٯB5gƟYK$d;hz 'H^0Q|CDD%mlUZsBPa~1=CQb8JztB B @& {@H\#yǨPua4ܻfkHT?B%{0)SeV߂v͟1es Z.cXbz^9gtKElj?nd_"T5VUjeQnr9g+/DUQmEΪ*ʈn///1-D!Hwǯ~+Ֆ5ov#8>ؖn]sUG%9CfT,̬ݻuم) {| '|܇c쒹yr"0qoQI]*6 (]rz̟,1M699? n8ObAV"4*~+zY&}Uк˪6Z 雴~z{'?Ud) &?ZI4r'1l oEXdt{z˛BV3@d߾[f|^;̎LC!ÏjPL)V@ᴈd:cbk#DZBflՈ.GIJ%JA=Rڽ1N2FIRE=R-8o"dZн~:iv>dYgcύjTdƃGȠsn0z?闪ͺAFFӰ[3Gl&Mw7 fakIWy'?V8>cz8_岥h5u3V7yN`w}ꕺ!J=v_H53Xpt)>!k1QП(D2jfAt ͏2MJش^U+hi@Iu Jl$ʡJ(< )jS$I2xWh[8/%5Dy5a۶|N[dRr{DHT],Dh9ISs pXTU*v؟ow?HD\$\w's"sG(CM.Eʫ̂Χ7*qx2(؈0 !4XQ1fs9BAY7 BBKׄ>"$hl iJ7TOv uQ >l2Y(1壸znbp}'m "d2䋦`$F$NM#۷?ɗ_K>=\.*EYtMx`K%½W&Ar P[+0,ш=z'k~T@m(jZ)p_2IP8qD?e)i^嚬8:X[%r#ǔt:ΚKn)]% %~[U%EXf-?rK 'V5,9q~^J9g[ t;&/|a^)u9SLlU[PN0j:뱲b="QC\;'H;=lI Bɶ01Wx;aiv1m$IQѨ@dG>]cAeRP_CUVVN"rTTb?ᑾBxp ǐvyޭq5*f6m}cP_#g0dH$f$Xn8:Xm۶5Z@G*`4j"5U}%hxq|jmvڶ́nƷ\\}A!gڇ}zznRdNEJv2#$2wK0wGLzC:B&< j@ Ŕkn(Fjmӆ˫1M\Wp;[X5]%p:Lgs±2z<,Tkb[z9q yYg6=}g-/q@`9m74X6C!f&, R}&<@\h@ ۈwCHWZ)^^A_YpIVg6G#)ļ,tQHXfcrD9'Y)\z*9?sw3 )w+Qr2\ʔXG]9^+"-,X z>r~3C(},Vot$]_ ^%vS[^[;I#j"qXMb>iqYU_"&9+emIjw[LY尯YHeyg%WVRܭ@x1Oq .GgREF;oxæ_ymw1D2 MБ;!yd2SkͶLnnTϱ\5d\ģ#F5ëAŹJv#| J5xcIV΀EXNLjpi4?)7"&i啯0[tU?tc0Y8Bݼۑ4R!oy"i9Dڸz*o2̊(^M'k{M-\:/2^T+fE#nP) *p x,>qd_ofkJy )D"muineN_|iۄi O 3 2{N.UȺzS(7sOVWMÒ n =J51RGMz;1:毈X+F7r$j%ڞ2rSgD\W$ 69qX7𛣲AK2 al$)"bccJ5nIk ] 61s<0cd8%zA,^)앓Nl")y mb`}7`( Tek۴gdxc^enx2)n>PzVMKDmu4{Wuf֠Qex-ʜE߹B-(Ľll6uQ7o| {7U i| ȓOx:3;!:r . Qڜe{Hb-n( N&x'7|;F 6D3'5#m)bfz}mElYUxzzz捴Й*Tn+*Ƞh4!a>-fsG." 8/FuM7=N 1i;drb#yx im^;U9;3}"}7G3k~9^^~r׽DDh efN56;X,fƐY(R!u[G8aUAӓ4HN5kn89Fk(k1+9XSklx`,7-)qOc}^#04pUaHFYO!)mU# ie4Eܜ5D Kz.I scp:r6WrMȶ Vs0|Y`dהjje(1$=e5߳,I{ML Ur^En "X_eCI`G]ܭZOT I7wHZK>ʙHB"z33se$4?|qonֻj=IWь a R" ܶ|.3q=ݮok̂ wa,C8'yx(BW f}Z}m-aT߼MQ JKI9&|qn?J:k#y\u68-\ȽFF*E]t50OKjk7_Yƻ!:#sR-UAo>;{G-/ 0NH/Iܭ[VFϏL@޲pcH[RGsnݼ4 \G~> ۶6,-Y !=֟8>pHY;CKM+ϧS]Dz`DDŞJ"u-r5fPRñʷ FQm7|/  " [j{S.ʄMh.]>W 9ӹooO 3Ez@ %<?-~ }PzH %SWx[|cF[Y,ޗALfE;~qywǑOp@1WocKocFm̟DWjByv>.9ȃ79H~iTSwY sNXFT6H[r|0*fg1pw3#jҊQb|4H0sAj1"$"-(Q%Gw9?8>2K6BZK3nUޓNIg{ + Dicw&ΖLSM5̇YpL|i|d%o|D5&W0ng` W~XYkHJ=#Kd$ht5%V Gp}p)H5B]IހfMaj$5M-{w'*qau5מTYm[_Z?ԝ!w]WЏW,6QW45%,fΈn-%zdw{gg1ڣCy޺Hav"*-Vs12@;B8:>Q?Y;$>~}Z! 3ͺʖg]ܻ۾_ `?Mƞ*y$2G]㵼}q|ʺ(jgZxTLi.3afi>}x^o߼imF:\҄"@jel,furJUbr&_892V݀ y\VpuM0]d|knF&6cg#ڝ"JS8^ףc%<xUV'~8{Mn:"dEf䴔Io5+bi7+h)3'zUSXőHtc D,-.ab /k  Z {jb>c*(cQ_7 sڴlE71*E1mnYm>7c$Olp׆~ zh1jQ zʛKSU=zjϪMIAq㨰ZaF˻]=ycVag'#r~9͍ )r- cþw щ9Ĩtg>^7L|%(g0,1;PKdݔt\s:y֒Α`͔&~$:Ix'QZIX2;4Yb& od[rJ# "0 Y@>U5ߗy3+} &T)Fu4? [&s6 n)Lg!68 #1SF T $9+_nkGo;Q7_dM`lpܢƅk^G^/`^cX> iJ؞JĊQ) w)H)*DAI1E=ܓKmw]Cgvz+pr'չj vjMIKww9Qmn{k'">n2Rxx~:muo^}Ov1f~9yy~voۛZcA5D ”AjFFTJ6\K6Qf"m2ىKM)OTnZ;F@({iOVچ99{ʖ&**R!"MȼfKbP WIADHYLYXx%4"&7 Ի6䚚U9nSF9she!̄;F N'ř 0e\^   ("E`.ID@»r&3aTya`@tkxrYa"Zaf> ,Q^Q9P2DYg1TRCT'm;)WMlέpM&"##Н0RT%n:rX_YM,BTT!NjFJ/;"%#t.V򔔖=pΦ^ͪ@ԈNDz/~/>\̨ń>û`ƲQ/a)߮*\YCeub8AV#൞F˜٣U|c7fCG@2f ?b6Y O&y1L{M4oMof멸`2gk3//_{hR[SifZk/G%>qJ]a֚kIw'_ cJݳ=7f oI>[f$l.Hm:ʀLׂ!;nVK- R`N R9y" ?a8.yxucIIjVX]T "),o-JpGN5G#jV{[gg3b;"ilk0/1058D՛1n^鵼Y7[?~orZ0RǬ(T4xw7߯{-@nvzzy-xvY5oCo߾wv"jMXG҄)odXTlp=?m!ΈB5 }:8d7п׿ 0hΏ;l`"r:[S3Nܚ뇗뵻Hkpi UY~?8>cY{wuDs%*"\ UJdH=?=ɺls?HS@G<ܐ}t,Hْ"*9\f/ңtRÈ?=UOBYG˪4d5ORfHWF'(ķG[Po)X]טY dchZQ+4lvMFҡ06$=K&r BfU2,@}/9(-%$鲾`h,kWd'kbVfyCHaH cQceV6[,Np֯3HTI&~&ÑTюtV~1!y&&40"Uy5,riҺMipJ᪪Ik53GCI9̓1.GyI~U"E\D&$nT%sM(TWӱ5 F^?ayu\`Zܵi90cqy{\N@A6 }m%̽b;BHl#ƽ6}\@.qЅe鶕1[O)CJ[{3$wϰT :|(M'VÌm;oϗK  κhr\.3<zHoq|9 %>\-QJPB\i={fSe_TS`Ar-+ ĻUɕ @(Wq lE|D~F_^3ACqGQfvh=÷S;BeFDmo_lǐ$֚X*!/- x~_R=JJ;,=n~ޚ{O?\_t۶=bQp)5}WZ sG_iV^&*w}RCƞx2N[|92|-rj̏vGKb,5CE%7Yg]bo'4A.Uehz8st|Bnv so#2Ĩ-'Yv uqFx 1%EQ#Vo +B&4K@FD Lъ2MG[s QWJm{z[Dͼimy^UeQ$@qJ_8!Бy؝25ɸZ4nXь0\G#{e8݋*˛:O.@2^0ևu &6fu/"i.]}dsV@" Lh?ix2`t/饐nH4Ng=B<(a0~ڊ@9A'=-?}'e|J陸oF9Szz'[n^0d_޾ͯĬڶmfrrh1s$ֶvU{ dWA z"M?v*-BUK{k|_|__g';0oTU!Az.yWdzkpu(˦T> &Túeq)W DQA)X]MCJ9zJE"@YoO Mi>!1k%FY 1tZQpzMR5s;ɧWigB4K+NlTR?J(tQl&+2.?uq{閾w9‡ LuIoFg3Mp=۫/נ/;mhMk˗{lv:dȶx|"lg?,}43q<)/h_|Y%bwOo!Ż @f̬///f!<iBr̖\,//WwkmӦ3cx7{%PuTUfP EJ-1_ $ѫ?U͟-N3)3l)&po9 82d~޳;NYHT"nKs"pzX* e{DlY (#[NsVlBtKn "pZc;G7s,^6o$Q+@AjXە*vֈg6mDQֺP( 7f uٯiE! [PD/fiIv\ 7h0EL_kfeFUDvC:bs3FH2/ ^8T.cg?sE"6H(JoMTYIsMJhMU۞VSiY&Þ?{o_~9[Ow޼vyw*{./O;iT"Uh_=KnxV\_yf2 R!*-[mWmI(wx}?OWO Q@N77w_oon__#ܼ[7spY'Ĉ8Σx:ы 9Q7s.dM mT[޸]yOtj5U =/)ڶ7mS-K|*ѻwZpT[na4lv:T[S֚ fc){NgI IJkV1ns*vj* [/O>U2N:&&Rx7}oM)╆)S#\H9CA2Sz7 RZkh28`n{֥ DHRϟ૯oɯ{:m|湲6p{q|B,ソ//q#ުg2]eWAOxBH( @$$LlhGؑ!zlw]v:s.bqy{b!Q!4Bۏ<{fC?c.?IaXDXsanwӘ)__~nnlU-sUGbk*bΟ9gBtL\"fCUu=O<ǟO>Q1x`!Չ TVgcQ:'8g$2(lB[LcHĺn93q۰F^._$ ɄCwU5g!`t0jq{ &BIIYXJbO12(XĠoDUVfaTfowiHAUij=""=Ң/¹tjѶI: mVĖ6"W)u]u1ƾW>|^b 1)wibL0[腁Tc+X8Btg~Ι< >zfaٛ-ʪB4r(PT9u20 ]Yu% J˷]iRo_ @0;5"79Ÿ_z3=}5 |g=g?VUsi* l=FO48/^}XZUKHqN6",?aK)%Urvab%>n"n*b0;~nDaQ&SB-g985ڭTDD8deeaDf`QD8g/hTlt]uHD%K1_^dׅu(ybjO S:4H)cujq"~DġeHm?3C!RS (bRD]c 3gz3PeރjNaTt)g3`͜sfal6f6M9s 2:enjLb%4QbHjZTMKwϺ`\Bsm)-4Vdt0sMMn*͟H!D14!u yǜ3u~6;l0KS'TMkAsneRT%4ՠp ߿wi8Iha10) B j`^3vf7nvcE( "M )&9OGO.*k ?i'ӱ4N!E E i©ED|V;沲s}aYs_Z+̷ B é:N\APx ̳WY&?$WmF-Y ۝͟Z#n1XrNbݽUh5DoamlU|9"$l ۠Cz [Xڕ-\}Fnd V9:\\.z1 [oA; zS}-fKMc)cN߭|EEa` fOﻔ;&i9 d:!:D4,wηk| }^ Ez /q4cCOD$_}it8@Bۧ>3do`\ 5ܜc]uݡoQ6ѣ|چ]rUDOfIKFco5P>q7TGB4l.nS^'~LPq&MAS,zXRYG1w䀼v#v]i1xmٗ ^Obkt03@IENDB`instead-3.5.2+dfsg/themes/clearlooks/aup.png000066400000000000000000000006751467622671600210360ustar00rootroot00000000000000PNG  IHDRsRGB pHYs  tIME qz*siTXtCommentCreated with GIMPd.e&IDAT(ϭҽJA߼oD?`YJAKDAkmk JN[ BPEF !kTx`f?yv2dOYKw!ۨ [_ 18M1ɐ|Lʍo2\nnsW" ax Řvgkjr^a@k?eR;GO9ٯ`WʺvTHlWI[E(-t# xXǕQD` k;o_[@kGkR0ziv"(AiVW? O`A_eRiOILD3M!<#_?ϩdڽ1N~r~'|(< G.v¿W Y$ݥ~ 6gnpdA?eRviE|Ց֘ښ;;Sm_?fS=_ғ;Dz\4{^%_=o{3^ F]YW<dQ\ڟ"A1ߵ|+J ݑӝ ]I!JwM~+A~׸r??Q ZrG ˆa7m>+3Uڤ$ @տ_u%NH}J-Qp&yR9dW,L\`Q7Ջ~k|OG~O>![CP u{krB_tMڬ'{W@(NfjWM{0#vj !}}E;i ?|o瘑_s?#TP ?bo·IWr[ Tvj<~:hT8 J-Οq#;KψQ?dP#ic  4܄v#ֶpL34oO~todN@c#ӈWa sX Lz|C=Co7BGopL%1s)ޟ~^,"F|5;{碑_M|tʧ=SЊl?8^\TkH@m=O  Ͽ*M1 9 l?8;_ ~^@"ybG*m&hI,nbo)ޟdPA TB+Vb{qoO~sd/PK[P")>K;Lu$JO(:SoO~uo'0{k)P7ڥz+c:EtyZ)ޟ~^G1Њշn) }M!z2{c$Vd/PNl_OdV PcPl?8 5TEo-lvn>my&z|C"znȬdOPk E~@'TcΨ&TO~po/c?^޷ Emڽ`KNZ>y$|C-ڣB#Sa_7Yqw֦jqMu#zdlvp>Ⱦ0>MN@ƢtuɆ}i.R~ei#xQڽr){g>r+Wv u7O~v/jcj=C=sX-+ ѩIHMCI g1dP/=;SOH&j.nN*m|WsH$D}C&?{E~$`dtS $)R|W+,p5Q{v/P@" 0$]tn?|Wog8;[IH{G2z^kokD:T~Ԗck5{cP{|=&gY =~[2qc+Gn’ˊ#9ˡۭG,m2(ڃ<4k04Am$4]h$N&?: ! BhqV򪇋`&6Q-怱`d* Q'҆́TŁ)'Je!DzGjDG=L@P| I,\gǩE&czFH`VhNL' ""D(MIWԣ$=>UYc2j ?Bdj:l9f A;0D9TT$X4NS)8:j\0FղNh1;!81K& yQ=n4 l:ұ&&J36MHzNwA#^}L(z$2ę^IGUTdܳLPYrjy(tԈYMd>DE.-E",jLQ#փ$~_JdفCMJ\OJh%xqU$DΉBu 9M,PR7,'#4m7jL$D? (ΠcAQ.-hfm:jF⫦,D'5TMyES:ݨ [CŦ}fSrP _$@Q&}P9b†4T+eP7Tͫ<*>"zyH`C>>֊(,Mq6yU*.HV9Z 2îՠ qBE> (i-ͽp HGZB8 <Ԗ[of^PVd˜&UVK&nx$ >tA$EsB^Xճ(QARUvpì lA@,2I"1*vGf[g1T#qѨj2^zaEI6$5Xt8M<]1+ ?ͩ[CDg2~FŘni#{d] FbE$H<ɬM0 ϙ X|r%ظPUW-$9j ;F+c4坰̈Ñ]zEh @ǜ75"?mI=&".ȩKyXM/b<ݷQA* Q;Ṵ&Q. dMkH4^n!(bd@Qk O: $2֜->gW%ĕ15*\&1ӭ(L.Hu2 Ĭ#U̓jbIϕTVd$BqNb<˛fd'J(R2(1DzG$OUA3#ߤ ~*}U]CsFsW =FP;Ձ AR65lP Qk#EfTE;*ȚBaG2k+'Bci`( اn 1sޓ ˩E9iRn+&1󦀠3Y;` dr@4<bE"pn&Fr*вHF)4Ι5Z j dQKUX Z h0w`b}җ8OJ`H3@qh*|Ǖû` ^1@.]6=KyY;5f@(5lM3[)&d2,BRtŚr PQ` 8o֘3AƠ^U³XUE$^74,H) zR]9'S3\VԌ;(6{xb$x@hЊv,<4"Rb37QTNZ]t)@2VLQZ6*zj6."h݋]UGJߥ 5ڭ<fbZhc{0mECA v~QAcSIjxb}jɣ*|Q!Z@RNFh| X̡0UC1,9- iW/ g5fK-AC AC:UD=).楨{`+ J Uoy ~z7cv~amf?RUU t~TmY^@,P BXfV8Pzf1 ioP+410X*aAMO4[llPSe:Ӂ&χ43? C{D 7)A@҈, =ٝ LXC-J<ڃX'cF`lM/Ap!bPXM'*(LC6̌Tʭ/;WP1@[OQ聵- S>T%A"g"XdM!0#5!C0lSZ|=]gwR6=1a۰#Ȉ^MXXVDP~+TuPķK vSs1YQ3NJMFԕӐO3A74 QyDA,;S94i0B&i׈e*wJT3@'xQn6ta@_h0F#@VP0LΞҨKBU]@("wTt`tA y]EV"N֊'~t ,D(3$\ Dy.@irnl0Q|TKAFFbZzjT1er9 `Tʠ @&Q 5P.z&hDϞk8} z>ZJ[unzeb-Ԓu>,U5;ѯz78Vb'&IVn!XJ4\:&Ƥ:RQq#,Wp,P6tͼť@u*;hU# |!J O\( KUT"[Űt-9tX`{pJ)A4@E6 Mi₁n_/#ӏbS$z@at#L4ޚM2W 'F;J4ᎣVAXםTGISVZutF IFYH| HP2!ʘR2+p9 '3H Y8ciVʑwNTho>B^P`!LP>8zS.UKLB7zu`zn*+Z$ZXMǕT}+I0OJ(I-|3i, M7.DP?jIG4fRChH"*yMc Ӹ5Lrp*ĨJ@C ,oUu:7 61MMM]57(e* ͍oC:͢Vkf;u!@GkzTٗvd`w!b|Md*ww2K 0mE IR;;ہh)3ň=uPUYW6Bւx >TH݆ lb)O:e!X`+gpkb czd&t֟*%ZTaJX*v4;D^L’<!Xun@!d)GO(ň^m@( 6EMyP>+/Y](!Kʾv]n¨k:3]Tn,Ml( C XwջRLdҴѴ( , "Nw2h_NJ ohngSpT Eq@Ua:i|k"7[FkG*@J,Eʘ^B@ŵN/@zLq%tme *Xݏʁ8'$dZIFX"]@!@'u>32zfycJ#Lc&fz2cb!ljjցlF7[NkwJ@B@0#p n hv)"#ފ*AB[rF['Nӽtp '0P$`- mDAA2Z yVR xzX-AѱLB6 6q ,@dh YNΤUCaOӊ[Qs3D]&AOIt !ׇ:jlÝQwCCA iᬊȠu@ bs,2ڒ,҃3NCAhFǝĈu vkxrO)+ K)?*'T4ph$;tƪFQ[*dz:ɭ_V;@UQrQsf6Gy2zP4' dbjC^5XH5~zP9m6`y\ii[Q±-V\g$h $ɦ'9IE'X]SۈmRBw3ұpUYQ$"üւh!8mnq"`ޏzKq5

|iFjװO'|{5,I<$ǝs^M ?A] E[ukÐ+$d荆:ErxߘVUbA uiR 2v zI!s3"gL@8ޘ;㙥bDJ&7Y$ "2ꕟH$%C&cRnNdV8HR. dw31 qMeV2&@ړVMEӜDM@Eb @0ۋY@6TwL((Ȧ rhHX`F@F0"qf?RV1@Ox P%iCCS%jzuu*h2*3UM]L;S y~Gս6I5}ީ3oW%TLO>0N_:$^8f3hSYTYMzCÄ9s*E7pj)>,ǎqKDyՊ7,꺀/ ",?3SIm0ͦXi1v7DL Uiaŵ$Z-Fb9!Ty8.|"IwTeqUO2sJͨ=|Sw9sSE[Eu#;4Av7Si bnȓ',}ցؕg-"ۏM%91X֕@4Zp@RP&M@ ?It!򪏰Rso$[|RFJ4H&T 萗AH<-@5op$Ƒ`Bn<[; ]:jʁvTi9P'mEh^~vДޙIUv ם o+.:`Mni4 d7 1ޔ &{SxAέޖq Ӓ}f5 ueGV,uw+\?H($;&EEX܁% sZE8R!L. 2zTY)uo_>ΒY <'&#mh ҳ ֞vwS4d7*9UGq} 1d9WB70&^t|+qgKjJpӅRĐ;*[X N(#⬄rmrdd16(piArĴE@ӰF$.sKZРgUF3"9#x3Bwo/F"` g:hGJ[QC)Yzo[I-Sav(*r>u1WF[MB'mXJ#wo4:|Ĉ&0qUn(x i9 YΚy1Vc.ґ UNM JVAM1P5M+wOr6+D.f4v i!rhI`8R}2xSfE~FFq̖Z%ӵQԾM"\OCXZ]YlQGb y.MX;Q҄ހ:-+qZJް:s u3DžGn&@>k u5{)?m*3wP-U S 8Hδ75Y&H"6-ǖiXP bk3#CI@2zU2̜r"`X5 y0#~t[pG/9ib\[GP䭡cr}uHʃ#XH"d`T{}9B; ""v~TB3oY#QWymjX 2)i !M5{P -Nk~,;Pc%"}[nc NyS nf1m11B 6j ߼MA܁h*H@)Yܠr-2q9dK/] 3BCm+% \[z%*T}}@U\Ν8K\ئ~Qob⊠I6иHum=M8vqH yV9s<@@AwRi'@  mt@Jf*A#4u@ G8* xE3P`Dco:e8i@XsA2Α5CMΙdxҺ4 i OԴASiMQHI:U@ y9uYtzց8$V]:mD\ , *H&"0Ahs4@nj<*vu:LZP'T<ա1VU tI /vm4ʬ|1baB`Q#Dз>k\ NgPΫ;ɩJٳ-6i}`LXsHrܷQTeP89ړ93  oA">Ya+ OyE#AEBk)F67@j;+pvڛɬP-kHu.&ђ r^FhV* ڃ}2¢ϕcވPTޯZD"a֤A=PDqu(9XŻD)Pw aEaMs:b|ڌEt:i^֩GO45 q4Q[e}fԩ nCz .GJ.i>#Q `|*m1K+m .Y&#j2CqkD)(ʹbdX+4S:I7᩠L3AWkw_ X#o]sjv@s@)K{-armUOﲘͻrNk% m1W/젃װXX[̌kRE؁*$u9X&8s:ʎ#>!MF7W0hΤ7mP{ 72 SPGUVsU9jlMǤG_N+s:ւI$ c#aO 3h`G:F q+]h޲Fn1@$AxNE#0`-X=M[;48p476Vf(>WP0qb.2b].b 4RL.#j?jUAYW$h7`P "kH2n LI)H9iۮh  mIܑ#:p`;ҀL@H}l$v d^ת@DB@ڼ?[d@j}Qu_FIAQ-RL<(MA0Чӫ!r9*\)dL'Μ&/ h"c@ -k%B9֒s2.tXOn @w! XHdlQ{N;j "8S.pEfRsQa]@*z: > yҨ xWʃ ݶiF7<.XvL!2Qd^EqM l?J5UpT] b`X:3@YZ@5 U<: Rֲ.@R˖XQY Ee *4-bH&nڀR噔Cnk& q* _n/҆k0ӵZXS%juV Ek ˝9r[E"Ʈ#xnZ9o<}#EM ;q'.FL ڌwzΚN9f(} >tz LL,G]%2oT2* Dӝ/w n-AE%5.捣ts%D4YJ#P[Yp!.${ZvCOK$4NZ]@f]pMfTbuxېi6M O}4oPۉ]xc¨ r!1Z,ӵ-mLdfq֠ѿrBV 29$lcac=(33@fS*pк{2(29h\(2 וA2FhkҖLt֭4HwWd+[1n'7n#jr PTSH ƨ7E[77`* ]"L puU O*ViaZ5^<)y@fkq9lOh2y@!TnQ&I cEm <̟ҒY ?tR ޳H_K餷m2+!,-#4@0'ݥ(a΁Pa$vJv@AH=(d^tցA@AQ1H*ǖ $_::S=Tt!`*`P!X4Qh*'I)̊Eu-QXbe*: t񺚨`P=2$\:T:{#5& `d4:PVK mkGh0vo@%fZ䞀UJ^ҹUH^Cz). JjPlPv5Ġ/NtL f-DQTϕWcsBQY"o`%֬::|@8\#Hi'=(a5HtNH#LgoҲ@sq[RXtېެ oAY2$nFpxgj ,#pM1*P!q@kwehhW0 0j 5@Q@$xt-f ˭fPNk0x tFIS [Ʌy rV~,j"M(U7,Z0BP.-XVdT21udf`$AtdʒFǧ΀IVoX1E3ù C G:eu .u^~S70v |gFѷtZcn](Œf7Έi'*J 0}4 ?3aޔÏ2U YruT?Pa∕^ZaʤArR^`Ys`9!E=sֳ? q|(ZNߊAUhˀ&@4xma$cҴq!(eVΧ3Lf  Rmk;)h :sT[iU Rȣ0Zs…Cs4ᕛ?*L1EDP0HX%- yT؝EK2XJ1̚ I!d.KF$2ލ[!|b j+"peP[n`i8:d;PKCu5tɺ֬-L6 4Ptu-Kuͨ!TW BGݞ膑1/ DADGj(vEe#E$k`rK+.\nU{[SO߁TxSa%z@5mKh]4c@֔2.ti33Iʝ^ToGTf2JE10aRs.0:Eg*J7 xbx&J$ރT$O֖QR0A@N o*ŊROd @~%KO I>7ނ'eCzgʖ|$wʀWFvTyKu ubf |X HS vn!YX}NkiP|[p܀LDfM7I$ uXW$B#f. 1$%`Hj}\0i!wɬ@9&kr23Xr$Ccs\A:*&c;#Cap!S*A+'#=jRh`yIȬ9[;ާ\N>E2F? -DoG2hcoT #~ʤgxA)*B J]e#sS+УLT̈15-0XHx޸= 3*S1ldb\W=#>l?z@T9vI:MOIE :ξ\sg (E0wx!4 Q ªX-SYfy68@W[yP5DŽXO:^;iT*ZH htB743n H_+p]̚ 3L 5 ԑt}a(Qm+FbhzʹUO{6>]R }k d諘 :uB!WʬNΦeN<iFf*&qҨ8icHY`G(l0önLjѸ#5C¶TX7j@ f3LE $o*(LB_: hmMn|y-&6LI0 c48cDȘ(!ME}\+@#JʚI T!&wK+3z  AQF,m4E $Z`do5@dDN[yQ!1i`IQEa&O΁q4$ER'L 9dJ['L_./EA dx,.#Ej8nYP.i2*hԸ tlIdʝUuJQt" "i'hС]Bm?:ʼn_PJK o-3@*e URAQPiWɦRJ.cdaVB2Rds+5tU\i8U@xI;oʐ,^嚧u` $؜)),W5LjixHgw:Kij6v~c4mNδj(kwZm*tTVZRHv7.?Jڷ&5-E`G5l7uZfT ?Y@n5O"qKs:*ի8R{dždo,[Y`Ҏ5I |6IB3D`vLPT&t^34 :POA WbVtGU⵴U?e$=ظx1le Nw'M@AP˹a%4Ia`Ҿ8*H)-MQSu`[ΓI, ˂ǠނN5C~ЯOF+e[LnўfWnA=*k'X`(1@T*ǭknQaM(vCրIԒy ,adj=Z4 ZG0ZnP'5fwn"j:ĹdZlDdHVTfZC$-@`7<5pAza 5[' #AÙe1LBtURD2)-5)ʛP2}i_":S2{֑Jb~\Vb|f&OF|@( +(⦼FROA+j>3$uV2qX˭"TQ"`fRAR'p@A- S":mԺ(0".uȡ+`B<8 K X-hPqFhh J`X *ЀIu a8nf1H ̍NT d(5"E?}3PeB7<8$[pAְ`kQ7/^ϪފYfGY&r㝺Շv&q?ҁ*|*uD"idYRlZ&:k3BBwŞBXc,W աg$urξ:lQsP|Z WrnP xsX@K6u7++]Ů?҈}Uf0i4Zjk gL,;s"`!ݗ+9 W]CH9_TK ݡiNҍ.)Ĝ>u ޕ%b # ̅J(5L@t't XΕ+YEd]RME+huKI DO)de'E4%o9t # Y4MZEJj7Ѣ\xwLg7>)h!RZw4{Lqt♁ X{f?JQT 7P'6Q&pL1ҧezCx袲3։`P,{˘87?Kg@L=[T"iI#Q3ŧf(-iU5mKx]ʙ;^8xLsi443OH O(gs)ISQP5˪'DKT Jk[mchF4)QqT+G|Y,佳.&Wm9'θm÷BkԞ<d>"s˵tN9W1쬟ϰe$dv*[X1mL ӕ.L;2wkmUⅪ 'SHSe*_,P˟*0?R7{U:tܰk9`R|hcMJ<ᩛ~᩿{734躬2ޠ/Ψr_)a}@ѱU@0JĦOQx.-pK5MhkcsTMo [Rh$'~yEXhzMY? K=&).aM;V.,V̇EB[H<ޜii&abu!]m#{F=CH:_u)n5&q3X0>YCCxP:B]nL,m[tZo@.yu\ֳJ얏:UEDxΞm[b֩ Z n' !X(Rlmqzf-67}9!m6Aa qTdFƙclBy3AVb/Nt>W(ƟCX.:ܠf]@xY?sM8H۹4 ⴌTOiE嬅ݝQcŴm,SPy߼lKa ~ FFn VeZz*jPL|YƉüfPoEenWfU]@UW AMm)Uf*e.bBh< ._J> 毯='G4ɩ.Vy5+E* Tj-}A+u1RnP\r$dPI:ɒ6YZf@T<`Tʨ[N!*7t:P9QmFs~u=M5exzҘU+&A+JM/>++1ʄФ9<t L Q'ӑJUD F:PmU8؍!USa4@ɺD*̪5-50bP W\sN`=i 4nR#@+1hU 6.dhH;yhu&)a@IqmɩkH|J_?JP:V0Cf:t}?:Q6({Aw9d^Q^gW!VD5zުiz:dڵbz4['OO tj/UVUdqsQAb.ޔJ"G+ƧݶŊMfgLn?Z  GŊloV]0Unո:U[CRPy)]Z<-*[ͦ`u"rWUh_+w<%qjhAcOF!YVT<0cꥭ;Rp-b*Z`YpX&z]R #ޠEu1jb4 Lwbi(+n=٠|T ŷʫl,. *ljʓwv_6Ԫ3X־Ŭ4Cjpf*[{oErjW*YP vppJԸ| %M3 xՅe BTȩn\]UX%RyLU<~|TX'(f k<4"F7\6+ԝ3ơy ۪>* 2//g`;V?yb]5M憟vZSJ?(>Yfj_'IxUN幙V&E(B-P^oS[tҙ{b\E>2ژZ|0mEo<7/wՍ1l6L\!o>!5XT[Xi}缰o+GJoo,ZQiuLu:vpmaZ޴.OҠ[ \B? ,߆''ݬ̖Z{Fn=%"5^a҃ CEfbOS]$pJk5 YEӁ^f\/ /xp1"-hmd>L-Jrqli\3h TVX΂ڣO:V.Oe;օ%Uk$s˄.k"vv]AV־:usXNx#@+jj.Ṹ eA64ګ";^@Vi<ڙ@xRLkG fh.5Vvw&xn=)oeW)u_)VSQxc{u'{8f@E9iܘwRӰdd"|I k6ܷAVV&)T@V3׭50f V܁0(50k09Ai47)?m5'351 @K9< LG2QPԐ*0rFdy6'mA&+Nu 9ʟPA,0 7dzԙjp`;ѤNzEH#<9rYQ9 .Db%wNՠp H &#:>KuvP zŢG o U_ַpjĪRU洣} ~^.tu}3K? xTOonjwi@;j'8[[,|"lʥFc~k}"K|BiMdžR p9ӫ+{OnbZ$㧕3ʀ ̈,ɓXʖ~!ցb 3KAXg5Hw75E}(LU-;&ϕ 1܎T\(p(EL fKl`Q*&(LGMҷyTe?Q AMϨh!LYtLtůFEfbN6`@>TC`Wh]wC30?Z n`2*%,{̎F2cNI1KE-TYb3hH63&yV,CHau$HAڙ1u]?*8`s;P$ iA܌V 1D) 21` ri ` <(%+,_vj|KjYk\ۍ_27wD*=97HhY7V5-E{ME, wn4}m7U),׻eHo E--T ګjMޫ´U8~iyV{5ӻ@dGnTX L)AƫsZP(f_U^2K/m=RҔR3[Lڸ Jb~B[.dj[sh)+uMf?()UMطPz*gy497xS5UV:Zj98QJ|4L[J8O4|"ZK_z%hFT>u{) xy*^}Suh*M+|7 ^kUpimHc&=A4kUbW 2-ξ~K@װ1׊2Ge?uԷ] o8KY[-[zPV1,e`*[n'6Fo+Teo*ܨ ƅwYx ` yږB[M5{˘os2UU j"pҾᣛq/*f`)SLn-RʁmQ:+mQ:Gbo@^ tT'_wpY{:MMl"mIZAm%feBh(5Hjq 7SU։A-wvWP5mPYk[-5MjRx=ER+9_Hٯa57 }Rn8BeY"LαBq*aM;ȟHb+N[$ 1H$]Y!L(pp9suGm)Ԃ$bڦCH@0GÎPIV D3P2toD\zd~T !+p%(FDEpLA;ӷ DJ#gL{qH+ 7;'azi\xvzxa|>V 4 f@K_ kG Y::J$cEٷ[䎔d0lȍm$_*kx3@AbANǕ'nU`Q#i?[(~F`Py>=_Go%[Oֶ g{ި#"s5u"ęF)ŷMA0 MEL&UyE L~,SZ4 @TڍQn=+ZD =aFVr\P#]6 Sk;h$T3jiͳ@mV) 4 0ϕ%w7;P=-^Z X}C7f]>+7!OYG]}630u^sXmKڀia-&i-ӡ59zk!ґNx$[SF]`b[QLCQ:iʀʜI";dy(,: +NvR~FXW@|f?H=B#5OTj@Qex-Uf)Z n{V2ÊU Ś ek} 6Qk)[ʘepP 5n-y+!]}ځ0cqo5kq%PCiAt\$@ὐiDw2 rQM m qC+,|6|yR1'ݦ{'.9oӕ-^BiΜaLo"QJӏmeYׄ41645q[T/=ڞdslPL+|sjOt{͘.Uчri5[!Dᳫ<ӫN:!XrVF)Ysj LZ:%w (E)#MAS @\{G!T.7Nhxm]U:yԺ> 5|&ly`u ҁm!1Raa5@JZP3lm<7: A|5YMnMhVl0^7ezV0QJv:8ib9RZLpϜ m܊Ql,kwj:3[.u7 ]p,OJ'I!q|Jx 5T|i]+txNJimUH0zց U-H6*pN/ځhfzVx [hw`c5 u{:$wpKe ģ9X$շaAޜna 4=Bi ݱ<*(BȨw.рnuGV3 TUT$Z`k64B<)2pp?QYXUMax+|" #Q6C v #QS@ȽRiJ0kDrݐ<tݼ^Vj+.yPu5Wu,2cT#XD0P`:l-r[=a d~5ֲ5kW.nclՎ{(װ&?rN3޹dg@?ֺqinR"p,pLΙG s0I)u 0VXsO2qJP-'ފ)YD-4ͫ|DUQ.(ĕ]M _+R%%ȣt›ުX+J͏D|H7iۤ~f:d~[U`AɞC(`d|\:qvC/7ok$+ëcVD%᩶)vUKPņRh2j'>oib!bT!23) m*- s+H4Y)AIZ'`m9]ZYJhpHK\G .Yx0]2W1> KJ A<ҕDu3i-kp  'i4`[($U]c8?Ql: T M@mm6nyn{DsClGJmm:-8^OJ@YAO*sJT u%ŒuFʁ+#^ Y40mΑ% U~QR:5ۼp]N Zzи!~=ꭲ<'y:t'vi0NJ1i -CUE&umfW/5!aDc0W7&(ηP2:GRM7U`,oFX ;V7mx.uBpPcw*54AA+-W!Xqm޻2ӹa\c%`~t9d=vA?k`bcz潓 kXUuQk6q""إlĊQAmH.|+9<%M#ҘjF&A9`i IYd|逦HAf:.<)L\3E-* LyhԘʶA]`A;e g8jX!҂$>7󨦸 9Q*Lʒ+iIT"Nzr!JNi=iNuEnhVIY1P@ڜn2rlp@mq)Zqv@LҕO@ i8$ُ! K9چ15 Al."zU'?"L;O$鈳jkOL|Uz=L#-58źÄ\lh AqR':(ꃡTOaP,YFHi_< FliAF eC2OVV֒>r @8_ DGbIrddjJ`m_\P|WiA! !y`#q<=K5 ~^TtUI;P2A"y&S$HXBAb)cmFJఀ4'5Z kV> AP 6y{Z ӕa/II; @8Nr ԸQbF*8+8A2bEMؘ$:Q.YB#sP '?ҰS96F1;q⁀hO$8g0AjL0:$ֶA961,d¬ "h)3,;yUedHC<fiΖT&AA.H\դNQ!=E:1P!06D|ZNj|5&)E"$O&8jw ((UQHJ PҘj05T):! hʌ,t .(:Enʰ'" R|մsymOA]Fn]:bt^{٠ֻj=67GHbtFJ]FJ95Y@Xn4J'Q~u;*-S$Wۭ>H 2&H8Hff3SF[3c-H*РBMU*"9Ѕđ,&YK ک@، @1Ҝ$JvWˁښ*R$GC]in,ή^ӣ6L< lyֻKM`EX4oJVնa#h ?֐&JiPu?kDB[>UK0iG %e`DXu0,!"ǭqٍ=c~ t\gDe ǡbus^A?UDn\߲ٯ`QӅɃTfj֠ǰ1WPZPz' LW l٭]L qSr9W̧EUu 7* t+6/5.>l҉R -`gm&O%Uiܻ[wF.C&9Pw;& tJZ?:8 i+} ]KDl-[u5eeضՖi̬A1Q欤`i.WtQYXC+"l P<4muTl7NXuK=qZLܤ~,VexoyL[SIDAXSαY*ʶ~uI /vy{HJ<54iiۑL.U#?$:֟R`;|pkC]7IV+@ d50 fd:1&WNX7J) z&*JЅ{bMb*ֱx.hJ,09S+ X\Xo* `빦uQ~QRC|?R$\[&N<&M*uK;QژD7aQuTBg:):F(Cxxʤ[SWSC; g.(6H=/ EB-Ht7%zixbv-R6 ׋*[G`݅SQu4KW=u=MGY[Qd]QRh3A2b0+f7ZmX XfwV h^;N& aQ8E܊ݴ,li_#QXAQʒ];r]R1,nڂP( \\RA-V vdYYX߆me.9-u G\w`Dy&u&?OBӰ[V|*p̻ǢNAY}Y[xފH @R8gh"cQ0Ab'a@=hF<!ؓI >; *Hbސiǝ7ݐFǯΦT3q.Ҩ]P` .Y/ "B7,K;Q OtV&N>TMxH@-h"WVk1'UOh&-)OQM5%4樨 `z@$@@:PգP/tKT]|F*zLjbC:0C)4^;⭨T]Eˊvn=Vf@M/oG&gSAP+}$ʠP)NzUW:MK?|JFaPfU9Rm.li  iQWPg* _ә0(:sKt@'SP tOI;fcWKiE:ss f uyo 8߄TMY@5KtKu8_TZ@:nYUNxS.zjW2]:oҀR  8t5rTt˩; K{=#6NxZ˛A\wXcvCL(7RDzX= 8ITg٧aJϢ.+*$3 kTX4 p*2R]f~W0 'ʙXJk؍ԇh+MKq&8F%QzDNHi1avXr)nR ,Mlm\YXwOHg&g]+!2@]dr#OqSŚ Vb&' 7LP8ĕAڢ;I'銴KI␻ & jݭz`Pʲuwia5+Vb6^qk,j=S }.p{ٯ֦Qz@Y-{&љ#5b֎.'*:d.eB:%|A"X= \(7X`rxL,?| @ګivS Ic'}3sM^#e}w̳ :P-QOSNPxQSN@(SM-6# 9RlMҴ )J`A$æqj b rBϕ8at"e!Z0BuQ06 pQXXn92'Y(iCt0H CM~xg8W(JѱnbnM"\UPzrWQZ bHQ2j佰Ok`*-apثp zFMY*1U >ub2:r9*nbI&,EV$ IQlȑLW1VS $ Ҹ fGVUX 0f&h4.Y`twix<%ZhccLp~ >5xT@rߔӕKT6۷ SpI恁ak 5CӨ ҈lCtW.q[P0¯4UXʀ}.-)*.2 tK#:ibAT"E.[pD d]%7ž1J2:QV  Te_iu@m!v"= qYXSul U/xCAʅ j@Y@Qp+y#ɳ@;Z8r7 8S\BX-f`ih|S,]T&hmQivS"l=z8I8 6cikzXChVIPoB`~Ȥ,ll{)װ Ϣ.+*n'l+6ܷ^"7#'e fCYSl{Vé#ny0iS d8G:c"nx|`'qp3T\z\O!XbMs1U #dgʕ]G GjܐɋLLht&K2P- < 2T^6m߹"*"m$]ϥH"IAI&1.I3@Ne8\ V́S[3w`WϨUađ2:rq҃ ) Uelb9V $uؒyTL# R2 ?Ԛn#OpӍx^4&!^IwOoάquԭI.`mMI,zmCI>D慚T&(,N8I#sQ~=c{Vc$R[0`3A`5SIH\Ti-$ aq@`AT|4F'"Pރ0 nsϧd excY@(JHm*U"74i#΁`w4~:c҃ MTZȮ{ևc~8ݒܖip7V iqj[U\s0Y-#uՔ;niuʕ`wP#&1݀iIFxvLP)yuIH1@)q4琣z?=)eַPPBh")!թ@* ijai;WO}3K\z9ԻPxt4'U=D_&L*0}OX(V.ְMFB:o@&675oPbɐmA4NFF540F+G⪹\ʷZXSe P?v &;ņ|\$-bk(h#\nAi ]IkP(Z) AF+" 9 TB#>liFqoBuV]/R<[f4iDTӀT8#PxadUKG m3l#z[: J5qrkhH`SX0 dq$t 7`@eSS\OMp6NЕ@џ1@YF")[P4/wY}t AHvUdDn#Fi~p֊ +yA|jYm2ʉ``E @.PA(0nf!6!;~F$6ɨ9 '#VfJ.B q!7 q%^g~VML-'DBC:N'$0oEE\EX(j]|kr3ʤu4IeqS[GB( 8rƆ\2(wX]zɚҸ1HX.A3rMͤteS!.u.z@chTZi~ V[v3`{@_k'#<fHEWJOxeC`\ײ{~ӕ`1m82Gh.Dm"@jeT`8'bn'L젔^j-n;"TN:ޒ\!m:7dǕ> ("Uczy N1ʔĬ@U@'zR Z@ Z18m#9 +hi9\V3@T6H*dNh4iك@dQ; 0IUTI\@aHbdbUmE&坾`LP.ܤm5%a xy氰GI ":9Q YM";FjzI+3t*Tox|@T0M՞pviV/ADA("I9"<i=B*nT %[Sq+O΂9Q u@`5zLlӅELT$@@3@јq+!Q4 ң2G*mFPOΥh'>\T\@3PU/SNir'ʱe C%M2IOBMQ#E@6hԒڍhuU)#)!\ۉeӐCdPP0%Γ!ޖI(*.Nr7T:Qp^IS{:aՠCL Qy&OT p%J:VodR1E;.Vs8EP7">: 5<|?.T@U'PP X]Su5$06RfekFɤWM rI_i"yf5G!FK&j~,.D-*V)%ҊF8*GBh3*ib|nr㆚ZQ, 2z=.=igɔiJcF0OJO >T@%1 :6@R+pRƱo#ZՒۍϦ` [OM"Ii B4㉎ni444_[UeS`Dםڣ_Rdzz~'PdzRh$KOSUnE57*#bQȮMSڢނ_V*rGv c2mB:h5{Q@2X0J\YWXjk1?[m5gHNFXn@Kt9Dd'SթWM |tŅd0^F-u&aj0(:eVFO_D,P[x#D.7D#@diX "["~|#Ú-%庢 xyXH#Χ(7xY6eF&ؑj5=F$UÍS*ns  {0#@5Us d#XDmUa'DfVgʺ"Tg<f@V'tx[p LLʹ $<17KFՋʰF65'})-fPdo c XU`pe)OB aʤ bsQU\狕+(P0sAX2Y?PG"k<I5*nUݘ" FMYݕ`P /Ef l iR$)Sg |F -o5i!S}7 - gyiC)2њ.u&Rd|Y*N!05!8Blkx8ATFgz֣D>t"=hXV[Y3HdmӤ .75B$ށ́LSk!50T[@*<0/ͧLIYݶ~*ڵӀ #pRf6qg3;00GL&6Q\br~ٗL{0qsz#yZuZ㽳c6Vx=4{5)q]0Ĝ9}۰t0 jX0$O1Y̑ ImR^:O>y+*6LMi)b%r:`$rh*($/01#u Lڞ惈uTDsޝ"|Ikn!P@CJHplu{*\A^{St^)R%Idi 8L#Yla%YAt%S)R8Ṭ )h 9A5b$T0Yڝ,.ާt,N" j4nϭ92 g 'ΰ0KI'c@5HjB&y0P$j$ PBq/G 7&GWQ+s$.MU!4EsZ3=u ΁9^& 򬉯x61 v!50TPp2,@CX,ӝD}@{hڂ6u ;#OM;:KsFUK%B9ʶ_*6\XlhȖf"ѰIA&XrPy.":2[DiiMըGPE]WQWם*M(\#1Ѵ83k&[T]֙B{j`!e-xEBOΫdJ`yck;{.[(%p֖ *yEVAu4H@܌`v 1e0Z*a8E?h<E Ҍ) Ce.PV1D(;c5%z*AG tN@oZ ř 1IT)QwjRCl!*5 aŞ{Lr^]OީXD*6e,j1nB R߻aG :(ĀgRNJSC]N\%XIPw`M1jVb`t53 S[UiPaUP:m%vI,ZcΦ55`@a UeJd,6cij*`H(-q)R9Pf,n)`U>2SFﵛP>v ]Cj*J#Q`|4UdH  Q!@{I ֌ @W MP혬. ,\1iҾ:$(lC)h$A1 :jaA=+j"q KDm4b,3;1Ym864.󎕮ʀ1ډ!$tJAY@Pe6(rV։en_΄30*-V` MC-wAty_:S A(ĦHjax/ʂk/㍮L@2wl- L 'z 7}+ʪ˻}},Nu{e!Ak'/9?٧a@U\H{)o5AǢG:udonx[6= [OH&7 f75a[eEL4N.\bg{H&XAʨ w . $2ޘ@@51p|@m1&Q,(:b` &E & thLv0 &J,Lfo( 9(uPfh\:wJ Fv)ްʐ1D:PjlV A$(IPؑ`TY@'X -Qro5:fI#^jutÒWtkPgU9WjH@7dm.BJ3=teEILoQA84@2 u_{%:6G@VA<+݊kJ^-E)]-@@1@F"304$R3"\un]@ìJAR*j=$<4dRـ.%jX7Bj΄hJEKmcGwk5|C(K >T%@&[j̥ETСpwT>ZyW^~Tci+Og򪂌#y/hT;0;L*ȠMW<3f[xyM+P[Lkʀ, w=)@"iKA;F=h*p5Aݙ}3$n@SG`WKn1'zր A/ru4m)(ân 0q:V ׏t[´[LH/v5=VO;2[Q3(EJh*m6%еt$a8鬵URZ  ,WU0 z֓?J:=$0@M,םYnDl*NtS670IA aMr1ީhVb~F.f_SF.da)#iU68RnDP+u$r&N`ԍP5 a^dϋU ʾ=M=;9GB(QP"n g\tL&vaH@7y{H4ɹ@B폔 1#PmVYacnq@ @TETrO  <m:di*|&@-fNXN*6LJJͽf8 K4A$ӐHEfq D]E"$h6U[N2Im鏾PP#9UցC6#;yY: V -oO*Hc|vV%a Q`(d'z ƿJ;Jtl΃2 =[ ~]x"lWٗ%{/ݍfvOhvWicڏԐdGiڵjO˄~[R6ҏRzҏZ(mG?/q=?+Vl--!ڛԫ1CjթI+{L}/IAjCm(]+ c{JVM6/9Tv?j?RsjhQ+';!SE c+?ER]SVM]ԩ{KKVґEjD`j_RevdRz7eZ(mڛԑtELJ xFkVl#G@;#(/dOi~Bj硶>ԞUvE(=EjCu7}}JDG=3^e=CM!{#ȏVWM q%{$m+V$Pڗͣ"}C+R?VM>o ?Rޣ?=ۄթ ڏM\vEjCdq7>CKZLE5SE a&wdE]@jhD}}DS=s'ڇ VM6IPOdv]zaZ4Q>GnڥP.B?jթܱ]zh;TVOרktvOjo+Vr-?s?]zxݝ#nZ4P?kQ-a<SE:=BQ;Xc;= jh'.E{bJ~؂SEnSn"jh&^v_}=mUCDB?7jO[E=>@ թܗq=wXG2ݑڣ(Zh}#{T7}e<Z4~/kb}@N+V܊@{THO?}+Vr }koD}}B_bv թܱ^>o jy@Z(};E0^oQZ4P&GN(~ܝ<+VrAj^UAEa]{VQjCDCS:}ڇRGf$vGi jh$-EHfSXz[ST-VM]}Bb7j60(Ǩ;PKEjCdo.Qׄf\_ݩi"jh[ڞbJkQ&Gd+V$k(Eoԁ#Wj0? թ7k$G(w?ڃ^+'Ǥ^F(թYinstead-3.5.2+dfsg/themes/clearlooks/cursor-use.png000066400000000000000000000040561467622671600223550ustar00rootroot00000000000000PNG  IHDR+)@sRGBbKGD̿ pHYs  tIME EvtEXtCommentCreated with GIMPWIDATHǭkTƟ.WJB#MTQMITc4=hb)MQ@ڔ" (r[`Y~Eszao pstx|vn웑 글!񡞅+jf%|cꡃYV>I?l@W՘P<'wASڽya|=*V 5{(!u  2dȸ ӺS AX VF3l.׷[|D# `}u&sS(0{_fFw|-K1(@ @R0tqG@F7zWDO'͵-*[^{2P@ z ٟH'^jAC>/p+@Cq_1/^u(?&_dߋ Տ}MlXne+K%i*d }_ز\o& ?ײAAlZ8Ue5Ldg12 *)uz?@ p<`"(Nၒ}m\׈,wl$_ڙ^#5Ŧ ̓o[wcæD_'yp՚q/d/3U>~8K"J/΢BKׇyS"&*T00Okv4Zrr.'n+]=d+[?d8BCn|ћ9)v`~,D`At!b/-3+K OO(!𭉳Ƭ/3I#GE.7u_@`@AWl ]+ިnSq ^~wjb4sTKDD@hy]Dwj 6 cm[;:Q:t=^ ַןZ>ݣ>i5q LnCH0uvD2H7?et~ \-|mUMvVsIݮ; <|G CB'_b dmwc^2w7lXmtÅ8 E/6_\rZ'W YӦ4J%0ڑf͍6%ф>aS-׎],u=ubPsQQsm_Ob Ù>A}WY)6(P to,xfo ё əfո ;3wזhW]-B$1ۛo6=Ȥ -Q2{Gk/ Ʃe}8)9`Q999ӻ{䗎Y&)i 5k~gRhG' qg=2q iON,k:d'Zw@-eg̿x%o|Τ3) &@D޽ Sx 7A`P>uFm[M{}EMeͿ I?T7kbŻ,P 0Pk<6c|Nh]Hmcѣu*HA2

]'iVxG ;n](o"$b"1i?4;n%66(b 7pED(fSwplfQ%!e>A2u}׎7gbbb~PqxG: 珹)HD udD( ҜVO'*$n}'<W>aKl$2>Yg[~CzzK$IFbJ8D Kh %VP2!ADPvIENDB`instead-3.5.2+dfsg/themes/clearlooks/menu.png000066400000000000000000000005431467622671600212070ustar00rootroot00000000000000PNG  IHDRשsBITO pHYs B(xtEXtSoftwarewww.inkscape.org<KPLTE˴::: !!!&&&((()))---999===IIIOutRNSx)VwIDAT(ϝK EKiPtw<1V`CO 1NʸR 8H˷Wȭ$mglϭHG :~]ĦIENDB`instead-3.5.2+dfsg/themes/clearlooks/theme.ini000066400000000000000000000022501467622671600213350ustar00rootroot00000000000000; $Name: Clear looks$ ; $Name(ru): Ясная$ ; $Name(uk): Ясна$ ; $Name(es): Parece claro$ ; $Name(it): Aspetto Chiaro$ scr.w = 800 scr.h = 600 scr.gfx.h = -1 scr.gfx.bg = bg.jpg scr.col.bg = black scr.gfx.cursor.x = 2 scr.gfx.cursor.y = 2 scr.gfx.cursor.normal = cursor.png scr.gfx.cursor.use = cursor-use.png scr.gfx.pad = 8 scr.gfx.mode = embedded win.x = 245 win.y = 21 win.w = 520 win.h = 558 ; win.fnt.name = sans.ttf win.fnt.size = 16 win.gfx.up = aup.png win.gfx.down = adown.png win.col.fg = black win.col.link = #b02c00 win.col.alink = #606060 inv.x = 10 inv.y = 21 inv.w = 190 inv.h = 550 ; inv.fnt.name = sans.ttf inv.fnt.size = 16 inv.gfx.up = aup.png inv.gfx.down = adown.png inv.col.fg = #606060 inv.col.link = #000000 inv.col.alink = #b02c00 inv.mode = vertical-right menu.col.bg = #f0f0f0 menu.col.fg = #000000 menu.col.link = #b02c00 menu.col.alink = #606060 menu.col.alpha = 230 menu.col.border = #606060 menu.bw = 2 ;menu.fnt.name = sans.ttf menu.fnt.size = 16 menu.gfx.button = menu.png menu.button.x = 0 menu.button.y = 576 ; snd.click = click.wav ; click.ogg ; 800x480 version ;scr.w = 800 ;scr.h = 480 ;win.h = 448 ;inv.h = 448 ;menu.button.y = 456 instead-3.5.2+dfsg/themes/default/000077500000000000000000000000001467622671600170215ustar00rootroot00000000000000instead-3.5.2+dfsg/themes/default/adown.png000066400000000000000000000233751467622671600206510ustar00rootroot00000000000000PNG  IHDR0_WzTXtRaw profile type exifxڭkvsg|Zgw%9d;7ef@Uÿ"ѻ\^_>=pܥCyqHx}5ەʏ7x׏9`lz Ǖz(|Ψ&yIb-5H1G/R;[Y粉&uׁG#s;y)>f7_1 Ws*7T2o|1ſ?Y&oY+k|=qm _~Hx(3j?hWsV;g{ZG-NJ+W]k찁λe8@O9i퇬}Y7Q oYk`rR,gd,@2̷s)qXQ",,cd0 o/rWy3,usO9o_dmY17c'w=wV~TaS'd!0O(]tΧั38L4B㔒g܅y'FE4JdGݭ0tj^$R圶bR*/N尰Ԯ]<׎jFCF4TemUXum-uPhahpB sOXIiSPO6J_|H-m9l@Os:aħi Lh,L2E7#zt8T2XR"۩|L:I3 ,$̒Z뎧 |']lp:`31rNk":i9+QrS :OS2&3ֳO鴅Sǜ8ѓyA_iGJm}Lrf9P>C#n%6NJ8a'`j 6ӗ1-o~Ykm'! t֙FWϬFlc#SCINK6JHQHjJǮ 3*pTd;rlS(3żI`-9 գ@JN΀=FjʼnffspEQWR+B*jP Y>QͩER\RZ]-[\>D%C|FRQqLnc9$|^Y#?#PTWRZ]R+68j*փxbԛjhRF@"pj:H غMP` czB0h,:iMdyYמJYB[(xkq8FL 6CABV~ 8umY{fX~i7jn2*8˼0G+Bw儳^UNv1ak'' hck2g*`KAѸ+,0NEbma W 1:\e+ #Vi5qb) 84X]g4MY5:(Nrvpc# y%ŘևNץ_e0ax]+]ӡJa)tݗE8@BGOG>Nenqq6^ηoS`WnhB `LH9"q'*>2AxK3UA[M,Lqn.#*,I}@z4^:2o:D…nꨔc 8@U9 ^C1%ot|^Bc4BsEUE#,ф1&PoIQ9%-%3B}Zϗx\MO8>~5 P~'^$a"S~>-uef٪ܷyL/|R ؘ)]H4M3NW {d'yw"j琻k4fך$fJYVF aM$ 3l1 ; (ںj'nt69`8m+{WKmF6g#8៫Iof}eک;MgōǶ Ǯ`vQgĽ kavo]ڭ/& [w)q&&b~T?$+!a]\j>d5Rg'Oj7$ ?9['?7:VC"PaeV,B F]95}D"w!v}7ϻ_7N;(O<3Dkh D _ @5j T2E$miӡ4OZbR%5LbCN1N۵kzBma%^uv$1.:Kh^E.Ɯ@E}T t?`l @GΘj:7!wPvkڝi}p䴕.jοۺo&MPV䮧lj2Vnގdه"ۖj"c&" Q4-B%N4e8N{f3zDu8da KݪbPMGPr'Ņ78vu8-BXFT `V궆/ٷ?}rf7(䘬Hﱸp *c}F;NR- JJ#Ekvtž'KG2(r]˳v`rJ@Rm;k*̅ktž l-6R fe{2RQiIB_ {pkL)/ ;lSEI#u HYn%M.gno21c^/$rvJm#u t:A`;l/w1a\"mnNdKCov\HVx:f[?jl%,\J7iFdaNN?g6@i'cLC:/u=JU x`sQ;\M߰3g) PFF+4DD!;Ӵ08UJ #-_~u쎢1mCj(BD rZvOWnt,`o[|ál0sV_BbۅݛO,jjYGTO%GT8P:b{&3s`೩ެU#D{<-tH"p㚖u0?JPZCjK_V[5̨:Uh o]{ެ@F䄼Q#pzo mu?z7TSJ \@H|=^!rDYA˴︤U*س0*beۼ,Zbtl8$yؗb\2#O+êpo[pr$r$= )-]eLDF`\0̢ GQN <ЊPX.ʴ Cl5l tI yEc:1k#VXFˊ̆ -bjzʻ!*)WȎaP|jVd8F,ޡ7[ h| ֜nߗ4 ]6`]c U%JcNxbNI~i&y?QiCCPICC profilex}=H@_S"+HPVJЪɥ_Ф!Iqq\ ~,V\uupG''E)IExwqe〪YF*3U1Џ0F%fsd>Ey?G3gnXӛy8ĊB|N bKGD pHYs  tIME-0itEXtCommentCreated with GIMPWIDATHK EÖ˒Tّ7R:ڨS  WO2)% f DJ8LD@XCI4X ~x@M1@36r3 $1-]\ 9;&"VD|wLb9uWbeTy੅;*~(#ITJIENDB`instead-3.5.2+dfsg/themes/default/aup.png000066400000000000000000000230641467622671600203210ustar00rootroot00000000000000PNG  IHDR0_WzTXtRaw profile type exifxڭkvs,>Pcvܙ(I[n_R6UϿr?w~?>wF䐽xhy|su{^]m_ޟyXs)gsFj5#'U4})F \6T޽Fzx~}42SH1,y.N)8>haoxO*n ߂>6bͿ, |~GqB^ߞ?u껟 TE  = )c9=VEӲ=\8V`6pmw*_O޿<>]|} X0hf9ͧHA8ϘQwC%6Aa,Đ [l/<$9!bla2!!IK%XOg18!,cNIIU؜Sl8 {& i\$J*M& S-j4K*HRJ-jRZkŖ4-zl;v9Gi!CGu'yYfmWrB^ʪJ;oٺˮ~I'9zʩ,Y=sZxf-D%ǯ5D0:9brk9ZUB"K 12wr[~e˼\3,us29o_dm̛['ʏc&DLFyi&Ks޲ 1JNI%ELO&d YL|&,ud?O޸D1Ь1-яTZsܴ։^}$F{ȧJ s> i.xSxOiQHw]V{9[fg8j쳌X (?ͻI]!)p h$P83aUqHIL +"jΩΈ$@)pp0mN⪵\F%{"VS.8M*;cySep1zʑ'2ՁurQq,ۅ},xUF:Q qѬo:Rws̒֘9-;3*qVq2I٩Xe!8U*֠ҼNeg5Y)Ȅ֎P"ҕa2dYY#-/0)g"=ٵD:1f@P-3ЎB"q! 2 +ŚS Jљک2n%9J_kDZ1f"d詭ml~)+`(xj}<^ɫ&2gvJ Ȋ%;Iyzt4jc|M &5% *)Ԗv 6f3ڙR5nR6d!VJ?r /8yYIeС 5jKu(C1M 7 ci!M#fiW Tc4k ְj{ "g *X0rc`]Ԑ "V(:pHlqgH@A΋3Vte=X-9hgVu2}Qwէ5hnm \/Pw߀jy+%0@=.AsLICHG;dP0hv rog쾝2ұVl4Ph&.D *eQySzU}Frr$2-1#yEA`:۠~ps8 ^)7:b(:\g@SٲbsV7oҳ?Oms8XYXTm qI7TFD.DiҰ&v٧ !V?\Y-A5CE`ݳ@󼋚D۹8~̩40'4vv [;dP_8Yt9֝bz R,V`Qn~gK?bi+ ,ZrKD9G>-u{c>_IدSUvւx' qbB7{C[,m[BWyvl y ?p4o<)y$z3$oM v>L;-O:eMv`Pa4e0QOh O\,%4|'􂃆ɬ}c,k,u_X3KTͧmaI4+vLm'1>b؎JGx-?Z@oVR&O1,s6-@zZuBJ֘4WO:zViZ 7`/^`P{],X_f)Q4QELa:{:{m[fMs{gOѲUqҪSuG^1̡8FR(Z!6bA2IJX?g׹˰{xc$#vC3NM&ZJkk랽Z[ mw۾)WYgZ\~0ĚMC,[4NJ #Cأї`M LWu#~tcMmZDbSE? dH]o;a(\ d qF8ZH03];K;UOg]c{XobZE T 뎣TD9&e}g: XɃPA҇34}'l+|uc2VCe)ul߼g5l/;{n` L,SnJt/rqQZ;F0`YioR0i\$Vo 0DܠFM脃-8qqPͽHn,-#CBNc I%4L}HQp, ]$/MJ5"F-$IJ#D3 kٽϓ*J ĞU I.(8iۍ%H)CAkk7䶠!v.m!'AjQ nA9YoX);+iHEʶo>if[%Ji V`H6-P/͛$DӋ*"D|m#u(V\!hR:Z sRZ/8%~Tb>G}?d>gԷ`:c=h8ո{O#PHj`S ^Gz#=Sa+ܔHFEưQ%vvXfn}a"*پۗ[3K:zp""ab~ !rLW[n.3T!뱎z2!7+=wh<^mN0.ډ))8FIIOzύW)V1/44{o`:4vO *&ZC30U 'H]`eZqx*G{96ЌD`wTg |ՃK4nԍۄ%]Ce>XpOǴd76neJʫEmv{40bέyLa/A,X'Kv650 /d;F A_ˬW0?owb sF-T(p( >b [$u© -"_B귯<7 ̞/Rp*3q)iCCPICC profilex}=H@_["+dND8jP! :\MGbYWWAqtrRtZxp܏wwTcP5H%B&*_1L}N_.ʳ9z@ đbKGD pHYs  tIMEUtEXtCommentCreated with GIMPWIDATHK0E-$%5|&21*`DG9[F\k5Rҕ b"[k5@ܗ'0ITv8QV_,,=I^h o&AGh yy<Ap6g$d5;wjA̴vcIENDB`instead-3.5.2+dfsg/themes/default/bg.png000066400000000000000000000054411467622671600201230ustar00rootroot00000000000000PNG  IHDR XvpbKGD pHYs B(xtIME  %X} IDATx! A B(f7¹{,<}&`@`@`@0 0 0 0 0 0    `@ `@ `@`@`@0 0 0 0 0    `@ `@ `@"`@`@`@0 0 0 0 0 0    `@ `@ `@`@`@0 0 0 0 0    `@ `@ `@"`@`@`@0 0 0 0 0 0    `@ `@ `@`@`@0 0 0 0 0    `@ `@ `@"`@`@`@0 0 0 0 0 0    `@ `@ `@`@`@0 0 0 0 0    `@ `@ `@"`@`@`@0 0 0 0 0 0    `@ `@ `@`@`@0 0 0 0 0    `@ `@ `@"`@`@`@0 0 0 0 0 0    `@ `@ `@`@`@0 0 0 0 0    `@ `@ `@"`@`@`@0 0 0 0 0 0    `@ `@ `@`@`@0 0 0 0 0    `@ X IIENDB`instead-3.5.2+dfsg/themes/default/click.ogg000066400000000000000000000130051467622671600206030ustar00rootroot00000000000000OggSk\KN9$vorbisDqOggSk\Kt-vorbisXiph.Org libVorbis I 20070622vorbis)BCV1L ŀАU`$)fI)(yHI)0c1c1c 4d( Ij9g'r9iN8 Q9 &cnkn)% Y@H!RH!b!b!r!r * 2 L2餓N:騣:(B -JL1Vc]|s9s9s BCV BdB!R)r 2ȀАU GI˱$O,Q53ESTMUUUUu]Wvevuv}Y[}Y[؅]aaaa}}} 4d #9)"9d ")Ifjihm˲,˲ iiiiiiifYeYeYeYeYeYeYeYeYeYeYeYeY@h*@@qq$ER$r, Y@R,r4Gs4s@BDFHJLNP@OggS9 k\K24 OPH5b6_H + #=G[b  ZUEZ"bj(V-X"E#6AED(`F[2]4|)1"/$T__2| H IhZj|I!T֢͆C)]VU4"|y EU؊3}EWgf13liG`2]ST#dezŖJlF%b:/PTPf 1V*FE +v[P#X`ۺa5c&mogiTZVլլ֬^zi/עR||e纋 */>ZYŢUTj *XAШ 02`slG6>ϔ*Z5) pPPΡ|9G.X@1L uJ@bWyi+ZEըblݚn,+EQqbeYpjett2L/ր.ēxٶq HU'2JMU)5ʤ R`U *j)3e.ضdXZS԰:d Xb)V C183Xj_]WJ*UDsi)#%D%"ZX 7N Zh X80j9<0Thz` Ը L6rڀi\$5LuiכfNžmnvTbT.ۂ&%DUI"3\F6 .(@S@e\;Ϟ"kD22md`m*cBF#"?‡ܧV ϾX y:n*Y 鶌;eW_r/aFd4^ N&ԵL#w(H"bE6hz(0ZXS(Ga&l˂isY#@jFJndF̲MRLJۛ T2YmU϶!-Z}#2v~d{gO]|˰is@?+_?lP%-DI8fnH'BNn!D:,0,}Ye,_ct=˗&x@t_xQinstead-3.5.2+dfsg/themes/default/click.wav000066400000000000000000000334701467622671600206340ustar00rootroot00000000000000RIFF07WAVEfmt DXdata 7* T T F57452646EE5455152214#]RZ^]^QKQQLS\'D*l{|z}yrrET]^Sm|,F42!NzYruXfeihlxN!3? $&*8, S ''-  /**)(E;59F' 6U`$4AB>buDDY.yEoO7 ,;tMrphhb=F]~lWm493^Gb#f>-S 2S '!}_3:_ syt?6Xd`0=~ {b:, ;  y qz\x(v2 '/J[ *Vr;$V0_>vU s,FlKNd:@#05C0#3Cs\rYo5Q!-j2:^;hlD`dWFt%D vv      9+)*&*')*&(($RGCCD@AECCCBCADBDB@FQ _%&(()%+9             +     7,*)*7G6(RFAC@BBABA@0k[Kzvx:xqvdpshI\k/?ADR' ~alqmoqdenup8ssprq`b_z !!!  :,+++(+('))%SDDC3{&ja^^^\[Mzzxwzy{N\\\^`n4DR$)%*&+7  "!,*       ;,+-*,;  H                                                !         :(VIEFDDDCDD0nRyl|Ql4AB2pcp5BX&I    H  ;/--: L                             ,)),& C*n+?  Z_\7XuE88LtB'uypK<My.x F SueS m_ YJYx!keR3F 1 [|`Wb( 1K EP%#k c%>L;upz)NddhviWx\e=RlpS$SMF}Z[VDee0=1a!ds$m:B Q  a08 6   W t >U  TS^.Kni1@ *eo<K1 Z5 1;{1 OF wxYL1&$jJ|=AhprLzw3b Tx|z YXeS!g@c]!\-h-]Tr]s|OJF xnK]Vc7)+&z,"P3lQM[ij\\k1?V$ ZyO$2555w_ytwwzwvrt5% $!!G1e;gI+&pzrFt~rrtZid^M_il{?ONQOQOOPPSNRRONRQRPSPPOPQ@{j]u~u[imv56EPd'5E G:F  G*`UCqo}C?}ll^uinstead-3.5.2+dfsg/themes/default/cursor-use.png000066400000000000000000000443261467622671600216470ustar00rootroot00000000000000PNG  IHDR+)*zTXtRaw profile type exifxڭkv7cXf])Ynn)@\#xҬZ=r=>15ߟ׿_bȗ=~}u>__o_}O~;H~}ׅRڭh{}s?keѷV;[[7{{ ~iI!y)~2/Jn c16?O~;&/ ~Dǵ7qz  Cӏܑ}$~G>X~yDmbG-=J.Ҋ^FMUVkR˭Z۰dيUkfmؓKMW|c8̳:۴Xʫڲq')]w۶'RSN=g\Rok#j_Q5jܿZZ|J?ڏ־/'E1#b1":*fBQTwˢ절|B,7a\(ns #rN]9n-2X/b [T(?B)ϱѯ6 T˟3BesyJ;wYF7;Q+yKy_gvg<8*`w[|{5{8<$%qbnfձ{Js6fI\J;N+XWͳYwZ5y]ʯbsntl7Tr=]%av,7ojϿD}w?R,/Zvxe_՚Zy޳{gif˵NX]nNw%B6%~'3Ci12Vl[?`EҥB.{#~I$$LNafIaɢL,ił1FJ;S35oOY[nqRH xr# ѩusu)Wpn`~ K#I:jؚXHr0]˗beACE>UUA>('y^Q Q\@Z{;I ! ZnEpN}m9֑"q7 X+ $нֺbWwZ\8M΅FVNroD]שO4uro-=/+!+ ]dܣ'\ -7>@5 b !@n,UYO0;tꡏRГçB=>;du_*=g{ n>47vs0u/ˑ"cUO7K= CX)$ stD.G ˗ꐳ!b,@ #R !]p, zXx3ڨ߲tLC( Ћ f/ѐ0; Ö*G N6]Fe0{YUyvEs$2 @|KU:b,b;ʭ8 ?`[P&ґj(Wx#Eތ`( ^ɇ&V-3KZk]֞E~jGRD`SS6D@P%CdtPF2|]O2=?޺d?p y~u d 7xkTZ{d}&뀕؉ ERz`GYeMxJ{F_]8{o+ߕ '%'o:`,YRrn剽K~Jt'@r+<'ٺuqM;1].(HY.$δPj#E@E 91w|/ď -L*Eb=nkQB1geo,{7!cTsR"{P]:e"Cz‡<~Ю>Bu2m$'\bN CgRbuE0*ьqXQ$/`a8iJD 7GĆ@RJ̃0jD.?^ @(•-xu8/WSױ)d ms\hɪ ./~uZK H/ZLa ~+yh$֬7 ʄ [,2d 6cayWLjIPj?㮱wF5H<ۋ+! r$(%-"G |kP MŰGKlӺ .Є(`H@.dxu{( $N,߉BZ(RWf`g30ƥ>9JSJb:qPCœh`)zy]p4 ݣ|!)jiѡ\SU<-GL@HyWHW$Z҅5 Nn歖G%[}'1FMꦻme/H`B1'NUܵ@-mζ` ^x8KO14oF 8R|:oYC @DYu,xӤǼ"M :y|#@ Krr+ W.mQ:d}5*8p͈RD9C?P/u](p @eriJP+̂BpQ)%c9o 8Rɣ`VXCYugnmu0da1S%7SAD~btI̥}૫sr}\2D9;SZ)U):5w~ -Spv3Q*pTuGP=4k.V2 A4?8fw a KvjܼWܰI+X:O$EUahsP&`G1H+`X(y0XhͪsrbC\S#&xۀZ yRy&(P[VwJ@kR&06U^EsxXB`%"F(UF<3@Q  pN5I[_=X%?>%ln_a8WhQC%>MG"nt(z43 z"A|y{VU\nDëDnQl>k)@ZāPQ;cwTd!+mt@zw^J Y0RY`+dD.UG*݂ Xe+1!:T(mAh׭:t 6 zvjFIb*J글pϓhHZ˟"꜐{+R){y̵4uPV&EK{f@w0"ې#G[r)GsH;/4W"#^a5bHo<;EQj$]s Q5m(giD?8~ȼoPc#8 Ӣ= =DBNU{0,Gaa4kǏkTV<1V#YVGuuLL>m6E/=hǾLhS%MVAm*b&pwڇqv@bMu 䊯/b_S"KH tKdz1X)wb"*H5_Tp[oi ģvJHL{edeAQvojb!ljLPk#ЌTAvU@IQNx]^"'H!44@UBz!fQ(褻ڈ =5=apzXQTx$0v#r4Z.p]rg@V"(7̯,0 ^RW~ i/6\KiFV֨i2WpM6F~(ރY*`iKHYM0@s~`}A"^PSCwZʭs w1#SSE8$!c%5UP5m%3z'9:Ak}thPA]Piσ"XD ڂk @\`u7iaj&Gg$ J̽&0pΨP gB\Ddn4i</o0 n)j]ڈj#{Vv},,%r-h)P#&nO^:qX+2T fk&&Thjp^rnۢKQK`׳z^{kk#bIG M7H!C٢=ר3z ۑ֎q[ ;sNtD]>umy X|g~?|jԨgߨlN0hE?K٫GgeDpJGXҶ.j 7Q@G%QsqOݥ+7,"`TF/9iV$$Db YE#0Ӄ >xF) M8AjAC8q."ף9Kj,7W*'́"hPa$X,Bt0fג /oY3^jKJޠR7*ȈuiBs۫6񆩺:wj?L@99G{!Y )Gw v(1',:w.5B~6HzPTXZ~ T\? mP s=*=W$8uФo>4ho1M$%t[Yi}Zi9 \hv7AHP#hj0ϰE@E;U:-Dyձ=< *F&٢AjM=YTUj>fp1! Jx7'w{\vjMqmh[ϯ!\_Hk|"pUw\K~kFa% gΧA*B ;uPL{g/|Vʣ5TШ˚ /zQxK36_56i|Q~ dVY%O42Yp @ERCZO@cs$gK Nn"Uǝ7՜k?! %)3MO~qUّn[þjYd|& CNjc6%#Аa= Qg1ǫ_A*l$S00IrvmO5$Hⱇ&:.Ma&*x'mpӋڑc_O:|ܧdLV' XrQ-1?':c$!ш=C% Uͼ@r虖zNHvJ@6<϶i䙀$< ԂJ һekBYvTIbuXMGL{͢h]3M6 `!x 7ѵwWg\ x#iVICm0,,Xu.r Q{M%.*̞vd^Q~/' ?\0{F[Ʒ!*U G ۻg.4vqOr5r+X!<(}\~wlMnU5O$԰@E`H5 eP%EI;+Q?Wl/_p5nh3MRu(/nӯc`j#`ZfrAa3.e-jh *YrK# ǎ:%/Ѡȿ+#1CTǣۥixH<78{:૞>6d6k[v* |:!$ڔ7eդ}4)Y֦St4Gm(_HإtijirXA.wN(ī_ڟU%Xd`EP!)ҋ?YoHowIR:=Ԥi1TkjPFD]gǮ*aqQ C̤ ?ڶ^\N2g%5Q'VW0䉋$鈼d-tWM~ZڤR@H/mݢtUW;4l5zpϰvsSv"BI2 RwWn5mwAD^m,[*lAQ;4.Q8hU;–EhBC)jmm!10ҿ#s'(/c)qSsgE A4mgCʤ)X$} \υN&'aB,R,5I  a4$̢A<{9oVj†$zYw3onf>h.> Q -BegJ _a6g{<: ϝu-m:y4Ip4&rvभ=갫ʓpq8!9yrGmkfq{E!L 5豎f)x~C w4‚&_zuD\>9$JkdTJD4jߩ.u|ܙ-}Q WYO0БT@PNԲr^gZ2Lлmվ=Ҭ.;9gZmesIɶ}%n:; o ]N&T6Ud8UW A*~@&p-z͝NZhmn3kXQLM;fXO]gu0<5B5KvBTĉ57O5|iGC܊/g}2l!EB35Ii$64>Jts\8[YV~*t=%)jUþ0qObG!un|=) ڰ.CYjG mo2dsxP,҆ i,|u$ 5v8F!Όd֙=#]|gV5ATu1&ԩi4h{;E yXNjk+$U P:ĻhߢcQw?7=߁Kv#K=i/e~< uў۸䠙vՈǐ4Qeun5x$B߈kAG2+zZI_q4Q'J6 !X5y*UU jhr)urt`+XZ ˚ueH:+,D.c8b"yKĖQ3On#z$[Lz7_a%Lr:˼XUL< Jщ3̕FOUw@DA6sD$^Y!I&bdf F463iLslc{%'|:Y./*^ɣax{0 KArѩZ4볆ӎF`yv+㗓  |IP`'Wx&:r԰sYy_.: %Z@5hn:={J= ~i]/:D43~LM75zn:"äm\׼ rm |D]<3Վ hjGद%4# ]ǣi 3Gqd騟otRH UIϏ:ø)hkA8f:rSySjl0񗖀Z\@ss!ړFfQ2W-y >򪯣D[1u&&yGiv?ҡxƧ%Q!{»"zjjG'o N7jOQɘΓ.@j=.cyyq"Zp%lB}?ovѱ,E45\[D6xc3xz(բ~Û:suV|.bȵøNJMjaׁ蚭ܕ\끞7=l;aep|Nե=OjBӘv^u( )Mo]˓H% 6m.7ԑZ[zn|+,#y-K^[ 3qㅣ>'Y!$N|޾!dDwjwm{Maw_H<:VL3^?z`tQ`3h*b寓.(4N4P:Hhuj&k*PՑ; eݹR !1!z/,qK/#o}5lRqf}iCCPICC profilex}=H@_JE*VP,8jP :\MGbYWWAqtrRtZxp܏ww^fT2RɮW1> " 1SK&_.ʳ9H Rf>Iг \\4ytɐOS3,{ t5q pp({ݝ{Nr 5iTXtXML:com.adobe.xmp N<6bKGD pHYs  tIME (&tEXtCommentCreated with GIMPW IDATX͘{PSƟH\,R Unc)hl3 ڱVmiKR[K#sMwkkqkGEb 0KreqV<)>3{t~3Z2=իW4Du?OӴ_(>u4Mӳǖ4>/^>>>+ t;w^ݼyRje24phiinnnv۷Jrh~xVVjkk󪯯gNTUUm  Dް^rpPw}$$$>`[|||8(qj͚57k֭G_~t\722wG䷆;g666 `RTD$%eeeUmذa@ sBĪTҷz@ +tong_X Bȣg,R%%%ns\2a\a₂soߞ_PPPgϞ111YPP'11qIQQQe|||Gpwup- |ng̈́-((`]Fp:99RE{{{]YYYGFFʥK]60--mV}}qsʥ+nR4Ba@*G<4m`***cuu^OOK$\rŰycΝBHDD?))IV>~;vmxxxZ"wN& 7< >i^PޭwyillP---^W``#ffffܹSJ!MMMcڛ0ec!$)))-kmma0zɢ5k^zSMMM`snȴZd]]]GmmmSmmmkmmm8aÆgZZZVlԋ/|7vorr666&ˋ5lYY7n@4_XXi2{فvݥ ]v}jM. _ 900`ZxottVZPƍ~fgg?+PWWSuu!_O** dK. _dI,999yƍѡ>>>IYvmnGG~ttTDZL{` >fs8gx>;wL`ϟ?@(9R0 nݺα_ 455Yۇrrr###cV58q]]]jaEZ9rW~$:κw^L&޻w`2` UBB(Wۛh4ⷆ47o'5 Ǟ,cbbFcJWWs#XS,:ZL#ׯ_#˲DPWWW禤y,K~GP/j``fcΜ9s۝MMMYYY111bպÇ3diCׅ$~ @2w@ 8$$d[ooj-l6L&mbbj4FGG-۷oR>9vXdggQTX `Ş={rZ t!sv.%TXX{˖- ;eljj7olɒ%$BH"!,˒>H388E;:::avӦM Wu̐Z 565MTiis۶m055_`Alaauօr,O={;T* *Jt:)LJ';C{Rd2MUTT4p9s_v͠'1X\ }ܹ[>S]__u4;;K$qgަMOrʃ8IBBbjj*al6Ĭy1ʫ**pddtHrrr|KKfjjJϵQ{-yXZ6>}d2MZ*C,S!r<(N;wnlzzz8!FQR\\>ov|o644\X,=!r\l|{)))A=^HHLLZlYH$ Zh˲Xp_PP_׻}]úuWZスYPD[, XkNeg/^hgdd !N@!ä*HD"ӧe+.\̄}"|:2|򼶶7x+Vmkkh4cђÇߑdoF{ԩb8q!gR)\R~.Vjw R3ZccׄR,t҉O-8p^dcccy e2!JsrrI$۷o$`>A7o~ߩu7k4uGGǍ6wcbbY&j/Z,QXXWhh}'&& "{Ұ1+tZz{{۸LKKK]lY^TTTpHHpxxtկ:;;WX燱12 Ì`'I< nn'vn*ʐ`!`0&&&F#E!r\T*ry{{'*d93Z}! =!!AH4PTksrr_;Oӵr=8f^^z*))I|!T*,m 2f͢jjjtuuuopQ `ɯ\a _ٽ{e??CexvB9uCCC"H)I q\>ݻ/.K|Ǐ/ޱcGkbbR 89tp9oFójww߽ju^o駟 QQQ\]X)<ǩBHnuGpxJgIENDB`instead-3.5.2+dfsg/themes/default/cursor.png000066400000000000000000000250151467622671600210470ustar00rootroot00000000000000PNG  IHDR>ŗzTXtRaw profile type exifxڭYD /x^o=]]R 32"1_J.J-g˿b?}lϋ37 u||=>^^3ٮ^ 5V˗9Տ)yޖWoc!K O^#x{vgN~,>gA>t !8É. %L q}|7β^00xZ?o(u<212~kgUd{̬9'E~,SM]On'C-c'5xќ'E\wό3<ˬ; fQ+joҎ;ˮ~ 't)v{ܫld{5ʚ 5v ':Iё hbܠj CU$,2Fv>77=sFd(u2k~ڒ̛[l=K 4&Sl]ŵҮc:XR:v>Fϩ33Єپspi-.h*= q(6v*N{Թ<чeS>{mk&rBC7÷췄EFlbJ,f`*ޕ*[2uΐ &1k9>;F"k,K_}ͳ鍱omClc͋L 7.)=bH62{?3- $:OZ5wj@:c49-(=+%vqv$'O*3ˋPAl@9avZ̩1iL7yEvXs5EYX.QMiySؙX ; 'M(+J73B3\`ZNQi~bJ)s$"9 վ j,|M{pu #;Q6EH2C)a왻 0SnSʊΓgϥSrE7(r$PR@Ena(j-& 'o:pdERyĻ4N5ӁaI<%BЋXntta$<\fƃlPN I_<"wܽ}"K0F1}w0QނG'3RQQi#]%AͯIѫ'F .A(k&话G,ʓ)"S& z!hos yN`Y~h2z!ϱSdP6qŌ:apwz"MBC &(<P!Jb{.9 JvWKG VZ1qJ:iX+uN=︎,(/?Urj XNZbX/nUi_ݓQqTp eIRh[2cvXb]*V"l#1"k DoO`:咹D4' .'ޓd CK&&3٥Fx7:Т3lbg? #o<õs=gڛCdR)tsiL8Gmsrd Pcc 2i@xuDO4Ch>}[nv4)YVx1d9/d,_7œ_"scu7WIR3KD9XyW[C*OQC(%b Ka7J³ QKmhT`ξAgmJ-Cja:`ϙjY༎ ʜH|}l2bQ Bh:G"jY!k \`b^G3cpڣe6%"ԉb{*9 |Ӎ(W {Mb7h&4X!ʙ)-VA=|Th`'ߙC0r^k@ >c=>vmEh'sw5A^vve39wč?Dgxx)`Xj8 BbdV C+<R 뚋fE儫2K1 Y^j4C ^I[.8V"̘&s;F<8LsRgmg/t]7BE i¸ǎO%%>~݁yq ъK 3kgќ걣hC?Rq;.fPA 'c3z^I*?EHx0o{wkj}Dԟn NLwȩ2t50dAG܌Ú NP' vfFo1)q ΉW[#4W}"kdchp~ҍn9m@) kcN;i=:M%¿ۚҴ?]ՠ+K001x,3Galvdt򩂿oFD%HFE&v.f*,K DS#ӻ &q]6է-fP)s Y@SK>כ̴]c)f Ѷ[pN 4ߨ>O۱՜!+Lt 4DNVW'1)cEp'@L~ /9(QD0ʧ}vx؀@%A2mY&vU+en d!('I6gՇʚ^T(vO^tA C|$|Mrxڦq)hQoswse4Ʌ i+ ǥ!a)˭e"0PwBxJ?tu_aQ0`iWyi|QQ麏͊#O9Bu%!˞>=Ǜmxt ռ)U=l"#.ݢ809&jYym>Qw}^l[Z<<(9PF0Ͻ(ic:O6.4 jw3[FH2>:9ؽu|)r$\GiF=ԵW8V~ 7idk":MF1(}o}qœ@tI*~y^xwGkoikr-1IiTXtXML:com.adobe.xmp 8/9bKGD pHYs  tIME.tEXtCommentCreated with GIMPWXIDAT8͔AH+GƿlۼĊ<Z*4hP  1-xz{M/@!w!^<(Rx(}/lN2=t#}:fHDDȻR&2X t˓dRaR̲ɹ_G1i`0H Hl>J}(l 1 BPh/ڞis?Avvv|\N:@D"M+TUXEU{WWWқ +pt~~N2(ʼ\Ǭ<W si' },˥REQuJ3' ̧h=I]u ,cccz X]8ݞmdjj6MZ:y!es091ghhmeٽZNLӄ;Z[[kf77؇q+ 8c(0pss!q]ڔR PuA`jReX_XXx}qqQlmmQP(D } `ds+++妦&l6BQO<[PoJ.666^hk*cD"rwww^<6r@#]]]/--}^ޑ$6g^577W...lJi5~/'BSW<)s7nmbQw 枩zKY(%m'#P>u 'yN-IENDB`instead-3.5.2+dfsg/themes/default/menu.png000066400000000000000000000231011467622671600204700ustar00rootroot00000000000000PNG  IHDRw=zTXtRaw profile type exifx[gr S83A+d֧O%XB?/$m9S!())W+'?w9ݾ0xdn׿)s}`|R_/㧧D)2@ydBbK♅:Ā_?`/]<֘aUkYX5d >D*b?ٔ@ NTѳVn7ϟbzNx(p{\'ifn3?/|!~%袏!Ƙb%O!Ŕ(TcN9R0i RMU_C5\K4| -D-Mq{깗LiGqG0i~gy4-~y5}h͈ai ]c<N< 3NC563sXu3 PY9]ƠA7Stw܃ȹKz3U#V7Zm$b7d* Cb&Rsa"F%o L Ib(߲iVB_z8mQÅZiD44JMĵӜvjfc3 lX ;{n0qMf&vdNqB0,A_J2p6+ 9̔E{_%Ya9`(2-e:v],QHQ^ E2C=f +Q*n%1y*Zs|EXEZc̙*3D \ZM"d8H;+3h !^+28˅^M ]Y,tE.gBWr ]Y,\P)󍱔%4m: CwI48XrquH)j$W(Sၨ0 8d!GxenG+P2 0BPF7i2Z6_$r@ (_ - WM$] kWrY1 [KH숝":6.AM;[N'c Y<׋NQ^/___O/N9[eNit[/E{Ꮳg9f##bQsv~jQ`qMw j0~{u /t^f:1`U&sLLQV9|55nؕ-aETViJ !kF5(L9\Vи~2.4kd;ƀ(8tT)rri`5{ai.T]OKMMkI}#%料yj2L d55Wݘė7e~]7e~]L@Eqzp& F ,&ԍ],ai^! ]'? Y{~QM@Ak(bW]F5Z tJ=sVWz>?AcNhS['jKW8+T*m骐$K7Eu[$WMSJNn k$滌5ޕZ~[ m~2^^d*;d7[Ar`G[˔sO PIKFA 4m LfvK1Ug!b1''!&Q8>-U*[ $y"12T^Fyc'8XtPYDgbR6!\p]p 1B YB |M&"Oe,T&"Oe,T&"Oe,MTp2L(ܕSj=cB'2GC𯳂W5*UNVpyrFq %?"@3=A[0:gȧ@bt, 7D+4`TF댢ٌ]VKU`cī({ %#spD@+ ;cR'gN Yt%?'E@l6N2s᤺H!%M_*H"AR'4^3~A# <>wاw}zwاw-\LإϒE7yV>,:6ki^K[N{]{c^)eX5#2~` aXL^ h+F [ZJHJ$I-țA>46X!csm`xKW:ҕt/]|+l!MHbqo2S.f /6ϿmnS=WEѻλFi6kt)'/sQ@郛\Fr'$"X\b+r9,"X w-+ :*L7=#>Z=ٓT++Su)ʹ{9`>A_b 8YF=[ZqAV%ZelA^6Ws+s!O #[*! r- #^gq):e*AEDlTҩGwkA)0(IC3NTfX"[j"]P]gh/v#<"l텅#߾ e.%$ *hFȴBHBV1¾2q_F& L"iy j1Y|qF;ErsfHz&M9Ѻ9s]N (7g.ʉ.ˉ*'F?!uq۵hrE^N9:c!psĆ8RD֘pT"Mp :/4zSBtGg6jk3OUR@bD\+/g'xB7c_1;`u iCCPICC profilex}=H@_S"+P,8jP! :\MGbYWWAqtrRtZzp܏wwVb1hm&11Y`#,3˘ڎ{zY9zԬH< & ޴ !VUs1.Hu7y2SyoaYԈ#SXY+UXuCcK BAE`#JN$]D.\E0r, Z /):_c|;N?Wz_3WZ.\Olʮ)r}S׼8}RU88F]{Sr>iTXtXML:com.adobe.xmp O bKGD pHYs B(xtIME0 wIDATHՖ@,,AB _ ظb; l|Y4 ؘ"IkqXawQx<4h;0]JFKQRJ !BRJ!. RJiSRJAHtZwm4M#V}??)?~şFL 90 ׾ol|qd?E5ydf /4I9Loй ' ?DilC'‚ BnC39 Q~qTl? NS~bY0k~9Cĵ 73kH%[-Ʊ3?r\LA(%2*ӣgZccߏ,&J"u&h2W`#~Z,RJ-2ʬZj fK-jkfO=kB#eFcE'g|zr+*kng]vmwǞ'tSO;3oͷzw^~^߳]?~Zҁ~"N90M3@@G͙!4u3?"YQ"wY49'hƘ|C,/5o9M9M?l͐PA38___i'w_|-xG~{ct۸ǻOwϙ txlNut\Xq>ru؈u܀~%3&%NbUnMC\xGz; j9Y_cȏ[?5 n1bRo;W{zt]p|Nm2Т~sZK:F%'w]1^w,=HfvÖ*{~7S6Gi^>Wt`4NWum5Ͻ͏uzۈ6*/g(&O3{p$=F#'Qxmwۉ,}pi+sKF־+%8'IW3vZh)377Nyl\k7.u9a5śdkY{I5cpcͅ1 1{ԺRx: zl%e$ aVI˗2 Ļ'xH}Z]IqETvΞc&tDN3ݵFIZ9Lh2sS!f7%gLEu,#^$(oZRy, $p5cYåq+r%})o^{-= sp$~?湑DH?\{Y4@e?c4Ԯ.T%Jmj'{:p'(\߬QH2w5][8-p m&d665vY12))XW3qg-f6պ a86HR0}M%s';QL.{.9n ?Gtڑ>BuܶYD\avo`} 6NnDG] 6UyC SfޭZĕ/Dw❭"sJzs$6a~]PQt.gehKCȓT4=6.?"! gCg:Gѕ\2ԙ @l$q[+T+SR& ;-n`w 3nXw5kYJ8'luadV#jG0uxg&BM#SIsrEcod?=›X&xDI_ a38{%// 9_ :Ù#o `8 jj 0 <I OIp 4ޓQ5nU@3D/iN2hB.IDP`s(k8YCO~W}c0z W>" 3Bx*:"f 5-p5 y%O l1 (&~2 " u;``Yմ`*WC@a#Px.AM~q dɖj R1,:U}c]>E-ՒĤ . q$%O0&bqθSs"O /Tv<((# !@sB1K˾L&.Dt e/ (kFsC"GI@7NvX/ ӸB3y풩 o!|PEG\N $˂V؅Q:GK"#+:nq ՈSJGB O]?UeSpzi1x-~ jM5Hj: h9x}&DÍ)B\nRN"8h['XE/z }pIU`oxrHE'0% !X#r.+済2'P9 R BΌ 4isJyQe^jٽP~GU<% eF85r"QF#'Z21+TCK5*>{#J uFgL0,MA tA[҇xp.[`oJ."A0r ln<`2YK@@|iJXGJ< >AeNaA85ڜYT9@pH:@,ЅD`# %jT !|l<]-s+FC\qn*ANzNĉ X),DF@G}\$y(MƠt&x[d_G #"2G`KN$qͩD( Va5] <>!6A# dD* eD6x:Ie#xY TC&|<LрLOߊ 9Мm2@\uV5١J 7!DdA>7 1Mm8>TcnxT&HDgCs55[`-"|H6I:;__Hx8Rt/MzL ݀as>@[UCmx;g1RAX`l>aɹKsIzu'வ~@?\_BgD&P lĨ|2Cjɧd>K _M;]q<%\KJ\(5<)A^uScXP@vtᅢQyP'Gȏ>GYp5c _ce\o<p2<xt ,Rр*ExD MWH=2F01$\PTr` nΣGїcm4]2T _AΩb cs$QcK3ǣ{e ~[Iъ ]D#L/|~Eh&9:p#&H.]A!\,)ve*rҫ@'ŜǸ$H4;l&F(T6Mg (}Am| L#.HY}v>dF>sǭ(]L)f(##$yI"GhmrwCV Ž@0|9@q2XZ\a_3Y#y`393ǟ]j{}GX|H"r,²"Ր&#߂tbtLUt0ܓCf7`uUSn矵_U;QE _Y8@e*wc>?Z"eі]' Fm?wD 6mxP5(޶Bjr%U.R/œa)8JVd:iW+$IS@_}] "7A94h7],G'|ZT2]0,_|Hcn";*(u.VR oXF9l8-Tb#jM̉g._BIɐ>gƄ֪y~[!qT%"~6P`*)d,Yg5 0 ) s@Y~lAF.;jں,c7ع$'ZcE:)"o? GX3 ĒsDZ/Qՙ7 c̽nO&1)Zv#l N,TU(;DձT ~ k/Ad'H)\2hJ^T +J&^ %UaA::T2K Wr%B$4RBLkQXQN " R`]$HZjGTwysV$ijap,8Jx~չa{gD;ٯŇB*T.*U=UQ.LRTJX%4_,QکAo x(y멵ʋZ{([R V TlHb)SZ1%d DEarގi{y[b%!M%?7hE_(|DChʚ32Eed)Ui3~U'nNR Q$(Gkh'ݮV M NQ|ZrxYm sX&:V9.)^kX r𓌉 +AF"yZv3L΀vb}zƖE$cv07(/[rI#f⤪avV^"QL!J Z u;fOe>UGjUo /_!L /@ (0Aŷr hn EGURG|bTgrYCU 5aK̼zD톨Ql7 xČaʐ(j{,~y[ւAq2ρ &H]*@3f6/*Aщ.x\ɦ숆 "Fu1EAW3H%0ۃ tCr^&g*lOMA&eb=Rws |<"!;@'EqJa1qZD*T,!E.'cP/$6"ٗVɚ ^.Eg@lAW,K'iT><# #p (e*?+=䖶,KJćW,JxK0Xx҅3>-gkG7psUml0YBN҉U5{ʴ0 ]f4vX ӻ3-ZǼ0luhxo<DD -!ԛks(U}[ clS1D< 劂jv]v|skv$~u1P_+Iyc|!ghI k^utP^ ^鳥Z3hk-Mt+qj}liǩOo,$"ZM&7wSXFpb5?'W flTԓ_PMT'yCmkn;y ڨϸ⪄m<&:ȉ?=TZF-2Mc`\TNj{` $J'ͥPyT 9}QH / 2%[J2M̨)PSUU+;mʽ3F*եrkTQ|hYa ˋPC/[_QCT0@Ð'Cr\xEó O̘{^(=G\;- ̆@Yb#Hn& h]E8o AߨmKaMk2YI!! LAT;X-j1WТ#b[Dzg bשIAzUW-R$MlRs|^wc^ǰ=V!4#Xo ABeP|8:TG-fjYb5%Zjg` 9ã39U5˚!7JڡZ7nS00rG+xۗ+P6En`5[qZ֙Fj݆'e-ea[{dZ(\UrWUI~M p:sCufb.ΨC:ZoxCKEcщXÔ J!,ΰ˧D5paBoj\",VӔ{ps3zPC4ex׫ xJ\E>i*9sio72R41)L g/͞j뮝7J[ݥv~Q֪m|U)7H[W^]Mhpװ(!,';W$k䠥rJ/h%E3PNzZkbՍbtqF--j8[]ˠ3>$HSZm;J.")Z'ϢEŦ.FSZ]Tx-+@ p(ʡaWy а%BQ#_"mXt,MFHҲ=箧FMLzO*c|>um/}s!CU|yx@P -l՞~GcúX`ubYc˦!.\L%Ҹdz'eZ?]I+NkR+f;TG2=/Wz0Rk[yMOF;7Ic-tA,.m -11'BoLkTGQkt@Kf--葅pDrpa;yɆBЎdhbZaa}N+ ^^T&=W DS%!Гݕ??YNL!6o`͔ZW4A a`\ #y]g*N]'F_G 9kUQPvu )୙9$$e; qoӾ 1"GhAT`C7 ЪVVVs;kײ1".qYLݵ^Fr(ݴ,iwHX8z^aRVԍZ\i 3jO7-U<> ᤳAoEZ ^ X,6#.+m>Ѿڵm$KT"dU 6T'zk^HGZ~ PrDeb^vaɨ \u,Lx)vS=k9Fv1*&/#p6%{ "*Әx_!&1sPl U+TyLɳ.+C o-+[BܝO#v;krTk%mfMթc]W njW@w(*0Q1Jq-{O,"}USyck1V·yAʒH#PCΕ܅y@ @m/eM#6BJb(k7Cr\dWVgw$}F8 |?G\MbSZEOJW~`>U脽~?UWyP,m HmZ 1jkm iA%nWd$ [E FՋH(1l/PMc$ ns8j- /ϥRF jkQo5xLe1c\'ioS^5N"jDf"hbGRk!^{b#>N>k)xXFW|nWmzb*骥OdzAXͽӓABSE0O@Ws2*`!wsz^Gz*؉4}}  " ]WAѵFA:y0) &uE]^x>\+pTL@թt\ݐb]K3wmSm([S[eLm0u,ZM״TI Z מ2L$f*J\LuXuhuB&ny$m1cvͪ j} kzżyޭtU4Z-c'`m@Tha{u lV?JSY{DFn@RUF5mӾ+Mj\Њئ<ǥZ\c_jLj9m?-8OS|I-Zx~zv>t ^ ӪWeSkJQw묬1mћ/noaBu%]eEpG׻SmS3֐3| k5˫iQ >Igْ*h:a[e2_ E7V!*fVM.蓴R+zZrڅEadD$߶.s]M*("0,?#gXBK3 V!0NCliF[M s@rlӲ/tOhBh UOA@XxcP:E0_@t wQƳmEDH ]dlbdwׂ^eJ}-+Lߢ&2wd5_IC9a4M6Ku~teTfCGD;0 -eY;'FRwRH6a$!X ÒQDD|zHKVN.mtC/(sLѥ哽MڥpV_l]WtB^n%$e [Q˛*W0OHh;m/ot%Ecў#0\*En N@oJVmYfCCT"G M&k[X%B3TV0%K8 U+qQ/BۼmSږbNSxWul 8Q %@g;]V E^uDRY~3qĴ:U}94k*A+(t0ru Uބ| l~Y)ݚ}[+ZI)IzM3Xj_^̠cU~uQy!6m qH4`ADC|\(ZY(aaG g+;_[CN,} 9lTQ;߬]WM̻FqIYsW'Z˚k6na;GlCs֨>mV&>*ȳtcyuj31o7U'CR pz碪…BblfժzsxXT<`Ly1푟|YPyG62*^LDXӣM8բAY;Ct,a}97$u`k*(c ,gma"++R r8!Ў$:kTz1^5ۋtIk}Ò;^ީQ 4~Dg}70<|/K?lQz[~_GO7hE@>&txZPWnK~zrEVzYqVUݎЊxMAv Tf>I4н \\74e ٔ]OSf34s tyq$ pp({Ż;{LrH[iTXtXML:com.adobe.xmp ,?-bKGD pHYs\rtIME1* IDATHǕWkLTg~03܇vK+E0blmheAcESUkvUvUF&"5eU 0V`Q20̍_Ǟq6|?<y/+ (*%%%wxxxx@СC+ڨ>Z$ttt\}?0gYA <Ç7OǏ;,n=`0xҥKOvѥYYY[,@ VȼCΝ;y<ZEh!~bۉ@ nݻ7^nf3fn 8EM444ZVbLy^***;66+))iZx1&[juE vfKԔ=/88uuu}m>/ gݸqø{^W%wlQ*---ggg'EFFz{{g&''h4ce.(;T i) غueu8P 7z||f2lzرA>_ `)ShFռ96m^(++Kw;wbّ6lXfIDDDDtttiZ \.yzz|nP N6o)Z~I r+l6fsY,ܜSTΔ|WYYm}}I^oܻwrʕR1J@ Dgz6n _ZZlk׮?fdF`Z܅  X @c aLKrDžB&&& ؋-,XVծ|ImH\pBvjjjJzzz^Pg+JW^^MD"ȿ꫷3224MmcXS.x8{zzzKJJ999SSSNsdr ݙg B JkƼNmVY`oٲBɓ*NgUT2l]v]h4C x@>LƩ$CqUUU|H$:6144XdIʕ+ 9lBh&NRk4~$REWVVJ8Οϝ;wl||$`ץVkjj'&&6m200p8K.M۰aÖ ill,hFKKܹs^PW("K dzP&?3bo[Vbqk,kakk듼t볲K |~믿F4233bbbZ+**"=zv?x<6DbkeV[[[J_  NGǝ"(9bj3g΄+5E8qz>('XQvݺz~޽{?-,,\?VgRRRDǏ.F WJѣEEE/b,]fMlGGȣȗN9pq^0޽{'xd2نί''' KyKIIy5---,##ZdIhxx8!x KKK+D"Q$Hw^~JՎNNNjulǩoF4tuu._66Hߛ,999N*t:gϞS7olUT0P\.7(`0<@͟eH`a,7NL&MHHx%...m4}ssszjF!Ɔd"?V% f䐐BXWZZ*&fɓ'*7987o:d2Q2K4FC G/\ɒ+(gϞعs絰G- BillqzzZyvkL=;诀o߾|>ۚӧOضm2;;[<_~.h$soѣtuuhLJ}AV/a!$_ ef:_ /'zhIENDB`instead-3.5.2+dfsg/themes/fantasy/000077500000000000000000000000001467622671600170425ustar00rootroot00000000000000instead-3.5.2+dfsg/themes/fantasy/bg.png000066400000000000000000013773731467622671600201650ustar00rootroot00000000000000PNG  IHDR X'sRGB pHYs  tIME )66: IDATxڄYeq}sǚ =wch4h@pIbr0$R YrXO_d@Za~pH%&E&H 4]sխtZ{8VBGU3V/27WQIB 5Z4#@Q @E$GEԂFbP @23@  h0 BHF -F@@0If$༘Y A`F3%_t` $оS ~=iӏ ^ AʫYH|mBMH!T`'X4fH(6U@@^H@( 6( ^ 18 @xiBTOfJi- @REEpi 3xAPQ8|J޲l(FjzvcAkj@̰Ea; J`h D4OXӚ/_k%hNw2lڛR0D%bA N\;mH̊E5V8:΢M q\j)QFD#Q /TҘ6 PӹCgiӆgN A!I016f#'6fP fГgDy;sBb!.)($Om`>Os#\'p•RB0 X j^X Km4 3}Ǥ;+ I̅!hx {瘎'Cc7pfxٜQm\2EE0 f%!%Q8PGS j`AUS@Ԑ֟s`hfDl,trh n3:78: *FU*+icD:,B ժH4եb$P!&Н\ y>ًSӧ%-!D`IԥZ{Ҧ[#tNbg5D3U 4 A !d m MjVMͿʹ?ݝhe )׌G Z$ZTK&k3Sv;eű3n|:r5!w{KQ?-m('1yvz74l^Ҟ6͐! 2B#=HqdSmlNгQ -3C"bz{%D-I@-Ҿ % 6mpnD!dhv&c|)6{ GUkз@ Hxj); t1mDCPSs Z1S_7:<))[VP Q21h)Dt:ƈNbBj0YNof tn26 1]1fЌQ1/I5(Ln)V R]vQԮGWK_tCҹNRz;KT@&d삯b v) p) ц=ς$7.G-r0%?-Β!ΓH']dfF$Z .b0Csjp'*(RKzf!śaڶ-3^ՙ/O5|RVyhі܍̽,vLx2EHD am6K7F46Vkf ;LGU WKyYm:,IǂeO%p@0xAY$zChhC(GX k`"@GB8.($-/i) q GeQpYTxݧdh";#m{SrL(׽ML#ςm^D?g 龷c[ǂi\k]bE"dl.GGH A2` Rm $(a7\I޵${ rN͑< R~tpyoWhJ%?(:2uri(D& `]I~r.2fYxKW:2yquq¸Xs_\3P5@x0ӳ+x$ ;s-s/{2Mka1IǶ#?>;~'T pfl-ݩ<Ȗ|eіR֝! vGW $s@5V[dUa@̂Hϔp*p0/#,W@^5"+XN۪g{sX%L[38L $@ӲB R- BK}  bDC`!=b$Yaw dv46ۼZ焅01iф!a@,*G'?M50x_ 4Z\;:יPL4c\c((B|LB@b,AB|ˬty|blp48둸R Qs @F-̄΂FêDЖ `dB&E ?:`k@`<Хh^!Ƅf! 1Sh$[lK }i{aP:*^(P9ulvu(W[[ C%5b['Ub-+C)b=y^:4*mBNhõΎiYR4rT:ƅֹ*B5"OvkfjFA-AXCБh1hah4{HV2twXFW joI"^iL&9S @bwK}dS핹\ gxsP|'t`BS([QBiUy-YQ!|SGqȒ_ Kr9KǙ^k6^6ٕіV jfp!JGZ{i;n=HZxk>fx[uIB26sŽglfBOK> ;̿,mYz7'1FjpY S3@1GgԠPg Td)jm$b 4IjU]jT",RH jtۤ m-<>kg)Zgn3abF?Zæ,x.f&*Sa1FA$F 3`bȋͥ,?_ CF#!V KBK@IP C4O7VkJrdT` mUTb֨I* k3*ZЬ9B:"`j_s -m`7(g=tgN zWe= ,@1Z F՘a% A։cB=Q`jWvR۔(ż`icht:)N^ɍS-coBɱHpN aP 9{s=,uvxjiVs.$!,%L'/eؒ40˪zw=̌h%G^i!!B~;im3GڙIc.su> $p`b!hm"!;]Rb!sN I>ԓԉ[!EJ8 ZJIKLsO6$Ɩ$y6ȷѨEZ|Ȱt5,FMuiI#;1 ,ҵxwk9CAadm|΅ݏE&pOjZQrH@ I6s Z˒ڄx UmhQ4,\{gǒV.8cR&1@5ƟҳTj:5,Y^qv?ω"*ĥ#.g3T'X RzVNHetZh[l. `Z63ȡuULBޥZsպE*BfOsz%Sǫw/Z;cHebItJaG5'5wmIJ,LJGi%#@5ϖ*2p Ǒ'@XvGV"^I'L"S7*AE us(f(D*Fs$ɛc8*d\P WW< c!&K_hRgڗQ56D<W_゗FyIge%| $t  e W<TJ8vтb1; JRID8z`VNR)0si#6K.TwjxEG"4i-YoÎ\n~DjiK*yvVV:L!~/BV ) G'0g:2XI0x'Ja8r$1LM$Ėd&N<+F*7)i)$Rޡt鷠rL@jHxLґ4!y(41'Zs8t 'iTD,y'"Eň&;)NѱdE i#FWsc/r; Q{KpKof3(6`ГT3)g?ڐdsV3S:J*X,#2m8sӮSﮕK\u f >?HohngwNc?LP@i.)|g<^,:K tBimlv[rT':ӈ' @bu x%]ۅ3ö,ÀKG˕yp"e[C*{8*}-o2`uV! aN](%yL_W '/2ϛmOGXq1 \O,ZVzI^+NRHȪ,\ Y|cu/@ 6 8Px[rC9q\ fฐiP^4VU+DiK+BKWkFXs @Ӡ`ns wB cyjGälaܢH*f,ERŧVJBLJ`xj8ӐЗnSsm`'jhV4,QR Feq Rመ dI)y6WA Qu ũڋw, vC/"Y!mnTHJvKҷZ (=QihI& "~X @"^9ϰX~rr v[KCR-QY5lY[2ے͖_K3 i{>G)e$zQU--1o4Qr^C19ihA5fsHN怬@ʸ}vuoUӰ-6iyȖnv?:E2!f9c5'ti1QA{׋^qUvo@R 2g'Sm LΓuS!<4]bI4T-{<)󵥯:,&T%eb/ah]!fGTua3RlY܍O)*1{PL fI(iHkm?hܵDMTd2P.[,%QD\(uVu,>"Bm}z(ф<7TAHgN% $HG=C{f;.v8km9vV3ǾI)ٳjgo2M*ɞQN̺BL<65[i.3{3WihKLɻfI葴,niSRGc~HhASѳvvhg4M-q74"&R$TI:R")Kᴛ܏!iKs7bM-C q56Bk=4J0OaJ/lF]i=3Rx?7=1DxsJaQj#/Hq ̢U 4yԄ$-r_E.o7mW[>E4hky\Io}a08ij=ŋD'P' A#ՆuTYjI]u()"e~؞Tm_"Mx D#%cΜFε:kDhuT1B6^AM:)ט[0oE+ԑbի<6ҙ6ĵb&QQ/GUxEӤYƛD)b h$\UY (\f|GZF8 +U)Egkft1yMx| c(L$ZLEXp*&A8e)m49謤? 5R)MFd.A_{G I1)8Epqj]`t:.hFsA*JCz_bd\pZ4fjLuvZB.k׮V m#y^.uF.h$āyE'PDx'3QgyЩ!O*'MVIh[P(l4^],R1fROU"l6H kB\ jUn\+iMДR.lAyjb:i)q6+.+OO>uu ~gq\g!-۳r4 :㢩\DۡPDdϠ1&PH:zFGTQ4,h @83,̹G_{HW,TS{I!D3s0J:Oa.X Ph4ib*F!+uIsjMV'0EZ [@5MU=uY~Zz}Ou n*oeѯ p*Ɛ7DE&fjPS .6V.~|񅵧.f4@ &8٠[+A|@31^#@ Z<)rDX<̄RVR Šb4FU)i15{׿x :37k(.cTdɑb0)˂ W)} '%cbQQ5"Z¤Ө*VDҥoɃfu*/J:O}$9)In(ՠƁ8pþκAbD[).!FVp`--2?ROC3HېKH6mvl1hĬR-mq<2VnR[;$GW>JILjKy _&5J@-ՅC,"hT]vƗD.{sE4䓼cJFa&h1+` z6>JBm43'j 'tڍҨidy*hB9m{H/+kKk+%U(b#!.sC&vE'.7uUKu3*EB!Ԋ,E{+Wpe5kϠTFj& x(3`buЪMԂ`(.;vI<7Ab(:-Ji+@l"ImiNk;~ -\>DUMsh*٤P M h*E4½i"§bh\Y(3~Jבɞ iT<>w:y'\?_Y cY_P'ިzcTm_Υ!97<4P`*lbQt~I W)\v`78~5#V_-RÐ`tQ),)lj{%{&Męf}SǪ*I딫i0 "!P441jYq؟vyv'lc확OmzqAȨ*BMD3@/lT&FE   E*ר3٤tǿ?6 Ft&Ȼ􌣨0 yUBi@Vyz-=J8!suz-1Z}]%)G! 5p 秵"i"qУ A9%Ŷey^q?>h"~P$?['ݩb}T,v*Vd]oа\(t⢵!yҴ,KeO \ԋKw~4U4aj5M-A0S5B̒ @E.cZj֥%M?{饫dz7Z_dREEE, p((FQYX'2FЂѢBRC) A-Dӊ\jAԱbi o _]}tq<{oWVUj H/0CI,b,d#i隣"jpB"ɨ7n=Fih(( w_v"_'87UTXQ}Kk[vT noj֞uo;DM4V"AQiLIhD0x;>ޟ?[5FIZM #¬plhCPq-?[,rDG";FOӬ 駚SU0 B `:k/gjT]k/[wn/}>o'z`."qz  ĈéHjTb \ByUIPU:);Aqan! jEH8E$ c0K\gvDWl^ii4IQ$pɟ:| !9"c #ӄEyzсgA.1FNцZ9.+EZH^>|R=X 0Afھˑ>q:SL _~G|ٍObĹ^gwn2)V/|o[6/b_^9r^߽߸Z^g2)K!(%gy k~מ-]2 k=mOo>}:ޔ0XGa$c5պgW7Oy'{ 3R|gɪIߑ͋u/=]NkG%Ŀ6ܞOѼY- )R8;o\+ُNFٴFO'p< נ&&>&N#w_y.{quhIYc8<?l|WesaJoe۸umBQԅ8m^+2{mݧnkoOOViFVj1\YYo5//gGyͽ}'Mu׍.:b:?j_ZVO=_oM?~5f1_Y+¼zQHW-gOK~ ⹏=-'jN|a5ܞ񢼸Y- )yK/|k}6ht8>o`zը?eES^bm"+׫ُ(>-:%_RUCH~}gqK7.zs[_wrxŵGɞ:77׋wkN8}\|TOE#5G~㭽7OoXr{X &eǥ{lϏfN/ =wfwv|o߼^\ 磧x(/1>>r^*'_x~矻6zx֧_I\̎ת/ὦ|}eO>?~Pr%<:,CmR535FQ78еW7V^^=/郃peSx?w~Y͟sj؍T'X+4`ZϟG5kW[՗m~S,ƫ1/^;eu8ݏn7_8}s;s|',&O]ݹ{8_LNIKXT(f##)=fZ<1 +4u!3l0<5|$`=?&et`d)j)M)\}PYK.S?BEOL̔gܩ gJi+dn^d&ŵm g wN5UJ[nELSV%OJnґ-M'W7bdserڇ߿39o~qyg7]?{?a}Ԫo>8 Žw/ڰᝇg5vltt~h|Nw?|x޻8nz?W_[p˯^8E~Ggw[ǡy{$n߁>GGȽz:>];l=ywk-sT{`Q>xY||w;o7noۇ Aexwgo:Ż?9^' |woƧ^uOo:?nu7W/ͺ qӇG<9hPfak{o{1>z|rHޟc㽷oN&4x~0[X+N+'^Ѽᨐ?|۷ou+_X?[z5[/7VWݪmo]8=~mux{?Rֳ&4kG[aqzPNv*lUQ~_϶&ipGRȁs|Ist0?>;.\ؿyg{7+/b7^]{;? _zvN޹7[8{d۹{p<`98~wrk߿G޺z{͍|x3:\ާNQV%.P 8JZ/7 @¥fn۸Mh$S~O?FZgfC◧eYfM.HhTBU y$!0AE领|'!98K}8Dٙ^_[hu!( }mIe j{&~>U?ڼztb%*l"&AxzhL)NS]XX$8& 9 |pÇCPPQ7]P[cp$TҋӰC$㚜:YX䥬*J}jpQvkRagڀ5{u @ݱe@t%M*sEG=C-+7_ _fwlK{@ʺʃ(߷i ,SqYeǀ祭XD!"i,eUNɱ M1xZ#fQȰkXy{;G %JdQ`eJi&}"4c\/EX44& c kHBq)W:{j4)<ڥWl ̢4FI4segL;vⲢHٗ4:| oj?xӢѩ`Ehwv Iy"d0PZZ7UawXG,n,8;ej*?,3KuW/.vuOHPh;k=/!z"-+p&XnOAPCEfqn,]{<ֈHEFE\cNhp/âC1XĭcQjr,VP}P\WV.X$.2PH,.Lc>>dz}9`Ď)}UQޓ}5^ViY8rOSw-t;eN\"#WB`. Cp@XRiêxH P"kSF|RY#(y'UE߻s}yqH_D >:Y2TTw=Nj,%Uv*H1}ykMiMCa~ę- މ\zK)FPlCqDA|50!^]QW-/Ò0P8XhWHV,3ntYuQ!)ĉ~_FbٙS_ݯtqFk݂̏t*dHr8]6`cDu|{ʗ!((tȎ}m:Md[ `qM,F%cc-#n*òTBZdMs4(dH֬PQ=! 3>>bBȀ9?s؅ސN&f{D7+&.?/bD{ZOdXtJ_eue#Č="dϯ[0j+l ^wx֌|$ZSMj XB[*tQ=",ZQ29Ew{Q2ۜg2RW Hk6j)?,`: JUw?8YXs}{Wo&yNAMЀL @R5dX OGI\#6;D6S:,+$ dGOk` oQ2@"Za` (J b1`tD 6LXWGk2{< h>mTJDea-,(: aإEԁ skRͲqgF1/[W"wiKTYTtFuh?qUz,BfOYA_ȑ)2L]YƝ7j0>]v<fMJ ΩL15{J[ Y^xx$62WfiA'ONC-n?2ͳ`4DHSu_ N9Խ./29]\{xL93x3f '0R2מ K-+ϯFBׯv*R_&8&Ʋ‹6d]|⡡RmT>>Ƽ$? YVrψlNwuSugZܒrkzʊ<V6gZ Di &HuSC.rɨo-}7mZ}'woCÃe +GPcs SQiTdBTYe4%ҽG-{K \;wF~[Nd7kZ!{XpX;6ЕUuP s]T1q/\y% CIJ4.{cO:9518$SIAdYID ŵHXxӣlU*Ug'Jc|[ԕގ;xxVkMWjL"!ʹŅ}@@NĚձhgׯãe ]#Ӿζs:'Ƨ%LSD;509]VWkWk<6{ά kYO<,8mNz%=cBýq0I4(%"wL?vndaIk Ϝ@}oLr m?WVa#X(eUV.HD&EA'<>ӮfgOEAknKl{߼ir[ŕEeY1oX#':GWfL.N#=ywxͪ<.- Gp!/wX\xzF -S *rLk(i?;9HVyjCɯ^rpŗ]rK{@x*;qK22RG%}ohs @HթM"\X!qM ʹqg{|-)ߵ}<, @I5cQ@ c4BH)8D.D:)%(&LaPPIӄ^"ArT4Jbߍog2懒s4QwG$0ҎP4RFzӤ<0I./& yo;݂`38250bdz4\d'F2*c3'4roC3_F+{ȝ̻q55\Y`-;>!itAѹoţ{vw;1 ښ_ܰ>|ﺢT]tdQvđ*aDUǽхY}m-5{uT_{Iȏ~x)2Bf7f<hѸ{o`mM#oڿ} W/|^qVHTSsGF\^6<|银>DspߒXֵKLJ=_Q5uEw|E[Զ#`cJ3[1 EIIB{I!S:7:|{1jjI˯oz/7/~e(\xP8F^yفȪ!oxE)GO[:}.ÕV].띯ش~'2Rdxr\a8 &PANX'!.0:PSE# BYV,Ӓi7qU%'O FlOwTf>ջ>ػUώ[S v-]o&MN"؄-:\޻W`KZ{OP5%#[Y84_X|cǮc~ŐcE*Ѱ Q08Md cjѮ65,oJ}oz/W-;A4PhS9',2|:-݇r\oڴ*ۇy?;rbt맭qսq-PB\zmZW/.sy=IWV?qɅx3핪3YeM:8;.{Nu, H13N}Ť>8N^?⦷W?ǗS_xP4ޡQoxzgz6^-隅6VnݺMO\wTI:vmƃ-G['YbJ06s(݌ 0a|+N3cBy49 fJSɎm_7 v2g7ٽwUQ{h^wձ@ŋvӪ&}U zR5QP]˻[ jGђ!odيEԣg:DFyR2%vC}7cӆO\t'1}hw>q6ň"$a2&02A(UDve`s>xd{%Ƚʖ=vcsOpn{5K_ȰXQ6ZX?4D}4ޱ|Au>_Wn=KQFj9=tgaI'.`AN 9` IYgz} RsPDL^CT&E 4y.`阎8`x0m Øg 5!D21\v, 2XՍ4!I`d0ΝuL00L H Ci0;oc4knCIu<׌ȌY437ڞY4˜ x&K$8@Y)pu (d c@uBǮ1c,-=c܄R' 鼎wO.w|y Zw޴=rxӲƒyԒ*3բSIeՙ,h =άbe?1 =;YzzV6lT͹htzUf5|k[CoZv-ti٢{7T:-q".XXsLk^coHG~j3~= ؘ%h$7sPBI&}Җj7*yxQK)?t1=[ўe|8Sn~vMCo~VX8v|*H 9d5EB)t GB6,F*,iS1(E#FRR%_V{W޲lhKF5ƆjK{yy=%"SemuSs[~ml`D̼z1))ց@ 99+if 8k8EVщ/N":M1U`搮 PD, Peb0Ӫ49zpvm=OHY&UJ)Ygt"#/NNKaXY`YFuDŽK(Et+ehf9DLbhDV-+^v֛״ܶ-rIJʲZZLI*TQUu=e9@_fn-t-qpt0ZM[&l~¢]t  ٙI 2<4zΧ @Zd0ovOC =_ee_qcUb4Gn)C,mȿrŪxϨĖt^,Cޜf.ӡ 0HdQL1ga`0$jb (\+C(ҒT6͌N*EpYY+Tb{ZtR[s285מ6}ҎMKå|TCәbQ\[g6=).{zclwpZ!4Nd 35Χ=@`?0| CHKH 볙):~[ZՉ/S,.oj:\rfLuY?3p5]ݗ?|bϪ" DD N ƉBAA֩Fq,`] Le S. b*ɄE"uXw^y{盦F=ּb Sss<ẺSongt/[R^i}ӕO}}_z6^PuT!rLD'@US óq::XL)Ȫ23AYwN=!gt塋V5#]jm=G)%8t1ydf10T* ,":h Bc*UE4H`:Uըsp 2YX,kT#D)(Ą"##Ui@L8/^vlXyS=-;;ڟ}dx;w}rßz/ݦ5e/r6/3 xk "A,FCEV?0aͤ!u( %,< (:3 9畇<)xi}XN/_yMΣܻWN޹_|咆[[_9)3;ٌoa(P I8tY 8~T H.F0ޣS3gnj)=2̄#a<ڦm{UDh@e]Z0fa0.y=řnG"cK.ix?qrզ/}O/dg?&b׈J1^X. b:%niґL]L()ekO7gFXX IcGk׮8+3/q X$0(Մ3dP>1I`Lje Մc$P SM( rL )T`QƲ,2N. ibY#*5DF 8oTyh22GÀ(YEe=!rN)̫)9>1sjtքtF7iAb.aO%)DiN͍L-IE!:@ѨߺX1 F:%F8& s4h% F0WF{FȌPhuo+e{qf#y_eWko&ikI߽vNw=WzIb2mݷ~xjm^]V6w.?SνRI"QLOa$g`iWo*9Be%nWSqѳ7/~󳓧ᬐt[ΝVE|-k~C>93-TK:Tp|:3N t$Y!l̴)KZ!PC* _oQR #1xo!o.8ӑvɥp&#C EƔB1l[wa s UU%NH JmyE܎ޥ[?;t_uEӢwv!u+}^)'+y.RA Ê?D1N\gr-VGXx'2oUz4<61|~;,0%W]U7g^??w8:2 L;6ﲥ[Fyյ0 $|Q=ɰ *ʹY?8%S8lt1|K~1RL\wnYm:,Ω~_Ꝉ_ZmymMo5)H? }Bɿohϴ U*;h:Z-o|xpp8?6_}kDѢj)q?uisg$BiηW&yCdGl:vTa|vFz~-eyn#\ [Szyώ)5 |:2dzNاU2KvKmŃό4MˀeNB))aPD)"ҁj%& 9i5j"YdeaP t0YT@BT5oJUN1F xl f 5"Jk::M࢓^@(Q!s?%ttCӆ(bѬ1tؗ^hAy8͖$Zd'(Ii-0 dk@’B3q<${zY(ҹskNX%H@ X$f/|~o򴡴5b&GJaNƷMYi H$~,ȭ~/!”/*nXEVvjXMo]5<YVi7/5R~+P:OgSޗo>}\kvd_׆ _vP&΂+F6&þޑMx!=4UvCY@:<[M dHZ$ 1P2> =%eE{(ܝ Cyٕ/EA\j,ZT>wG#cY3:*-t5 _SWfm{M$it5j۶#3{?8\pdžU7 oۘ*_YPwF&FQ.Bٿp9.7T"'eb㞞!y;漪q< FH0hu8<Đ\柟bق}|IqcyV@,{E^8iū,zzAt>=>7Q26ޞ*%BNϝ0$NMqoVf%4`L ?3QB *0J0HBH˜ ГpMTXƹ /2N&~_zNiDP 7HH:d4}<'S3f0E'*MxD]U^pܛq|wo_=p{G:rЧgW:"yϺVg? oy֝v qnylT,.G"i2 D@@(0RtjTQL"`M5N-Be:g֣,)7|+oo)U* 4|vx}m* ]& qǀ 5Xi:0ᠪBu H W[BkmZ,j.\w Zz Y%e-W]\=Pk"M T@[Ǯ[W-R\SQzFN!U*`PMQ8bxDr6oj<4vkyvmuOnڵHWot<ԟ|h_>Igd囚NOc,{gƒu#oy9'3?:8r+ E$E]AfK:(JblƠh`(FۖoZWy۽kB=~W7/zJ / E|Nwu#D"[ygآb~>1-6O(|{R bMϥXN8 !!&F6RJCUTʱ T&hAHd$BwccIUkk>uva]O^܋{;B f,qld'dI0DDM0q6T 1"* E1e@Ak߿uM=o3H+yH_;~S4|7 q EjzFd&/mY|5cjMܻ*{P:WmU铽CyY+No {ѣ}3򼚐|{<dq&W$RTjq@{&݅f)8S,%KrgF? ImJrkW~Y[G82QO&{CO^gm(8W6ȣ9vq r,CtJ f"Jc,rfWwnBuB:!*Ld$~Rj@F i4#q,(X*DTR`Z@Y9EH#,$Ό" Y& MDWja4c1r`F<IqR#vqvT_k]Ug>=!I'ݙGBBH!"Wg(^•WETD/ B22=Cz>SUt@{o~T^{?g#n1@i0jOMaէ DR] xy{T? ε׃|C5Y٧\,@AF0"ԾR#"ASSnyX^7 "D<P{3oO_9{ќ(FU7oh~AiXʚ<מ;f`a\mK83j ?{K,[)}`w@xCç[Lw^VU%;χM-|3y/4Lgr/Q]Z̾඘& C rg !#D`4 &m Lћ !._=Ͻsiۑ-5=tߍom}v .EӪ|5ƌo޹%K+K"Y˪$o;l (]"W1ꌤɆ2[I{tIۋ@pDe wA׉.^cɬ;]i_kCݵ3(8>+}}"c]I%ja\=6whzEDQZTbw,({ZCFPQ eXViGs(xU唣aYϱ5mMӬwtܭo׮lxA;Z8ԛ KY}PjXZG󫣣Y8l,^1o[6fi.2Ӳ{B[62ԟr\EB7CC."<ݫm=3+b/t C+~S3}oٔZ\^QUR4+.+qq`9_w_}vs^U^Q[^o[{<;_ Y[|ȉ] Bi96AY)KC\ѷD[SF ^;!oq-lzYWn=;^vosϟk,??{p[{;pٲr֜F%܉dg{ w4V?jkӼ}ˡփ9fW=ӯ]ӓ~&|`e?~k$lKFk.:rdE?&{y{Asp.yk G_?0RPa$; }woо= ާ3} ?r7>|knMͩ+yA!][?~hTIτ =Wc"O\r ֨RvU3̘u {j9=+5eN,RN):s)vҋ%cYXMLg@Vj B`ĨBH)}3oh|0NqP`(LȤGE 5.!zɨ5qD/SU!+|!)H bшܯROaH#&m .Ov8S]%MKB6(Oj1kР`MZl SIru>Հ4r揖<9wdˋ2>ɵ;PZ1G֔~4^;N*R ӮJ:'?RY+^zPdg?>lAuHbԌxٱye?8|B*DK B hugK+MHF" Pp%ٮvO(2D ) 'l=񬞴!1@0'ɑjx kV̮yqۑtI鎎O}bCڥh Zlqt4o} !KѲH< B%',-jiݑDd[i2@H*j)mk[J@G"ӷG0 4r\35o DXC}iѕ%P<(&#z{^`(#+PYQPB<ځ5Bq)Z;((S`A0'i8mEHI @/ D?ڍ"iYWVW>{~YRCmi$+Ln_;u3_Zr+',bkhY1cNUI]Eٳ׊\+_F#2[҈sHI:/*)l*4ؚsd֊uo:9}~]b"}Wj#3R};9opҎO+ @Ȅn\ϩF/_RlvmdK~egΨ(6qfԔF.ygO gL@Ӭ% }3vTd+ϭ3a3hNy'J{~L>;B'{9HVΟ"!&R wn;'#+NS/~ݭgַͪz'7<,8'+!2G1j!dpnfJbaVYc\SxkDY*EVU!#BC dYAE Vb9'cDҦd&2~h bdwY|!(MJÄh 4O0rJ"LpǙsЫx> _s` J h MΔ&Ɓs@;` QYp.zʋ<s&8B2S|,""rθPujd'!M}o玾UǜKgpJ'l512e0/8xsyZT\U+0]Mew¹chPOB²pfb`hvY;O{iʦy&gA[:&l,3lv!b֝draNѤC.?-tD|C49+e0.AҥnO=)DFr*#O;C-yhAmr- -VvbXH8QQIiӃjϽyu]\d+" 2@O$0a%2&j}xL:9.3D*2ܾ 3?>]YPҙ4C.k涜BӚj ]Qm4'uD & -i*aX֟q˱NO:jGkS!$}p?OEQZ@Ĥ{rBXs} ߸-}1V:6Q]SEE%fe]^s+ϝvޜU\VPY]1.i~2{=9)qHB߅Ur)0_~,N]J(]Rcv"l>Y[jY%w^k,pqQ$Z<7L-[[~-8?lӖ= 5Ϯ ꬨ "}yJb9˚V.h,(+ @EUU{yQJc}[GFe?BQZ1y,@ꇷ8>77oi!on(P,5Q2 ;٨MmqN]Զo;b<9E鑱BC~'w jgУRs YQ8ьvi&r޵ Ba4׀P\%`I$0{ΤN^`^1<"bAP,nY<6RVSH_]ԾdFVXU.m~6a“'zi潰kp] +ʖe!3yFK.QA IG)2QXZ,D^h9:=g.8 q+Шc,]R;kJ}O}x8(jܧ_><:IZ~ 3ݯ6 2v*3[d4*WQiXH 9b֥hR[Bb89ՓplE"ߞ,)h'oX:q:]3UTmNǥPZ}#i٣̫ %sM &cUH= 3?}''&e LWG,2@AvIJrC)-'ho}vїV=s(,5i6Cok Dz;}t hn?Rm{E%$i[8Z1#PFS!O<%U1]&C[k;ZX?勿q_ 森W=134ѢH$xm{o^)u1S<Ŵ_Ce\?xQJ?#dbaՇ9pt$K si]+Ԁޞ;7o(򢥷^{tDI;Kg5=uUڒ@wm!/|䢞!gy v(=gFS CS et_xAڕK>U?Ö28<э9.?v$KwUӝjC 8z7 VpMQV٣#U{MRQd]6yF;>P0 G\R."a zF%p*)Wێ.dMؐQ `ID 늍x<ʭ[XF9y^k*yCh 9N@qP)MQ r@)i@ɥԉR`#cE;׫O8H1Ĭy 5!c2赓8 Pr\ !CQ0ȴO\6i>&5G`(bތ+C]e(+aւ(XFC͒߾cgͳz]Yss5Gr@yΓ"(#_s"]<ݙvgyɜ97\0;M;>qU-qϴDT̤㩸eO-_t "jq5CY xVe%Y="ȺJTr\QJЂS6u%qZ]8zΞiܙ]g\Cq]mu]?r /-djݚӦ_>}kpJә1;W*B `,\]ETrYUȹZuV˰=v@0e]ڒ(^9+V Z:Z-B\CkDzٗwu/?1ܺuGOv7kk޾:1[.Z4qGg ZiP Y ՠ4y$h0qҦ3c;NΜ5?|x] n_Og3LeAWMR-]PbVDoDKIyLw ovyg#Bj!L30>4|w•("ڒr C,`P'smKYua^D@@~e<"BPD,p$ (r8A\͑92RkEPp&I;~J$,'<_Rk"I^λ̡2|={$&y@72 9LJM2@My)9^zwZ`>|/'<Xc L&JIҤ])g;X,,H|bͬʈ836z_1<⒢SCdp$>DL,A2<=K$laK{/G-h#F2mxzKDgS U[.9qCE0XPѳ`GIJI 40Mdװ~*0lՏS㗯7iJOj,6**pDHZ-j-])scUYB!c(%uNFxf4ao9pv,oܶNC69;~G_:qTg7lpT#dž2lO[7=n}5~d`xg03Y}!0p(Mݳ!@IRD, 8r#@VrFg^? z@+. inU,fpVjӛ6 hn5xdu3W7,0{N m}lA] MMdR{!F MApLdar@ԚɮC~/wǑ nȁv^nH*7p鼦Ou-gNJ;uǏv>Mz/U&G@ 7B`k(aYm謚}݌AduEE #UUAjpBk%T@([ɌK,* diHi!htUFy$VXBWʀJLC`*)8CSV;o9TY1otH \P^v&"h ,^ w9xAHjɯMvڛ!z; iT֠Wpݐ)C`+z\L+ 9F~ ƀ4hȟG HG!MZk {uX+CH.ycH@+^wƌ!s33J*+h^RX̪`.g {Kys3/)-n=ʂ@siHJy7)>C#ϏIJ tLΟS\TOّ0K'fWBu'_ڷ.>gq5UE9u  8uB`XCW!X@GR<8i@@s1b2<5xvv̡SMNGʧ-#s(#Cv8bX|Pʪk|yšEd@$5L:ږT2jWRdKJ9h0L(ID@W^r G@04Ĵy_778yt}EUʽr`pżprGCVDWAaKtͨ ^5﫹'oe]4B2nmݛtSʸCh▘tKPCxV&v)䓶Fp$WMږ#J JSb&gYW+ԌzC匡hkgjncaHYJ8ҞGU,7<3|PvBl7QI:qlxv:*9纉%o0 aptKipIi : EIM#.ݱah6s3ՕkǓ;LۉO9nU eന9* Qh0jJRPY`fdVDFN:1d<#b"=AP020dG ^CC^/AM̈Y"娠`HFr.ygRD)&gy&B$O1(R<' O:d!rzm,M9DR2 Y[F X(9GQ j<`HĽ&'޶I#7N0RHSNFSypz"_t>3|O<9y3+J$x(\kA+d`qԀwϝuDIiqWۉ G4W 2'U*wݴ䒕[t5+K#M3+ Fz{p=9Vk?gGsϣXzX@OHANd~U~6GuuKgkͫV-3pl%l6]93vU׭82߰3 BAR)0dA$P)PD[nqf2ISB $Ld|>KGLmzՎ^hDž C-T.S)^4xGڿaIG{<袠(GXV&*Hk mEAE,. "WQ". `ɑ32(ϴ&oVq`{f]$>tEj_-+4Gǧ7VVƇzp~yzܙnظA+ƅOvd^Ajp49yY)Wk \Xn})9I<$8)<"r.DЛa9Zco'W@0eW\ԙ\tW=s媆MG._+gH,-)UCS9%q{$KA q &29+ XN{X"\XJ%,`ô+'ov]{e8_ 8}~xKJ"֡oSk/H[6H^qم}X3\._^{ՅsS:dr)pϔes=|ȓOCC/ݶk,R-//Gl '5k^}(S\:~_cemm'7,&gԂS䄾Q`i * fجwF4oIpnfz*;$ 8 [OJ!(5r*Ak ̀Y 8R94ɉ8T㹜FQL(M9h8g^ěsȹڳF!HIh %.i"BƑ  7!:@iwD<2j:mp_^Yy>a s q {G&<Tf^F#Gʫ)(G楐zH #b &Dsҋ{E6%W3-d|3cmgF۰tٌ k.ϺT8A0^ TʻR{Y} yn|/IL/cy{˕W,yV.n[xrd<8<GtD߀R'^(GK@bEALg]p|?ӫcu˼闏q*UQc:}oM]P[S_pQe?ᄝBId BH#H Hjp$LL$0fRdX)$G I^4 37]x֯e _}T8?xˊ;~į9 ԟY'HĐ3xVDZ] p2؊&0t Y2J *oE[V #w:n;xvzm3w,yeu3?y®>+G^;Ѩ|/.W/3jӷϥ݈㎞J E .v<0d B񯞟 ` it8a F8rM޿a-_zmH de]va?S6雾$C@!id>YF 4P|'aD= }Qcojm/W=ӗK͂~y`!thS_e*7~D_kBXSA_O?|üuKYs[GK˙m֡LȵIWn\_,CzO8M73&Wj*5X!bF3JtI(MjHcUpniZMqb– ZT`Z 8:!C  Lɜ-fK\*pH\YG C)(*JB&2%e\0zл+tFű (Lm0dA0w:YB1D3d(KD!aH(.fcʡnKCwrWv{#Bj=q6)1YL @00(?S~fێґ'SVO =藚M3K;rzچϗv51^=n0'22B@vTX5*c|2KYE~qD4@i!f G=Ιo|jٮG̨Ifҍ;O>y:w$Gwx"aͣ-os7\*JB$$@L6);qtlۉW;N'Nb'^niOq@BH*I%Tws[0n;MjjsEQf wB.WGN2&(#I#DSHE@ a) #A$LçN^ѯ?7{Upt1Kji[!B%*9j3j\05 w[s_p$8ĦYGAg֗6~z>#7hXw/cops{ſ_?;Q%٬F%eaP+`yK+4N)$V!IoZ}r~;{~\v|TU!  CU٣㰖 WGzK9|Ƚë~m'ί n˿ѯ?~mcWͯ}6&Az\&*(8 "v3FKzp4C DϘ4%^LFU|c/\٧~zwǏhO?ymw/?kRd(;D|T0gJ-O;< :q#62*Lr!5X`3L06?F}S7?/-. w٭70(LJ?r#'x?ٟZ}[n[5d%v#ɃO?sGc7;^_ۯxc/?xx<^{_S_W?]vEr8IHĴxOx"8V=Ҁ"B!c(ɧy~?׏=s3}7,{wu?3C_3ctDq*3h^}SLs-YC+K+7)>QW[^>oyzJ Pr.#׆@IpȠ+xyVL =!FW 6+!X0®Rxb"h !q;kU7wLJ LUR% 4$EILJ6DASI"!2#4RMb*iljlxyƈb*I&MBSC|hZŦ@S\oFlk} *[s6oWQQ'ScGrѷz۪ g3#\{?q}ᇿvfBt2***Zp*$j>'DW;ʛwx单7/ ]w/_~؎E`6@$&'l ꤈6MbCo+vζ\0iX-+`|mrU -qamy3˯y^wӯ,^?ΰL\Öp$6Ne> TZ-48(!l(谖25&z2#Hj/6VQpTF I ]wn ~C=/kgvL*J7]kUbl. W+K[12k)w\?pRfBF-Op+-sE(uRwaU7/Ko}K~>2l'`9 kSU"E m ke39rhcUPج#L0%K'c;9k8_k^u.+W_@'2°OKs6hc݌ %ݖͰ^ 8( ZM2' rbh&LmuIM\A?x݇;͕^}{?rxu2~ ߌP+5j AH[x:D,{Zmٳ 0ۇO>¥ϝ7T#"A+Nn`ox0'U=Y`v܉(d L`xo<3skǗo7'w-GPdr7kk}pmIEFU2(X@T-|5s{?޻sW?/=#tu7ō4Ry!d{~T8-mqBk 3RYoVMPCQBT(>Wv TXKqoo{lӠ^ ** !Z ADicUL3hCaU&w5YC46:@\XQS^B0Z :Bƙh ;gfUII'`SR_7dtEB6*h)hטEͳf5)x wqW/)ݝqBg0қ/VҸ-;HL@uR&1Y3A2 ͅuV=d7#?xa[b6&m鑼4U婛&QßR>DV4aZ2$M4~C0ZEd&іg&}啱فYtc=s+F%Q\W&hifTeU(@Bh FvK+c Ĭ㓬 Z4&KMC\͗ܲOFF\>lȣ'=S;#B{ĵNP'@fQ˛ajHZUs#* +_KTI@%IBA@5 ̶\xZVO'uS _U @HAR=kT,rlydYQl{qWG(bR( !)籕z&ύ±B9U(sA班GZ2mO{;LD( k-U*Ͱ<`YK BԲ2Sȶ/GHqPAiVrf׸~2fbͬ-={nN~FHd}Ҧ  "dSg#&㰖MXnZmzLX$T*#V땜?v?iY1>se26IoI4r\*e60U2$HT4eMӔiG},iuLt;\Ί(h]8!ԚPVbV#ukS:NJM0d q(PԂIL`&⦽[ 5 W>ma֛VVK(27vUB\E&x2&Q(D%K7?_جيC(|sO"xnTE 3NU,D&=C%sT*J+W1{-W?U$Q(#0C$-1D UTKܙż_Б(1!lFqZo_mB$':SVJ-eaϱSoM#=5rn//޵6q7/dO/Ea+c HN &kz)`P:I4]B?ɅŴ0c3dP&1JKqSHZ/e*QAT6izG Pw339~Σ$+`Y Ѕ*mmɀ}?DDTT7K?q[\6Z׎W򓧞;LVN/Zbd"00Ɩa$3WJez&{q٥Oo?s;^ *Pa\F i3FPnA4:5cL"HA=^aJIQ%LhZYiHJ<:à3BW1k+;zJ1$aIL mGP2`a) 28B& BRa(*50;$I)&11mJʈTxTq%lVeP1EmDj n @B@DNAMM#1( `J  ќr @L(" I1Y$N55A >YE3=vo{/W(%Ux YE-F@Še(iPuoVm*"Q@9~p8R'qԠlSB?on |žf &FIxT5EzK n(i A *b1ـm]yz (ű}UTlJ!UQ!-(h)ZF #%e7,$Uj{=Fii6fVWnGU J'䦪/j"h9؄ϜnuۛQQZW>uʢh`f ʄsmwr9-76y~fٖI\7̸ 6j-bI𬚁WDY1k/ ${ty)"}/{]o&#;3$Q BPd84rwkOϴ9[1L TCR&U AQHP0Ĵ<Ŏ{KfZVx3n1={vڈ*ܹGI"Օ1=oe&:b7{!j5 u*IvP5PG\G(Ig&BO>ze{7=NIw‡z!e[YVfRU9v$$IaT'G]AQUjEl Ke۶mMT}DgK!q>s3(0Bg\0j̈bibwv\?g&ZhŖS2jгY;388-8D Tζᧈ ZLx*!ї'ךyY7KI~#-@XDjBfCqRF%ϺKkޣ?F[z]_3ic35O63 sYjRC7ާ߷= }Xm]?09FA6RyZ~Aeg(n&!O_eܬmV%*6vepy@08RVL45)(\ k;vrH ti3S'NF0}:C;g:UPD;>1c8FAίW#'0`=Ac| ^T2V hyάM ")*uJbT&mb%`63G12%&JDRWń )jHIC39r)"";nn"%SkY)bƞe}={>x/tjTj1KbS(`iCUu|_t۶Wږka:Ӥ))IChHv\Dc   Nڽo_FHggXlN\8"2 "lT)(hˑ !Lw{L_߰Ƨn>ڹ`V|][.. sEE8zu^2R#X}3LkLs]Vq.~ZF֢hT՘GDs8 :ҸQ95 (8aᨗb?IC4SR&v* w$-b3IsTxjej 7SQ9*C3bOU@mF@4kl&DC =$Q_bT&ӷ$IOh`AnZ M2XĔ1VSɖỊ̮G>>m?yegn޽S~kG.&'րEsI0wj1nTb*:$UJ#&KdV P 0BᰖR@2GmUI6*i9z ܮ_skO.mDE) b$;{&QXGX'٬KFʠZo?}~PdTBI:iZ9϶8֡zp9oz=vng'N +XFֲ: pϞ;R 4:n#j7DsFUhgT%(y}'b$eHdZ9:j=!>sbi7Eoz_xs+D5Iz CRl1Pxbq\T;߽bZQCf\ƍRgN];#&ɼPFU==VQ}3~ߌGBOJDpeaxoc׾O_^F%"ꈒ8m:|=0MS]5(aMv4!\^:Ťm &S0i?!$pYwwU{>u#6Gϝ(",QiHN"l9SB2A#!j0S`Hq#2#7&i(Ï5[Wo߳ *VF0ʴ^8T2Wu^,GWGA6jELAA瘪^gle9J&t538OkGNYo󕯹{g9^Z$ ^7QK-EjlQIYs;}ow 7|K}&|u $2҄1w5mDSLj8P{Q2 :ocȋ+{j,C,3aa2a-uRGu :R&w{K}}\a ]?г#_8~`Ջ?ymw;}un\r$/NA%GRZRR'p/ٹ[(/~UQ Oz}R##"apX 4a 3-r3LhYhv29 ߗ.D- @vf ]xyl)ZVo?-&`/';P1WZsqH$Bi$IQBUu )HTX,|%<_(2{QŦ6@EbfN`ZF1#"H̹s">M^uL躚_K/_;_^{ח]={g±r\1HR*6u>[ثuRsW&;.' g]J :$-Dv1izqQ}iffAsS$c2]'gãKEaf-eTOQcEu: ,hwPGH2b bǍX$#f$HA?qJԦitS:%]JXn015B1ɫJ E Lܶ(_2Dab\cƚ*ʷXeZ44!L'l=V1M 泔7z}"OὶK؋)e_<" J\ۥo=WK1<3a;#UƤ[&2$s8!b;?/s˭ON] ~wQ7ɑgO)+x= Kog9 KCZ?|n.ܺ#;٫5^HQ£'Z+ ZR"xMeL ϮTZf%K8Ӣ=s\9,ZynǕdWFa$C,F=Ri<椞 dRՈp\᪌u*IA{mD(cOd'S7Vn">sh&>'D,D*QԎ,@g$u 7 Q E@1#(DR᜙uM(½`vf3/xך|q({7{ѣW,=xw.Kкe%t›_~}<6PA SHZETՍaM mfGh٤r('lَ~F{~{{n*i4b464pX6e>RT$ezdܩQc Z%+e(&AhLgA4&G@2+ƩQAJAuuTQ|hsW;sx|a?! j 0AB* ZKorg62AL[%:+PFlmTqX *Y'P㠹ٖ9Suzn'yHD"c;d0ׂ) 76 LiT  ^l;(Dq3UA(Z'$7*:LX㐈IQ=Q6*Q㋶b۵=rFQ=.(HHY8[E[Z6ViX(A6dM3ǫ8 RQkFFt)Z"@BH6&4*ѭA V EH 1<]Z=sN[ea-uT&(\ ej#!QU3f G3u[J:(S-!41W5ҋf}uujP(&4i!x:VQzFFQs&A-yҴDh;㵱BL3#RbqҠٟ [慭[H.пT7MWFtAZ@S%S02N6S#-At ;+>v^R𦷽m#G.t_T~ExJ1tfδSWZr0%$iSY(neqȔjce“$Ęy=JZǹcJBvF ݞnA)reV 9!&hy`=V!jJҤ/hz 31#LT""RC9"Oqv"o΅n&!ψ c%, &"2\TE1%%mֺrCQCJLHcژYwIs&B`!=l h~fWO.?~-7Ǟ?;>񬂾?}oxB䇿Jh< ?w}c[MFv$))ZEv %$9B&Ic3ټoQ7=u<k8kA%5]#&>0vɯ&Å5@lR8Rڞr8ۢN*٬$$0ݺ*d2&#) )XQK UR;{۶剕Z0a0c'bc5OAjH;(\قH"S(AWqy|"@'op(&QG$6eIBՕʸ bpZĤ騹`jVg<:B;%刉jQT$ƲV (Q+tA1DDqaPB)@30Av͸4K-ZfVFɘKaN<Ut ݭl_sk!&ߞȌc' @Y(*LJKdȟZp@f4[޾W@DoɞyԘ (Eu?)Q9I[{.r4B6g)!fcm2/-wV6v֫4e,BmSa4*Z,8tL"j?F$)̵wvfQd"v%g㹟;pDDąhqdBus7ƒ1&:5=O``%A[<-BI\ŖOM4[!~ W8g &ŒksB Sބ3L2-ك*/yJY[1-ށńjJěpW`&`{Q6zgԧ:B+Bug[øNUl:IYK|ǑG/E-DU&<=1>DUDl [[*SJ"HHLlBz i v"JH̄IiO+n߳Jޮ>cxϡO֙-3[=/ Y}߾qșBVeD+-4/̞&h^{U0BܗZb01bl0^9uD/g&sc(-$w&ѫszB-3膀andza%5n>}&DƆi6g٪f5IOL#fŗŨpD$EVꢠS z-[q6Ds"TNb5l1cWۮ9^ke fmFZL/Eu)(tk*Ej.!?~5{ )60H55-bƉȪJC|d( L.Ov6C}~Hcuu]iŪˑi\F"lfE?q_^1>e drs`{6g5-Wwڇ~=}eߺsǟ}GfZ%S u4;3.'/reϵ},Nj"H$Wd{7akJ1ТgVg"3: Xvj M#` 7jUeP5Gb MB 7|?w#UUy}.km4zo,u{lv^1TQQSPD:` 3f!۟  X 4CTT!lu4^p0Y&A0jjDHU 9 ȁV7qFt ߿Li}GeVw)lF x ̵+>A4RqB*GjuS!UBʦP1`>kV;dm.yB+B_L7U;[S>lWI r-*3m6ai!r9.KbVCHnw? 1ɗGЋG! @֊%9p{Df YEıj0+S!2Tv31-iݥ<]kۛI}6f"hkKSuUJ:5ϦT~ ]$~A٬QzP\ J<Ą6KE[уVYmj֫;ub]Vj^nռϬ@>i0,NjE4^}^FM`DJH^Wc3Ӏ)$}@'Vf9M*:51b "8OK'ZGZEjU-Ih!\`fpd xY/f~k{ulՇ ´6Xj8 vrS ("ֱYW볺 jFuya/U)1SRprH83yv.e_xcVn:)ұcOD=0X)/D< ƱG6KYדనjcR1mĈ\A臧V@5tkʥB*<)#V ?ZH]2G :EA+ڲD{XL*֙xav"Yfܬ\pV7k )E\;=㓰HTMes͑Z&d>񺧉T1vϾR2@%1SYKEWVM\ԊsxXh"MF Î8l0 ̄ YF  LAa DTzū>ȳ EԣI$"#hRn$*cbl|RGܨ\_=bG|2zN\Ty/><ެc w ?sm׾ka_\?ǖ᳋pb,oˋ`o?@j>m1dBj& Qh Ƿҕˬ ~+mFW3CyhlDj>7OdYMMMn*Z&& q٤!B\4&w6(j6A͸5 'a }uYvY}n lGSf4ouga:0t gCdEWWZqv%`YʃoaBfYT GAV@:H (0D04Ct2R/@ɍ%:GZD׆!qF@`1׋@2Jue+.f zKn⼙=Nox'ueӷCf#K|kaW8Cv&%F*DXpzX:喥P3vIRv BZ- ܣcF"4|#A`,>y3XJ]^LjV~Hb}{E*RQz5uTc,UY_2Hu@/R3~Rd** BؙΏ24"I}R1 5^[Svh`<7C ./rV3eÒfpms![-FCH'7톟=$jxd4I\'kEC,€ԢX@2!7Z$ fI\]a1bc q3iʁb~H>RXdٝ0@VͪAzzk?[7]66X5ŁB|m 8.* ,2)I^ 'EHRZu1kbop30 dYE.?[h*X+]60wVH=FS貉a{a  S<MdGbf`ۢKK{ZHJt,<CI qBClA t5d{PR8PG\6C!Ō 3X{]먚cP:8/AWqpQfwẅpu TkI\Y`=o `A6UVj+A/eY-gs(D$|B543ߡB '֌^}a]֬o??K=tf~{;kw3x߇ws[^]_| g*`55W1v(e E%ѓ! -0f<@1v2p$$%r,Wr-^-f&ge$HԒoZ 44jR& BP1Gb@m@Зj ,M#,zseX@bh@ٹDdJX ! V," TJ845a!$4Y Bs.(iWB PŘZH&@\9`gxʇciDoqO|}H~?/3{/%?c>O?_?{𦷿;N5>/O @"bP!o cdܮ8&my_H26iGU :ͣѡ%}m?KE)8ذN \!A/Y%iK9Sހ;UTX1wHz)3_E>Cʶ"YdkKe&ĬƄ3 LM>,>FLnס]a&H;ЋghA Hy^5VLA%_B95A|kp$b$@ex׉Ze=:![=wEڵ03tT].VÀ@Tf.5\%x rEqn4Њz +@M̒ "^j;.2&3ǹxdXꉁG-M#FFZt!T)= k1:q봢i` ꊊvxƥS$&dc|rV%+ R$2sن:` ԂB@#@XMt aV]M:w&LSu7@Z:5,5H$k!ǫAiG֋B1H4rd!k< x͗860Ç룖n=` 8 Ȏa5"sy4' enYKHnA0Iŧ6jl0KK~ Noß{O>{oG_|[^ko{+݋^vw/szB؉^>̬5K_k]&&qAaygFC#.-4M# Y@8mڒ+ @bH(`Xd;aҤvr&LHVE /ک*΢{Y5(iz41A$ MW2:3:[rdl.thqEkĜ9<1hӤIfܞ^X6Gچ'u$jY}6$<{±IPe@;YnD.y $R4"13h~7h6kq4 LY1402PuEBhe %oL"&3k (`E3$%u}&@/&60"4BeQJ/o'QG蓳b#/0`xq'9 N<[ M80aUA_eˆU *0~ `IlDJr $%޵!~k$3Q`{`2f+k$ZC:bt o'' _G cwT !2LϓD;Γ: Nn6 uS$&`'2y83$Ⱨ|Xurd:Y:ʧ_O>ϱFS :'sުX|3`EHPW` yFX(.ô6lI2,".Q=\X- צ^O+0 /h 5\rM :0n$s(#c#g(1*u~; fGb m*Z59FUX$OoDd[z@AL$"e&fWDtqI,P'FX,{f"M;7) )2.z3C/,:>ce3 bYS|k( Z ",td } G}>\O9TH.`U\Gi5LZL9].cX8Qj>cbTs3:û0<.Q$DO#ū֙#5d82Z%5y~[kBo}m׿=o8U[ѯ\ f)|<}'~q 4{K6︵9iog> {KaYEd8z|g:|m.3;YfU]rU~wdƛ~ǯqn Txɦ Iˆ@Щe6R;/2nb&-pp"Rs-U{'#M+J S,{lJ+fh ܬ4 ;^s牓v;xک)M7/³WO8ۣ|K]g<12T"ܮAgfcեv3O%qK&kՒY''RŊ٘8ۀn0ҥKDղ@Sd O} b0wf^,2vYOM#dIi< dI,i;a"g > LxFZmɲ׽eSJkfC/\S_q)œz_3f4ЎC䓕!u|n馭2A PPwD 1ACP1"/!P:4I12$sl1| .er?d3UrQ @[&%Ċ1%ySմU"z0T1BA&5u\b*3d[elFbfM%K}4 DJ E@*⬢lY6lћi N}4a <0&2B4N8 br>XYq?Ԋbe#qK|$n,Cɽ=P 4O)ü>.=Z!;C{QUqəDEy_b 쓳.{kR G(U8q}|Tk|x]֦Ds;=ԁ\0 Y͢vImy52_t&+^拥#RdXy"&D 6{U@c.H%@݁AYj?+^un ӟg_|"Ln{NqF ~g-RS7׽lAmow<v}hΩˁ^OHW]M PpG^v.,0B^L @DRՋR3 z޴7*^&'C˶wXJ6‘1y+.Qb`?M l}7*Vt+RUǰ|k޻LB 3Ȣb2THDa%t~kp? bbbrM#Mb`^ZA/@ @ Nޠ% 0iN)TETECDfF$"ɰ!4 ,)_Z潥.US.Kҙ^A["q{9:zEW6"SX$:q@\+r)YuzrL U@3|4Kg17M+~f0D*իѫRϴ!Š(2`BO2N,t\%HcF9tV#^<s`[e3ZyV%CHe0׊u3'D/Z3yVFgKb J jF@s >1ɰ.Z/vZ 5 gqֆp,3 -Ķ@St-uPGR.9?pqTa 9̐ѽ~y]Lgp<= !eIqѕBWY7E=kV)eegIYlѣ*c-qA"wmT:eo!Gs V>`5 dfZ뿷x#F .zgӏP65jw8OAC8ڴf0`kF;DD$ ɊN_VTO.%97bBCa_]|βp1~ le{IHH'6Q'p$@`”"mVЛe8dO*DP jfrz+;=J1@@* AF`v8׊`6e4T͘'/^;.d1&#cBb$~"tq7W6QѤ9g!B(@yEAd"&@O$3369r @MQH | [?AbI7HM-gXHԵ<8LK"lb}ڻOw ܕws?cݽ2}vM}xw?GW篚$ڤ:٢$#]}hd3?R,Dbfq[iByɕV..R@̊b8x!2A2pfYsF3!$"B@)`UՀEqBU^ &B/ډeeRfMUt4 }{taw }0Мu,,밻&O7L[áA\ Y vB@Xw:ofCoEǨqC^H'c1Spu@0UZ)V:ܺUyI7NȝjR$Xykid#slGD-n ZEE{q[^),bNP#ăֲ芃uyLEshf+nNb!ҧYDeMT45`0:1(VeƄI~[=)DFqlB0%ul78d4D0cAV@D \-[/_NΌ\/~m{x[H[_}ۛA^qZtZC DV.02aY'1(c9B@Cvbweަ؄lIyoX{8jF"u6[@6&HVR"XlY]VDDM"'P"ZDy\g}Ǣj4ĈE"7ԑ`0FAHR˶ \J"DǼK(=#"D+ ҬEa8U-]ZqD~Uwl ߸5EdF˃W6*޳W>O~ß:>GTxbDgo^qv=MrݹSއC9YSP5| 㴢INb<:~Na@p.[ӋDWDW!(Lm0 Q貹eJV @.jBu0y&6I`ы\2m0r8Lz|&ͳ!4L@N/^kH`YM4ϫ@ǚLХ'7b@Aeefpu$N+Ok1Œ~'HxF`dr\j$+u|i %k&D-BF`qz/ @XW"%vO#NkhBWn/P*B%mYt>!r׌E>H0= Uf.? 'M*R\nE}*92b+0.RʓHˤ}C8YU+i5Ah`W߉ϊ@!$(AU6Q*0SBđ%Ttl~ /GP}>:EB\ DgeX$ PCVjB  !en7^u?OClnNf l`/T ˶qeN#́EYEgXv6HӊTBh3AD/s]hGtGQPfiÏ0̮[}2$=b$FC\#^Lb:k `V\vwk^x}wtW|z];{|o}K ;_}fG/? s݅gyn5gىn7̈m74mQڶͤ@0DYtz$:9Ȼ{5485=6["Yͥ߷n٬$|Q$NB꺎5ȖmulPȝ4$i,A$p#_TY BHzqD8"Ձ*.wq!&H>h:U)QN8t<^:"*X@MH]$#k`=ђvUsRv_xu4X۷j>Kyx/;si9?},x;O箩O}Rg;s,~^zn{?~s7c-zU&bP&д"?k"5nkz) L5F"\P4ӾI[1yo`rjay _*2d^>%ఄ4aGs2!V73 >;ԭy3pI ,0Pie$,Ra3kZ(]/ !5gE[QCמ#@ D:iE^z((t]lRcĬD'RӰ8_9x]#QōNkڞp,Y )@DA95ʆR<OLC ߺ]EN4nOBq&jf& FZ  hšHeEҔ- XN!`*Vg m쵂'bM;Kt)XDB^ eBϙ(c!fw!`{o  ptlWlH< ͠ȨPdu@7aWOWۤ]&4W/'wӢ}G<_~?GNGWOr{W?GN4_~VsNBݘ`|x $fV[ #lז?WWN#UZ+"vbtՃ<:lLafV5g916LHӈåLF5S6a ~:Gz`0!2+A.2TP= 5jX#8 ~~kԈ00HdR g1UU ٽ?jvR ӘNxLw^Cn߾Lo{Oz|???'UH{o~ՃV_=]b7,{t]6nEJI L!kUނ ꀦܗc02lմ_&:O\8b[6f|{bk~-yޱǷ rdH8`"Y\(4bX= !(@ʅoaGnLj'1Bd[Q:1Q@5oWB&>ӳV79M_+$]1adU[ђDe=Jl7Vꭑ#WUEw]5b̹'ɭ5ht:@;}&6k˼u ]'{»^w7#ovיxb;pք>/пۿ5w4rwŮ-ľm%T7Ui]mD=l^l QWHfh3l5).&yk`ף WJ礢 dr-UQڸQf}+y_P`, 'Xi'_2b@4\Y mkVre5Bd&F\<\C/O{9"YX 2T\_f&XgWW88h۷o9]'Ý~}}۶O|Yo|޳sG_y/}WN{{?s~?_rL ْ8%zQoK(JtٛH+`-+ La^\i Ө5FM(ػۖ]}sεg~ !D H- E`Hą?UIUH\Iv*;E?lW1P A!ZR{5#9Z{s[jN{^{s}e-R6pD4ecZ6X̔ Xni30mF96\$P-D1lƤD4d.Ƚ;a8^ڢgSpSږuDLY;/j:ImiV)ڄ ;kjVi)-{bА2q㏽Ww+瞹?9?{Ͼ~]ħ>>׷4|^sNzK+#5)9t|:^?MjiV.,һ1{1urt^8Qzv2ɂQ;gr#@$Mỡr=WWN88LXocAK:Ytd  oW#^8QMR #X"kRB)CJ2MY FwPdUC-u @ɲ[$f)0/ ܂.%.[逭03#\Z?rk e:8sO}ϟw߼B>0|K~KOyy5y>lr'uulߐOO^מ\,/4D.]1#YsZ^?옆Lǜ d4&cHH!WNuRA %.R]ZpLDd4G[o"kq-)@R%I:ls3'ke%UekRY m%I4+ Jf.u"]-]:ǝwv6381RR;bgjZCL֩j[6k5%e2JboP/wo'/ϼS/ҿ]Lg5swjRc4oL3b*E` SФU PtBy̚L4}uќ-@ %!uTUQ&;a8,/oֿHZ>֙PCkgHϤi6mQԁ..ݫmT%&,Q6@VsʻuSr vs_RP"g_k`VBuV˃ 8ږ|rW9@}wЦ8qL \^h{vڥ&QQ5˾jZxv]ܐ\ h~KvVPx~vIU%[Yd7cQV|vaSdMie-= Xl.gќ}uV1,7 1 >q|I:vU騎++XgbEz'wDJQL,vs4O6,fTG #tF8'Z8ZgM Y 9.c[8FŐ!{tDE -)%5M^*w@5e)ՉlKHRA])zSp=zab%(i p/֙{ =L|oxk{ybZ]>^~ c~_|p;x[޿ßo}&I;~9;4+*-<_;%Cp44W*-c{ֽZ3&̭&3@+ܢKJh}j3$^ґA`1B+#0i UyB2XlgcLS'>ڶ@2 ~x <j/KPT'=[ փep׹rwlQ?Y0ffLi21k%N!a-α#DL<$z Zdi.O3,-頂m4y&vC:t1uH8ƐQ"g"=x3fv J Ņ3=~Ĥ1 e"k_Szn):putF'.=x -C0JɯWZqb{wv-jƈ頲4!%Y#;B~_UDc֬Z[3M~G1QESi T ;lzUMӹShYZ%eV.NjQa k{MSv[l$MK|&E7J@bd)aUx~F' ;x>YKMbfmQU}UE<{2Т3P{c0%8.G؈*fٌNi<54 fLlʥ;-ֹ iԘP !5RF5N'2-ՙ(PWrwQg~ծXUK")`CÁLe냍+Yy!;".^~*1D>tknT}+'O{/_xCW64l}^|/­&[)%0f#Eg>CR?njY[IzlFhueÅyԦ{kI+e6Iх\f";c;ne?d4O9!Dj*=SӜt@#'o)ml*E*GEHS :)8 f%C;sE;8ޘLv )m])Fz(tJlk'2E>pV1Rk["Awj޻9ย:? B"Uo`I+Hvgv;vQ`Ϊ 1i=[i.mvW`S~Ŏ£BZ0eU:vϢ5qOvYagti'XG,f2aAb>Ƀds\vZT 䃮$RK]X Ei7eN-ˠh^.\HȪdd{t27|`j ?̱]ފ~FT:a"j%G//,Q4fO?,5Ǟ}'_}{?3O=wx_|qxww9=b\1eu_0wDnbAQGŐ]x$0v\:&:Î9t3]^uW=.tׁRʸ@Cu!st("`F"b1srG! J4$\G|6PQ f`0|OGA@ 惎Ȫ̼d򌡞@*@HZK,:f1 - f8L0% Gޑ2t\YDdN> 7l LرwhetǟK.~ӷ<ħ%s7N?O58S\ NP4E-df|{E!tЛc Kem޷i_:-!bri@Tr| 2=؍"41JW!o0bmri>怊EuH6QU_bwz+6pQ'ӎ4MTKKg=K_5-.3/y5si$I6H1Q` c`ٞmԈR`bE#h j>bZ9 GXvLYԺ;>E+gh7!W+LX"..gnvL}(j9ca1ihMkq mcVZz*98W5cZ7KgM/ 50jKVCPOdve3{Vzd㼆ּ$j8J)ش%nZ/,8i;*QQI^FnlUzO1# 2x%J5疦Lg"ԧ1E ,gŒS 'l$"rL&p$i\У ep奿FHŔScgtAw#<Hϗi&rL񬡿\dM*.8P]xbDXI6>]1Ǥlʯ?» /?s K~|_?V<|5o:z3=}ǔN#Rͤ"G_ƌ9&"ǣ>twc|;(/Qp/ǣ҅ Z)UO9g vV_9ICEWC4j`RTQh,,Y-Sy( /+jR61xL){љ-;0V;OIJ oe7})?qĖCU6j(yEljf,y2F)KN I&DwZDDTO!zD\"Yf+<ٿ-??ew['z1|O-TT̤p!啍 SQC?%#fe>OJ[1WWs*UC⵴ŽKhyÚcfU$2/0iA7 eq;l>|j0W,C"Ld)E> j"wƬ 5\^~1}#Id(O)m&5%Ά IbQƬjt tmOSTixβaCTxUC"1.蒁u6-[Ȟp2HEcҁ0ɔ=@#Ѷ S$P٨`!ԝMX0DIe[|MT,I g5[D \v,ۀGlj:U$jT=:e6O/6$!oUOLr 580dɺ3l<1e50Z4TqKt[@!=Z9f'OX^'MCnlm1K4);ܵrItuDBEӐI&fƺdͱZAX=zO?~7o?7ziHDGQ[,W{63m΁ޱ#z;f9?VM9D;\˅f`ӅjdE Bd$pEl`6T{ ۛ,U[DVORĴuJxN6봴5@R'R)ӄ3dzWmfGƶn8KuX;pSބޘ;.*.GV$(IjJ0&݌s-:Dw&m34AMbs%eGCQG8EǬ=js>v䈍UTS9ˀ#ȶ:m3D mN: Lg{02o48;u>s,`MQQP Q5\r> KVVrRخ QTLY~b?N' w'-GM," r +ճlGfe(&:֚ihfJJL v-1@Y<Ѳmm?Ch e?API֊͉|'m*#8#2A޿=RK]\Xd Y δ));xW*]zq?ԛk$}ou;{[~uzݑ>:x $# mV"~OJnlrkUS?IcTXz^8fǃ,<t|kOdJ ݆A4ғ8f1.n5gB(QS.IOY\=s#DO" p1EL TVl3g/6l̺S9zf(]JA&\iJoY/N Vd0McǛokWHp~'|{=Տ)=_ Gm$m;JǶqQs񗞈qcrv;+;b&l,\.w~'3trNK/\:zrCggOTQDnYE6ʳeq߅cn兣&{/,kp_Wͨ-]X*{ 0?vR>ڞ΂;do/;3"UB #cyOw[<@紉-_3­N&0S? \zWW%Ra!\b\$kRsoo+3ud㶄BʺcF0AO9y[5ܺhP`ZN|k#CTf \"MLl;.f幯p q+ըi[cM1kRIdK]  5mq/3+OXkڡ[LL4Dq:&ª1a`ɘa?x^}}~woeOw}.9Q=()_^Y%fc'[K„{\>#^S%_9C(iS(8Q]p_rLFM#;F*iFD]W.3^Yg5v rF4}Aed4ru݌RSomz&)+Q-K'OƢW6aL%ATJh1W*و/`g B`ADuRI1Jaԡ$@;C} UV\t?ɍO黾MG_?{Xa#?}o~>ޠ\OJHTWR6եsAQ{tm%Luo;"[M|OךUJ@s2vc)y͵p548~݋Qd%ĚLM xv5B [yݨU]INȠ[ۤ!R~1-ػLc{tV.7e> Z8&MƩl)g$*ۓ0FUVJ%tmKKNR>}ڟDd-X+v{V%DmT)>cv̦A@I!ٙU5)\Q: ($ N|Wܵ@CaB5p(h=zݹت`p/2ٿ]Rs J&'UO%BGK*pzW_s䙝Z'cCp:l%!2nM ^WeQplzvȢ"0JnI; V.]O69:uSL&,;ù,΋Nq]}6om*x{+TuU]u+_Z %&0t.BR.W%DdhL37} wo~~o| xt/AN^#_ۊwuO;O=z_%2±EAbm[qD').X%ဨȢWnhXGeÞ./cx_>Ɇv@8*(wXz;Fps]Sۧ ۤ{sM1aepi[a{.Þף D\iɭYDmFUa:f-E*#~V`)Y$ezK@d*6jI gt+YP :Hچ.PjDpeʫ;xbgi|K{3'/_=~#zo~W'QrwWOUQmvHM,`J1[;^Y[gnujg妵/eSyEզcy5Ѷ%-t gLrN":f;-Ѹ񞇯n6î{#H";,rVE_\9;(zf EvV"[ZY„Λ5LN6b|] =1p޵r!oCʆ9.!%٭E_:Ij"[G| ㌰؜Ilԍ D&-;5VK +׺Z gd*u[ +Koc8ם|(nzK@ δY`3I&? Jl6,/qFZw p4n4:mpe2s08cE=}2t~u4}Å{S[On|{+cԮ y,LX--/{͓<^XT9iT\9եK">]_?YUD@ xGB0՘ጮ I7=X'Yʌ1DOjuppл:AX8x ) z:NPTcr(HQ\"IیeEi&t8 `@X8&m,[.m ѹ L\pHb6Ŭ9|[ J$\8 nud!dQm'$ǯ?kNwMJI3&hak-ǥqO82QDּixZ))WΎIN888_i|&$5O;(.1/I`z1&&6RD'duջnow&{ډin+ri笁vϿmIs|C=cHy=p8F`b1 +#>pDB̢)kZBTitIl6_Vs@t:nuZҺ M6~SƟM?v0E#‚gKUZI=@qacͨɒt;k)ǩ|sxg3DY)0s`us,/e\6ڮcVf@qkPeOW;zv=Ҋ[QT햝k=Z;w!(J ! 9 (}&`d!8,9Qdy3t "eHeyQ!3̤#S2 s8rgkT|W)U;rј I9.M$=ӜVgh2o8pKs*W3@SJŠ ͢'Wp:jPSZ^3ò1XMHfОm{@VFSqwRՋs]cYaw~:uaEij!̯;'qpiQak (Na*J#Ki6{aO 9GD._<[aDx(&)W zOޓ*IM☌~Q) vN8ASR͘sY8f+sPYQi%nN9k ˲KS-jKg#DT2VIzQ{Mݿzбyc rDY۔=KKApm܎٥,~}=w8DcN)ocAꁃ8J1 ؞ Fy,!Pr!iːqW(-5\HtAD%bl[OHtTl5p'̟s'8:mv;`Y|*TEH]ߘ-(V1',G( l;f㔳A2UZkӹݦW.XdVg꫼K7/hXɊ0U|>\,1˔w )>M^lp]p$g0ŬA̳AwnV;fXtLf_7 qpBJ4 jʭ^b [mYrR J Bttjlzkg,xF߀rPRHWoe?3{i+GA,O!ha#% Acuf0јY@\veq%22|m6s$=ٜoWwzrD!I,'QT 8؎V&YMhw4DyWœ7L O!KMJG/[rj)dhg:K* sA -qYlE敍:ŤIISFJeUUw̬*fK&\SkW*lo΍@?qVTB$ʝBs#@5|w^p>qUT\f;H9C-,a<><{ͷm[1Uu\%JRVM2 r X%jcAe"`cAW@z!.Q뮒5 !֍#u#K;\[($Ch1yD)Y jsYnP[Z{NB̎:-v{"Y;JOli-cmQDY8Hak]4f$GL@I.wcdj/W` WbYU}V29Ƭܟ.BudSE%kfMyDK)[Dw}|WO3Ք !iʀ{GiHd9Eyc(C.1P[g{"Fp% 3}TzHiyD;j ;@ʸam@y}pP'Skv bƳZVhNn{5MML]9i %sflO?)( nhʒg\X~#_EN㈜z:*u MuZ%R0гEJ/[B}僶ykB%i̲E[C0ʡIUSƋQUgՂ&W9!Q:_Y5IgD_Y@,:D"]n{w*YF>Up2ֲ m_MrB +<ל83vj8SkUc>͕IbBjYFw*<JsW)Ͼ\ 2Tiy)FoLY _э[3U|ԔRSǤPͧh'Gt0uh{UD5_L,3Pg2lBwqz4J1i;GI9ҬquHlI@ " 0cbbhsdaMO1:.jUGc"ڦ|,;Ir.eٙ7Ƙs9ވLel2€Be$DO@&Ǐh YTJ*8+]Ng:̈sk9Ơ1\k9F*<ُ7ǐFTX'%wodF'2gav16t4͒㲲hsPLǂd-̅P1)κJ" =T7d2M$Kð֤_7~[7N\Zփb1bHl,7ڐQA7A9: N@ZƧDb]&,\9T̍@eaR+,}$ȂqߞS+c8'"t*HDw Cw"LAX-㵾nqY;2#dIx䴘K;p>ߤM09l}~|3-7~߽3QN=nzyA6Lս(΁UO8u`z,Odԛ~Go۫w—(SXy4lo2'F]ŵ,\t,p,-EO)D7c\lv0%j sN.MZX*Ot5aΏ39D wќhIlCQ7samxȜJ 7sä6|nuDIwB(1G_ίmv] YHܴ;AaZ։9nIOСb_5?W>p 8fbGjJBQny`g@[rmQjv,4=,N0E1QᎫÈ6 HD@=(rΉ8e`85JCwU] GmLd ^e! [ܚy_{ և;q~puCR+zeFvie] `fdo7'?li[m@>_'Jf&W!6Xm?y愗hFmr 3DPu(5Dh'ڍ?7$(i%[Q/^ dT>RBbսrS7:'A;2x5uo'm?_?a5 $P rZk}TK-ec-W~6")[-k-cMpnLJ|^VRYհM95j-Lۄ%Ne@LCb:4&C{L& (a,QmׇODސq_pq !X7:?E#yrhiW `lrb$>AxSACE`FeDGT! B1"0=lo~O,3L/o4 鱒5ҭCAL+dQu]~=ឳȥ37ۨ9CDCnffѽ3 =RCmB,Qwo5BHsk&x{&!I;}8 gZ]/o5XŁ m0o?#1kg CKRbpmcci7Wnx? 5s4o<]| \ ̔*/|s-R*@ytg`]-R WkV%-ԇ)תRq,rrbjAWӹǘ/@!+`9 gK5w.kw ZhM4 Dz}n9UI!P!PuKD[/""uVT݅1U3` XoRWǴ1R:~ ! OyXVEv(>-ڒѓJVI$үyY35B*PvkτK z[jkbE.̳>rz' 78 hC] ʚ 764U8C} Q Z]QO~? _1qJZ%;H̍r/S)@N~$$5eAITTmD}zDdDch5Ixhw6xզjM|]Q]0>| -Ѫ o6TRMǂ0hWwtTi s{m"T}!)kguzK[3 E)zH 8\=0ydӣu4EQ:M\TcL )$C7[;Au7IIY"ݤvbNbm,lԨc'ML8T<&L/WCVPϳJΗ+V x'JީO? (2I8$hMf5k``R/!_F[xTOM6LŦbuB5hkp-*3{N<mS:A뇺ژa)zU4f\zB:5[\hH2vZ;Բ/=Ht^fSO Bw3_ ƈAw'v;i"FӴI /Dʀ=3`'P&s/&r}dL{LŒ.h045K?Ⱦ|bEOVPva-yJjIH( wM&EijE@I ChRhX sC?m)OCp ‹b9KVV+K% LK}|.lsg+3uW'O3Gu0Q*j``b<*>pɏGO%/Afx8ZʭcxMd,].Sjq^nd*ZjGc!d|Im0'$ (͖?ŊքMN5%֓%y0GTV0#&džs6LE["f\lLHP/.Ȇ{F 4sT 6 `6BTvC"CyL8$.{Zʑ/.%Fu| 6|~z>K/wr>-pOD6&5s< Jq i;XqmС@/7Mt? h /b^^/=:\.ɞmĔh/}X5!q[zU&ޗ5b#ڬ.$\z0iblmI{/}tlꞙ^m*Z?Hb֕Ky3 X%ҬL\L&=E+;ﲐu/7=XO8޻y'fzx|΂ s3w3rQj}Eq ht"+StuEi/?q |F~9Xa^P]Hsa01lWBOQYyd kؔRcjtys?_2rn2oK$aԉØrufbQ460%lJp "vRiB L]숩BR+)p_0p7}8./>0.GowClǞF8=z LAf RqP KgâG˹ -h)4aQ`e!{fY@Y!fCTIbώ]9bx sLJaީuS&924PiݠIXjvκgtMq=Rw/_;ϴS #\40VéR,_mUR]Tՙ\cou⬷Ԫǧbx0{n]qe(ޥW}WΠL&g5=e$3-+v˱K[߽Ո%eM=>gjb! U] j-%1 BIQDOgbĞ=>>$Vo Q$C8Z,}'&Q-'Ϲϟ2~x/܅:3|^Yևv( 5$a?~shvy!AqV"OJS\Œq᲍囿x}Ar!^^2TfjB7Eh?UZJQșr\LUMp(~^| s0K45 JR#^j\-HwƅC YP U[DXC۸%#3)AVgJšX]~pR`iG{br`H }tNڤ+JP󋤋Kdn JIҫ8GcY?#'g:i#'3 t(0ڤ"3ЁnQf}><θ/\rWIsLBV5OD7}v"0@xXM=U~T^vl-ϦYXתQDI*y<@< 8$ԕm`Pj-nv^/̟pnj#_7kYzy}^ս=3Ǯ] -Ofk)^oCDpC'r =dvu%#7pFMĶҤq0xĕU3ѕ-PB GSɊ9L *,wfU݉ۨDx?=pMI=$Ih#Kc$ohGdc*`i!9(h_W2xUI`GmC>9* "I7v`$):B& 1*"3$!ER윩MeX̓cw0O:Jm?lgK?짖f s#;i{@u h~7!á{sאeCR'f1É8 㳃=Nv*-Z+|p`en6iJLSzrVJ{3 Bsj_q!7FmWQ YW_9/ ;7l. I*we%g.Z,3KV͆%j VP2?ivWNs0`$\i@v+< Fuw%ʉJ4wW[7GwشػLzSUDhq|.0W28Źl_DyhOk(UX-*M$!p٧SP|Ѩi#ݖnA|O3mt!UL[oO'ۥQs"˅o PcA4XN\DKL#T]iqSnhK.UCU?mk|ǩc,-cV i$'fEFP3B D6yqJg/~bފ~s盳$^]sO(=dĞ<0TژsnB8 ~ ch $mUV3i3bi㦍 ݖBT[t6/^vm+zꙍ{3~"gubhdͧo¹'Kfr'5[G\>QA' ]v*QjPچIp76.# yٛ{ |?Ͼ/; MdIӐ$m0j& JT ^fԝn)ZהSs + [n,H!&HA٬O[ A1L';{FćfK"*BPZpԜk*6 &HǼݐ*">wpZTu "jm0RoIw; 4^/_,A g bpTd|s69Uy#,v囷C5q:L^ɝ>LV)}ro]դg4W^cxλ} ]uLlXgl4n?@v9giVi|hb' n(U/ĞV@0OM z9{Wʙ=pL5d>k O'„mj.|>E԰Mb=38ԋ(uim zϿX{]WmXc^<ӕX,\IRּq'}Ik*VyZ"V]o q:joez^wԭ\P6qh0#o ĊV9'D6l"1N0c%Z93X[[PgScϛQgDjDwxQ pHsi=aLgb=pyxshT!lFu-db9sࠧ .9Pէafb.QQUw /23mo ί}W߿ d '?O 93)H$HNFIUj7WV*bi[ɔ0v~! zKmOFŖhoF䄛cnR pn7:|IJp`ʌME}rfSb CBkc>oU;9Zp|?8Av\Aـþ+VA ‹X,F(Z<,iIlA9(&Keˌ*_'_͛"ĥoGj+ތ4sLj!L]@A׺u?@0! :hlEmWJxD4R}qcZ4}T$LՐBBmөljFx3qfۙ,1gZ)'va+NCz3LZ3(lؕv6f{I7èڍ. 6j Vw55rtuդsPaFϝ]y. l=UpX&t~~+yJY]8$8.. yWʨpᵿo4N'}`NX+L56ݗq]#3zua]Xv-EW=釘!d@p@W3^r@7Utw6UTuR`?h#g_( A Dv/8\2.T\khrt8gNk;V[]+B)2Еl,y  'p(HDq0+)PinK?b/6n||x3鋁oưjrbRW&~|twͿ?W_Ob,p?ysDZiaPȐNSv85aNEBHj-q\C"7/E$$VE$98Q]ܳ#jR$cb蘺bD%|M^ܺ1%$M&@w;֔EA8oC¨-N"v[! vX5׈2$3t 4F7@!‚XMm#l Ԉ;O`"rXᓍNN^+|_lv{Z ?`'X]\› C: .8F 0ٓeޗ4߇yO(K_\av ΒX&djq=sXm̓Xnzz%^nsO& u6en@o=^jhzc$`>~% nY,ܬ !|^=9SRWk0WXsծ#97?uq hΧ\3iZ'N~6%% QY~2zj[r8 [A$O?9JT Kq,Df zqPN}`f^ljec4=o/ڦUGxQMmH<ˣFD,n8vUD.i+0_[ zTx>ci-ZsK֭I Dྕ!BQ{ e&֎X@1rZY$Og`=^ŋ|HG90ub΅4p1T?86(b1=jQ xWO0OXaEbji&vk\x2[̸'pwr$NO>5nMNJA8$i<#M3lX~ts$"%@GM LfuEhVe=3%4y`&j莛]*zphrʏroF&ʺ.k zKqz?Ǟ-aVfx&]guȮuLZ4'G _D %=׫5wZDϵ4^g֗:3ysfڳW!3m2o3ds6-Z9 h= o{ϓZ iG_u:O@.2h9m4v4Z\XٸD/_'w\ci3oA mN\կjLծ]CL*d(Wߙw.d3fY둀³Z1t={ 9r@Oo^z8f \_~|QnSSѧgj|J2SU!ͥ=Rq>]96&[]h;t;7ڭuyrWh?=ר'R"9bGtonEC ~DP9.-g6haf335:ʏx ˪k.+'և-ogEM(~^̬4GN\Gn̫u3T\ ~pOFh1Ng = A^ “&\IZEY?5rDz'<6f`%vR06ѐ0/'{7?Xܥlwa,3?nGj)I-zV)4̓0kQ3kČ-sTML*1Ԑ2%3;%Zp(r&V%-!gv; $-+].U?;cm!2>ʨւ6"?Ivrv,Ni,D֫$Y0Dظ,KVev aMsT FB`(ٝH`G1?q9MqfHs?I{8IX5|v7믬~{ߟr-_>62VOD}+3b0@}⮕ %~_\(;ՙ,.D*:G9XvI[CjyߑUH CXfA>Y-[;9;v&#+3է)2ZUw[=Dji%B*+(|%gWC水U3>y1S3s$HOI9v|: +'sƳԯnw2=Qwspaڀ?8y7;,9g`2[+/8%Zw-QrvYE_rpșKaҨuu ra. j+jNZzљ2&ܧ .XN˄Ac-ns@XmZеt;>'L3)jg;fI(j B7Ynf~#Bq~xjzAAc,%%_}(ڝ1b(p];% ;f'"af!aY ]F)j]// Z9< dF*$çqdmơ"#G+CiS;?Q 2fbbD(~4"b Ifg8,9`&I8#Gc-GEu ̨h!.dz(v]%"M"m2rb7!9Hq 3܆*LPR\c_G?'Z69I?@C /Xh3pQpL̴M%&u';dL;t_9/GOM mik)U3|  ԢW51j:X*땤Z \8)JvkI.#e*:3u5o+kl/͂-BkpX~uY˟U} OZC򫉋aO#L) /5CK ې>q" U?vkNT>olb9qD`JZ14}%f4obm s E g@Y\X[\Bh-`b<@Z wH7C'v 8nJգDaK%OáqCR&Hj no@;k7>ljۻ0In6jo?|1 ,fU-nSRB T5e@xc8`:z,ūŝ$9 "$kfHRּ5!6fRׂ#30dB&L`*(^`9n"~~_Tqv4C{&GU8q%Շڙa! &#ŋcԔ's0zdNH!l*'t0@)սg}9I6_`UR^W,NEegWC\{C+xBIŸdgxQBKb`u^-QO|BU3@C=ƶ'gdps)\)w~ϯ4̺]~6<{M_Z(zsFvm: ~[h^N M5&j/\ԂCu9{sP&昳SX` ?55_T:''LP>Nj ҮWTì6ι6^SoMj\ϝ,~(ƻL߳[suEF 9bam"fFv`M,v~fon v$hH_~׾d+>Ϳg?Ư~w}ĜH@DiIr-e:8Md4U$e3Vá侒efjjM9QK5&W;yb.U'ީ"̑00jC2"Vp,pCēKzTwP"c`  Xg *fI"^$jL459 nß?ώ>wo/#[,|ED`ܺ4MŇ,T3A&zWo-$,Nc_bu  3U@UuQӏ_!3M}j~~>,Յ?SG3]kk䊅Rh@kۣ.@t,&ACn ;v. Wv Hmrl֗T=gwIWw5)\W׉Ӏ湽E GuSkgU@sf{~kVȜԚ/+DgOH]H[4VD0^EtzTs\Q- 9v6۽iݩm"Pz5s٧2B`bAN4/c(\;,=`` r'!}~,ۖ# IMD~}=~^g?};ܡb0Z])$, s$NJHj V!R'u $ U@fY,) ~D3,eIM=Lj 2 e~cNPHv6 C?jDpW/IqBDE/ո< ^(=Uui=n(j!ȓ lAݵ(% W@Fu /_A~uV DRjNtLݫ?or* q:N\]wvRu+@d TQ[*FZfZr8$?W7Aς4@dӊ:u"ú%!3LK*3Fv*-znsswU?fS3mi}[]} lOU˖ ,>8\&Ku Uj;E~nKėy:v2Ǽ뜯☫,`Zϳ/N0<6;g5ߟĸ u=ԗ/֞DX7fshHQ`}PoQɫÝ|2@0z-2&R?_$w~²pⱚ= DwըO?+U,:[JIHDD8Vد K"lVۇ@JLj;00t;<gWMޫc[_ݥDoUo<}×_o7_>Gc=|W?*`KBCX(N&C2}y1MZM]+HE R}`L7C&u8ڱe-Z,}L嘘nWmTB0N*~r!g!ljڨӣSd*,Ȅ&g%y{zrFL$$1J(Ҳ“,A&-~,[E-KSD=J"Eb"@ <{sUuTݺgF^znPT}!/D<":]`azhwEuH 5 pD9Rm`! &Ld. B+5.ʆ|Ш*)#]M3*wP  p+/޶#--ӻyIZ<8;I6=R'KZ/zʫw<=֟/[ʭ\(*UȒ Q___U]N^9cڲCI5Ȟ>㖨;ćL)tV`T2^LcQ.!n(VjKt+Cu dpUZUm{c&UM-)D_YάeLa9]j˜HXx罐B/vJ\*RD䵧+ėY0 X &Fq!=D:aJl1Zc(2c[t>bi+BNӯ˵-I*D5xU Aj)xDW0VAjɘo|@5QH9S0•!D^P'm۴7nuB7 Orԟ~ꉥNW|'N8|ž BCF딞+FcsF&E o4Tu5WI g)]zYfb 0[@ QLu%e k]_ӄ U&Fecx7pЈh=Tq1!R&H`]*\Z*qߨWtU*edG>KdZu`O([Ba N06UrtOQUk^i^^ 6zpq!y͝fNJ (e2'p3b@E!:s+,tJ s+*طp2)VseѣPOۺm˅_p؁,\=lm|ߧ|aqo{ZhtOtu`V AEUrQ+RKܶu+9sPa\N)\(+kh$0w52^ ^>!y"[Pu"B&-F&y 4 rYW=vO%:/np[WSePR'=T{`}EsnZ? EC#%k =z5 >\=3VF5߼jT=wNk'_t= 0s"~8އѓQT o;10 >t5ȫg^,xK,ؠaZN~y7aE}Z[E:pT#̊7T)x(DRiS.1F :Ƴ~GOSR/RO5HDTE=hmxM{8DSp9Jt"+ԥXL]Bym%$ѯ+fuaCbWubJ- ɔcfvtl;Ic3/yk[׿Kq\k'60Yp! 64H32,C/BbBX%hix2-m:4I9-i(!M!@ETy myTi:[׉P( rr `!a)B!n!^u/ iӼ뭯Ƚ[zϾ冷_'c@W}#5$kNgM,:+!!ĐeDa:D U<^R1GMR_ #ufuh}aq;%>6`zҨQ_'SnD9Oc\:ϭEjpxC߼Bj(a/`&~*Jk1"Tl%nV WSēRZqYV<R٤ kڽ\aJmR[:*V;"c%Xp N _`&)MD2ZXB”ΜnJږ1w* )]^zS'n.j+Vîv_r'>sBgn}GڔB0 ҩ)r )TA͆5NBbn){1LZ1)dn"?b(ihob!ӖlZ2d]p(rM*,SbHA^5%P,A!aX@<p)?G4bWQL&I[~0|'}oIRndHN!]M-M5LeRRB&z^X*aI B%PĿKֹƾ=- ,NuԾ98?oBjyChvt7_Xé_1TYY.p5$Q/5lj[Ӱ,Ik:N"'׏!8&eFѾ48 3%K(4N#Uυ-1BխsCX6n(5^gOF jNlag.VxF)\H ~;_7xb!]پGH(5&K%\zu3*G~ ȝxy-EoRk<:'^;=KoB DP0%+?nC0l ok'L7ސf ['S6L&65ؘ>r+U/Wnָz;3-S] _~8votnh&!L7 %%e)+p1+Y1l y8"XCK ]Hrn&6½ +j*% "TBQ'в<"U$JW2Bƾpqe̋1lXN5L,fD C2_`BhE Uԋ0e`KY‹Ջ1˵ȤpTޣp=īCEi%4:tC0 s󎂧px/1w;_xԡN??/6Kk=%WMwquyo#;^+4jfupwi7L5uG|o*=ʸC#ARUu]vCP/Յ8^UYְAZu +Qo#-Sh#jsEYmϳ%ZC9#tg,υ+344,0*g@%*u UAM0;KM_kGy깚so\cRz%4LYhYhZFA=%TfTnZk)h!b. t ~㟜Du*N\:;n)ewt!􆙃8էxM&WN.=Y[>CX>8}u^\8ꏝ>u4X3GfVr TC{%/G'w [AH==m&A3$Nt5wyV2 J H̰L04$W RF+EQQ-@ E@ z_9!tJ(1h'pJ,^fe>8 .EK$%LX0gh|M2ol5;uth'LP!ky"VQZbW` 43MXURར ,c>ooSv>c7\s;4=wҝ[?t!e滟X?{>D7*e^tE.I z#! 5^(}A`@*-` 0M^Y^9Aʥa T;z7t_{FC>0Kkz* Pت1h+/36FrfE5N5ȏ)Ȯ˝a-xv!}h: ߆p$a'uZ0][3nXuAQAx5gMHױżV5OX+B,`(ZOju 2GLzc{XDURNMevNtBsPlN_{9ptj曮lǟ~wN?}=k8z|ɧ|ٕݕ.xeIqh|{me\ eNL(͆1d]U)$LP&J T*5&&*r򅄦\<c*%KNdE M('Øn'Z̴+5 rAׁb*bBBxCT'jM4{"İCxHL S7\{CQp1PaHقmEsE4@Zz-ܲF36N d5… RMm <Ưt:Q70ULQUk\kb϶DvL3Y{w׼G?xΗ_+'VGN?^z9,_/rsF.4N+>t$_| v?%]]X֛/ܴ{Gəbƭ-[q NaRDuUa9߬f@P* ˎz,hZp%6p͎Į}Uab/*/+סXz5yc>i0acSֵ#2: )ƚg>f_o[D B"K{H5zfsaDR+ǵ />YdI--K*]0S&jZb(>=^8lhriM NΑgҒV88qUR Sb2M7mӲa TgsnmP앚!BnT`&/ȝZ7 4Vʷxի/kG?vW?1ꈹ-5=3oyyj˟BqZg篹z1*J6-'V8L΋W!"5%eNMrWrI-mjYꤤĆU{ h4L596"+ &0EuFhNxtk W%L%\D CdNFw]rxűr4ӄi@Y<{diq8f2QQSdȋ0QRR;A @Ll5аD^Cjđ"y(Edjѝx #MC+<BNw-i.i7~=mJ:z?ujK}%42gs_?og7ϊ(1h]\ߘ0Qm[QjcS&]E/{\0P0a*u %Bb|D&8XyQ;L34lT\+`}W]^p#Hv~𣞣:8] '~G?kqK Mײ-Em3mVzQ)aV@ Y J`ҿ #`yAh-ѫzgaYn_ ׾`Z|Y9 @&D@MK)!+64x5\ံAR hb.@˧/w;zN~+SVOc)M7{6-o/7+Ntg;>prRH* (TW]0&Z'fOȎInlO-M&QlL)T]"* ɔ҆F}.._d>Rp-0J&'hX4 ,+{LD%,;:Zb6XU* T5>b2z WE90F_W _#Qq C{#ISckHUU^5vC 3BF1^r'ʀ51Ft4-Cp-jͪjĞ orOuNMlʷz{WKws%?2^g͝גW{=p^"/]5mվa6kqIDpE߽DӦP%a ]FT_G($dO ~O&Ll8y\ uA7F#)9? XDʾ4KW.ǁqGtx(_E0|9Btt$h}o w J =׍\VWe]gDqZFH/:uF B/A0VI$c Ga+=q G@1}^D$p6ES p[L5,mJV3 #h,ΘHݯ{<'.;<yL+=~owto֟럿/x/⹹# wX6ʢB6U$'SNi"1]БU+ H-v.su+ܩ1{b#,庐:`ŪӀOB_jH_ !1pUqUC@DC}q V}](`ŖvEjNR T(аvTt gD]eo,,5*{&EfŎU0aæD BbX*J S3aRkQtap安;w>~ٽeצG4W86Moo˷\8tDnKk7_wxus|ޱccK"gC'|W4;̠2\ᡆe!sS'jt Ԩu>fdS[v9E- xgSA'j9T"bDO‘-ֺ B]nQ;8VvEIBCz_;U3b-!*D4FڙI:q5/.6NM⦴1+/.zݠ ը>>DDI%)m2K32ްhXJ%5/mkfU^o{Wy=_~Bȉ\_z_|w>uWpxNoe?vNrx677_8 2BPw5[t.RBC Q"^ ԲDC tB@ #1-4#4 ° !ʹ &)rA)D,ڃi#av Azx^2P 98a#FA5I  mYHX@e^e:cu{WѬЕ'ZJa8ePev2 &r^ƈWTz*D2kejF,LWػ}Woqߦ8qxþox|e'6mHP̿u/=ye:b륗H@7kQDi%F9&ZClxuH ׽2{0@ʷ~Dx P 7CO \o^:]ņDjHH$RkFjۉ} lpkz〴9l]Ћ#ҒV>YhV C٪6!6/ƭ%%X>n3霎' ?p)xSuRȔQAk{ A* A0'_ȑm{/0b_rnc_ٹmg[:)Sc˫j;9oDbvoz[g6NǏwO/ub5 )r9дD]ͽ22QRlLH! (DPb9xz:РS^H I0BO,tΊ=}NDs,sKCc]B! X'@( ! }<0&`/\@LG)IYX K\~E ]΋2S<Ġia +2Mih|~(\+Vw>$fc^ 5C?\㈮9A ~hWklغ|b߱ќ>xjEW_Ot/t׫oy?y]8L6ؾa?rcO.oǖ7mxm~⸙ ;rZhk YbƖ"RݞJ\f'=G ʟ)4X*S˦*K5lN1S0H'~1{;$nqL˔Zj$qFj)wIϞ*)+uLc|Ί_ԡi}=fL3ٙMT_}"sr׵k$A^r0Qb!1|XFل?),= E0f\A?g?C|_.FsgZ:!+5`Lwo$u6Yg5T>Ik7=ՕƁR<@zNkW+B*XQKyR?cgMA+cS.3z '>ҝ9Y4L_ڟ}V0K=O?]:񜤇Ktֶ6]0gٯ=x /K}l|xQ1 뼪jÐ1h @P&%0$J^&l9E@lHD;i#儣^*R/36XGV@̢?,GF/ꅔby1MuF 6 c"\+6(q$BNmdcS`-7("21l+ FB6M@Kۣ&G7Wzj2:slG[ Ra14@'UR9o[[iro)hVuu jZQ*>hَGyQ2їWaIɄqݑ@UZ _oj++С?6JA-S=߰DlPx,F+|{-D)#(U*],F #ɴֱTOUt0)l˿\TսQ'is?fk E%5֎Yi(7ʘ Q(l- !Ȫ޾M#w Ϩh,((ʵPu!LCRCN`2:EC֒Йl!Ȃ\'PkXmG*5Bǧ4,D[yy4,5,H#.}SX-%xf[fȤ %ī\ % Kra(2'h% T-PrT% X.l75Zp2(ArRv 4,(5Wc(%dh\cɡ # cV>=IEa в^`sU`"@E+wM\y]$]nsirٕݏw /;6'?O͹7껴m|={?}ltO?$F a\7}b%傾v˞ERY0L&oyс1(S#mue(}4szݰ9Q =tAp!N(;S@5Y깁KٸS`U!rGW-UmTa=G{,TC5,]\oCPΜE4*m\0 kR\s"l2%LyJ2:vll =yګ.xɅ;n:z[o쁯|| >{A3wgoMnio޸}[V*:lk>YX'Eaf5֐1b+BsajYt=&䕔a%$Zx-հd D}pSXFdGKeZ[%+lc*ڄ2V xA;BN&3-yե<*ֵg Aba(q6*Q .`:!-]ms/ &UMP a 'h#%&Ld^@!Z|6IԋwE@,Gժ D, X5lWܻ3F/~v Wo߾ukkǎ`uo?| ~廿!Evl?k6=z͛mNR<0"hM-5LzquK $яFZ `7UѾ7ʿ*탻GRV$i< H+-w]LB_ݼsYLѓx>1bPEcb~Cù&WvSS]y5|ˀ aʁ%pѩ5R-lhBEDW3SHXϮ‡ 1wXJD))J'ed]__e;7.G_~xm}#xɵyMXJ =ۛ7}ˮ/xZsK)~䑙_ISY/ g+JOps9atcO-JƖ!)\^=<ѩL:X.%\ӆ;X ! ]jPtI-K2jAʪBKt BKQh!`ʖK13lHTEH50&)(edWQJM WQĠvk+s)2A`B1`Z< fR,b Wس~K_|z荗mʣs_}K?/uG>De9+.1qx"vŗ< /[ Fs\3!(hYO+/Nu;q(i*5>-|udjA G $&2D(yuY'vO<}O?wmI!%n_Sl޶}~_u>_˧:l^sa"xjurzUl‹X)De+jq[S6̱XC#+t%i}pz}/("1h&.x+,*`4.j(#?qgN&s_7_/\/=ѹ>v_;ZS߷gn阁?r<;=;Z6ι\&m5rBb%b^(hZ$H4e(QeciX"0LXp.X,DnI0N%B CNy5L"T:HK1Dwä,D@™h 1y) - sT}j8AN5)D (F+2VD+JXB`GM>ȯ` (xy!F&(DUBӨcc\8)<ӍN??:ahvy#{75BUmpW6ؿ;;_ ݏ Hdojm0?T憏a6U_ Fajhctxs3teoJ~%TXD u;(Ro$kZׅobqN_dߑ#Y`@_,W5r xs8B L3Xwe:R?^z("S`d 5dc N Nr.G;0J9LFx֟gb e2 _9B c=4x"zjկ"Wr =x{65~W‡̞^<ӧ]捷_{|>vu7]xg:Nn)5+4+6MkY!&/D1H,N5hXY0Fb`L RTm-QNLAɗ9BHSC92aDOͥQ״h'h%hZ80Tz~Qph{ ! RkDXD ZsBA-0B!/V(<׾v?ҊZŐ#!Aޞ0pWfy{[`4k EW K_aJ 8:iD5 J]uqBy$d<%I-{ 5C%2jT]QlGe]QL03mS*ei"VBSܶ-#zOS׿E6mĩտ{{nْ>~Ą^ibuo ݥ[X<$8v4{\bizI+s BDWK `Bf Huv-岒xm$Ĵ\rN##-Q!) %d.X-Ě]0#0B| 2@ ch)2Ql#-V!OѰIJ1eCbx"%KLbgޞ2NEɉ^<`voܑ:DNUI1kdAuqT5U*!aBL8M%\{rV[M#w~#?7x|b!O [vM=GVm6םsw1t}fTegF‚s9<&Q#TUUuFH+g 4ŲE 8Fy_~{5x=։C׺- z" DQ AwU6*RTj*W囍zS_í1@@J"Te– cK20dUxцMr;R_{j} ϻb[¹?xׇzW_ /񼯜ܱv/c_9//!MWN rID+ i W8dt DJ!- P -(BE2bp$$3 \`z2,T, 6 \(d:N}"@ZQ_ "h0pUA@ ^2Z6AEUnXjŇ^mMVVzbdu1"`HUHh5% _gg+Wlڸ'<9 wy/fsMC':{Mme;Xjw]VVT #qӺPz&~{Pƀ9uҪob8LxFg=_BDkE㘰Xj?+*,OsXHD ;]kߵ4<X׀ X"DE@\Cj]1QA_ڠ\ڿib J?eHL^ZJ mmW&RDCY+itH r-k&2C÷r?y/vƇ?y_ݷ!ݹsCd]tqcĉҪzrW>wjLii (r_>ym$lEF̄) I дh.uʰYܫ5dq^+;a"Fs|(e8<(b. Ej!F9- 4-40_0U._Đr!$/U3Lqޛڒak}{Wsf7,Iˊ8-V @F@'  Τ ,D$a(Ȓ(Q)3fw{Ω{W:wxSn-<ﻧN{eU 0 Zq3vablB8^쥳_fO_N ?Ø~[wug?paj|DANE+yס'}y/=׹7hئÈ)5 ]5`/E,9a06zx:qWטh\^폸;?Iq]` "qlU|06>ha-mͅZgc$O:O@ֽV1n& v_z{cn?kg7_~O&{Y?w>n틯;=, Rڦ&]K{~Ewm{px:*xawPxAHe 08 X-Í=[,=7(`pa?Kr.e^EF.a W}ߓA>4 ph;1RūrT2t i $k2Op?O ?bNUW?5nboٸ<1eQj>O% Y%phVJpgcV|:jf+v >軌jVSk4sV{*9+]Yh݅CpoSO[g/{ՓDu;|6@"jxsim6rՀDt͍3w~7n߼?"³˟~⇟}7V Mg `46P 2-6I!!08:PgqAbp{mLV489C P&ڈmƦY_oz.m26BM֦VP3*2G#4x BSk"迗Zc.Uݻғޕ\F3`Ps/vJz(aDj]s+1^pc:mW7&mr8mw֥.iǾ_Hwݟ/p{e?SG}{^|qwՓSYuĹqFہ\WBssyiUx< \AqWt՜,ͶzGǦi}2~~aʈN] ~_nG1x)zoB]:nԫdnN )} vOS'g% VcV%Wۇ}yYeQee4dznI#;) {[3WO&IRvZk#oQ͞ec]o\^;Nٷ/k#O}_gbK??'wߵZ+9.t9I]I~* mnлN;_e9TqD,` '7#omƙ^=IMv: o=L#E6k+@XDF{mӋ ̵/DZ)p}EwWpW!KٽXk1ڸ+7,MR CPKFZIݙ-J``CJ# n) I@5ӻ`f묶uUd/LV4?1~hFEqܨRaV!)ʭqVe!.Z>>%vjX:I0w3Πn|)b/x.UHM򦹤]zHcX|_t6U̱Z Ǎ\wڝӏ 9[?sG^g_sޝ7Y=#76-~>|U |_y`,F}WƓAwrGv⤓X:4њqjo-& ~@\ɤ65t K`nT8 8Z`](*`Ȏˈ&H3)ҔDD'yEDV b@H>j^&"͂1K$0deaHÐ1r9"Ü"g4,bս٘ZiչϯV%cռgGM22o֗ 2{~k>QsycEk@ZPǽFZc.Fc_~Sh{y`b*&T'ߦ2r^]o""J) eFnhmZ5[hnR&ZŒƪ.~,,AjRK4KĨHlMCy,Ae`3h+r6h3h&N01lS+?^ſ?~go}o{_JXWw>{>n(e8e }u58\‰y8xZY> C0YɫR06D,.}Mm l"X Q6#  !G砡SfHV+PS hiH2pya?w)H}4nrvGKpː#@$(|I68DFIhX2"rB5kM&ś4VZoll1&_ Ţ6 \ʙ߻wԶÿOnx^W0NERy&]s &`XcaGW})J쯷u$h0 YYYhYjL.FQD;9ǁy>< 3y 1F_äNi"PVxMJօEU#bXZV-ދapw MKBk9\.Boవ|?{_*ovy=)M?V ۈ!)g0x{;?IV,2p:y*26Y'GA[X8jYYw׳ǁ-ZYf6C‚X Hi 䌣a  Q^U԰:/4@d`?E@dW %QBc,}6Ԫ=K6|c`p/^\z@$;ykM*]l6R5-z4yy<&aI7@<*fn(ym.y 9Lˤ2[/!{/^?4p.{YG! )6 ը2߼ \>|*SSv3Wzj"`جccQ4Y\_XFN~Hv4jvXi.c , ־ 9ƅ!% s_tHє-h̊w8^7μ`Bvlo@gEg,r<"^?I9j(^'<{1WyWG,-,9;< fvwӿQ{ ANX1r%@$ظ"gSuczI ِr}MZ}NF, 댳M2Gd[-hrUoզl]6)K(q4i2إ`Tr*B.w!dC6 f0gmiƕ=ZvtI]v3ƚd28,IPă:9&9jTI.|pkZ+âQkX>peW䷿v}Kʭ˳;[JW9Y\FwU&F1@mʀ[S0?tqu1Aߔm`= b3~[Fz4N}{vhƕe0g*cYdo)–l|)ᤷBw|x3JKʶOjIF\iZ񊎭 賗RHHg=1Ip\ppM Y8D(+lBw:۷ɯ}!|_|w;33^d>H.@ \ܭW ^S,\i$Q[Y]kYq'$i4Snݧ[<9 san}f3|Wn+]²fSVǷڌ%T*1pI;`BOc\MZ^rҾH]s{-26|:ߕoC=}o-#\m>8T\|qeծL Ɓ?PS]ͥRIkiyP_.#_H™y+gM3]1||_~NxDLJYץ~#hKK2KYW^[%L9}B U;fF\,ȯ߬;1.M16zn={ɏwOn6.o%-us@@xu>&居m.c@lK0b α.Z#挳rAlm gn0iTan@ΈA: #kI dF֪X{;lR;2& FI2ZИ(9*ViY|qC"%Pb$H]f@ R+i)s87O } DDDPF`x׷o}/2|qf+ CXg{rH'#}ByŦjR"U^ӕ1(O/gJ`Ԥ'k<_Yxm>(~ ѴjB9x׶@dF,C1T׀3 ;ʰ \Fơ]au˾ lӨVH>%!J"F Q{DvfqYo7z $!4Y}D`ղI\q$#ˀED6= 8hpfpEv3,h(t$NmhlC1tOyzԿSpK'yW1 9{ 6 Y Zcq2vX}G5 Ӿ@_-oD[Dn9Z0s/0F  cHU˷8taUӻ44<{tEAr!m+v)4b\ EZ َy# "Z>lG1GӱEcrپ̽ulZ?x[6ex*w>(ߎ㢏D?#=nxstey1FS`hB%Ә]KJ)RަeJ;TZ_ ,ڗɧ<3Xhvef5K*)kn+*g:7w)drnjJa9P:% eKpCRcϬxrʸZٽFC[m,!vkɽޗ/fftv6[UN%ڙ׽A9rAco}p#={)b0w$Q&P hلzȎE! YM!KYp@ XX-hBCci^2RP!:y$zb>8ɐ 4 K\]h ޽TB#j#kҪ.CpY~VnzId5ͲpeU@!!cgqV=LttNE-}&fA#D<Ҁj_4\~p\Yu'}Y8/᱆"Vr̀a$6׈GAWNoWCoBvjxq^Xq Q>zu䧧t^o?$.Րҗe},X@ڵUv2繷;ʓZ󍄗Z^iø8< 3Ѩ/ʮ;;|T=t)JWf,DHMa\JIpkɥ [b3Acf˓ap|S4|-Bhtw"=YoMq8\4ק>.RC >MB\1 lr"A="yx8D} "%U~j]m.=?Q޼ǭ>Dxy]yA'{3_L!eم_|;/>>lGC5ϢӣGX|sve D4y׵XhEPeV>2[ΰ70=Ô~oa4Wn0Rt礸9 Lf] {t~ d@Q ;x =%0Z HU~9$MY'vI9ycBW5/hX6àB" {!L 2Ά`h#GeFgYcŹ"0 y?  q^;g|ҫJq-Ղ %ӤdƖpst4LB ,,08`X ,YX"8M\ h80аMJ`-(3u*c7 ![f垕j=Zp卅6AW VbXJmj)Icr׶b۷VnصAU|)geb5{ \e]/}m}9DI !cSQD.PJWģ;ϝ d`6M`ŰӘWUU5([. N./4{n1YugYثSkN{YM- ߌ۹N6BFW x!x}6BB(Dž4H#>#cj[4,C4+fNScW\nK\.!%75Մb.61ak-ml2E_~w>E!Sx-׃b-RiRN0c 8sp+w4tm,wˆ{4aiX H2rt%qlIf&p(FwB]ְȇ@k zנSPF3#F%h*C !*"rؤvo̊=a1!')h=oՅgZL|QirVqcW}}}ZYK-`[aR(a-fӉ43#2] tl_b~^cJf-BxR5cn%^73sOLj^<2LwIU>zG@6-tȫ $&t "Q~bzua:oQ+϶@" d \ ( ,M@ 02em7220rA\6V3= z[/ "p09@ߨlZrk3b4 DC5\`#%Z6`E'4UfX.L&g2Hy0z@Ša?{8l*+5bXa@XZ luifHU%&dȥ1pe&䪽d,K cL@#4y"jOC/JbAt^ h"`BF`ٓto%UiLp8&̑SrL`WthQH&$)M2V>LXǔO͂{0xΫ5l}}@VyN%J@(CjѮbĈ&p}m'SkUuo> y xq/[~r1"G~ŢHWZn맣A@+Ö}6/be2]@1d$7tpa7yp#gd/#r&%X,2 %ĶG@YXY1Ve3|m"ܾv1 M(1D6&`Xj1t   h PKgѹҘ\.0˹wBgE3:2Yzh\}`99gEآ`@XpnUz* 0gI53+jt3g4 `l<Q㛷4ZLiOUWP;P,}B"C׆cbjʮ _Jg\,T|Dwv0*>Q._ 9x֒' ?IDr&on1%C />_*AWR8ѹ%>S>cyoNf|ae@\33Sbߌ.e^)21hxq&"kGk[!ZXvm~Кqߟ-[ō^f\E}m܋ tCah!u hEmзXDxlf|^>I::ڈ~`r7,}kr0fg}6#6vb\Ȥ Bw2 z[U=^:{޽6jE2T  5 qҽWJX28O94aD+9 .4@͢YcL)"+~z)L_VDr[X\641R̝~!YgJ(r"qAS8H6H>Nj%5?N1dWqQ^Ohn#r;҄Wf1`{]osXyIwÈ4 e # /7'ŷ0;4npK8J9}^#uv*FK,Dò!oz2gۼlrكHҨ`c BSQ8aK7>Bk`'݀U"F905|Jgn6.C""6V- 4# W Ɛ!/;`5nPUȦR\NFU?J8rҋ>k Jũ47\>XycKF,㪀*v~K:.t{;T E"xJ+Fbst]!tiq{;._d48vBNo]ԉt.,h_\5,F|.9Ar'}.Z+H>h={g{\Of”9q*e}uw!7|+[XLw+n̔a/O3BV4WNᰡۀ$Gk!aN!h!$5dd! % Zs̀a(FdaN` ܳ 780HGƊ AS!œDv/I<bԼuPHvCPU!V"͉j@yꒌ1!D+w6j Ch јBzU`)i*8#kKFS!W! &tέmť`fVj'HLk6r}U. ed0ʀ}@æbeTEbM>u* a [K#DeWH2ee4ɝfdTw CUOvD!Ads_lD#E@NPFkVMTR,T)wLZ߬>g~Wz(WDNCD_hvjg At{2UBYB<}4R,-_.+6}.c}v+Oǐǀh1dMZ4.k<ږJ{!Wio+޾G'= k`I>ceF`1`z|iv~ُ؍#:q٧Kxc\ɰRuG!m;F}Ʀ/NU@>{h,ia \\5xfel>xIy+e/g6?]rB2PԒuԐ꩞%q#F^wW7!iB YсWL4XVX6ȫ;x4,bx0Ԩc.;1f]R`!QMRr4dB@z![3@$14BW16Wr#)%)2s ,1pDr\% *ҥX5v& &l2 XEk}g+ !ƊHVa40eHD09b(e9QҳKL_16"#9l1!-'i XNm'/iP ?]K~\l]9>P^ZnJ'PuaOoS ͉bzS FR.Mi~~:%(9nb.uEs`]VK6fw7ᨵ|M;IITcXw z[so2 JmrgEKݓ'qliF ALhPGv"rFvI]BÆ$C,fIs>z y}`Vޑg؈GRakjjԋEԔ@rAXN;1%TzfR fF^(bPMY-5HȽH+xǖ uvNsc۠XJ3\Ew@r7,~97~` &{JsoL\+z곗sۊ0dT2;|* Ğwk%+n :M vySG:hfJ7c˜Pݗ'Vةfl-4^"=5WW٫>i5{t]o \zĹHLޏE=-U}jl.qO*OJƟ ]{ۮ KT"0od:I-6;~c p`m/mq7= ĦYn~H{ cVot!6~.\5|zA6|wӄ& vm3HGߵ$~ohXF$mNxg;l=#q;Za3>}kW^ww\d$EpIYč/#oN26 ϯl_~c('<೰{0[]Ǚ@ Z1k 뽟 *$8͐Zh`}c mta#!c0fnfGvJ07PN`fŎDE0M1FI'e2*Gs=-h C, Srd92 1/S% <ͻru7zgUb`ijцq/L:a?t_o˜I \pwCh ]]oK\<{*8hox{,*N8,!`/1JjlJTAֻܽ)`+ZX\gVf{ݵj9$m'2ruu=Dxk!a~}pٹ[5!ш>uVaraٗ Yxԋn#=U#nހ@{!{)A.O%ˀeS{Z]C1̬9`rV0d0 EX⏥M@3dUFQH*S\ ̱it/dipYiݰKFr˻ RcPFP龶G 9:S+b-(shuM X"wT-h7O"g~/o21zrc ANPK2N$?lN|g+[r싙z;/ʛh*uۂ*JB eJSvR*pdѷIIPD+w_3Y9|u]]Q 0ZKݥQxUzT]]o,~uVe4böh2;I"l$e`kiHh#< :s7(1Pe26: XQV` !пmD]!h]\y6b ,ɳykЀ'W.4(˺8eP4v@*^9|qR#$lH/>s"`!Ҕ=wIȮE1іgd`ve9c\&W0eՉ |7RҚZf3l1m\NQ+T *2!”FCd!y )j%'8u )!T=2jůQ l` [_^KjBTTko=/auזbXBU}V P'"+mjBDc-u^T*J!34[owх)rXJ/J.;q^LKn̰mĚeP`)Tx0-:p}>AT֏%Y)-R̖1[ƕ.Meb "Z`U@!PRBUeJ@.Ƶҩ͏J9  1+7&tr&Wz$tDg8D{DXcH)WU~`K`26y(VackKh;1ir[ڵidsB'DhX!PWqkD\sya%J\0Fj*|ye1r) bI-zQŪ)z}+nuP5 lVY *46:j/!tEd:%vq~O7ʂN(PvFU z򭤯a?;)' oR Z886R5 JY jB@Haۤj x% ҔZFAf8"'Kib@1'E!Hِ*I}Jpd&Sy dJ 9Ȉ#cmBZ a<  UrR03R SW'p^aEd;> SHUqWhDTפaǺB 2˖)wZziԑWMݻFvn^]iXrW6 !8i"%x@,;%, QI535CML2Tw 8@a_?&&+ky@W lH}'ӪKsE1*g #kz N Ӭ)UF\+vw8N ^/kR) Uߒl:'fՀՓ`x垯U3TU<:CQR6ee2 WMmv!$d L-0m^GPJ&WKJjO,6th%OxB3ˮPX5(Y(]r2&tlta2^NblHY-ҩ6->MxCǪb9ws9lLQx b`4X|ȣH$}j*d` Q)c&dqeꫀK;0khn*;Pe(#^&H93*68K`T4kݚ&z'5F ê2R\^J;aѐ8}YR_:erUoZՄD^VuwTyh{ J *Z;%S];h:cyUADYComK9(@ Z0r`B**!K8+Fc5]ϲa_m1l[JDI ׌8/ 탛I/4\Nj` \0q{6cri2|o|7bmtc)3S}XvyWH*EJ " *:$ࠢ%IrB)1h^s='1LR cK:\{s:e1g{N')=/˱ ):Ŧwg_MpO-i5c s?X'muX^hP"M8Kh/}Aە !5/eQ!D5`Wk! :R d* }avtAaJEBP E(X?Pyb2l{-醇e!ED1YT,*ޗ^Da jOXfːpV}0,%SPN$BJ՚hʜ0(Rg aJ(!K`>!¹\z|g~^hd@nbƘZ_"s/ѭQ-{-2M-jkY6M|"bZ/z&  QS"Cid3'wO-)Y7ӥ=/N eIeU{(_c%J Fc3wؐedA߉NI-%J]vSd 1:adq EU@P% *@1D)SX&m$L6`&>C6 ʁ5 k}phW]qaUqeꡁb|¯.G̞jhKHX w^ Qj(מwVJ06yٷc /9<6l?wܼ+=z[hdc3ܡ RNK)Y<ȢYa 5oTS> aЭ/@bT/{ uuRa_RaVK*:| d5J$4g_~,L/D1k}sWXbXJhz_yqC6ï_ WG`&A@jyz J3*lzB N*U`T9cJ-%s `,#x˄7XtK};/޻grӡ޿5{޸?>[j.ΏӋyy79foKSC^Fl'KGLX/ĢLNIaceBQeѱ2UPj( t2NM 4,K5CؤkUӥ;xqQ .pz$MpZWR(x (yQC!ql\1l ~! UCjUyd5;}DZĖ4^Ƿ X9+m86/F/$:p/|{7Qc^c J@5g4R@g+IF(e<6SJ ˹Ͻdx2^- W?/*MNLӟz-fwm_hR+(f 5 RP>4!aJ & (=%CҋEx d~ QxURXP`a HBx"dزWϨmT|SXGd eQh`- g#$@2#;E6,*>hl.v2f [cШzjO%Rd)@AD 2sQ'xX,KteO{l|hᒻټC~+p趱 ?}SC&DVI STH +"3pp㌇kRL@*ɀ N 3H YBY-GpHT5sFg5[կg 6s-)e_Q'1*(C,1B\aJLȷUxxLjU7@@;OTEj8ծ,ǵSc}[Y#W(*;BCE5ЮVh1K`'Z{C-[ SK#ÿO|Mm(}Lۚ3jFZ42o~ӏ2o:vfl.۳w~DtT|'j (C.dLJ;,M8%?IhY %%FRFB (Re6XƨNJN JtR2yB9j.Q(jS=*D"5V@"b4Q`YZv 9ղ(^ DV6*L#h#5\:bCC`}EUaN+wP bnx *A;KɃOuOLO^z}['K7~vrfʫ+w_;[筗LNQ_DJp@*TX/3ΔZN f ֮Sk`h"dQoj˫ECz696/@֗)KH kW<4j)xVk(,Ƕr tǒLUQ 4{9\Ih)he-c||}?zݯu>lK^+؜̻_y3IJɉ]ݑ9CzFC[:4hG*,IywLy@by/D:Z3nZ`ht324 l_ eԌ%<#uhca-28Q,m([۰eV(}tpFbI4x |%^XtcOJD jzWZ|K(0#UVDW*p1ؐ1":e:T@mbEAh*BWJ^k{M':<9>r ww?+?#'o꓋[@?t;wt}Ws[Y\ a;̹hh~d*hв.y `Vֈ ߗ^Aơe@F .65Dk*_rCbl*/;WtmY{ȋ M_gVT4'Q6luOsruCO,8<S]W2(1L)-N-\R\_oG\q WO0(Öɱ׾|^v?Ęͽ׿薹+dYBQ:ד}0^XjP'0\ԓΗ(EQt{(( IUks 貽 WB4 Zh'(,W &8\Uv\UJJ`JTQI L!І0^'QC9'tiʈ1`c1 @4jW5 `+W۠\PHhR!J gtᯘ, 2@rJB O^ɁW_~{տ?7>tbw_.0,Ǫb \3K 5k]*pY,5qUm0+sp(UVB&aFeP}=ll\jTںp Am^ H϶W{6Ӛ|OZt-}~?KSOlL{tOtk/tcsy׼ld{Xk綉d(Y)e91$6բl'9-AqVzu z}Tf_^xQPlq zJ!/Z6uS2a@@\7'KܢR: Ѭ|2ʽi8DiuRf3C~υ3J+aW BR˲ĖY*g DN`[GN-Ru<[GB_ *ן3Ozﯿ}Ͻ ۲s WZ^ZSY8ҕNaѡ;}EzSʝb_%YqOLǖ;Fȝ̽eaǦ"tFҷߴ#?ΫoS7]1U>:L}/=;񢉡\q2d}Yp`U8=Bz~URCEe/Ï# +L)*5}j "}ڹ)1]ZWc}<On1hƍh|xZŇ5;dS[ *e$@+),CDb,82W+{^ K}=XZ*Rj}㍓w|{z͈{ߛ.6c#L}k-;`2s:17?v[7GO,% XX*{%AB3}=:uX(bK2P/@SQ岔J d 6$|$BYҋjj 2h'h1Ղ t RZL#I\}dG~':81 SXҠUd2URA_xB)N[?Mxym^!QA#SA(DU ĕ}Uд-@ FGTv'SϚٱNveQX\=WN_?~?qNK8{go[oضm9ӰN$0gᑄ]ewBf8a:kn8. 2$l8PJ/4V ᙁXKE+i܁#XAU@ilC[PY鹷L ׳t<e>^d\ui؁4:4/]Ak@֚ )3Բ;8ՠJ0AyNxr$7jzzǻo3S]W{G>yɟ?⯽y/7޲=ڹ]z챣vT>=5S)_bs,ѩe-mC Y= /j B703pЃU70D *VLD+=,;ףP 52A?Nȅ^4WFK+dzUv4LQԘ$$vQE!AK&]3e-՛KP㧡Z,UK^-71f7{ rlٝ|eL_6fJCs'RUKw雯h`#|uW3^Mʊ (XT\9rWI2T)!J|ɏX5L(_kbi8:D Re$`ggd7cQ:K*>׹bJQt,js2Cet1Jp1좠hc]vRzd498PAc_w+;qx37^u߁/bȓ'['>R&S3soy宏}&:4$|lťTTx!``mNS%lH)KWFw@Y%* ܨjscqU?X x$!cI,g/" 8pAUy䅔^aCpHE}Tך\ݼ9JQ(,6t# z<0U<dCB_}B  =!T bVG-p9Ȍ$,@艫=07$G]gҴ+Ez̸/?wrzZ:6[WRᶍM(7\q y|׾̂O-RgXfz DWT)+X4o "!ڏp*ES]߯A*0(bNFS_^~\k֪ Fqbkv≯4myJj}p8FjXƴTaȋ&kJE^F'" bbeFszގ۟tNwi+m|{`na 7]#O?>*NUKJG)MW\k~ShdΑmd?;4r~N˰L CX3R-0%Dib%*Ty `$1wK%m`-h B;3lHCH$P^P (ȹ,*A}&-3A@ILE'Ğ;"**D KFe$W=a25Nt tx5 l.ĆDT 0P[Xh+T\VJUJvJ+ցCEF{6sB3]JRO s]JUqE&>2}Eϔg^-ٰe{O_ٽ)ӋLs<6CPSI{쨪&C^(4~VE(ꞗ91*rȳC5hPj!M:xS}8ޮkxo=3 :ED *kO`N,L1PҎ v!Bhm̶tn+ܶe~|!zsl3'󋯽v_a}׾/?qWO.eG֌aNʲ/өnF:IYHtޡmѲ$%GS%@y9|}Aׅe4&[!$DB0 ׄYPzJL48(lRm%yAFgL 뵵PH,)  38t؇]EzRǔ TfRQ BC0"(0 =BK*,z F25LW]52hj{}mnz+:'ٗ9}ƯZ}3K'/l ӳZ߼~.o9\ݯG|L_g}[.t[N56]p{oAãګ\ڜ=P\9M b D! b Lʁ꧃pu':+!H(j j +(E 7،Õ"(obWjX/BU5p}?OU2,=--1{IЪ2dU85y~bܦ MYz@>2^#{\Or|Ȱv yr|_Ɨ~}S䮻jڃG'g6vLW_GL]{ݸic]tvcO,.- s cjI^ 7J/m0NKPUa0SX0D'Za Ee)W{k!FhYD9tRx DvDT>Lk}sȚ^  ^aLT@DP0a{6JT+ɝ 2`υ k 'l%: WWr[+ 2:-zz9~wF lj~'^+;-lk'Cy;co5FaG{OoG\cBz"JL °EVEjA& ծ'L (mĤBT R0^kv6_p/a+&'HϷ}C=>^l g{4sTc<'CUz!Z6T fb/e=րbLSFKlsͶ-]S݌9i[?Mw 8Pw^M&J0+JQS`4 K ak_4"0(0RȼAyD8Qc(Y 5j" a5xhL" $P[\VAs\ЌAؕ2x JbêǀxUԒ2RC5@vmQi ]Qz(k*"P$!II _Z>ɝauКeZbT#0>˜` W]M>Hs ?G n Ѳ;gtd׍ĝ^|t3?p䵗n|+3?_WoO.:zuO윣2 @qQN@Բ BăsL R!A:  ,XQW( P"7&pn5)8>tuՓC̴x = ~J(Y*>጑s aÎN}),P$/թ2QH% e(ej[oٖB4a!(9=wj1Ҽ?}ѷz]NMsZ8ԱOvbJo|z~励Sibg&7SsNtRBPB}ў #ʘZzAJA),BDzSY jb2G^sGcs}HLM2vJ @<8U6`ÆɋUM W](0_ rD">LBU"C I{@`p`d=^}dTcIJi\uQCUVw 3oŠ7^{}_~|wFwﻼN=\ZYY-y䝯Vk^_㦰PZ\VYRKAtߟZKx%J*gl'HZlNSʘZ:,Uf AcMuiRJIbc]ԖQ(+t6E{DSN (+Mu p h^ \7`TFwS<`٬Pp8?|o|e獈7sgW<6Г3yڋ6<:#s>e_JNCY0 ,|.!GҚEv N5H2=  ɛ!uaΎN!݋ bVQ45,o_62uh}񢡲hTIAZ0Ȱ`jc p֜Рc^ "cm]KC-LN^<1O<{?MWKnaSgm̻nxo7xU̽ss>ٻvԩ l^{4<1?~l[@0l:QrPW^JAT(hmɕO!XD;-}<\UH\$us1V[D5Rpj)  쎂g ¾<:"\/-IbN04}UTKn0c῍5'gфs]*-#U4^*vVx{$UA %Z?8Mcc7~#'>? co+F1b9{} Ny"Q,(($ډ&~{jV,ip|,j'(&XZT G+"3(䦈lHmA_k4RUf@&b& i^("Ay 8X, c x ~l(Exib{#@; *zS\AtçFUsi](cjRٮqkUc;ůإ'Ot/=_xsZ^J'E~z/RzU_mwN^+NsIV8Pp=]a\{ UB:PD{^or#t]M_Ч:Z'p%ZuT>^rus yai~"`; zT1%%ա9` DVHtK-= h;ǒI Bk;:C3ÿ׵ͼ=o3]c6otbj}coڟ-/ӧIKb%!5Is`.N_aH`ы *_u+2h G2Z23J^Ωt/t@#%L$ y)%$ ˡB ɌRƬzXFJ^yPUV:0GA)ȂAb;HS'>uLlcFK҇aQ(ec$ Bd?ZDSU^\*&`p\M3Hx`a׆t&Sle[x{_Llu";sb_?㯾fWӽ&G|$4 5<.hHx(U*IArv4R$ע }C2,6UYV8$Ʀӡ3LiU;ޤ+ƙҐ:Yc}(Ɗnh`X7 ]bՂԁ *5u(a6LP0IنXX"-KLhYk!W;5Le71vsw\?3?kyW}O|ßj[G?rdY8vpUNYS|W='"3IM'/Ș"&\Qj,XT9xYCFF{5{ɲ:lύ̬GwW<ΐ3ы-zR,"(ۄ%?/Àa6 dÀlY-@h")EKCQg؜W23޳>ƍꪙr:7"=g^k5B&4MSb@H"B}iʝTj 񄧚a5Do=^-?{oWO^;_'/=<?v/N֗|Ώr}Z$;K1F;F`Ӭ}͐}Bga"ب82dL g7b} w.\6wZ+u5;;ز&X*%)En72;[Riñ~*kpPhp) TEy\fF|(SP9fཇ  CŪv/sO>+/_s~_{_g~mqoxhsp#? ֯zg\@!0EZDNq-2ʆQ=lf'` Y.)-*` ة֊eNKU7N UDQ"#n:Dۖר@d#2?GG!]|&|@Iɔ'H)__;ȥ;;; s3=3G8.g3BJT2ۇMrO9O@s eN zL_{)%dstL˹c`g?)1Ucw{V1C~sVbc#jq:)8lD-L5N~W~柿p`o _y'>wz#`]w=,Q-$ UB"$+ 3 "si@2o*f:4I`4ŰG aLQ[ Mogp!,((`6UtQDA8F"4F%U|ld=\[3bK-3M GWK6U{LfDH yd9O:KHs;O[)6t΂NYK|5$Wxɮ5??7??3ekw+f%ѕw4sPqXs &F)6RS41;}tOֵ"y~> #BSC=~>5r5axwJ< ]wFpflbMO8hS=O,IUgB'C . ES?Bqg[7j)GK[ۯ]k.?g?vom{fy?/'}Q=4n)@',` ni0C0c$SA,(\*<,::nlڷ{;Á⠠j"0TdTGQ:.&!pىfr wY=Mx|>{"v QNS$3J'tπ4n(" 0D(uiYUYt-sY"qv8xLzPp?G?Wp/?/w?R{lZ<L+b[GNpjw[T&\ -?cp|@{:\\Ǝ=z82ks./2}z^!6N~Ļ,w~{+!ϟid,Ls<}*"WE;Ig˸?Yp!д>?`q?O:j!<k: O޾?:n,ey>ӧo~x,.{:y}[@K85ߌkڢ?ZǮ0UЕ6Z5nLE,TVUWlzTxuũa0U @l,ml{6I~JtT,LU t*:T\;N-a{իy QRi0ef9)P+c|XD6|YX66O"b"voA;6Y~K'?o?_{嫟}[زPaDoL_$vs'c1ּP/y~ꕌM'Pdk 6jqtq(=?%ŷ>Gp㿩K] nS-Ex8UQk5Mf3;"zJ "GzNVp#8O5 -< yb7Vp!O,xx_x3|jӟ/:3;{oGo>7W! \*#& A++]/ bD&j J֎12&;GRMXT1"(fI0oD;G MDqJᢐYbnz[ NRPkܐ 21 V ЙVtO:p8^SSᎢg,c˳?l)qrJ=*y׿IE^7N>;k}'g~ϭS/kw$*h}A7vpS-HB[mWK6u~S/ dl3Qe9Ys!|%MQ<|/dXWj>+oxiͭ;fi˱؛[ˑSEDMq)fsX&^;CUbS37VzP${DuM?감lNdY䃍aXu|7>nko?89s[k_}D>%_{'Y_O{, 8FxKn T .a 4{CȘr3n)Hk̂QEZ- 특,X관(;AQFdhѣBK5BM Z*U2.s2ؤ>hA}Ϗ#q[p -8lTt-|$.4aٮwB±po,~e]O<_;,YO+/O_?'xۮ=G_:/'oXA p`nN4[#鏿מo'>ۯc|tA:(̹"Z3xTϤ`OfHp8:v\FEEӗ\`>8h\>-@"( "b\pHN )ھ*R)! |AzD7'"Έ/ eiɣQ锫N9hl [ˮ˪~+7LE t {eaGxZ(hΤlRA\;|vxQ*]fJ)2;o#rs'j\;Ҟ|gf6OSbM4{Oe5 ^aƽ> g:T4*ʬ Zxɍ}{5|ŵ>Mg>Ԍ+SK}@:yr?oJR]S?_?8k0{wf!Y: 0THs4}ڢZjB[5w1BlfYݢZ%b$l*A]Wٴ":`,Pe3ϡ]iZXi>-6Ou*t h'tܤA֫%;#̓lY &İ@TTpcTݭ$>(m`05}>l<Oُn\[bfFu,J*ԶBU3n:,R}eyӭpax:^B$ۅ;GENhW&\և@]iN)t\Dbŷ4)`rsO ,pVqp,.>ո0~]ob7(ggL4)ܧZRe2v;eOբ3^;l̗H_Zt񙓰r=Rq}%CIN`%|ÃߺwǞ/Y?#LS|_.Q>\_u1ڽ[&n2cΝ`}Wj|kw2^$:sfQ-ߡcg[pXmIvMĘK(*{tH/z2o CA EY=2, ksVĂ)n,ﺛ/?7߾"HLⴏޗ. j:Zf;ɻաE! p3a < Q  s#ldUT%p aD!`!&G8!(;zzj8V}}Uq9ھiQUO벭PO@HJXx!H:\QhUP hmḓk.ΓXx D O؁}B,L8cMgpr}A ɳɕj?BN?-ֵN8Y.ח k'>u!ua|Jqx lK{c[l㉊KxG- `  PJa d ܆l }@h"feiV @DUt- SgL̝;%O•\($NixkW'e%DڎQ0v▍pఄ8G_<_cļQz7>ELgL4e dBN'1XŤs'Cm9v=jTV{Y7 /ՁO%;CM.c1禴OX{1͎[ʭtj\x/Vd&5S{`vޚ luV-o;"l1\P\FcVj-sۢpt`HWPysUNkԊv rO밨 #ⴏZ_q/>g)* ?ryAʍ=G?w6I_[- Pq5T7!JA Z:F0RDQE;+2Y[HjHDcT3YtX gi {[MPIi:*8& d"yn-{H+D[$M$ mRd5?WLS[΄妘QYAQ%u_];okwϑsBطєH=7Z65<\O :_ۦ_.| /hI<}poC+ L@=7j F륧P&lJA|vool3P(?tt·NL=|{OwVE}u] y:؃ur}U]["zC?BٝS;/3>A d-iFG]*ț C:6YXx*(4J&?R\ UGy AѤ`$]X(fN,8A1M~>Bk hZ"S`t ,Xu #;O#< ݂$Щd{#G}2CEl(*p.|SepU$M+<$ ;K^%rwVUcgD2XPhEɐmYںt@Ulj2M5U#rkp.i ;*} r!ӍC9 gNĆ8OOG`yto}&x]*kM]Z!ߑ^8/x }}cGѸs~O#r{/3̒="Spj6p?X{u_[N~ԡ Hz\\EP-D).{*,+R 'ðRRM">U!:E:pe :pbP[ΪqcD@:!.a5+ JBIzDj%MZp"fU~  i>3hN`iinXdupwYg dJ1DtYkY\")PHo{0RuJn"K3㍡lUz\´) w7FҪ;'EGW*yoOxcj=C=c/E0u4dV9os AZΜ;C4󾺬3/l5+^!8(?RaR\h]woP#x<^RRQ=Y6-ՠYC[圯ɔ.;]! uQP#QJO.ͥ KUzu-U9xzON>rWr\ky6"J` ՎO6g}qX aPئbuClAzkڞl,ܱE҆$X4`jNBPdՌ$Gr%EHUyD , V˒Z@DYvU*0Zp9Bb)c}36!6:Y uXVg'mݎ1_vU#.BRSrAb!T((тxyl#-eGVa(bK*ZR ^Q"mӶ$NF°!$p8؎"FlclTbcaALF4"A Q|e§}ww\W=?ތqyM!>OqUݻq[-|nXpDZ>v` 1Į 2Pem)$7#I4;EeTu` a,/~}6sc2U S(;a.d)p2_H'ٵE-٘ jiCk`Sdc/Yܭ[<2ZM#,:)n G,<G^ܯic)Mm{t S|Bg8Ps{DY.y O믾xSWwS{T@BI"$ RNGWظI)`?zh~ 50X+YDHfT;T9eVxj_w{=VAm^ F=_=xaq0߲!to+Iv'/oIf{ZMd[U*6V'zsAURog8Znt5bc7+XKp!Z3t]{OܺqGJJ.qsww+DG6f H݋ý&E t mtdG\TS.ܕ4wjMi{v^F܉"2txJod( QA ;dg}QNͼBG춄|?deCXa-wVF?iĉ /n*@hT-ꝟ] Z@]ˊV{ hrAaVUETfOfD z?ZtR{8g(9I66>z>߹':*b%i:W j'Gj]<.c@up@Hjj{.3qC|Gtq? Wj|&*^s$ a-F0bno#qMxKfYK1AR^bJf}2:.BN7nNqRU >^;">>s{I[J P=%^Eԓj]%ݔsVL%bIJ5#t5K~ED(#(IyI*,5UU1ob DL.0)JBҋ݅\G֯BuH^='A)`l,UĐ 1 )SV[F R1Ys6*pjʺG/i`4:P@P*RɊWy"tyE>UzDwGa{7<4|/շDx5=w__˫3u[ H;edwډz`7kn4kV I ͦ' RCxIJn/:!§P_;xwpǵ.E<Ʌ~mBV"ǃ?P rj"Z@_}Gzm kF] UYAe Pa"]CP%6Mi*-}6JKS0ǴfQC̀p`|Ss}EFc-حGϠ1z eUaR쮳aZүC!WDu5P(i1YM0^|mD VD?B*ΜB[:Cm92X@= !G CxL'O37߯5ND@[T ͥz{}8(Id$ 0oAf4Zia5yٲ'R6py[(9#㭟G&LAFa&[Gq߯cϷ6#.X)H!vIoj<ºO#ddvc."ܮԱ"}#Eej @``E{,! 7COXzf>v "N NG?oOmH'WkZJ'`ի<*"Mob0Y[sX0k f1Y&1k@}͢(UGAEüfy@Zdt .,:jCEBvkzB s6 NաIhੱS,y@2x,ۜ"$h:his߉zm׹fv_*;$yFV_}O~EMבŌ-22L5#r:Pq@/Ωo=!#Jo^}D]c0+P4X iYȧ Bķq&tYΎyjI!,v8 2+H!jDz6O38r߻l1rA2j||xi$*zm138NB ,M i"EW{xj6V-^Sh 2z8w?{M`a'Cqlc&pXt"D&BvCaC)Sc n*yFظ'G<ʒ*>'kTJycd 2X0m iXMz-3^6m,A [%˥YT+k'FfVI%KtϪU*{#|_P"eg kؑzǤZj 1L< =Du"ھjepE#(<Ũ V,Ȭ)tXgW[N= րFťs*)h)ԛ `aұ1cѓgu%UPܻ""&٥ w3̓-O.t# E,eKmh42rڏjjUYk uQ#M4yȭ 1䵫t/<8W ~Ŋ\403ڙT@ЩڬB9@ D׵19H- A'oAM"#h̙ŅʨFQ@ќTHD7 nUƎ)ZLRS:9ya'ųGg&Δ9jAU R: !<-*r9YC{:JQqhQep&YWUzu]r@' !8LpCU31ĢP9#&ڤ[3QI#EULW1AܗN5CT≼" dGUs RJA~2@f*6@ 9|Ӱe %,\^ okJ.A^m]5򅃝MnuS1$$Ψ p&3.D-^3\EU n2dէeOEoViQx30s&b IM#/P}œA-zLe$_0ᯩ5K"e"#l)jUFrU㠛WBI dQ86ȲM,,_1T`9[n^EedzZ^s)sϽ "RwmGsePKa21)K=# صڅ@AxQѯSs|%m+Ʋ׵hH HR5+<!F eiMP8*bUJ̸dLPDJBFb$ O ,kocUgN$zG6H G*ZP=ca ZǕ _, !sL3ex&f"I*(zmb#=ߤ4c}}jpA *z3L,U ^5`'ӧ{Ϝ۹;L2[T!g(EK֍t8ߗL0ѩE%vrθS #;[2&NѼod;U6l9JskjմU9&GK\K|WEC^ȥ.-GgWPWKV2\<:o婱k%1P߾jѓ[BɤU?2"8M]&څ@+Z f-5UDERcN)9 -_aXC{o&n:e4s9Dmͩ =Sq"jY%G~)m|z=OZϞ<oqZmhx01lN's w,Z)4i()i#FmfnA$#pb;! HR@#'Y{* 1"`OfΌw@}TG;8WZg'EDdU(Z\#3rrQcku|qi2U2@+tGaY[gO1Mi"WU_o^\{I8&wz۬$6B^6mZe8z5Q)X;E! ʖczEjhNwb)j(tG(ZD)`šjn-0`ʥaȻ]ULjqh^|l~^K%\s}EkeBG\E-äq ՠ*i^Eܣd:v8GSEW]Zl)Z4P=e 2R^< g;L7JG-=д pj!<1=1_t2R=Lj_\yb>QbD+ jS5_kVpErxeDQ;Gb).pTCZ(FJꇄ`Y"L9{r[lUTh8gs!31ƫ!ZC "ADEcPJ8b}bp2Z~)nz%q)ALl9"LnYE 8rQ(1!jPUŜW f8#&Fe@ cU[luVƚޅzB[O+Ar"R43e("*Byٸq}6ӛp#ܴ/Y'oy-bkp2Q_-u<5팪L/cFQ 0FeDU˃3rѲ 7œɵduk Op K}}>3BPT pveL@37V Of}#jlE2AALdUg{2I3R$41׎Ɍ'[n[! NsĴЏ3rnԓ^/P{o}H~?~ ۯJGɉ-.]f|!ѱ+ eA@? rUNEhH9Q'euJE'",.\Jx@1~)PIy@cgXf8Wnc=j&ZD 1ATpb 9V/S!"DQEQSc! ԈigW;3A`Äj^jb dCeMNYcC N; J GIt'U|銑?pW'O򒭛֎p-E`e!.-f.۷h܊RzA[lr*w92%ьG2GT܉\:t/H\TWrxp p KQϲe62!f+Pm1ZrO#pDֵQF-.hyvA)%RTT_oz]wUUT's2QFshq`H< v~辽O\wHtKSjx1J!J PqBzVEM)lKFZ1Ji[Xa4we^Ts(f!sgTbNoeg2yާN?dU㧻 AOJ̔; !B,CBIU*HPQ5*;-:>A#sm8mьFcnTȁ9|*L1/ WdK *`0[|D%ĈUeTtFf(M6c"9J"]XG QJD^^dJ60A!"=*$^:QِYYr:b9Hԩ P[_ݠ3hwE7z(|m_|ݏ%q`R ()B)){`QE=SuEя ZF¡ڟg{f -\5aΧ28^t2T/IJե9PuMrLgG(EaR-&q辈 e>|`TP=Q(M#RLB!E""X?1*:e녅t<^:y;ݟ5833s|>kZo8u{tm1D2H'R CB @QR hP"!Jcx&Op1GAfÝgr9Y2Drh$RI"U`-BQ ҘCq[Wr ML{̰x"g79_P" EZyn:Q!Wmib_nrߎ Ȇ[#tD2.4?YumYoY њ82Yt_'W?V=[䌕-U^N+69ץknǺ>8 Zx JAiE +'j%)L\/bI7+:9.NNT~~QtL9G.h p ùN&82@R;2AׯyiUqi;#~^)EԨ(;U]EWmU&e9ƨD;Jr*uGx xݶ5әn #ot̑CgǞ=yljƯ/>r-_|5щjγs2STU({rBT6qUFrk!3DŽ2"*<'.%Ȋ&=8-(J%@LBT=yfREb1X2sDFV)0fO+`eBJTTZT"9"f(85CcC i ,NALr:ScosV IU7@TTqL9i7]Oʏtw‰~+|SgO}Б_ɫMĨ}Qcse嚊Rĸ/,~`U?ljx Alo.VuX~7⥢ e^nZv uđp f '9U{c X춎FR;QKAGV>̉2S=uETRp/"LYTUDJ)Ny,s#WAt'E_y+{n0Wl|t?^w|#<5[qr}5[U?ݽ2nܴplq'<>;b@ "v+㙖 #ZIJBRR6Ș( PSjR 5():`? ap KwSy*/+EUU"H "*cYc ԧ^ >B-j0!F=K$( VDhybui5G>ougdqѣgE#Aw "#RdZ7M.Z("DwYKj3iZ$b8r*` hTEeV1ڶ)2HJzLBg+}e[gSG:f{99v6lWיc"8$e\uJB6%JB'Egf1疤bDYHsYV@;3_S5WEFΒD @D1*L1Ęf6@f4̳c-BQOM95Q& k"*2Ǥ(*R"Z dB54_S9L~:eڤxQ,(].l{θ|{ΫrhemgЩӽ{fƿ~ʨշtWݠAf,[=G3==[`mvhJKw󎆫娬zA*Z| ˞^؇Mae ({5\MK)ÈC{=7 zJ3u[2W-6aAo9>U-"ȲC-cA+7nצ:qW|G=sz]c5\9ԡ?Y|;n:{|.پn{O P1٢T@B_ 1$y"!/C))1TR D!B,riIZCZ-DM؀B*S&7t#!HTHs}@4foL̜b5jZDTYEAZFUSEX"z^oXtxh\#dTjdi @ˏ뜥z*32NJBC8OwK-Zyou;}w߻߶?-Elڛy;) sˑw͸@(\ 9&oggch旼ЋH(_=}k:+e '*~yۂ4$t4{2T jpVF#kaRx/OE j'h?*"h_DUGۮdNGyyhE6'K]^NpF-Jx_?&]gV=0=5?-z̾YnD@NA ʘ2@M 5 2#do \ # ];w*j#|d*b D)(Aj!"6(@%\,D=8c*g9g"hLc; 1=1;;UKpGAʓMi@ nn=spELZ7xιs(='\ǖlzk/:tb{iSDoqG9}y^ k'7{x6yۯWMGO$z*8s3j -%گU7eZn۲\hfuJVy>s>=0k^YZp?u2A~Dfj *RA_Rmlc퓏ֶvwQ*G"Rg`L"@ `3uRKVΓm~2J׎[(d%eƭ6Rv[=}lkw[ÿWϝ>g/ߵw?_趯7^БW\m٫v<{A+SB}1'A h['$Q*3"fDբD0ٌZL3AӓH8RBY7 b9bD250aV'O <]ֶ>y1W]t΍N>)1S)vK A M ZU]'ʈB$"~#ЋYP Q(QT  1J "FފEDI* ɀT RRQPQgV+5RKĠF(A5"HhuBzuX xs3SKɫ04Ϧ5DO]]WÔ P%+{",F宊B"q"ۺ6;p뷍NSMO\9ᒕǏNͪ}Ǐg9q7喿.{ye|ϼ捏g&wlV*ϔ ig|Gէ:,jUӘQ/+)ǯW5ddp KA/4(~KKЋ:쒞͝b!zF 5]%'v*@mRV6TbPezAU9N2;e?J/Gfo;y~ˎMu[|쾣*ؓ'ڪԟ:}Νwh4ګ&vnm99fET謹J)+11;k|[!QbjTrVdSxXYZS1-Y4DYz+EZrTW7ڤcl.ߜ>gN_rw>|m'.f|デʋ7W0w"|P{"ʎļ Wom}fy[7/GȘso!Vl m2G#jV X"Ra|s%J bjkX')zPuREESJ釂eF}Z# TԓQ9XԸ)mޭm;xc"nKAcrӹhӖf蜌iN&N_8;uhr;^wɚVu9̯vC}6gy}u'b v &Ĩe:ݘٔ`! *6v4 RQUҜr;( TDž1*1u 4Dd!RoVccNR%}rAeYz٭\5AUFyFpnO +,XX7ښx|b[m-UkĈ\wES>vtO?pKOmBq?MOL'W]\5ϟʺ=ș BUQ?c)=3QڽLT4'\4WP{w瞺c;[n37S?>Uk6{Ƙ {Osf-:ٰV\a"Rj/@QF!*JQy$L EL%cIB[N,jV&N4QB5e7 LLαRnD9"ABKXZJ@"uAp13[GU @f,0ܵ3p׊k L n3t>ҒkBwՁ;Ws׭>{᏿83>.ٹBg8p kW9mbbݵsK^O_Zph^wMc"*RJI}DeR@?j7h)) ao i1X $ךEËp ?+"7/fahYUX%b6]_Dw o,UUj͠ <ڌnF3mn7>cy6f?sO뾼E;6z0cc~Wy֥~q?lџ]VdCĚUX219!AEDAT8P抁7&DAi$9U+݌1ri(ZDt iүqm0;f T'Zolz*c@Q5J-cUJ|BOmng!Pl*D&EXD ذEܥbk5~PO3D{+wfڤW<=knk7Gg;q }Hz|&Cm[6<-[F/l=رO>Ϡ/{W2G dLd! 2&J9M5³U]j^ O8Ik^5<^#N Ry j**j]sK68jR4b62peAFgZ6kƲk{z?"n:oϩ͛|\f~c=''o>Iꮼhݟ{-W9|=m]7\6Vp=;3Ý`je6liۂiTQ*JJJ/z!6lڋ6_J ~ r@a#wUDըey 1 , GL^G䈘L#c4"'M $Cz69*ЛZh -29@@Yh29 < HxFO1}઼^yr䘌Xn<ۺΕJk'W|}v߱qOv7m^}W߼Ϳo^w]|Wgݷw~|evֿٖW̻|@/j' g(FvuTʹKlV),ʠ^,?/J5\5\_#Ҫblg0.L`t40P"E!|ب,/ 5 e4#ʘWēKVLaEuekЅRs|}{?Ӊݠ -aρ~-[yGo;w]~͛>뛷/?yףSSg w~a*]O:/Nw2dQP;(;qB?hTˮF?#_"c8S reU*8لBCR`K!" .˨YI_"]'c2L(Y41 T'{ۖx,2+4}!\G c|Ko̚K]6Eke4"d ۺi<ۼGG+&V9vbES-ڳL(Xw{ه)AXq4wC'?2K$eu2*+GhV7}CE^@=8&_&/*养eiz\ĄŐX` 劉k뫳^-\pgY.j6tنܪՑ.QOMʨ%?hQS{zݜ=3%cj9f}YT#2gMϾ}fbԱapcc7|K}36'YLJ:7^vM/۶uz zTojNU"wԼ;3)MLDI-D{Dp2G7j"$ ǀFMXYQ (b<'VTA$L.Nc6*398ظ"ɱc(BLp̠՝+ `RIhMa̾ O!G'\Fc8V6Pո2&p>Ћm}-oWl|x<1ܣ@X}͏;qOUIAby6f R?nY=H`D%&d^%NTh/Z9ⶭ )uuk2w=oڳOkW??{k^©N΁\;7եgNr:rd;:O jl!*qƖ[HVjy0،$U{[(JBY@QD1TaJIfױ•*B+7L䙭(Z F-QS K:3C+Mڜ{x UćjV.*4T(q]EB.56mպȘU7ZCg>su3?/.۱?>}qG9}xUtɷun?*I5x(H:F3tm; ` /$H:Zi["z n\el.b2 azMi˙g8ڰ"y;"w}ukhfI̎함PeUm?#?xEYS\im͖/?6k N_]gOx C=!ЅA!JVzG̦Č圡( r#X_̊DU(ٱP9F*^fZ4i L朁Dn4jeѫII0(UFTJ1 e^hQJ+iVz!<`apIw{Ь2 MeOC5=qy]^kVsڕѨ~.||Wȸ-y՛ƻ굲΍_xZG[ E))3drlь әsj5U :մrjg fdL'`ʱ;e'6)5nE(Mxf:QP"BnoX{kn25Q?%kuZs];SO׭՗l=>JALΜ,4/F"d]%XQ~|Q9XO/܉P5')2FTAB%dQ͝!˜㔜0DDu RwШcԈ\VIY7 Ax]rĎn Dfjz.U*QUP}IU؆P6>uNUylS4 uoR@U82&2ܸUD[wlٓgţ979Qq'3lhm-OMdŧ߀P7k{>T2y7y K4ry p ?YZq5YҺ5`c cX"-A"բgD[ 60@e9A)) spx<Dc6Nm~~e_t:y"sZ{N,95l%ve!~Q>w]Vy>p]EbrJXQꠘ^;z9&HRBw,`thq I}:AʠeDD˨E)A2jHæyASsy(0%ګUn!RMNfMcff Ƥ0"ʈg%t "TZqҘaO#71 `(YD0b3MURQ[bDd S8dWGuݣt"m7mkWoR!OЋ+[ fn<͕R,-DsU eZFZjhX/b@6\SP ޻Jak}{Suo===/RHeR2%2cGW^F1`C@'08'@^b  X)[)Q$Mߜgꜽ>N{zE5u:[Z:?{ě-)+aO 9+,W,O2pkwG EaS5:\\wHE77uffD*p1 W܏'~~}? o[(}dQv$!Q-oXӤUJUx=icFTU1XꚌ$IM9HHC9q;:4D)LDסkb,-tc[4]S|佪 C}ha7V=Y<t~nL;:^e5CcԪ]y\NOz8MQ{gNmyO_/}?W9c?_~x{3_r⚃ɞ}fR ͜Hg. +"QGfڬbu*O8x1X!OH$ :$05oU08ƂKGil`],M4$RDq UmOrlǮ![03d|ĔPR^\{k1rhnvrre£U[Ŝ-i"7.);{cOܽ~M??S _y7mcE/Kqv^޼Ms,[ӚU}KW*3GXΫ806+pQpe:ԡK~ y%äpD\ E%C>]3M h:N-H0ءu+%!M79Bx]3g_nz{&H-'W>@ aBDU$9wsU)rBaS:bl4r_|v6/}mϬ_|/=<OW?<{^^Mu&|`&@zs CGdC0ss#&^dm(D&48 !el\Ce/0 %BN(()^=KCMްH1 Lfurz401O+YHJm3-lqN_'-W|k3~NEco]M{qn+ō^|O*?OcU^9}%8P+?(Τ 3Ld6;Q1_Tn$9%5VJ\\W$Ǻ5EWQ=͞ +/P:ԡ~mH_&cvIhˮ+N,U܅Y f9bӼ3`DNHz|a,5EۨV$⢸%:%ื'{O?֋#o}wbmz/UMEnA>T]2j[$JjXgkϘﳱ2Zbl},uf7uꫵxd^"uւj 4WnXԬ4g j8Wc;ho9f5B )SD ̹C"Yz/?{||⻿_8܇5pbTףOP̀H#ƪdY?@RX?y1%FW`҈\&φmxd ?߹pX07J>AÍ:ԡuowxc 6-@f[۱4%v5Jg)Jpe~qÏy"Պl<@*I7zcS6UO&:X0tFo :he|l45I;Cu2n6Z /]ո+_SOMU&DLж\$cwb5@!qv {m02%À6:2ɬG]'qwEܺgv*O'p5ԖŰ.\OAHdZ;B:`C< vVnK/|@Ͳk# ];@I_(0'^|JĽ)3K^|>uIg$@BqJ:۝>26Tdooxq[CɸVGWD\VgIK b`}<+=c=}c<ԡu_zχ{H M0gv#] J !Z&p/OKZwQJPX__VɌ&Pi'"˹:mQ. 8p9ZY`[Gkq]4eEue0%18R elVVC?/OÊ%9|EGNݚ̺84;D4ɔ+CZ/4vduĤa>#l?ȈB@)"aQ^[aRx5۟V JH4&70gOM>s|Rqt'Goy|[gORȆlN#mm.[+^[?m( 5]ݐLMqښpOvwL5-vx~;ARb:ԡON?xpLnXFvvne, 9A"3q{^dUɥۛzJ͉)%l1|J*際R/lƲO?/:PF;'οCO=:N<n].7FIZQ%Z)VX\vt CI*GgH@BS ^~U>ʧ>઩5kUb 8T4ONhMaG-J;X! ) Ff8fPE)X۾ʁx y2_|t:trNO@#JLM;K=vVX*Զ.2YD^˪[Zs{+oBbՉkZ;SҶbmтa"B;Bgſhw,{m=C(CP&[g%P3pG ]2IjKv "w+JXOdц@NQ0C/9$r[3$C)P J>Knn:ԜrRrQ.C5ıhXwPסuo[W`p"n튵btpA3Oɽ%$E4Jom2g3*|;3ܯ{믟/Ѧ<6›+9 nL_~RV$QU7JL;m+ ͔]5f͋!:})ä 811s4DMlA"U(HD.Jw-ϧ5:)BDͅ Ӭ8)5qIZ uh%#!G2@qqRY%wz%Si߸ULBg%Vg/_UujT(3xK9Ju?y}s>svBh@?>+t=Fa3moߩLF4r:(nrR (dc&FPQjdapONVa#5nz 4" _4즤0UxuD"c]EK,$e!ʤz)>aO k99jy~q*y?šxV[wkϾ!`p6gxI1p]mPmrag4ʈw57ޒzS5_BU7Ww|(<ԡ=p_\MV5m;li{uIaIߗS䱲'$/D):$KTe0m 8!JGU>~ǯ'Ӹ^) y89 P:+BkB9DWP2ƯflE]m҅"#Iˆ]¨mmE®_Da#9zg=љ9+캉M)ٜH8wl 4vfWvD#%jD+B6kf99~"0h{-ݹR-Bgwi v;yfx-2DGHdF\q1hpLȵ+Jlf;Fjf\HZ JPt%c~^%q R_cP:Է%q@M`asF-!g2C2߉Zޝ}پ怵{hOY5@¦[YL2'VpY8T,gi Inɱ#P4\*G9mǤ89PuK"0JӖ-L.?6kWƾ)w%CkS?]~fO$6#ݓ5e3*d]rBdXw%c,Us=7USX78\cH{{P:7u6r;7=m؏;DH^d #=giq#\ '2'0¶la* u[@a-A3&xuL%5@S2 4۔:V(&ST F5TBPڰKUXP|>{' 0j/8il]BG÷@qA$PTdapwp!HAF9! j#||K&ώh=߄ { aItnaI x>ZUWӿZqM-˜ _y|+Қ[lSqtzM J}q6I0Jmz|.AW*OVMq-3< V0G5 tK[OufWC@b*yiȥR6-v10D0:%:s'6V۫4&Pݍ,+z7>(cO*4:np06ad2gZ%d.TJQ-U]cYBYePe1VGH#Rn #QŔ"9"J9%+1Wnr2b8"njhF&!lvRf7Uɗ(~`m`aFZ3 i@C6K\M\9 4Fh?{Ȁ"3R@SYt| std93^bXbIbPS꓍UCfT`$ bԂaְ &c߀GZNuD 7VÈj;Gk+>~CۓU-w?U -A%~%gUn (WX|{Bҋ1'C3 ӓ>{7zK[JahV(i)[БFa[ĆWM֩ɳ l"-=:\jtbOd"'$2| v2#3LXcS]i 0B>ݖiPHhQ?uͰ)>/TY <Ў In r]gU`"Pt>޽s38GxMUucrcUbw0oo$}I]eUnB]Kcf0ٞQM|^̾WռyI7CPFpuՕGYN9K+~4*Fsq'Hq(]gC=%+mQ2i&P֙ks/~ڙ$K qY|, $כyݓ5r.y)pc0a%N\u¶(gPk#3-H(G^ !8!)֦;98%Tx%2kUq.Đ2 R RsE˔X-\2El6 8gfShf03pgke6PO&f6Ktc^!'W20ǴW}Koe6k= %nb`o3ם^ OVvJч*֯_QKLJ+ml\/*ޗ`OyCuC};ǏmiZzkuů>Xd.3 )X`hR̕` N磟d{VxmA'}3p1ʁaܗ8}(%&:GxXā1e"᎞X(`HD TJSV :d""m8VTHYqLY=)Om2!'flqvWf&9Ma@X4p:jh5>lkѐʝ,%2'qXpͬHKE?pt(`WaUz!`))'Yvn#WQ{l%BHl2mEpZD] JP6M {hDM؄k-y2 wk'q106\09yj}l`hW̒=m@$vWX. q֕i@ T˿5|~m*!98t3T>ΊoG t|磇4~X}w-F(i)Z}njk4d^r%0^K'o|6uo:t11u&cME`T2ZL==$ c7 1m1 ]rcJ pq?g39>gOP#Ew,pXIϡdJV]έd/'epU0518*0kYGǥ BVd2 -iJas#'tII@ՠMxR,8:|Gu4 Ɠ@ 38C9~ήy/cKb$F0ąj^_ cϟfma523C9ZOՀ픝m2#vL47nKVfUMŦT ] >}K3YufUuyH Ez'ʅ}Q-[|}-7O+P7Ro믍i7y־Sbf#ş\sfBZt5U U*NշmbИ6]XZ:ic~Ὣq L(wWTGכwWX3p635Pv 9P0 G` SZRS.LɰF10[dL :u䄜YU~5WF)*)]Ɯqxfb@*;9~X:Ej`,k8nZ7_9\w_vaLl7^:<*26O+cd Xw@$q|7O-Ԉ6z)x)`bxPj*jtL"Dp%C/}%<뺮CKWuqWG%QZzKP:7:#0߄ӝC5;]>4z2ډ,?7e,IfUN{Km )Rqg3| g;cQ)"Uvhw{|h%flO0V5$%Cz"x*8V!L9ݨQ0@?`8+!5&kpGpGjE*dKfi߉m- 7yP{}nқm #H-mҧޘ79SJ۟bkѻ z5OĩLVCu~= ֿu*1*rZ% X9czOI/F=[? Itf;ݰ栛Z%bSh P&ؠ +CŸ8&h?'ć:7pt{yq HǍ>ȫ݇%ƚD?K)m 1E?,n+:hS8[f}PU\_I9[%=Gu6 _;dk/{sR\Ru/DJơhSeuu p6"[SYp^ 57 o/)a[ 7iπ. XfP@fƱHEQPeD!gVŕpHZWDmt@$e!шmΓ(EDbisut"ͅj %Epbmʯr˦/ %z/00V8Q\3dGv[>)gۺv775.RFhv]>P->KT'Mg`];?[aeV"n?q?ɗf׊E#48 ujt@:ё7E].;v o]J@&h֢QMU4P8wg+s3/e7 l}櫫FCPߴKUߦA>dS/`6[Ԛ&wAqiK]4^iyz{6Na)Iݻ.S ֝-x* 7.:ѥa-#Ͼt']#N&k$U+ Db#4kb[}+_. 6~r:)OH&=I͌ Dl+FkبD05K)qj;Ike}(Ky}V|x6D9Mˌ;{]>}|q8qZR`xK?3XajAE MF FͳEFZq3dnT)Y&ZP$,k-yI%cK0 Zɚ's,F#1xuC}sTg?>j0HC1.+tY&o4{IVHa @>D(bC 'p.a0Sq[Ez0xN\?uǧ?ۗԇe' L$91 q`K9#Ħ E@ͻD'!Åc o.Dkuv  a[M׊Aʠ0DlI]^&yjyAɈaqE9} ӂS,sm?vKsNx&de/3gBWx3Jލ~ {N4r4rBݩ#_ڛ"hRfA6a$sjq=pd aw|cVF*{&6e7B$kufFߛCܧ_}1c3in$:ԡÏo*:ZFWYJ<Ɩ6C6Υiߐ@Ky*`Xe.ƶ*mGUVc.2_}n'Ér[u)D;KӞ3;-\7p@j]0%'5O8E9HvXI4J!!Hotdc .U 27+x \$B obfrfw _'#L%F*P8ٶG/>v>N'0ϖݳQ{od$VKoJJ/?GfOv^waLg3zxHEX9(fJ~QCM.Xvj G5c .Tn^ #3.q/s ʉĞ_tuC[l2eW]4p&аdZ -,(3Bŝy2p9dyVzAA*Q2Pb;}z$-R:g[;\lOYzUǣ{)Ϫ$AN(9Ot7WE]\L9]` cFaQ,22[Z+er) AkpdԖ Soa r}tAa}5kڈH* {"6xn7b{eWJ;^. IQ@7ӣ~?+˖L|ǪѷU:;>uٸNUǙmr]c67Q5!quulr+,XWK* Eb͖LÐ?\]\1z uC}VrR\zͿ[C^b(vE:-{\Ҕ~9HtMsKkfwr/nCHi*@G퀎 Kk8:tSo~ Mz\:+6 HX%c6HSb\ u/2rl>Y)j!.)`>љ$a`mֳˮ1LH]Q<7#'VvMZ+$'5F{wqZ Qt Բ!eLROJk}S__S1Nʐ?|W-p/Q1'-RX%oQUb lJ`LTu Erh۫ʔ3;cvzè+WY㪿E*CPTmw1ECbeKk@ Efl3Ĝ$ou-z6H'sN G{]wP>lmXiV?[zPkק[=p;2'}r`> !fPl+rbSEֆ.RqZ &O2;^.$c&]_sn֌ b^MՅ\u oo-Q*RámC9R4:>!-6r5+Ȏݩ0"]fҕDE2625xOwܶ ܹ}_~|?1?/{G!}??|sotqg={3Q]lJa'x;lmNdJ>hr8-?ْ`dds"3yf 8%[G@uxćC{uCW~ev ?]VܙO.>Hh8Z4[p=l̯ȩcmP`,~>x3zlu^?ioGO<`s#yg|ɳ:lC }(an-!p >TGͶ(5biI4":C#m2[D4_%*ooQD2rGqweU.DQ󑟜l"k(w?M]99"GkٲKf}j&jStܠ0ǝtZsqdjX2A#>Io}x|O3~KGKx?W<}Yģ*Tw/=~xSDvθʼ{`.Y @uUc-qYːtBxf'WR5TJt~>Sw}w_heo]x۪plIPdPI荝!5lq7,1 8$PBljG]` /ТuĕCaFԢmXP09eqlg֪N{'fu.^24f|{Cf0^* /MΫ]{J+bGk I(¬L[.Vç?|?x~gQ\֗:j[5:FtlKZeJ:blH]yCl.UrT4O =֜ P8ChILHkIQuo!W>W &'eFax:Vn-{neN< >-R"2A&bJ6NtuպUvV^k?r7_//ϋ?¿T_ē2H08\bJ)y(E"bO%:8#\x u(\pJ ` pj;邠ĄIUX$OF"ܫڤ2-{4NyMyI]3ʙ3e\ˣ5.b9ixPCl`1ƫ+p; M0lhsNzyrb,?~ 'wK/|k7oЦ(f#p2.ߌ> Cm.νO79$c feѨO#QhmїLp\ԌF^ݣ<:ԯ 87I݈xxr۵X^% Qג"v A$NʳwA |m*.F=q>O^|ܧ?O>uo˗g^>ŷx+,42h$/ghԯҨ ;.u 7z>X Y{|׳{d>E???0x{R/_տrqfW"oVn}"gWWNM v&0ʰN쒵XgM$ɪ3=Ƚr@P (6!@@BhH9Lo=5}zLh3:#5#hM HЀ( jˤ**{{#"3j%Oanf{ɨ=a'jzčAuM&^}:^:HqѪq%7n9o[9hJE)"`MFdqLl TWupu#Qi54&JQNgƑ(5q u]h]jT*np 3{z=D6tm2meeesi8Wmy<42Mfk O엇?~OwSSc^=ϲБdC2JI),}Fצ^p|ɚ+lA &1(.5c!*'R]8VbPIr"P}y V f@ՌSZi) DQ dX*{ Puz.(9*uABZјBaEr৯bϽ Sw|_={g|,"JE7ZML)Zho;/:,5ZawE>FELqLj X+{MK/Jn^jTu"R/EPEF[]9(n X Y!jb~BT" e0nM+sh*U෾ub埾r6'S'{{oѷN8.n~q{{p, i41Cf,}kYVo  2F!Qհ( (C7DjMKB(E / J)0<.ꠥkPU` V"P#r tý'6+`Ͱ| pFHrh> J֣2A[N_KNTdtY-OL9{~mg~`MC={vl{uo8tϡS/iMm?2ⵐL۽@uZ9xUNHNTML0u:\zãu=#ƅp\תFS!.<&J k¤H"CQ^x 쎇hu'Q"P623Z ^xnb{S_ے4=ѹ _~`} [¾흣ϻrjgܿ{vqޟq3ݒ -KE8,WI؄D!kc-ș`l`BF̮4Ieȉ8М)#b"˔1&ĨD8YE焾aJU  ;)5BKC |t٢RjZy IyR"ϲA{JE* u%64V,HfJ ]ç -޻V;yjrKߞ c/}mS dm{ v}E:ve'+nӞRP zNKжcBn0sf)Hf3WL rx135G1QjTGEOkeR" 1^DL}n`UE6ix4[K56X=2I'UѶUmK^¢Yt]]K?-诼1W_~s;N/[zwQ1@1&LYj0jc'_Vjo,ۏ6HPX1514J T0!K?JZ"ItT:!Uy 쥫#[ֺ M8KmŽqovkkVziߝ ~/Kz?}ffҹw~䷶W_xϟ}ss <~aa3w~+k3/{ĕ[+>>|hk=XΫMq,@W/`WRnp2opCsn:kǡi̚Hvmٰ-oDrjT>/-xSPU׃2C@|Y-r _41+X_t] 5-{%5k+vLTuu?vy뱕#ܜ?lʎ W~rC:y t|fʓK*WD &cL<,y`V&RP/TP>iZC_4!2H (i鉄 z2jkRU)*T@Z;nJ6do*p;Ҡ^~GCgP4:jhkxȜ#cb\ջ̹Yu_s+4"1D +~-ox;w>ʉ'+;}+g㻍N{,S?fOW%eKTz]tړr]NurJ QZ5hZC|Vo]6QȳVbܰŀlݥε٩E ƶZMF# %aJȁ_9'sn9[_79_=gOlle<`櫶|s}{6Nvn 6nNYvֆg͉:\)hbdMP(RG, zW ZBi# T09( A%DpnоD+HP7x _pejuKш HԚ2V_jSNEQfL^Vs\}s3A5 `縝ScǗL|O/_+|LyWӓw_C^pB¡%'y۾OwLپf1ile⤟Rk E$yɥ@r(aޤ H j ~XS׃\f3BWըm5<{]JԘ+(11öTA|9 Qeؿ/۽su+9sg?ϟ]y'9C{+?}5?~햽5?z;ǖڃ 7ak`LDC^34w׍]4h() e`,+{$J(?>2[Qwz/Y!>1s{gzBXqw~ɕW>or->|w~} ?o-L=ph[v?|s綱ީVP/y'O}"8V~&T a!06\"k b (ixn 0N1aK\EjT>KrHMa/F^(ix|S}DDd|jh] eXh}LL r[&K>aL=qaeev-;͛-;w_zڔɟ~'ΣӖ7-[݇|b1sy˦s]sWwN/g%'9D(PAc Cn 1L2(cd _"U)(K0a=%$Uʘr F!!c aʘ>M+T0E֐ܬbH֨@W>A6GL@׀ ZB)%4Iۤ:`ETVdZ'aK38-8nE"a6Q5CwU0Q잰.liY?;߾tCG^+>#G=׏,?WEН_c?svbzĭۿY?y"rB~&IG{Ra$y2LfPYW]T?^gSQT}|Уp&|ClCUnU}nLDW#lt([k3n[.[WvyIqjkJ5K>u߾βxssc'<45m~=~W^;߿Ws&6{+?fzZtD"(5pal2;DzMwx޼}^֘є;6Yicն%tԺ!!#i6~9\~Y*:*2 F˔RRDjM-Tvo_}`SWU>GBQYꙇF5Q"7]%x8K7ȍ6jwjq Ic2QC"i8D+w"Cd̅d5tIHSmx,#?=~j7\փw諟>1;],g^vqkwrö~us_zx-GN/_~Wݲ8 /Ϲy r(Uȋ IKg qԃ.9E-aC|#TfC1bGyxe A¥I+&Iq֞\2;w[v1d"&PJ, KsQ$1F_TWhpdI* U/몞`Xt4}hH ug{ln{&o^}.e26&Ze۠u2BDPž: ;tiacx 57RmRPiMk>};վ? Q{AW@EV=X7#t ISR'ZYkTDPT -K-CLbLcI-2d@:]cE^e[v񼝞>~DoLϙnʼ|O_U5iNjCDS cWaB+C_{EsKK}W/}߾]ySC,v~fwMۊ{ ^/~'/,C mKMC̀a+YXdÔ%2\AFI#Eڈb|⩱GTqZuܾGtTngL eΝehR(#hI6~T ƒr:/d:,e MBڇAD\.i|{A+cXKi)6>1玜/N;ce}?7sm-)˧+ܱK ?vզvzgE/ ;*Y@a, += +YE S=R%yRǠe匜` D#ˆߘNƆɫ:A4wxQK4a(C|?cMpD /TȘlΌ 'N|(cΘ3z9=΢kY`n.%DhMJի׫|TEl'&_ZjkඡaȟƤevSlr3N\9[h/;G2n;5O٫ß?t/~-i_>y U4u2$1e=i%BܲL۴>A H&ZwE Gը kJ཈i b@) H> 4yD%ؠV P#D!"qJk gHQxe2D:fUX8ybDnuŊ|䅥w}^K/>U-WGN˘3Oݻ+vY˳Vt+Ja T85p Ss  JͬRPjt<y 4d}Q xAQ KV}@ }Iq<{$4(qW4[3*kyQ0 Y-T8))zGA΃š fa_Zj몓{ݻBۦ|9_Hk22־ݸ'n?zzĢۻO--wq_<֩3C^B(:`g&= *KR*' n^kIiqz2/nըFúфzY]%wMX5W3X\(V'(UMCKDΛڶ^obԱlvLfr.mDZ\ᾓ|_fuGN==~[>7|x@}myp27ww?S }*;|cy'dMO]rT#1DCM&"y;)Դ9M<FyZtE-Y-j'eR*k֠GP 3IBȪŗ*+m<}5U4hĠ.YC`P| kW3))t,ߘs?U)d9[*:>?G5P@U9Ut"BQBa F r&ׇ̜0cOP[հj˲^0()U0KQ :{&;- nMu6tyQjTzv)*)DYyu ֶW-L׫eq+^\ZM$mk2CRN,5Lm32mm ^u'ɜ?׏_㊻a~ugN?aUc=塉̼%G}oWWP5`-Hs %{_Bkp\4:Afɪ. JEFPB)AC.pNMu$ -0mitTL&eF)SK02ȠV*#%M2jөFr`>Wqs2f(㢚$i: 4giU3 !ho A0I@iaVeH*P'Joʬ1&莛7?zczDx͏{gq33 k ([1ەR  `r[^5j񪥨zTSA﵎aU0Keg ]=Hԑ?ӨF5q=UVϞiL % "|2KPˠema-=\6Eut3?6Ww +J/<mKf}twܴCzna|WW4uZld\9W't=N P ƒ! *:b6NT{Mf2IΑNPz-P)5X"c,SGc"rFF# (zPv, ,j@ad֪P74BI.΄]Dj{dI# ^ HL"jOkR+.Ku<ٴ{'BF9 )3Řl_;cr'} ]V[o'HTӒU&8b& ~%N\4-zU$sA)6gUjJe\L5Yv^jq@G5Q {!bZTu\DHED G?m(DkhSdXD1w23`lOϯn)9(N诿%Opu}gOͼg_|/XOtx'gWqVs`}: )09CS60kic*Vd  `Е2+>vȉ 3M\0eNQPP{iTJNK'ږLDԫRtCTAnLmVlc_jh aV(FAϨ$`@C%TD!7ZH_sZIU%4lu`5>;b[[{kO-/>sOߺ_ݼ+}^& Q-DJ-ɜ-QD) ,ZGj^wʯX.5 E uPTGG5Q}(qSpЗխd7\ѽ=<̋zU'|"!t0ͯ?V\I6Od{2|:̱Yt!,cHN]֯<>Oq"7ܸ%X-/7rcK+O:j-,,_xͭaý;3Q8q-K팭UA=2+o^bCc/(ӾJ)̰2`7-5:T&0 #1'm!L2r"[gDv*X8`t%^T &w$"0L L(psR@X4WFMx푄)SLʟtׄjGC{~3GN/ l;α ޻i'9[o:'bz#1` 29r3qF\D+NFNi7F s -ӀF$M0ѥU4aը]CLxTx(oTeL̐ Y*T NvWS!F׾ <1y@RxUUeYibX(س?+];).?tz_ɣGO\8WϖO_\"&yr8P ^)tg^㚚" b)%0> s25d,[6| ǭeき3J `A`bb SLJgf A!`5J;bԲfH9:(|oȡx Hi2$x_r ?S}`X`Ϥݷ'=OO?339v9>_Y9/~y?e|dˏߴ} }pTBbpiRnת@j(: Z 0VqSG6>EԾp4OjTzKK6 |X#AZ$^`چʉsTLc =\(Z 1R(q0Jn6͜]}ow+wwNZZZY.zٍ9;w ,͚1:v80J xL IUte˜%Z5șMwRCE'e"% BT2LJ8EPqdȘN@Dx >oSnd4w3 P)JT,#6 Mq5jdI5nese7Ԅk]١Sityx?TA UH̄_&!2; DD L!LUasbj<ꑖX XuixzO =%QjTzFkc7Gjngxxe!l0gѥh޸?0 JՐ*팗 acɉ)74nN5gjY@E1<斁*AYj3:6k*`vO_;yKqk 3AE#h!j@Ȳ!gU]| /_ V`= GTRXP NVc/h)`#T:@!%@C*7&E3O>‡kJ=hr/ūcfB뀞iF*)$jy{5~!fgoj[%UBC^BRz^WJv{󭗵rٻ}ey^; epCh28 k2ŷ&J_Cq $#kTճXjI{F zZ%}e0;ѐȬ`հЦEgH =55yh +T%MiՒ)I@40bH^Ny%-M͕Z=dꮔɕ-ͷO=1=ml-t̮AQg ;e'H63Z@'7% lH &Z8{N.xTa7go%3լGeC k >]Cf? > >~ՏTŀ={LÃ"t'4toT2,ARGf0SFXz0|w2uBup^!j"f"(y7>=z-Yʜ T཈&3wQcCJ+WWVldY}0J( tR*eXrd ԋ$EJ# `F hҳe)rCNW+`[ZV:m5/xhr@TǥʏUw[l"AJsbz!I0, )<Q%hZ:8DU4iD@_rNM+j0e&K Cm!N` y^/) 9:gK"2tdWMf⪘ *U>PhϤӤ4Pjߜk6*Ea hNۤ"UQ^T-mi(ԍM]H2FuG:j^99sqv CaF'TpިF)ԳC^&* ȕy g4tEș@)R_PTi"cNBW{BPhe&ːqpR36 .Rj,["Ctp^J $xm8u" AFVz@L>3 J@FܱX. :tz"VIY QX9b@-J,qaX(꠬*> DPD0Qf9%(K) mX$hCčfU/yl&5w5CפUf\CBɲeQcߙ5`F?W4Zh#4 3j-~QjT;ٍ<ϯm>c ݲw9Ȃ:L6VPuj)dc^Jt˸. UK19ձl-c X6=4ڲ*\kvjT*I%Udɖe˸6ؘ4~8AyK_ƣ#!$<0&{BH,YT*uշ9{5{޺J0gZ=>{o~U\p ^;^scyE}{2gJD (0d(%«{Q4"R (aDC&1}ì@`(wMm6SATŦ rDR&M)QE ]6G׹&c [ .@?̅Te 3r/S@*=J\Ayu&;:PlYetNϪG*m6zg g5l4WƝw`h|}x1%&4,AS0_Z;"5 Z*c~MBd{zAÒ,ʹLSb͈D+;t0lm%D,14d;7|9D 0U6:ɅA04 "/ 38x3XiiC 15M 4 «Qi0@5d"*G3c -aoL$Aͱ[9DUNJ)%͋jH @+ 1Q=RQ xi#$ G9jYW5ҫ<6mK x('Ef„ف`Zxqh#qoZ5UeA] au 5q$#EWA/b.P>-S8`+_UJXB2}Ү~+ 4&-$]eiܪ;0Ɖ "uYT"=OU]Zz q cYT z\}qˋ̚E-5dܿX8w LtZhO3eD(Dr@$ CsVf]d9 Bspǭ5mv)B* CUjJ V[d˦$Kb%yS$mL3ń_N#hU?]>`޷lUw2T%pW,Y&%bP;e:Ё2-FuOb=lG&[C|QOTj/Dո5o|Яc W^O^Ħj{UUUѺ)6EO]z+=k=zMXk5YXvf:f"`ʨ̚ɆsJ_['e,^{GX,e(k$-6M#l֘64C‚̖fU^'3jYn2HS"+DET0Ș{U  紂(JT\̪$;Q ޜ 2 s][/H!Rr`&NPaTQr\%(TvOZ\ JhN(n4ƯjHALąs}QS7 9ok\7s/e Q2EB؝n곭0 Qj?Dq3#QvQINڲ-U[knz/u)kʮ~qM`5|U] nE$J:`8cc|"i^ !dLfL" ^E  %Q5L1 fCTsG@@dRM'NS%!̋DH&&ځ#60}&4B9-WR!'0@Kǁ8qMWacvN=N5!,XHUPCѯB$gDʈlnӣ FJ}i7៾f|;='k\w!4pŁz} }f4pUo–FJ'bLN{1ZL`lr'$ aH ʰE1fx_04YϜ暝 ɖVH7' ,$*ݑDċzBaYsq@ C),B4X&%̅Jh"eL@!^%0a `"-D ΠJ],HM5fUux Pa1oPWT-{dC&KJƢuȔ>!Qb5 )@sPKin=;|rsh*!XD}vf,n"_]%Ӱ%z>/:1e5q륆DҺ$6~@`F>`zFwz׆e+I 1hߎe::_8i1j`mnINC`-n. =۶LMOtj@Q*PQUדd.(lPr|!aj0 T`Tabj1Kk64I]! 4 G5W0O D@`Gdlp5*rT v`CտP @|Ȫq08XA% >HSCN`&zPV>-Vmſfdh0ZUis3 om S1{C=9Q>1#أq>.(TUiShCj C4]k\zɖc#4 SbI^4kdBO0,p2i(`) 4Cg{G &LgZS-li*έ:Cv\]&3)rǭz5ռ+<{Ƶ-炘Q8鹸2PXR)2i8d\*8@  NrQ &BDKedD05"Hs"`KLTҽჵ<_6U1W]S(JiVBT6$BC3HɤS[4LX*TNDzuOQ3T%pO =-<\kSKM^X҃nvOc_ {8=3cQ?KXЁ!ژ@qgp\׸xzz9ڧ jDĩ-$dUz)ٽWʉ|=灌y2[L6#3RP4mTJשdfmi]ӗOE` @P![08hI1-(CUUE5w Ti!>dLp5NMe+ʀa6YNyu2BbBPWS% OMM݀AZKZX33eDPR7lPRvVik\[\Jt$y<:Z( E4dLEUs)ԉ^iϡi@^{i;0˹vrN۝Sv23!/9>Od c/߻pk Դ0(DxBx/l3Mi8AWJ4F-'0xX1Q`s84L4Z66R$y[ZZelM~6S5ĥIuHuV$TxgKs%~m4O]oPE֨!ÚǕ dbrG4>KƵjI3i_ 5gzK)}ZQї%4(DY~QNz ź<`RNL/ᘇ׸Ak[ZQA}T,kZh-MddRĒcB8-,Khg$TQ4=Yt\!  b"@AW!*z+a"E!l0:f5%U.Hl^%U7 a ^%({xЩUfU""D'LeJ="bJ 7Rޮq`@BվAUʠ.uВ Pi0jVynVkP TQaFDյNǿmJ빆/SB Tw_?X&FLPxk#l4A^a>z]e'F޻;&Va~f{^\}NTjET3yK ,S^^AÙ!RfU?zʖF-[c b*d,jHՉ|IHCۇc3, ,a$?= Ȁ̠1/ᮓ) @=H 1&x'򂽆1a 0-9UHjZYB vQ>1qyl?(كH鷮0fJlҩ@k/FuTDa!RxJO^Ntg Y#kzBݶ}p@S J"t'0hXu\ bn,ɺI/QME]G#'K$J4~&{d<|޷ϯX/ys4_򱆈C+ JtȈA$9fiy IQ7yP„ִh*mC6G}=+iW4ъǢ\u 5q]isӟ3̺?p:z&CLkVL ^{[&![qPR퓜;9-[Zd-td1\ҘnjOd57]sc;ѵypahM|eUC|'FX.5;b&5 CErA ,uz`=r gIUhgL"CK L mAP%"R2{*r7pD2H@\z_a h$edd$\UOoԛ*cy$57jZ*IKjyy#jf#Te lbTA0w>2w@u{t"5ᗾw_ƕ'K#mGF%qG\KUK^t]Տ7ChdE/2 op:Փ<> Wqk\{ )F`#QZ6Xx͘2԰Wg^j 1avnl0 +] d@;]y|֌ekI[(zu|)JwjD!SF* i֐1qgP!tsu"V4&{ AEA!f*DW!EţIÉ(A48G{uu"^ E啯vn'LT+T iiTV?TM-$#L:3u%DH,BȖ+h_s% Bn+ݹݬ̸W{v>}0 (*cxGB &UF*XZf"&2L#MTD> ƬQVhC5Wu ` Pk`@(#n5)NAzg80XFSpKL N# wQr#$/5j>!Xؤjѥ!M?jm 4N7/y c\: QQ8#mkCHW̧3-{~M^qusٕ7ss 7ؽwהx8k@<  [Bݵ S^ZG%qE \9ml:qk\l@0eJ`e-¡\@ZꚓI5d2JQcL kGKD0d E*jx -cyEp,g$t5rր#hϤMϺAU~~/ ? FpN!s]Y{?}^'?1s|wj7F&?@ ˵QAlu$BT]£x!pAOni}ct5q=7Vx\/߂$%E;5aV<],vh7(3Qc iWbW~+aKY5?޼U|#_8t-h_?;毟j 5A֚FfD1.|EE; ` e el)DӎC!Zmд  ÍrpR̾* &VBhXDPWQ)c,{'Zx}=FTD*18QY*bšH"N,@QTK(tkR*C5TLt* S>@HZt]k=:syӁm_OmOF apl-BUEB&{-Q~ԉQQR>?J͞!1׸A4Ƣk G*5%j񖥨aZ z^D"l`A l6Nt~o:zk_=sm^@|[oO;vn$+zx`jA^ a.4R!3`F/ =VF-0 z II L tt(D:by21FUAbW-aLBKJTZ:Brv(eBDOo{K/U*DЪN1^*Z|}Қh`␻ذn]q1/7\7!;9U;ݵل~{0\Aʛ!qBG>{ZѾLC[>tU$ҳC$4 qk\cDDi_|x Ȥ,K+W zՎ(W,udB:\z931d~GeN{v]ˏmkfS%ŵ_c'^=n/ZCфRKUkGP_\4U4Paď"cs]&??׿Q'3;._=?7g^-K玟8^=plPIOpRE|`@_ORnע kWЮJi5aezן9{ӁmO_U;vtV>®?y+ůr{.m?P#__w&;;Y&%KLa3B( eh ah(z 0xSfa 7785q}sPY!T i&FD -#S/?~䁣s[vn+N.ꡧ<<ç9i{ˋ|aZ"50ƫ^-g0mr"Ϋd΋INCS zCbrbG@< 0n2 UE)L fKhjAPk9cQؒz!C-E+2RQ%E >5RP!Y\g3!Wʵ O}6N! DA׼$Au 1<*XW]D6{fX {g~S+kNۼ+_ۯ>߸gWZON[}䉅^]]#%K?Q,5=Y&渭c#/g M2X\ m` ;3]j\7 fԧjNX.3qɌNpyxU5 2ng ^>ozS>=޷wC |O_|G}7f{yb7louy5~՗[24c{}]ybA5q]Dy<a,RTm BƧ iӥtrigmS-~Ł_xdU7\G?+z٩ɉ ^~h#^W9ESfA+eb)Y6 6dV!X0QMIC_Ta1Ѡ Z3NmQ 2)PhXnkNrJh1S@A.XADl*]>2 1ܰ̆R0!XM`nAgT`N}S>IM r5w45a~rzrdS]|ppꛍ|vy}4c{{/o/~K5 iڟ~}2a( Je"w>!TXD\[:82jZchTo=(]FFnA٤LƔո5p=3 J ` 28zծj/`,M 9Qo?_BD7]?u3¿Uvx./Y݇f_>mO/ W-,asW77, ھO=b=G<<%Mk\72}%w eF΢U2CMCS )tnRoW'ymw><Ǘmԝg߼#oym7]u~8҅k/3s|OUI!" CTj."2̙ CTITByU/)DT5]Mp(٣IB?!╙vծH,YÙa6?Y!YPz"t(D#$9԰|0f JgA- yv%JxNg 6< P͝PɞHYDL }=~Hk芉"\#YTg̛uh2Z6);HܬF^ߦ6u;t'꽊/TCQfX&S;@ᙚRtErk9uyq1G]}㮣'kz­7]93;ٱ3kG}cvlgzL˯έ8xc/z /p>pXSXְ1p"&☼B ҈AW \{֤֛5dR W]rY =TBl&\JDE`C+e<%%/'DNѧiz#JhU]NڈD,g,~DU;k `I(؎;k̻7oӚ_3 [.m_˾sS=f2lA!,zMkh<}KE&>~b/ztOly-]v@b# 4LE+n: M;qGW"7Kk(kn`okc7i߶1⣫{+; -r !"-$^v^z= Wί<M ȧ|h#Z:J3Q`j :zX%1 hHm^l#NQ + lVZG0 5Eeo<)020*-;iLN,w.?V|.+koszͷ=tew|}1;N:b񶛧^,fW]2f9KL.}AT)Z[OjpF\Dx+ruzRhZbr>1q+n:ruE(6\ZcLp4O =]?] =>=~܉cO-,n=yU'.|^^n}o',a-OZ!ƶN,^)֥#E!JA$*>&0y/$$6wxɛ 0 cXbl|R䄂Yjl3y!,J>Z<^Pl6ixcpGT1mPat7DY2?GԩTSm5PI~8;WgÉ%5E8GemrLied`7.cWY[}+^}|ˌ}X*̡K2~=zlu3+v䜻7;D4[|;聧UK[^(&.ZjV m`U*3>+lE*ʉHPő3xh]Ik\@73׋&bózڡrb \8cR&+e13< ,ӯ|7O>ΟvӴ~gky:vvS߲z)96W,-b=-ם[XrK֊Շ;./}zW'!#DKxW@B_v?ĄP#3^"w=@Ȓ)* X(ԤBD>&*!Ylr Ȣ-N@&y ,2=1rq/R.ʥ#BMX*[Q@P2 f"⤨ {ZS+U\qؚ `9Q>^)/^DdؐM84*BND  Vuچ8bTg˷&Rw&TG _MoW g6qC9Oq=!7Ŵ*īs#{Nk&ʝ_D Q1QMijṲ0̰l2npܘ(cB(T={Ȯ©bp2B.^5pL,@9tEfQ3EEBj_c;m&(bP8nљ!:,ᜰI/@& R|BHNc1Ъؐx:H75QNi<\G&ݥW=t_ Is`}dO|3ŧ^w[}s?; xLkfuW=zxV۾t߱O?|cT69 >Jأ`4pKfdZ.Z6c7՟8ٮFcj\/qq"ArMR>?_.Rj|)@j.[Y}饏:!g~2=;3ܱpoSg;l>q־sǎ}[c{ӏֽꚜ^)D_L# PxѢ6Jd6*JV!¹+Y҈`y"4(LDI$+~MFI@_MbQ3B`DBPqvO 9Q@TVҸ?ՠb +W5J L;TTeuP^7j/*ԕ^5k?}Ԡ+XIIkf.KguGssG{ Ν;Z3mt|(4)̠23ب>YMxwG :lĢQa,WܿaCxA7/!5b+5>ABpR]Y22ÖP#73goa_oy#y랩kFnGOuE_yttlm]Z|~=vb]M8vwfQ/)S9f5wʈlf BS!p @IqEI'Ridilj›K 1$&G. ~!֨"eޣf-QYqnD (4$R;6?jIlqNXu%D6~5Q(ioɨh7}D\1c?HO\Wq~x7o>mTʀkvdZSG>n+:֖[kN|⁳qi3C596!/#t6bO? kDRBa?zx³lz|s)G =;y,mDk\/ov;+|m0iPÉ%ڴd {pv2'݋;|=w?sgGfr+wLXa/؛q3r^w-{'yoi&T0CDa%2N id0+,`$1w=4IrA@"k:jOW&H"x j-2IJ04.Y;}( (p('rcZ4܀( TP@!k ÕqS&P".Y$QL:]U$:8 Һhm?x6v;: k\׸)RҍBtx9yeN-&< m_=<ФIwBw{[yU;N-Y97Vm!MɩWN6QwPD>]oǾ!pe=`9薀NU z*,QBCA<0z>RRĶq RykZK$ ٤b%#)fWTERZ)%qTC*Z!#9 bC։!zuZL`%\6vY:C?Gk߸@w)g_:*|}w~UmXՇ(J TrIm5r(ݠA"F .>Fto=Էu|a =Fr"rR&7F"3磑.5q4Vu[Wk-p6\.t&S^ +n-n*=mE٥_65_{KGs[LJϭ*怇PP@{p/ eĔ՘l61s'BMNiQ1 W9|">G8Aj {DKχy(au/#`% 8|_WF'ўhX[CKVU4Š%zI..K4[LKz& H$Oa`* e*YLkY 1PLNjݪk^?|m+/`nT3=&ڱ%={5_;R3VME.1T}7!3'Jj9%#hb$uPх9`GQsCHc⟕55o.vNX+h XC[_=tydDī*6yHHY( @(,i`g > %YӨ&E)MװaUe`:nf NTT|j@1r4'vŖTM$%S9+ZZf_%0` 8R^~iF&hul8j>\vMwY/z[ݓַ':Ə㏟?'f6ٿ^2F8pW_R5Qjum.$ɪWռAyղ78'uƮ+ʰ~cB{X|5qk\_ uKPu/rDTL:aLdH?|g<>Sn}%]^t| gNv:0WdwO-%rKYC0))+ J@!Uh Eu f2'6r㤾 oADeS|E AHjiJ1 ! $:"L'TK) 2W#Wo/MkLu ^ۑтXnƵLUrj&,GGzfҭ.v姎._}O|{ݖ]gWΞX'۬4N,>ݿod]ߵSaxvND%^}ġP&lh>."hה02V:|$5qYp995PpIt ^?ŧ~ne2uT\Fp kp{=st7I2תXFDe9_?37X4Ɠ~?n>7h~֤AC3OqK`j ;nTu3A Lb: Y@L)F$24T`F Z (-f`P,sR Sq*o QPtX.3SL#0m]9{(lCj[:d 䶨\1?4}ܐج̹8_vWݰ6{[|u<}ѱsyc 5ק6[o#"Y"B8APj}E$ٙ!xb1έmz^kX=nrjUZ *$`mmR_Oda$"'{̅{ȱN|~t|O~~2\?3u7g1tuĒ3st+Egj汀D)LD0%*2U:Ĥa#S 3ԒV;5DeBlּ[|!Bt IM)Uy{82BY\ uZik_{ߕ]r ֣ʁ( jeOf*Bfƨf{"}x&o:1]$;ro?tv2ηvhp:}w;|}?>ȅK3b[C x6lpܙ;;ؠ(lx){;jYcZ._clص`qW,xÃ+NkUZի='t!M!- ŨbDMɃFi#ׄErG[s'yDNO?y>7.CSyۉNE4xEGJI"@5c(CTQB3>k%:) hxC0 V80LBX `bCHԜrXp(brlK4;*48b}G9N*qUpB 1TYT3-hD֢@ bChۙ 0i~Iȵgwٴ4d:hk$`kj9J.i۫`Mμ,olΫWA? 㗐5O~D}\wWM\ժVWz~+InVL\Y?E`"7 !)dۭmhcEYS 9if陭vqpo_ڔY3i HP4\grqM U:._d݃@A,SCiigV+ua%pͧy*Ljܟ: Ic (s9J2|퍭f@ɑI$k8-co~>QhB A6;HnWjHkf@06Yk$Ԭč{Χ_~bwb:'צ=l*꨼GV)հݩsTθXdz!3)%e_V2̑K~LŐR5SkDMN ;YdCq#}`Pl0M@ h~;_%rbˎmVӥ6 蒵)[BL]<DQFZb I:ÎSD`Jr#Y2\#Qbפɝ̺c֬=` N|_ :dאq2KVPPg%C#:~Ӏ 3߽aYd|A1{[Sݍ XcṘz)lY¾vk*}ٱ~l4 wX%zf{zsv%)g+ٯN&7"'֏b&X skLPR)[۫C^q~:}kp1iWLWtEWWב2"WLfZgQ&,iM:_t;3[6W=Μm.& {yꭷ&psJ|'~/RxJ&#-aIO͢V\[IZQU7` > {)%{pȌx{. U'/ gI"YQ4)Ǟ<6 i +" _ TP@vd`ve3# ]FXc%U }גߑfYf$i? 'CpϯZժ^uV^J,杚4pDm.&tKE?u~eBo"H,ԺΒQ 1@H1Jp 5@{iUP3ךBcC^ Rh "]X[?ePazQW&TZT4+WJ^~MSՔ7ۄUhQ#҂(.(!鈲r ! !wqNPv[6SE;`79[whgd-Ȋ0f Zbe%y 8 u`@||;.~\ F'LN{`X&0+; d|~?@wgF[j˂l `cj3 Ftf.msg{; ^~̊%+˪VU%BWke!T%QTwXrdp3̕i^\!7 kMA;YBZ}Gԙ̓f)r [6S k:ԁQaR|Fo"4 HjٗA ]{WCMď"{ X}69Jff;g@, @^HpzZ~/|=:xcvz^$BmX.Bfs;>7hN:N 0%vr}ԅ6-:<j@)U18DBKnt H.cDI-b 5d|+ A#]l4-*Ĵ۪VU]޿hYůz }f35*dL;Yj,J`5NRQt9dBic7SxHd A 8{][ˊjq>)]λG:3<vk;F)S# LwTj#AB3E6YaKn*&50 N'ySvO\xzy#1& ǻzW2NiNTstUZ"$%\G*PhN{7}GO$3.V̇-'2B0b̒-iˮT( w^-lEbkYk|oHV*n)j~!@ve jqH#(ٞZ1'@ 47@ø( |. .[&5X$))C])pph:!iyT ƹRέdЄeݘ]܍x]XWC rjUZ}#^=課)Ka*oJ d ]]bY;ZU3ˤuIIH/7uRZ7۝^nm 魷E1\@AmETnM WH- 46 cL见?N A[d8*r$;a(+G3ւi`Z_ v<B%J|p4"Z/˿MrD$‰d67Ob@6gn]rߩ5B V"3y^GŜ]K8h9 ɓ#Jsh6˃UƝ{+|.!N{V7%nտV} nO4~.}s*WnxZ5i>GGsRboooҗMUfsR`𴢻VUZݖ}UÅy43f4EE v9o@|-Vե*pB}#nBVK0} {O{{= B5tk~i0'/duA]ժV/ Q72Vʭ% `16jM 1 MDp$yVւ|3&vzywkˢp$`"3U +WOELFteLXygDBB-,Sr ٢U$7Q+#aJ Hق}2tm^cCzR 0 %%o?OA-Cpfi%{rEdeD\$wX01 rliMQSw_v(Y2 qaa٬(CS@R̘nKsu2swЋ;ZժVW];"}jD%{25[I9yi3j͹x!D.5tB>c%L\eoHb CG jL}UZq0"(9l8%yЛ?.FN@5C" ;C&12Q ѐB kYArx#FALnh* 66Nfq4Uop;W "/sl(=Ș}m41V;C 0vKrTrcuʖ蕣"H SهT½ob WRsx!20p`gfw쎓~SOܪS a\j"agY  {F2ZwG#9^wvo#Tp6wm,qȫkVU@:ב+5S2מ7 f_&:-&`P5Ei֣]XFGBn4dsK׬vAvR-,EBm0 h@uul=%.K4bލ>49Ȯ2:}.);ˉ/R*t0ZO+sPbm7Bwfg=_l*],f1x~L.(J)S~i } jcKGWI40 # 1M֚ K[^wݍMe]8/ɢHNQj06bA3.ь{'<~os9S~!w-UkdDYwjjU/9{-ܕO78%s:aO!a%%XxlFC&, .u,"ܝI y`c" h zu/?{~: Tj7,X$$j]使i &5w P$E &F`0 ]"aw`i>N_:CWPWtUfY#Qx)c+ISqoJñS;,ndV[.J D#hBơ%, WyZ1ԼOw"+]5dKQ&Μn$T;=yldkÝlaڪ%;_uC9ZCӪԮ@.:xrg/]Ug,l WǤuj]waBwZ=t T 'yDi4![{oDSiDCx'?:=1CJŰ_QHl>nY@&SE,jӭU Pdޝ5 "1WG@Kw2K-iLnc]gZ:/DIzdeBG] Ke[w+ ޫUjUZƼfWd,V;ipEVC .SSag@@H=ƍ&0@al)HB\\X0p 1Hm.:fPU@^/ DA2XrI{H .Yg LkARrO !&͆9RѶ-=#h̥Gy2egQ\Zp=Iof2"MV}",շqdt*c#eQ^4+BzN.5|@m SgOVl>QSsh@&~:{XaI-98,f|߱:zae5ls] }FVUjy)\5yYdˁDC&A(BR40bK{)B O]'z)%Nl3IH0C]!H5:#0!LBւXKڄX-=> hMgf2I]5wsîUnkkʆ'׷>3' DC,`oH/xuLjω._|#n#X/.1K?Td0y+'MgåK;?[pǭ & ))"HA)Ede5 R'GXG]I!0vםt3`o@^&w/ŹBj?W//.rʿSl"M$Z^ RV_E`f[jsyEHTF88 Cwtְ_ͧ7CF]rFݏ`m"B7% ( 0"QDRξs%P`#6 ]^f]l0iawFn*`贄 I8VZ>zC̘~ϟ<`X(|@^]e+n{y+B,"<Z>Iumo:У| I{ɗ.Gnu0BoGjAD8N}5T =+ÇeK\ժD1ֵ Lt]k$yk6¤@ -FrX$0'$Xz9 t`} z%\evcse(ՕWV{aUc i㳢(^YtuDMkB%@b[h"Ј Ngl_4&"hVlH¶ʁu36iyz.9jV n2LA¬S$ HA>rb J5k |wEW0} b*R/VL:28KZl Į%`F9hBo:UdpvL0_ԇZTP{l] {gj{X0{q344m{ɍ'N5'Zo]p2,R|HF}.p8 s W31Sˠ΁]% êSժVXϏڍv.a#!(TNup͟pq`@v%):,*%eW,+m_q#[;xZ@nAny0 o),%̊ziQ~J9@e+CfgQ޽Y8 6Pbtm iNQ^e|Bi&9Pf%CJPKԝ`&@UڄAZmQ0l[qXjg{h4 @KrrH֏%nF6sdƭKӂDhK8hX::*(d44>OyaK&LW"b eb-^;+eSyoUjUcWeeIj{0DZؤ*DH"MHQRQ[IYL͌͏uoS5db/.:eJҍ GxF2\( H@Tw x (U-@^0f -[1hj,=ɋi1U=qI>կ9W: )6fF28@dF'E}]bYQMH5,:=9`[;8YHfA ?/;oZs;ڎ.a2#܋/nԞH=7EZժ/umolOiSi5-lֺlT"MHܢͅNe=؁5[ [N|g~ss총)Hv4/8 MUdHP汸jEXR;ۂ&`0ae!uTM}8W,yX<3( z^QWT5dB%x6ZQxȠ)%%LPC?'yDhdz]:i26G3y{ f>F7TAlܔU`Km_H.}>/;`>~vu~rzke, 2J1s|䪡S']tک$uK"gD*K!6-ֵau|y:_Tp5~[SV/.# 6/F/׋dX(HL˔$f{Y~}k=O{6ϷO{NC M%TB!ZOtVSh]JY~IM6PD2%@CLB66|7_ JtfN:DWHW w͸tr%TOey30}s 쀭 V;ZeExi2{j8gD6U[&3 ID!`6z#+fl.a}*?w[?u,nu/۔=?q 'pׄ1yR1#¬tZgԛHPD e<Q٥~s:ڇJ8fym)ׅwd`TeU70o[QKٙB*.z4y[ J2A!nƏ=pI l}MNo'rםO w_q?e>\ؘ] &3v܈)ˬ;>r#`^^_lX#/յuU<\}&_ 4#I"9 zZCk1Z1E#qB-0?o{?><~i\;~ւKv"Rk>uimMM|ty [d`l$H4'& .C'H x8a2I]a+j5&?؛ Vv@@RZ >ly17ػ e}XWTMg |&`6~/U1T~q7"dX"-o^g%ƃGoߑ3gμѧ?6/}_>|8nGֿ zO?xo{o9c? Y'EVȽ#X?vZ{+ă t:*㪴"^Z͚jU/kWIrt/7B4"!PyFȭ^ѝNkHNLE֢D!?߰9p/~LMoq??v_ϝ~MϿMynN=ӝ0wb :dԔ=ֵj}AL߳4b&_ U4   @Ų%U6׼3^Q6VR,!;G!O+:ۮeTxe†bSQGy/=m 䱴뛳[}%L#6<\B5i䓛vߓ 8z;9~l#ğ7ҹأۺ>wݗ|-=qx윰No?͔4I$9o-i&|!b|fjIuJ R]T|$  HZSr UoP5$EBSH!O〬-;z@nXga*=GWGv8`XwR8%p:gO3X >ljB 6f&0߻!u@`0@w뚎xS?}op>y֯џ|>|w?C_@aη_q 83Lckj%jEt1K~945fnijU/jD^Q{InpaSpI&Hkj$x`0&Q΢۝Ԍj m{z'?{W¿>spCw৾~wW'~_QoO7\wi|fȅ ^6,5.Id)(>fgn5,7t%~x`2롛h|.SmV>ekAlUWm0f^p >""+^gl*/].a=2޵C$-*%>ehq%Ӑ9Վ Wy"] @f-}7ln<Sۅ{S_ێMtg6/[o>\9t~ixqhr"_G/r/y cBWZK˔@S,|bbU=]G:z˭ LEB`J4O)l"o?8ûڳ>o#>po~G9}S ߼|mz{ӗo^^G\hzfJT[^&*)Tsx C }ͧz:s*g<Mz2'b-tU=G<0gFI6Y>|k (z8e6Xs4ޑ'\oTgSAm'cCj͇7>r7ٙ3ִk<VTrM'۾M#毾uN|hqNnno(@C%6g 퍖2/J^=" zԺ]U++ /199 8 ac$hđZX|~gn?y}{Z;/7=ԹoyLsN5'o~}ԭƣk7_\Omkc Lt"[*?94Sr@C{`I:ެӳAI%۲%-Y Y? -taQI"Eqd tO{U~{3o{g bx]^VfVޓ;92c(T;!(D?BkjP)=y2LSDpZ^9|0{:INmpmvJ A)j2$ÍUFi8 tԳz`pЋ$]-iF'ٙ75}w}^~}:|M76Ļogg.͟8מߚzW>_|ϝ^x7_7J6pa߉1s(A7qKkҟ#=&vGοkr u'!EepW"ҚF;GʎGЁ#'#ϕF_fvݪ=mׯ3OOg?GΞ>pjw\sv˳ؿ7?ޛxc{oۘo]'gK9 m}⎙9j rr]Wz8'Ba6OJ}D"'IWk)]@cm,/rxhjW?4(i~*V}().5)WôxKSKNE +(hYO喟-yuwZiδӮFŷyxnS;}>}{wwԹlqM~o} q֕ܭ 3߶6;cQGS?t}ǛO=~q: RRSfR KON$} \ap%0WO`#Kv3vy#'t$uژ L|*IUCo;w{.PƵ>~>N{npvO_?~lzA~݇O.ۮ??:uwz|g 3$7eq@<1 !g3u( I/gIr^ܭ Z0zd8!CQF楤J['Ffn-}dywTFQf YgzԽs,1_91JbYO<9o:)Y8ttu[_8ƿηv.\Fob;o\ڏ81VWBe:4uD4{_d> BiklDzm v}GajQlF¨8"#/|wߴ"=V?:#:{ ~W?sg/׾z|?|Ҹ_M:Ɉzp|#?MW" Vc.L,/Ⱇ]Xk^ɵgY˺)F|i~9[2C\JѴ;9&cq6֬{n[7^3Xwv֏N?̡IG.Uo|٭&k+za䗶~nGg?yNn;>za{/ݵzJ<}i e' BC;]v6 ͗ `DhAm{r[|;tx#bej{y~v{o~O_C0a\ ŹqoЧO><{F]wovݪ)kfP&L{8 IqofѢYZL#b-;|K#:Uk#Z`&HG]K#i_U9RX^^qWI@R,l4.AءCg^xQݏF }j6IŦG,n;27ʷ=sR{g^޵Ns7}8Ï>}}#gsU#I.CL"JaּK įz}0 ;3$m`kw_+ߨZ8&\eo̖|ղ\(lqǎ;9N "~GOYB#~1c/QmmVܜmLxXNh__[;^7ܹ}ƚwO~7~s[{O7wrDLDTCBs -@SSrΆrn͟G?ExÍwh?7?rbş|o}ן{b{h3έ7ܞ*DJc3fu6*#SZbH]g鼀ڛЈ9,YCij@Їb :>3,J6+-?t7 c  '‚-ceoQp$罝ey[8;wJ-, `J O.נp. \܉vRm:qmw]].~1'/϶f?7?Ƶ_7OӹI(Նh&2I.ĭj:,ZjNX$ĦCJJ'# uc~I.Е\ֲ,8U@*%B)> sULmfh㨡`$zejN3m>;}1Hn;wy Wy{o9q.`+҅qq9'mN#-yqB:Veج]qq%c%7Ch*dccxj۾F?l>_~ ?M}w|ғ'/X3ӿoRw$\}Chxϱ 1yXub;c+O?{aK{ãϟ޼x[o;=;~~]2) B,\՜@m14Tޣ*;\jD,LXD&]MYAk]3l_uq]:2\eC|՚HWb]Ή2-~%*tF|!p.I I:;]:_޶m?ؙ;ϝ~?/\a|TV~46o拗zsbԨ5oA |q]Zg 䏥'awه3Md2yN${;Z㇞lHdO3,;U%,9UV'**ioȹhf@-"l07SE0m\z~:c9z,LI7E/If$MsUXb^UP*2,έ~otѴ׬hJMjkj% Z5F.znlϋuC4{$5,06"g9xMTMYKs9&Iϓ:rN}O N?q 1\>3>7[܇_o9~tݽ)te>IHGFB!`YCcq:۞?w|ܙs.]O}Ώ<}j#hP)7D 㴚B˂%bw%p],Klm{J gw+uLFE~MS&{_w.:f='O?&I2Sڎq7?3/=sI ޴n6oTS |>L9~ןiDAE5ܚ4Ւ{-Bb؉hn5D(i~P@5H0~ /g?gD+vޛV gGcڝ9 !AC<McG0򜿔95Ox ",y_gTKwISbU#Z8ɢ 2sϴ"l*xL\Af6*wlCz6f)|` BD fA8C0FM X"O*|G i/SkcFD%-6M K+qG5 Zjf"$S.M+ᘔ 1RXI%,qUXE, vUڛ^Ӟq7!X/y*=by*HWMtbf19Գ`[.[Ѱo,=v#Zd*A.Yb%! IwXi8\1 Lw`;~,%]V@" euxϼe}%_˿ʝwW5ɳ!8"Givz#=0i8i5;Qy`$ɤ4Zՠv`,\΢:r$lh)$$91",zlk-  0dH$[Yv7 @ C\0Mk%;u=$c)Nr>L<"͵"l.`b dԘ\ 0IV_KP\پ@z(q;`cUIݔK/'JHJ'T-+2t`qn8VWٟ?F@A5q%9`F<"yDqZ\ Y7-J s1i{Xӡ+ci`^elp iyp L;aY*kb5BZFt@ keKh@d@SøIh81Dxɹˤ\[5*CԨj[ J ~g>>oЈd4uFB8gDBoNfQg1&g'.׸;fZlʥETch R0`Y, ܱLLr@LD20Ǿhg:*' ̓=97ϻ%;wM;}k V:\"娥EZkTŕ5 ݷ=5p@:#]Y[dCՠ';%(546*ԒUl,dS-/qkw4Ǭ ej+~ϵT} ?$ GB3x(]2e48DT[r#q a0G:'B*R&ϤБ3N[34~=Q;npqz]74[38nD9Pe[LI i,(dImTU;w?DT)%TEo`;BVdMIIvKҋmb$Iq+]꣉bcl0r`/Z,ٗڗ]:vITuftJvƝFtc@ǟ{qc9y)aY$Xɹ!C0 9r9f 4+#UDC4Z!D Q l$kxXA$uX23ˁa~2u; nkgczMp!˭z-~^lḌ%c7vE=W<)M'l'T͙%d#Ccxĉ8#0mb49.` ̐~W9 Ʊ8X#mjuS" ,AV>1kmQBj*ࣁ\=-]me{e ҆j7\ .%cR'gq?QpkN6+̠54 mtƑ1WMYsUj8f hLzA8R3fc07ׄǏFզmP h4C#&fjjVcT#ci{B1MdUP)LpBZQ+90s@# |T,H 1 ̊IAX I^U[ V0K`aٲ:Yxlse0[8 z0?~1kg3׸|w4/ ZUc: HXRS"Z~/d_+hVA"H"i}4EZAL_*h8TZ8,kYz~y+\GVA`e !xa9"%/h!j0#14V#'m6G?ŠI# pzsV1 AafӀ uwDGa-1C:KKdJe&6:12Zi" ]ѷDCHȆ/0  ]T aJpΕ~O7jskP!bzZ0tPv\DBZJԁR} Xلw.2"M/Mye'ʔ_͔6 6KV mqm `$U&jKL6kL턂5jtZ C>!;=(*Q\gjQV l!z5kx7Z@cak( ǞV&!'L[9!0xr4v/}e6v!5BaҰq4lXk0qr{+CAMdZTj֪d⥖2CRZbL%?c'afL8N;jhlDMۀV`k~=t1WCGy!Y*(*ɦ *zg*XCEg?hӵDlu}\NRtկoE&ejih4~ Ț?5Hed?V&,3"Es 3ݜaՋt\r룑ƞ#6r Z9L͜f:,%IH^,X/KC9ѯwh@4K3 mtݪsCMBF^6eA-)#$oj|2 5Qc,rQi*jV-v !aWk˺!0MiWO'{֧8Osdз$Eډi44fmm♋"*g1"FN H'V/9U.Wnlz%gךXy5{riyh)wpb+#IKOЪqo$ !y=B8!ֶ1¼LXR0=o &DLcD,z$5+Hbn sl``haPp+EZ7З|DAV=]A "fq0jW/ EBGFQGZ;{íG.M&o sGVל`\z"<#rK1ێeb Hƒf>K rB+ux\^ظPRye,-kYZֲ^"x| h6W#Vm[1 {k#6gY(*SIEJ0rp`N[DUI9quG!i%‘nh8~ˑkp%Bq3Tm;8D5!Gd @hQ{pG= ,gKYH#9Pe 3ȁ`0!!§^dZD)c5c `[:wcݠ8)=deEKK Z)5RL.yDFp&~| B nSށءqNF'%PnRFÀfV &;'X(wܽwhKZ.HZֲUn ^pcrRjR䫱Y 6fVkZ4M58zB484[ϓĻN`+x i=9ޱ#‘#-d!:0vBaL53*g:w4$1qEfP#0vaM/ᄋ{ G65:- j`CF:dIq˖Omfd~p8ckd5&'W-ޡZ}"h /΢Rw@LD6 HX/ju<-^SwO'P.XoFPbԬL,CRÀUV\Ilh-衉8+gVFV`pb+<C!"v] W6^؋9XWNWve-kYd]d<{ ^aPNEd#!=ya;X$*Lfl+b-2;5og=%9+soDfճ@7L ") eI98YZJ3OY}3VOf5PH"WZFD CxK ھg*3inzWz22N{92Wjtyf|fY}Ǽ,:ݙDnmP5̥H"e^4ڡ>0 H-jAlhƁ `0DZ* tCvE>CȈ,E>'K =HUb .Tq]ҫ@΃`҃>-Qm{.p&mU"nhbN2<&2cXRB&CPuH}5T< Hn2ݩϝ1Hu oɜEH׉h919SA+2#C`xXyb[̌,kS/`\QU&iXkMxx|wQ|wU1: ^Ծ2|aDPI2gJ5+e p^u9AX8G( _~\~ Sv h%0W !\l#a 0L$]}iH$. xDu(=)q%PNHG Z2 v466{fM ED3Lađ~|Ϟ=vnOrFMf"S="=B,gh"ᙲl`JQ U*8u%HÃ.祹'ZMধOڈ(ԯG >l$NOmQdSvڰiTC.z=LԽñ9!Kō(B)@t{< g:|df^7M~Yfo<Բ_)p8(^!dI *NC@r0AdV_aeSV<ՀCK}vt#:r9lzW Jk)wRxx|. ؇nk7DWՎr&Ӱ&ۦd=.Uj mdSA2ɸ2pj ? 6v̆/w`d`y[8x'IU/qΦu\#Wi˖ /[ ^R2(FiQHa@F\ 7upLlV9!#dPch¢PFN@D b ,ECj8j7Ԫ1@ 'zGU*5㊹msPj`ԡڨTrU׫fW뙾4ʩXp BJZ.' m?nZw6X JA_R:hxy5i4p_!]#^PbϡaԄ\)&O`n+[6u+st]o;ۍW{Ǐ8~ٮ헜dFyk:g;f˓9w3Sbӳ \ ? P t412*)^$6_r>#WNP1G;pCAu@j*ԫ.(}P 0DR_@p&t2u2͸tPE Y*]P闺\;~۫7p?7w~ihƴ!ƌw҇=nÀꄡ!-Eʍ@Z GUFMR+=#XaE<1ȂlȠڙnJ6H9AlQq:<9$s``9vV(-4$w+SVsiL^I7l*2B0Hr;gcmlUDTѺP R1.S+׭\7n 6vo񼹕?~{|#Opc&:&gf&D($ 3rKUnb`l"Ph ҤוݛX˯%+oc<Ï7B!Ux.@ PR"ћ [vW])=3@XŁ7U;eKyΥǩp'sͧQw[q)_?_ebᄍ²TNc2 WDkuhMp]Qi~ J DI$ ;Qfq[>ŔΙY%BLɐZrM w2BҪ>J;%Z*uI AT뱉 #^mkGw˦ln.XgwnbƇ|%{rUn0X\}vLwN RI i2V7{VefуGyއ(,j!ﲳk7^#23xw=)߸"%Z]vDA+"1Lҙf]OK;x'9_S[n~Oۮw{=zzyiilz?t}d!ɩz;FB kJ=EDBFFQuW`2YhSd@uCW*TtT |:vo#>!XPeGr4mQjk54{t5ԔI_MksM@U*88s⒝`"}'z9:xߵY9o6qsrwl㋗o}3g-S}]pS޷/CEm^5~g~ $iԪ'ORb`qaad,Eɚ4 $ iE(Q'8 生3t*%R&kppaEٍbw^PpU걦?Mj-pql {q-]2Z:Z..-n6X?ѹ~ɰoy͋7[3k9-׿xGnh&3xdOӇONQs f ;ZEPn-J OJ_Yh;髽Z1=<ÿuZ?N܆`AN4(˂rf[T'3*=RZ^ tsd ٫^JyǛ;?ԡf8S~/_{Y+~ҼOY`PK+^(:論 [h#9鴴#5('#'WHi54E-Jc!#ANoB#$l)IumzKVb)^x ꓉Ѩi4鴳F[GV9%⑔s6nv᷾\Q˯~x{ۏ?TG~zV6Sqˋ.]OΏQx 2 j/>'X.Zjr,'IG;Q6mt|s.|/>ubY^4wi{prNgSs=y>q-+6eZ,-{|+PFѸ1yUQ,0GOJV @ՏdX8m ؂3PFh߰ hnF(o(C7y,ø7;*FqsjZiВUlVxyל7ybQ>ݎ+/N8Xz% Kli:%/uwE{.+g<˞h)_CVja` Im4Rx+( d݈aszնq mi~Jxx9j=c0Ail-jQ,qfw S0GA9J 8̄YMlkmNįxw7~+m߼qSJ ˺wq~Wc/~,ublEO]3GY2yEn(3m)'a1k/ԫO+ KUUG{ "ʙJJЧXoJ/Q+qk6\nitX78*:x^:?HM-1;v1Mbxaw;KǗ(~t3D-,sUt_uk/Yܾ.[螣 ogr׭{'v3K" 3C $tSv暟.Rۦ1 5bI(-l==M:mƊxx|(0UÍ8F/l`N\ 嗒(xKW+76d)ѵi(@`Fmm[j_gtdǷk:rϤm,دߜm ’@DTxN굀 0h*N0ai:7DzM7_SBoGW[:|?k]Je{q_-,x=}l`:ŠϿ`_|S =y. ?tG^z,e[NbrLC) -ꤿju&hl2HREqqĢZLgpILy5)+Ƀy£BJXkӄ*2K|ifAE8dff6ґ;`W3muU"f77 t_&I &r/3$ԯ*9DQҧRRRr"4 R"@t˅)TfI=Hԩ2K'ml~B!X1(y=~gq>;lr׹g/xտD$Lg¥g}+WKw ANEJ |6`@٘4p}U?53DD*P)D~WOg@#.-4־mL?x SEk7:Q:H|1BLp",GEoj!3D %-!2&3L^@ٮ}blݼwYIѫ/ݿ~`sMw6->8l9;fW/f}> 3ݼЭs:=|a>h Rh` )1SG^@; ``o %d=OAhìN-QjND3ըOx|<6kV4iVĕ"F>ZU@j):iU)d~jZ"-s&+vWl&IW(j .t&W]n=ȾܗXrB-_dXZ<k3{)ߴyS,5[/|ω*2Cɏ+(גCjҘLt "%僫F;"Z%sh~K[PD Ud{m3>:ʵբ VD~NDL4ӆU I(JY>0غ Ϻx{ݸ}̦׽/{g~Sܗ~Kq3 ǎw^{O33ʹ\1s'WJ/@`2CaUW"cs2 _#D@V"KDJ\}Wkؗ 9 9RQ1Ic>ߓl b׺lH7ֲP KKp/P f27JLflhӰ0MetG95r$_a[?^s0 ƫ'&luמ{}Amtj}'~KǶl&,!7N+PՌ:v9'k%< RaW #x-^50SK^h / )FuylkyiՋE[Wv(͐^\NQ&Ti!@BRm{UFidFaW0 "6e[[ + /}?횠,8!oJ!05Ξ$@PeJʅtAWSeISncaxx|?uD]h 6QLm*$@Px+< 5<2fTm|Sws]{?x?u7|'拥_c n"][|࿼+G^\2' }zz͠ eDd #aiC!^QZփK;2v1(cjJ:tSIMo\@ İ+kZ%?hti%cC(8j;Wl7_T*O4asMP>gfc'& m<{_/[z~㹗_4^}cyO_]o{+7ZDnwRHիzU'0@IeŴp2DcF!^{6ObQM!gGZ\\qΚ-%d?z%S/}ގO|陷n cǖ\۞9voܹ#SG^FiF@A"IؐV;Âs"׼ܐ% '-`ʨrɏUY# P&!Ug^v._[gJKOg~E!T 72Nq׉1'7,*8<`*T9垨!&X l@a\rCNU+\l3 \/6`MR{S򅯪LC=kA`NQDS%N@ mmIPQl|ՃY'Lx.MK܌w*ehT]1pSN-MЬjү&O6 `&:Gܘ ZGozZC{LDAOo^6v:N=R v~O\N˷t7]6-+clo|p :@ )Q"8H03Uh UTXEˀ W3srѓ,+485 $ 0bhHSŎ2A$Iѫ3lŕ^.2%)')FI5TqBulS&N0$4hH\C_zLuYs4l4քƸBI?Z麄U%6}FIFSO^qdM1ݰ/͖˛n1ɾf@} ](E^5וR q.3U z0((S9I*5ۺ3W\ϗN#.T7i^,ֶ R4k;Dߎ<>J5c'7}GN_^{vxufI&3mB/i*%XTTb^Qj#Uj-1Q0 9THK(9E(yxa2,K MEJ2LUhِwG]Yb̖* 4qp[7LUY9kJ,YN(|*48,RʩX8WA k;]r/{ߴk]EdFplPr+D33c(HڦK\|ÌQ?񂧨e uV1ū5-q#H5Cv;t:u}㻚FR- Fc<,f{PC̨k y(|7=sϩKI d"ԶINDKӾc[)=fr^ /W5@f)7a,?䱝;JEW]˶|/22_7?xO |oK7+KUVB4BWf^ة_beUTߴ遻BK C0e(h2:YBh Q}@$)JEOQ(R[>U%V*N @IbV+4]T 0AkUt i+ʑL{3 Zb6@(!񹂅g64oy =a~|nO7nX#.)꽊,Sl<u 1SUE{R[\ʸ#-jq:pi%t,Kc0d0n/0@*k 0b:/w C47ίq F^=C\y=ʥdDz@$10c2p}RBJt%Ž(Ud085W:vsun\)~%|S?e]XCjdIp̄NF(1 ?JbbK Gڐ) eL=i(x 逇t~4ճ2q[L )i` 9r @i&'wN-pӳ6o_ӅhUR깫C;dH_Q6m-ӗ5 gNT451,5d˫)$*e;QNɌ-+2sl+,k0.J eAͣjlΓCt`fkt(2dsliYZv+[^ӹb"3?9s:HpNGǐa*Sk^ev$2_eUYd_eQZ !#tCCQ5&ˋ'c*}D)P2h@Cl u'w#yGJ^Ej1Z3J:İV4U'ЦvHtTU~ZmP(T7B`]1b<% `Yp&;3=zwv]n?R3}W(b$%i~=礁h] u *5`(g~l:+IdRekf-f_HՕ]&ZͥCj<4aΆ\նѵu=ک1ߪ OkaH)3 B('S>>AQUbۼ,yŠTCUr39 z-L1(34a8֐K[Ѝؕ@D{\y.~֍WfV\s}%DVR}O*5ABdHDx"D˨6fPP Kh5 ݂>%-uoª{%4kV_Mµ_]y*zm*,3++Du!1$#'sbyhdUTxPAdN1pi̇|EYY'f=bZ}‘b(K0kẹɴh jFQ^Vyy&IE|bJŔPsϨ핫Aihgv*5e-Pj8U11  @dzX1e Qu^Kd%3rCj@uLHnF> Rx+j4;(X q!O@-؝Aċvfe%u*-[ʽ01'F +kљ3Ks*SnVj] kxLNP'ʊJRHPvz(X뵪o@Kw*Tf^Ra$)GzP[0*Vmxf'\_RxTԀ ET4.Q*ӔPd|B n@]C MNeC 9ֿ*JP|#ƪ) 7s$xPHALufE 5Kq%L:|rmpgQ]vsmFq~&Ը'X%H2#K蕃Ž{~j|*U^w#0r-FIQ™uV g%#4Ub }ZC8.5/L>rۓT w_;M`3`(k@u@`ʰ*H.UB'GL #tyuSV%@u d2S"^!ahv̓ݻ4,J}A\4 z.= *JQQMY1VNj,0iHT{ (lC_Z \[^VzC)= #xFHbQ䓼,ˑ$oi E+b86X4?rs#r+ ͵qwK0C^NBQf.H$vD+B)AXB`j tc]4hvuW!T-Ժblԅ^n#ERuwYjebPMq mY`li{8㦳ȅ3 a*`׋B0yq"ܨ1f F dzưjG[{aՆ`NL̢7EtA.YQ2dRG{Xҫ<]~&Tb=ǓeUј4/O;F}κ"Ssx \Y4 s>A [iW]3mSijJh5Iw-٤4[P}П{m7xeiy 䜞bSa Vr0G(IɌtC7v$cA- F_[g]XMVFFT7/U:6gG6Kt#ḱY2Eܑ /pIq9$u|G,ѻ3H܌|ML;b. ~V peShǚWؘsJ0+SY1`RY Uɂ} VkX,U)v%x[kno?/+aTZtNkYK ZMcj?IB"ڐ]3b>ȩ3ΐJ=){\?ĩhH{.>WzQW~/YŊf65E UtqY% h0AiѯTZ&rmzAѐ&KLL 0`)rzA[r¥q`a3'<.a6 -d.Er-`ZIgΘEUTî\^]ϿmoZAq0`<5l cFToXdҙF A0-H`'}Z_iO (pO"t*}")$!3EtӛZ("[KR'VQx-P5DgP\*Y;;[WN'؀mu,mxԩ;.nr͒kcVN 3Ve^zXHV%f5-R N-e;ޱ`qO%3R2cb% g% ]Mr::[eW/OhUλp ^|QNp Rk}m*ȥ-,L`PDJ]ڨX6p 8D t MVR K&#NF 6X@n4Tl)"$A 3{O>yw 1k0[ZH l+$V1-; KC0 8*2***(["-?uϪy朮 \~6UykrɎ1Vᮮ|ޘk/]y";bhdZ"61zsqWhK22(`AM-=4V(.mm MMh"8 ±3fX6bBfZKxN@JR|-i<~ݾE<Б5"KY~&} F dTcUbUFhcO;}ftؕYTZ9 Q `*LFeeg PBNqYC~"Gt\Y?OUR|˒eӠsjYŞ"[2H?'9 / 4iq=*'o/b9ܐcGA 5OZ>`ԴH`0 $j ,];B7d{^}rU/lj~pcD`^F-gC9Icdy؈xjt&@=J}nrŀx yFn)b8RbuM2c{#r-N5Y,Fn-'7/  h QhL)@Zߪ>q@%MÂbyC slۋͿ1QSe odbHˆlZB<,鳚Y#wWD$-Q% {>U$(WkH\,, GG26R+.uj&׋'::]O\f7?7mݢe5c4ZCZ8yvSX@$~ jg֩ %g,UV~pЅ6ak!؉3sΉ (VÏ]|[D1mmUCQGzpmZ,QYn)=H"Ty 95y86UaD_hXUJ,AΑ$Jo(Xtê!ST'DEթ*ư<h:nʯǡ⫖պ|Q;Jk]N$!+DQeVoShŠAz Ҥ*kqm:vD_nc*rXaP[m׽BŻ>S৅\ՌCnYF9xˈHqDg]%ݻBH:*XAxmЛZd_MZ)B\h*v.v=zZw#7Ngf1y\`Xcɝ^V_a8=k} کvb-76[>ᑁلYgB( ' S`t'F6=!FC5;ź8h]U=TXmL%hj&sB6x G t󰔲vtl[#*׮,`blzHWs0IX%8f FKAj$,\TyASO-vPe$c WBMBp>̡ѱox%QH ۂٍ=]$3WvW2KnҰ+/()f|8.G4u ]/|>Uig7ynUNaZC{]O] e-&' hbDֵ>6Z6 lt 2:߯#JWmGZ).g!EϢVpͮz&,^D(6t:o]|9n$j^q`P Z]Ԯa^#ޑܴXxY:^X!>mcP\ZŕT3n5txJwPٲ kgrR[;"➛ƻ?n nEsX6O9'aG˲ Yli1ZVt`M_-J-B({RzIBN!Vڟ.Ad~bpU|lأL"o`Ls\^,C&S䫵@,Ԙ.AƘ) mlMljr½N|#5^h5żF';Y8{ 0@44 fCzڮv"533n?MXcIfT;Xq6h:]u=:l ]U6wԣSuZ`:v/&Fm%3x]wu:ccg.+m0FqDpz!`^Y\nM6jUUXz :,Hzq'O-»UkN`mufp¥p jmG DS#)/ҟX.ƻO;zD h66\$АьBEcKɴϽclDѤt`%bp\UHAhDvd_ac2o`Xgye7@KчB:Jޙ=^SchT' VE޳7tbs^)[|WC|Faɏ@X;I-E NAxҬd`Ujf~|-GM|;{|:9a5OFAtwljUwC5󩬎tIRCFHsjj7jhVRU/9~ u&jB%R\$H¼ څuVYn; MuШ=BU[RO:@Fհ M0awG*xGVM6aAЀ N,a@as@-zSC֯.>g._ |s֝A]LxUg I# ě)cM8'B6rsbnx >EҔSbC*h9-r[P] :GJz5!& yIY]S9&Ÿ*{%NGRRw\h5"$\TݣSY/#/#&W16IL"R52q!I`%`,b89"d=1+F'ۭdc4ӑ/oswmYӋ-n&6GY1F):JB6gNС+@*;!98>-h[>U?玪0)G4 ĭ)K]x]}A ,'G`01&X٬2\&b>.LY0^( :5x\zC16!g[]ύa #wqi8# ,ԡ3i6f0PhOF^jxYDWZz:k, ]cp뱁x5q6u9J9S=?:$m#m9Hy.mx+Z*` 6}me_Kaֶ긘ӚR-*ڔVMK:mBϩ, Z{' l:SEGSA/w$60h[x,ڀQWV9rs {2=J;X]^r/+]HCa4gY^ޣB Sá`(ݭ!Z]ewj0%,|;@`E(W`&!dQ eSqBP.vA캔AOls~i+!%O/ uWE~W|vz$k٘e`B^ /4Xwl'|TN1m,(oݷ;nX+_ғC?5+]L%Ru ]C"jRwYT6sqiJ&j< PԮ`jGzÇ=^Ybo-L5=G'Bm_?F|M]ahub.qZ2#W‚<>y@Q!gͤWdq^iZYw:Z."i Ris Ilj-8]/mb6Jt! ]O/jmb餌qÍܨt;pb\6[3XXVso^uM=]r!,$Ck Lmjckqzu=NDƌ >a`4Z4E϶2yZ!sE֡]!'O>)X]v޹K }u[cZ#.Kdr]`;UB'v5w<.wzR8 AB^Ch#Fa!tfs:9ޤ1 5et_ieKTMqRGt{/%=mCvz9vU=9z o]5ś5՜] /$ße2X b]VpTzX@ڊ9T`Ic-,2aә7O|OI.:4Jr$RXv:=lmi1ž"H7f EQ}K}.G5EPmB-h4ׁp<hKgmg[[ZBVRstb]Hսb2X\!66 akP3'qlC;34ɠ܂3 ,< a U=脴VAW@'w,&&,=0E"B]w~O|G?蹮yG#eڛ TSr%v)25KRسV9H/8hD..NHksV^[Gl2IxetU_ܪ!Z뉽3OH NumkD9G+3_/bZ=tY'~WvÎ?\o•~ݵaxѭ/ Bm (ێh3ڼn]G\mCl`٦j*?f hڦdQw]WaC_-hj)Yo$C!tn#:O=Ưz։G|gӛe1)IFBASFtas'WF_lM-vD]-,^'5~f{nb' eoL~bKkɒL>mp: *gZbck%uaU#s!y|wz՝/٬ɫHri zSovs}uyU!g[4YpQVdNZ1nwu3[EKKR6ޱUQe /uyP_I kY 3x.'TUhwlbϒ?g\7(g\1f'Aj}_K_5TZ8,WЫ,Gn5]l,3pq.0ZY Hy P`pJ.7}~oS3һȓݷFKZr9RKb&/h{=JrP}knWO+ȅ\xFbqZF"&[L2MVsÍ~o)Clb` !akp2o m}{}Y dt2Si>Gq‰?U|9z[S't'O@TGfN^*t^ALءzUeR}g)4;^B ϿH",8`x0\yɉ̽׽\3? ?9ivvBN@N_86x';Bg֙u(i0`;P}f:l3PF+5Og%SZ-br"ho!9pזk* IJpO&Դ/dl;b1*kN.:1nG9qK[ܐ\agv [0$-iC`3g/*.}$?>~m/9yʷ6(ړXjcߌX(,JPErI֮=߷s<1l]E1[[zWtWUŷDQ)QOL#4 !rU쒥 k=]oMQ53o%ܠ0AqB m4FRYMGg18ڻgɎX[ pg@"*=Efjs YϞ-F 'k.9%ĬҖ}zYDz;X{A`Nhf`*uQd^q#B`X8Yxnx¡Mήt4Xsh6Nréo PЩuj ' "]T/T"}B<0Um2yIeLL¬Wȁ{4?p`1% UXK&DMAMX :$l6a~T:F>b>&x3 dSww@~=t쓫;^y7'/ߣ/Y{nY~WvE ŋ/gnW-Rs !ǹyʡ+]z.;,mٝd 2W5aWQ" iVz?Iw5@Zi9JkW)ªp@,Ce׭pKsƍ}M~Ե>z5N%ш,b@˰RgV|$R5XmxHv-(jw9>ڌZ.cMmBE? *P%3KpEZW|*2~PGSd0(F$Azw\:*Ac%vt#7|*\Z}w4%[o}+G?w?s9yk^|g:#6z `p*,)RX + EAsȌ'NWdLړs^Q_q8)H&bAxJd AB& I򆈗Y!jA,h[ci'#Cg8έN TnJ#<h&7:S`Zԟ'?;C:bXy[WeU#o|,3QiAm8ȉg` +)؈lS6"N!1Z*yS BU3F:ڪӽ3 nw g/鈍WVrUȝȶ2F1ynU^\g7GT3blW7VsA=TcV,Z!R)IF,% U5'xX\^%[DLe@&e )TߴrrϑUwywx.>} /zwȧ._>~)6䅃~+?wÐp1'܄l\ZS3 s@ Oog(ŞN:ݪ;&HQ]53?Gdb2׈z8҃I BcGFmGK&yPwA0wCy18TzgC}ɐ-PwpC%.^raξ8pvN ƶ#r9;5X%dr=ZQ)9JT{ BHjXFq`1#u707 ׄJQFAt@4876MW:KA7'atdppY$aJ 7 LiMLsXD[]dhB!kvj!yNpl$ܲH[8ភNM`Py߰L`c6Xuw{緾gyGxKo?y;卸G3ytǻO>~ ؘc!7yDS49ڄ:OCV*Bޑ$ނU)!A3mя6r(k,ԚUXYHĿ `tW{j0^e F<ev2WJOV!x,1фిM1NnvI_3DNGνS?汋߻yӝ;ݝ׽h٧ƂoGtMw?xӝZ]B.hO| Gzrzx &G,Y_ŎԆ=AI}Gcc\u45 Vx..\ tFRuCEXNKH,<2m~Ify]E0B̴""R Y zqT6m~YBFijFu"ɣ2ԗP[U7y5#xg͓"GVɄR;,5IHOm^J^ՁaCʈ7Sή]ҥnosWw6wk^q'k߶d˿߾?ѭ[V:,ۆr;G8FB>Reꑤ:z4UC|`A< G QY6`_Re#6EͲW9a8Rjc+bgF [ff7_ CMpB_ EqqdqeC-ʵ~'FF6UxG_*GUԔ}y䭥Wk=l/~$Jt䩨 "dYg!;ΚD'LO87 iw=v|pPfZU[峦lCmU+9چ j3Ø7o逤l U`6>2YLbfBcdA٨^Zكp%qX47˭ltqvYؐpi,iXx5x/ί.<\?|[_[^[}Vtobs^X^j?{N7F;`WlXQ?*(;0ENp/R V"~ma+wow#!.0^񆊔azgWi{X+W:k %z2 :wv,/Əg[ MY2cQ)$OdA]H#QvZ;ooz-S|Wȿ7?7O|;GO~Sz ?'nw3't78Knh8쁑Lj#)&x8LS }㫖 Ԥ}ZF]oEeqi*XaHM3Wf:->huK#3pyP(oy1h/eͰJgs6Gk=!5晦#V'(ya`#,qvV"K |Fwe^j#lgd8Q#.md(}uwƪ@QFcuLT3}K^jɔ^_߃;%&X_ «OvERd^d.ǷeO2 !5N2IQz̅`FR<#)4PD!\铧G`*'e 0]ЀĂ2Qtylt [KH'܍Әd7YpLk1sNc;jE#(͵-FnI|xE ;s̒*K״J鷚Ҩ:HqV K_;uDUwR&F~3v#ѣƩhTt}6"1>ހ0HI򂸙Nr8G!- -:˅Klymwo-hwF8(a&F}wBtb!pdVA } qmVm--*KO pM`)"-2;"&[ڮbDI'J4d$nQ e;,,I䢘d -ANMwedAOVH,*:k @n+ŭv$g]vwNOk^vϴ?gx=APt `f Vqf%n_JJw G6$fFtL̖I }׋!9 e ,$Z4^&f[{լFM+6]; %GS#O]koNDs׭h׼`e{쩏?}{KNͻ>|3U@x_#X.5g~7]]✑zUrF:v; i$rHN4E \EW(!rR\0^~9-xYE p TEf?$ y |V=OGYblWj`~6M#{hVq3I6 Xz~ma/zLga8 R}f{ JuK2#숋-ص¸@l9DLd_d$> R#e>BIjY, &*I7-'9i.!A1 ݬRp;EYR$<< T1lV^(12hoǥK E\!ek\վZVj(bo`H.=Qa&^nCZxh;hlV%oyi f@9IIIh(D[.v$Je,,ʴ%&+1 Lya^~sNwڻϹw(WSS/{^~\D!Pºkm!m1uGG??姗ݵ{C:/|{ן>s∏{v /^oB{oxiډ/~Guo8S^69.\m_SұڔE@@Ioȓfo#Br`%)XbrI/C2c ]/r`wL7v7 i:nѵ6ڿ Ld g߳ ^T?:]w ^\:a^@;W|vKX.}uw+/ݜm/OP|?X}ṍ76vë7ÇFW?g_>lyp7k7o+诃Nz V8A:m_p0WY'q߭;k򠹡uq j&6P6a_ ;偞"!l#|yn'y2> mEߗm8.Ki[(tO:'rљUd8EI%F8LR^:8}U.'I \(z+@:7VW8A$D|Z:0rF.y$Fp7wt󯘛b#g %.e8j]yjuY( Qep.)uJ4nUBgaP23REiJd2NUp&rwA ]b,R4=Z(HRK%q@Rer!fQ¢FxFՑLwCl::r\ *f!D96F!USzʥIzj{Nqȡ#Scc{~[_rCwNb_suK?|[G8Ա=HX]yW6tk3\=)se"4-)|FP:n>t}1sߑog{a:@@ ":+1hKX`^`uM#F>ZG9p2o9i  BWM,$Ktksp# W8]w^Yۛ77zupbo>q]kݵnkwvm$>;_>ۛ8|PԲkzciZ,3]s`:(5B`ѿ}=yCZBtxg7\*ƌ~W,es>9G4хdI:ehwCMy`i7#ss?.@[N 1[EEYHjwC ]ߎ Xt.fvu٦2 zXO, P0E\%Z8ދ L=!G^U/m小rODAӍk L9?98M#jN$ IXV5*^Dg]H!˥P8 *DnqR9d)cـșp!j\#O]yDZi cFyF9z/2ص sF0_我 TZ%[MwxQ ( *<&UbѬjBԙ5\$T{[wVqtt'?I)KϾ}7&v~͈z{oonnMg'׾~>‹iÕ)Ҳc:I W8E`.`H:蹜bא9.si6(VNdNkO̍}1+7XL;`ؐ=J"(Cuf[?Wk% ?HuD*ՌFh; (6f1 `;/NSy؊$Y WUr܃QJ .ؚ#ׁt5i^/j]ݯ"֓n kSWn;}/}g˶WCr8wG|{;~?V+{&̧?tʿp~ra*mQ>]7_Փ:&כK;PjdOrVX̡ y ;m,]/ؑ`:l~AJ 'Cs\J 'v:FO"](\p>d8[ `9/Y u.:",i.g65^}k] O@raS$3BT@;d$kYD6/<5UI;rIOՠH*؋~36cv+o$*GE TQy tӞ sT"Վ_[1>ɲ,sX`AuRfjxYyviά'3(Uz"^Kvd"Ν]ߔ!b-zA.^|)3bwܻ]ѕ 8Z"›-WV<2>/nO=oL>M&,|ho=67w>\qnvߒTdX`R8"$|![+ib_K͛Iļt㼘Eݍjn^9阓1qټSyDZ(5յ_y/:̓y=y'RT6a? K/.Б^h/z oš /byd8#;+ߠ,87$(-m[.rl48a>'ZMcq^ہOUHa~%QQ :jPuB<ɒgL p1EBO;gt"j2 ĸq`Lg奉XM9.drGEUY\މ_mHRTMom1뀁I:Q!uTUxjʘnd% )&V0<6ZKX8rh9IcKgHEc%iM*jnQڋhR=w[M=Y '6#c!$q\# :WU {.13P܎1Ͳ`=xϕ@8H %/%2pD9mՈN0 q)Z鶛"b"\Ԉu ',rlnM+G>(z@ K>rK֟xCmoZobv3ҏV1w7َJ`YZ`t\)8ɉiaT?(zd,cm*ҹCu#6ꤍ p+Vɑ%7.DU6o}ёv:?_WQ<ʍO|⫡{>vW_޾йg^_qf-L|sg~ҵ Y.}x1,Bv}& LTرx㢊Ҕ9puCz]dw4G20CAv3+(ʛ1}8j@x,02M~֯sԜ-\(kMHOg9/Ļڭk= h#?7Y8{1 [3]{η?z|o[;(뷿v}坘eG񏋽 7vi/n܁l&}|RIGP*3_AYLo^e m*n%RZ,!"jj2eV )dv, Q .+fj_MvR>p j1Pb󠚻q0ꍨK5mgQe^jiwׅ!W*@ MAb(O_pVGiB<̝ rX9ր16>1q"l;OW0U(|M-X ydN{1bRkUHu usiboag(=up𑞬/B5ȓґlv箥u ٯk_͛{sF_OO~x/]ީGNw{k*/_mo&AhTUB* mh $k50_s[%mm1DKK5S "l >Ӳ/_+;}܉ @U2)[(4* uZM_'̓🅭#bo}g_Ek~{W$UxRwE~` 1pVQ0짶8v[GtMpZpUEtCɰM"tW[ ~X8N{af\tط9@Dx C}>_бu; 6ɜ$t!RF<2%i'yhVq&jۥ G.uJ3o[)׌kgzHle>la.X[vk9;  Z 9Z9V8Z^ݘFF Xh~p,0i AwR8泣}D "4[sL-PV{X{LJRcmrLFtJObq AE5!Bz/|za!l3gŃqЛ {!IjQɵR `iĊ g:!"8T 3 1VUuɋ`?v3$TZhVQ oy|??>_C+gǎ{GOK_t/>Wtkf;:ys皃v[נQQP zZZ;qcB~etRCq~WECOW qn!imlNX2B * "rJtֱW w `KӓEA'x p"4t0ُ ֢ӫ!+k.vy{/SpC~v{7;J?O{K{a,{AЗyaz=7Ke9 "%I, З9k"NX:%] !T,np"h3gI/R:3<}YkMuaƱU^鹟;IVWum8kN rt+e}1i]}g3 btvsdz & `z Hkdz7Xf$3JΩ!>s0Neu,tsLɀc3Uxu/s: *3=tXg35?7r(M^J+ 邞ax6I\t2.$AV!Jrƥ%qrM  +Wz8pdQGy)Q#6' Rȶ[.!XTħt_z&ݘy\FG.yq*F1^9lY/2p;0)]SYmѝ.QSԱ \*dEA$+Ttr`##BĚ4vQZ,DŽVt\*PېQb|qyC-K*,h.4@N.6 (?. pxhDTHARD/prK5w urvhRݜ ӗwN牛ty׭Ϋ/iunͭ>{M[r}.gzv)˞uk_BӅH z|}0^FpErju0n8Z="yzȿ{+;Wʝ\?=P?5w_XpHN<ܿv}AiC;usJ^#E@kTW6BsPeZ:-d$?uBX8AR$e[N.C`t'WRf$1;13=&AoiS7:kI?⥍޵]im/SjIVY"پg`¡X$bBT(+Ui:i `+(.AuBM@T.H+:)ۤPdTsDMJD?.ѠұNQPȉsY:Y) 2EhAYYSuQ !"HN,6u,}jB`3Uk'Z3+`A3ݸ.;傻uZB #V5 2h"vkD DܴfUL $eaOT؅U^M IFL.U$#R()Ov`RRMfe[I>Y=Pg8*BHC4:hh<C`%ē:0A0X*#4F]r+E@X) W$T;L ۱ ,҉Pz%ôU6c=)ֿgo^97&i\y޾pico]k:nm]׮6Wf$V,H*[ը3*'+S8s);b沋 Fu•ʭf!rqn |(C^ !(n;؈e MsaG u``?U8c+u9䮁\ɲOaN;u  D5{$D6Iq߁v#%Y>A$#GդRHe dÝ}aءD!Ni7]#ǨvP614ќ>v+=[E!m‘:hP,ұ,4ǪQ!BT`IYMT+ccA+ QPV'W+6JQm(ќ\iW,iMٹoڢt/Yn%qi:iѓɝOt I4"hsTc ! >Z2@c`R%T̊;>6,'Z:qDݢ2i8TlZ10k*FܩSLZVJ"(9S5KjOKmAK4xuJUCR)C0]xDzWBЋ.k)Ȥc1;Q#\YܭDUI:,Q %(?ǿz/]y ]'>h}+y7o{v>09[a2vsg?=gom_-.\oOֹi̟ԛ:1Xs Y+Gu"[,HRrBS0l+Db6`H, U AIԊZab ڇ; (dcm;x4{;ESݹm9}i֋|s-$,ۼ!/쫟:TYw5ᣟ;Kv<+&ty{]>{˩O~?E1)cW:3s*.Dm?|AVFs jst9P=5OQY6;ыt!'$PV'u1ֺ_*]Tݞ:Q;Σ#Yzss=/Jr7Qtd@QZ8uBEm.7Zw=/j0} r$9!{} :rTI39v+2JgƆ;J:Cw=, ݀hYW¥c[K%4\&7!9.\ՌaʚO5UiWiαiSkw!‘%` qFP'8\4q: ᄵY)K]Q:F F4AIل.bIUk=֢3}1)w0Y#PU*'eAm$*Q$--'j:E))#SP:A{hL HSKZUVmޔը@%;r!FR1b(RB,d -YrDtY B* DYMjv ӿfIXrndIiCAhWeSm:2"*c\0*<%@GkBKb윅 U˅=MwDHu §^ݣ+ W^tw?|sO{?sWƟ}{ꇿ3K>qcxZ1I O6!(K/) i.? 2CqQ+i`+n v4cT;cA5I, eO4UA1`eU]S&t u:@:8mg$L0%v8h=E "bԟ H^./?ʕ;Z?{~~񅺉/6)6vuګo^ow>|cۿlwS?/ "[u}a>?`~3Xh,8˴OF?uKý84}pT9i[ !(,R! YywiDe(P2tɷ\q!ĥlYT_$ä ri)md?p^,K']NgJ2bͮtbo(p^u v/@4GUuݾv+BR[(e` [:&WVNp\8B]g~n53H0[JAvLgIȠ nvOZM":gILM ȥ2a bjkZ9"9tX>){SrpGP@$|AGNu⸐{풗ii3GnT lmPŘz hʐHK|DMUJ£p yQT0zDhJO! FU'kPvst1L4zERwDY#Ɛ,`wZi4F+(*AxoVּ{K{b&|.OHa;x$I'~S) A 5Zb RD6ijЁz3{|Z:Q:a G>ED0 V3__P=7=zkϾrݿ=94k^ yC/J:lN͹Byҥ;k3ܳ,j>Ci].RX+j;GyY/et3+¥)!@U*!9 1j#9Y*:XH2yTH8mdKm6"˕`'QvZGD6)$14 jdO^hL„lUj9w%e_w7xS xxiJGs{t3*a ,%ᬺ+aZ"KNR l:fY9 1 sY4i(GXFՉ65TXBځs&LI= &E8 ͿWgER:(mvٹ;M> Id9 :kSsUoOc)tYPB`ZGQ3gCvpu,mSJmZ܍6[S:ݱKrT4+FqB]+˥E4!*fm4&m%@|6¹nΤBvk,ƠJIE+NH*Oe#*4>b`AD&]b%\{,OX4 u f 0(<ت6B[hW6 ZM' 3NBܩSw#: C"CD:k3@TG@ ]-S!kY06-<1 F=k[4iruB<$"#uBC/xYP/l;3N4⽬SG;0M'@ko_z߳j7w/:N#/_?3/J<㦍C]lYɛrfK qߎiʜ93D:t[;I ".Ar-˕c!rʲf])DeAOy þf8ء@ $W Xt@/tC[pglA0F+}>t%Ɋ5 si&"qGzu??#j-!~Ν\]}?ܫ^N7@vhäcy\ǡE]*N{[݈J7EnJ'TC?4hCSr&b%Zc':G]=T^JY\B 焳& ,Jau'qƥ uNXB*-vwMo!4ʀ4'?m>vc6]ݿċ *>Zx#Β18TpCGm.]Or*HY$a?yږV7nyaeuK^Kx1F` wOΑ[4!̼LҒc?v;|OPMhԘ$V d DcJJ#,9*S8t^ȑ C@ I9 6IѠ/(E{ٛicW>z'66 'KsRUmo lY* y$QT=vڻs]r(mđv /vؙƕ1FR!g׋K>YøO*|3mt wdmu'c/XGj&;LZ&F5ew#OU,9\),8<⽇wkVc7f6tJV#P8?~}Ոp^S`QH"8"FnO('lTG^ ,s۳@92ncѶA ӨP,4^]~o|"CmD&tb̫Rrc&Ȯ·Q:8rBțQQ NHMYPIH0iW<04+%'NZQţoO_BܭihJz‰BkN4*UmZfj%hGK/yoN}o_>t3nwsBpj}c,KB'N&u9T$YR\癏' #J̈KN*P<63Lnzh%G D 6LA ٙЁB LB*F"/$l!ʤ8osNd884 'n^޵P%l}q!^ qJq減E?tg/o]C/Է֤O}}X\i۶Kmړi,Lh2r UчVBu[}:߸Ε,TmD ̭?ASYvW"4j2=o\]?zꑻ<nMp mBF9c/BurjQnnhuV۠0벁u\VPI Oqbj#g=БWon(Δb:hC1&>3G]mjИLhI; ( ۪YG߸yږa vHbr!jM3(.IGO4Q-0rB4lbՂ>ޣnFܮ`\za'lס%V wLP^f^w7>xצclӶ]ZC i y(\bD5$äI빍(^IN8%3GޔK_y5F6ji=r|fA lkc`7Md3u`)RP00j9r/8\q{&}CcϽVUu\{0z隨lUQwji⊗g|O9 #(=V$es՟9Qڑ/|ZؙЉ;[΍.܊xۉx׹k_M5Q`^af m3#@=iv:sQ^gs&昨P!sf=p׊W3wZ*KWwcHBdK%΂x̾ZqP\)+:h9mⴍU8m5SR$pmf!:b:n; VKBZN)dj:BYC҅R9p{l7w썧~Nѧ^+>wsO^S:3w/7@b-۴46*YEB:G.U37^UɕbL0j/×IbGnk0xAS: HHNҹuH[ǪCxv﨓o1 V]"}Z .6CRnAD\r{j3sqjŽipd/__:Tmm7dvf|[?]._o㗾oooķ|,O#9P^m8 phsc۵܍W6'O~gā?t>ɥ2AҤUL2\rh>{Ym_׌PQ@B^,VNA r\V<5G]As[9tNR%j3XmbgH% 2Ti@`3,Jml heV Ų͉u$B*Ǒc{jV:)S5lsOmz[)Ǝԇ+/\7JR=d$H*'eީb^P9å7bAH :*i@983ph[N}Ս[qڭlzt}O&o( 6hɚOG@QRښm6YD7{s\sURL9$$!!JCݶ>mh+-@2UURpᜳ^{o? Ҟ2- aǫtMS2_;xl\ʑIi˯lc{n<+劕lL rLngΕDkTzbJ2CTDXUuD4$Q05 瑂^3j6(b!b3Q.LfeH%u8Ȑ[߸ @5&^U* 8΢ڋ:`~+ `Ao]hkUէ@ޫ귪$52Hc׌Ќ#HEc(gzۺ]F!TYu 9D~;DRkDR],&\Q do(C޼(F mNM7D1o a:" N *U_fXQeQ̍.l;״s'$uh@ |E4yw5g8]$#gX4 G "Fl+r2˅Us ~4) T*iV/uf`"C..HS3wWjq,Pa|IՍIySw7 z]7$CDM`@ @lNQ,b#%zuK1S4n7ќ\e& 5F#OՔC07L7wA)`I4MHgy3 Yl8'b+)]UP`!m/S$ >8-n2^\62ͩa tE0/75;~j#F+Y2'^;c,ϸD[- IScs0.d}2G!4F-< fE y} :,^Qz뚖Zǀq"QI L!פ` f` lWtYv_ThfWU4FEiSZ BE@UyHX<,,o%'NM"3u˻Ky2LwS3PPzElN@㎍yH0A ΡBT CLEyb9:-vc 鴫],XJ["8$K0 x}̂Zq#ቧ;/]t`Ts鑊04pR&V@ȹ&Qs`Lh ʳ&X|bp]9G[fmp`8uݼ.H8 ÇI׷pCWB"؊Txh&b`!4E3s,T&z>(zLWiYP[^ǞF $ૠÇ104ӃZKDk[_0U+{F<HC֚y%XA <(̓3pľ!Q6+O7W-(;6\2ͪ;Lk 9/,\ik" $4cL(⫗ELNKY.N$lL"fq3Y,f1`>8ռTT$KʻJi]_]+2D8k  ( Xh"wCHsyzln Dn kF5!ZI+Mh |MQW5''*[; kX% `npIpZMK#Q&GMNKlRoj G,a slmt 5n\V 52s6Ø@D6v8bs `EL+f[nΔ}+R@ ˕A'ڄӵHQlm|MRy_qTI=K]p{*!"–m҃ /Hƅ?wnߤ}ꖩҦim""Z7^4ef{`g.n^IBsYPE &Kg,1q {U$ʒŒV,n *hp"ʗaP nyKr gߵKD7R%y h1EP+DS#h1"tIMVTƕT=\P%4 F 6+λ=|Ldf vYRQekf(z|%ݳZgl<1IoXIr}(P, PTkӆΊ1R)0jd+b 8>eZ ˒]yPӣe"TwES^,PPK\Ymtw\nO+mS)jKlASE4T\Ds ,y_|*]!uE iam1`Hʒ<"000 bAk["fQRd n4S M\y9-Mmwotu4AEwM@r @C*(:Wce5\>QERL0aƊJsU+kjsx1_C%([J؞[.:ϾtQ[n9X+*`,fl@kR+)Lƺ!AΣOƐִA#ۚR)?}ϘJCA&*T<1})5>)q3!d$e= WcŸ@ U5xٺK~=34ЯUoyuVxXD|ºB\q~G]eu7.ikst Z>9/aw`fOwmXaFCJT ~֚akwXSvzݦCo]/-rcRF jhtIIdLi0 ;8$I#`25i&m^>[dwlhud~Ӣ_DRR&sSt!@5#XB x* 8UM !geIa)E` Bp2AҺ.7a]#r:xu`Nl\Bi⠎uT󀛩R @端U' ,QHqWIjykh?:uHy+L,U?Y80`3(s۽逯^dCGCYF["PUKz?sK[^񋯮~1P9|,>}OӾߵk<1U)_sp?\16OrIY2_:ګW>Ջ~8܂~v|1#}~Ro}u^r~|0Es@v09A[,f# 2ROi1Pt9XiU_ O?}۪U-~߱wg)﮾QL~5~_G7=ND &}53S $d LޜtxdW:p D)"0f1 R$I;vCݹy1Rٹll1_k'7~Kg_~"D4O0t)y2 Տff[0h \ >޷~Uw맾Gw=\|Vgן82>{_68-"$&Q׭|PTTD &PAN)՚cEURD8˸J)R6^_x]ïnxMOuYc86^vٜ LTYkMgqf3􈔧9"2*xlNA3Ǭ%[kۈMCsU5E͂!g}eEuR0DD|雏e4D8ΉʒL3T ,q$$R&m,x 8DX$PY J^R-ۇD ._׿_)Dpa3S7wʧv2zd#&-v 8C_Cf\BFjQuJ><D8p HEc8PTYʂwهo29}sw{ ?gN@ phޟ:'»AbP^| z5`uxFPl u]/AԵ-&;t?b L 6G(e"W_faU궫/̬oNRt6 h]j. 0'6-4'` fVFaPsA[szY,YЊBJc/8[WWOeʙσ``sCgI 6g.e6 blqҚt\BMj*C >uϑgC/:eӹbI{$՚S{;{^=o̔b5*0*#͚LP 8!"$R-WT(O1&6X,pv%?wuH~}YiW|׿سGn}Ł߱C]++*$1 ]ƁYʊy%`^78'P PR%I0& A$,C_?w}߸Ȟ]Otܢkq[$ќܾuÿ}BvGS?=sF0f2@aBOClv@p8F9r&uiJZ,SF _Ab-tƭc%E`ٟ=t4CWmSGs;}H*xndӦZ/.۰o5WmY9 5l֑` %I+>y , .@i(J*jHvLOg-H96Y-KU?+]#ޙ`\8g ̈́DnVzBtuz]eV+, t<@)8p/ RZ>~-l~+e|N;]T|E3SgXMXGz{^MqչkfW%W͑4C 0'aui\e4?{xY0XBz _coHE@~V6S}ݓ<8GһMGz-mюd6}|WSc>=žE+Rã__ S,UXR58xuppȽppڷX3൶;b~6B\MG|r e/v?[R Qf*K]5ƨj4 & [}]#͍=N6v8V%aq镽2oO 9q.HpbbGn_K^8II/i2~I1&cQEil 0 "gp5ph gw*3kcVTf0I^#skϜWa*Yc%a1aWK@נgGCb53E.NȬn#?bm]U8,iݻoO^5'{Rg;3X!0f,% +bfuO LG@BWAYuQA'*D b [07,8r"}g٣#SOʃeg*6Fm7ӓJ. K 䆆׵x8G#n2Т= !K6;(8kN FJ,R@˿;ֶǏ5uV9Dyy'Z>wgXgK^|A'?܈i$h O&<0՘ksw.5(E 0B+#h5 O?O{\ǢJs{39f'O U~?1ȁ%{djB 2 iʊ,D 8NJ"_SȑF A 𵩀uPt8?WzǗo{vס?vѶNΊ1e=y??3H6={hp'޿?T@ 2" lyI>4kczĜ,i51^ eM05r]?|Ֆy gж÷^ٝHNN-oL +7H*4|ѳ9z?է&#ڱ?;]ጣyժј!cƭL.ubsMK~wvœSNy)x乃#}%={6g .5d+*_Qي4WDMQpG4:WjŠ[=a7E-0bqS߫NS51miϻedN]tܴSrPkgvé4LhͿ%i?7] 8r7+c4lyO VavE)*I]p9΍t6 .n;Ylǯ\smyCvwPnЬEb*AQ=+yEcO|-kOOyO}BM%I&Y, d|},qyok-"FxNMy[Z9^ʌuNL9-e~gG_}dJ2o۾zuO}=4(O1&|*2B(V SEe(d" t`۵  W&%[Kʔ)]%4|MEr.tunY4P1jӜǧjzT鲍>ħ)fu6?tmǢpۮ<p8;Wnz`fjhݹx( l-s2vYФ-oܾfR9}(;X(Q% Nj=]ѓ.%V4})ѴG%AYAчK,$5h  ;H5ZTE|^:x[/w\)(mm4t1;uc HzʦӃ/LEN:/_RLYg\]52/Q!"xxCi@@l-[\O<""Sŧ+RK+ʊ\ȗZ|Z-/#3ip=4#kVDRjz|,TI?j `L$tM1L(Yx6nad^<`@b>0PS"0pfN^hm C#=]wސQpTOZ<+)Sv44=v"οu`&'ͷޱi_)Y!͖AUjnY޾$/+x:>xU<{~'̽nk ˹t/t"ѳCzsi= fy[hcJ~uEe&*r_>rT}Zv}^a~b<_;1ٳ}SSM-q[Of "r,|bP DۗϞŏfM'- O77.?q`ʟLNl_|U nw'ݳUnرzT1\}e(=t8pH`;(vՊ1OWu^yXf/Y:OqvWvG{e7]hP|\ˢ>7v>=8vFP!I 4 PU4l[Xt&ݴ44>/;cymg' #Vs dHjdqzp+;.y'ޜ|pjEh1X>9RC'\ 4##1SΙّuN'܉'Knm5-Uztxatxtpo}uw,x{pw|z٨kw?V9vP`_u / e&E_{#*BIk$N}E% I.*L$D8[gǾ-?nuͪt6Wcg_9g~}yk:_؉tS[X<>%ow,)dThʪJCU%I$W @`+JNtLD~e28 ׯyΦEmS1鱴:3j 3͸Ks :Xㅠ fHTG >iyd0Q\˥Uƪ?EE@Sk:!tOk+2. UL*AH0${oYĺ:oSfgº匝؟;\2+raqpv^5^='u0CBGDae_W|r,Ԓ.|Sorf|͊hԱS۶a`=}y !bsAI|iD j" T=ILUK>Ӵաy KÙLK}c8w1":wz 4S?#PYa>z| BW95g܈k 5 40©gwBC' XcpJFf9 c-2CWN'>W_ԼҔ\J' Uv>vM[7u<1,2c|re=;%ʁS ٴF~tp7-O$Ό"$߶ՀROeԙlY˪9!"Z>1asK.1]tiWl_l눧DˊlJ r.e\(ĘY ["ՁfM6/+j(GW'tbD=p?سystyΟ>`J7‰i7W |ntt`Ƿn~H|q@z2f7r5FkWC% ʡobV{ׂ]/guζOZOOcⱯǏT5-,-[NoqvV9y's$O$[>:qΧ^рG!}mn1&̑4(t(pze-GX_:X`x8ibL&ݗ6;t _?:?E~jB%*,ztrU Wvrr_o\5ЉxL눽 f`+f[g[UӞQ5?3L*WwuιZR+"Mm=x 382 & F Pέέιry? !h]^~}%NSαM% a@L7A51޺x״nV9﹪gNZ%VB0<3jӎg+RZs,Y {lk6LX\Mgb#A3+G2iحt\'1}A{;KIwo CLEMerkkl=-P;"Awͳi $;͇3]Z9nZ_:J%,):HTz3VF,ej&06JKF'Rc ▊Ӭ,tܻ,ҚlR\BYF@ \6p6f_{7Tk&.Ig#!ӗc zKg&S# '44TDm['u55c`Qo/2IX\X\Ԝ_0nM2H[.\6ƹD [WHBL3KJ_ZoKܱl,4FKOrdS3$ H() ,=76 $ǢV^|c0J#h' ) nZA܊UG( #8( (MBm'56uTJޡTX+t)ՕD:P f⚮m"V 09oʫ:O%Sf.YT21$j[\TߔL16s-A79oXȲ! s/%BƄRlv"3:4n^RvĤCn#K# `|22]cqƬ2U}q`KtMmfYma `r@%Cƴ" 8 4PI2 L2BIO| @ڼt:20Nw`&P Jaz43KstZhl*vM&TޚJH{h,lϟs^RvXaԳyL\!)'M2`$Y6CĄ(G$adCɵV$T=%#9E]] _mށDhҜI""k߈?RP;ko>= 薉Dhpι"A΁,qqՎ'E@\bf<\] 3'xL7 2n9&hEYK@p@D0gsyV!8C"dsl>*B s@C!kb;BIV0yv:3+q8{Y|Nwϟ&?B 009l>\0as/=/2㽮;\Nop$ף%ӌqzeQ&'.HGS)Mz08₢$!-g ϮO-zl~U;;7]$ŵexjqNHXFz7.kk~f_&SCfRB'9/t8E$}w RbUϹg,|g͌~qf/o3UC@ӝU"_SYM YaFwJ8%pMښ+MLQ$o < ͒:Y(_'Ef=syVzuk/%OSUK]w^Qe]މ3HLz t Q|$6 9YVhH~ͣH8>jٿn ۚ*dZSIJ`*:EF$ܽ\9%gƧtD-=&u_"VGD( * + B\gٗlsePu``MfO o뚼F9/r?JC`Z/+32`䜯i^v22FpDu# E/%68d 09ZFHCq5& >bWĴ-yIs^Wtx<^]|֖_8TSa'<{es~;G, )] "dV0dž^x(k'$F N slhdp%KO\m ֓}Sϫ^ؒ*ݡrOko6^Q]Zls< 8%p.K6dZ) /C@}Ne)MD6T=y^PxH&D=2xd(+C N2l0W|*D)W 2Dn W2;ɱ$p ^ 2eP\IK⓯N^sa~tE% WwjsW6id,͗亶\hQ|M~+[e9Sn("Z+AA"J P&r rsB h| OwNz));[vxyɈj;޵+<:v{mWWND{ڪ]3rT!B2:d)^;qP$n2m$) P&EvT+"P4){,:w}xّCK4U>莬[[?4+*9|d<[_TMq wCo|@%F_WDQMB^:dp)RЭ׆9!׎yv)K}dtJ!×n^]r>)3*QΓ3ak-:p¿9LW;WnYFj˕@rYY?qp}wTRB] 62"%ȱc "pʬ!,r")S6 "*2:$UM›ojWl#qO%8?t+[vrZNE֭k ::vy-{&WķzL@}|[Ã5EƼQ]28m財Kd2et+ . KhE.),\琺Ϯoi8}񹬟,k+R ͡9)34X:Oψ+HheE:jj 1ߺ}qi+r+B-6Y,++QB%W(D8=k>3Kvq xh&.H$myXHscuNLsuUSӷH tS̖3L&PbѺ "g, t]cɲyV)^^V6aj|WyxWJ x@t#uxbͺ#':>7c_H3WI> _giUk+gv^͇8|ۭ+]MñI}rd8>uE9UJʸS^Eyþ59p0a{zoP~pI8ۄ!TQ3^‡_ dcq,xz1Tukd_Px˅GeMWF4y=yd(apjug6fg|-m쮑m|o)@mSr*:9b[&ñD] C:W?}WQ\燐+ kwƣi GFAEk fLjm,je1G8A4;LJZSXeiÏnETn\[|̑]://=u*3[vMegnKSk->ֵ=13Kj?{Ȍ$ 3~4M(J1,p*gͦ ьR܎6D>k5MuFy47X,m|ڑ! K7VvyaXG&g/}wfvE^}gt /gsƘii)p :OH PQ.S%y9ܧ'TVWF`%\=r"{$JeR:5Cy=.D>&&7D7'dx"7yAu8CO^k L?ޯLX`1fCND % M:˂?$G։a.?47ۉ;K7 RPbg >'y˂T37 :V/hSJyfURP?:g/?/5r[Dhٻ]$ [*DeêΑ38%[W$ Bkɨa=%9iߟv!z]t ; 998L״=OVy76ᛛNuNM\T0pe0s: yTLa"9O!fZrSdC[G'o))s/-Tꗶv\}"a丄o2EL[BNeO9㞏W ɶ ?<ԍ-F%8վU{/+-b$8q{:+Q *n^_̱BM]Xr3Kq&[3filӅ$i*_L(YSJS'U>4S೯(!taK𽙌uh?q4!RAA@S C Ef_oGuOOpD=gu bڇ{3TnX!~w}-BPDt+ktr'8Z34i2 PY6F)kh2N#"`<;'jB8m:[R2̝#n}i_`w<.:3'vЃ7|[[bz^{V|ǻVIu%JL9{ڽ:.pJ\xr:Xo$݋I32Giq853_xf: Mn]s7HR?z+LVHW[z$;q-l2=,k'> `HTx|{w:$)\2eѼѣ׹63ni ?kFW˿!5-㨅b 9ITq$$eeq 􅳉p ;H `[k&_(Qa0dz fƊ\!~MNNM LJos󧡾{/By8TO-;ҕ078Sbfc^9 GdcixΙ_A7xZ߿OtEzL 6v]3oԉ<'ʢع+<7G)NYy2.ml.Ψ)f0 Z>R0-Dơo4Н)+,A( XUt";N%MRVl< P% c֜g-K5!!t$.; pp8bL2t6Yլɉ 룀Hsh YhT @GVUl}?Xm]RVm}{S qyLcz$J΀gϻP|_WhOOrDق <7s{Ob?m z{*Y)ByFgd76"GmZjg3d6Q1UiB)݊6gY9@[xIpo,CpHTTY[ S ~e:/- ="bGy?݁sM EB3:K "(!uɂ(sD ⓙq`&ΘeY`Jh0nE:6O12-SboLk7-Û.k._:doZ9u~kF_|/p"zde'LW|E@8d 1d0MM818pn`B7M4]"q+0N4dɑ]>Oyݷse˷U~"t/I ^I)ͤ kK6Ѝ9Z$4\P0r57xlcєP#B0a L̜MD~372&xSCp+s_xT£^~џ>styU#CPD j6]\` "d))f H(]7 aL51LN @j8O3qTؗ;_ կqR3{nk/[`N[}%*jw( l4eB_Xf]0"A8cb FLD\4HiS P G5iGܑ8̗nZs.).?4* 7z.-Goyؚmh`*"@6G8flH&'5 *P8,GαDLg6@" Ph( w}^OiMM_olZ)*aR9kV{$UG"u907]SlLհbO -W;`+IY|AA h} hY3Y_ ;'} "j&Nu^s;W_?wM <~JNJ]]cEn12qHrs䶦BI(e aA82AKd!̂qMNX,~v*#iNw7d|:G|*q=G_/[So^7FnH8AP79Ms X3Hl0`V)r(S{@&( be=O;V)@Lc#A @uq*@:1eƬI \[ghɳk^jG ܧ 8=Y:n m@RgxBȂ5Kȭӽ|a^5HrCG eP\^w$fM G ]啎;Eeww8ya[9˿xyyJVm~gwG}k|h&ΕtI{r"Ǒ?X-[ Ps%rn33$X tXRdK۾'D޻lĎ}.XUXZ,rٖ-޹9>0dqyۇф998qPDi2Șd[-h뤢@TF690tdsݲ4[xys;FpM(i wl-sLJ?6X||,y9mӃ)gz[.,y̶C`i]4{Q&@"$N ^ L ETu< RMPXEu)3\O>޸//-߾+}_VLL]Vo?VLYirhTFpKs~)Y"9R-{@@$Pt2 }EuwJso:;WR+/>oTG_Rli}s?6swƔxF$+\S&sܐ 8㠙\"H %A7i:HDg4nYAx<|%9He7?;O׽w+6^yz;i]Gc NS@\y909.M] (̳~c]ԏuJ'YOAs@)0MeG`uI 0fV/~sg- 2O런͔ =db4bG#ZT2w%(}|%G{Bʷ>iY-ӿ:J˽ݳwwW%Q&p^Dr*;߼7tƺ7?UU?{~w.]U\qѧ)$>,iD00L"J"d QkamKϿQ?µMcTvxAr}Tr*U^5gޫ~oj(U8ܴA1Hr@$e30smPK2ESu @MO Ee<6:}cNONg~}cB9KΩw86&:xcS1wbqIH/]\ԛ%+y&#I3:ˤBαSdw;u Q3da&蜇S,339,P ,AK/'W}GCvP*ĸty p&?G~<Dͽ_XiZO&W } ỳLf@c䖖 D3Ac@d0X`Y79!>嶢߮'oONKb'l4 -,~_>xņcur;o xP}yY%[=F-6?zŕ\KPBwx蠚,C$R:f̔b)T*BPcJ]b Tzy%}k[ZVGfB=rG:Z:DsOD~7;C;i޶ }6{|2@g81{B0e 9f9bBĄfZAu613^lRԢ6ұW*Kç" GnԴPTu{㓉K7vOӯ]zGI[%[_|nrIӿo_[ 8ptJPip sX,!!$ s# u08lr raê_w*_-+W7t裁w~}cx8K ΫmdBL֮W^ާE/|m{O}?W68~a\Dw' "I%B6hLh0. 07)J-Aڀp4P>'dX:ҢWrg`|_/FҢ_hʞxd7xvwLϼqkzI[L-[R[}=IR]jJY"&ª.{e0Bi̭PdI3U )c  %X4Lˊ9/ˡ?bW/vpj[6l}qGVZd?5-\&}IJ U_LcSmg_4.k6""H`)%f'6Y C Aaț oZcK* ?E>4G# P DC$3vJ41;<V˖@uDɑe~hWh3y2'Gqv-^1Msڢ g֥Ϊ(3wbQrp] 4V. xG^:|/?:;7VӉ_Jeo%˶SWugb#^ 'kk ׮$OW^>bFPr0W5Up' MNjmu=^OYh.M=#h֛-;,R_]ku ʶALk։螽oLGgƭjUF+W߰W64O)?Z6?y+kk2401am13}Ƭf yR<HeI*C()]$6S|gXy{|c9:[:Xl3#3 +ꕫKC,.pȤy4Ҵ;ƾɔ*WXFrtM_ep m+ڒ4&֔67弿gē#w,FT԰%9b AT-P^U_vnJ6R*{mMF&ҷs{8;pdznm8sBzMyMyb{櫫^zefotLS%.&z] /ZW̖၉PrV`ܛ'ߛPDYit AcM k߰2ramЎ%R !?zV2vz25e2cRܹOB3-\wղ25.{s+3:}l} zr߿~*W9<"ALfpEĔd!cpՄH,]Xo:jGn`Ow▎],)69؈vI;76jfg1wW%j rkpê Lk0Sv LD" .Dgܥa#Pte pf;%LǏ?QǖeE_m#A4M)et5Al;5[uKΣc7^bI9xy1ߥhonjۻo{Gg(D*#.J( (WBu5&Yಀq[ZD8Wt)6jJKn箮m \x^SwW_*$ ĆBũdה5.]I{;x6wmX81vN}CU^Z[U]V-'lywڢ'|Eݝ *C^hL,mBTUN "I.3kϩ pE8?ɗ6^Tb73fS/j+aIv=.IE(>4L,#;'onrrmWܻЫ f>v^mCSD"i65 b*hw*Hb`QR /ʦGekO8>WB+nrSCLcz8y| sDY4YhVɜ8°ZՅ| xQg*YX|T"̧5ehsI;8ܟU?%ij{זjESue [wyZľT(~w\NqY<#RIUIh"|q?rRߏ )t8VU(f&3&y"F@Eq`n +TOޟ6ӴDH)sR{E4nK]H߼o]{g_ܲm@Tv9J1k4 c6:OErEKcXlEKLE?x.Dن:$G%UhINw쇷DfFU@֝ВRX<Oe4.p<&'qz佮<5}ߺ]gXT~w*C)"!@):$A5d&9%4({;0Y mPhwW8b|bP<Ø!DCiOrj_ēnci̕EiWLMIK!^=1frcEo8?*zJmDX^>եY`:uTC !{CN*3ƛD T]$c%6^P3&sQE|;KeyE10x9fG-׹~*W26 ƌ|IUJ@ id3WԌKz~\\Nvb %h{6SZ7ccQyS#M&MzCPG<528wHڦ"Z,nWLwH &甃&u^g:+92&uq.')9EGz'wG," sݹU@8G#Ѥ\NX`Si$f,&?+X[{sM{̫ꪮhF7@CfHCfB҇L|O i }* jf!4$EO @3vF{S]yל>ν7WU Dw37Y{:[{E&ڎϬ>tvw?`/]w]=42y)`;nv޳Q!䱜e.o ֨C+L- W_{oFPAX~geC9 3-J9sDd[oehg.$wҒ)tOֶ{馂D5ij_L/[kuw(Kqc@~ԵW.}#ϕ ˔zٿCFڕay)v|I\+RA1pb r{.{ҭW~a꯿~r|¹7.A! bj)mӱLh&'g9mQ{qw?Q Q'a"/i+V7_XdL^dnZ{9Խᄑn ݲ]n5<}߱S+i+KnGݽ""$iރ\m7&}[2^_LwrdEq+l$vWΜ^\+77_ 8VIۭǖ/]Zn;p_yg}WE/|҉Wn''B|Zus{XWo\ڎ Á\㵡?5]/^y$?rc}pPorn9=}}4b@wȱśyc/ȞnNd=z(tx+׾}\u`%W^^4\6XH);y_"*ǗVҵ[DE|py}c go6b*щhD{ wxv߻gß:ɊVz}s}#x &_ w_'_xg\}{[kv,vZE5UD0()cHV^F zDl>FXM된)j$?@B}G5 /)-5MCv`Pu~&ڋ]K⍵'YN#k/mlmv:O]t}}lgͣ;Kٯ=~5{/ѧϼqu'Zvƫ7ϯV?hבΘ3sQ+.+uLJc ttҮ'[}O||iPKԹsmq g:˧ӹ.oo}?C'A؃LJ{l+2O߼Qn<|a͝:V+o?O>,>`,Փwߒ/>x 9PqOSϝ~ݍ> WgR6,/vzƯκ}Ʌ u^[]ΖΥ˟=76<7S_YN|7ZiE3!7oHzE>r s~qܷ^ƕK .~S˭)=zzhn:Ͽ376]X_♵}O e]oS/s?7nXRVJ-nX{{=zv,f3c?E^޵sbC 9:/?ߎz޺n=pn͝<}̷߾y枮f{δ8bqyrP~^ФwMaN?x7;yzv?v[x~rpx+/'[[“/mSyD{n7ؗ޸2ū[r)cC7/~8?=Ѕ7vW:K=}f638֣v7co@sn,wDN+:ӽA!;7po\ϝV"NR ؞=әν(|=ͭ\rNލՙn?yԇO9f|"])Kϝ>4-.-;g?-~gon'V OyV=6+W[~m}n=^gwsbqexYݹ5-ir׷g?~jŖ=x:)S睫[gi{s3~no_{/O=~L9G{Iܣ3홵o~o#HgKS{W7dgX%(8mJ~F##*)C&49m,MT7tW:"@T7iw@[4~Yi{za 3 Ivc'>d~V+OZfݽ2JݡkkGe?b6BN_s.=jQDk z啋7AYJʁAߥ}Kz3y}f-vLaL$q7mLbWgՒZdo"97CE4Ew.ͶV5ek3-- 'fFԙ]r;jp랛I<;7݊"(Jl9W߸ ._8mw2'7^8薴MVDݕ L &yNI+ni=(Dþ'{f'gnۤ+pY3yq_%0fNd]̪3j/ZaR<>p"N3Pwefa9.}+~~^qsmf&vl^=ZI<$+w2}"9+"vOR%XS}=ԩ'JٗߺL*ݔf9aCNk1TكH0R"RR86{i !*Ք)o[l?XvwwߕCn"6cn1 D-C)Q&.T$~抈Pn K rUW5:@O5DJ0H!J`A)3NR^柾yO~l(b;˟yIӊm"a*E,/v^cK{!UU!E%uJ)0pm)S4 G"FZ'oJ뷿~?Os͔qűpH">!x0 %x y9ְ0~MԘ¨sB*5 cC(JmY'"Cns'ꟾCfs?vWſ=sw_z,3Si1r@ʹ"(Ւ8%bVQ1d V)D;4Vh=/D 77+×RU~%S<U5btKp<ʨ|ڑS']›KMY50YԔdyޡix(\+ $N?u'D%aDID$(dUA$X""E-e8 fD<p!Fqm/8m-uB@( yD6\*pD\*"h 6LY…R @B -CB]Hn"6{(AI*D?Z~O=FlǺ23L*:1yA+l^sq!I "ҺF!DOfʂ*Y YP$@C"f)lr*^(NGcdA66ݵO_s׋S0lLb#k JjzU)DFAE@ bb**!@D4,51 !"xu^P** yˀW( $'[^zaNbl@6Bb1P* ($6 r'E XLAV 3z6Ǔ'G` ĩaISMN^`.`{U CH!{Õ]F\l .14X1ԇ#֐x5`TƋg&;-s|%(8U)5bU vNV1^3 OKՈɑQd ޑƑ F sizQ3\T,^8Խ|*+$&")E99"z#gd0p 1^=. P-:QU((I)s):1}H႙^=Т"CG&l%`P&D_ދy(PH`%xcXG&"2D*@ZJNUB hI$FJYSs}۽~wN[ i-<D lflC$YzdAx ^abc!.[hl)SJN:3-"G jIP52z"+ށa}wǎ'!ۀ\aV&jFTf w{0r#eQeC!cث 8V.##v, Re,*A#RB>Z_8ϵN-F6YK!GgLٓ9DHWauI"!u+y#رFd&5ꉭ@mD zUR+< ;oΧC+ DF}@Jj%BIޓedB)w)yUbʆ=<`HUH13:!sz/x\)2(D(R%2es}x}`zq$, "E7B S~e S6G8E Otb[o^zs1h!Ի`C#,rSɂ8 vBJ;U4iiG:R];Q2=+шQ_yETw"k_YH `@B N9I-9Eg k5`2B``},XђX&T))Xqk.O@ DkDJa(Dɐ+6JQ ^(&p9Ld{ Y!+Lq=ͭ3lp8klƴ:C/,»| /pST)*vL\(l sxAB\G`f&LThKچIq DI_y(c6W0/PǷ%5ldx#CZmsҚ c:0z9RJ# +G)o^FFoFtuH|4C4=M !tuc@6xuڠT;$O2gΛ܏Uʶ3Ah$CiDhP~!Y~4h|lաzS05Ċ$0I]iu;#f"B椞%&D aMF+$j%ֆ_I(]ٕC"6X*$Uz`5X+ 15e]ʃֿ=%iϩֶ4:&@NhZ%2:UC4Tǯ&M(0zאEv(&Qm}/)nIѡm$ִ`FnL;nAJVuo]M#!zOsf.|=H_"* 5DѸW_$rU  xix@Ճ$51G?M85n}QFj舢GI NBf% $>PG6 U|!(yG$hzt盛 !QhJl3$bFqak(Y)^UT:а^'BlࠁFWTH-N@ @+5"HSC jʜdNو(-z+TQe5(ܨgBo.pNrR-K-a"6ġ&իB}z~>)7ZH T 1WL2ѪG/2&T)ai6 buJ bc->?kJ UEl)^T.'- 5_F3>^T }7{r72MBL%Ɖ:/eJ NPä !6Z T0Px+wT a#Ci̞\ dk)ZJQnR- &6|ПNhXJC2fIt|5k 2vlcW}vWƛS5Z&va(jQH V2 `DLmIBpjqr` 5<L,ҝX1:" U [f4Q神NZSUIgk _}zkNuKMuꑒ)p3qsaq:"oGiW4v¥ 9ք<ωdthXkG.)mķ)@T^nD]SŃirD2,&;5I8*aʸn'K@Hi٨}C 'W:5\]\KO6  4H( TpbbAgKC -#WmnBm'{ƖJ&@bI0ȱSEbF!#%RU|u"ٺĒzv82!CLB#$!Yä!0!w"6Њ+2物(2Teɳbt%B_@CPxA: 1&IFl-F?Aj=T#ǔ"9D* SFxtd/9ȇݦ:h3 D^׻ Z6-FGLU:o3|~w{ԻSک6sMSiГ*:{5""FUfMO?A64ak ׇsmJILjRL`\bM)!PsPU*h& #AIHwȒ@u\qjb%VG%K;)? ?I=R" 5wN&),ql*@XշkdʼEkF1j۫QV_\ $fP\sEqi-\#NiK%|\=cg7 2sr.=1Ȏ4rHW7 <È(fuR*+f18 ̘"ʜV(Uj$m tbRCm b`X"Չ_BۆReFK'wiH@ 6 Q{dD r&(VJ Y N9{5deiLlc* "I-`d˹B (h#:ȸ2Yq+#K 2?x\@7۠8$,cGZ.:襥wټ/Y5C6$_ ]կ0ot0Nɡ=DmEF5O],8oą(UQqN#1#76hd/6:PȎb-),˜Tfz49څCj#?0Qt@_0UB]ʰ@t cCBX~4?/x54iJ7IִzȨ@QU]Xb_ۘ Ҩa'*e-XZ D\pb\-"DonEs cfhT.֗X9E(50\'qdTo%hhg1U ""n|VlxL1:M*^Md4IJ`,Q) LD1)P:u B3%Tu/XZ29Fdu^%XlL\Yxú L4¨L"L+u,"4fܫ iD@lvR#83cL"nbr'[^&qaY1<ׄQT+MӴ|8U;>nhF,u eCN|DTjc1x[>!Bq}M#$h{}EwbnetXI˭K!]TSr+Zfj)R{fʦT;r4:Ԡy5{)NԍR#-_[;'2rd q>Ŧ;x5EucbsʛK{^#CJFѣHP/ "B'LG=$LqT㴾nlkLgݰdWa"у!aNDo"Kc;|bG ,C[)P/22;0w&ND7@l6U&!̜:i4 *_#FDeG1_ QW LpM-uj|G)e7:"'8Ƶxf¨\E\2l#F1DGkz‘^F :R, PU_㈎V6#e34X6jj'aTa֚+6&|+y1>M_׹;'wnSSЈ"G<90jXO}p5ף#6}#e˕rj[ф,F6ϕc1U8ي;/h7G2{vC])E,=Š׮ʔ(2`8;EY X W.!4Oˮp([Q~Bt1uqȶ};mKG? T[GJm^';NHiݺӴ`r?ID=x5?D:Rԫbp)Ncjt01{+:|A7zw:F)[iQI?C4e[܆+ߘ<)y\U|>B̨DCymɟTb:%ps0x?>ژ]WFtQI#q&0ƫU҇4@"a 1zETOv׹+0AuG{vJSD*"U3j(wҡQ΅Ѩ}>?J"zUKD;\RۼeʝE9A:>x1e2Ϻ=&vEPoƪtgO{eNH~:ݽL{[ϓ>8y\lHQ~g⍍h4.TR g/#*T)Ȗi"R48T'1Si^YE,+G '"cL]@ʡf6uV ]fnvmnlCS+izdx0C*߉qT&M}=KMv `M/8"IE-QXeTɭiH1F]JQHFߢUVs̝ts$*t, 3~hu&zt:_Xp5*mIg`G_cd%-BqX|g]r;ojME'ζ6{7[=wM*'0,>Jxuj\?:F$b 񠏪:~woG%7ZmB@x+8Ƒaey51W͎2455qT<}> S-JSJ?!l \페Bvh;X?ɞǣ)QpIatG?ѥKY0bqByDvZ4BAW}1Ln/˲ߴj;}.gS~/O!xx@K `ݓi }C~ћ-C\31 й{6&a$9>CNƴ4軆'x  ![櫚Jo=qC^VkSiɺJ&~$WzX{AwUQ,gK;^`kCBu;y H2쀉winF~ḿ49M׈EsIñ:fTk@B_Č7FQ\{!Vӭ4γ vN?jyW%S2TxVٺ*?#>C$۵'|EZsʊ DX9PBɾ//~+y*<ɛX0>&č ?BY|1:6s_I5LWLqpq¤ur+nZeIW ϵWX E{??[]Im:1Tcep`dJ#I>/>0m*|u ` u|{R sX+ordErgZ~V}6~>H=ESnAS8ẹwإm  )c,n6q`1U?(fiԭW@hE<՛](i4Tej}s/sEw7J.pFSN HG((8]n trVO<ƙvUXC{S-=n{⾴ˮؐfv囝̖gMg~irՕl!lsCMP]zGԽ"|Mxb(L=m pRZl$MVܲe|hE7dA"d'S;3ƈ;Bs[c/5j6ȑ٥YyEJC{Z鼙h^YVN:C}܌MŤZq a iG_WCV)b:dSٙ6r*Sckx,2x cc 0*2LAx|*DQwJ*x =L)9n0qR5MqX6D*R7`/ WCel*V[RQ1q`G( Z:ø0;V8Tק,)'PSjo1܌r<sdܧBBpvsߙ]\$nB\5Zi,(6WŽ03Dg5ӓ)wDt%A2XE0cHQ+yWVv·l1Г㿏~S:W s(EQ` KP%TEH7 uRM"g$_bJdyĴپ8ty߼b%Rp00sn,:XC=PoPuZVR-Jcpq}J#B.l)R_ |tzY*9AFi_glV.Z4mA ΂Y8I+[wȇSzoObj1=ߤ.,cAVS} kz niz}uq! /]|UȂF Jf>D0I+o:TDZ'$í:LQ'y?eGKtlm|&򯟰@U_eA'FFFKJ1;>Z^+#7MUrquCEu`\UCZvRbj4v,B%D%{lSQeu OnR/Q.9b4D0yގmNs+K9^ b-{H2cH[p3_,{H5dGP ǶzH[.wʍMdUA[L]c}R U0 pR~S0 $eze%9nrp :N9<Xm7VR՜֧I=e octQ̹]%iDƱb6F]*%CH&Lt\ %>$T}O9Ob$] Ȅdf`UpW׶S:Bv < jIjD1CM2{Jd~/ԍDNzUd#deL-'uֽ?3]!.zY2$d1`uź.71$ͤf׀C; f=)eS<^k0bzb"x&&Mnr,3;]كg5xd$mF})dR2 ),1 LwJإ/qU}>{ʲTp1WTL%rlЬVhYUqd< Xf{s&69=ZAJ<) M}:d/v&s l=&w (O^;VC7;+6r68>'Yp͈6ZAc; /)!D j.?(h~WO}fuGFy*ɒ{9xv h>B^nX6~&mhN J3*N$Pdê|b)Br+42pǗ4nWgIr6$f)8(DCa ST[AB-l[$(suցׁtu$յuKbޫ+Yڛo . Xps֭ }Mݞj(g1Hvuȹ M?dd]<+~uDΦeʷ ԔW>u&}?teep_Z)Y.uΣଶϳ6# 0`_sYwXh Va7S;5hj Dw@3z7/2N;6w6崐7+nV<`-Y-lQXQ}?#F^|vky" T0$bQI6>>B-1$m9j ɤZ=;9`um{#rhIENDB`instead-3.5.2+dfsg/themes/fantasy/menu.png000066400000000000000000000014201467622671600205110ustar00rootroot00000000000000PNG  IHDRaM=sRGB pHYs  tIME (}tEXtCommentCreated with GIMPWPLTEU2V1d(}TYW[7W`#c)U0U1U2V1V1V2X3X4Y3Y5Z6Z7[6[6[7[8\7\8]&`!a']!`'a&b#^"^#a"`&^'`#c(f(]!_%_'`!a#a&b'c(_#_$`"d(f*`#`$a(b$e)c(g&g(h&f'|T}TW{R|S}T~T|SUW~S~SW{RYYXWUn tRNS LbKGDV HIDAT(m岂P7l[ ;2|bvFȜ`[:W`8N14XYFL^aeKz{=Q RyKu4Vf"@`eY,4TT8^ 1Eۮ 춿>nSc!*~HIENDB`instead-3.5.2+dfsg/themes/fantasy/theme.ini000066400000000000000000000013601467622671600206450ustar00rootroot00000000000000;$Name:Fantasy$ ;$Name(ru):Фэнтези$ ;$Name(uk):Фентезі$ ;$Name(es):Fantasía$ ;$Name(it):Fantasia$ scr.w = 800 scr.h = 600 scr.gfx.bg = bg.png win.col.fg = #00CD00 win.col.link = #CDC673 ;#9ACD32 win.col.alink = red scr.gfx.pad = 8 inv.col.fg = #CDC5BF;#FFEC8B inv.col.link = #CDC5BF; #EEDC82 inv.col.alink = red menu.col.bg = black menu.col.border = #CDC673 menu.col.fg = #CDC673 menu.col.link = #CDC5BF menu.col.alink = red scr.gfx.h = 384 ;scr.gfx.mode = fixed ;scr.gfx.h = 300 win.x = 60 win.y = 60 win.w = 514 win.h = 464 inv.x = 645 inv.y = 16 inv.w = 127 inv.h = 508 win.gfx.down = down.png win.gfx.up = up.png menu.gfx.button = menu.png menu.button.x = 645 menu.button.y = 545 inv.gfx.up = up.png inv.gfx.down = down.png instead-3.5.2+dfsg/themes/fantasy/up.png000066400000000000000000000016041467622671600201750ustar00rootroot00000000000000PNG  IHDR sRGBbKGD pHYs  tIME 82G!tEXtCommentCreated with GIMPWIDAT8˝MkeyMz$R@5bde7j!KtE'Џ ]EF6Ѣɦ% I͋y'`nP 660賅d n/nZެƇLJWOv=+zE@DL (YZaV5CãrXkDb7rd,0*&5Nۨ: KW:rʹ"@"WItXIR 0&hNaZ̊pG_`g=zn>+ׄ% cnT7>GE?W%j? Φ w$k}x@#g H&u)2$$wf'7wPmh4r2auv"oJ(_ŵ˝9'ۇ]e>A6UN:@{8wN_o*ɇT$ =%i˟o[ [uSc+Lq (IPS,H&$:^X!C *%Pp4'=l,@l?Ql13(#GP?sgk3K 'ZFAqU0" $ 9Q)'ͣ?/lGوNJ XP-)B6 /~KssrkIENDB`instead-3.5.2+dfsg/themes/mobile/000077500000000000000000000000001467622671600166445ustar00rootroot00000000000000instead-3.5.2+dfsg/themes/mobile/bg.png000066400000000000000000000061261467622671600177470ustar00rootroot00000000000000PNG  IHDR@pq7bKGD pHYs B(xtIME4 Wp IDATxA DQ{A boB"3qjn   @@@@000   @@@000    @@@0000   @@@@000   @@@0000   @@@@000   @@@000    @@@0000   @@@@000   @@@0000   @@@@000   @@@000    @@@0000   @@@@000   @@@0000   @@@@000   @@@000    @@@0000   @@@@000   3 ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `@@@0000   @@@@000   @@@000    @@@0000   @@@@000    @@@0000   @@@@000   @@@000    @@@0000   @@@@000    @@@0000   @@@@000   @@@000    @@@0000   @@@@000    @@@0000   @@@@000   @@@000    @@@0000   @L ` ` ` ` ` ` `W" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` 000   @@@000      LIENDB`instead-3.5.2+dfsg/themes/mobile/theme.ini000066400000000000000000000006211467622671600204460ustar00rootroot00000000000000; $Name: Mobile$ ; $Name(ru): Мобильная$ scr.w = 576 scr.h = 1024 scr.gfx.bg = bg.png win.align = left win.x = 24 win.y = 16 win.w = 510 win.h = 768 inv.x = 24 inv.y = 820 inv.w = 510 inv.h = 176 inv.mode = horizontal-left win.fnt.size = 18 win.fnt.height = 1.2 inv.fnt.size = 18 inv.fnt.height = 1.2 menu.fnt.size = 18 menu.fnt.height = 1.2 menu.button.y = 1000 menu.button.x = 552 instead-3.5.2+dfsg/themes/wide/000077500000000000000000000000001467622671600163255ustar00rootroot00000000000000instead-3.5.2+dfsg/themes/wide/bg.png000066400000000000000000000046551467622671600174350ustar00rootroot00000000000000PNG  IHDR?P, pHYs B(xtIME ?؋ LIDATx1 1 >QRl`%~y+@G|$  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4h0`%  4hc)IENDB`instead-3.5.2+dfsg/themes/wide/theme.ini000066400000000000000000000007001467622671600201250ustar00rootroot00000000000000; $Name:Wide$ ; $Name(ru):Широкая$ ; $Name(uk):Широка$ ; $Name(es):Amplio$ ; $Name(it):Ampio$ scr.w = 960 scr.h = 540 scr.gfx.bg = bg.png scr.col.bg = white win.align = justify win.x = 48 win.y = 8 win.w = 664 win.h = 524 inv.x = 780 inv.y = 8 inv.w = 144 inv.h = 504 win.fnt.size = 16 win.fnt.height = 1.2 inv.fnt.size = 16 inv.fnt.height = 1.2 menu.fnt.size = 16 menu.fnt.height = 1.0 menu.button.x = 936 menu.button.y = 516