uligo-0.3.orig/0040755000000000000000000000000007723003535012140 5ustar rootrootuligo-0.3.orig/uligo.py0100755000000000000000000022610607723003524013636 0ustar rootroot#!/usr/bin/python # File: uligo.py ## This is the main part of uliGo 0.3, a program for practicing ## go problems. For more information, see http://www.u-go.net/uligo/ ## Copyright (C) 2001-3 Ulrich Goertz (u@g0ertz.de) ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program (gpl.txt); if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## The GNU GPL is also currently available at ## http://www.gnu.org/copyleft/gpl.html from Tkinter import * from tkMessageBox import * from ScrolledText import ScrolledText import tkFileDialog import tkFont import time import pickle from whrandom import randint import os import sys from string import split from math import sqrt import webbrowser from sgfparser import * import clock from board1 import * # --------------------------------------------------------------------------------------- class BunchTkVar: """ This class is used to collect the Tk variables where the options are stored. """ def saveToDisk(self, filename, onFailure = lambda:None): d = {} for x in self.__dict__.keys(): d[x] = self.__dict__[x].get() try: f = open(filename, 'w') pickle.dump(d,f) f.close() except IOError: onFailure() def loadFromDisk(self, filename, onFailure = lambda:None): try: f = open(filename) d = pickle.load(f) f.close() except IOError: onFailure() else: for x in self.__dict__.keys(): if d.has_key(x): self.__dict__[x].set(d[x]) # --------------------------------------------------------------------------------------- class EnhancedCursor(Cursor): """ Adds the following features to Cursor in sgfparser.py: - comments from the SGF file in the current node are automatically displayed in the ScrolledText widget self.comments - It remembers if it is in a 'wrong variation', and correctChildren returns a list of the correct children variations. """ def __init__(self, sgf, comments): self.comments = comments self.wrongVariation = 0 Cursor.__init__(self, sgf, 1) def displayComment(self): self.comments.config(state=NORMAL) self.comments.delete('1.0', END) if self.currentNode().has_key('C'): self.comments.insert('1.0', self.currentNode()['C'][0]) self.comments.config(state=DISABLED) def correctChildren(self): if self.wrongVariation: return [] corr = [] n = self.currentN.next i = 0 while n: c = n.getData() if not (c.has_key('TR') or c.has_key('WV')): corr.append(i) n = n.down i += 1 return corr def reset(self): self.game(0) self.wrongVariation = 0 self.displayComment() def next(self, varnum=0): n = Cursor.next(self, varnum) if not self.wrongVariation and (n.has_key('TR') or n.has_key('WV')): self.wrongVariation = 1 elif self.wrongVariation: self.wrongVariation = self.wrongVariation + 1 self.displayComment() return n def previous(self): n = Cursor.previous(self) if self.wrongVariation: self.wrongVariation = self.wrongVariation - 1 self.displayComment() return n # --------------------------------------------------------------------------------------- class StatusBar(Frame): """ This class administrates the 'status bar' showing if a problem has been solved correctly, or if a wrong move has been made. """ def __init__(self, master): p = os.path.join(sys.path[0],'gifs') try: # try to load the gif's self.solved1 = PhotoImage(file=os.path.join(p,'solved1.gif')) self.solved2 = PhotoImage(file=os.path.join(p,'solved2.gif')) self.wrong = PhotoImage(file=os.path.join(p,'wrong.gif')) self.empty = PhotoImage(file=os.path.join(p,'empty.gif')) self.end = PhotoImage(file=os.path.join(p,'end.gif')) except TclError: self.gifsFound = 0 else: self.gifsFound = 1 Frame.__init__(self, master, height=20, width=65) self.label = Label(self, bd=1, anchor=W) if self.gifsFound: self.label.config(image=self.empty) else: self.label.config(font=('Helvetica', 24)) self.label.pack(fill=X) def set(self, status=None): if status == 'solved1': if self.gifsFound: self.label.config(image = self.solved1) else: self.label.config(fg='green', text = 'solved!') elif status == 'solved2': if self.gifsFound: self.label.config(image = self.solved2) else: self.label.config(fg='blue', text='solved') elif status == 'wrong': if self.gifsFound: self.label.config(image = self.wrong) else: self.label.config(fg='red', text='wrong!') elif status == 'end': if self.gifsFound: self.label.config(image = self.end) else: self.label.config(fg='red', text='end') else : if self.gifsFound: self.label.config(image = self.empty) else: self.label.config(text='') self.label.update_idletasks() # --------------------------------------------------------------------------------------- class PbmRecord: """ Stores the number of right/wrong answers etc. for each problem. A list of problems is maintained (and stored in a .dat file) in which problems that have been asked already are moved to the end of the list (if answered correctly), or moved to the second half of the list (if not answered correctly); thus the problems at the beginning of the list are good choice for the problem asked next. This list is stored in a '.dat' file. It also contains information on how often a problem has been asked already, and with which results. Three modes are available for choosing the order of problems to ask: random, sequential (change .dat to keep track of correct/wrong answers), sequential, don't change .dat file. """ def __init__(self, path, filename, noOfPbms, defMode): """ defMode is a Tk IntVar which stores the mode for choosing the order of the problems. 0 = random, 1 = sequential (change .dat to keep track of correct/wrong answers), 2 = sequential, don't change .dat file """ self.modeVar = IntVar() self.defModeVar = defMode if filename[-4:] == '.sgf': self.filename = filename[:-4] + '.dat' else: self.filename = filename + '.dat' self.path = path self.history = [] # list of pbms asked in this session, for the "back" button try: f = open(os.path.join(self.path,self.filename)) s = f.readline(); if s != 'uligo03\n': # this is a .dat file from uligo 0.1 or 0.2 f.seek(0) self.noOfPbms, self.pbmsAsked, self.noRight, self.noWrong, self.list = pickle.load(f) f.close() self.modeVar.set(defMode.get()) self.current = -1 self.handleCurrent = -1 else: self.noOfPbms, self.pbmsAsked, self.noRight, self.noWrong, \ self.current, self.handleCurrent, help, self.list = pickle.load(f) self.modeVar.set(help) except IOError: # create new list: self.noOfPbms = noOfPbms self.pbmsAsked = 0 self.noRight = self.noWrong = 0 self.modeVar.set(defMode.get()) self.current = -1 self.handleCurrent = -1 self.list = [] for i in range(noOfPbms): self.list.append((i, 0, -1, 0, 0)) # no of corresp problem, no. asked, # when asked for last time (this is not evaluated directly), # no. right answers, no. wrong answers def getNext(self): """ This function returns a randomly chosen number (with probability 5/6 in the first third of the list, with probability 1/6 in the third sixth). """ if self.modeVar.get() == 0: if randint(0,1): self.handleCurrent = randint(0,self.noOfPbms/3) else: self.handleCurrent = randint(0,self.noOfPbms/2) self.current = self.list[self.handleCurrent][0] elif self.modeVar.get() == 1: self.handleCurrent = 0 self.current = self.list[0][0] elif self.modeVar.get() == 2: self.handleCurrent = -1 self.current = (self.current + 1) % self.noOfPbms co = randint(0,1) ori = randint(0,7) self.history.append((self.handleCurrent, self.current, co, ori)) return self.current, co, ori def getPrevious(self): if len(self.history) <= 1: raise Exception() self.history.pop() self.handleCurrent, self.current, co, ori = self.history[-1] return self.current, co, ori def printStatistics(self): """ Returns some statistics on the problems asked so far.""" if self.pbmsAsked: rightPercentage = ' (' + str(self.noRight*100/self.pbmsAsked) + ' % )' wrongPercentage = ' (' + str(100 - (self.noRight*100/self.pbmsAsked) ) + ' % )' else: rightPercentage = wrongPercentage = '' return 'Number of problems in database: ' + str(self.noOfPbms) +'\n' \ + 'Number of questions asked : ' + str(self.pbmsAsked) +'\n' \ + 'Number of right answers : ' + str(self.noRight) \ + rightPercentage + '\n' \ + 'Number of wrong answers : ' + str(self.noWrong) \ + wrongPercentage + '\n' \ def store(self, correct): """ After a problem has been answered, this function is called to update the list. """ if self.handleCurrent < 0 or self.modeVar.get() == 2: return i = self.handleCurrent self.pbmsAsked = self.pbmsAsked + 1 newEntry = (self.list[i][0], self.list[i][1]+1, self.pbmsAsked, # update no. of times asked, self.list[i][3]+correct, self.list[i][4]+1-correct) # and no. of right/wrong answers self.list[i:i+1] = [] # delete old entry if correct: # and insert new one self.list.append(newEntry) self.noRight = self.noRight + 1 else: l = randint(self.noOfPbms/2, 2*self.noOfPbms/3) self.list.insert(l, newEntry) self.noWrong = self.noWrong + 1 def saveToDisk(self): """ Write list to disk. """ try: if not os.path.exists(self.path): os.makedirs(self.path) f = open(os.path.join(self.path,self.filename), 'w') f.write('uligo03\n') help = self.modeVar.get() pickle.dump((self.noOfPbms, self.pbmsAsked, self.noRight, self.noWrong, \ self.current, self.handleCurrent, help, self.list),f) f.close() except IOError, OSError: showwarning('IO Error', 'Could not write .dat file') def changeModeQuit(self,w,h1,h2,e): """This method is called when the user presses the OK button of the 'change mode' window. It reads out the integer from the entry field, and destroys the window. """ self.modeVar.set(h1.get()) if self.modeVar.get() == 2: try: self.current = (int(e.get()) - 2) % self.noOfPbms # - 2 because: pbm 1 has number 0 in the list, # and getNext will add 1 to self.current for # the next problem except ValueError: self.current = -1 if h2.get(): self.defModeVar.set(self.modeVar.get()) w.destroy() def changeMode(self): """ This method opens a window which asks in which order to present the problems. """ window = Toplevel() window.title("Order of the problems") f1 = Frame(window) f2 = Frame(window) e = Entry(f1, width=5) if self.modeVar.get() in [0,1]: e.config(state=DISABLED) h1 = IntVar() h1.set(self.modeVar.get()) b1 = Radiobutton(f1, text='Random order', variable=h1, value=0, command=lambda e=e: e.config(state=DISABLED)) b2 = Radiobutton(f1, text='Sequential order (keep track of correct/wrong answers)', variable=h1, value=1, command=lambda e=e: e.config(state=DISABLED)) b3 = Radiobutton(f1, text='Sequential order (don\'t record results); start with problem no. ', variable=h1, value=2, command=lambda e=e: e.config(state=NORMAL)) h2 = IntVar() h2.set(0) c = Checkbutton(f1, text='Use this mode as default', variable = h2) OKbutton = Button(f2, text='OK', command = lambda s=self, w=window, h1=h1, h2=h2, e=e: s.changeModeQuit(w, h1, h2, e)) cancelButton = Button(f2, text='Cancel', command=window.destroy) b1.grid(row=0, column=0, sticky=NW) b2.grid(row=1, column=0, sticky=NW) b3.grid(row=2, column=0, sticky=NW) e.grid(row=2, column=1, sticky=NW) c.grid(row=3, column=0, sticky=NW) cancelButton.pack(side=RIGHT) OKbutton.pack(side=RIGHT) f1.pack(side=TOP) f2.pack(side=TOP) window.update_idletasks() window.focus() window.grab_set() window.wait_window() # --------------------------------------------------------------------------------------- class App: """ This is the main class of uligo. Here the GUI is built, the SGF database is read and administrated, the moves are evaluated, etc. Almost everything that happens here has a counterpart in the GUI, so if you are looking for something, take a look at the __init__ method first, where the GUI is initialized; there you should find a reference to the method you are searching.""" def printStatistics(self, showWindow=1): """Show / update the statistics window. If showwindow==0, the window is updated, but may remain iconified.""" if showWindow and self.statisticsWindow.state() in ['withdrawn', 'iconic']: self.statisticsWindow.deiconify() if self.pbmRec: s = self.pbmRec.printStatistics() else: s='' if self.currentFile: cf = os.path.basename(self.currentFile) else: cf = 'None' s = 'Database: '+ cf + '\n\n' + s self.statisticsText.set(s) def convCoord(self, x, orientation=0): """ This takes coordinates in SGF style (aa - qq), mirrors/rotates the board according to orientation, and returns the corresponding integer coordinates (between 1 and 19). """ m = map(None, 'abcdefghijklmnopqrs', range(1,20)) pos0 = filter(lambda z, x=x: z[0]==x[0], m)[0][1] pos1 = filter(lambda z, x=x: z[0]==x[1], m)[0][1] if orientation == 0: return (pos0, pos1) elif orientation == 1: return (20 - pos0, pos1) elif orientation == 2: return (pos0, 20-pos1) elif orientation == 3: return (pos1, pos0) elif orientation == 4: return (20 - pos1, pos0) elif orientation == 5: return (pos1, 20 - pos0) elif orientation == 6: return (20 - pos1, 20 - pos0) elif orientation == 7: return (20 - pos0, 20 - pos1) def setup(self, c, n = '', changeOri=1, co=None, ori=None): """ Set up initial position of problem. """ self.board.clear() self.noMovesMade = 0 # Choose colors and orientation (i.e. mirror/rotate the board) randomly if co is None: co = randint(0,1) if ori is None: ori = randint(0,7) if changeOri: self.invertColor = co * self.options.allowInvertColorVar.get() self.orientation = ori * self.options.allowRotatingVar.get() if self.invertColor: bColor, wColor = 'W', 'B' else: bColor, wColor = 'B', 'W' # display problem name pbmName = '' if c.currentNode().has_key('GN'): pbmName = c.currentNode()['GN'][0][:15] if n: pbmName = pbmName + n self.pbmName.set(pbmName) # look for first relevant node while not (c.currentNode().has_key('AB') or c.currentNode().has_key('AW') \ or c.currentNode().has_key('B') or c.currentNode().has_key('W')): c.next() # and put stones on the board while not (c.currentNode().has_key('B') or c.currentNode().has_key('W')): if c.currentNode().has_key('AB'): for x in c.currentNode()['AB']: self.board.play(self.convCoord(x, self.orientation), bColor) if c.currentNode().has_key('AW'): for x in c.currentNode()['AW']: self.board.play(self.convCoord(x, self.orientation), wColor) c.next() if c.currentNode().has_key('B'): self.board.currentColor = self.inputColor = bColor elif c.currentNode().has_key('W'): self.board.currentColor = self.inputColor = wColor c.previous() self.cursor = c def nextMove(self, p): """ React to mouse-click, in 'normal mode', i.e. answering a problem (as opposed to 'show solution' or 'try variation' mode). """ self.board.play(p) # put the stone on the board x, y = p if (self.inputColor == 'B' and not self.invertColor) or \ (self.inputColor == 'W' and self.invertColor): nM = 'B' nnM = 'W' else: nM = 'W' nnM = 'B' nnMove = self.board.invert(self.inputColor) try: # look for the move in the SGF file done = 0 for i in range(self.cursor.noChildren()): c = self.cursor.next(i) # try i-th variation if c.has_key(nM) and self.convCoord(c[nM][0], self.orientation)==(x,y): # found the move done = 1 if self.cursor.wrongVariation == 1: # just entered wrong variation if self.creditAvailable: self.pbmRec.store(0) self.creditAvailable = 0 if self.options.wrongVar.get() == 1: self.statusbar.set('wrong') if self.clock.running: self.clock.stop() if self.options.wrongVar.get() == 2: self.cursor.previous() self.statusbar.set('wrong') if self.clock.running: self.clock.stop() time.sleep(0.5 * self.options.replaySpeedVar.get() + 0.5) # show the move for a short time, self.board.undo() # then delete it self.statusbar.set('empty') break if not self.cursor.atEnd: # respond to the move c = self.cursor.next(randint(0,self.cursor.noChildren()-1)) pos = self.convCoord(c[nnM][0], self.orientation) self.board.play(pos, nnMove) self.noMovesMade = self.noMovesMade + 2 else: self.noMovesMade = self.noMovesMade + 1 if self.cursor.atEnd: # problem solved / end of wrong var. if self.clock.running: self.clock.stop() if self.cursor.wrongVariation: self.statusbar.set('wrong') else: if self.creditAvailable: self.statusbar.set('solved1') self.pbmRec.store(1) self.creditAvailable = 0 else: self.statusbar.set('solved2') self.showSolutionButton.config(state=DISABLED) self.board.state('disabled') break else: self.cursor.previous() if not done: # not found the move in the SGF file, so it's wrong self.statusbar.set('wrong') if self.clock.running: self.clock.stop() if self.creditAvailable: self.pbmRec.store(0) self.creditAvailable = 0 time.sleep(0.5 * self.options.replaySpeedVar.get() + 0.5) # show the move for a short time, self.board.undo() # then delete it self.statusbar.set('empty') except SGFError: showwarning('SGF Error', 'Error in SGF file!') return def markRightWrong(self): """ Used in 'navigate solution' mode: mark the correct/wrong variations. """ try: if self.cursor.atEnd: return c = self.cursor.currentN.next.getData() if c.has_key('B'): color = 'B' else: color = 'W' correct = self.cursor.correctChildren() n = self.cursor.currentN.next for i in range(self.cursor.noChildren()): c = n.getData() if i in correct: self.board.placeMark(self.convCoord(c[color][0], self.orientation),'green') else: self.board.placeMark(self.convCoord(c[color][0], self.orientation),'red') n = n.down except SGFError: showwarning('SGF Error', 'Error in SGF file!') def markAll(self): """ Used in 'navigate solution' mode: mark all variations starting at this point. """ try: if self.cursor.atEnd: return c = self.cursor.currentN.next.getData() if c.has_key('B'): color = 'B' else: color = 'W' n = self.cursor.currentN.next while n: c = n.getData() self.board.placeMark(self.convCoord(c[color][0], self.orientation),'blue') n = n.down except SGFError: showwarning('SGF Error', 'Error in SGF file!') def navSolutionNextMove(self, p): """ React to mouse-click in navigate-solution mode """ x, y = p if (self.board.currentColor == 'B' and not self.invertColor) or \ (self.board.currentColor == 'W' and self.invertColor): nM, nnM = 'B', 'W' else: nM, nnM = 'W', 'B' try: done = 0 for i in range(self.cursor.noChildren()): # look for the move in the SGF file if (not done): c = self.cursor.next(i) if c.has_key(nM) and self.convCoord(c[nM][0], self.orientation)==p: # found self.board.play(p) self.board.delMarks() done = 1 self.noSolMoves = self.noSolMoves + 1 if not self.cursor.atEnd: if self.board.currentColor == self.inputColor: self.markRightWrong() else: self.markAll() else: self.board.state('disabled') if self.cursor.wrongVariation: self.statusbar.set('wrong') else: self.statusbar.set('solved2') else: self.cursor.previous() except SGFError: showwarning('SGF Error', 'Error in SGF file!') def undo2(self): """ Undo in normal move; undo the last two moves (resp. the last move, if it wasn't answered). """ try: if self.noMovesMade > 0: self.creditAvailable = 0 self.statusbar.set('empty') if self.cursor.atEnd: self.showSolutionButton.config(state=NORMAL) self.board.state('normal', self.nextMove) if (self.board.currentColor == self.inputColor): self.board.undo(2) self.cursor.previous() self.cursor.previous() self.noMovesMade = self.noMovesMade - 2 else: self.board.undo() self.cursor.previous() self.noMovesMade = self.noMovesMade - 1 except SGFError: showwarning('SGF Error', 'Error in SGF file!') def undoTryVar(self): """ Undo in 'try variation' mode. """ if self.noTryVarMoves > 0: self.board.undo() self.noTryVarMoves = self.noTryVarMoves - 1 def undoNavSol(self): """ Undo in 'navigate solution' mode. """ try: if self.noSolMoves or self.noMovesMade: self.board.undo() self.statusbar.set('empty') self.board.state('normal', self.navSolutionNextMove) self.cursor.previous() self.board.delMarks() if self.board.currentColor == self.inputColor: self.markRightWrong() else: self.markAll() if self.noSolMoves > 0: self.noSolMoves = self.noSolMoves - 1 else: self.noMovesMade = self.noMovesMade - 1 except SGFError: showwarning('SGF Error', 'Error in SGF file!') def showSolution(self): """ Switch between normal and 'show solution' mode. """ try: if self.showSolVar.get(): # switch to 'show solution' mode self.statusbar.set('empty') self.creditAvailable = 0 self.optionsmenu.entryconfig(5, state=DISABLED) self.clock.stop() self.noSolMoves = 0 # remember how many moves have been played # in this mode, so we can return to the # correct point afterwards if self.options.animateSolVar.get(): # animate solution self.board.state('disabled') self.undoButton.config(state=DISABLED) for i in range(self.cursor.wrongVariation): # if in a wrong var. currently, go back first self.board.undo() self.cursor.previous() self.noMovesMade = self.noMovesMade - 1 self.board.update_idletasks() time.sleep(0.5 * self.options.replaySpeedVar.get()) if (self.inputColor == 'B' and not self.invertColor) or \ (self.inputColor == 'W' and self.invertColor): nM = 'B' nnM = 'W' else: nM = 'W' nnM = 'B' nnMove = self.board.invert(self.inputColor) while not self.cursor.atEnd: # play out solution corr = self.cursor.correctChildren() c = self.cursor.next(corr[randint(0,len(corr)-1)]) # choose one of the correct variations # by random pos = self.convCoord(c[nM][0], self.orientation) self.board.play(pos,self.inputColor) self.noSolMoves = self.noSolMoves+1 self.master.update_idletasks() time.sleep(0.5 * self.options.replaySpeedVar.get()) if not self.cursor.atEnd: c = self.cursor.next(randint(0,self.cursor.noChildren()-1)) # choose an answer randomly pos = self.convCoord(c[nnM][0], self.orientation) self.board.play(pos, nnMove) self.noSolMoves = self.noSolMoves+1 self.master.update_idletasks() time.sleep(0.5 * self.options.replaySpeedVar.get()) self.statusbar.set('solved2') else: # navigate Solution self.statusbar.set('empty') self.board.state('normal', self.navSolutionNextMove) self.undoButton.config(command = self.undoNavSol) self.markRightWrong() else: # switch back to normal mode self.statusbar.set('empty') self.board.delMarks() self.undoButton.config(state=NORMAL, command = self.undo2) self.optionsmenu.entryconfig(5, state=NORMAL) self.board.state('normal', self.nextMove) self.board.undo(self.noSolMoves) for i in range(self.noSolMoves): self.cursor.previous() self.noSolMoves=0 except SGFError: showwarning('SGF Error', 'Error in SGF file!') def giveHint(self): try: self.board.state('disabled') self.creditAvailable = 0 for i in range(self.cursor.wrongVariation): # if in a wrong var. currently, go back first self.board.undo() self.cursor.previous() self.noMovesMade = self.noMovesMade - 1 self.board.update_idletasks() time.sleep(0.5 * self.options.replaySpeedVar.get()) if (self.inputColor == 'B' and not self.invertColor) or \ (self.inputColor == 'W' and self.invertColor): nM = 'B' nnM = 'W' else: nM = 'W' nnM = 'B' nnMove = self.board.invert(self.inputColor) if not self.cursor.atEnd: corr = self.cursor.correctChildren() c = self.cursor.next(corr[randint(0,len(corr)-1)]) # choose one of the correct variations # by random pos = self.convCoord(c[nM][0], self.orientation) self.board.play(pos,self.inputColor) self.noMovesMade = self.noMovesMade + 1 self.master.update_idletasks() time.sleep(0.5 * self.options.replaySpeedVar.get()) if not self.cursor.atEnd: c = self.cursor.next(randint(0,self.cursor.noChildren()-1)) # choose an answer randomly pos = self.convCoord(c[nnM][0], self.orientation) self.board.play(pos, nnMove) self.master.update_idletasks() time.sleep(0.5 * self.options.replaySpeedVar.get()) self.noMovesMade = self.noMovesMade + 1 else: # problem solved if self.clock.running: self.clock.stop() self.statusbar.set('solved2') self.showSolutionButton.config(state=DISABLED) self.board.state('disabled') self.board.state('normal', self.nextMove) except SGFError: showwarning('SGF Error', 'Error in SGF file!') def findNextParenthesis(self,s,i): """ Finds the first '(' after position i in the string s. Used to split the SGF file into single problems in readProblemColl. """ j = i while j= 0 : if s[j] == '(' : counter = counter + 1 elif s[j] == ')' : counter = counter - 1 j = j+1 return j-1 def readProblemColl(self, path = None, filename = None): """ Read a collection of problems from the SGF file given by filename (if None, ask for a filename. The file is then split into single problems. The actual parsing is done in nextProblem (only the current problem is parsed), to save time. """ if not self.options.problemModeVar.get(): self.packGM(0) self.options.problemModeVar.set(1) if self.pbmRec: # save statistics for old problem collection self.pbmRec.saveToDisk() self.creditAvailable = 0 self.clock.stop() self.clock.reset() self.cursor = None if not path or not filename: path, filename = os.path.split(tkFileDialog.askopenfilename(filetypes=[('SGF files', '*.sgf'), ('All files', '*')], initialdir=self.sgfpath)) if filename: try: f = open(os.path.join(path,filename)) s = f.read() f.close() except IOError: showwarning('Open file', 'Cannot open this file\n') return else: self.currentFile = '' self.sgfpath = '' return i = 0 self.comments.config(state=NORMAL) self.comments.delete('1.0', END) self.comments.insert('1.0', 'Reading SGF file ...') self.comments.config(state=DISABLED) self.board.clear() self.board.delMarks() self.statusbar.set('empty') self.pbmName.set('') if self.tryVarVar.get(): self.tryVarButton.deselect() self.tryVariation() if self.showSolVar.get(): self.showSolutionButton.deselect() self.showSolution() self.disableButtons() self.board.state('disabled') self.master.update() # Display everything before the first '(' as a comment: j = self.findNextParenthesis(s,0) comment = s[0:j] # split the file into single SGF games: self.pbms=[] while i', lambda e, s=self.nextButton: s.invoke()) self.frame.bind('', lambda e, self=self: self.quit()) self.whoseTurnCanv = Canvas(leftFrame, height = 180, width = 130, highlightthickness=0) self.whoseTurnID = 0 self.statusbar = StatusBar(leftFrame) b1frame = Frame(leftFrame) b1frame.pack(side=TOP) self.showSolVar = IntVar() self.showSolutionButton = Checkbutton(b1frame, text='Show solution', fg='blue', underline=0, indicatoron=0, variable=self.showSolVar, command=self.showSolution) self.frame.bind('', lambda e, s=self.showSolutionButton: s.invoke()) self.hintButton = Button(b1frame, text='Hint', command=self.giveHint) b2frame = Frame(leftFrame) b2frame.pack(side=TOP) self.undoButton = Button(b2frame, text='Undo', fg='blue', command=self.undo2, underline=0) self.frame.bind('', lambda e, s=self.undoButton: s.invoke()) self.tryVarVar = IntVar() self.tryVarButton = Checkbutton(b2frame, text='Try variation', fg='blue', indicatoron=0, variable=self.tryVarVar, command=self.tryVariation) self.frame.bind('', lambda e, s=self.tryVarButton: s.invoke()) self.pbmName = StringVar() self.pbmNameLabel = Label(leftFrame, height=1, width=15, relief=SUNKEN, justify=LEFT, textvariable=self.pbmName) self.comments = ScrolledText(rightFrame, height = 5, width = 70, wrap=WORD, relief=SUNKEN, state = DISABLED) self.uligopath = sys.path[0] # the path where uligo.py, board.py, clock.py, Sgflib, # uligo.doc and uligo.def reside (if uligo is installed # system-wide under Unix, each user may additionally # have his own uligo.def in $HOME/.uligo self.sgfpath = os.path.join(self.uligopath,'sgf') # default path for sgf files, may be overridden # in uligo.def self.datpath = '' # default prefix to get the path for .dat files from sgfpath # (if sgf's and dat's are in the same directory, this is '', # if dat's are in $HOME/.uligo (under Unix), this should # be '/home/username/.uligo' self.optionspath = self.uligopath # default path for .opt and (individual) .def files self.currentFile = '' # default sgf file # try to load button images self.tkImages = [] try: for button, imageFile in [(self.backButton, 'left'), (self.restartButton, 'reload'), (self.nextButton, 'right'), (self.hintButton, 'hint'), (self.showSolutionButton, 'showsol'), (self.tryVarButton, 'tryvar'), (self.undoButton, 'undo'), (self.BbuttonGM, 'b'), (self.WbuttonGM, 'w'), (self.BWbuttonGM, 'bw')]: im = PhotoImage(file = os.path.join(self.uligopath, 'gifs', imageFile+'.gif')) button.config(image=im) self.tkImages.append(im) except (TclError, IOError): pass try: im = PhotoImage(file = os.path.join(self.uligopath, 'gifs', 'bgd.gif')) self.guessModeCanvas.create_image(75,40, image=im) self.tkImages.append(im) except (TclError, IOError): pass try: self.BsTurn = PhotoImage(file = os.path.join(self.uligopath, 'gifs', 'BsTurn.gif')) self.WsTurn = PhotoImage(file = os.path.join(self.uligopath, 'gifs', 'WsTurn.gif')) except (TclError, IOError): self.BsTurn = None self.WsTurn = None # pack everything self.backButton.pack(side=LEFT, expand=YES, fill=BOTH) self.restartButton.pack(side=LEFT, expand=YES, fill=BOTH) self.nextButton.pack(side=LEFT, expand=YES, fill=BOTH) self.hintButton.pack(side=LEFT, expand=YES, fill=BOTH) self.showSolutionButton.pack(expand=YES, fill=BOTH) self.undoButton.pack(side=LEFT, expand=YES, fill=BOTH) self.tryVarButton.pack(expand=YES, fill=BOTH) emptySpace = Frame(leftFrame, height=40) emptySpace.pack(expand=YES, fill=BOTH, side=BOTTOM) self.statusbar.pack(expand=YES, fill=BOTH, side=BOTTOM) self.pbmNameLabel.pack(expand=NO, fill=X, side=BOTTOM) emptySpace = Frame(leftFrame, height=10) emptySpace.pack(expand=YES, fill=BOTH, side=BOTTOM) self.clockFrame.pack(expand=YES, fill=X, side=BOTTOM) self.clock.pack(expand=NO, side=BOTTOM) self.whoseTurnCanv.pack(expand=YES, fill=BOTH) self.comments.pack(expand=YES, fill=BOTH, side=BOTTOM) self.board.pack(expand=YES, fill=BOTH) # The statistics window (initially withdrawn) self.statisticsWindow = Toplevel() self.statisticsWindow.withdraw() self.statisticsWindow.title('Statistics') self.statisticsText = StringVar() Label(self.statisticsWindow, height=10, width=50, justify=LEFT, font = ('Courier', 11), textvariable=self.statisticsText).pack() self.statisticsWindow.protocol('WM_DELETE_WINDOW', self.statisticsWindow.withdraw) # load options, and some initialization self.pbms = [] self.pbmRec = None self.disableButtons() self.board.update_idletasks() # read the uligo.def file (default problem collection) try: f = open(os.path.join(self.uligopath,'uligo.def')) s = split(f.read(),'\n') f.close() except IOError: pass else: if s[0]=='uligo03': # otherwise this is an old .def file which should be ignored counter = 1 while 1: line = s[counter] counter = counter + 1 if line and line[0] == 'i': # refer to individual def-file l = line[2:] self.optionspath = os.path.join(os.getenv('HOME',l),'.uligo') self.datpath = self.optionspath if not os.path.exists(self.optionspath): os.mkdir(self.optionspath) try: f1 = open(os.path.join(self.optionspath, 'uligo.def')) s1 = split(f1.read(),'\n') for l1 in s1: s.append(l1) except IOError: pass elif line and line[0] == 'd': # new datpath s1 = split(line) if len(s1)>1: self.datpath = line[2:] else: self.datpath = '' elif line and line[0] == 's': # new sgfpath self.sgfpath = line[2:] elif line and line[0] == 'f': # default sgf file self.currentFile = line[2:] if counter >= len(s): break self.loadOptions() master.deiconify() self.cursor = None # display the logo currentTime = time.time() self.board.update() try: self.logo = PhotoImage(file=os.path.join(self.uligopath,'gifs/logo.gif')) s = 2 * self.board.canvasSize[0] + 18 * self.board.canvasSize[1] # size of canvas in pixel im = self.board.create_image(max(0,(s-400)/2),max(0,(s-190)/2), image=self.logo, tags='logo', anchor=NW) self.board.tkraise(im) self.board.update_idletasks() except TclError: pass if self.options.problemModeVar.get(): if self.currentFile: self.readProblemColl(self.sgfpath, self.currentFile) else: if self.currentFile: self.replayGame(self.sgfpath, self.currentFile, 1) # and remove the logo ... if time.time()-currentTime < 1: time.sleep(1 - time.time() + currentTime) # show logo for at least 1 second self.board.delete('logo') # --------------------------------------------------------------------------------------- root = Tk() root.withdraw() try: root.option_readfile(os.path.join(sys.path[0], 'uligo.app')) except TclError: showwarning('Error', 'Error reading uligo.app') app = App(root) root.protocol('WM_DELETE_WINDOW', app.quit) root.title('uliGo') root.resizable(1,1) app.frame.focus_force() root.tkraise() root.mainloop() uligo-0.3.orig/board1.py0100644000000000000000000006047107723003524013665 0ustar rootroot# file: board1.py ## This file is part of Kombilo, a go database program ## It contains classes implementing an abstract go board and a go ## board displayed on the screen. ## Copyright (C) 2001-3 Ulrich Goertz (u@g0ertz.de) ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program (gpl.txt); if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## The GNU GPL is also currently available at ## http://www.gnu.org/copyleft/gpl.html from Tkinter import * from whrandom import randint import math import sys import os try: # PIL installed? import GifImagePlugin import Image import ImageTk import ImageEnhance PILinstalled = 1 except: PILinstalled = 0 class abstractBoard: """ This class administrates a go board. It keeps track of the stones currently on the board in the dictionary self.status, and of the moves played so far in self.undostack It has methods to clear the board, play a stone, undo a move. """ def __init__(self, boardSize = 19): self.status = {} self.undostack = [] self.boardSize = boardSize def neighbors(self,x): """ Returns the coordinates of the 4 (resp. 3 resp. 2 at the side / in the corner) intersections adjacent to the given one. """ if x[0]== 1 : l0 = [2] elif x[0]== self.boardSize : l0 = [self.boardSize-1] else: l0 = [x[0]-1, x[0]+1] if x[1]== 1 : l1 = [2] elif x[1]== self.boardSize : l1 = [self.boardSize-1] else: l1 = [x[1]-1, x[1]+1] l = [] for i in l0: l.append((i,x[1])) for j in l1: l.append((x[0],j)) return l def clear(self): """ Clear the board """ self.status = {} self.undostack=[] def play(self,pos,color): """ This plays a color=black/white stone at pos, if that is a legal move (disregarding ko), and deletes stones captured by that move. It returns 1 if the move has been played, 0 if not. """ if self.status.has_key(pos): # check if empty return 0 l = self.legal(pos,color) if l: # legal move? captures = l[1] for x in captures: del self.status[x] # remove captured stones, if any self.undostack.append((pos,color,captures)) # remember move + captured stones for easy undo return 1 else: return 0 def legal(self, pos, color): """ Check if a play by color at pos would be a legal move. """ c = [] # captured stones for x in self.neighbors(pos): if self.status.has_key(x) and self.status[x]==self.invert(color): c = c + self.hasNoLibExcP(x, pos) self.status[pos]=color if c: captures = [] for x in c: if not x in captures: captures.append(x) return (1, captures) if self.hasNoLibExcP(pos): del self.status[pos] return 0 else: return (1, []) def hasNoLibExcP(self, pos, exc = None): """ This function checks if the string (=solidly connected) of stones containing the stone at pos has a liberty (resp. has a liberty besides that at exc). If no liberties are found, a list of all stones in the string is returned. The algorithm is a non-recursive implementation of a simple flood-filling: starting from the stone at pos, the main while-loop looks at the intersections directly adjacent to the stones found so far, for liberties or other stones that belong to the string. Then it looks at the neighbors of those newly found stones, and so on, until it finds a liberty, or until it doesn't find any new stones belonging to the string, which means that there are no liberties. Once a liberty is found, the function returns immediately. """ st = [] # in the end, this list will contain all stones solidly connected to the # one at pos, if this string has no liberties newlyFound = [pos] # in the while loop, we will look at the neighbors of stones in newlyFound foundNew = 1 while foundNew: foundNew = 0 n = [] # this will contain the stones found in this iteration of the loop for x in newlyFound: for y in self.neighbors(x): if not self.status.has_key(y) and y != exc: # found a liberty return [] elif self.status.has_key(y) and self.status[y]==self.status[x] \ and not y in st and not y in newlyFound: # found another stone of same color n.append(y) foundNew = 1 st[:0] = newlyFound newlyFound = n return st # no liberties found, return list of all stones connected to the original one def undo(self, no=1): """ Undo the last no moves. """ for i in range(no): if self.undostack: pos, color, captures = self.undostack.pop() del self.status[pos] for p in captures: self.status[p] = self.invert(color) def remove(self, pos): """ Remove a stone form the board, and store this action in undostack. """ self.undostack.append(((-1,-1), self.invert(self.status[pos]), [pos])) del self.status[pos] def invert(self,color): if color == 'B': return 'W' else: return 'B' class Board(abstractBoard, Canvas): """ This is a go board, displayed on the associated canvas. canvasSize is a pair, the first entry is the size of the border, the second entry is the distance between two go board lines, both in pixels. The most important methods are: - play: play a stone of some color at some position (if that is a legal move) - undo: undo one (or several) moves - state: activate (state("normal", f) - the function f is called when a stone is placed on the board) or disable (state("disabled")) the board; - placeMark: place a colored label (slightly smaller than a stone) at some position - delMarks: delete all these labels - placeLabel: place a label (a letter, a circle, square, triangle or cross) """ def __init__(self, master, boardSize = 19, canvasSize = (30,25), fuzzy=1, labelFont = None, focus=1, callOnChange=None): self.focus = focus self.coordinates = 0 self.canvasSize = canvasSize size = 2*canvasSize[0] + (boardSize-1)*canvasSize[1] # size of the canvas in pixel Canvas.__init__(self, master, height = size, width = size, highlightthickness = 0) abstractBoard.__init__(self, boardSize) self.changed = IntVar() # this is set to 1 whenever a change occurs (placing stone, label etc.) self.changed.set(0) # this is used for Kombilo's 'back' method if callOnChange: self.callOnChange = callOnChange else: self.callOnChange = lambda: None self.noChanges = 0 self.fuzzy = IntVar() # if self.fuzzy is true, the stones are not placed precisely self.fuzzy.set(fuzzy) # on the intersections, but randomly a pixel off if labelFont: self.labelFont = labelFont else: self.labelFont = (StringVar(), IntVar(), StringVar()) self.labelFont[0].set('Helvetica') self.labelFont[1].set(5) self.labelFont[2].set('bold') self.shadedStoneVar = IntVar() # if this is true, there is a 'mouse pointer' showing self.shadedStonePos = (-1,-1) # where the next stone would be played, given the current # mouse position self.currentColor = 'B' # the expected color of the next move self.stones = {} # references to the ovals placed on the canvas, used for removing stones self.marks = {} # references to the (colored) marks on the canvas self.labels = {} self.bind("", self.resize) self.resizable = 1 global PILinstalled gifpath = os.path.join(sys.path[0],'gifs') try: self.img = PhotoImage(file=os.path.join(gifpath, 'board.gif')) except TclError: self.img = None self.use3Dstones = IntVar() self.use3Dstones.set(1) if PILinstalled: try: self.blackStone = Image.open(os.path.join(gifpath, 'black.gif')) self.whiteStone = Image.open(os.path.join(gifpath, 'white.gif')) except IOError: PILinstalled = 0 self.drawBoard() def drawBoard(self): """ Displays the background picture, and draws the lines and hoshi points of the go board. If PIL is installed, this also creates the PhotImages for black, white stones. """ self.delete('non-bg') # delete everything except for background image c0, c1 = self.canvasSize size = 2*c0 + (self.boardSize-1)*c1 self.config(height=size, width=size) if self.img: self.delete('board') for i in range(size/100 + 1): for j in range(size/100 + 1): self.create_image(100*i,100*j,image=self.img, tags='board') color = 'black' for i in range(self.boardSize): self.create_line(c0, c0 + c1*i, c0 + (self.boardSize-1)*c1, c0 + c1*i, fill=color, tags='non-bg') self.create_line(c0 + c1*i, c0, c0 + c1*i, c0+(self.boardSize-1)*c1, fill=color, tags='non-bg') # draw hoshi's: if c1 > 7: if self.boardSize in [13,19]: b = (self.boardSize-7)/2 for i in range(3): for j in range(3): self.create_oval(c0 + (b*i+3)*c1 - 2, c0 + (b*j+3)*c1 - 2, c0 + (b*i+3)*c1 + 2, c0 + (b*j+3)*c1 + 2, fill = 'black', tags='non-bg') elif self.boardSize == 9: self.create_oval(c0 + 4*c1 - 2, c0 + 4*c1 - 2, c0 + 4*c1 + 2, c0 + 4*c1 + 2, fill = 'black', tags='non-bg') # draw coordinates: if self.coordinates: for i in range(self.boardSize): a = 'ABCDEFGHJKLMNOPQRST'[i] self.create_text(c0 + c1*i, c1*self.boardSize+3*c0/4+4, text=a, font = ('Helvetica', 5+c1/7, 'bold')) self.create_text(c0 + c1*i, c0/4+1, text=a, font = ('Helvetica', 5+c1/7, 'bold')) self.create_text(c0/4+1, c0+c1*i, text=`self.boardSize-i`,font = ('Helvetica', 5+c1/7, 'bold')) self.create_text(c1*self.boardSize+3*c0/4+4, c0 + c1*i, text=`self.boardSize-i`, font = ('Helvetica', 5+c1/7, 'bold')) global PILinstalled if PILinstalled: try: self.bStone = ImageTk.PhotoImage(self.blackStone.resize((c1,c1))) self.wStone = ImageTk.PhotoImage(self.whiteStone.resize((c1,c1))) except: PILinstalled = 0 def resize(self, event = None): """ This is called when the window containing the board is resized. """ if not self.resizable: return self.noChanges = 1 if event: w, h = event.width, event.height else: w, h = int(self.cget('width')), int(self.cget('height')) m = min(w,h) self.canvasSize = (m/20 + 4, (m - 2*(m/20+4))/(self.boardSize-1)) self.drawBoard() # place a gray rectangle over the board background picture # in order to make the board quadratic self.create_rectangle(h+1, 0, h+1000, w+1000, fill ='grey88', outline='', tags='non-bg') self.create_rectangle(0, w+1, h+1000, w+1000, fill='grey88', outline='', tags='non-bg') for x in self.status.keys(): self.placeStone(x, self.status[x]) for x in self.marks.keys(): self.placeMark(x, self.marks[x]) for x in self.labels.keys(): self.placeLabel(x, '+'+self.labels[x][0], self.labels[x][1]) self.tkraise('sel') # this is for the list of previous search patterns ... self.noChanges = 0 def play(self, pos, color=None): """ Play a stone of color (default is self.currentColor) at pos. """ if color is None: color = self.currentColor if abstractBoard.play(self, pos, color): # legal move? captures = self.undostack[len(self.undostack)-1][2] # retrieve list of captured stones for x in captures: self.delete(self.stones[x]) del self.stones[x] self.placeStone(pos, color) self.currentColor = self.invert(color) self.delShadedStone() return 1 else: return 0 def state(self, s, f=None): """ s in "normal", "disabled": accepting moves or not f the function to call if a move is entered [More elegant solution might be to replace this by an overloaded bind method, for some event "Move"?!] """ if s == "normal": self.callOnMove = f self.bound1 = self.bind("", self.onMove) self.boundm = self.bind("", self.shadedStone) self.boundl = self.bind("", self.delShadedStone) elif s == "disabled": self.delShadedStone() try: self.unbind("", self.bound1) self.unbind("", self.boundm) self.unbind("", self.boundl) except (TclError, AttributeError): pass # if board was already disabled, unbind will fail def onMove(self, event): # compute board coordinates from the pixel coordinates of the mouse click if self.focus: self.master.focus() x,y = self.getBoardCoord((event.x, event.y), self.shadedStoneVar.get()) if (not x*y): return if abstractBoard.play(self,(x,y), self.currentColor): # would this be a legal move? abstractBoard.undo(self) self.callOnMove((x,y)) def onChange(self): if self.noChanges: return self.callOnChange() self.changed.set(1) def getPixelCoord(self, pos, nonfuzzy = 0): """ transform go board coordinates into pixel coord. on the canvas of size canvSize """ fuzzy1 = randint(-1,1) * self.fuzzy.get() * (1-nonfuzzy) fuzzy2 = randint(-1,1) * self.fuzzy.get() * (1-nonfuzzy) c1 = self.canvasSize[1] a = self.canvasSize[0] - self.canvasSize[1] - self.canvasSize[1]/2 b = self.canvasSize[0] - self.canvasSize[1] + self.canvasSize[1]/2 return (c1*pos[0]+a+fuzzy1, c1*pos[1]+a+fuzzy2, c1*pos[0]+b+fuzzy1, c1*pos[1]+b+fuzzy2) def getBoardCoord(self, pos, sloppy=1): """ transform pixel coordinates on canvas into go board coord. in [1,..,boardSize]x[1,..,boardSize] sloppy refers to how far the pixel may be from the intersection in order to be accepted """ if sloppy: a, b = self.canvasSize[0]-self.canvasSize[1]/2, self.canvasSize[1]-1 else: a, b = self.canvasSize[0]-self.canvasSize[1]/4, self.canvasSize[1]/2 if (pos[0]-a)%self.canvasSize[1] <= b: x = (pos[0]-a)/self.canvasSize[1] + 1 else: x = 0 if (pos[1]-a)%self.canvasSize[1] <= b: y = (pos[1]-a)/self.canvasSize[1] + 1 else: y = 0 if x<0 or y<0 or x>self.boardSize or y>self.boardSize: x = y = 0 return (x,y) def placeMark(self, pos, color): """ Place colored mark at pos. """ x1, x2, y1, y2 = self.getPixelCoord(pos, 1) self.create_oval(x1+2, x2+2, y1-2, y2-2, fill = color, tags=('marks','non-bg')) self.marks[pos]=color self.onChange() def delMarks(self): """ Delete all marks. """ if self.marks: self.onChange() self.marks = {} self.delete('marks') def delLabels(self): """ Delete all labels. """ if self.labels: self.onChange() self.labels={} self.delete('label') def remove(self, pos): """ Remove the stone at pos, append this as capture to undostack. """ if self.status.has_key(pos): self.onChange() self.delete(self.stones[pos]) del self.stones[pos] abstractBoard.remove(self, pos) self.update_idletasks() return 1 else: return 0 def placeLabel(self, pos, type, text=None, color=None, override=None): """ Place label of type type at pos; used to display labels from SGF files. If type has the form +XX, add a label of type XX. Otherwise, add or delete the label, depending on if there is no label at pos, or if there is one.""" if type[0] != '+': if self.labels.has_key(pos): if self.labels[pos][0] == type: for item in self.labels[pos][2]: self.delete(item) del self.labels[pos] return else: for item in self.labels[pos][2]: self.delete(item) del self.labels[pos] self.onChange() else: type = type[1:] labelIDs = [] if override: fcolor = override[0] fcolor2 = override[1] elif self.status.has_key(pos) and self.status[pos]=='B': fcolor = 'white' fcolor2 = '#FFBA59' elif self.status.has_key(pos) and self.status[pos]=='W': fcolor = 'black' fcolor2 = '' else: fcolor = color or 'black' fcolor2 = '#FFBA59' x1, x2, y1, y2 = self.getPixelCoord(pos, 1) if type == 'LB': labelIDs.append(self.create_oval(x1+3, x2+3, y1-3, y2-3, fill=fcolor2, outline='', tags=('label', 'non-bg'))) labelIDs.append(self.create_text((x1+y1)/2,(x2+y2)/2, text=text, fill=fcolor, font = (self.labelFont[0].get(), self.labelFont[1].get() + self.canvasSize[1]/5, self.labelFont[2].get()), tags=('label', 'non-bg'))) elif type == 'SQ': labelIDs.append(self.create_rectangle(x1+6, x2+6, y1-6, y2-6, fill = fcolor, tags=('label','non-bg'))) elif type == 'CR': labelIDs.append(self.create_oval(x1+5, x2+5, y1-5, y2-5, fill='', outline=fcolor, tags=('label','non-bg'))) elif type == 'TR': labelIDs.append(self.create_polygon((x1+y1)/2, x2+5, x1+5, y2-5, y1-5, y2-5, fill = fcolor, tags = ('label', 'non-bg'))) elif type == 'MA': labelIDs.append(self.create_oval(x1+2, x2+2, y1-2, y2-2, fill=fcolor2, outline='', tags=('label', 'non-bg'))) labelIDs.append(self.create_text(x1+12,x2+12, text='X', fill=fcolor, font = (self.labelFont[0].get(), self.labelFont[1].get() + 1 + self.canvasSize[1]/5, self.labelFont[2].get()), tags=('label', 'non-bg'))) self.labels[pos] = (type, text, labelIDs) def placeStone(self, pos, color): self.onChange() p = self.getPixelCoord(pos) if not self.use3Dstones.get() or not PILinstalled or self.canvasSize[1] <= 7: if color=='B': self.stones[pos] = self.create_oval(p, fill='black', tags='non-bg') elif color=='W': self.stones[pos] = self.create_oval(p, fill='white', tags='non-bg') else: if color=='B': self.stones[pos] = self.create_image(((p[0]+p[2])/2, (p[1]+p[3])/2), image=self.bStone, tags='non-bg') elif color=='W': self.stones[pos] = self.create_image(((p[0]+p[2])/2, (p[1]+p[3])/2), image=self.wStone, tags='non-bg') def undo(self, no=1, changeCurrentColor=1): """ Undo the last no moves. """ for i in range(no): if self.undostack: self.onChange() pos, color, captures = self.undostack.pop() if self.status.has_key(pos): del self.status[pos] self.delete(self.stones[pos]) del self.stones[pos] for p in captures: self.placeStone(p, self.invert(color)) self.status[p] = self.invert(color) # self.update_idletasks() if changeCurrentColor: self.currentColor = self.invert(self.currentColor) def clear(self): """ Clear the board. """ abstractBoard.clear(self) for x in self.stones.keys(): self.delete(self.stones[x]) self.stones = {} self.onChange() def ptOnCircle(self, size, degree): radPerDeg = math.pi/180 r = size/2 x = int(r*math.cos((degree-90)*radPerDeg) + r) y = int(r*math.sin((degree-90)*radPerDeg) + r) return (x,y) def shadedStone(self, event): x, y = self.getBoardCoord((event.x, event.y), 1) if (x,y) == self.shadedStonePos: return # nothing changed self.delShadedStone() if self.currentColor == 'B': color = 'black' else: color = 'white' if (x*y) and self.shadedStoneVar.get() and abstractBoard.play(self, (x,y), self.currentColor): abstractBoard.undo(self) if sys.platform[:3]=='win': # 'stipple' is ignored under windows for # create_oval, so we'll draw a polygon ... l = self.getPixelCoord((x,y),1) m = [] for i in range(18): help = self.ptOnCircle(l[2]-l[0], i*360/18) m.append(help[0]+l[0]) m.append(help[1]+l[1]) self.create_polygon(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15], m[16], m[17], m[18], m[19], m[20], m[21], m[22], m[23], m[24], m[25], m[26], m[27], m[28], m[29], m[30], m[31], m[32], m[33], m[34], m[35], fill=color, stipple='gray50', outline='', tags=('shaded','non-bg') ) else: self.create_oval(self.getPixelCoord((x,y), 1), fill=color, stipple='gray50', outline='', tags=('shaded','non-bg')) self.shadedStonePos = (x,y) def delShadedStone(self, event=None): self.delete('shaded') self.shadedStonePos = (-1,-1) def fuzzyStones(self): """ switch fuzzy/non-fuzzy stone placement according to self.fuzzy """ for p in self.status.keys(): self.delete(self.stones[p]) del self.stones[p] self.placeStone(p, self.status[p]) self.tkraise('marks') self.tkraise('label') uligo-0.3.orig/sgfparser.py0100644000000000000000000003732607723003524014514 0ustar rootroot# File: sgfparser.py ## This is part of uliGo 0.3, a program for practicing ## go problems. For more information, see http://www.g0ertz.de/uligo/ ## Copyright (C) 2001-3 Ulrich Goertz (uligo@g0ertz.de) ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program (gpl.txt); if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## The GNU GPL is also currently available at ## http://www.gnu.org/copyleft/gpl.html import re import string class SGFError(Exception): pass reGameStart = re.compile(r'\(\s*;') reRelevant = re.compile(r'[\[\]\(\);]') reStartOfNode = re.compile(r'\s*;\s*') def SGFescape(s): t = string.replace(s, '\\', '\\\\') t = string.replace(t, ']', '\\]') return t class Node: def __init__(self, previous=None, SGFstring = '', level=0): self.previous = previous self.next = None self.up = None self.down = None self.level = level # self == self.previous.next[self.level] self.numChildren = 0 self.SGFstring = SGFstring self.parsed = 0 if self.SGFstring: self.parseNode() else: self.data = {} self.posyD = 0 def getData(self): if not self.parsed: self.parseNode() return self.data def pathToNode(self): l = [] n = self while n.previous: l.append(n.level) n = n.previous l.reverse() return l def parseNode(self): if self.parsed: return s = self.SGFstring i = 0 match = reStartOfNode.search(s, i) if not match: raise SGFError('No node found') i = match.end() node = {} while i < len(s): while i < len(s) and s[i] in string.whitespace: i += 1 if i >= len(s): break ID = [] while not s[i] == '[': if s[i] in string.uppercase: ID.append(s[i]) elif not s[i] in string.lowercase + string.whitespace: raise SGFError('Invalid Property ID') i += 1 if i >= len(s): raise SGFError('Property ID does not have any value') i += 1 key = string.join(ID, '') if key == '': raise SGFError('Property does not have a correct ID') if node.has_key(key): if not Node.sloppy: raise SGFError('Multiple occurrence of SGF tag') else: node[key] = [] propertyValueList = [] while 1: propValue = [] while s[i] != ']': if s[i] == '\t': # convert whitespace to ' ' propValue.append(' ') i += 1 continue if s[i] == '\\': i += 1 # ignore escaped characters, throw away backslash if s[i:i+2] in ['\n\r', '\r\n']: i += 2 continue elif s[i] in ['\n', '\r']: i += 1 continue propValue.append(s[i]) i += 1 if i >= len(s): raise SGFError('Property value does not end') propertyValueList.append(string.join(propValue, '')) i += 1 while i < len(s) and s[i] in string.whitespace: i += 1 if i >= len(s) or s[i] != '[': break else: i += 1 if key in ['B', 'W', 'AB', 'AW']: for N in range(len(propertyValueList)): en = propertyValueList[N] if Node.sloppy: en = string.replace(en, '\n', '') en = string.replace(en, '\r', '') if not (len(en) == 2 or (len(en) == 0 and key in ['B', 'W'])): raise SGFError('') propertyValueList[N] = en node[key].extend(propertyValueList) self.data = node self.parsed = 1 Node.sloppy = 1 # ------------------------------------------------------------------------------------ class Cursor: """ Initialized with an SGF file. Then use game(n); next(n), previous to navigate. self.collection is list of Nodes, namely of the root nodes of the game trees. self.currentN is the current Node self.currentNode() returns self.currentN.data The sloppy option for __init__ determines if the following things, which are not allowed according to the SGF spec, are accepted nevertheless: - multiple occurrences of a tag in one node - line breaks in AB[]/AW[]/B[]/W[] tags (e.g. "B[a\nb]") """ def __init__(self, sgf, sloppy = 1): Node.sloppy = sloppy self.height = 0 self.width = 0 self.posx = 0 self.posy = 0 self.root = Node(None, '', 0) self.parse(sgf) self.currentN = self.root.next self.setFlags() def setFlags(self): if self.currentN.next: self.atEnd = 0 else: self.atEnd = 1 if self.currentN.previous: self.atStart = 0 else: self.atStart = 1 def noChildren(self): return self.currentN.numChildren def currentNode(self): if not self.currentN.parsed: self.currentN.parseNode() return self.currentN.data def parse(self, sgf): curr = self.root p = -1 # start of the currently parsed node c = [] # list of nodes from which variations started last = ')' # type of last aprsed bracked ('(' or ')') inbrackets = 0 # are the currently parsed characters in []'s? height_previous = 0 width_currentVar = 0 i = 0 # current parser position # skip everything before first (; : match = reGameStart.search(sgf, i) if not match: raise SGFError('No game found') i = match.start() while i < len(sgf): match = reRelevant.search(sgf, i) if not match: break i = match.end() - 1 if inbrackets: if sgf[i]==']': numberBackslashes = 0 j = i-1 while sgf[j] == '\\': numberBackslashes += 1 j -= 1 if not (numberBackslashes % 2): inbrackets = 0 i = i + 1 continue if sgf[i] == '[': inbrackets = 1 if sgf[i] == '(': if last != ')': # start of first variation of previous node if p != -1: curr.SGFstring = sgf[p:i] nn = Node() nn.previous = curr width_currentVar += 1 if width_currentVar > self.width: self.width = width_currentVar if curr.next: last = curr.next while last.down: last = last.down nn.up = last last.down = nn nn.level = last.level + 1 self.height += 1 nn.posyD = self.height - height_previous else: curr.next = nn nn.posyD = 0 height_previous = self.height curr.numChildren += 1 c.append((curr, width_currentVar-1, self.height)) curr = nn p = -1 last = '(' if sgf[i] == ')': if last != ')' and p != -1: curr.SGFstring = sgf[p:i] try: curr, width_currentVar, height_previous = c.pop() except IndexError: raise SGFError('Game tree parse error') last = ')' if sgf[i] == ';': if p != -1: curr.SGFstring = sgf[p:i] nn = Node() nn.previous = curr width_currentVar += 1 if width_currentVar > self.width: self.width = width_currentVar nn.posyD = 0 curr.next = nn curr.numChildren = 1 curr = nn p = i i = i + 1 if inbrackets or c: raise SGFError('Game tree parse error') n = curr.next n.previous = None n.up = None while n.down: n = n.down n.previous = None def game(self, n): if n < self.root.numChildren: self.posx = 0 self.posy = 0 self.currentN = self.root.next for i in range(n): self.currentN = self.currentN.down self.setFlags() else: raise SGFError('Game not found') def delVariation(self, c): if c.previous: self.delVar(c) else: if c.next: node = c.next while node.down: node = node.down self.delVar(node.up) self.delVar(node) c.next = None self.setFlags() def delVar(self, node): if node.up: node.up.down = node.down else: node.previous.next = node.down if node.down: node.down.up = node.up node.down.posyD = node.posyD n = node.down while n: n.level -= 1 n = n.down h = 0 n = node while n.next: n = n.next while n.down: n = n.down h += n.posyD if node.up or node.down: h += 1 p = node.previous p.numChildren -= 1 while p: if p.down: p.down.posyD -= h p = p.previous self.height -= h def add(self, st): node = Node(self.currentN,st,0) node.down = None node.next = None node.numChildren = 0 if not self.currentN.next: node.level = 0 node.posyD = 0 node.up = 0 self.currentN.next = node self.currentN.numChildren = 1 else: n = self.currentN.next while n.down: n = n.down self.posy += n.posyD n.down = node node.up = n node.level = n.level + 1 node.next = None self.currentN.numChildren += 1 node.posyD = 1 while n.next: n = n.next while n.down: n = n.down node.posyD += n.posyD self.posy += node.posyD self.height += 1 n = node while n.previous: n = n.previous if n.down: n.down.posyD += 1 self.currentN = node self.posx += 1 self.setFlags() if self.posx > self.width: self.width += 1 def next(self, n=0): if n >= self.noChildren(): raise SGFError('Variation not found') self.posx += 1 self.currentN = self.currentN.next for i in range(n): self.currentN = self.currentN.down self.posy += self.currentN.posyD self.setFlags() return self.currentNode() def previous(self): if self.currentN.previous: while self.currentN.up: self.posy -= self.currentN.posyD self.currentN = self.currentN.up self.currentN = self.currentN.previous self.posx -= 1 else: raise SGFError('No previous node') self.setFlags() return self.currentNode() def getRootNode(self, n): if not self.root: return if n >= self.root.numChildren: raise SGFError('Game not found') nn = self.root.next for i in range(n): nn = nn.down if not nn.parsed: nn.parseNode() return nn.data def updateCurrentNode(self): """ Put the data in self.currentNode into the corresponding string in self.collection. This will be called from an application which may have modified self.currentNode.""" self.currentN.SGFstring = self.nodeToString(self.currentN.data) def updateRootNode(self, data, n=0): if n >= self.root.numChildren: raise SGFError('Game not found') nn = self.root.next for i in range(n): nn = nn.down nn.SGFstring = self.rootNodeToString(data) nn.parsed = 0 nn.parseNode() def rootNodeToString(self, node): result = [';'] keylist = ['GM', 'FF', 'SZ', 'PW', 'WR', 'PB', 'BR', 'EV', 'RO', 'DT', 'PC', 'KM', 'RE', 'US', 'GC'] for key in keylist: if node.has_key(key): result.append(key) result.append('[' + SGFescape(node[key][0]) + ']\n') l = 0 for key in node.keys(): if not key in keylist: result.append(key) l += len(key) for item in node[key]: result.append('[' + SGFescape(item) + ']\n') l += len(item) + 2 if l > 72: result.append('\n') l = 0 return string.join(result, '') def nodeToString(self, node): l = 0 result = [';'] for k in node.keys(): if l + len(k) > 72: result.append('\n') l = 0 if not node[k]: continue result.append(k) l += len(k) for item in node[k]: if l + len(item) > 72: result.append('\n') l = 0 l += len(item) + 2 result.append('[' + SGFescape(item) + ']') return string.join(result, '') def outputVar(self, node): result = [] result.append(node.SGFstring) while node.next: node = node.next if node.down: while node.down: result.append('(' + self.outputVar(node) + ')' ) node = node.down result.append('(' + self.outputVar(node) + ')' ) return string.join(result, '') else: result.append(node.SGFstring) return string.join(result, '') def output(self): result = [] n = self.root.next while n: result.append('(' + self.outputVar(n)+ ')\n') n = n.down return string.join(result, '') uligo-0.3.orig/clock.py0100644000000000000000000001456507723003524013613 0ustar rootroot# file: clock.py ## This file is part of uliGo, a program for exercising go problems. ## It contains a class that implements a simple stop watch. ## Copyright (C) 2001-3 Ulrich Goertz (uliGo@g0ertz.de) ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program (gpl.txt); if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## The GNU GPL is also currently available at ## http://www.gnu.org/copyleft/gpl.html from Tkinter import * import time import math import os class Clock(Canvas): """ This is a simple stop watch displayed on a Tkinter canvas. It is given a size (diameter in pixel), a maxTime (this is how long it will take the hand to go round the clock once; after that the clock stops, the clock's face becomes red and 'time is over'), and a function that is called when time is over. The clock is started with Clock.start; it can be stopped with the Clock.stop function (returns the elapsed time) and reset with Clock.reset. The maxTime can be changed with the changeMaxTime function; it makes a new window with a scale pop up, where the time in seconds can be chosen. When the clock is running, the system clock is checked every 100 milliseconds, but the clock hand is updated only once a second. """ def __init__(self, master, maxTime=0, f=None): Canvas.__init__(self, master, height=120, width=120, highlightthickness=0) self.size = 100 self.offset = 10 self.hand = None gifpath = os.path.join(sys.path[0],'gifs') try: self.img = PhotoImage(file=os.path.join(gifpath, 'clock.gif')) self.create_image(60,60, image=self.img) except TclError: pass self.drawClockface() self.currentTime = None self.running = 0 self.maxTime = IntVar() self.maxTime.set(maxTime) self.callOnMaxtime = f self.bind("", self.changeMaxtime) self.red = 0 def start(self): """ Start the clock. """ if not self.running and self.maxTime.get(): self.reset() self.tick = 360.0/self.maxTime.get() self.running = 1 self.elapsedTime = 0 self.currentTime = time.localtime(time.time())[5] self.updateClock() def stop(self): """ Stop the clock. """ if self.running: self.running = 0 return self.elapsedTime def reset(self): """ Reset the hand.""" if not self.running: self.drawHand() if self.red: self.delete(self.red) def updateClock(self): """ This function is called every 100 milliseconds when the clock is running (first by start(), and then by self.after(). If the time (as given by time.time()) jumped to a new second, the hand is drawn in its new position. """ if self.running: s = time.localtime(time.time())[5] if s != self.currentTime: # second jumped if s-self.currentTime<0 : self.elapsedTime = self.elapsedTime + s - self.currentTime + 60 else: self.elapsedTime = self.elapsedTime + s - self.currentTime self.currentTime = s if self.maxTime.get() and self.elapsedTime >= self.maxTime.get(): # time over? self.drawHand() self.running = 0 self.red = self.create_oval(1+self.offset,1*self.offset, self.size+self.offset-1,self.size+self.offset-1, fill="red") self.tkraise('fg') self.callOnMaxtime() return self.drawHand(self.elapsedTime*self.tick) self.after(100, self.updateClock) # next update after 100 ms def changeMaxtime(self, event=None): """ Change the maxTime; makes a new window with a scale where the new maxTime can be chosen. Does not work while the clock is running. """ if not self.running: window = Toplevel() window.title("Change time settings") sc = Scale(window, label='Pick time in seconds (0=off)', length=300, variable = self.maxTime, from_=0, to = 480, tickinterval = 60, showvalue=YES, orient='horizontal') sc.pack() b = Button(window, text="OK", command = window.destroy) b.pack(side=RIGHT) window.update_idletasks() # grab_set won't work without that window.focus() window.grab_set() window.wait_window() def drawClockface(self): for i in range(12): (x,y) = self.ptOnCircle(i*360/12) self.create_oval(self.offset+x-2,self.offset+y-2,self.offset+x+2,self.offset+y+2, fill="blue", outline ="", tags='fg') self.create_oval(self.offset+self.size/2-3, self.offset+self.size/2-3, self.offset+self.size/2+3, self.offset+self.size/2+3, fill="black", tags='fg') self.drawHand() def drawHand(self, degree=0): x,y = self.ptOnCircle(degree) if self.hand: self.delete(self.hand) self.hand = self.create_line(self.offset+self.size/2, self.offset+self.size/2, self.offset+x, self.offset+y, fill="black", width=2, tags='fg') def ptOnCircle(self, degree): radPerDeg = math.pi/180 r = self.size/2 x = int((r-5)*math.cos((degree-90)*radPerDeg) + r) y = int((r-5)*math.sin((degree-90)*radPerDeg) + r) return (x,y) uligo-0.3.orig/uligo.app0100644000000000000000000000056607723003524013763 0ustar rootroot*font: Helvetica 10 *background: grey88 *foreground: black *activeBackground: grey77 *activeForeground: black *selectBackground: grey77 *selectForeground: black *Listbox.background: white *Text.background: white *Entry.background: white *Canvas.background: grey88 *Label.background: grey88 uligo-0.3.orig/doc/0040755000000000000000000000000007723003524012703 5ustar rootrootuligo-0.3.orig/doc/manual.html0100644000000000000000000005401507723003524015050 0ustar rootroot

uliGo Documentation

This is the documentation for uliGo 0.3 - a program to practice Go problems. It was written by Ulrich Goertz (u@g0ertz.de). uliGo is published under the GNU General Public License (see the file 'gpl.txt' or look at http://www.gnu.org/copyleft/gpl.html). This program comes WITHOUT ANY WARRANTY.


Contents:

Getting started:

From now on I assume that you installed the program, and that the main window pops up when you start it. (Otherwise, read the section about installing uliGo first.)

The first thing you have to do is to load a problem collection. Some example collections come with uliGo; see below how you can create your own ones. So, go to the 'File' menu, and select 'Open problem collection'. Then choose one of the sgf files that you are shown (they are in the 'sgf' subdirectory which should automatically be selected). Later, the program automatically loads the collection you used last. Of course you can always load another collection with the 'Open problem collection' command in the File menu.

I think that the user interface is pretty self-explanatory, so I suggest that you just play around a bit with it: press the right arrow to see the first problem. The problem (randomly chosen from the database) will be displayed, the stop clock will be started (by default you have 2 min 30 sec to find the complete answer), and you can play your move. The indicator above the clock (and the 'cursor') shows whose turn it is. After you enter your move, the program automatically replies (unless your suggested move was wrong and no refutation is contained in the database). Then enter the next move ... when the correct solution is reached, the program shows a 'solved' indicator on the left. After entering a wrong move, you can still try to solve the problem, but you cannot get credit for it anymore, of course; instead of the green "solved" you will see a blue one when you get to a correct solution (similarly after using undo, the 'show solution' mode or the 'try variation' mode).

With the right arrow you can go to the next problem (this works at any stage). Note that the arrow buttons do not serve to navigate within the SGF file (use UNDO and HINT, respectively, to do that), but to go to the next problem, or back to the previous one.

Alternatively, if you choose 'Replay game', you can load any SGF file, and replay it by guessing the next move.

Solving problems

Next Problem

This button discards the current problem, and shows the next one. This works at any stage, no matter if you solved the current problem correctly or not, or if you tried some variation etc. Of course, some problem collection must be open; otherwise nothing happens.

Previous problem

With this button, you can go back to the previous problem. Clicking it more than once goes back further, like with the 'back' button in a web browser. Note though that you can't go back and forth: the 'next' button will not go back to the problem you came from, but will give you a new problem.

Restart problem

Go back to the beginning of the problem, and start over. If you are at the beginning of the problem already, this sets up the problem again at a (possibly) different position and with different colors.

Hint

Give a hint, i.e. show the next move (and the answer). Using the Hint button results in this problem not being counted in the statistics, i.e. it is neither a wrong nor a correct answer.

Show Solution

This shows a solution of the current problem. (The button is disabled if you already solved the problem correctly yourself.) You can choose between two modes for displaying the solution (in the Options menu: 'Show solution mode'):

  • animate solution: the moves of the solution are played out. Choose the speed in the Options menu. If there are several correct solutions, one is chosen randomly.
  • navigate solution: You can 'navigate' the underlying SGF file with the correct and wrong variations yourself. The possible variations at a given move are marked by green (correct), red (wrong) or blue (moves of the opponent) markers. Just click on one of them to choose that variation. With the Undo button you can undo the last move. If only red markers are displayed, you cannot reach the correct resolution from this point anymore - you went wrong earlier. Use the Undo button to go back until a green marker appears.

Using the Show Solution button results in this problem not being counted in the statistics, i.e. it is neither a wrong nor a correct answer.

Try variation

At any point, you can press this button, and then play out some variation of your own, e.g. to convince yourself that/why something does not work. Use the Undo button to undo a move. As long as you are in the 'Try variation' mode, the 'Show solution' mode is disabled - it wouldn't make sense to display the solution with your additional stones on the board. Press 'Try variation' again to leave this mode and remove all the stones of your variation. Once you enter this mode, you cannot get any credit for the current problem anymore.

Undo

With this button you can undo the last two moves (the answer to your last move and your last move) or the last move (if there was no answer to your last move or in the Show solution/navigate mode or in 'Try variation' mode). If you use the undo feature, you cannot get any credit for the current problem anymore.

The stop clock

The clock starts when you press the 'next problem' button. The default time is 150 seconds. You can change it by a right mouse click on the clock or by choosing the 'change clock settings' command in the options menu. This only works when the clock is not running.

Set the clock to 0 seconds to turn it off.

When the time for the current problem is over, it is counted as a wrong answer.

How the program chooses the next problem from the database (in random order mode)

Apart from the database, the program maintains a list of all problems, together with information how often each problem has been asked already, and with which results (this list is stored in the xyz.dat file, where xyz is the name of the SGF file).

When you request the next problem, a problem is chosen randomly from the first half of the list; problems from the first third are a little bit more likely to be chosen then others.

When you answer a problem correctly, it will be moved to the very end of the list. So it will take some time until that problem can come up again. When you give a wrong answer, the problem will be moved to a random location in the second half (more precisely: in the 4th sixth) of the list; so this problem cannot appear again immediately, but it could after a relatively short time, and the more problems you answer correctly, the more likely it is that you will asked problems that you got wrong once for a second time.

You can erase the information on your previous answers by deleting the .dat file corresponding to a database. A new .dat file (in which the order of problems is that of the SGF file) will be created when you open the database.

(In case you installed uliGo system-wide under Unix, the .dat files are in the .uligo subdirectory of your home directory. See the file install.txt for more details.)

Using your own problem database

The format used for the problem database is just the SGF format. So in order to make your own database, just put a bunch of SGF games in one single file. Some conventions (explained below) have to be followed, but I think they are much or less common sense. So probably you can just enter a problem into any SGF editor, and everything will work.

The following conventions have to be satisfied:

  • The first node(s) of the SGF file may contain anything. If the first node contains a GN[gamename] item, the game name is displayed. Besides that the program ignores the nodes until a node with an AB[] (place black stone) and/or AW[] (place white stone) item comes up. All other AB's and AW's have to follow this node without any interruption (the program gets confused if there is an empty node in between). After that, the program expects nodes with a B[] ('play black stone') or W[] ('play white stone') item, and they must alternate properly. Two black plays in a row, for instance, are not allowed.
  • If you want to have 'wrong variations' in your problems (as a refutation to some answer), the first node of that variation has to contain a WV ('Wrong Variation', this is not an official SGF tag) item or a TR[] item ('triangle label'). The triangle label option is there in order to make it easier for you to edit problems with an arbitrary SGF editor; just place triangle labels on the first move of a wrong variation. Of course, that also means that no other triangle labels should appear in the SGF files. (Other labels may appear, but are ignored at the moment.)
  • You can insert a general comment about the collection which is displayed after the file is loaded, but before you look at the first problem. Just place it at the very beginning of the SGF file. Anything before the first '(' is considered as a general comment. The only restriction is that your comment must not contain a '('.

One final remark: since every move that is not in the SGF file is considered wrong, it is desirable to put every correct solution into the file. Unfortunately, it is easy to miss some alternative moves, especially after some moves have already been played. Certainly there are some correct alternatives missing in the problems that come with uliGo; so don't take it too seriously if your answer is counted as wrong although it is right ...

Replaying games ("guess next move")

One fun way to study go is to replay professional games by guessing the next move. You can load an SGF file with "Replay game" in the File menu. The stop clock will then be replaced by a few buttons and a frame with a small "go board".

With the buttons, you can choose if you want to guess only black or only white moves, or both. Clicks on the board will be interpreted as guesses - if you managed to guess the next move in the current SGF file, that move is played; otherwise no stone is placed on the board.

In the frame below the buttons you get some feedback on your guesses. If your guess is right, it displays a green square (and the move is played on the board). If the guess is wrong, it displays a red rectangle; the rectangle is roughly centered at the position of the next move, and the closer your guess was, the smaller, and more accurately positioned is that rectangle. Furthermore the number of correct guesses and the number of all guesses, as well as the success percentage are given.

If you just can't find the next move, you can always use the 'HINT' button, and the move will be played out. You can restart the game with the middle button in the first row.

The menu

File - Open

Load a new problem database. A database just consists of several SGF files. Some example databases are included in the uliGo distribution. See below for more information how to create your own databases.

File - Statistics

Open the statistics window. It shows the name of the current database, how many problems are in it, how many problems the program has asked you to answer, and how many right/wrong answers you have given.

File - Clear Statistics

Delete all information about problems done so far, and about correct and wrong answers, and reload the problem collection from disk. In particular, this should be used after making changes to the SGF file with your problem collection.

File - Exit

Quit the program.

Options - Fuzzy stone placement

In order to make the board and stones look more like 'in real life', by default the stones are not placed precisely on the intersections, but by a small, random amount off. On a smaller board this doesn't well (and maybe some people don't like it at all?), so you can disable this fuzzy placement.

Options - Shaded stone mouse pointer

Disables the shaded stone cursor which shows where the next move would be if you clicked at the current position.

Options - Allow color switch

In order to make sure that you don't just learn one particular problem, but rather a shape, uliGo randomly alters the position of the problem on the go board, and also the color of the stones. Because the latter could cause problems if your database contains comments referring to the colors ('good for black', 'white to move'), you can force uliGo to use the colors of the SGF file by disabling this option.

Options - Allow mirroring/rotating

With this checkbutton, you can switch off the automatical mirroring/rotating of the problems. That might be useful, for example, if there are comments referring to the "upper left" or the "right side".

Options - Show solution mode

Swich between animate and navigate mode. See the description of the 'Show solution' button above.

Options - Replay speed

Choose the speed for replaying the solution (in animate mode).

Options - Change clock settings

Change the maximal time for solving a problem. You can achieve the same by right clicking on the clock. (Also see below: The stop clock)

Options - Wrong variations

This determines what uliGo does with 'wrong variations', i.e. with wrong answers to which a refutation is given in the SGF file. You can choose if uliGo should tell you your move was wrong immediately when entering the variation, or only at the end of the refutation, or if uliGo should not descend into wrong variations at all, i.e. just show that the move was wrong and take it back.

Options - Random/sequential order mode

Choose if the problems should be presented in

  • random order: here, the problem is basically chosen at random, but problems that you have been asked already are less likely to be chosen, especially if your answer was correct. (See below for more details.)
  • sequential order (keep track of solutions): The program maintains a list of all problems in the SGF file; in this mode, it always presents the first problem from that list. If you solve the problem, it is moved to the end of the list; if your answer is wrong, it is moved somewhere to the second half of the list (so it will reappear sooner).
  • sequential order (don't record results): In this mode, the problems are presented in the same order as in the SGF file. Correct or wrong answers are not recorded in any way. You can specify the starting point. If you don't specify it (or if the entry is invalid, e.g. not an integer), it starts with the first problem in the SGF file.

The mode, together with the current position in 'sequential order, don't record results' mode, is stored in the .dat file; so basically each problem collection has its own mode. If you check the "use as default" option, then the current mode will be chosen for other collections which do not yet have a .dat file (i.e. you use then for the first time) or have a .dat file from version 0.1.

Options - Use 3D stones

Toggle the use of the more beautiful 3D stones versus flat stones. The 3D stones were provided by Patrice Fontaine. (Thank you!)

Help - About

Some basic information about uliGo.

Help - Documentation

Open this documentation in a web browser.

Help - License

The uliGo license.

Miscellaneous

That's it for the moment, I think. Feel free to contact me (at uligo@g0ertz.de) if you have any questions, or - in particular - if you find any bugs in the program.

Installation

The program is written in Python, a high-level interpreted programming language. If you are using Windows, you can either use the uliGo installer which contains everything you need to run uliGo, or you install Python separately. On other systems, you need to install Python before you can run uliGo. Any version better than 2.0 should do; I tested the program with Python 2.0, 2.1 and 2.2. If you have to install Python, you should get the current version 2.2.

Windows

Te easiest way is to use the installer. Since it contains the Python interpreter, there is no need to install Python separately.

If you want to install Python separately, download the Python installer for Windows from the Python website. It will be very easy to install it. Then download the uligo03-win.zip file and unpack it. You should then be able to run uliGo by double-clicking the "uligo.pyw" file, or from the command line with "c:\python22\python uligo.pyw".

Linux/Unix

It is likely that Python is already included in your distribution. It is also easy to build it yourself with the source from the Python website. But be sure to install the Tkinter module which is needed for the GUI, too; look at the in the README file coming with Python for instructions how to do that.

Once you have Python working, just download and unpack the uliGo file (uligo03.tar.gz). It will create a subdirectory called uligo03 in the directory where you unzip it, and all files needed for uliGo will be placed in that subdirectory. Then just start uligo.py: change into the corresponding directory, and type 'python uligo.py'. (You can also make 'uligo.py' executable, possibly change the path in its first line to point to your Python installation, and run it as 'uligo.py'.)

You can also install uliGo system-wide; see below.

Other operating systems

Python is available for many operating systems, so you should also be able to run uliGo. See the Python website for more information.

Upgrade from uliGo 0.1, 0.2

Basically, you should just install uliGo 0.3 from scratch, and delete the old version (Make sure that you don't delete any sgf files with problems ...). In particular, you should not use the files uligo.def and uligo.opt from version 0.1 or 0.2 with version 0.3 (these files contain the default problem collection and the saved options, respectively).

You can use the .dat files from uliGo 0.1, though (these files contain the information about right/wrong answers etc.; for each SGF file that you used with uliGo there is a corresponding .dat file). Just copy the .dat files from the sgf subdirectory of uligo01 to the sgf subdirectory of uligo03. (In case you installed uliGo system-wide under Unix, it is slightly more complicated; please see below.)

Systemwide installation under Unix/Linux

To install uligGo system-wide (in /usr/local/share, for instance), proceed as follows:

Put the uliGo files in /usr/local/share/uligo03 (if you put them somewhere else, you have to adapt the unixinst.py script accordingly).

Carefully read, and -if necessary- edit the script unixinst.py . (I think that you probably will not want to change much.) Basically, the unixinst.py script writes a 'global' uligo.def file (in the uligo03 directory) which tells uligo to look for individual .def files (in $HOME/.uligo ) when it is started. So for every user who uses uligo, a subdirectory called .uligo will be created in the user's home directory. In this directory, the individual .def file (which stores the path and name of the SGF file used last), the .opt file (which stored the saved options), and the .dat files (which store the number of correct/wrong answers for each problem in the corresponding SGF file) are stored. In order to avoid name conflicts between .dat files for .sgf files in different directories, the path is shadowed in the .uligo directory: for a .sgf file in /usr/local/share/uligo/sgf, for example, the corresponding .dat file is in $HOME/.uligo/usr/local/share/uligo/sgf.

Furthermore the unixinst.py script creates a link in /usr/local/bin, pointing to uligo.py.

After you edited the unixinst.py script, execute it with 'python unixinst.py'. The only other thing you might have to do (if your python interpreter is not in /usr/bin), is to change the very first line of the file uligo.py, which must contain the location of the python interpreter, so that uligo can be started by 'uligo.py'.

History

May 2003:uliGo 0.3, with a few new features, and a Windows installer.
June 2001: uliGo 0.2: some minor bugfixes, and the option to change the order in which the problems are presented (random vs. sequential)
May 2001:uliGo 0.1 is published.
April 2001:Started writing uliGo.
uligo-0.3.orig/doc/readme.txt0100644000000000000000000001224207723003524014677 0ustar rootrootuliGo - Understanding, Learning, Inspiration for the game of GO uliGo 0.3 is a program to practice go problems. It was written by Ulrich Goertz (uliGo@g0ertz.de), and is published under the GNU General Public License. What follows is a description of the features of uliGo. To find information how to install the program, and how to use it, look at the manual, to be found in the manual.html file. --------------------------------------------------------------------------- Acknowledgments: I am grateful to everybody who pointed out bugs in previous versions, or made suggestions about new features. The images of the board and the stones were created by Patrice Fontaine. Disclaimer: I have thoroughly tested uliGo on one Linux box, and installed and briefly tested it on a Windows system (Win2000). There are no bugs that I know of, but since this is the very first published version, probably some bugs exist nevertheless. So let me state clearly that this program comes WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Where to get uliGo: - You can download the uliGo distribution (as a .tar.gz for Linux/Unix or as a .zip file for Windows/Macintosh) from http://www.u-go.net/uligo/ On that page you can also find more information about uliGo, including some screenshots. Give it a try and please send me your feedback! Any comments, and especially bug reports are welcome. ------------------------------------------------------------------------------ To get stronger at go, it is essential to develop one's reading ability. That is why professionals recommend to study life and death or tesuji problems. uliGo is a program that allows you to do that: basically, the computer displays a problem, and asks for the answer. You enter the first move, the computer responds, and so on until you reach the final solution or enter a wrong move. The main features of uliGo are * It is free. uliGo is published under the GNU General Public License (GPL), so you don't have to pay anything to use it. Moreover you may freely distribute it. You also get the full source code and may add your own features to the program, as long as you also release the changes under the GPL. * It is cross-platform. uliGo is written in Python (with Tkinter for the graphical user interface). So you may have to install Python first; but it comes with most Linux distributions nowadays, can be installed on Windows machines in a minute with a comfortable installer, and is available on nearly any platform (Apple Macintosh, of course, but also other UNIX versions, etc.). Go to http://www.python.org/ for more information on Python (and how to install it; also see the uliGo documentation). * It uses the SGF format for storing the problems. That means that you can easily (with any SGF editor, in fact) generate your own problem database. Also, if you find an error in an existing database, you can fix it yourself. Comments from the SGF files are automatically displayed, and you can also give 'wrong variations' that contain the refutation of a certain move. * In order to make sure that you do not only learn the answer in one particular position, but rather the right move for a certain shape, uliGo randomly switches the colors (black <-> white) and changes the position on the board (by mirroring/rotating) of the problem. * If you are stuck, you can look at the solution of the problem. You can also, at any time, play out a variation of your own (for example when you want to convince yourself why a certain move does not (or does) work. * There is a customizable stop clock; so you can set the time you have for answering yourself. If the problems in the current database are easy, try to solve them in thirty seconds (or less ...), if they hard, allow yourself more time to think or turn off the clock. * It comes with two problem collections (easy & hard) with 80 problems altogether. Some of these problems I composed myself, the other ones are taken from classical problem collections. Certainly for some people the "easy" problems are not so easy, and others will not find the "hard" problems difficult at all. I hope you will find some problems that are suitable for you, anyway. Considering that only some of the problems will be useful for any particular level, 80 problems obviously are not much. It would be desirable to make more problems available in SGF format; of course, because of the copyright, it is not possibly to put a whole book into SGF and give it away; also from an ethical point of view, this would be undesirable, since I think it is important to support the authors and publishers of such books. I would find it ideal if some go publishers would sell problem collections in SGF format, at a reasonable price. It should be easy enough to find volunteers who put (parts of) a book into SGF. If you own a copy of Cho's Encyclopedia of Life and Death on disk, you can use the program cho2sgf.py (to be found on the same web page as uliGo) to translate those problems into SGF format and use them with uliGo. uligo-0.3.orig/doc/license.txt0100644000000000000000000004313107723003524015065 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. uligo-0.3.orig/doc/hint.gif0100644000000000000000000000466507723003524014344 0ustar rootrootGIF89a<(***RRRjjjvvrzzvBB>ʞ~""":::¾ֲ662ffb⾾..*JJF rrrVVV"FFB^^^22.&&"Үښ¾>>>~~~ƾZZV’Ζ榦zvv2..⦢NNN>::vrvB>>vvvFFF222b^^zzzBBB...&&&666fffZZZ!Created with The GIMP,<(袠(cCf#]=aTM2@0 J(D<%=TgqPL+\@\$$0F \<ǻſ|0=d[+l)|\x d`V| \`C$Ã@egDaqPH-<@d!u'<4\+4[B80"DɪA@A \@Y4xqGOX2XW{\r-%$ JXqS :C 2>@ N8*`c}g̓PPdV<v@y!WX`]!4!:|PߩPB#Dn{qa@B @"$۱/\q1߅թoE7Sl €&;[E Z(оY@~[pCA ג?LXH(  -@v?hA W`Z QD8BB-a#j.X@ [=Nb$W@Ji0}K@ʯ 04đLqx |BXE' X E8e@~ͻ߿i"h(bP B 4 3ʪUɆABH>L a0B@ N )Hޜ?>'[.%KMEٓ&5H!a 8TY i| ifk# `*! BҖ a8LO2Mt°p@{"}M aQ `ԗM,#YdNѠ=V5i\&,7a C G!'@P85)AK4ZK. HBl _f@"q|OG҇ld9p_Q <  8.mb+qe;͊5HB l5 fp'}._)|~/ '}`XfQ $o 8kk .`&i%K^$U P*4(#ZmojpFWНA@;uligo-0.3.orig/doc/left.gif0100644000000000000000000000415607723003524014327 0ustar rootrootGIF89a((RRRzzz¾...^^^ҊfffJJJjjj222⦦ >>>nnn"""ނ~rrr򎒒VVV&&&662ڢ~~zFFFҲvvvbbb:::ʾNNJZZZ***BBBΚʺ֞~z~¾殮ޮΦ꒒ʺB>>fbfβnjn.**zz~"~~*&*::>nnrbbf^^bffj**.>>B~~~vvz޺jjnVVZ666梢NNNZZ^֚Ξ¾º!Created with The GIMP,((mDZR8ÆM 1PtEQԃ`R` BD >̏"7<*A`G'Ni00-R!F DMcǎDzB`\DJE`Dyp-|l(+h-긹FpOȥ @IpI"P)"UD=p@ySŨlSt-BI=>`à Ee])c )%-|"FՒ/TfL1fF1G9D 's *""\p]ji:T`b)aahZtPI'Q C^b}DW-{Gu 6Fq *d(Бrg##?x@z|Lr+/8pEBJN,y#ٶd ~ `L QDQ%? cI O(QI LrKn,gVT\"E QF1 BhI'(QCj`2| [| & M81V$\4ۉB(@ p@DJ_`R\qB(0h»j LDPy]rB; I,Bp@3B#>| 0 R Y ax@=pШ4?ȐAjP HB$1[Aj2]#5A$<@p Ll+22ih$"'  ; 0@#ljLihgRD7L!$\b)`4FZ ф md!LAt @" [$>@`A;аx, ,aD)HdaABЁ $N:;&}%D|Ȓ#@" p+X7a=An 04gA7la>0( tVH YnV; V(,0$LFtU$ [BE(B! Zp(HH` 9B%*@v `>Jh@D"7T"L da|(E)WPb]Mu*rHD` (JEA*Xź51h$ 2dŽY8_1 Մ3 %=SR."8,{˒1l\XZ-0; NLL*_MX؀ \?: r'u3TcܳZB驐4U{%;'g0Sfz`Ԃi+J\;uligo-0.3.orig/doc/reload.gif0100644000000000000000000000374507723003524014646 0ustar rootrootGIF89a(( FFFnnn22.VVVzzv***&&"^^Z~>>>NNNbb^΢rrnffb666¾ֶjjfJJFvvrRRNޖZZV~~z:::BB>ʾڶ2..ھ...ʮ–ƪzvvb^^"""ҺNJJVRR¾rnn~zz:66҆~~~掎vvzƖ⚚JJJ222zzzfffjjjvvvRRRZZZ檪BBB&&&rrrnnr^^^bbb!Created with The GIMP,((+T0BAh;*"F#EF ;Q"!8Kh(PA$+(1"H*iib@d8f#y1%“'E8Z(Ku4xبSr,5#p9:I&Gw@$ՠ^ˊq:+ +N54VTXؚ;MS iA7AB E^7 ($ 鬡2pkL Q k8XJDQ p&U^2| L-5 1 D Z c"%4:k& a _!L: 587$!Tǹt\>)"8!8f`  :Tjz#U p#5 `#MpA#$RtDB`cFd+1uLG4@=- )ð@[+(AUS4sE E$u " @{EpfUeyRwd^H" ܐA7( !WBT5FCQ!$h`#uD'zV'ɄR|!G{!!&|RzЀ n`Z@&<QC0  %@2hUr >Ѕ<@!^p\U! ]8כs3E$*0 h)rCPHD">I"P aHa뮂0h@a]C' ”dJFH!Ha_ H&\aT'\HACІ"Ee !Lah!'P T|28C@;uligo-0.3.orig/doc/right.gif0100644000000000000000000000370207723003524014506 0ustar rootrootGIF89a((NNNzzz"""ZZZ...nnn~~~666fff>:>ƶ ¾JJJʮڞ^^^vvrBB>ҾVVV֚ڎFFBvrrjjjrrrbb^RRR***222&&&njjjff¾FBB>>:®~zz^Z^rnnNJJzvvfbbb^^RNRھҪvvvBBBFFFbbbƮ>>>vrvnjnjfj¾¶!Created with The GIMP,((Y# @E!b xaѢ@'8@れ4Bb ,4. @xxÞXsfʊ.3bDJ:䄠EOfeiIy4$ Z|֓(%a–$ sEi= }Y]g6zVnj,ͮxrχ{Y%/+-F2F6jVv(7(W" .ǩxTrf 7sVKtn^E*(ȇ ]d\r  z@85,\Av0@@$q%0^DMcADjF?aNX& i@M!I1N?A d l!N@E'qSL6B`%KX j&wd @  IZi$xz9wXFkL! Voy C NaTUQx`Axp! _@j9٫'DAA+L 4@wCh:{iAqW”!8ȩ'F;D7Ԁ0gH^$aD`F -Qn@Ƞ<G $EQlЂVi %@(0wQ: } /Cb80]A*@$@odt !RIyM\,Bs }49D[tY7@&r@< <7 $qF lFR1d1q w UNB,Wh@,MMhQ-@_[SЀpAS[K;tAbL6Ɇ"d衇k0DS/ ` L87ANBç0f'cB.@ /Ps2vk-D ?80 cA0M8d&MIP#lRd !lPPZ>Dd!yAr DQ"LBO@` d@̈4R1P IX#I_AR>pP$(e4aǀMdI9q" ;uligo-0.3.orig/doc/showsol.gif0100644000000000000000000000562107723003524015071 0ustar rootrootGIF89a<(***^^^¾nnj~~~>>:֊ZZVΒNNN..*殮Қbb^662vvr BBB"""ƲJJFfffVVR&&"::6֦FFBzzv.22jjfֺrrnšRRNڶʾʪƞκ¦򢢢¾622~zzƆNJJnjnή~~zvvFBBrnnbbfRRR^ZZ2..ꦦ&"" 222vrr¾ºVRV&&*ΪƮʮrrrzzzھnnn^^bZZZNNR...666vvvJJJ&&&:::FFFjjjƲޞbbbVVV>>>¾~z~RRVNJN΂~rnr!Created with The GIMP,<(_4i0`NS:4qH3jDxǏW6flAC >0C0qbGwG(@`Dh:i$V3!M0!'86dpj dP ʼndrI5$T9 c :I,Xuft uͷ 0@) z0ZD0 vh-("PT@cH -į )0r +{0R E ) CrH]P @Cв[=w ! JAgp(!)R `gŠ+p2 )Xt B(s6b^M 1-bgtG 6p )G[1\|$yYmF+Y`*] )#(Rxv _*̗ FpB LlR bր)D^ׂ\Ѐ_w׭Q] 8-P0A ׇL] gKK &X7U"`CՉZt p)JZp}@  tTVփOe& HBX*JD(E*N*ЅQK`-lA1+,TBȊ P +@' B@TH*:I+3~Vp!`I%,, gpprB)LG\cx8A a h,4R("g )Pa 6sXtb =X@QC(yXgxHH*PqTZҔ"dD(-R @ |P(bm;ᙉ7,i D"p0+] @^"-PJ: =E BL<9#"=XlJi:9q3 BX,dPPq(J@%H v?=^A!Yh)` X\!b+: mB[W T,"@.RA @-AV {,B+B@*r@ Qf` SHE'Fa3P"P Q`@H %jQ:+p$FY NBAdwCaQ\w=!BsCR4a:a+Ơքu H`]ȁ%/ZsV4w@P4B*H Ђ0KBi~BEw,,0[VpP(Yx,ڰ tg:AKV,@F P"Rhjւ6r "la sDư%d@ m@Aڐ'4{ Fhot X  NĴmmk;O('2=#B@T獁 \^78Euo,`"pYi9e`]8+i#Yy4@s2 Rd8BC~s ^iK *SNp*8^B+wL`V``g:>#`꧀;uligo-0.3.orig/doc/tryvar.gif0100644000000000000000000000570207723003524014722 0ustar rootrootGIF89a<(222jjjzzzZZZ"""ꎎJJJ֦666ʮ¾:::**&BBBbb^ NNN~~zrrnҚVVRΊ..*֖FFB&&"悂~ήnnj^^Z>>>fffʮ➚ڢ¾RRNžʚvvvֺҪꆂʊ޶Ʋnnn֖&&&~z~&"":6:>::.**b^b*&&njjfbbZVVVRRnnrvrrbbfFFJRRV***ꊊ¾ƚ226~~~...FFF枚޲&&*^^^VVVbbbRRRrrr!Created with The GIMP,<(a #-""Z0aҡ36 9rDH9d9h%H"X(bTJpyFg3"RB 3̒[4 =vhi1H4ezTH,Ȇ%|a o"+3߶ ".5BE&T#gGn팈"J"bFu,r|Bn jd##EAg&STPh'(TDRF,!L2Dp% $HpEDr q0BvvC8G# aL"0P A C! 'Ā}XbgmȗVȀK1%C4$kl…"XLAQLg,ʈU@z IZPE,<80 )1.i-Sİ$.C8 @e+݀2md# `@.p;qHvD|Ao`+HΎK# x47Bxr, \Q @ @5bcr=;` 45z_H4p BE("H#p8xJ1SĖXY ^Tn2}A%g#VWGp/$ث EK1v#O`Thh O3\σ @|Ax; Hu-AJլ}}`*,v@K[$~QU}929e7>>Ҫƞ¦ꎊʊξ¢Ƣ¾–VVZvvvކ~~bbfjjn!Created with The GIMP,<()xćH6#Jd#bFƍ7Bz#(H )0ѠEl|XDKO#Q䆖E8~D'GU$|xC81q@ -(¶GA` JT DdoCBbJ'4n,bحl8B4Ҥ\(T) tvEV!k*>1C+WS&T2@!. #O^ B4QFoqHuVmG0O2[njܦN#̝1}0n-zQ0U5UY߭g^S0ctGM'u)fvAA@`z S c!F"!}e'`maC! 1YEʼn[AG_aTHч۱#!D`MQ"84g gq{ bD"XUFA! 3`@T*)ge+2SyўuYUG`dF3 3!#&Q&eeTK~F]2~ro>jGV)$P Å`8 %jSd e.*zT b:lVJ%kBzD畱  :n dEM2BQLPL y챀誛n246 TI;!q`Ap)< 6eТ;& ̼8358@ 8@t,40IL/zTa.5DF48@,Ahs/L<KDOaIhYvF/]O`k7+P,@ ,P@\Dn8Pj<@khuϼFyPK (y ShA B<[\Մv Fp,` ^ LU^ DaeT -,6{Qz)|SH:?2H)AVoYQW˛8Es|9I ) )M d0@"m.JN$ *sXD9NQUD%(Et4g;H@ HJOɁ -r:y)NM8HӧX$eP"k L1H@:!O@jB"&4!_(ag̀ )NP2A  ࡴea p2:\1Ѯ@.@A\'\ϸpZrH"*PVycPɭ6Њp6 * @D$^=WqΫ<%<8 p:L mN$$­HT- C@aA@PAbD+~ B k2ZbȮozmP`!$::At,CIx&>Sp",$m)93` bt:IH Y8T scl%4)`Yƀ`-c,ڈr6͠i t5&i3DP'M2vT0:[2c@ U"Set- $TV<62`6l9aa}f!ve .(XTR;uligo-0.3.orig/sgf/0040755000000000000000000000000007723003524012715 5ustar rootrootuligo-0.3.orig/sgf/easy.sgf0100644000000000000000000001554607723003524014367 0ustar rootrootA collection of 40 easy problems. (;GM[1]FF[3] ;AW[oq][pq][qq][rq][sq][mr][or] AB[pr][qr][rr][sr][ps];B[rs] ) (;GM[1]FF[3] ;AW[qn][mp][qp][rp][kq][mq][oq][pq][nr][pr][rs] AB[nn][mo][np][op][pp][nq][qq][rq][qr][sr][qs] (;B[or];W[os];B[ps];W[or];B[mr]) (;B[ps]WV[ps];W[or];B[mr];W[lr]) ) (;GM[1]FF[3] ;AW[qo][qp][kq][nq][oq][pq] AB[qh][ol][nm][qm][op][pp][qq][rq][qr][sr][qs][rs] ;W[no];B[oo];W[on];B[pn];W[po] ) (;GM[1]FF[3] ;AW[ok][qk][rl][mm][ln][pn][op][pp][rp][qq][rq][pr][qr][sr] AB[qn][qo][ro][np][qp][mq][oq][pq];B[on] (;W[po];B[pm];W[no];B[oo]) (;W[oo];B[no];W[pm];B[po]) ) (;GM[1]FF[3] ;AW[pq][qq][rq][gr][hr][ir][jr][kr][pr][is][ps][rs] AB[ql][op][pp][qp][rp][fq][gq][hq][iq][jq][kq][lq][mq][oq][dr][fr][gs] (;W[ns] (;B[nr] (;W[ls]) (;W[ms]) ) (;B[ms];W[mr];B[lr];W[ls];B[nr];W[ms]) (;B[lr];W[ls];B[nr];W[ms]) ) (;W[ms]WV[ms];B[ls];W[lr];B[ns];W[mr];B[nr]) (;W[lr]WV[lr];B[mr]) ) (;GM[1]FF[3] ;AW[iq][kq][lq][mq][nq][jr][kr][nr][is][ks] AB[mn][on][lo][hp][ip][jp][op][qp][hq][oq][gr][mr][or][ns] ;W[ms];B[ls];W[lr];B[ms];W[os] ) (;GM[1]FF[3] ;AW[ip][jp][kp][lp][iq][lq][ir][kr][lr] AB[ho][io][jo][ko][lo][hp][mp][hq][mq][hr][mr][or] (;B[ls];W[is] (;B[ks]) (;B[jq]) ) (;B[jq]WV[jq];W[ls];B[js];W[is];B[jr]) (;B[is]WV[is];W[js]) ) (;GM[1]FF[3] ;AW[jq][kq][gr][hr][ir][lr][gs][ls] AB[jp][kp][lp][fq][gq][hq][iq][lq][nq][fr][mr][fs] (;B[jr];W[kr];B[js]) (;B[js]WV[js];W[jr];B[ks];W[is]) ) (;GM[1]FF[3] ;AW[io][jo][ko][lo][jp][lp][jq][kq][ir][lr][js][ks] AB[lm][hn][in][jn][ho][mo][mp][hq][iq][lq][mq][hr][mr][ms] (;B[hs];W[is];B[kr];W[jr];B[ls]) (;B[ls]WV[ls];W[kr]) (;B[kr]WV[kr];W[ls]) ) (;GM[1]FF[3] ;AW[jo][qp][fq][iq][jq][kq][mq][oq][gr][hr][lr][mr] AB[hp][lp][hq][lq][ir][jr][kr] ;B[jp];W[ip];B[io];W[kp];B[ko] (;W[jn];B[jp]) (;W[jp];B[jn]) ) (;GM[1]FF[3] ;AW[fo][cp][dp][ep][cq][gq][hq][kq][br][dr][hr][ds] AB[dq][eq][cr][er][fr][gr][es] ;B[bs] (;W[bq];B[gs]) (;W[gs];B[bq];W[cs];B[cr];W[bp];B[ar]) ) (;GM[1]FF[3] ;AW[ro][nq][oq][pq][qq][rq][mr] AB[or][pr][qr][rr][sr] (;W[os] (;B[ps];W[rs];B[ns];W[nr]) (;B[ns];W[nr];B[rs];W[ps];B[qs];W[os]) ) (;W[rs] (;B[os];W[qs]) (;B[qs];W[os];B[nr];W[ns]) ) ) (;GM[1]FF[3] ;AW[rk][ol][pl][rl][om][qm][sm][qn][rn][sn][qo][pp][pq][pr][qr] AB[ri][qj][qk][sk][ql][pm][pn][oo][po][ro][so][qp][sp][qq][rq][rr]; W[no];B[op];W[np];B[oq];W[or];B[nq];W[mq];B[nr];W[mr];B[os];W[on] ) (;GM[1]FF[3] ;AW[dl][cm][bn][ao][bo][ap][cp][dp][dq][dr][bs][ds] AB[cn][en][co][eo][bp][ep][bq][cq][eq][ar][cr][gr][cs] (;B[er]WV[er];W[aq]) (;B[bm];W[bl] (;B[er]) (;B[do]) ) ) (;GM[1]FF[3] ;AW[qq][rq][sq][pr][rs] AB[pp][qp][rp][nq][pq][or][rr][qs] (;W[sr];B[ss]C[Ko.]) (;W[qr]WV[qr];B[ss]) (;W[ps]WV[ps];B[ss]) ) (;GM[1]FF[3] ;AW[qq][rq][pr][sr] AB[oo][qo][rp][sp][kq][oq][pq][sq][or] (;W[rs] (;B[qr];W[ps]) (;B[ps];W[qr]) ) (;W[qr]WV[qr];B[rs]) (;W[qs]WV[qs];B[rr];W[rs];B[ss]C[Ko.]) ) (;GM[1]FF[3] ;AW[oq][qq][nr][pr][rr][sr][ns][ps][rs][ss] AB[ro][op][pp][qp][mq][nq][rq][sq][mr][qr] (;W[pq];B[qs];W[rr]) (;W[qs]WV[qs];B[pq]) ) (;GM[1]FF[3] ;AW[rl][qn][rn][po][so][pp][rp][pq][sq][pr] AB[qo][ro][qp][qq][rq][rr][sr];W[sp];B[sn];W[sp];B[so];W[rs] ) (;GM[1]FF[3] ;AW[po][qp][rp][mq][oq][pq][qr] AB[qq][rq][pr][rr] (;W[qs];B[rs];W[sq];B[ps];W[sr]) (;W[or]WV[or];B[qs]) ) (;GM[1]FF[3] ;AW[hp][ip][jp][kp][lp][mp][np][gq][kq][oq][pq][jr][pr][ps] AB[fp][gp][cq][fq][hq][iq][jq][lq][mq][nq][kr][mr][or][ls][ms][ns][os] (;W[hr]WV[hr];B[gr];W[ir];B[gq];W[js];B[hs]) (;W[is] (;B[ks];W[gr]) (;B[gr];W[ks]) ) ) (;GM[1]FF[3] ;AW[fp][gp][dq][hq][iq][er][hr][jr][hs][is] AB[hp][ip][jp][lp][gq][jq][gr][lr][gs] (;B[kr]WV[kr];W[fr]) (;B[ks] (;W[fr];B[js]) (;W[kr];B[ls];W[fq];B[js]) ) ) (;GM[1]FF[3] ;AW[hp][jp][kp][lp][iq][mq][pq][hr][jr][mr][hs][js] AB[co][ip][dq][gq][jq][kq][gr][kr][gs][ks] (;B[ir]WV[ir];W[hq]) (;B[hq];W[io];B[ir];W[is];B[ir]) ) (;GM[1]FF[3] ;AW[op][pp][qp][rp][sp][oq][or][os] AB[pq][qq][rq][sq][pr][ps] (;W[rr];B[rs];W[sr]) (;W[rs]WV[rs];B[rr];W[qs];B[ss];W[sr]C[Ko.]) ) (;GM[1]FF[3] ;AW[bp][cq][dq][eq][jq][mq][br][fr][gr][hr][ir] AB[fn][bo][co][ep][fp][hp][bq][fq][hq][cr][dr][er] (;B[aq];W[ap];B[cp];W[ar];B[bq];W[aq];B[dp];W[bq] (;B[ao]) (;B[bs]) ) (;B[cp]WV[cp];W[aq];B[dp];W[bq];B[bs];W[cs];B[ds];W[fs]) ) (;GM[1]FF[3] ;AW[gp][hp][fq][hq][fr][hr][ir][jr][lr][fs][ls] AB[go][ho][ko][ep][fp][ip][op][cq][gq][kq][lq][mq][dr][gr][kr][nr][gs][is][js] (;W[hs]WV[hs];B[gr];W[ks];B[js]) (;W[ks];B[mr];W[hs];B[js];W[gr]) ) (;GM[1]FF[3] ;AW[rp][pq][qq][rq][or][ps] AB[qn][ro][op][pp][qp][mq][oq][nr][ns] (;B[pr];W[qr];B[rs] (;W[sp];B[sr];W[os];B[qs]) (;W[rr];B[os]) ) (;B[sp]WV[sp];W[rs];B[sr];W[sq];B[qr];W[rr];B[pr];W[qs];B[pr];W[os]) ) (;GM[1]FF[3] ;AW[hq][iq][jq][gr][kr][gs] AB[hp][ip][jp][fq][gq][kq][mq][fr][lr];W[ks] (;B[ir];W[is]) (;B[is];W[ir];B[ls];W[hs]) ) (;GM[1]FF[3] ;AW[iq][jq][kq][hr][jr][lr][hs][ls] AB[ho][ko][ip][kp][gq][hq][lq][mq][gr][mr][gs][ms] (;B[js]) (;B[ks]WV[ks];W[kr];B[is];W[ir]) ) (;GM[1]FF[3] ;AW[ob][oc][qc][pd][qe][pf] AB[pb][qb][mc][pc][nd][od];W[rb];B[rc] (;W[qd];B[ra];W[sb];B[sc];W[pa];B[sa];W[rb];B[sb];W[oa]) (;W[qa]WV[qa];B[qd]) ) (;GM[1]FF[3] ;AW[cl][cn][co][cp][dq][dr][er] AB[do][fo][dp][cq][eq][fq][gq][cr];W[br];B[bq];W[cs] ) (;GM[1]FF[3] ;AW[bm][bn][bo][cp][ep][bq][cq][eq][jq][mq][fr][gr][hr][ir] AB[bl][cl][am][cm][in][co][do][eo][fo][ip][fq][ar][br][cr][dr][er][es] ;W[fp];B[gq];W[hp];B[gp];W[go] ) (;GM[1]FF[3] ;AW[kj][lj][mj][nj][pj][jk][ok][jl][pl][mm][pm][in][jn][qn] [ko][lo][no][oo][po][nq] AB[lk][mk][nk][kl][ml][ol][km][om][kn][on];B[mn] (;W[nm];B[nn];W[lm];B[ln]) (;W[nn];B[nm];W[ln];B[lm]) ) (;GM[1]FF[3] ;AW[pa][qa][ob][qb][sb][kc][lc][oc][rc][ld][md] [nd][qd][ke][qe][kf][lf][mf][pf][og] AB[ra][kb][pb][hc][jc][pc][qc][jd][kd][od][pd][je][le][me][ne][oe] ;B[nc] (;W[nb] (;B[mb];W[mc];B[lb];W[nc];B[na]) (;B[lb];W[mc];B[mb];W[nc];B[na]) ) (;W[mb];B[nb];W[oa];B[lb]) ) (;GM[1]FF[3] ;AW[rp][pq][qq][rq][pr]AB[qn][ro][op][pp][qp][oq][or] (;B[sp];W[rs];B[sr];W[sq] (;B[rr]) (;B[ps]) ) (;B[rr] (;W[rs];B[sr];W[sp] (;B[ps]) (;B[qs]) ) (;W[sr];B[rs];W[sp];B[ps]) (;W[sp];B[sr];W[ps];B[rs]) ) (;B[rs] (;W[ps] (;B[sp]) (;B[rr]) (;B[sr]WV[sr];W[rr];B[sp];W[sq]) ) (;W[qs];B[rr];W[sp];B[sr]) ) ) (;GM[1]FF[3] ;AW[gp][gq][er][fr][hr][ir] AB[fo][go][fp][hp][cq][dq][fq][hq][jq][kq] (;W[gs];B[gr];W[gq]) (;W[gr]WV[gr];B[dr];W[jr];B[kr];W[js];B[es]) ) (;GM[1]FF[3] ;AW[rp][pq][qq][rq][pr] AB[qn][ro][op][pp][qp][oq][or] (;W[rs];B[sr];W[rr]) (;W[rr]WV[rr];B[qs];W[ps];B[rs];W[sp];B[sr]C[Seki.]) ) (;GM[1]FF[3] ;AW[qo][ro][qp][oq][qq][pr][ps] AB[rp][rq][qr][sr][qs]PL[2];W[rs];B[rr];W[sp] ) (;GM[1]FF[3] ;AW[lo][kp][gq][hq][iq][jq][lq][mq][nq][oq][gr][or] AB[kq][hr][ir][jr][kr][lr][mr][nr] (;W[hs];B[is] (;W[ns];B[ms];W[ks]) (;W[ks];B[ns];W[ls]) ) (;W[ns];B[hs]PL[2] (;W[ms];B[js];W[ls]) (;W[js];B[ks];W[ms]) ) (;W[ks]WV[ks];B[ns];W[ls];B[hs];W[js]) ) (;GM[1]FF[3] ;AW[hq][iq][jq][kq][lq][mq][nq][pq][hr][or][js][ls] AB[ir][jr][kr][lr][mr][nr][ms] (;B[is]) (;B[ks]WV[ks];W[is];B[hs];W[is]) ) (;GM[1]FF[3] ;AW[ck][fn][do][go][cp][cq][gq][hq][br][hr][cs][ds] AB[ep][dq][fq][cr][dr][er][fr][gr];B[gs];W[es];B[bs];W[as];B[fs];W[bs] ;B[bq] ) uligo-0.3.orig/sgf/hard.sgf0100644000000000000000000002175607723003524014344 0ustar rootrootA collection of 40 intermediate and hard problems. (;GM[1]FF[3] ;AB[cb][dc][dd][ae][be][ce][bg] AW[bb][fb][cc][ec][ad][bd][cd][de][ee][df] (;B[db]WV[db];W[ab];B[ba];W[ca];B[da];W[ed]) (;B[ac];W[bc];B[ab];W[aa];B[db];W[da] (;B[ab];W[ac] (;B[ea];W[eb];B[ba];W[ca];B[ba];W[ca];B[da];W[ed];B[ba]) (;B[ba];W[ca];B[ea];W[eb];B[ba];W[ca];B[da];W[ed];B[ba]) ) (;B[ea];W[eb];B[ab];W[ac];B[ba];W[ca];B[ba];W[ca];B[da];W[ed];B[ba]) ) ) (;GM[1]FF[3] ;AW[ro][qp][rp][qq][pr][qr] AB[qm][rn][po][qo][pp][nq][pq][or][os];B[rr];W[rs];B[sq];W[ps];B[ss] ) (;GM[1]FF[3] ;AW[ob][nc][md][nd][od][qe][re] AB[ma][lb][nb][lc][mc][oc][pc];W[pb];B[qc];W[qb];B[rb];W[rc];B[rd]; W[sc];B[sd];W[qd];B[sb];W[rc];B[sc];W[pd] ) (;GM[1]FF[3] ;AB[ao][bo][bn][bm][bl][cl][ck][dm][dn][fk][gl][fi] AW[il][jj][cm][cn][co][bp][bq][cr][dl][dk][cj][bj][bk][bh][ch][fj]; B[dj];W[ej];B[di];W[ek];B[gj];W[fl];B[gk];W[fm];B[en];W[fo];B[go]; W[gn];B[hn];W[fn];B[cp];W[do];B[eo];W[dp];B[ep] ) (;GM[1]FF[3] ;AW[dn][ao][bo][co][dp][ep][fp][fq][dr][er] AB[ap][bp][cp][cq][dq][eq][hq][kq][fr][gr];W[cr];B[br];W[ar];B[bs]; W[bq] ) (;GM[1]FF[3] ;AW[lb][nb][nc][sc][od][sd][oe][se][of][sf][pg][qg][rg] AB[ob][sb][oc][rc][pd][qd][rd][pe][re];W[qb];B[rb];W[pa];B[ra] (;W[qf];B[oa];W[pc]) (;W[rf];B[oa];W[pc]) ) (;GM[1]FF[3] ;AW[mb][rb][mc][qc][nd][qd][ne][qe][re][of][qf][og][pg] AB[nb][ob][pb][qb][pc][pd][pe][pf][rf][qg][rg][qi][qk] (;W[sd];B[ra];W[rc];B[sb];W[qa];B[pa];W[na]) (;W[ra]WV[ra];B[sd];W[rc];B[se]) (;W[sc]WV[sc];B[ra]) ) (;GM[1]FF[3] ;AW[ra][mb][rb][mc][pc][qc][nd][od][qd][pe][qe] AB[qa][nb][qb][sb][lc][nc][rc][sc][ld][md][rd][re][mf][of][pf][qf] (;W[pa]WV[pa];B[sa];W[na];B[lb];W[ma];B[la];W[oa];B[pb];W[ob]) (;W[na];B[lb];W[ma] (;B[la];W[pb];B[sa];W[oa]) (;B[oa];W[pa];B[pb];W[ob]) ) ) (;GM[1]FF[3] ;AW[ja][ib][ob][pb][hc][jc][qc][jd][od][pd][je][qe][kf][lf][of][pf][mg][ng] AB[ka][jb][kb][lb][mb][nc][oc][pc][md][nd][le][oe][mf][nf] (;W[lc];B[kc];W[ld];B[kd];W[ke];B[mc];W[ld];B[lc];W[ne]) (;W[ld];B[kd];W[lc];B[kc];W[ke];B[mc];W[ld];B[lc];W[ne]) ) (;GM[1]FF[3] ;AW[na][lb][nb][rb][oc][pc][qc][kd][le][qf]AB[ob][pb][kc][mc][nc][ne] ;B[mb];W[ma];B[ka];W[kb];B[oa];W[la];B[jb] ) (;GM[1]FF[3] ;AW[dm][en][fo][ho][dp][ep][fp][hp][eq][gq][iq][er][gr] AB[em][fm][dn][gn][hn][co][go][cp][gp][dq][fq][dr][fr][es][fs] (;W[cq];B[cr] (;W[ds];B[cs];W[gs];B[ds];W[bq]) (;W[bq];B[br];W[ds];B[cs];W[gs];B[ds];W[ar]) ) (;W[gs]WV[gs];B[ds];W[cq];B[cr];W[bq];B[br]) ) (;GM[1]FF[3] ;AW[bh][bi][cj][dk][cm][dm][bn][dn][dp][cq][dq] AB[ai][bj][bk][bl][bm][cn][co][cp] (;W[aq]WV[aq];B[ao];W[an];B[am]) (;W[ao] (;B[bq];W[bp]) (;B[bo];W[aq];B[an] (;W[ap]WV[ap];B[bq];W[br];B[ar];W[as];B[bp];W[ar];B[cr]) (;W[bp];B[ap]C[Ko.]) ) ) ) (;GM[1]FF[3] ;AW[da][db][dc][dd][ce][cf][ag][bg][cg] AB[ab][cb][cc][cd][be][bf] (;W[ba] (;B[ca] (;W[bd]WV[bd];B[bc];W[ad];B[ac]) (;W[bb] (;B[bc];W[ad] (;B[ae];W[af]) (;B[bd];W[ae]) ) (;B[bd];W[af] (;B[ae] (;W[bc]) (;W[ac]) ) (;B[bc] (;W[ad]) (;W[ae]) ) ) ) ) (;B[bb];W[ca];B[ad];W[af]) ) (;W[bd]WV[bd];B[bc]) ) (;GM[1]FF[3] ;AB[qj][pk][qk][ol][nm][qn][no][po][pp][qp][rp][pr] AW[ql][pm][pn][qo][ro][sp][rq][rr][rs] (;B[sk];W[rl];B[sl] (;W[sm] (;B[sn];W[so];B[rm]) (;B[rm]WV[rm];W[sn]) ) (;W[rn];B[rm];W[qm];B[sm]) ) (;B[rn]WV[rn];W[so] (;B[sq];W[sr];B[sn];W[sq];B[rl];W[rm]) (;B[sn];W[sq];B[rl];W[rm]) ) (;B[rl]WV[rl];W[rm];B[rn];W[so];B[sn];W[sq];B[sm];W[qm]) ) (;GM[1]FF[3] ;AW[qj][pl][ql][nm][om][nn][no][op][jq][lq][oq][pq][mr][or] AB[ml][nl][ol][pm][qm][ln][oo][po][lp][mp][np][nq][qq][pr][qr] ;W[pn];B[qn];W[qo];B[ro];W[qp];B[on];W[pp];B[pn] (;W[sn];B[rl];W[sm]) (;W[rp]WV[rp];B[rl];W[rk];B[mm]) ) (;GM[1]FF[3] ;AW[pa][pb][kc][mc][nc][oc][sc][pd][qd][rd][qg] AB[nb][ob][qb][pc][qc][rc] (;B[oa];W[mb];B[sb];W[na];B[ra]) (;B[qa]WV[qa];W[sb]) (;B[sb]WV[sb];W[ra];B[oa];W[qa];B[sd];W[mb]) ) (;GM[1]FF[3] ;AW[qb][rc][sc][qd][qe][pf][pg][ph][rh] AB[rd][re][sd][rg][qi][pi][ri][qf] (;W[sf] (;B[qh];W[rf]) (;B[rf];W[qh];B[sh];W[sg]) ) (;W[qg]WV[qg];B[rf]) (;W[sg]WV[sg];B[qh]) (;W[sh]WV[sh];B[qh];W[qg];B[rf]) ) (;GM[1]FF[3] ;AW[bb][cc][cd][de][df][cg][ch] AB[bd][ce][cf][dg][dh][ci][di] (;W[bf]WV[bf];B[be];W[bg];B[af];W[bi];B[ag]) (;W[bg] (;B[bf];W[af];B[be];W[bi];B[ah];W[ai];B[bj];W[bc]) (;B[af];W[ae];B[be];W[bi];B[bj];W[ah];B[aj];W[bf];B[ai];W[bc]) ) ) (;GM[1]FF[3] ;AW[lk][el][kl][ll][fm][jm][mm][fn][jn][go][ho][io][no] AB[ii][jk][jl][ml][im][km][lm][gn][hn][fo][ko][dp][fp][gp][ip][jp]; W[hm];B[gm];W[gl];B[hl];W[in];B[hm];W[hk];B[il];W[jj];B[gk] (;W[kk];B[fl];W[ik];B[gl];W[gj]) (;W[ik];B[fl];W[kk];B[gl];W[gj]) ) (;GM[1]FF[3] ;AW[ib][mb][sb][ic][jc][mc][oc][pc][qc][rc][fd][md][od][le][me][oe][nf][of] AB[jb][nb][ob][pb][qb][rb][kc][lc][nc][jd][nd][ke][ne][kf][mf][mg] (;W[ja] (;B[la];W[lb];B[kb];W[ma];B[ka];W[kd];B[ia];W[ld]) (;B[kb];W[ma] (;B[ka] (;W[ra]) (;W[na]) ) (;B[la];W[lb];B[ka];W[kd]) ) ) (;W[ma]WV[ma];B[lb]) (;W[la]WV[la];B[ka]) ) (;GM[1]FF[3] ;AW[sp][pq][qq][rq][or][os] AB[no][po][ro][pp][rp][nq][oq][sq][nr] (;W[sr]WV[sr];B[rs];W[qs];B[qr];W[pr];B[ps]) (;W[qs] (;B[sr];W[rr]) (;B[pr];W[sr]) (;B[rr];W[sr]) ) (;W[rr]WV[rr];B[qs]) (;W[rs]WV[rs];B[sr]) ) (;GM[1]FF[3] ;AW[nb][mc][nc][oc][rd][ne][pe][qe][re] AB[ob][pb][pc][rc][pd][qd] (;W[sb];B[sc];W[rb];B[qb];W[sd];B[qc];W[oa]) (;W[rb]WV[rb];B[sb]) ) (;GM[1]FF[3] ;AW[na][kb][mb][lc][rc][ld][le][me][re][nf][pf][qf][rf][pj] AB[ob][oc][qc][md][nd][rd][pe][qe] (;W[rb];B[sd];W[oa];B[pb];W[pa];B[qa] (;W[pd];B[qd];W[od];B[oe];W[ne]) (;W[qb]WV[qb];B[nb];W[ra];B[mc]) ) (;W[sd]WV[sd];B[rb];W[qd];B[pd];W[qb]) ) (;GM[1]FF[3] ;AW[cb][db][bc][cd][dd][de][df][dg][dh] AB[eb][dc][ed][be][fe][cf][fg][ch][ci][ei][fj][ck];W[bf];B[bg];W[af]; B[ag];W[ad];B[bd];W[ac];B[ae];W[ba] ) (;GM[1]FF[3] ;AW[pd][oc][ob][nc][md][ld][kd][kc][if][hf][hh][fg][eg][df] [dd][dc][cb][bc][hc][gb] AB[ib][kb][lc][mc][mb][nb][he][gf][ff][ee][ec][fc][gc][eb][db] ;W[jb];B[ja];W[hb];B[id];W[ic];B[jc];W[jd] ) (;GM[1]FF[3] ;AW[bo][do][ap][cp][dp][dq][dr][fr][bs][cs] AB[cn][dn][en][co][fo][bp][bq][cq][fq][gq][ar][br][cr][hr];W[bn]; B[bm];W[ao];B[am];W[ds];B[an];W[as];B[aq];W[bo] ) (;GM[1]FF[3] ;AW[lm][mm][kn][mn][lo][mo][lp][np][mq][lr][nr][or] AB[mj][kk][nk][il][kl][ol][im][on][io][jo][no][oo][pp] [iq][kq][nq][oq][kr][pr][ps] (;W[os];B[ms];W[ls];B[mr];W[ns];B[mr];W[lq];B[ms];W[nr]) (;W[ms]WV[ms];B[os]) (;W[ns]WV[ns];B[ls]) (;W[lq]WV[lq];B[ms];W[ls];B[ns]) ) (;GM[1]FF[3] ;AW[mb][mc][md][nd][rd][oe][qe] AB[nc][oc][pc][qc][rc] (;W[oa] (;B[ra];W[sb]) (;B[na];W[nb];B[pa];W[ob]) (;B[pa];W[na];B[ob];W[qb] (;B[ra];W[sb];B[sc];W[rb]) (;B[rb];W[sc];B[sb];W[ra]) ) ) (;W[sb]WV[sb];B[sc];W[oa];B[pa];W[na];B[ob]) ) (;GM[1]FF[3] ;AW[fq][gq][hq][iq][jq][fr][kr][lr][fs][gs] AB[go][io][cp][ep][fp][jp][eq][kq][lq][mq][er][gr][hr][mr][hs][ls] (;W[ks];B[jr];W[ms];B[js];W[ir];B[ls];W[is];B[hr];W[kr]) (;W[js]WV[js];B[ir]) ) (;GM[1]FF[3] ;AB[be][bf][cf][bh][bi] AW[bb][cc][cd][ce][df][dg][ch][ci][cj][cl][cn] ;B[ag];W[cg];B[bg];W[ae] ;B[bd];W[ad];B[bc];W[ac];B[ab];W[aa];B[af];W[ai];B[bj] ) (;GM[1]FF[3] ;AW[rb][qb][qc][od][oc][ne][me][md][lc][mb][kb][jb][ia][hb] AB[lb][kc][jc][ic][ib][le][mf][nf][of][oe][pd][qd][rc][re][sb][nd] ;B[ld];W[mc];B[pc] (;W[pb];B[ob];W[nc];B[pa];W[nb];B[la] (;W[ma];B[oa]) (;W[ja];B[na]) ) (;W[ob];B[pb];W[pa];B[ra]) ) (;GM[1]FF[3] ;AW[nb][pc][qc][rc][qg][rg][qh][qi][rj][rk] AB[pd][rd][pf][rf][oh][nj][pj][qk][pl][rl][rm];W[sg];B[si];W[re] (;B[se];W[qe];B[qf];W[sf]) (;B[qe];W[se];B[qf];W[sf]) (;B[qf];W[sf] (;B[qd];W[sd]) (;B[qe];W[se] (;B[qd];W[sd]) (;B[sd];W[qd]) ) ) (;B[sf];W[qf]) ) (;GM[1]FF[3] ;AW[rd][rc][qb][oc][nc][mc][lc][jb][kb][ic][hc][gc] AB[ib][hb][jc][kc][ob][ld][md][nd][od][qc][qe][re];B[pc];W[pb];B[lb]; W[mb];B[oa] (;W[rb];B[ma];W[la];B[nb]) (;W[la];B[rb];W[ra];B[sb];W[sc];B[qa]) (;W[na];B[la]) ) (;GM[1]FF[3] ;AW[qb][mb][qc][mc][qd][md][me][rf][qf][lf][pg][lg][ph][oh][nh][mh] AB[pb][nb][pc][nc][pd][nd][pe][ne][pf][mf][og][ng] (;W[oa] (;B[ob];W[od];B[oe];W[nf]) (;B[pa];W[na];B[mg];W[of];B[nf];W[oe]) (;B[nf];W[oe]) ) (;W[od]WV[od];B[nf];W[oe];B[oa];W[oc]) (;W[mg]WV[mg];B[nf];W[oa];B[ob]) ) (;GM[1]FF[3] ;AB[ka][db][jb][cc][hc][ic][kc][cd][hd][de][he][ef][gf][gg] AW[ja][eb][hb][ib][ec][gc][ed][gd][fe] ;B[ga];W[fa];B[fb];W[ea];B[gb]; W[fc];B[ha];W[ia];B[gb] ) (;GM[1]FF[3] ;AW[bp][cp][dp][ep][fp][bq][fq][gr] AB[cq][dq][eq][ar][br][fr];W[ds] (;B[er];W[es];B[fs];W[cr]) (;B[es];W[cr];B[bs];W[aq]) ) (;GM[1]FF[3] ;AW[ap][bp][cp][aq][dq][eq][cr] AB[bo][co][do][ep][gp][bq][fq][hq][ar][br] (;B[dp];W[bs];B[er];W[dr];B[es] (;W[fr];B[gr];W[ds];B[ao]) (;W[ds];B[ao]) ) (;B[er]WV[er];W[dr];B[dp];W[fr]) ) (;GM[1]FF[3] ;AW[kb][ob][rb][jc][lc][mc][rc][nd][rd][ne][qe][of][qf] AB[lb][mb][nb][nc][oc][pc][qc][od][qd][pe] (;W[oa]WV[oa];B[na]) (;W[na]WV[na];B[pb]) (;W[qb]WV[qb];B[pb];W[oa];B[na]) (;W[la]WV[la];B[oe]) (;W[qa]WV[qa];B[oa]) (;W[pa] (;B[pb];W[oa];B[qa];W[oe];B[na];W[la]) (;B[qa] (;W[oe];B[pb];W[oa]) (;W[qb]WV[qb];B[pb]) ) ) ) (;GM[1]FF[3] ;AW[pb][qc][rc][rd]AB[oa][nc][oc][pc][qd][qe][re] (;W[ob];B[nb];W[qa];B[sb];W[rb];B[na];W[sa];B[pa];W[sc];B[qb];W[pb]) (;W[ra]WV[ra];B[sb];W[ob];B[nb];W[pa];B[qb]) (;W[qa];B[ob]) ) (;GM[1]FF[3] ;AB[qm][qo][ro][so][pp][pq][pr][ps][ss] AW[oo][po][op][qp][rp][nq][qq][sq][nr][rr][ns] (;B[rs]WV[rs];W[qr];B[qs];W[oq];B[sp]) (;B[sp]WV[sp];W[qr]) (;B[qr];W[sp];B[rs];W[oq];B[sr];W[qs];B[sr];W[ss];B[rs]) ) uligo-0.3.orig/gifs/0040755000000000000000000000000007723003524013066 5ustar rootrootuligo-0.3.orig/gifs/BsTurn.gif0100644000000000000000000000126307723003524014771 0ustar rootrootGIF89aЇEFW56Gh&&3qI !d UUiXO2!",;ANuM !)  mF  ((.802>&?"gG- zT, Z2rM,3>@tmLLp!?,pHRS Pl:E<#|hٶɐ K s#8!< OfC&yhtPcU&;P'N*R[D?ĺIu˫F`qs'fF#=ؒ]y! } ;uligo-0.3.orig/gifs/WsTurn.gif0100644000000000000000000000133007723003524015011 0ustar rootrootGIF89aٸ̢aZਐxvǺŽzo~}wtupmmlihifddaa!?,pH ȁl&hhJс H G&ӘPv\T*c0&*u[;p"tey%&)/[!SUx$%{.0Lo +2~Be#))+08 !+/-?  S'&&.*/2BT ޜ',9">ěǪѸ,b!`BC!0P@ : %!^;uligo-0.3.orig/gifs/b.gif0100644000000000000000000000015307723003524013772 0ustar rootrootGIF89aLKK! ,<πsP{\ |Anm읉K N!r BФYJi;uligo-0.3.orig/gifs/bgd.gif0100644000000000000000000001415607723003524014315 0ustar rootrootGIF89aP!Created with The GIMP,P@ (A*5,)ɉ^Z_#ƫ`Np*QYBTP)S9DVOvhz*Ud-0*{YH$*RPy)A rX &D^wL*h @QfpA 0@*@z+g%XMAZbY1E $* 2JXS O|mKCKPvqհa.RM,2jf3ZbTUe'J8/+pyAWD}  6*)@{imݓ?/D${Nn6Ti7v xv#}3*x5$^} 3PC 2ĠB+j8Q:Ty. K @s3I! Z@A@6@wvB Q`!(` &% !8 f_plr2t_Qߢ' my q$%$ׄe,2"bbȫ[|$,E nPo FXB A7Sb1s `AumDҸē qR2 <" ^0  ^P6T $/Bf!Y@~=c?і c>1!l.rt$Y3| { „  _uB JהRj\K80?|`` ?= )R@1E&Sdf@mKX'Q='T)"ZNu3DE/F P/8%(T|d$`34s &DDdV4: A(S ŔK J&AIel/e@`ĚB@!R U1СEm(&SPFR@^쀝>B DzSZ !S2)!uVP24Jku:|,8j5&)B`U5bA >'n?}Rw+l)[f F5CVI +`t@#.cUJ~)C@vpͶ3fKA\'ULw`'7ݠPYw \@^'6=ɨ!*C8 AP3K[!m$jc!1*YAː\씙isVCq"f_1F! DsXcL(!A blܲy [,9uD8BcTGp|+%~%AA<%|3Eha@a H{.t4 @!L2NWEZBJu8͎= l[ %dm}]E`gP؏0d_v =@Jۢ{o[JC\ofK_ ׵WBn`Wp{r*`sQte S <ʃ ъcԉ 7"x'̗э~, 2rU¶K"rs3fyk>$@D}t 3%+!qHz]3Aʷό>)! э|@ÄX> J{ @u; / {:@D;48P}duۗt}gEXa{4(OWrr6 FsCAg> u 0PTEZp Xe e76}WC]'vX:e'"s 0qWK7YPWP~~oǥU[eU|37uP@CBt.kA%n#Lo/[QtS}VXXHZX~I$5Kt5a-RP5Xk Ad^LKN[1y7PV`G#ҵhU!J[psK>sJ+ POY`T7|d4rh+%vuV8hl4]f6ЌDA28LW7Hl:70$L.0@a>P'Аgu|RCtXTDTloK&hz3l&I_(y 7 `&jISR Y x8Dd)bu5Sh4&y(1"!W#89#Cx|:ċ%@d#HuF|uxQ H[x7eҕxEHBZlnL&cEAvyoQ}$D A- q58#HFo=H9TzLlH Xȏ؁^9j:I&FFo b[9WVEEPُ?":R A!RWxUru9Q p$BYQ ~ٗ4tƹGb0*R&yUqtrꆝ$yreLT q e,iA@HU\SqTQtzH ^!3!T'EVTH{WB2 ZO@0ql T4~vh\2ѸhNjAȨ3@&TkqnJŊW xڞP3yWQ詈FQnZ`(@hT(SĦWpLIHכEt-L@15 8fۂF[a! M ||t@PD !,a=5HU7xxJqqGVH8x sg2K<$)v lLQ\|=wKљUYZp ɬ|y|8A2m9)Pw ~Z ozG0aS)=)1}Ԭkp%0 ݢϥݻ+=Lݼ4LՊ&4):D![) C-ߚ ` |ϩI:AA4$޴IL^ ^E>j'~-0an"^ 0t |t["XCgcs0L@׵ Xtn.ztwm@ Bm"60]vWn pY~v`^Bk9}~Qmn^tpKqyTQ/HW %T_0 ~>a$n D ZeܷAtv -g):6 xk}XqP^.)Nf w#Yue8mV,:N)|܁ZZ %` > oP0:Rhͤh׸4mOB=S%3bp-JWxE!0 o` Ȼ؜8Ro -P˄e)Dzqno/.cPQ}HVpJPop~ _em ~ 0YɀN`_O۲ZݧNPU!0oto",{/ pAu{wE4Zb/>n=* s6n[QꦺPPGOoO0q М4 auwШ A?ANc2U-b/T@T\ԉ8@Hp n C@;uligo-0.3.orig/gifs/black.gif0100644000000000000000000000247707723003524014640 0ustar rootrootGIF89a==mV#JJVo!RScrs;9Cǚ+&53<,+2RA #!%hi}&#) "(&,*(.0/7A@M6-?5"Z[n#!*&&~`au/*'!,=='d9"("M횚x)Zrx<xz #`L&\.́%meAбX,5fjln:p wy]|~ MkP&*.z^adh$r}*ʤnλyzśRͻ\عcѬ@|O2إBљ<٩CӜ>՟@ӚJ93mδ uLaKYPTJjE:7&4ë0rWMa1-Jm[U|;FÙCi ͺF5*Wר'p弽Iod!aC>>qX/5 z K2谍Ujnʅ kPޟ۞Ѵxj/-08gY 7$5ceucpҠ"Wi߄$F_f`5].xv]_[&MikaeVU\YWXCNcG`0V 40q~d39RNYI9B ITS-XfuePGI4cNwELt!)V'ܐSUEDrqH0 h7 ؟J y9nsaS(]y^Q2둦 ` *:gl[]zE#eje5&، (lPv k(Ii n[PK6Nt1Eh-Nh`\mq8Zv Gw)~,* e*c#ڰ"atFղ;R7-Ymh7^0%] 콠Z;ų؉HbeYnH7Y s1s .Vߚ2ըNXFKփsjM *EnN~. hy#H@MY 8ī4R˕lCx/ 6+A"٨KտlsNRbz=].c[|Wb?ԋ|*ܦK•)Bؙ&}'A_.CKO&Md]%쐟MQ:pf+@B˄AcB mzE~N0tz"vYXch R e[_Ȇ1}@""-d2XdtpI\DөKpx"!ٕzh=SGErlJDV6"HQNG5P! ‡P<Q) LwTY$<սFfyOvDq1T.0CP, j[OKhֻ`n(QdQ77uR*?Fe&ݧIG.̍?\ kHA^,ӘN:$x;)a<&驸 qX*25$%aKγC|n(FYc(a2j[uɟD {>5{ *SGsq)%Lv'.+;'v8]WM#mJsˣGvF/WK}tZF`㺆VY6WVN{hL5A V+tHJV4R_?G%s1sh>Pp.l*A/tT>TYTR4!(d(f^v[>4bܮG3ﶨmƚ(॒#gmf.jVa3VVv4]U Dx GX#^5Ͼ*h8ؾ@#|*Rθ=,_BK,I}2]6˦M$Ck: r,ӆgX J[KFr͛*P^>{4Ra&gD26@槅VoՅthNUvZ7ܾj*Ԅ2̫v{!? -p ~&lDT lz[Mm\hT~='nEGa-%K+L}+{iڢ5$%wJMeR+ l/ xӘK^serW1x{Vrk4Md>M׽vZ0-uEZK8mF9r)}RK6]bh{կS9MBOpm\6{5[yC>j9aK3-Gtگ6ӷb_y+iu4=B:O%]# 'Jeϼ &#RLXqvYV?%SwBrb;T fp'j7sWs{Ul}kO]Xx^3^fb>E>j{IWZG%7}}sFgoP[wMu8}5wtfew.T^{vEvm79omG~@g xyjaGetiBxh$x7Z5xSny Ȗjr^"sÅ~fQG0|'U4Edz'_(`51Ѧ9h jgK7.Xf'w}f+8nKvR~"g%I~P8~8h {@~~Et; Wmgbxxdet]xd5 ׆ŅCԈ86j&MX6")Ƃ7ăzB?hSA.V`}I&95/GOy4̨ƏuØt4.wsyavHVxCq$F 6r}ƄHauy)_sɘ:gG׏"XIY,c |7}iv3L9g )ɑ$o5QHyx%ot"q \Tx~ȕ Z ښ啩XBifzbT; qYr}A!"R} 0zh n6DjD U嵠(N~ecꦃ?ǘbVʞY_owa:/ Xm…}Y9"94) Yffwdjyz?Y8 2d61ip n JadxW8mwnٝKNO:)cYrUڦ'O_5_jإLJ@jw)}htJ5Жt:n{wj*av&2"2s!b`8VW%x$mٛ?R8Z:rrT])9=fZ;H{ sNI#Y&G*hI{nbZb 4 );3:5:t, .Y:}bu eғZKZ Z"˖Bh*xCQBp} :s>e7D#w+{ ( +^Hڛ&۳4|>.>68  ojIEDo_Pz9§~8ck꜅(Vj3ZxaFSwia#4>WgIX[˯{ʨbb+Z ,˹{pj2X̓cHy_7[;;G A}J[뭺HЁ1+ۛQ; W"\^l!{e4.Fé0ꩆ +!6a &xz;V*# ;;۱@=!eFK*;m2{[z+Aj| ;YzrNXki 긮Ti[ۻA³ N1W˳{7,ÝTb? ;y״ kG8f;a1XL]Q(h`PD)6[Zg|ժk,٠Y\q,Sæc(F{]\J{QB,G#L%bQɼd˶˺F\J |sPh 7\y|Ԭk,eJ'ym$LFK\ɇ>J\͛Ћm=oݶ#HOT,ըy=Z'=ŵk(Ώ=l0[H;-m LzS'0O0I۸zo_HaȟۼJgӚ6վT1ʢR-}ꪣ߽ط<^ڢ#{MIؒHLҩ-Εڮ-[nQ+MZ-]ǀMn NgfΙlp6nAտۊbMMjܰ- 1 m[$s{y!-?)f)M!:=БrLθنnm;tCl?>]@}̼gNinlWǠж0Ew Lk(۶f_؄ڊk ֐NNavDn&o*|E@r~} ).,vTw~ LDZ)kKыm6pW.7ˉo^|-t ތV ?~l#ެz\8닗 ]C8՟ fyzNn^}ADa"&L]MU8):I@Z Tw?^Lz4oG9F+nL~+A>W|f^2ЕV?tVDƣDÆC¡sg)Bӈuűa4A:x#!W7Zr9քBB(Ytek-lܪTH,|f+ ]uMaK$(3I+h`}HfH 7.ֳ'Hޥq|E'M |5bf[yҔ <19 %.DxB(rv͸#J0Ӳ%E19Ƭ4](SטԮZn٨){ŴZ: ^Y{o卪l ` j45j^dp3ն9yzz襶iTgni/  J7|Y/V!"SXkMAjtP66K憽vH=Ds;gѠdL9Bw)gn"YH}j[g0rkOĪJmB<\}oRJԋ(*ɡJ;+xs7˪¶bд]uhܬM.|Gi5li/6*5AϮec;pu')pwݩMiYq윾,&/ n篌s \@3aIpsXNF8)SqPH@ YZ.'ve a¶A7S gx6~2#׾ -U(ߵ=eB髁p3n]h̄iQf{Ti4\WvVht |az ?J-ӗThx È:lS;^pIGR#-T![7\pA1"sBwN0W!Ҳ:;"i'1Q{N (E1⬊ F{Ǹ$/d_Fg4_>XaOWVjKo) )kd@ ebFީT,$C0ϗiL\haNj0O-ԟ\l-L S FLdgz%+/%tQw'vOXXSz7ZU(JkW;ғzcԯuV(!%8rHcA-85-~t,OE;Q~nb?D ~顠!ɲ z8c9"Gcy!IW>%W>2OWRDzؼfƩ,-QI1kYXٙOUd*ZG:–M.b\+^"&J`UKxX}_({8 c&ix; ٺ2dv:E4,sQZO x~Ű Y[ 3V N4qҊ'qlbVS//Q.[˛!{Lϰh{V1 NVȰ-zs-B[ kM^Y,GK\VNȹwNΜM[K3κ{jy~4sr_˃\017͎GSs3sgԢk.0'KB<,¢yZLFx4S#Ċ4Z0Gj^Tl4]\)mPVMw2@m`!wtnrĎc|yŒu2 6"Y}ܫ&%J'huS TN+s$':`fuEǴGk9K E>O>ZNl/7Vv}}lSy@u!fHF|`H#ASzzvIdwMwy {`G|ӶՖ@|'vY||wZ7}_I``, }uhWK7\uXx"~gv'H(RF6x76Fft0sF (_x^6z1X_xzv_re{NC!|ssVaVfoD?}nx[ 43i$߷1n#$C)UL]jXo-HjG%p^ 6JB}  JHtHws)U.hPͷmn7˵0LC8eHnF7{fyC\Hd|fg8QvmBs6TiW@'~wg+~7`abrh(V5k@y7'Zŷy@4tqF׎tE8Eu +|ņh]w|Zd%`:Ȑ(vpZD(hx#G([X0E;cكׅ0GG&H}wͨVEɓ02yAyBus(&~fx8)Y(noEgp_9@Hzy[h,Ɋiw)V6C#҅HQ 9ycfTs8Y(&/A?79xȜTz t,IdzȀum9vvWmGEK•i;`sȚMihh 4'YHhIiue[Ow+j%yiI5mɃ֩Uy k]jY$RRv'蘦 fIhI8zrYq@$ڣYC*j5)(yhzh9i;9+**D *|"TSiIq9ڤ7)oI>}bzsk ) x4y9cIa,'@Xs%٠(joڳX ک?zJe{':-բ{ړ8@"[MvjO A ) )J ˖c;pxjd)kwR1oZz4[;7 էi_+)ժG׷:#aQ+bU{ղhe<룟z3e ~A8|ҶK ˗JʌiTʲQ5ۥ/iɘ᷸ψ m zZYeZx9Wۍ٩z.QxXKZ[3* Iһ ۽jK)J o%iK +тz|;S\ϻx[yW"l*tyZ-ȵູ}K} L9|tO$묓XvxU&RYp3x̼}-buK 5YzeDN\4JGchg, /˦o㦁vq*J\|/NŊ0Z?[\v̷Iې6k:7u5Iúʠ)hFFhXÆL0l28lxǏ괪뼛y们| Ӛˇ_7Ư w(f<`;Lǵ& KniLmp[{vLiS ǽ0-bͻ̤@wub5(3}hRR\ܨ[,s ,\x|F}m]5dZ5կ\V2i[` e) !a s= ^MBTKœh#x8YݬEJ7\}+<=xZ͔2jE^؞JbV-Ww}ຉ_ԍ2 5"bl}w}0ҌnzƫpLNG+۬l4팙x-Ʌ>,iJh͹KHSEzf]i}x>ֳ.-혇^ӫ1Nކd.l7^;1BˬNUǠiJyUw^RTޙ A~OPdMk^+MG,Ѯ홾o~>>_~ q~화n^Z)-pLO&bjm0?W_rd-VnX;e4\8 /V _՞l<:\+Ҏ4ŭuE*r}/ ʪ29x>5m,ހ(NMy]\۫tO̬zCE_8d.v~o/t!f[G6? 诿xݨCE@J&KS̤A@G@5= qZӟP6SlW|IH0Pú#g20* LjDG͈gaSd:0I;%ScLymO[NfxE<1$$SFvAy?VIuN"y2!{b6Iە칷 痻@;j8՟ץ&&%Uus m\ΡgQ 64R5"%*ʒqB#i]ecu2#( ކmWFKdj+H03(M.)ʪ J)aIyQf=nUU[eіcyX9DڽriǛ0|j=N먩q.1< B^yVF}Θ$&')$Вd \C:HVWIQ.A&Jf [řgk̜:&#p g螑IIކ2|xJ: h'e2L0'4XTέ6TFjޮ:¯ 9Huj4*֢s7vzeo|6?wsq7!ݰ K aoܧ++Qx6_ĩ0r4EI'Bl5,3Nd>5z3ƽT ,^l|} rEwaX>u+`+ז%&yg)BvҌgń(N$5㑏y/RGd4Hl{V?9tnn%#D# e@ns ?CP1].ċyB:HȇO,UbI04pغJvah"DH^1Bϔ'g"KH/PV3;RLKXR>kq, P4QF'7Yr"#ֿNva g7L ݄!ԮH&pTޘfy-`l)B9MNP t, bSB -> 0kC5t!hG|⚱PzMV ]WǛDe(Ma*䁧'z~y'PjP(< 'SH6"R[:tz4%%K|M@iu +,GDGT \&'Z= c{zX̦bݣ[MP3mD .^V27US"8 @;]?{*4J? oa TdN[Ⱦ-KܖƑVKT%-}9y*\0ŁL]]zpnz!𗼵i^xHPŴ㌘#yTuMWu fWVY Ѭdhsc^|6 2L嘻d^_Tj6t ]%z`v,mN.`?jJt\ifL&sIA<7qa@O9M7Cnw{fV,ZDSVYӆ6IVX{Wwۚ"ɽ3h\f7iδ:3s($Jy6MC:$Fa ]aZ: Rf-Tzb^vxwH ¸L;:u!TdN"J]K6=)GT;ht mL*܎Վe벷٨57OnI ȇlʲ:Qky )pV m.8H.=ZWFs@{y}Uiջ>ΑKkB|.snŧ\e_W(hM=gKDP.A_ydt#uf6p鍗[ ES`d})wWSoӴl)NK!ߓR3~&NߟwCy} )7ӧ7rDJzWUc"MF4f{{d]T:=h^C teDf_vty_gW7|%DuvHn!+ Hu|B[bo5vb'Ow{(ׂ~ARaguVQ u$G~`i66^8zv7fm³j87=] e> ^yIk8xwG}n(?zl#m%_'v)mM|Su݆~{'Ugn8b˗nZ8)}vx=^Hv?K؃}O8w!$i|p3Ec~8'C\pkxL8s8y¸c٘3uXd`q(lŇwEGEwrWƁU\S %W 2{koy<7,R'xWăF_Xbht}Ivgpz1~eYM.q~WF`3TYdXXTqxY`Ety*Bl/iPXI68MIfu^=׈ dYz1TR-p[4x7yTy4ɑɅ(_r.0e"-WR8.uwy,iÈ(@KUCq |5bԘQgCiQZ]IiyHTyt9qyY r8m%N֖3ȄX 8Rh:}I:z$cvj8YttYw)#bcNj왞|1ɊYlXU6fך1>))]kMb&YVyl\rBgyb #dنZJ#Ig 9)8 N(3f@pꉑW-[@&Y9QhyXCْ0w䉠ȌqP,x$pF9sgLI Jxcu"yȢ~Օ/jE9؜tc {yfufQ"V8 yXiX?æ| KY{Uʥ?لf^ `ʋtxȨEUj jf혦p׭ EJWzh Z$n>)'Evsa><71>' .8X|Wģ*B[zğ! }(iNJȫiɑڧ :[tZoٟ(p w֧-a2"c7g0;UEUxvK$J!;߳$\bQY>kio8hv8'وq9ŰhWG /H8:ZX& :xZ%`mjOh⑈A֘1{i~7`4q;jc?:Fe CP\ˤijZd[**ak5L?i} kۢ+m;` x9{[}[Q\K Ϻq%GصQSԶ'{0;kcP;ׅLj|A;.R“*㴎$ku#K¯gQiXY[ 0, r9nR᫷3ķ)k5k-%tVи+ lio,EH[n69}uJLiFj#G1s"8,Y1TD Sc`Fk:ȡ/Rz`UŠ{ǁf{57ܡ+۽1 6hrH,9 .NX'ѾTlV!d%,qwzRl]VS(aX$ݮm֟zݴ]ӟmp[nl (p߰ne-M)+^[1]?~A>38{ KeK>ŝP|>B؃ [\>n쉗GU,悽|1\]1~RJ$'|뇫{ڭMB.SYR܂6̓Ր<եj\oo em4<0ƽzRA`'廙Eؒq-_-˞qϞ^̍ 5x>t@ ]:O}ЕLMm0*>ܣe=V6jip1+nҧqR[w/]CՄgpː.ޢFm JpB4`BW2S4صHY1'4DhtA$e)S 6{E&)C(*ڐus{ܻ{{+ ,#FUaR<θ(ukCj%{iElC/9GʌDPH6nAz bD)S+[c.zcm"c- p.#b!LЂk T4UxxnVV|i4)-TV3J UFwӴ{F c)č#Mp#Z%֙$ɀc}ݸ7VqVxGΏU2I8pdxF("O"Z‡PotpY4Fm~6fj%!/rAdd0? )d-5F~v^*ețQU`ZhUfX&Szjz( frR[7:Ǔ[&b॒[Ic7!mX=P!٤* "eыEå'f1Ƨ?vj ʔqz!Fps[NxT+$-*4ء$*5F,whAj8*nrbXY%z 婨ar" WfBGDزL "5Sz6$y\6F7;0߀̖#6t_O!DI\u >vArU2u^8?O: `*8R} a&hf؁e}735*B'6}dћH!/]Ϲ=ky&b!u_e8/Jݢ꽪ow[;aJA Ӷy#]"/e\8-/Ꙅ: 4WA9@@ x;֒];ץph{\rC۱bNLkO "ЀYE&%>!42G=/o> g7ERáE$< >M-#vv *wGqnnx\d`RdQ}bj|?&g៨lG.ix& B]NBy=aP*[0jH=zuaƀ.Lp%dc70UP{6VBR:}Ee@!ߧ`~wwiGmRѡy2qk3Y5k"Bj\<'gчRDxjƁ"_-7uzwqN-PTI/ 6{Khjxerg~uw|u|K_YCunSgW!ހ"lYs%SqWva8g\R}5p(#R"Fq+i44)gqNԈ!9Jxrz,Ge?$1N&A(H*s81z8^He4ym߰,Wx:%x^8 XG>)_èؓeʘ[cKТʢL*jW~"{Cᙌ*HLgT^hp^@ 8WI3%jGrq9A g9iZT=Bhja)zEİI #!ym3Šix'*|(J8*P ;>̊ŌJǕ`zNcSժ9]+#ЕYPce 1%*׉e;ŬUy:z՚MpK^@[Ftkᵻz;Fk(, *'i1a8,鱟2k9zͧHx$z#'낱j1ʱ6i4*1=* mC#KmUiߢʜ6 JbA[A HQ( SSЈE>Ӛ"Mz! AS2ZZ;OZZe2? ӧPZh\ʚKS1khʷ1l 5>IxJ)۸1 Czi3ɣٹINˑȲ,k:m4KȈ8+VH|]`E˖j"[[O[Q'Y<(#^kWkf hں\*NFY4[Ý틍*nu<ܰwicLu]7FP+*+QIf]_Vx˹0QGyK;s8 <3/ۺ}ayXGD},' Az8T+b9BMIsz![*ܟ콝yT̶ػ(|ƚ reEpl)ƅ+; +y²ǔ<~p 2?ړoxϹ[3+X)Hu e;^ ˨4<8L:Ʒ,#(Lȿ:kRk`AZz <|fq8*>5sǑ5ЪWƞj 758\5Ɖ!ԥ <+!-^MN<ֱ{ <ߒa--;9fi¼PpZLͪ6Ү҈Pˀҹ ΅˹SUj Čz̴=~jň}q0cQׄo<V#8i=K:m˘Wŧ? 9\ʖזr4ۜ \Bh\ܨb՗ 3_9N@j"{Eώܹ> +k4jM;lց\˵:k  ӃEi>}0ȁdLȜ/-3' j]+YU>\ )䊼ޛ,r3J`~ bN']}X,⁑J{# tѷ~dD_eBXc"̼ km%l[M}^iZȍ[]J^J:轛 Z.JO>-V=1>!niS1K-j~Cnp-vąj.ަ OV^Oο2%]E?hIM寋Nnh|?}@f ~ĎBѐQ=R>U{Fy-x:T8A63&7ܗ[fbM. ws߿-/.WJkW`>DFÃkȝ .Z9nR. .# @j!G{|`\pDRЀ3zR4ЋJ!@qqPJFEv+R ^NCI#Lo u6<Odn#{@%Z{z9kS!lgUN%~2U-+>9SH$x{j.=OWn@sIayGVU"ks:(k@68$pjX]&´4q7V#־C͑S6`h¤2~ iFב2bwнPG$L '!*y ZOv2cj*fBGa]NrJ-Wq7ePW ФܰnrUɬoƁ7m8S(MG]|APӂ9kgܴ7F+Ɠ\O27 a!of5'$-qK d#8Q[bbB9gJY(7],#YX {In`}<[dbtU1U$GlN\"#A5LIhIV^qc2q,]Ucю d1`e'`^U![(!i^Jk{};X3[b-D\&WtɔuR}U 25%xxx1MJtpNZݦ ~^H8I#cUbaJjiw!g2zn"3ZiUbj-eq Y0qA$ hJ~r-%K:飞G RrSрۄF -T$ǂQcBCIŕ zC$إ'hd:Vow27ƍߨ@!I;Uk0cܑ8!LguR'z=Jfs~9 +=r6LB5Z shǬl6Zt*_\{R&-[LwxTôk|8#3[)btAnۍpdjk@䕏'{ 72̀8hpl_՗8΀[^GBQms#L1Zrk ACr f:ΔǍ!Mw?N| =5,6> Ff汱fK}N9wӫ;Ggb"| nÕ5n!\@TYn.XaFE9`^dCW !T l!a(5I`p\2*%BK7vudzf%u o 3ԅ3Cdsj:R”S~"#0;g˛/ [PF]G|y͠I(d<$vFgd8Brtt% S*}^c 7D!Ձݎ-*N`EbOG*CQW*7VLB5"[49Of$D=.F|$ں憙'q7ɻ"~1wEM'Lb94ndzqdJ!Zgژ0K Ef )DLh,iG 4+edR (TkQj%TL bIUkg2|4L)*KxQj*]֤ۺk:npl*ՊkMΰFjw1MY6ݥD˶M5\۔:ϛPo\Aqi{g@89*}$[|4+g.4, .CBD/?nk|hŮڙXR"-B& @\ T̄;ܪdtdhZEu ab4ݮC]RUOZ7ȂBsԈ<ޞUg ߛz4Wosykdb线ѯXAX4$^2ٹ C=Q c/I>sNXskRJ!sW^2rL"SNuJ>u8Χv7+o@7O؍w ޵a+}xqz̼ujGڤfh\~n%d|=g;N(wff?UHvd(8T|X}4Wj ІSru耆H+&{5Qx( Xyy'xCXdwRz*G .T6xՎek[90{U{B'_7{IiT|)|HC-91/T7L3watB䵅h}CW}}Yui~يngoO8w=)h_k8Owh&ǕwHim'PbIbpٗsQ\s&x舟zi?zz8du5.l 3:ʔ)]?șD_/_R1D!vOAytCYS$GW9~vufܨIwWUi%W!@Z R"_9PV6baIj Yly㉙K]z u(9S( m!Qs SmǓz*('h٠r]2]{ұ بf FW͈vuƅ$꨹{YȔZwhXcT  SipXx${; tDhZqӉq܉%[V ~J7vz"z_R0ʵ~2SF kpiz~͐dꝘ5 ժJ_ڤoɫ렧ECزJg 2+Y)GgZEzB'e뒾J&NP[:*0Y+ڶ{ūfɋgϨggiKʨ뺢LAO+,ǩ*X;B3vƂ(xI+VKjY/\9B2kk ̂0Ii8AKoJq*vm{!K¼K3';P=ӵ sV";WhE>'ڢ;dڸnLI|\Kۣ a5H%`;I:KZpRjƔƾm(ƜˬAgCΊ |8# ,kkpƞIƈwZZ!s+ɡllɯ|°2yk9]]˜:㇐y oc,(;*[Q.&L8ƌcS"T yܙ܊ :YQ,_vHΧuDi~(蹷qt=VG|&=O]~*_wxqhO8%s̞5p64K谍b^,ܠ~ [Y:y>._eU^LEWi=IN><޶T~iN\G>.}R^@x lȽ=畽.>\9[Y}>A0߿~sMQPm8_>a;{n$TW;pɉ\w?PGWȮ/l'~R- Bx;?t) {ӵZaPU=RdNx^ ~sq\6Y#j\㩛0OmTl*+)dA.X \mfaS` FnP*:P {Ȃ!QHE1bTn -дW02g t"!#p_i;0RPwTdXs$5q0x(`Yuѵipt $y)&z%䩃b; YZie[}w:#*- CL5A"&2mrAݸ8P"SL."i:e,.e Vdxf yf mwb7ЁQǞ@A2bZL[_F)j8J R"Ԫl^0a ݤƔ4-P"biJ\kVֽPgMai CX#Zl w2'AmCW6;ķorʑSR$ߋe mVbpp޸I.j >Jk{<89 v$矬J;9Z5Y`ypAGSPVf&z'TteqFan1P]uB!u^5 !J0];U2"@- fL)5Q#FP%wh)='^qwDQpD̓O=q-M @L!vI3fC<$^|eH#{Dp*YH-@KJFO !Qei@:5(D^xXՓV䞲0X؞Z \JD&Qa&ؙ]˔!&撠wgdK iٿMb1ʁ}j黸굝>'v)n &eG(tfeqdewpe qh- 0Is{!<V1M4Ǵ$I4(n lÂBRe"qlXhVݳvtv.&U\igo5HHܿ$c׎\1䪣vdr eLo2[^s9]h0WL: )FLe9Zm; >]֙v@9l蠵Nh1j[Q_KwaPGHluwf}}C{)z-o r@ll [VFDA\58'r.]KB^ G Y,yG9@fғ]UM d9,:ٝB"U!S{čnD;OxɟrJc\CNjI,pfdV6545Hթ:CED%i9њ8jE ){A緷)Rؖm-)d /7Rfo %N,}kpw ' KXN9nsb&%CC;!P")#0e:d29w Gک0T_G[SwE:냓9VvF@o~BMI]![hZ+̟> :ͯ&+OiXHlgK\pm|AfvД c$ND=Bla a7 k:ӅW2岘8LX0j4j&1tsQ'vDa"\K7,/TKSŞ؜M3^|#7GU6SgĽ*9Q?TTr"ګ>R[=J`cDʶvT Gւޓ% *ɻ%\+QеF + Wdq*[/]f&f R^ Cv'ww!3Q G,%4YN,jX l)ibEs #>Q"߈=h#mm(q ot3lw3 glY9IKc%2esq9h!E(^x6W'IX7J3xqz[",lyyNͅC|:ě=\+*fq]wW\Nc20\)c>n J"NPYdpz'ڂv8uoE49f >dlMzndq@eS4]Lss7;G$];GNPO_3 E!6t ]Z|0 Y!O9 ]u,C^vhbYO3Kt:Fl=R/=lO绵LG;V ڦqwJS> "='>b,96ޞ =EUYnw}8wAG1Nq Αu0v;јKya12U4 jR[sYC ޵>wTb`A-8| uԟ]j6-6.с(k۶~_ߊNtia=9~fwwlyaiEx{4y5us N+M&6;tqR2Viyr($lQz8_z7 m"5Nz.zGVW(?3~gkk& |#l>c4΂##RMthalXIՆdV}L6uٗPvlO~A_yvd^t`8Ei7vLw5Cy9bwpi7wUr𧇧WDXgFpFY{yxh:`fgX׃i^nqa@z6x5bigU(jX{ڥ*BX'>>%aHhew)'~V_[|tVeuƌF}4ͷ}Z&qDq?n$pv#%ܰ{1xoXvXs$@Shq(N `1Hp2hqm‰w2'V8%a!a(MFҶPp%D4s6{&I};+8yI)@'7ȷmEGm0$K}lRV+tr#bQ愆ebǣys@]_fvwDlxf& (ywgV(y&$ЏI9xRLY"*y)HL1ycLHiqhXayG)Uc".r8NY8XQ fË5 7>*Z7 ([HN@&T QYԙJ|}#rD}Ibhwe}`hz~)hs84v8VJֳz2w7*yQH*~Y? pEX*ryPFor$r0sٍ%9n$sPrkv):zK9RWeɍI~ʙu>[@8Yi.\`ޘy9B|QvQdYi⹖YX|HM!F wɏD0ɀ'@6{xSTiz :mwJ(w撢Vy"zN7Q)isI`BAcZ՜fÛ78!nEjVPJYT}VЩɍ'G`fsHue֝X:}T&PGǂ#ڟrjiǫzzF[٠wkzWHאf,I ȭ1Q5(0< i~}ZWr,-Xؙը9JJjWYgY YJ"{AvYOZQiߢ|Y`]x 1B4]Z5zиӭ$يz x*yjȧʪ:֬C xecV#Wmt8 :j4갇f#eKX鰱X=R(%0 [)u駆Gўi[Mka{GgIvei*ko)릏8PE:C_[YzjF`);iB:N {vGR DzY9+p)7 `2,K) /y5J /IzC1TMzZ.aȚ54jjʻ9$xSqUp4Bc88DuXˋi`K2(Fj*w4%̖xֻ<Khg\PTcK ; a뚥k +NYJ`L7UUGD9rl'k#R`1AdxN'Lv»  '|wu<Q~2`g=+VEĵۻ۽J Zl}ք K%r2ڰilʢ+ȠƲ[\̂S l"u- Llib)쉰TMH"ħuٴ߱P<cA˱훀 #T7=?|u*4vqKܶJp+< \|̚6XaѨeƹF(K{|m|4i͜P"xam@B 5NYT(2֧I~l.)""h-" n }ܳ \؜EzK!~? ɄPg 0[;IJP[Rv}njSly ܋J_!*DfޝڴHOL--PuF1D(8UidM˭Z-<3Bӽ:Š l-ܭ>ԯ[F3MNsI姕Dịؿߐ]V#}ļtM#ˊM_ܒ4L^]>x8ԸVmՅm0[x\ܯ*& "v>$Xђ]~|'M+GR$\{y]==; c; $ >fٻ<Q Sng4>%>ijB}f.K <їx%.ncȢKJȨ EL|N~*PκcV>SjRʞ(/7.eKU?lLQt.vn q w FjۥPġ\g\5_g<+=ڰ,8;\ܭSe]T?\/6R 2_\Nɞ?IO*>/5m;l.ƒ{i{˄?=e?4/Bq?L閬9}_.~ť]Myb}ugJx@dJ)`23գq"p7* G=f*ϖX&@!"GdVq|)5LW:R20J#ҪLkWoTf&Hr=t&v9qDBp"x;4=}4"A^2Ll`C>Um[ Dsa\OZW"qm|6[G+TCs hXϮ\7>cЅO(FA?'BLh#M Gh{@"er̗y}91Gݰ; a@*A* چ~k VM aIJ)]utД EW2-)EdaHZFF#F@@0Xt`Vj$\@TL,jpڙu`G$Χ~eMn<]Gwc1 &}W9qC%Z-&, [Ꮚƕwgljۈ2fǃ|Yw3S6D4h_粸#l^:wzBgKJMMԴm8N16QnCSKbYFTA!!V +^|!b|g)X^mD$!v͕[|kr vL!bE1&A-6Qr՘\0H~e7(HT&E䢍f}A!Zq7@0Nqaqwܟd2_έgC_*ZVAu;1^=&/:IT+1IAScaS z3)P4'Nl[bqQ#@or1\ڊH!c2rcbb78%ւY6X"E3C B$F5fzZ 9)'Lp}iLDUIň<ߪĄ9P":]]!(E nMl؈r"~L#|7?oJg*%ч%z"M4Hbfz, 6L͕|L<)〸4/T>v Jax:8Gkd"La~f1B-23U-fUf]l 1 *8$N_5]NNiI ,h+JxMcn|'P7jS*JR$;1Չ#p?ڥ&k_O^5RjLB5YLtR&)jW$3IlP|, 6Qb97VC)[/mK5pjrڝ"!Lm ri[nhV) uBn](K6 *ƯϑP vOj0VY?k<@CX9naTB:(Sat64mg#biJO;{tivKܛ4YɠmJͮ^^Ż3X-]!1OgleǨbI-LgA8.vico!hФھFz&ce[8]'J?AR^IQA9nLf~=xy_#N9M$ķ-{7 W avŗ|gZMhjU X_24BG}'bW<<^ttw~UvulR3cR^7lPvQ4DVv5cH'uW~*T S'z@~ ?r0)yvx-&'Qkyngp'Tx72B^-}2xqpdG]g]9^5Cz{,l@d/*x(`gHwmWRtPH3w ͷ[a Y#62gb}}1psOdow U~ȏWvKrQWBX+@5 'p r(Cwg5tIbMtAJ(HWXee;Xxr1KpT xqD'|h_(Ggo$LGҢMRKgX7~(uHQwH&Z0vJK c$'됐v3Ԧ3U/X\ w(eyYtupኅ( 2ED6yȓ4gig&{5qǷu֔Ovh0WY+\(׌шUYҜ9yoڈܸbHL#QIiFH굡P٣Q)j+ʙQ碟9m1*9"{|i9[j hlziVyj<Tʭ=IGk)(EenЫmJpzh旗DuwI§Au:`ve&sK:t+ɤO%gsoI.{=^N߇> u!PݣL >,٤/⣽džxf ַ=?Ը-FnCnLL 0 9ܹڻҭMڸ e>/oIJ M̫GP,tgա\VdM͠njt̶J }>.Y?.VL^x _J_3hE٧= T\A~̞HœzOQ D}/n>3`8|dW"3׮&GF\ tvnR*Tn^9OμUnpYJ;Ŝ~փm/\ݩ>W;/o<1%]'{ Iu X`$NޞJ*}pپȆ L~{[εﶪ뮍" DD).Bldh<VF#Ezp)^|(NYr 1paI!DQ'ZC爵jH4TFcBg䤦WBbGҢHǘǕSbP@1gŷgfPvDSH:ָs0 (fbP4)` z"S\Mi=dC,;I-N]\2LlEK1 )QjbA4%EpEK9CMd9zr s ]e SibuPjڰb76TBP"RͫAMK,"T(^1و'*X$ f^A/̣H.- G9-S,727)Ei o9N*H-gx'fcslSQ:M7o{|sd8nLz箔WmFkaI_ۘ/_ŨnaqqŞ4qQ].$^)(x!t]Gb Q_xtTWHC5p"%X)Z% [:5F M_np<7D8Ɂ!c" Ȑ(⸉&(YeFfH@B*yK ZnaRf~ijʆd3eA'i-k Xj{["hkg#ŕiyQwʦTtԺ1fB=:+v,|r|{s&GWد6V3dpZR܂=`h\f2!ԟ92XMgfW{ڪG?'S[dSɳ$u Rc?0f4y$&H9!,*-+gy JGW&ӡ.b0A \NjR=kNavhI[;+HnBܼй|dhL9>V.%U [[mwA~+2`OhhKZ"C{Rd:3RPr]T_;/zR8VCM Z 7&DLy [W1{bS2;adx>;ޱ~b-n_4e+eRrI\e.,Tr}A0AB L ۳Q5r>!((Ffip8S]6-}pL܃5QHbSdLy b$̘zZ(LHx{Ct@3#+wcS7YVx\0%bIDIg|F iPM/M`N‹NbCƘG|Rn,>]}SѢ8m9r^ψ}(>k*r0 Y%>%,I!2fXL (7*0q|iMґdtGW@Xt,)\,K R"WF>XlSMPZ;udsF9Ɂ#U?Jjǔ1D%@95Anj`5֙OK%پuk(V8 mC)YnWכ vO8XrM a'N&h*g3{ BwO+Nl܌Z ]Q,+ATK8KZOz)h%n9tB;Y+ I\I}mh(>՟/5Mža^ fL$t+Si;{ t+^7 2u_5nWc(#)UGݵu΢jg/T|A5A&YMْ$F44~XӡUjtg:A/!]3ݻʜr-nMT3}b.T8&#zԯpu p=w˒X$T[#6*Ķ^ōAp9Pe!t6M0\`r:tHsr6I7PAsrЀ$gFy!heeVXbrGuc VjXF HHBIJ{ԔHC.M'{)4A˝bM|=kgyhc˲&Yp*6r%yoاV7YW۵ְ'ʭ?s9/rU{Ԛ걞 ~Ɏ'{mӪWTegk4z9[:ڛfq9x?yz+hؽ\ 8ʒԑS[j֪;[:i[kZ&VʞI F*(mćGU\%L'j~\sɧK{FjH+I<)[+%ԻJ>UC3Š(C)9 ;jF:[$ʴBx0J 7X6&:,&jABe18R)F+9m|w)6F tj,le.XȾLɯȷҸ{:ܼعl}KZʨk:)s׺wʨK$ʴUER -Aznڮǹɻ ,>{+ť e,UYdI #^cٸlfjl=n-} +}ȹw=Ȇt <0Lũ<xPlK<뵢P)IA!.0|,5 Z@޳5ݓÇ{T ̒4!TINE]VvOm?ŀܖKyTM.mjo GL߄qHr\gW?{ZZ󧨅vW  笐x>T ؕ\+ ˱ٝ۟5yk亓{ზ z~ε9\=֍ ļǫtNIZۂMWֈ4*x7{N=b`E\]uc~yluօ_^ƹ?er X΄K* \dD#Jv89.+Uɝznc|v"0ޥ<7:~0Ӧ;O*?M -G]KRUo^|H }jl> P]Y~sLoJ3^.]jލoM *y.]^˚^U WY{nَʭU2͍}۷On~䢞FC^٬̕}聥9,o@l?i}ZwO*;/搛kĞpg1Uz=GN m˷νnI/БL rep>1D_Q&o(W` ҢG@$ K' !D~0A2(6I|ѕmG̈́'9zbBQi^$Ϧ,nIb)} ؤ tZoQ(0S\v$ H,es^9&JcD ~$AJe,rw*C_Kj:,.k~UN"O6!+y7F|:d W/=i?E=uz[TKٟ(NWSg{j%sTˤlg¿wjX4eQT806b 5'YlΌ3Fd3W3,jx" ÐErRRJ_=j񏔈)# FN1Λ O.2BC>hS`l )dܷyOrZܥTTƍNw-4d\ە)19˭ʔwGF hAZgbl SE9iL2X@f WfH1U0S;?9P뎊sj<15sPF֣[@NDoY?J%Lc&ZzQBp[KB4PȘ ?2[o즧j ږa8Apǒ] 4}%]G &.;ڬ!a=_BIP*xs_T[g.Z d:9]7fs#Z:AG i.Hkb9RVZ2V#S(oCEFka$Q!PyCby1u$s ng%rbX,kyqs:'6hI~vjWvN4:B?W/^xx?/ -Es`+J,"ڢ*"u "gQ+Yqn%A|7ƹdk ĕ8\>Ivy]AS:2![U#/&nkXS0ʭ\c 1hb]gTtzDgN0|#sLEլ'k`c!ڟl.KI16!R +JkcU}GzO,ݱMr'8K"Ows"vt"6Mq48.@ -ljQxetDl*7.4&S}Eq 6ٝltPQ _4F%paC.a˼6Lpo,T^ҕS`W&tS:^FQ_tŽfd_ABQ4aJS)mVej9$юNTYKI6w*!LXr|G<E1P2Т䢡.q:CKH[&1;QG# od:'*Ϙ\J4t c~I؍AH22E"F]Q=!n˵ 7XpEldnw$Il2ģM2o (C@v®N"\cnpҜ8ʥr"G%9vhPJv]df dmGWm7@ 8R>,SmRn0Y=pu5v#KBo1J>/AX9SE/7oN 3!TT3-.vjO9*ڊsA:Lr!HIqzm {nRacZdYoy-?la.:B]X?ݣEům)[D{1`l NOYj17jj7Pg[vM:b[ 7:z&Qd=}mcjݞvV{\ ]wBkdtqM+*2$V,Yv +H_gRW"C%: c9A3Ftu'|-[45R7lL/O2c_4GPIuUswvyfdlWQ]huypu'T}`he&w~n]T+z ;r?xhg~B)DRyyqoutOu67+^Ƃvl駃~?8{""3NWbw8&Y`<3`2M]N@kyiIvk% O(gMwT'V'V_uyy|IY@x?z6mwdd(R2ɖՙ"XpHh9y9pGgƓG3dpxn`^bv~Q:SZר`%3IF2jijNH |hވzW]X;zmFbɎfbX4xèZڨ@ 2 IQ} " $:& z4, q1k,o,o7}})G\j0G]RqJqRq鈥3%wv{0eQ㚕|(&Tt &%7G׌WfiQ%mqTfj+vcx842]˔D!`ΖkۇZ.IFjyeN>N{:}Ƕ;K huѪ],;fCq55U 9[X#axgii}wI;A ǙѨ˜4zڭ(*j.z[Q| {cjB@{I}z}tԯ뛍З4Y:IIȟ[W:M=fk断Eֹ|<̹$!i\Mۢr9y zL:k @ ԺH䵬ԬŤKln( R+s=8愵9^z$9/4Zy\u"kKwqjnPZtV)U2`{]{ *eugk=Sc)m [x [lzÛZH:ۇ#L[ '36¦[Xf[xk̛(][hټ9`ֻY99{ {}ʶh,o} ~ǭ[sV˰$'k;Tc1wZ;+өAHQ! KºL5I;i4G0Ypcf?éKIKk)afă}㭉 y _l8NMvSγITVNuLr\Dtpv܆^qȗ}LV|iPkɘwZT`nx'\cWe',ʿʬ̚J*]ئ[<ܲ MUWd A)\YA̼";oEG{r"oqY (UB2F6,=M6ĹCaIS3]\e-™ (t4ҚW;BU]$n{IEoR T2=>qY)9Nv1l%bZ9ҧ*WFK5MhZa9L?@EtPJtma=2e%~L`6`NaX"i1Qūj)!D*>`!8]d#ʩ\3El4uIAE\;[*4dl%Wc[sY̑E&WniAjZ;tך}K*Bxe¬ tʂU\Q,Kgg&ؕs|T6m iVèf_"#]}ݗdB,`:kiAGO {'zEݪKO øHI .OX ,/ ;cVI'$B(Z1%/GN$KP:zX1Pi J*6|3+|BGPOBkNQ=yAu@9C;i X[7ukSN^3gVZ%m칉6"!}\U3XXQ)IaG HMk[Hǭ_qsDX,m|52XdhiBJžeLf]6,IYY,J4>򿫑y!ӔLlaa_ʌ3>iLB$ъ{ۼ>,~Զ748 B' yEUlYs/Z5\,H VAoVh 7bBKc$6ٸNUn 0r<*7He(SrJx{h%>)K|;t"Q^D_^5L̈w Pm[L@2]2&BKeZ>bO[*d#Rc."YПY_')B#5_(3)S1zZTZGq@tR tDZRG!1w ͙59]Owk/x ,@չ2kClxwfP9z j?t+EAX+yA t=-wrt}ucNqw C4 ZArg^sh6f#= bag%tv~y'PrωyXt5aaY3"<u'W-]mYV|됵=lGRgt}vf)O6xSds[e}\Fnvf rskIyn>%s^zb%O\WL'_5W4Rh_;X 5Y\e#0G]pe8׃6jnstjPffsZhBw.KrcIFld18bOuQ"JLv0/~pX[$GPW%exyv1JQmWoT5wodvg x'e'genNWuM"Pԇ(?@iėfff {6@p8^y}wrz^rrU6rb ? 'i_yV$zxWփ88v|;W3}pC4tE46u W#~[Y(|LJCe$^5pW]1t1\C{'[s2b4?~} Hxx!fIgeNof]xِDty 邵(*(R^_JbϦv{DX`HrXM؈P8,X{zXsƅe^ftdHlfmCODbFZu46xhElc*piF)dWC8y+q'd$ wx"xezgy*l1f@`b'?<477zRz=ggp^4hQB:xhf`q9LBZIhgiE#ocט?dYLܨ+ިal9ҷjԗj}mt~c04d8lD{Vkv0h^jg&6)2+'Cnh!IIth~~/CP( 0I^6 g]ڟDGXleՀ5Fg4hoJyhДԹĨ+voV93v#ԣFTAD1ZecQhs6`9$Zs*wקH':Z"5OqWGuu EYr8awccwPH=Pf7PT }|ʤb;xy|SeؚAx\b9SCBIyfh*D%T~ۂyr؜(VxJo5T#UW=£$io9CPi9&D[~*k Ymekچ9~W~ƘwXE$˨/}lFpylD:YpmQ , 96{0eaas.j_f`?ʲAGɧɪ^jLؗu@p˫f׃z@;:Z:pˊ*ȩڙwZwwSfrpXJCkJ*1d1j*Au39^A[ACk>ZXJYۤ\-f^{ߴ4mC^R`Qh$hMP:pn΄nWTK+|zx؁m<n~ٚEM-T0~^yzNڞZ:䥈Iժ y/2>0^ĜOoj<Þ}NT0`|BQ[o(ܾEf*sxU wWG@BP$DU)(@Uue@F $D90Ah] RD8 *%ʷmĊ|[Wf<}8j&H8ƈ)xH -LK|#G1'{ 6T7(>4wFE/@2P >1K'z[WDaF1)Qw/yIbhzjͺtZ+ɹ0j`1aWjf9+l1ZZ2rˢruOc͇Wf#{QSכG }ߵV=|Mgc݂ۃj wGZ@NY1[xn &qݺJP.(ԒK-Mo_LgM7$f,}sƙW7he]՚`sxC4DNTˆCeȲRìӅ-rS#7vKҢ^h" f̛>4:n$q cip7YV9G~肄-i u֌ "۸Qw6|W8 \+b:0HXU `IVOPhEL;#. mFvW*+0Y?jJ_2ҟh</xzK5AHRFJr[N I3Gvs"[.2mjKh$TwK.S˻gY:wDυQϾ~4ܡ Bη]k/ZSJq>eyDCqƐpJeص;= I<$kBQ7kz0 \Y6Z ëQ+L l8a|ڲ<9,&ɬѧ۝l@o"!eiG&qQ<)^" M[(1HF͂aA X1MRH)YS&+4"{"10 |0g;8V}6پ'0'pN˅$ z0vy{YkrspKr1eN$3LU] FYjpXe kڊ9O4kY\#|;}!>xCp4fu?mI%J oL6ӣZyNݳZ.G\實Eu.ҬUnIݍCalgdCrlnvP&brJnlm{EwLkTqtuzU XAeM[YL)XX56>PYFobO:DZJ7yDo&8s_}tg@FU?% F{g{wsfta"J^Յar&Uo)W1Sri2WTqT6'V.i}AXD G_t F'RjHRI"`OyQw`V#suʗUz]7V4aWIf"y3ˆ@mlD1wJfQws w[x8N:vV"y~,#v'ZWzb8AXE,_hzL(n!(wp%FYlD2iyfѸZDZרg pe&j݈WAՄr6`fyq٢IZ@ɗ]_wt5S+&5sqXsQ4eGf[&#Ȉ+_y#s1(I`e+5TgJ`k\wL'cxf(Lр^ l'(w"yOs`-0'0ٴ5?%{}rF4`mVNtNubB1Xy ZeyXI۸zWHJGhɜ K}|$Y\ȚǢƏrihYL/TTUؑh+Pup{NLwww) )+iiP)m=I xyyuWZbke780Z?TFaBX ;D]iS2Wrr^eڥI?iZG}}ڟoڸ5%Bw눒R{QZq~98) 8rsD:Jth_> aH1%'-:yٙAgPz{;j|=tt!JI>>j$uURj,*'^q L{":|bJjئw,S[i'icrmw9-ii:GnJ:H84A2ͩhꢗ$ I驺Zcm{wg󸣳PuD_N'Mkpű(Uaۊ {2U.g|)*U|1 z>JQK`Yzz?:WjL $[*ȓKpj{GZ{8X}3"K6 -_j@@:PtCBa o4ˍǠƵ|4j :xj6KԺ'j]TkJӪ^Qa Ȋ1A{FoʶJ [u[w;xʺGd隴ۿuǛ[b\ꯃ۸3,K*6{Щb}9];ql-:k"UG񉸞w*dYm^0*jkQc*{٪iPk[5z(y%#-J;eKd8;?[(:a? =-LmM͛pQ\Ϧڴx~<ݎFn|V -1Ϫݶу}q>Vm Z+H mĝ <8.}ĵ}f+N[k餇,3ʿ',,$6uUܷn>ù\lwPT S$|'Q](F  <;6v8?&su\ Ͽ|X>KQzg|^߮zVmn2__||}wRnݚ0ЌqpAN`z?O #i.AKAͦ*vsxFEkHcaY H#L䭬mfF= ڗx -wbʬW❎q p"NCt FGTkDM%لZ(ǪC'0*a[AhUJK &60]R%bB"2FhX'QEBc1)@I!G)8306Tɂ䰃rzŇ'\u|`5RV7FĨe\r"%PiI /gV)Jv̧w@*^v)Pz5p~BC5κ|_krc8(x"i,*7 5-l^`I2'o~#"bTz|[|VXp~sN4s;wHsB>‘%͊ӾbC*i(M]g}5Μf}gxڛ?he):L[!p\d7'g`G`Jr^\=jN;aٮ'#4Y \t},@D)B_ U}\–b;|ICXNܥkw@!D: ) 8m إ0ʱa;&7"2Fxi!}/C3aXȉz+ \V(̟x;"%YzZ B'& _X- rpZ &EQ;STc3*]{'fpu?)e&{$ wDB+qOpb-`P1HF.J:eTlEEaJ2*b;$蚷-m0`e蠅MQEY9FEbVٜw03 yܤ6D֙u+4[e g"hS=W^ {*k>dRʅ)hfIH,Py7OM$`>)%kA`Gᢧ }V mL׉r$ \Jap59&$YYS23ZC%"'PnD)~nf(qzt4#Hֽr9Esy"Xj38똊Ƃ*S;Y}i3mj&:=f (Arh"՛q!PPb\74j3<~2kke>J8Csi!&lSjmgGBV3BEFnlTX!'γ΋FDYOy܄]|>ql˦faQyٻd™ X+aC\A92B>ӏ],QKFf-Fٍ">i"#V,$ReU7.np/쿾,{-vmQtT̻oo{JaUG^ŴW#'dy+"Rf(^A$S<8/lo5`@Ѹ0ͧ07FqFce8_3yjuȎ 9mlcfQ3D3|GqqH:9[fRZ'55.k<5z]Te1vM]5m`lS Uʌ/LBƬCo3D0ff*}'"2 sZ#a&-Y' S1l\A_]ZmKbα޼#X<]z - CWz7[ׄ:6(TUO5< Im[ ^Rj\yTaec9H(S*̔V n kg-% pvfEnRmJ~vʸP?RNy~ue%WF-K'E&Zߐ- hB:aWtjȊ8t$,b[#כUkۏ?6simԗ*ldȾ1FlMۏWnĽ҅t;%eˢJxK&K]vt{3g^Tu~~g GyԲsb%>~cwhWsR{?hbsii*0vN3-Caxwr?s.StėSP~;{rtťuNL'cuA[dyHuull]QTd2CEvJ Lv 헃hzSWoIn͕w2Bno=eQhFxdx~|sxqGiB8%\XybW46W&愷ZwoT}2a$Ku4'Dž׊]zPv5f|.ut|p(Sc')mlxZ.C~c~qÆpvfcrtvs"t-rIwg3i\X|WHcVcݨdATxhE (pyyyG4e!? "c-,qh1I+wE`8jĢ/^Lj(Xx%ybhOɈiǚ@ׂTIrcr}%)xkQ9WwIpbx}ugH@xc6m\wxn%wo" i$~VjxYV$^x&" hYxx*yHɀ294Y|%@9MT+zO`J sDib1*K UOE8S9tUGPY( U_ Fii[XucosYn"Jx4ًٗz|(-BbbhQgy$IyB]()L򑧹 yfhƉA86i`r8WA`3E`JWxO#`#T4I$gf~Mݩl|ՠ2V}xY*=aheBiy nɗњ w_f|_W(J-$$n:ءhx%:q% )ʢHji2:0$0p֣-^/';pZNh"a#oFCtVbTt:*F%åY+IĖb*!x캆&%mbgO}^nzT]k}J i&TM ~R!Ɠ\pE>G[V؝>Q从iBt]0pnm^`_1r/Wm߫D؞pុ~vN1o]׋ *\GQp7 а精G^~հ͆]δ*.t;v/\z 8 $/M 8xM(˦WZuq7Co/J/8^(rJ:]rV>ޥ;_ۖҠLcgYIF?UL Dw| "-n=Oy{P- JPK`[TA&v7`PiʶL7C1pjI-1_ʜ yCD^&Up*&cI3T>E6XRjy{USN<w-yF*|nq\uv?!S^<( )J[QtEKLcME:%z)+FM 1?Yfa`uD1Kr-ʡ]h0H@B5 ? CP]wD}!l=hCpPN"IrU(5x%խ+q kYZs\*mZ,5_hPYB&qP/10f6LdkܛRȸL:R9TeӪ|c4~z-1|kzhoV*)+kƸ}2먽*Nym[i{{T@4MP%_LoΦ{[UWIkz(1uKF,ڸ-&lf !Z%K_ͨ:e:q)4%ՌIo>)zC"ĥ8Ku-5S&:meK:Ul*8[Yamh} .?&#X+~n/f}p;oAC|E{I:4&kc^xhuy`]m5G"#; +[4 > aJ|712AW* ?4.v^3ziIn 2\cNQԒP5 kz&(C{ ~(- - "V.DJ^5VLNH n\U0OL:e+,7n'?J#3m!q0cJAw%$SyAt$DBꄰV3X0Fs{2{G$zޒ1$=*eL}'2"Vt<$E!GdԿYl_?`,P?S @@Q'!Ny( p"sQݫ1enʊ Z5P#q4쁊A[,C֜kfUTgEI@ꢧ{(+N#Lwy"3g+ ZEek L=Фk?9x:]*ԴVte.Ofk\7HGgOtjJAz2510uS͚NN?%?@+ j6@e+N{S,g(VB\4TM) Q̒kJG{+$kwKu?+{ɲ?)N%IWEc^y/Yxť h-d ִ!BoUAD3q˓*p2o\B/9Ktr}ˊϋ}h9`*`zpFkb[@=/a65jH3@k7Gֻ{2g7G|Rgp-u7V]Cc 1{";0`,OIHes m./m<-swmp|KxB;m.kiAë/`ab3pkZhNKkknqY{p{}/z`Yn9e(7c:!fkl+_^+T]]IF?6;ZzzzEJER 3HQH'fxSk_\]xyMRr^HmAg}jyW 'zvfV_$q[qXguf6xDW`r5.{s7|e7TƗsɅbj?a$t('}rt& tf|}`"cUG}Hw} R}e؍k#~F~B*iZl^>HCtgvRHwZm[Oxe&=HwJ=?oHXx(]&R#3oR~npRVy{xoEW؅'Yw'2tؑ'ס>7{FT8rHL& Fnjǘ,M1Gxf08:PVEXewnxwGIhSuil6TFxjwHW-)pI%iJA 9!:`))`րWX7[L08/yF{ &,3FTx#H3IzH:؁z{8rPrya VIlKMIs-f{EsuI\}ؖ7wz}72YdU=#n鎩luIZٌsClZ `y` Ye9tq ^s\ Y pЉV:@EzT4Hv ȋX55,UKqu6_>|2˜iI< 7HYYwRָ#va8וv3pkd*u rWOWZqHuC}YqvPƍdɠɉ1ɐi&JfpyI~"9i;S(0TƓyz? q3DɟMB'QK)xy=t|ߙ*aINwL s* xJ{;}:L 蟜yy54r湘Jz} 6CIق鑜(*fJ5셖6 6q7=u9.ʃJJF),O~|tj8n_\E^:[pphk媘Do'쉰?Huzuʆ>C lϺsz6Zx0Gh89V=Ǹ ˡmCoХ#zdȳڡ}F("nGkث#ٛ4ky]n(6FB"~ʴĈRHZb)mYڨ^ۈr:d 9i0EaCpЪMُ.۳Z5z+$Ӱ9 +]˩{; fo8xCJ zj(,ۺg5zffpI=&)@[Ɗ |ي%M[0`MS{hyȵ'i[ۦ踖ɶDUDwLr۟ENS*jXɗ|=;Tt.MZOKC,eZ(3/\/3\/'¨J)*+H(;Kzõ;5=/CV' a5ʜFܼNLl*bʕf.Z,bb앮iٞCiX:S:ZTu{>wt [ɨX1)}lKtLJY6fvИhz:= xܪFʲ¶3q_<^=8BυʤɫE̼<<[{TK:@ܵJk\l 6XDYsLc+:z,e~l:ݐk׼9xե MwL0:&Jуɱs yb-L| 4L -zBYld/׿Zl`Gm1։A_ʭI]K-YMj{p\nJWc G[*s|* uKMٜ +P텇,σuR*{]ɤmͪ i$3m)zclͪ!,.--; ˓K/@yŹ54YcKźPH]ڋeZBf٘\ܜqhRh^EvYMKԄu,ޏ@omg\` M2| ~}v'm=ݱ[SዝɩZV߄t 粉#=h΢kzT>xn6>V[LďE,L|V)eػ9ȭݷss`AmW<-).nzj#\Kͱn-a>=6ܹ-ݻr],%m.+k~(Z3n^fw&8ZU}Q^MoS^Io܋d[eS @kX-ENI]m˭UŒĶhk^0ZUI[˯Lw|eQzMD:x˱ ~N9>Zt6Yÿ˒ڕ 8{vkWS9 3_c Ob$Jwոm;ݟg.FU Ľ\׎ׅ\Fc\߮XOUH=K&)S *=TIn 4:zcCGӅ J{O>b cAaq$ڞu灔+M~ MF,@KVuS#a@ rtBchHLF@T >\pE uq8RWgxģC)8fö3c@%&ff +)yE%hJ+2uI"u56dEeɌHk鄕Q1zwEct`Gu>B RH/w C.lK!%G +d` ) F g@^@iE=WAbrg M8rQ=50!/%Bn DQzL1Sb4:1-=t-+VZiX4.uPH6ZB"x mAG3Ep٢LE^ 4R2֕JYl[zt^!G2t&)n I2ZԲ]{أH![A5xe+&KIX6< HlI\kDvLvFt! Sv(1%e`S]ibwVu_VTNMX{xZ GZ~hH5 :!_u_!ZIF>`W% BֈdT#R?Fm \=Pjbm52ѶOPdA?pnbewU> y 7Τ.Ǟu3= 7Ν7Mo 7d{@YRݥt$6UdWJKaǃ$4!Yx)+VZ02%{dVv՚_y]'`% s7h!y_h;M2j.f''–ft^"%Y{^9ҽhn;X,ڷA Ote4dKmUziM7ЪQ44.i|964 N累i9FCa_ V,6{J_$[TKr )̦*E@qes}Vl/PqC縝cߣvmRvH:ܤ> |mHRK܌r ,@q\bI0mY Jז=8B<8YX3܅Sf&^k-ٞ}Lg9tpyxîl˪;Wfkayj}|άD_vM+=kCKu_mܙÈ|SRmOJjfMJTĆccxx3SGQv]xUFgf^c'Btt.Qp h`_çNL7v!#nky$z*`FHVr2i|VG#+Gj~t$ l(|b8eshOPF&0taq3}Ih.vP;)@W~u 槃~uiv'7v w5.gpi;gWfasf`x'xܧ6׀ZRsUhgX\P'&gwpf{pgՅ)V]傛D7tiARh`z8ElRGT'-60|RT=;ft62&[@rtN}3ws~'>Ňm'p(8R$h~miy #*9@fQ]n|XA;GoFXxPH71gkχkuBr8_wWR8ZU v1sJHfN%hrar81WeHrB#OG|PA7&YYa5قH 5 @Ø}A(qhh؆8"vhVcpȀط6p%hwr'\{n@eMPFul2 Xi0ĉh, p,Y_ΰbK׍MxD=^id^fytyjڞɑH:k* y y 险)*Pc+dm&I^ hBƀsy#WZ /hB` WBY1gjz{88[9ˉ[ ЩUe'CSFz-J9`YE2ɡȈF(qsu|tyڎ~Ap'%xw4I$m ֮ ѰTmڙȆޕrRꑎ*S(zS065)x"9;6`qBj\q-:MziĖ?N5 Y;%bB媛!BxkY!{z{)(jo{RhE%:hwɨ&iw{[TTaDdˮ=vʌ*ַ\*bHY1W*8"BQ௞Z7ۓfʳ *i@E;avm:|X)-&80H@݊|)p%ō{ZjQ9{xy[6~xZrGP<-@{]Vz˷ e !즡𽀹{kG#;,%{bK^*_)y}i3 N-7>[[$7ȩXLGʞ{7o.X 璍PbW+䚛D uc˦kZf(y d;vh x-/;ǣ8`&J+4++A9AֹOʲjIJؒˤ![ʣ[[`zAZ1<3\{a\n E#p[]g. [k$T ܛ;y5 +olƞۺG1jxl ll0,\Vw I;,k ,M+C KǜK):Y-JB-+KŸ,'|jʬWŨ,D6컸ȬDNz>ˡ*o,о,G$H*X|c4hZaQ]o˛ٶCy Vt[*@D0ENJ[{1Āg{4ds,Jkߕ]]'w&eYzl<*,̬{ D̥ 4ѲU耩z6:}M4w;jEuq}28|o6x鹦3ПOݬQ}W~gܼGCՃˁ בd{\}#ZϘ:{ތ-] * |Vǁ-Ҽ ڿ=Uҏ(}|5fܴM,R9;LaY>}IZ\&۾dbw| }PҟMT![wlf;l}4 ȍ;Y @|Mxhm${M}b}/ ܑ-M #m"{= n˧#VԌDL-Ě@<~EV H-|J>~5BE͍ڦo?մ\R9Ger kM!x̤c-`ȁ+Lt|s~ m}}<3˘ }nٱVPNȞMC@F;_^*o3KN->}<ۇna笞1eh{'^|bH! 8m#7\J-Ͽ }5ip[R}evgun7lfnc=N災# _n"lNGWG{ٵi?U/I~ ^.]oo۪26ҽ(8b? N W8L~ N޴ V*nri7$_%gL&\dk KɡZI! !oE޳\s$mA fop&,@qJ$ΰ)PQ\96)tR&țdztSyì5|]0R$ܑ:'7pL δv9NXmg\nK 1rxN}ȠO4ɕG2NoQtb7^j %2RU.GBmy-ShHcyʁܰmPr#±96T΅pgAwА")0WϽ+H-v:wqQV<:f"mS7وZ"l0/=A) PllAo,\n_z "#E&H,͇_ؠ:!02K(>Qa YוּqHr/MibÔƉӫ̮ k;Jn3Hz#h,a "$$@0U@F=.bDe%P= c@#ѧW;ae$D&qVPH\p1ya'MFed&ELr=܀8Km5n;&>JaeaRflp yłi1\Ɇ! c'@m gkВp^.Mq{dr[ _ĦHfHW$٢I_I: Ž/DRzTkGN=WE4/11R;/xD rPp`=u+YlLbFft`5K1Q8Ĩh{hUbJYӰ*n?8iqQ8QH]>YE-I$=K~s͆-827ǤM"mOBho[OQ4P%{ł4:SkI[JPRm;F}J+*D`̲Mhz&ըYbH*KuU%Hum9UZU[(2~JkZ`sۇZѕ~DU|olh#ѳ9hz͊ʴ&^jGѰPyepFǎj׵?tmk=zϷK_[ZkFZ'iT-f+Q?J+^7XqZ DߔY3/|FA B*|f RfS(YE%/#l;3Tݳz2-Ь!~ kh HŰ4چ<2X3]prɯ5Sٰ8YC*2vzyT:4yc)Xjo1 |8[KK.~m^;2܂mR_Fm)Bl4~§W|Wy7@tV'(z inGt)2{"WǖpGvl=k Bfݔ{~ytd31Sw-jw8e}ǥwnw7vO'ocmhGfx RP؄7^{Eh}+lyt%4qtg_Hhz!28u׉t(<7RMxCMl0|G@xDŽ$h8 P%u&ƶiWl>XvW Նܤlpgxow(xvgCP$nq d7ftH\kj(|&yHyXr g͂i)sh@V-}CrfV8=uVbzDXyȸ=˘OTxy)y7mEܗCXu7t~DF~`nȎeG0GnWꆇH¡ Oax{)'Ge^w:hinɀ#S?xxC8yvy ؑI9h ٔ)4T&!/_H0yȓxr1yŋ<`sqq R\wFbh)Vs HZGxd~nt~>B|ߙd|&kI% = ~ۜKxv|X΁.m)M"nw7 LJL-2 Ҥ*޺,m-ɏ)+ػ>-m>^@_.=.>ۮC}ɞ@ĎʾလAo NM'$nzb^oEoG߰~]_=ސyҼ<,+G^ _?Mˣ qq$/#j;3Kr_/1_fnnC(T,x-x,ULܯG^qwN !J[t' J9MCn\J.ODBP8jʀ=A'/c_Gφ$KviOb*('s4V %j-´csZUR#pK!aIp2Zi\PKuGĠ/qwr|M -`h6QQA''ŷ%hcx C CFgU Z2䇔%iq*PFDQY9" x&k Cmհ14kQ$l7GTH2дd"bJB%V!pqWAutJUYς.S|9Ոjah/"#tn}<%CEYdžEJ3|3-0yهS*("LrX)*5qH(OQKw $Kc~IˍTk500f [xYlVpBf ͌WjܲMOoBkh(#?y*zEd٦t-=]D G)m,r% 5ْ2upm a$+M6(Kk̦PfR<)?ͭzJDfUbyqtrOڈH' %W9xE9`GRX݊`5vWg ~!NM21*K\@AℍYyf'^ Hbsfʠ*Υ:#"6h<}ٙdВeu9YaTّ"veSn+v |VKaR$dVfm+aMw:\F!vqĠcʩ^G`v7i*-΃mx)U{!q#kܪ 悬7jRV)% OWlZ%0t.u\ sܖѷ՘Wq.Cƫ.~*_ ۥV诔g'L(֪J^帩I5^/ҩbMڮJS|\! 3p47 9y#qXn"~9?Ԧ&|:$w#*My^h6dca[X=)Nn)x4JMZ[Sx'8իem`Fg/4.2F8' S-ŹBk*SdBt,HBKblmԏcNֻTzUٚr &*r v-fP 5 M6ƯG3rj~^efōUc"r'(2MPJB15hē7-Љ(r2Тn<['w9m+%B0~X ?X,1 $}Gt?|$pT`/u84DLwupeH6~̺r.r.k9˘J"z{È^ زy~Lky?N-A <" \yGqĤ {f;bOӊ)U}I禧)iciqMhE 5!f5/h箔`!g2{::3(4I1$b_4 7 Sd Ds֍ʃQ} U:՜)#{''F4oFkBH% VX.mHv8Fđ+:sn#%N8n/\K0 ScuUii`Be02"u1TA.JP_>UQMVeA|5OMCdYVʢhK":G5oxI"5屧F#aϯ7lJMNX wuX;h6V5FʲWgk:67կ ӆoM ii0AhV*ZScTTeණ(ݕ qbĖ< b9+-fKJ1ɍt\o/{-n/lJUݭ_DŽ"o}UPN# Jgׁ v)C^OM,J=S댂BËj0l71۬[ա+w mlc96;$Oޤ=*甕:- 5>,Np3fܭxϙd}gvo =/s_G_*dHѡ5s kX]V/zAxAfy]<<$oSMSޅ%q'SN5|Ҭ9ew7csxϮtFCEֻ0MliWF|.h)4hNxg5%xw^8bz'bOu,"yvR*Z*'03c073]2sb|RqY8S4om7qBqM fR[^qb䔞3gG՚ |ѡ&nԩ*'|,IMvN^ 94<|ʄ[\ٮ^Ҡ"-CHW%t|؊NBwO^w(شUm^.Y9$"pG3_,.vIZ+.2e5W>W+Y=_A! JJ[~M\J& X]c{1MgYʯjJo XM 7}ý-2o5: (FQPLQ,RV)ZXe3 Z6@toF$78501=:3㠆A&p":;PeoSXO"\t!L-uOj}/ eN^ur`l=P6ACz`6h "24$N]u;#I:dv!lq$1YQ̳o4w4eWS/+* [FΈ,N3 U09eItIq+,BYp vςBt20QExFPK ,;x>0票Uހiz2S1cqµ#!8YД^P4"lhX zL{"P*Gؘ[ljnn9z)I(kl-suTp5B,~WX*ӑJg^yMB\Kg+:U2k0awE=IDA|Ds]0Vr^%\LlzVmnݠ_I]5~UMcuPV…LgT5)CR֜D-o&fa#[0Z4AZ38`ʔqSY r^.Cs"nσlSxbB+i)H@iXUR2߆;=DU_).D_%łHߏ|`L5\ BӃ>9*Cpa^":ӈ!(^ɥQ+\:)#l7̍"g kXU;=q>rXj< ffF^8ZiL+cƠ[jFy癭Ԗ &^nlP9F_]?vrJV+:|_D0]xĬ~;YC_1իM y.@HA꣬F-sHwvS.,VN[+?eaBƯ.&/$BP&$%p. zn:lD)J4^ek:&'oegxgȏ'ɭ;T60=z[?W]вT"mV3E=G(3Z_`ֳvmESؼrՋt +mhU )zCHä"oE(qS#G<;:KR\_D\2q7cD;ލGgL ؘn&8ܜv C*`^wˆ"("~qn<ʤ(Z(5a*exmimiZ2Hdo! b?o T>f`BG. ۆ@j RBQ>>VQ|$Q(<6H'B,fئ92s0ܡzhFqM+Ζס/%"C/SKFw- Ksf fuiyV襒fh ;t1HReTU*Mi&!=&*κi+֊#)AɲmT% "ٳf5^hO9*Z]5WzM]j"D㊨BHmx,"а0Tw6:qp¢1D、\TN&O9N@`ux2y3CYCO2Uq_omV壤G;!|+7}yn$2Q"#Dj٣5E_,dFzKgW:B2d/n݀z IseK^QO}٤J\`VU5ZVP֖jZ/`;5{78v7؈1nWs xy՞QYcZjȵ<}( cV YPX({zZZ4gk;V8y!_)uxH&\X#T1Ŗ$KŢ-uGcnGp<ౌːov.[%DWӮf:ↈaJGpΩ6%zYF w7ۦ'HL,dDMKn3YD8HQ4I& N 'X( ߗ)vƜX!  (IE󙜘C'l9Vng[vH5՞T)0ci)I|yR zgYr19+㠗ᦧ؁vdZO狷8Nړ?&l7i#?$> }a*}{oq6ZKMoؘٛ9xTCp4Gt_4YKfJ֨;wWMi%Smyh:zJ98Z׀XUڧ| :9QmF-*JZZǫZx颢 ydZuY&֔WZR|t ,ךdžUfyIR7s٥/# j jJs*uUhܚ1Ú~ʉTxUG)fւz"eXF8=C:JjLzH dƢ?꛻qÙ²:SY)kDOg4+Jkڟ+j:VU 䦫H4S`gN#[Haj*QРj,iꙸSYH_Aw[ڤ9 {Q -Z];S̘a[@kY![++Fԍkǰxk{J舻N˻w);E$_kC̏G;p~iN+&Kwkr(cT c~3Lv:ɷ&|fXP+{˄*6;<˱JLi=օWCj^SzÍ\;^;ƹ_ K{+0e{FLiMl|qܵ(h*Ę|E|*zuW_ly,GHŵ4l[ɶHK 8˺uiQ9vS)I` I,;,b aPF<¯wwIV%LdB!%-L 1\^3<5_.O҉nH\mƬn'܎ޞ<}>^A!ztG-[/:EKdi@PiCN-<mA\ ߽>ƙN@j+ɞ|ˎ2\,/ٗ =_@ }z^|.I-~!~[9 mu,~onxș'^fq΁oZ}l$<,ON2m쐒  N-32q* PtP0-T2AQ:j2ásfYO@dh2 +GC Iň":2%KR; <5c%ȳ2&x!)5hERոYcs"iѩg'eiҥ 0y@A'd$h,;E7Nj0|וUAs [p29%4VQp3`sy )~&H+BNVu&:$DT>GECZ_ Yf)%vg551~PMW"qyZqWGt&.b*(p!Qc")1@f:!/B ߤL>X-B]}6:_S]h&Fu٦qIn*[M+ Jm63휓T豤y2b'0^]Iʷ,;_HgaxSSA)۟MEKmd_s -u{Z19oDss492ͣ^}H"XDSz ^5k0{0uh f* rts'[qt^r3'󠨘r}O餯mѳ?Jק\+^s:t$S ~Xw 뼔N_ Xh3V$m$QLyR)2h܂/.^"Q\.wI ,{=M_㜿`6 T'B,  k`'iu]k"o9H#Œ/|KYÔ zEX:TCrtNv8={UT:Uh=Ivdn/h&Y3UHxH a̦a4Cz!0/./680H~@,܌Āˏc_HA6<%AͮG 򐂳fP:IeFti M&b*W>E8q!(1&1cxÛ >;[D4xїL o?k0"Y`r|+bHKPfb 8)"z8^so"%`¥}Hq%/W5JB#svT8кRqIUs;ţM:}wb=B{~ܩ7%sBWF MBHQˤc/OUы&QFѫY.kYa40&P$LBeHf֔"aVY +|l,1*,4E.KR\*u]ROT,'z4uS$d]?;? Tu#Msά6Ep*KIԦE\K@'76d)߄z}(Ғϥ} ʨkN +cUϏOn~6vPR.;GD Ӛs+tK-uqkuk Ird2iU!7Vm/+V*K=Ԋuڼ`9hV a,"ZabЌp^l5le [,NˎxÙ=f!Jى%kO4vsk[Lieme/LD\mrWg6/e2R7.%Y5w6#zU@hۥ 뫜<9tINJ&TVdU(|M BXzv jZ!G i>!ib>NG{ _cT-m<&[1axll$, "lO~/m%kظMq/toQw#읋&_/0om{8W;]&YQx Wc&4=G}L^,8.g"Dt$,閃 `N+ݟޝQCp\tx?X=NmWQ]=v=&jcZᶽ>czٿ WLEY4SegDVݴxMv wxUjuUy-uy'st'OA trtX wFzBw&O%{=r9s#874dUW'5ccZsc|~| r[}|wR b}SV|qH}\Ta']'Bf['fkJv WfepgzC3 DW_Et_ pre yA8?)%E~!}7eltzh_~ :3zHwnF{PM5T7g9xpC(|2oƗL_UcW!?v6LWNgfg8V](;X[ئU&2_?ѥ%8n~9g-f 6JhUcwqiwXM#vuҘo g;us`Hsy z%(wz#ׂ `$Hs(fdY){AH>sFXcH$:~HG?6S);dpe}۸eH~8;3R,]Ivb!8gXQM:j ex{Wiou(Gؐt’蒋c<a$| Irz菒xYIki;hHK6iPZtHȚ@u|ȖSȌŘR7L9hdSDnty~$d]AYfqI9UH783 v:HMsx~pSy!9# I`i'ט xŁ*h!Ǒ{58Y6♖^>8ZIs8Z:u hRϷtz0Ù\cO4ixiGTщ[\iajgmTrX@옢ŶT֒ )jq^fD7ew7Z xY񙙖j1矠ɘʐW 4.bNؙ֠Q$`YY"VE-ɃTٓUGb~#T%:E|K5Ag1jR@r5b}}N9AUCSTa,BeD*x뗛J~Oj,QUa٧)U^jwj\D i&hY$ .vUJiuèvJڗ>y*xIl1h xӘ)defFƩ.چI K*{*6iŰ}جY[:lE&wxab7[zp kjmz>qwUyzYeZyPyZ'Wdi?D'(8{tuW,9a pϸbڮN;u@,{o. Haf29[ݩȚ:|7 ZzgkPG2z W80Ai媘[]Kʮzjhjj݁q*֍ɗ{{e9y"Diܙ7h24K hdGk[X!%(%[{2ʺj)fhK fD˴ Q[JnɋWHK:OԻXʠܫދ늜iٻi {k$JrFY \6+,k[L@² eF;-[/{3,N[dty(rEwԽvVM)p:0|KL6̧:hV×;ĞXc ܖıN|)ņJnʱKʡ`J|++P#cAg۰FSƊ Fksk2| D|y[XIllLlVɾ1m)IŘL]:,7^Q1}5~"2ރ0~FaܭvVk:X(+A `{Y˗Cqnޢ-dV'Ӯ-@-t; CnͿ"CD}6:܇Dܤ]:ޤ~C=!5}݈>^ N}SLJ^Nö@7(`#M&j2مeKx;ڄKZʾwӭ?]MI.ǸK_~d>VM墎8y^(ڝ CEnݎO]=u]UZ*7ɎXp㺾+;̠혐-O^-PwNnh.>>eӪ},?.MP. \R;\ 罼k-n$PRo˖bPXR.m/_}]Cz^1O;nrkmcNnCdܥl"N)">+XZO\^頺Tluo{ +~ ,^Di}䢗8֏*︌?Xm3` sJXm@PTaf_iRPˬ@7'EI^Q^pI\N.#I /Ŗu`ON@!7/w 3Q8sq;=A IWmxJldc w 0N{m>!>S[[KAm%*L(K "8aK#]z!Zs"emJϧw0`Kgj"&5pK txQ_z̩3 9jSĠ3),R"k*WiD4Lo8c<@ R ~@TH҈*) UkmGJ+8ٛpu-" 1ff@ sJEoLa; ը0jT(K43ɂSLr=d!÷K;:,VmP/g{uia'1a /~p nh)΁X>qx5ّ* _N/LiM;.T[FKM$`GL %—$p=!Q"ăt{qCzT5VdE"l8]SPGN[~Pϊw(@r[{&MEOJ&&(rJxTPg-Vbڔ1Qi<lxVI( o0֔'QH<9ΝѸO^uKBKbgܦjI 2@^Q,ʷ=go Td i3 MCi@@kZAcʾK u|RE7_߈; ڝ@BP n_57+S]۴ȸk\Ğ.r.dCϲE*|'"Q!s:Wb0F ntthiw CܮuLIx$z d-NxC \*`&j2٬X C{Y,ȼKmK&Ib\4or+^Oϑ`?^+oˁr 7 ~INj7$ ᓏ}Li$ Md8QNn Jc_Ap7MHdꪸ.-ߛ^hȟb#ej(E/y#%i"|r3RB1C]cL;;:ʜ܋îq:t+!IbH9$l\v5>ҙ=4,885Od[c2vbLB(b)e0E3XZҌWR_*T%T\(dPFuJ;E kѠ!`"<ՐNlg"XwNnb^uz,"ew5HI/7i_*i* } L9WgAR H5h@&]|R3dj*O#ɕ87kקN̫6V:SS]ݚ[P&TI{٭Ӳ~5Yce':bk ͢i+ܜ[ȈS9k+ĮS#6V#5 X e IJtcsZі&܌Qﵵ8dٖmz #ޚu;\t\@rh*n*+ԜθLXv ΃Z#l.ݛS^r ,@QYA`~#Jηrböז Z`=kԇܡa mg^޶ÑACJ*n=P|j3ŢŮCRCJ5i_L6xMt\ ](aqäi׍=\ : O`'2sn#~YU+:1a{gᬬA1hi2fƎ" 8v n֭(˩Y)r61n!} W]3CSyKU~=1w9ZeP΢;~Ձ86*mZ|1L|41/W,(7-̐Q^e};;uiɎ#t\BTEd~6n<6sL6ve.+X6',x9$)16|7UoHHF X+Tun~Xp(_ڱayy9wiSrit,<&`7tj6x8Xf(6tDsv鵀RstH+[N0P(cχg&7r}0VyffWxh5w~e׆\{Xva6_XtgTvngf'@8cU^Y'eLo?珜uhr%th$qa6a#XWV{CXX4(rcE4ǃ^ae@N7uqėehPgzwGtWٸ؅S0if>{{嗎ddžRQ%mwWIRGT5py7!Hgx,F^2SBi)pHpgXuzwb(sz!YD%HՒ'犬h;/r8O3%=?ȓBBi×YcXhtL3NIuh (6ɕ~Ya)FbWjdeŁB|ȏؘ~Gvf?i o y8Rɘx)y]םCe>')j% M' Z\Q).N0N4I蝴 )G*H*9t'|'I8{Z1>Vv؟й75ijhqXJSeَ晘aeliiӷHwHA)xՍXُZHـ(ZeBHW opcR1qُ)i7(wԤcr֡ZĚ^Ŏ':AyHBiijYNTɜe'0Txxi"`+mܙ:Q߲QJNWr Nfelg*V8wZ qz*uzf wCs*KQ=Tg 鯢+V{Ri͚7%iW&~=/uEioG7jZH,4ʈ]i7ً\Z $90nʥ9ⵥzYdqXʦaojشHvh+bO^j9XW${ڲǡY*3Ut:ֱ 囩 KyZ8+衬Uwt"g[ 9k=kNJvzkǬ≧L+gԪZfyw?UsF9 pҫwJyD/ fh2JzK˨wkڷ計9XmK۩( ~};' ;1h ʋ[+[J@ g KKw{[ qX/lg˧'%X˶4Lqi?Yik Z s׸'xBwV&+7\8 ʐ' n<P83J <sW{^K 9K8@Ť?q)EIyk ȷ*: ȷ^,ȭ)_DcƌmJL+kȨ~q KǧPGk L̊ΜʞV]t~w~ }d^yD~дwPV{,qwTeVLʁ;~,rF`k R.l>pAy"A^Mv .2aˌv[ӉᲱFQƻc =u ߎ4X([F=ݯ~׽䉈\n ~z&l-+mJq=a>ʬծ?j/,]qNs~. n -:Lިz4h>(`ގo_ h /܇{֪y6X˝YΈfi#fM`*_QnP }F3X_*LH-NK GBH|W ㋋b+JdokI(/ \`_T}?i,̃/氏*.O *2}"Vb2E]C 79ZEARc @ `8`BNT.Q 8"@BLU;&Ɏ+ 1a$XroD`Xv5#ES(w"t`&9UwU53Ĺs!WJtsbRk4A;Q9KJ)y"ƃ۰ TsIG &4 h.).U U+ur =]ʢ0Νp= JP62DN;Aa!I. ƀ#ҩ @CQE("#e S.xa5Ci6هV8+J5Ne9B7إ):2|"6NnK.hE] $^MI{oe3pnp\zcԆaqET{nCX]jcIqh!!|x _ Uu&(|qfgy$FWGUfm9ŋXm#)WLbD)\7G8\nmf|Qׁ5\TcɘWbj&(}U*vmTGgn3BceJE˛ 9芵p:R-T$2&yԏ!H۵)ㄬ[PFde(뇶JBŤ"=lfAa@ikJa,-Elʗ {&,qC繟yIyk'>mU tzi0Gs |hwi9oHw1 ڰƫj`qa^Y}-^2 `Anu .u0fBlc8qMNeX,n" d*-oo@ERZN~M߅jd/1*?V61.WUQ[[smV s`̑}(=wla')w澯+ D7xW7^i+c]Jg<57 JgTnED [2T-ވqw˓LV 0-]":iG5Bc\4%i;:b43_E3v]DInÏ ħ>"8'9E#+ߞ2DW7&MD|""CaI4싢&\/Hq66j f[ Dz9+{8s3?ˆB-KyN59}I4] ҕqa42 rt1).юj=%"g-J:ބZlZ[a:"v4~ݴfɣ>%0be _\ W8!D@Z^A۳IcQrLaJ٠Sv lh)g  ]'jh -B>ƌQaAtȑzMJ& `ZM#b "?J8Ft)٘xFfVQ3-'hJvg.cʹn{EBP򣁴/7%2FMgwСFUR2B)=(Y FնoKݔ:f{*+ eKuS^"ukt[RPNJ3f#"J>ɦ&Bְs eXDB<P3(RS*CP>;Yꟍ&1m٤c\a젎jhi44wb\ڵu]ڷtnn;I}Wڶ.]t0 kOg4b'F8$5D}cqJLkz .38sm} -LsJwۛ9kIL%%SN݉zmƇ9s5" lu|찃`.{C|#QqQxi^`VLz/ȵ Mvk흇7g^'A~=3?;kyl{ej}c4OgxWAyUPqtq&aEVqGwerR|Bjj@'k%{IրU+x{2{v{}7ɗ]x[p|(ƒ)u|jU=Wsw}KmOB !nS㧀f6Ajn c_qnb8o' wuwlWGhgOJ\47puh(O ^ h~ Fwsv*DoF;a"7u6\Ss?-R1s D;s_BWTOxq[+Ch UR|Kx`MdmYmT\v֖Y~jX{Xnyh6wֆuo[!x_uoglLJgjWx8SE(i>TC%lEz#G2dOxk"(Q^؇/{'8\H{H7n犴(v$"_|臾ĄH}OV(Q̰mhuU$4n]q[~:gkjvVo8v2.0g3(hHt ŕv}S() Y_>X&@ <8w''8tòk!Yh88}M]DIdxHmt4rT7jHTڕG'xYW LxRV?Qj03[4>SEÐ]:~c*3y \ئiYr{W)Rgg9 +)¨ٞFHJ*WjJF!ʢ{)M4MƉĉBgڊwixIm.R:|z { W:Պ.;Yڟ460zߪs=ɧGJ|JzB&{Ʉ[!Y%*LAY ;v ۩* TDMD˪ѱ ;`bVɫPʝhruw:q@BlT Fڵ&+x}&B gk`0&dܪfź& '+N(ѹ ܀oI~U=㌱izoDlbK8Feɟ; _{P{{ƊȺ8:r 1jz+%tX,;̺[}츯ұ͏,Bptt ̾G5 AkL5|$V$Ǘ{ \Jl,“3ZTۧl%i˵ q\Iω٫ѰЯZIKN"-]S)+#Їb\Ӎ+1̌w=@M@BۜK|8+Ԛia|OM\!J&< |:nP8WR=;1ϓ;# M }H-QD}wز!Zx)1}yל4M6}8 {tڒYF6HW㉥P9k,܃9Z-յbM|nԙ-L\>| 4H?_lj< //0-|c9g0qNHJ3ʮjR람͈XZL`m߶LK <xg|8uZHBo!qmL9qW[I4N-F׃EJ >wEXQ 9WȔuUX\  0 Z4X>˅^W8^iWAv#:JV6Y)O}!ҙ'vG~dfG׹)Br~ lmek$8!V56~Ms%b fw#TbV'.+xQ&yi'"-q'q#n݊U襉3 TsCUhH}D.a,L&;W9ŬdcqRFa+V] (XM6ݖgvG&Jtio}Ul֦}ę,+O ȺPF" 8 jQ^w6ESs]IN7֜v܊,*7ŸrVL+ġ}Cם}ÎDF[Zdhmw뙷=8"U̙kwfZCvY>AVk^W @0T)d5iAQd]<;TץwBz{ӉZv8kg̵LWͦo|eӝBEG0ƨ9&Kcxg%_M}[d/H>bR[*bra(h~КK~EkH\+ePFΡ.Uf JG/5НCbF$gۙkBi!9S )Fv_<&J@*JelC5Pv ;'q|~AQSaKo12-ǪIaE\cIIlO0)!A_n̜)9 U_BzP[/IO--ahL|]\3mHԤe])GEQ`Pqb夝YE*|˨&y~NL)BXrQs*3tLg䱮x("@b%Fا%(R*Hȑk&mcۉ5l +L+R^š)T SY IZj`r5Pey|f]ըn1wh]&˴Mb*$EVb&[j:XᎢ0Sۭi#>qXJvy%Y=^Ϡ'tAg#7$(SK;'kkTP!/H▞o؟ =:'c\4LVf5ru귖Uoz4ȳMUX. Y9xBJHzN}NCEQ7AWdl<9**IO1{30c 72!ՑHw ji6Gs)CH2qBTYcz1TQX`v rVXSyBjߴ;T$K2C/Ys0hZ{~IR\'u>14qvKStaV_?2%&p6bk<شVё8C8em9$j+c[Q6 k[ncVgn7,K0^ji>d|e{o-۹s {@G.Ƨ_ )]mU,rL̵@O,rUi0&yH?=qxxy$Rm '%x`zrvz6;-h'<,IcjuOrw{;Xa${CDkgkx%GkWbtVrJK>N}Qroh[ٗu4}jS ~4SihvkevO,q9Hhot$so7'dhWuUwntXp{fbpb0_TgEihw$WaWW(s(ZyuXwVBɏkOS(\woiV(׋5iSi`I HAɃ(Il!urs}ƕ3rNQJY*@6.ZR~* D~:,aZygJo*]zG,wJ^Lڇu:j:r|6mؠ93R!MC"Xڱ :d/酱rFuN-j"FX &rC ڑ!ﰬIjpR)`3w .ŭٕ\Z iSX#튞jyɰJ!p rl{MxZFP97ʐǴxJpBZ+kSt%ڊ=!E#K pe 8{*J#v5{6++v>pG5ZWaluxڮ|Qķ34>XݺTۚW:82^cZ\{7{n+t94: Vʵ{^@<#Dk {C ۻŸj8Љg#Z<gYa'5,9^I6j99[z' #țКN P+'F^jev"{I Fd+Jwl9gɶ7GܗĔg@9[J Iyˠ IgrG(—,§J(-,) =)B{4+XwøF;l{t8yMcAJj͋ǁ ѻYYSKũaOկ]`;flbi}|˅fl:n\op\#F< ܧ_뿀ZU\TȔȏy i||K#d\ }%Llܲ{@0 2[|r$ˬL˽Z :<BÖהּX{u+ N앃hۚ!; ,\ۜ$ dxW;2mrٸqˬL tkL̽~k|l~,OgӀ% U+;,@,M:ZLѡit&Rv񬎯& *.I<=\;8=+F{l#>MA]C~RO{, ==Y %皸 ՔMm .~Ml=}̱PxM|j߱)CyH7-|O!,+ ۗ 'W„0㡝+GEpMl⛫+ַm5.m~Zb{zJJNkfm|K|ڍHI]^zaxmfn = /lN&-% f(,.2S@F=kᢆᒪ wڶ c4%')E -~,L ԃk&6<|.u$2ޗ  ]1Snώ ,d?ơ$D,@Z^iN@2)y t[xPP31W>.qP`pZ. οunC˩ T2O;ar\l2>)ۂ۩:o*n{+Q579O:=_p??Kpx.Ϭګ PPaPCՄ%Pp@2fbCtD&yi2sG%UYcGz4v{k[;QQE' umfYWvxIMS~>cJ_ %4#0{{t x [c]r+(QJDX2QSyf 6uAh&wa- | j Nàa(z$jѵ;VؚU)2D[-IclxjϽ8/v|i:2@@ut.a|F3pm9kDgtÚ wmB"0$kJ-IZy70\ .e :-B 5c;M7L?yk!JCoƼS>=?:SQC{t;4f\M4ECآ]u9"Ia pAE )?}hSe. A Gs0PŰ7r8Qe\k(z}@fDd>ϴV+p\`Ե7Nd Q]L:7GlYXayU{gyk~D'bD(̘5dZrƐn) %2-Ar&)߂`XUJ6Y5kyD}$#gs zGO$Yd5 }#A3IjwVg rN%>xFx6<3jR_$bx pfQy!PjCyӋ N=T 2wLhGzh Bq%Y|4MCv1 eRgw6$$+>z7ށqI`!/ITZQyLj _(( ]aIkjk9rQی~FۭJ(!-ݑJ跹 %.MW \t/>o \[5wc1"j@6PK'b$=2z{ErIRǀQ)x* Uশmqgs,NpAIU"PS Ҹ=A(? s\ E(;pqf! g [U.I1pMtu03*]Hw oZeylIsر|-!REMVܻWoDT&J9^1H&ѧ3jm2]g3.*ό2,\Lq?R,P^kT*C~x)\ )2lɠKʂu#y/|db 6C](-z:2J)a&T̪vX:`JR+ئjқ`bw *^=i{ 7CЯ಩"AJ)  Wb%"]\b4;.ĬUxP-V_M':Fre"Qۅ`UTڂԬWcKhҲx 2jO;.\@ $B>5{2~.je Eҁ:`yY1iZ/iA^We0y[HPlɱNmle-\c6Zִs,W:|Y.88 lP@[LP Vi-#O5Z5v͢C.DƸ%~ɄQ yݘA)h .J_*:?}.5TiVz'D2<"/b|3ԧ3S89P"sΪ+} aAqܬ{LU|ʼn3ن8iw[[-yO7L[!Z|ahdLÎGTRY~!fjrՖM0^YJYvs ]#׏B|9nzꝅ్96eglT#UJzJš2,8#vxoynGn8вeD7D7q9YzIKU'fpePT8 gf,>[/]Ql$|Ʒgfȁs%lbnV}t(hӳ}h:7i'AEG#~HtYjW`×vg)WBUushVfv GUHbCk[҆6xֆXÈxs?HN YGy577Ty+(Yyԍ9t67(OVpd\NJm8]dG|DFFǎzyvjxBYP,"Sז\Q9~8<_ry1BiF7~`hjؒ"1)Eh֊orlؒԜEiWpI K|UYЋ/Vz(1yykÕ8wM@lբ v+{pcn̹֮o͗"DIow&z=X>&+Z9dt+~n]}A#+Mʹm" AnC>Kmd瞼ѭ1 &p۰kmʆ܌5;HmDvǜ츾U՗ly~|3iₙ]nT~[Δ|nmk Ⱥ;]Ʀߖŀny'.{Џ-иʾ ץ:_ @/15:.~WPR / |->R#픜3e_ ?ةjlm|d,,۽w/ pg (PƑA)EAPvhIU׸&pM,Y@^,t3NC1AuG3 \j JmpTka~h-k8Y^V#~Eu$7WVI|@XPN8 f=KASQ]GSV*T[ #c{]l.iR?>j] MMz^@{?ċ2hP*t, `W_g׽hq(H*]R"P*O@f2 -sVAB|F"ʈdɾC 9"b!ؐ1`& g\F&=^ [)58fh9B \V[ wIIHnm` kU |ZG5jٌ)ˇ>!=SV+21WUVS=o71TOF}[?ZB"pAiADHxA5% t8 -DX#)S't0q0O<"TsؖQ|̅?B""A ) \)M]thQm,EQxWOX|(dʄY"drFgZ:ɉtRt ZSݔ2Ă n{r0=]=UWJ3Ly'7j83zhp|4![e=j c)d_<Q`P BhcZ$=t#V ~V`]ƁoTbw.zb0H9`TIِH7?fDe`*[(@K !b:Y#gv8kfq6YIpgF%j} :[-(mi Z1ȓZ3bHYr[ɜԬtͅx28nT5DkV6'AA,{.}'l"'f,x̖,F;' ::`Zt[D2s+_~P}+DVxjI隅`p풒n]J43{qqe;WRNgNbeUsG&|ܜ0(*[g8>*'-24}2/Q7l Ʃ= f*ߞTݡ[t-jm@rӃdjݘ+xFU9ZcĢU…_  k%b9 z 01y uE%u]dǶF[YCezm&x $ 0r%2<b5E1Ɓb$Pgf@ޟ63}P'oLHo<K"aS`9 TqClxAMm[9ې`n#!D 5]*|ʨN;@17Q֬ا&+3^#zK#N(oS,V<5Љh6j[4#~glHVґQΫLHȃ{AQ ^Cd 蔂5$;3PYUjG a1령 DPx+Z@WSTN?S#X>rXQQA;?n%l0Sa008 Ih5&e/y2,ד  *)Ϗ.Ea2Ok\ZP/֮n&BC)GxKߨ82u~ɘVt¨HA&R|N{]jfR"̰bG`L><$yd&gCPGITr 7̋fLiK2R+ iXG6Pő VK\אhY\kд5 :[òdx'V `>b>)Xu%fE4vWBxT%lmAa&K*p؊6{J{ $(E$79N+S PgZ|$qy;T2O\KsJk#WՅ}#o&+G̺+=f@[sw:]at%6bla∗M'fa|.ar5.N I/W>"{.mZNW6zyx*iE)92($neRU6is\y w6D1=Ck}h^/Ш;Pg p,[K:%s n ,eŠ6|eL_#WtV[T:Ƙr lPӏ5D99HԥQK)GDY+VKknlqD&F܌5y+@[ݏy.CִI;M$W %7 M>&ƶ'>Y&N^l\p Y _*ÍT$0ʎ@clq%J:6Z`ERk3JpuZ5`LM3QRR0?(އ{ /q'٦<04HWE}?%G D)cfI;{UBhOx5BBLKMuOx@WR(sxLWxsXnFrnwէb7k}h{8~ty@E5P[g`_my 6d'dr[=!q2 uHlx2).<5\s˘f;oyTTsv.0JI:L |lj1YxUuqTTdY'\y64ɐf*ȏ~Q THsWjf0y bk(De'ň< iogrȘP ZY~rrڒZBh2,બ`b6I0@B@De+[HIz*[%P_7hhcyAѦ pr쉯^iyz M~*Tic >w#ʰ䰑7R 6נl%i5+y|Qu!ۇlI{viwѹ y˪&zֺR1CqdFz˚LZ?1AՉ]3B9 am/8[]J D*jHh!'{D{d{uKs54u |`;|;,;Z};u6uۯ롈9yJșZ̲ ?3/*R˳n6zy+4wq~$ ܋6eKC^Ԡ *]w j,pҵț9zz@C.k BrA(d`WJs}Z{%#||n8 I2yJƘz/Fr EXr#Z),x,¯{?85[~MY46 ,f~Zċ[oˋfkv9FLˏ&Q_;zC ƨRy6j|o{njAv)덩f 9\(X볏\ lR3[- ,it)$*+k+ZF®Rɮ\[6馨3=e\,z JTNi)*,МpVqH;aH{렕4:pe)@M{8{֥;&qV%?\ۧxɭ|wth ,ދn=˷ #HD>=E=K:ټzʻL|KɲlJҋl^KB̵9\lAAh\]}a{dzSX Ls-|@ŢmF=|tJci }¤Pѻٳ= 6ۙL N =ĻYVM̚D *}Kd,fE̞mkNk{KP-{{~m]-Η͒׺8 f ͂O%z 3Lx,[[[Nz[57|9i ӹd3>Qɛ;>#l?I(续)ZMo]H^̽)5&WqJݪo|ٷ3ݛϔx{cWo<"-}Rz~Ρ0QoKFԠ]m 6mΚ_.د S+dn~JL([ܽn>_ޢ~ Y Ħ c{ˮ~_ΦGޞJ~s|߈*tqCW~5$ C4S 瀋Ns&,̬0nOvUKt^O o5.?Ln۵4F ]O\g;:߱{Neci%Lslݾ53G?_fg}%k(lfߍvl[՞^%\^?1]_l()E9- у?ЏYߋ_ٌvmQa ιsͰ4Mqh :,gӭ9 e2*` <"C8 <'[i%R)&tLX%Mu zFQ'aH&'vT$uV9 dFa4vD3x&֠D#q# {\%qsvz ;NۧډQ3 hF~)=ю Ώ8 ?T^!@O0BI ~(g2DQDVc4ОP6$H(XűJN4VLE1 dдҐ-FF2 ;<3NH HXh;ha 3c蚦v۬ M^ ,rif \b0Ů.P{Kx\Z얅FŸQ(B}7pi9|7/%d.- `7 Eo:y B1E]kuTh0"wץti11e v[I )~x(9AiUQuY؊]`CY=AZ\H)WBXL!239qb d%Oq6Xd\:Wنxbx&!hFv9kهlaR[b5P`sh RI#SFS]jr=g[vㄘZC-vT>O*j>Ҟxrw" I6u aژh6J.ݬ"P 2!msT'QHjQمaT.:łlce)sR葐D%Iʒu9*: qZc[sCjG@Hfq#Iy 5" ,2h"wLVHR9,dqd8#IwMե#rIkN&*aF#:r4a C.Sl2Q[n@HV JjXr+d8yRa\ a;#r$Mrbl[+h8$nOp #ҊbqҚݱkKxv6-QRgw̶|j˟\(iAK:4nӜ7iR^E>?=1s-[MxfL>if'9cAM$M rEoкipZd蜌[v` b%n0Nxmn`p4/t?’/ZuܛKn8 3nv,f7;2@-p#aRPry!آ%yC((>GGf1m19bT:uF%?2ƷWQ@nԌ8,NM=K+Q^) a&UAu0_ sYK]$!O+)ae*lY9Ёgc!"q:_pi;oԃ"y1-xn'1vGV̟+O$Gz╟G}Q ( R 1|RLK{dT꒢βD(84Id`KWϘjuRMRVmƬa`A@ٌtigl+ 0Q-TW]&P*CS<3tS&!;CcsF6ͳ-[KĚNQVEKKlr9M^M'nG̬V-3I䫢Y U^^Fמ%HuM8L$sJ]G'[wʉl X6a,1)f -֐R7p4HW{O,B9T31f#}mcbRŎc;3=. q$BFoRkV5fցjnMF\^0N/ s=OQcy:Ҩ7pv2 ]d>r 29~ jycl ^wAG5ϱ7{za]Z+̘5vr& s76 k7!S%EraU u`~2Lۨd;VY'q[fˡ.[aEg[rs2]km9֕[ۼM,k'5ub#< e(G+aڊZw+\E ׼(^/NكhlͧA*\ۏ/ʇ,*E8ҝ˩seY l7] o;@ۊBnj'T5x|h؝5ghkfF)Lb=5و1݌f:] nJ-*{Y]pvI.cPD}]kG̵8t!v۲r̽\Z3e{n}#KoUUgBxuԥAb9z^#gwoڔqCq`q~ zVi6}BFujCG1!'R)H6vn#~f}pl'ZARUu}Lsssuue} B0~f~njWaxv4Xր&,7oMV(x8esev HfrxC_wwhyohH e!(PTrQ|IOr,xj(XH{6!jG~8X|?sAXiW~׉.ztu|H懷kT\oc7h\?+c5N6~lxBw \O Geq ~wfq8XjwlW`р#Ɖau},Ha47?5G ڸ{dm{txӓX^x\Vh E;}>քKr8r4ZsRg4uSȅ{vdƍraDkTq}p8rTws^R+|Hp-cIƎ Va95BlpyyOll^c!j+'yrG3"i[$9hUbu\=~|tH|$DŽCg(g'Hd2}F9v4LJivi~ 6&9UWjH67P` oHoxp4pIZs2u)IfYhɗgwyKyy) 6z&ai*蘌y*h0GT&@7U2dK\2Ku"{>@B)]G*T1۞4;*NpS ൝TJ^6˵F+CJ[ck"ܝ*AZ"Hr` V{ƽLd%ٹ{ [*ڷ6IQ/{O'}I,KM4tvH7p)C\JI0Zm|;ŪTAJ}v:q9̐Ldth lzWGFszHxPy{?u㻯@ȟgȡHJZç[ǀʬ$܎ǚ+|-,Y,)TS=Qg/'ݼmy]Ū#^L[%>Bז؏w͟Dٙ]ԦHeڕҗݶ8/D7~x4V[Ω jRH3ȚA8}W@:gj84Î$b X. r] q숽vN}1jܽ/O. ~ ~~#e ^>>9٠LlqGW/_aM_gpϽ 'ݧ.?nA_h h?7Z}@edœ%0Ul4z=xT{t v$!cQS!6%`-OI #|RT9C]8a@aᕸ*K.n+ BZM]9^CSdjVJk壆RdޖъǗKh 銚֦->1*`rW\V7d8 T ͡^G!j8[Zmqy| m?ip'Ya#̲+ x 9ƾa(m~XQk;2b_"nc]*nmk8T7WHKX;vp a&:諓:'+o45ɩrr*Gh[5vn.W@wAW.YЙ>/GyJA #W|uGy~kaŁXs|BE)ZByR|Q ,xZb\OH@),oc,̥Cs=xL!F5˙E` }"Rd%;l!%AoxxHgS Unr HwqO|^=Gj/ȴLN~'?$ .A";M 4@c"+~ E4SU`Q?|^MrsCe9b8P6KCyl x="V3&LO|[’Ub9y1w #VFR!Sc7%aͩ_#l/zG|(qx =HH#$dDjh FJ ,|p /-@y%x2lotdz9A&X:ҕRpǂBgzR+52s1QbST8NQjZXw,d5[鷮OtzIWlAe'C6J jR Eˌ2 g,H@o`k%L! O ) 8}U)2CYYRVĮLJp:KdT?h DeBup`t٨~rg}* [ˇZǕyd'WG ]ipW3gyA0Hy/R'morDYfQ-_wN#bWzZ=ޣOd]~R 1֤kI~qiXISq@AP!ز=w3 詎\\Sf!T^p@[Rk-*8sE485 _M+vVQNY3< Fԍ*y#0D3Vf bDYr\#=ZCx:kQrI'idj3.|9ȫ.&z+/WqnSSQ7dn}v oIOzeG+Q\2V1{9NK1Q6L)>tJXie bh$^)O̼CjanG:4x]qm6n]9grmO63P$lpLt{FO-w}~0}~?rZ.g+]Xk-7ƞzvNh5Hcɺ\xNkھwS+@xfxiaL~u,PT_qp{\ "Vfŧpaqz qQy6Ua\z;(E}1P#{|z6 ws|kxTt>d|oVligob )@RO(dHwAg@~f~|eLT6fq/sW'o"7"$%lTig\V<'|ϔѤ_`.%kD0DzG6N $hb&Hi(8ENzaVe2HuŦjjG{k{?]M>WXxc|"w^bHBG3/~&~}?mcfp6귆'wvsrH|sޥn$g\m7x{^5g'ZcM FZGy b4ztrtjegF*HaXm%WuؠaDCǒj`Ljs IHtƄy][ZbW[I#腲x\Hw~(&҈ܧO XtȌJfxz'ה~*nA'![ep).8f%zC:v1Di %"ƈjcrPO$|X55#!{x7EL)1$HepPxecHąiRmebUdi"`[O|1NYV oـYkINs=)s rWh(;Xy7 &9 WTt+i}؄~Sh E$#ēp!כj)JdI#*rs)ʂ*){iuxXMHIfHPȝzٟ x^bw%H)"QR- 1V~VŸqڥ~9J\woz`C9sB +FqzZ^C"5h|#ʜ1ɚ uh)xlMnjZ<-=#\%AV;h ^m\=õz ѠЦ<9,51˪6 fjZmp+=-ߛ,嫹6 YȜӚMLa ~eMHM{mmjk՟(]U 9VrIKgȮ <+e#ձ68 m ׼t̀m^̴+ÇMRT|=꼈mS\US|ZT˗ O춞&Z7M ;b×b{ۡ񒠪ʏuֶLr^|^MNM |e;,-:-f }OC=ƻaYyҋn<}]68ʍ,!o-S-BCg+ζ!Gp^ouӏ:]:3N:ԝۇ;[Aې'ԗ ,DC5=㋦:N<.dѝؼI {GDhީ}`״l;Y]N";L^\]-l2t 9y>]|kwW{}x~@H-<.ԭsu| }lSތ-=N@$^Y9>kV &+wɾ,|f(_N"|-6V/ 0N .̝ .Y }Y: ~>|<}~Ԩ+꒎۟/7v [Z.{7?ڌoE1X<:ܧ=I?+{.˫;Ύ@],Dh鈽,Nüಊ|d '> ز?]2wy~p o:G\O>ϊsaAP2 gE` dL_6/$rWpfEL֦s/  JhGtͮ*i+SF| oR18VsɦSyG SE!Augu15aGwp@Id2*V"1[scipXt:C{$f`K("#H+pJƒ ԃ%EATbH# ^ʇ СBB7D(EF{nPZৱnd ؤĵΓ?;?V(“q4/_e\Pi'q SW/oHIճ,DjhJ]CK /BTfsBfM+r_vmUYVx[k+A a<1)BMjIKe6ZykiRKٔoe^5N`釘47_l4SgMO~#fI=d$%GM\TMmTW aEaa2)VIf[<7iG,)u٤LaW y02=YYG.ZK܇y닷k bsYaJMg:l;"/44XkغĞAq8X׈&+Z*?pu$fx{tq;E+)Fx"&YXVi!s(&Fz[c2=Io#|-,H-"|;9sE/#ë́s"t1!yNbl @q lzʮ%ƕ7XIW1 \Z+p5M,"kڃfKE4CCf3BXaQ'8JfwR#z!\TF#X5*P,:IYDƎ1x1#<XlXaAou|+PK†O| oFNP)ώ@y8}iL%' r 79ktW!VJmP Rin:! "Z}q;~b5aʚXRje+ЋsTz݃OUa_*]:m_wXwέcc Q0pF{O-] /1b'g<8vb YƶZz89ۓ3etZB$H?~3uS67υAt<]SU ^YVu=F,G mvVy~pY!&}k_RcV^a[P!\oh۵x1/H %f_fhș8R'-&)<+ddhGEGVs EOPa;vm%JrvS%ia c0 WU,4Z[XME78n!^1mrMg: }!y2':Gc/6#F>!7Վ~aZI69MDzemRk3e#T4r;E5sך_i[Q|^7x@&g'pT}Zx%[ 4&6BpG_vGZw'qW17T1>\GD'RfNuw{|Zr[{|X<+ehj$t|wws{[BG:F}Y57QXRއ)GZI/bh7~١n>UG\tn]*rftn})z]w{3'^4VW[RrgK/Sup~\txoJ̔k%tǁy/FfxWzP#)hwȂ!,rC{7Ӄ{<l6S{x#?Xq[HL|MP8ReO&u7=5[aWm zj8Em9%okdžvTy("z4o{7!xqD2gf]Y5TQ"_4yX\;u\LiJk8r2@]DIGiWX,gXąs@(:DHkZ]( `ׄ;)Z#vkZ(lE)vV3#ԦSf86(J%mezXhE%9ieD͈c3z~ v:@gvzŎ % >C?u4SԸii/H.INy.cr>H8 tYZ{`hRLNl҉snd]Z{cp&SsuwXՄ)VȗpXY"p2Z1yxL'8(#/)# 阾6I%H3p qG̥\֗J*w@i 93hM/uwKGءJJ$dHHٝKH*i+3ښY9hy^)Z驜QeQwG(; 8{nZ}~n', :J):Zk6"0imਗ1ʦ]5 *ms/ȔȹG z8 XTEGړ5W x깜Rj[Tz| 9sƗqi MBY%Í~@ɡY-UIJ5 h_*xAoMYW4Rڤ&*ec2ؙozov:^:bSuIB *-z Ed-عDiFzHj]LMkϊNJ{0XOQۥWWKYKgj:[n:d뮺5ikki!+qs;5mrۨb*&xsueX\S[+,[Ce+K|_'K6 |:?jkKwKA bJq< $ a1;:,Q\R;|쪾ImI k;t+ 22RS{8˿h++o%u`\&|o+q 8z5# pl>j$ܸj볲YwUU|>ʬkB8Iťjh|S:1twR{wlܷk- Yr ㌺xe|:l|ƭ$Ŝۏȁj̥F H̲\{:>ꂴن2L4̽ڦ<'s/ h\,-!=sdڽ<ƛWlƶJ zIkYc(}jd}@-B[q֠B L͵ͨrtԂ?T] <Ρ=֔; l[Ի}nMȖ8_Z׸)^G:;lNÑW-JɋA٭̞c vГВҲ`[k묦}i-=m=[zݴݶz:0~ Um٫gLj+ݶ;=oKmƳ.\o޼ӻv];=2(tG+څ݋}{+~֛Gk!.X^J^ ޛ- G2-4Mǜ9=#]g&>? >{2]wNܞΧ@n+i]XHoع]LgonclA,̧ME#N{|G=ĬN\͑۠y䇎Է!bM}(*.[/>l13 ~w&sL .ː۩Ģ=*`â~VD^=l9nW?mn•]ܚ.k[䞾4rk/#Y3bϬhjVC1ύkν5O7rœ ,:-p;W/,eM`Q >'& oj_loΜqIs oԼ_l ^d!/^º/}S*.?_HPZAUL G1EEC[ fEs 9XKEqV@ Rw@s~~VB0Z2NIbۨWr(48!tk0:{+M,%{5`vCy-X=,158Kk#A7jN'yT~8yJGwf/AQM@/; W'b|М3_u# FG2k5eQ9ŀ78c4r☬Qp Ype*\,D_ Fn]GpPYK^f3WЧ(KIC2"qZG.i Vc+(9B>$?H O˲e]T2; P:6H&zQo' 9`ݬ%A l(٨}?Cdr@;/%A>Z\R::)FT߫6pD{bÿdU[JHMeLD2LsCBk h yzDQ%E@m!L_Qlu2q' [2ua^n4Q]6R]؈]|P;dgvrP$eIhf}Ak:!Dm*wda4X1&!Q^d#{QH2tGx5IHPs&'%j%eif9uT1S;hœz fo%W-td5ejJy (ߊcO5EAߋNN()b z)^{!mZ0-ObhCU$twƧ$$5!"iHSe$ϦQ*`ff3dzʙ~*M,$IysEצ̇W3W sL)\\ _\δ"dXktGoB`Rn:H޹G,l1kճ׍.9EH밣X'C*[mbg+܎xkT(F 0As3RbH D } o*j` 7+~ Bձ VdЕ9"yA;2!ShGA|zĖ&ǚxx|],6 6h<, c93  7, ܳoY \:GYix~gGlS'%%bR)e>?i6f MnMA+Ǐr-N^(/2,P?BFՓ;vXH36=#8t4qIa7ΞAS:Ϲ+ Kn; FJȩ?8veaX{,FC[U4tZܔdBԇ*S:J*n.m( 7b4ESYH>Χ%Ԗ7bGSR? Q LP͢8\VGf5J%f`VEHҩE 2T HkÈRt,l>VĶ1rz[&xQG#e姛%A$vPWHb,MmY(4c^nMo]*bع˜ׯ_ww!5)/}WSf{1~`'hJ]{2hzGByCyJR3>QiuiyvFwi"WzGsGK_L0h|E{$uZHk6fdR>GbC|,wE&Wv'tͷ8GmdQmǂ@}?IxB]~Dw|7SBdg#cMbq&1t& c`G$ W x)pj\hWb/iy~G'P$w{M'xn)+{r0YgQgCbbQ7Gd14Gu8a|O8]h~f|8}kw}7GAVXuXZ(G9%~E~%Svv6.V2oh5i^sH~VqtUWhR9/%'XX65p' F@[˱!i:UHdpZOQ^UsL1o{y*Qw+=莾M eg܈8b\Xlr4'zPxKg43Oyvֆk}(wA B)W|(xTDxdvă/ds jj -qhi쨆8zh0&Z8<Ib X ;B蓦I#=)[ɘt,ׄx%)ImUɓQuۆe F`Abins7G\v[ygfI6pL&4qW3;)x` u؃_94IW TtqxgXXUuhQǒi16D<8D HHzȔ9f{=9yNSa*؜WYT/b#Ysזdi rug3 wx~Qyp(55-v}yU4SqIU:d JpYIhѡAei  Y4(R%ZkǤ[қ^ @NK8J|6 :BVK>}_YYtR:X]E8\ M^*t9ovGzo{}j {79SWwp :Hy\avZ8q鎞&Oa5Tmjcx&?\|7:mT*D̈1**JzIj[vkS:ìVU(Ɇ٥剙*l𙭝խgji=9kNxtz\)ʮ2t ZiX;; qدnIڵI`t){ʗ3K٦sMYʛJ+n$FW\$9Z)eyb8 X>wjD;sf`Vu[oʞ{%nZ6wI} *yvkH/nP{J;6zzC۩«ڀcfWlaLJk)L7E^BHl]cln|Z>X~5={lra2ΘiM ɦ)#Kvқ .1];Vھ}-ѫsӣ2ԎkFH] dr)N+^~Ǡ{dnGA㪮_[㬾쳎4ܨּ^(S^m嫫S].Ў,(+^ʐ= %Ql>浗nzQ nAo?d9r$]&CWn[|af( c0wasL `2 116SY<%NHU #w^wI{X^\f]FBg`Ur!յm8_x CX#6mAIX(lf"dEh4釂ŜkigГƤ8FtD&($+]N7srgutEXmeHp9x!Rތ1W|:Q^ &0H\[J 6x&c[Bi,¡R VQ= B뙨 6[We]P$ aR\[]ܳYDۡUbULV(Ve[YY:5ˉ,yi yavYRBuT?I<y.q" <՝ߒ'ʊ 5QV*ɘqͮ'"xǚ@)22&fŕ0wUbD2M!kbf+TrK#Wmy}׫9\S$e-f2B,O0+t=杆f=vܱ^ \֚ Kԑbn hiuL][m_{mJki; oS@HY8'A1tbN%Ѵ_AxQn{ǩWJUSz! T~ZVԓ@DU]4=o72/F;<103L i-=\u@x.]@"G:+\9('D\ gtV3 w ¦!wYa?]@tf&fU W 5^\=p+3`Tr OC5 - N$oXX*CbY{Ȗn.dgRm! FXk)FQ(|n Pp [Gp!*;5x+jpǾ.ԺXȺ7)q|$3WDh/t☄ۭOwy^ɔhxALbQPQ/x4+uT EP| OlM稤TzIIiR N>%ITJ(c|lȪ\LGf "&5ʂ2B/CTLT(֌-!$*|_RL)&ZU- !׫l79ӨrkChN9P\՝p43mگ|>DK" Q"tTI:Q1 jFȼ/|TI9 oB;E6 <{; @ٛrk: DYʺCs(&edZƐmEյaK*1 亃 ْMBZ1_vMp(;TIz#U<0-91 lm' 4"jul2;NZeY ͖Vk^u)f̮wmgMZ Pw`O2k}f.xI]2W> F {UL7 sBCKDtmmz3GHrgK2ɜUVr͈YKV^g~Θa CoR%COKArk#1m;3ߺmdMCY];32(.PXKgLyZoPc0?ڒJ޲kݪFUZWmm^t(uvX0IM]e]2w"\ L~]WF5}R'ZSrx#kb[Iyo yXyls{#Xv#784hBh0t{oeC(v8{+q9dN6`7|9aƅws-D%|'7b&}bcLx6eh x];WcW5\Wxѣ~qGl&&{\"kg{[$}-F[,u{ #%fw}7x؆T͒2X9ty1_~@p%hg 4h>hUGziz28`5{xFt*ăڕ{8/WCwV-8XJxbdjh t|}̦k`t}_HF5lucFiX~sCxm$]'LƍtڃvMzȁчuH>(jenrFEfbHl}h X4gtx(x^pH,'nX_9e57zF{=xƸ{($׌䳄ngW#wdXdǕamk x}ghg0'%1+וQH{6n؍#Ci @وN<SVݔF@ԑ8Cjygz󁘷)䒄i$kPzHH_LRbFHM#4 Jȑ78h78j8Lǐ٘&F Y)`;2eE}jiَ@2s8gwYD^ٗwE@q&e؉߹gv- ɘP(Savn(.dxlyT5AxxRU;+z}՚+q$7c1|g;q}Ĕ%w. irDPlʞx2i{ @rX%85ɢ'zh00˔xOАA]aV>ji2*T,:rBx WRsrX&)Y)~ȧc:_ФY8D~`H]RWn8n@p.iJʺcpzy )Y)Zf5jꡂiZyp厇# DFB/J$9zJi))@yCv_Pګ&ELK٥V`AjJb)Xh&lq*zGꇯ#h BT2;K. *+ O㰰Qw0dnKzx5ۙvt&4%۪' )в9Mu:˫ٳű C{Ǚ2G#@6ta&Xߺa" %Zay<h+ȶ8Gf9k[w:dr:⯞jFHGH 5;Kcs G V2+;s * vZy4&gϔr{b"p}ıf~ʩ UN@.kR9ЊVq݊Zk^4Ea녊fuij<jtJK p;GfA۴75&*}&p:Luwwĭ𨕰č\Ŗő-`; 2H2(μ.`.).7\Կ <^oؽ`NڦL9n?@-)NczA]ά܋] ku]$n*9sr[ pܒ.eقY^rNm>߀ ۿ ˗x᭝!%~'α-9QTa[jb~b^0K^NczkE m<,/E_Ǟ^!F ,]be^ yNOsJ>$ٌ`ɠ^qi>ŔκCJ Z{5svNƉӨżɼ/ϥFBѕjܭU˵Q]ܽ-ZD)}f3IGԾ~ eN7 j㧆VobxoGjLeS>y>}doϚ͊M! z.~ʼ1L`Uc0hS苁c-`D Ǖi'BMVJa5LvtĚ4d:/R!U3h*)Rjx( ]v7Axv2#[sjqru*^{qAj"$.=qR%d1|ty->ZR+>wy|!XH }.HI7 :Moj4KrtPW[&Gc}d<šޓtJ4l2DZΑpPOv n)er:(.^'JYe']"EC!"8Qg U # 3\Q͏m\Ox\jL!Ѯ-$4!&XfEہIHqMτC2PKUpS &Hc]Wӡy )wśar%0b'^{AԾ&*n~5B޶XfZ{dG`>yBEױ3_7Zs"\t.,Eޖ4 a׺k ʵ$]i%ru_1}ci!uy7U;\XN-3 @v]gKd Or &'a QhUR}P5&0F6NPZu'%BhQqLp^qyDAK 2{QU0Zp1#NiMl[CeVn8v c"F`ilUB*vg Ӄ \s•!M)8C 5Rd~̦#{dD|BN^ _5SJ4 ^hvڋLIסO鈿 ͸}"`,Nxɦ9SN?UyUVX7`/)Ѩ[(O&ceq=6dt[hzJ~|Ɩ*w)o9h9gj"5$펴p,T4mo]3bx=!ʮ/oѳ}A;pWQ\mhrKܧeҹN!Scs sJj|@1y+F0~Ldy\u .q>WF%@uטN#>WK'"͕*s#ߗd9Ї,QՄ29l !Z6<oCwj!./7|Ihz<0>7MYaEq8Ri čmqXA#B?~H$ $J폒a)}fJ84jH#wb6 2YxBAReNF菽m}l&+>w t1Eq@U!52QC\4$DμGQuEK!!aHfd]ވ w1l-˲u ȥmZD٦? #p?P37$ q. |$UXMOr%PA3(+u2N4WÊUi|-`\G!H_-rwSLt߳U!q MյWD#]dFdi;KŠ.tMWo/2O"|O|E)"")fpxl(6aX@lJK^kGHVGnsI2EvpK5u%k÷QY>5RҨ:KeȖajۜ;1r[ D7 PB i1zF[F8Mzh6e^Vp]1}ifNV 5mqcR;}HsGS'Lŭ,x-$b$j58EҧRE߫FPܪ} f^!u9`fwIzp##[$1 wrT5rG9 @&6lB>zGNFO6;x˳WDw.ShQ㵪^Pf{m[F[c-)~W.r΍l4s;3Tւg91i6[pwIU9iZyى>ZChv̬NHG[BaВN8SO_ptS7HBH.6s!^`m Z )WeZigE6rkro5 c,WףE6Ge" IvN#z 6Ŵ 駵p] ƒpXj O:ēBB H6Y[d]SUU>`o N.bjr`I|6kk]q\GHمt _iXC ֧tQȬhm׆Iѿd2 'eCq&Iw'V)Gz޵frEp5`&g?tg79yaW1gUN""+3x?Rv#rȴf!4^jurwhxw<sֳ~C7|JRqd9Dy;8t[ tEGeRGLTZwu'h3t2vwmeqEv:_XcsD|tSuC85w' _uByVzt&f6S8fJ#g:rrVuxGC%)8'ӀG'j@VsL%3 65szzr$g&L,Ui؈{#Zقj|B9ׄN|US26y|XI~1j[v_xl7 gy=ʣ7Gs?j[Qy؅|7s"=.{xJτI?Eo׉28Jxyf\GqƊՌFzdAei {EpY-AX@mFNPgGNypC|MytO$}JwO[(}hEa8 HlX%)@@f^kHdk72v^h=`L%%iOGx' xTVB>]xftfpg(HGǖohz,R؂` {z6Lg =?)EɊ ( BLIo3 ʙUiX:vɕ0y$c)U=a'ssX9EdX(uƏm7}S*ᗟ5 ;Y_vbXTIѐyg3@Ӄ Iuy xTqؙ# 5h){]0_yVz'`6x{iGɌYyѹDMr5V9:t9#^ 1ca}1ZPeca^w~u՞WzCjyٝٹl$Fȗ~hccu1V,\SxiV9x>CeE2 ǁW=!^@Q|IvXGꂮz՗ZWvU!"kz m dȉƄK:X}Փ#ԉh]lO6Y9f;◕DV~gi f:GDuIVPκtqrPzz5~&Z >f8`GK)F7RT\8vh}`9iWih~+[fG:YyږnzH9;k٩'ڋبh z6e6Hձ&*iג\k#Z*x-;GLO:P}W/ aP8wacYu{[ǵcaz{݇y̛γ*kb8ecEd1r ظ!$%HF/"R/im+4*,6:0: i;dZ̳ƪ lkءl"0kPt uYȟ;GZzrz}*uAmuڵ?J[ZgKk{,wo=;YDĘx}+G>)l< ,;ee7;"汼x:wqӶG7貶APKf@,췌G yU[RhÂUi3|pjXkO\aldXkbhRLd9?14 v#yƛVy{nLɪ ?fKuK){:l*|bLli w<\p̛i7̞6g>|0sϧk\eK" 2(i~$]}"Fl`{ ig,foX{]W g笑y',ORy+Lƅ9tZ1ژKl^͗LY5݇8dZyƻE!21B\S`wL ٛ_,:ӲlwQaeIݾK] W Ljq;83FS]+$Ј֢IS*L$Ϟ_2i׺, Θ,*ڻ]{gX==,Bۈ Tz ) W|,BMݖeڦeAjL-ڇ`Fc5XжY?>WAQ wJIP-W|Q "#t;njUVᥝA~i%?=PA0H-pp-4*O~g{݌,M߼ڿ} M- Tݖm.}/ n}H." ɻh8*a@^68C]pD"<8NM.Aw{ঽ¬7--L\̝` 0ޫT^nq{KՔ) ^HNsé.lxlݛu;NNy?U^h\Z\Ng=uxwQߎ.^|".NYoV\}>Οv.6tᑮ8> @m~|מ[O>~m ֒ yacj=m={r=?Y|В:_֞)~7 KJ o:7 ~g/"%!`MbA$Cy/ ?P/8!H-Z1>ސmn퐋R3eV;Q)ӂU[` 4hJ 2aDZ@#iH&[BUB٨hAo3ۂ]@Α[A@»N. g沦1AWu2`vСXR!(Bqŵ:GۃQ:w4SG8*JkvwjS,(e+HpGz [G1k1jEJۙqҔ_HjEeBNj$ l !JB-FuϿT*CwACU| Ŀ]%5508*REMLLErQV\ j6,qkR%V ؄'P` c5 Q=e]x ftzW E7=3yT}dB,ёv AT  o o[bO~Giuر]3twmDlVj~/O\/68ODk-FI0CRW+Q "9>J'u~sFE)KTBHv\FDZm \yIXAh]u)i񝘱eśT2+&yfEr\I(nan0c|$31 짥~pRgĞ x ٙb*z[gͥ*3̓ Vt*9j;!(ؓ{paE7Yt&*e.2V(q r&!rqi7` 8<.~lejx(aT2#i Bf'ċEaWTv(js oa!s<8ǼF>mɀXαQ7$y|i߂e>.}6L(KdOKա uGK+τN٬@E}Q 0*%ͪAQo*yV(?1+fq!8ǩhdh.Iˇ-ބ> a>!Έ~"*Ffi[\d<>]npFkD2Jȱ4ť9Xoc8 엢4mA(\\Hf 9%u>QQMA,BzNyTr 9@Z2[esf .=:}<6dޔ6{O|e 1!+%0̚CLыsS,r&dֵs5@RK#L 4 ]28czҼnXĮ%WG"2TyE",w enXS&YjEE1U`煪"iW[5T +JR_bl-Ih1xSP "Nvz}6QPBUע&[Cis̕71_u9̪,-a/m]{KY9]n!vĉw%fL{ ' ` T Ŏb|29ƕXrU|SUHrqlK7ےj }uʣ̩'~_4Vtr,WJ@ktbk`jaVÌdt [>ַ$qD_V.i>F3BCcҀUd)q4'y|$:Ļ,7S-/}d+X[r K~ݣrT;ns9@ 7 gʛhZMMel8&T"]u!L:خ+lLj5nV ͌ެUi1;_V4qIgZ~7qfDn{񰣭(+dʶm ә,CWff:0s+^&lgHS<ês?#Si &;9.8ZqI36;iZkfIWg}Q}wq\~̽Qs޼`-su!&ٍaI}7ꢫ]|H9ֳڽ$W,#=aUv@_k_.0_do~G+\n{f}Vpepx\p}VUFN+yu8$:Ji'ryQ+V{/]qmu8*Fu{s6|Q|u|QUtUo`.crc'}lV>7u^4Vfy!4i\ma~%ve7Jv6hvh\oWKtuEUg(f XxPUxgenb6;yGfiLNHy`O#|-xrRX05H{k!s9#;HCZ: P&BwsiG$|M']bmRe[n^[7~[v6-j(AS7Towg/0K{RxOnj}~XnU 5814lȈ&y%-u:LtZq'`>1r+hzȊ j-b&?&wA#CE=)($lPxohBWm79X4e8&s卄8@'aH渀pggƎB?*8}ȍW Ik-ZyXyQh ix9pq,rNy-ē%aYؒx^'[s847w.U]CW1kԋN9a;Ȉu!dƅɔᗑHdS8a0_B&$2}wVjəUhEpephp(yx䷔h.?D=NW7YC37)bt3=UrM}Wd1?i4-6yW:9Z93HoT}b.m}#څW8W5A@ɕkq]҉c٠e0AikyT٣8ixSwtyLٞa.c>(.9JLQ:"aLؓ9i)p 2(e*2 *Hp6od{zJJCC BR}IJdg^Ý: x(-Xyȴ}]zpcZਕikRiu9 \f|zyK'MIB6 䊜:؈, qv$Z&'N*X8ŪD[jY~RO.*oҪAZ]iUJpƤ{I:tƬwXqYgպ^^JV쩭ɭ:OPTs2*ʩ zݗ* *gYn:>2JG!j"Uɛ'["q$K;Jk-k*5,E7YyD}T[8=/q Դٚa٤8H:M_ysvʼ$y2JQ k m04(spjsh|~' jz'9 ,+mG򹪒7:' vkr@ʜ1K^IYj~ںS*vjkYǥK{_ y+yd+*`Kq>2PeOHԋPc0Er*{gz6zgpx{{8PTK̸]Գx. c81;ZzȤo'loܿT(Ƕ5„_{P P7*gfz jh`kR/PxMO, ǚw X,Z|YѾ6 E)6Z#*=Ǜlt1`̳R\`(K5{/f\ysX\)™l{'l,x@^/Okۭ(DV>ĝ/|LhU0pƼ UѧQ̾ƒz̡b-ڟlzwPb}q•x8v"}`N ʴ œ ;  }x=]׿G1Hè`Ѭ |0&óL,,][`ĎX5rfBS̳LBYҜW^1sSX=ŦT\̢ 6ֱ|LSeLϱjhqϷvv<<*"?ݰ\%,΍<Х+;m1ѮF6Z+=4(Ħ˨b~U"mL2 8h ԹM&̽MQ{Kfk  ɵMQtA]=mpݖsenԛȝi: }ג؉PFHMv7gvݏM!>Q~c"D< ڬ;y½;$Ͷ*mC)E!)=h,5M+sDou|K 8:gK߽RQ%IYN+þHٟ~], R}:.uN'z.ê!\|2hLl C/@eZ-o[֞wGԩy;~ 6R,:R6,RL Lvz[M%Zfc.'5iPW!ћr-JUYjNyїò*zt{M,"5b^SkMؼ )@HW5:СhO/(O*oHn>.R0345V -v폶?fpY5kLМ$-N@/tU@3~̀VNn.ΦqO_8=~6-םP 6 & ÙմeOPKHV ߄3݀EJ xvBPņ8>2'ÅXу0rVsHRTng,o$#nnbTJm!jOt`@ {+(s;m]u.]xT3&vHPUlG92We;iq52rtv ]QJZ3/fهDDu(L.5G;&}QyqafW-$& c*V>N"qeH_rSIIlsem[:FLYgNϕBg| \6P"$u&iNHhO@Qj%g+6!j.yAKZKi@TzdM'Y2CX#JBuZ(11=(r4\Tm\wvu W'ˣ ZзAb[W/ }+'YnHO]1Z"Õ#^ cvENU X\FW6z*wEȜK 5*bpa *=chYڛzU Jiܿ rRHΎ^n A˪)z9B}RCC&ݤjN؃S99kzt"oٵGQ;7g04YyVvΥ0R6XJvq,E)ؼ>y4łs٧B|0ZYGг4m WƳ"{`F 5_UP)٣CTKglrdfJJ̌,63*BQ]_FFJ] &4z>{jרD~u~GM9k&zLTzў_Fօk=jW;кPdhd yvf!u$ekRN6ͺp6]9g^I6ϦY1 B_V'XJn[(ݒ,OfY[0w$4N8sL ,ϒT]?uZ4];x:]_py4%MgBMH`̘֤9^}s!%En~D9cV{'J_=t_{^z~u.t\Ohy]ZǒhZî}G^zwkue~W\guƦ\_eodf3xxlv 4p6Ur HLp5s^v@Gwhhe nL'V$rEpq{5SQăja|f$h\B|:Gt5?' amXJp&h'FOk@*HuZo%#o:5l^;(FcZ|kGvgaG T G@RegwhUxxr 8oXoX67FHofCEyXph9^gg]@RԂL5rykGWgzWVvv3rdP|qȄmM\,~DDtfFP-X]hX(HYspHl/f{%oc` 3IC{"Fqm 'H|M8~(e6b텈] HxoT\?%W?;߅pJX^5% iv7\U]8 w7%g(F7ij`6WXXs0-i'XtX`l;gluXyfsPqDm%AׇgiSjgNx9x(3,9 n(>⒪fBd7{ FRXU:<>Y[+'z0Qcu qLɸxBrCurORɉDjmU ֨aZH1aj!X}jxiXĎ2E8tBvic)~$@Ƈ6䇆y>]ILAł وt$k`ٗ ]YyB Q)(zU&euYٮp{r9I v9axjx-%Z)=JYb/XP믇~[˜=yvɅt 9"K$ڇq3K *Y=U)ڻ+ 仫%k "rkm'ˤWpI,Z:bp|6h Sj Wk9c9Ҧãt[Ns!lѷ--l= 2:̯yx'̘zH{{},œRS7G@ SK~`$ʛ{/4@,9ݽ+mM}b i]ЯNom!,#\tǨ v Ag0\ؕUz ا=,d jEݒ.Aٞܶt:]V\Qq<Ï, wXfx ۼMܰp &F7ݘټܛܹ9Ҩ\q]?DǝE3vX} Ѳ;|2e-ҡmvy-O׋Mf\ K/ . 0ُϛ z]ܹ)SM,: fR7-:1>۪Z}̻S^$>>XG~bKRlʙ׭թȃZ~ACbe˾m\s]u+&p%".k|i؊ ꩮ0SMLGzލnnLljƘN l'Np#v;*Á .9@MҶ/^̌& +k|s.o*.D F i.·M^鞌'#(.8]PBL8.̳;/>C;VY> ݐOW9X㒭JL`ݮ\qΦ>0 CeOO];Αℽz^ٌ^>RseLi1UXfxYAq.#0iB}Q[ ]'1s|A4nqTBo Xt6pVA`# C1ZB:~=E ؂M<"0$m!H +-sKԔ'R-sI&RBruL]X9;KD^ G_EϦM<b**YdDF'D OɿUs3N"E[[(lFq iA˥^Z]Uzdr{Y!V R1 ߦ꼽t qF4E\|4 -8ͦ}#@x!AFMqGаSH\N -p LyQz RGReB vDXqu2fhk1XLGC:`;a5N} N!HqHIYI+f1be՗&!HV@7qZfE5- Br_Y!Y%05FLo"B¹L6JU52יCw]ee4y"!|qjPوsRkB60;bLjx  ' 퐨,-ca16Qjb!u4ylGRhOM&1>Сu[YLr.b% Z>­ca`+i%ٸ)ʙʶȁCEZ՟fi,`*|Î i~epIq-:7NcZj&-NVcSJcZE6=JX~g7 51_'><10)Ϸ…d9{]#RYXg^̺x2ݷ ]x=zEczl(Ҍ&IxJ'2a^\B1J&;&$sFI|׵ͽ'] #ku9-KfkhT爫n}f&M9%URMJm\SV=O6F,~Ybr$o<ۀĖ3d+Z{ah&\jǹs ) )W.x *r[4B Q6LqӻiKZ<2 +$QǺؼhL{276esbTy@i&h:^}QicG6BRS#dxD*9'X+;造`*&Rb"Zj㑙TBc !'@V5Ɲ'xpڑrX95sP 5!t2/KyDHERv_jGxia$I=rh#Fe@fLe: M7xޚb&>noңhFєi[#iFVId:٨J,'=cSh k63|-2cmRvyL_LX\0yE*FIr %@w×OLqEiD tHJaTf sUX;%2^i?kC,(?Q$CӸВlDEUƎ!g( ˚eJ*dMOjLֵ,UBjY1/$$ɖ:K݊`*O[J-^]lKK{)&N;k,ZH@qagCʥev+O3 Z~졝T{"l>c5?~6N̒)فU( %s4[mhw|oMJ whA.\R~Ľl?0gh]+DU0ëo蕉z\YUXO|7{~1c h+6^n2Л[T^x^}1]z@SsEڕh$o`,Z@cAKtYExNm5☂O|s7HD/TH*;{utc*8V6-ݭ2[̛j_fpPr`v\)?.4W(p">]Pu 6{f9UJӦzh8<@/MN cW Iڼe`52Nڴ={h {,=u;}C nqœqMMn볩`طzEw HJ{m[ q疐oF^#\2t[tq;-j7<^/Tv%~ˉF0_C]۟s4?~cn0-?Vlhb %cf$뷍TmC; hH>!^ʃz;GUO-ӯ WO[{4FRq2jfotThFLT6xgWpphpybxJ_Bf%zhhq];9glW}sii(igrAagay5a^ Zk:Ci(ebFr^c3Z 5lUgSSV-͖~h~ׂ~7vIv^%%%swp%DedtOw!s` ٥wX!g13jWFU=K c ׁ/z_vƂzϔ`$ivic:烢Fo6W7~bȄ\QdIPxc`Y+vr8zqVl7ZP`b&hm3m?_vSJRs脏lnV и|uncwow|Xf/zarRx$xs'Ʋ 1PQ(%Ŋт&}ڨG6h8THD/HgpGs X" 65X'w`3t4'J'YQelBdlц`~tH3vH"(Xxwga7o :m6FEr~B)+ƄfF#%''L+hfq/Y58r\XQIjAij4^ǘ/(P|yoH|Y^IYՍ1Q )XlV}2FsZ'V혐~piv7czw%Q)4Xw&鈞8|G_~ ])rV^ho9qyhv`I4ȜdD{xzɒ9tMz{p,Ѓ{@)B)DY_y{t&&u_ mTitu0.eȝ'ڟ'HZ@VuwX/ G Kdm`Է)~HxGz̕ $9T $hJiDghƩyZye_$$$(ڒآ`钕{ 907rAX jgiXMI=O bh'j}dН+a/7gbI3%i ]ҦINlR9ew :V]) i^TF8C ZɩC_ޙOz[YѪ|}OuG'{D٣鉗B*|HIFZJLZXZ:U =WSwlLJ(W f:J%^s*xꗆX[֬ZaĆJvx֨xĘy*ڙ> ?C4kV*qZ$(#qDPZ$B17,8bCM5”iKkK*xY@qPz%\X2Tk7T`ZaKL7yd2|LJw:Iy pr;گl XdǷgᷦjC9c*p.7Fb{xKS˻;Z!MڳdD 0/k7*ak'DYe ȸ%PnԬYwǭVj̋j}Rқ^VVCW-轷!f+>ReuH}t ڻ3K{ko ; 먵{}`eMUBb|#z? X68: jyX=z/71\ȽKxHL LlF\n@+pRGJc+vד [gj!ʧAsz l[YmʖT n"DŽ׿ (;gj;K%x/WsĔ%KH)+Zks*ki.q41,H5Ƈ]E͌6< DE&|̑~RĂ(ߐ"w tOMͦ_| sӶ;cF ]Kr]\jLs|[[lt\-$I׆]|-ȡ =]k~!`ݫ$<و\&a]L |hꄨ.mյ5;&zAk}3Amٍd]*loWX 'WJ H_#ѭ%Nxj?Z|:y+΀Ρ7׋}נ-. M nqB-i&H2jjǖ ʌ(W!]Xy^4OIF$%&~Ӭ4-lMkڠ4Υ58~ŝP\T>ޜEjg7 #=)F-%gF_޷] rv. q>$?v`@ؚ*~o"Yʵo*_OwSDNq]^n^u=KfZ o~uښ +6}^N:GD$jl>{=D?.ؖuě`lއ0 '.벾Ũ<~E./0_oP6'P5NN{&OaW^Mx~ܹJ {Mژ/. ^a ' ],  ^&W 6 ,)y_jy嬟(`SS0cAi] ԔeBPE I)ԫH0]˖:Z>p!63552dÍUҪZ7DH]>r|MV0X%@kYm>)_/fdhpW xR%5!`h1>nccH6\;!PPUh3aBV4n-sk3^0hˮ%J2R97(?&{F\(c'"@Fy iٰ+rBVF PLLGChu1bخuĠK ác@5j+M*E 2G%OhLT_AH*RJZn:J@ADiA6T7_L=AgQ!iRJR,5̩7TB'P|=0gQkRBwdi9|p(qhr[Jy:O˴u{I)zQT~#vHbUǨ\pR5$Rj;5]c6NϩdZ@5Q6CI(5eWכ7dEDFIC]XH[OZ~y vY3 -vEy]P'{8.4R~OWФ  %1u*iBa ZXr#kcaIPYƩ'~ XpWaڨq,w)#qKpÕ0 `h!&ƜB *ʝ5V}2on(׻|Oq2f洓Nk"2 =#{#ϫ"SC1-1Jf'~H!wF|֠B@H)9Z]*fM_e:.T!x"YXkcCUK!GۘVHμ0~qKZ$T9?)tinz%˗"_7~|q]7{F͞<@g=e]<4ӺGM6khB|5щʀ 1LDCm3hz|et6mlB Y }IV8KqԃVBn1[Vz%J*G鮍FH>fS_Gg>l::T,67ړF'/IYT;(q:\cX6ylA!.BW ت^E7#.d$FIJoj xYCȐ?D¾DNEmH-1r1"njHe;GNԵĠE~ݶ23-K ꙿѯnW;F"dž? )$=D鍝?nE.iEiaQ%$>Yår!z(rL <%˯e I])J\>ևlY)OgW}:m4vxp푘ݵՎAFKDluPXR frF\>&x 45o74 Eb'yyu$|PN4B1Eg#U\Lv-7_+Fr_E>'{.erF5F0|J,8pPusĐs+E[stXJ$bjb}Mw=:~lYjj =9xj#cjHAvnWׇeH~|#ImXXXheF n G8`e 6z7W2]p&Ey‚yy7f'_kdq6X}[8@z=(SVEC {VHrLV,NT(9{ wa|ƈ5V@kFH}i J#]Vu%@E;!ywWqaw 5q hvfw=(}15 8qL8f&KPd4޴ Wst6 BSf䀋F(^K?LDGA8(L:Nm>h8laSI8K(|vu20yWVc9ܖw"k_\8&};k1qU0}ll"`;SwFe v HTaqI>Vn@)%ىBx GЊ;orh+9iyty>i:|HiPSKL&]h2U}Uz$\IKՉ,>aqd4f59Ȗ .<}<7x9}{sLGy6fA@\3jj)7wrF7Vy1lفl6 Kkey.iɗ8Gi/L9N;}ȃTIW)A>)ōIQH:jrWֹH$ 4_*r$|(x XDؠ S:cv:١ka im+IXi2t 1=ڕ(xVQr.y֛iWv9)}yV~)uД֩zIh igx6%Wnzƕ^=jKn D؜UX'@rɢYx}ȏb*_!e8;`Zsw ')e"A0jZBPr ۘs86 x")&)*) :\Eo2֬Izgŷ25RpQ$Iiڢ ) QHSh*x[٦{Ƥ Q)`8-DŽ` <ɷ'* "˪X,U&{t *!v栆9  zJ+JF:+@v~y6\b< t#{I* 5>N:SYIfSzf̊uo^NEYge^1ܚ (⧶vs[edCzolzF(Q4ᯄwZc{]{ A*<Ba;0S+Z駰 ET ,KEs8lٻR:{Ӹ`sj{}1G <Яm hg$4VZ _pN?xԓs8ƅ9[sL }Ƿrv~SW § 9;!j{EG<8f/6Z2A<53Dm7,1|R!;B:lJ4r/^ۼW| \,yAhSG]bZ{y"yf7;!*`HQDĊ⮅N$NiE xtCK +حaK۟HW9GE-/[tP (|~$Gf*?''[=ѨܴC|)͗LhӪ˜PLFc `IK9YLQ JHKX i| K@Y.rM,Ӷ=9YӉ*K4رv1ܛG̉4չČm=ϵV%MSk=ըxM~u~߃ϐԊ"@}ߔ]1 M]a@ѧ-y'^F jB_~eK9Y68> }P˷AG0^I *Z<.;R~.)T`0Þ\1^ ~$/$-; Lw/ǹPSӌ/`%F h)at }]%$>&}"?'#@;+4/9I.H& [c_ۻRm۫PbXSվKza_bo[Ƿ%pۄUt-v : 豣Ծ:֏3eొ¨0]2`u4'$sN RI€B&ϱ)P2(NV"e1MhTx5nyes+Yu&Հ5$$b5Qi8fh BIE9 $ 2%jiSx1#ZI¢$K:xPl\l%#8Bע:Ւձвvk(LaʠR>6`1p?:htsG" BG2|9(Q*g-vi(Q?5I$aIᣧK׸۲1$XRylf`=`)999D6fE!7LQY̬"@Z*̚ ѐI[8tnBɸ'R#SԯDqA 0,֘2ڷLu MۏDt"ribkjWqnl)]mhf(@չ~ ijMILGHhp*_:1gůmn{chReuI)e5t/Q4 N* X}D1bAwBҧ!wa7^DU]VmU;^wPBQ__+F|/$_\QW/ʸaqɸXN Xhb@!5`(`IF%F5eYh@aolc676cr)@KȌISv[\ +&h b:`#)3:$w$Pl ]ICեkF/&C KHJf :,XגSJET!gCONP@Q Y6T)PUұϦ I}E"yKD@rbj &pR˗5nB؛ɴrf!{e\vpǁZ䙜O+Vܴg\ndq:i%;[i0ϝ L+GuEc*Ugl*3A3o9|(NG}+R6ଌsP0] nS"E=-St?Z՞BK g-l^z(1t6v'Qk^Ϭ=udLQʍ\wѽ֊Uo:A(g[b5s:;)p@j' ]<$Q\>ǀR)o0 (K & W<`EmxbjŰ.o;°2yBREؾR0#pA9mrQ3\mBS2Ru  N\~yJZmBXLedrC|E6EΦcea BޫʾGh9jj #&P'Qh ]w $ K[Ӹ6,a7:ABfOB d`j5RP;D<۾Ӏm&Kr!`ȹk 3Ҵ%CXĸי r֑I"sk`:TDsiXx/2Bv`KLȍ5(N2š;D(L,I{-DuZæz< &=?X^hSetuGnJ7nq6+0wtngA`{nFiEvug($ER2olFyqc>f9 {~1g;6 ?G150KfE9w&z-Izrf"s V L7`9ujBRPai:;?+ǗN  ;2s+זVLh 5=iXS#,Ytpw3.)BiH?wTۨ4$$rMe3Pr@dX sp9hzÞq՟XvchZ* 궘8Dgt8ukԘV,Gl0flI\]JYZTVa )pAjA[ٰO{X!f/YTi46EJGȒ^"m{bpڊGsh5 *~]H /{{tt');9+-[z 1z8[ z1Xe{Z;(3–.O7.{MD٫Koۛ<2;4ιvJ%xgK\:d8cb={ex" fxw p䦛JgxRc9J K E-+{>0ɄU+j+˼v[ JPG0f0;2 4?[ LmK"}T!Nd p1~( !ZHJ ˿* c64܊hiۥCr;,T8Dyy%Bћ}(PMG:PɶvԜKb, Xۿy@jawy)fksȺ3 S(UB]gJI0#ڻȱI B &,1Bw;HѾRլء нe@?Uw|p&94 lP̿SƄLCWVȂ |l|*F¸gɜX= "%$,,ߧȨQˡ5ۺ)TW k><ǜwH| 2Mʕ^-EԼ¤#~([sp/*Wzr b<]L]ׇ\lLLΏu\w듖}MB ̫ѾƛXuQ}uvĤ.L62yfŜpV2}LoڇbӬ;uW˭|MZк48yƯ;i˯L%(-Mm>K*X@йɬޭ]M]lϰҵ+9\#",*,."f,#c#(:A[9gWjWv AV*/UVyd(\߼Yi"߲hufn-\:ۼǓטMs}39E=n=owʞ"J{JXk ٚM!]bvB-v=eڏ^0%+0ܴlݓ۱Mcԅ: P'VDDVң<ڡkmN̷ lû^g}Rp޷ОnKmNJ ]>Ta d3N{Mooy. B &xOQnL'ӤNEd7͘RfN2'eEd:Q{Hn)[M&],n[ V@;8. S*6&v-xKz>}RȀ_I _?9PW?{#ɓpqcՍʮm gp4 ON kͨם 2ga AuQSj~lT*Ҳx3'MS`5ˀ"5,=6T^_m/MvX0-ԙL1C!P ̂SXk%e*qmfel;)FPL1sXI f\N\$.q-1(g#obunjZ]cnePOikJrYo&-+Z` 3ڟVVِɉzk:UO(N!d*PC+&o$*3Dp(Cۢ"8Go:[Ȓސ@#N*p(LkY !iS\f$ajD"i)cycjT0<(/\'Yut`'>Ńel깚Fy L,2]}[UDznYyg=hE ?Z.2:k^EEd n6{IxD5ۗxDwyƭYrVF*tzGLw%4~8.\_"DDd<Xhv 442hec Qq =U"u4 }=I>‰c?(P% E}F˄E jD2aVWj1Bxg~cXBbyB+Mm0Xf5 ל+m@`i asyIM>RG/.+tWwcPɷ^_ր6J^:nE`4DIT9Q:UNz0lz_ERJa0i榊y_{ec\sUEbK>Fi_YpZQf_hYҶߎGpNщ Ŀ9倥TxErxryˆ^A&Fc$}K*Ƥ׎j|+kոFvZ[FQ,;mFr "EC#pU.T/̖ʷ/)`)HB[,0^ɱOR^hkJ shBC:,Qgv~[ÜT̕ hU6sͺew8G:u #i 8Ѹ(ծH]M@Dk zg'a[5QJ*28sx6.[!ķ".Սi:P-0@q %9@ F/5ЭOLPG o}$oi+LnA|xP', |5K*^j%m3\#OuU~eәZTahȼ2J0nc^zo cEw 8蜜Un:Q>oe`ԁ`E#ܭ( ̓:ȸեAaM2W}YQˠon6T!!s.a峓R|mS]ׇ{saH6֍ G"TmI;Tmx{ȸuǹ{Cu\w?w޷Pźځ@~]Ю'K;| < O8W5QEP,%Qq5beI5rRrbFt6corswJ5'S>FSJƀ7\#z#$bH97u1tK%u]C `u!f [g}VM.fۧ1frIkGviN0t2_݅o<bWU3nMwE9GhhWP t45yHv"'yjr&'|Cj-ȁ206zrlVsqa${F87K[gN\Fg@/NJɧe_ХmϧggD{%^\wLOM%@NvDʼnYl2yЏ˧WXmK @jU8cfghF{^wn}H5{i_Ɇ~=dW\ۘ-QCŘ`w[`b)PuȎi(5"FitR8(R gd2fWc3w I7P8XAV8)Fّ yeRG&0|- /~)3Y}WgL89 k}fh79qը_؋a FFBDf=JruKH1gS y[ [ 5n73Ve!9/gQYHa-pԕe)8Gi~d#ztl9Sиz&^':v<r^}̘y u*$-vGHfاʼnhSO 4 HJ>H*8 %?v3 .>oHa?*!r$eph"&XH :ұXx80ɇgɤx9UH8?Zz'EoX*M mjRqJIB;a&FO5T]:Fb&7}zjVqMr8Щ_$-bw$yߙ:jeznUaԢƬ3|2hojA:S Ii zz 4x5TPFZ_mvRհbK6m}{c5ుP CP=@EʻوSۀ}lAlS9 WJHv@]cɋ vjdZ!HJtyq,@ KjH8Tˮu~RH˽g%i }۱˿wpDH; is6*iwRи!D)($|չu"M;8z:܊^Ӻ\$EZ  /L8 KĈp}K> t$%r@ Ckݻ.*;P\tVߔ%]Ǜ{ԶbT~uam!dǐA@(6+b \T,oY L[r,E{)<ILK[*ζΒECzňRţ*@lߕݧZٺ r[kqAߞ|9d;ڠ|\ [Co3M{`qPAՖ#Qa+Y= ][M'e j=٬0Dq b Q)%ײ=}YvR^|Z6tClz7`ؖ,zd6.DStl{ѯE Kⴍ)⣤QjX"JEyUK װΔ!] ě.ӲY1n,$}\^<+](Gm)~qX< 㥮Hݵ Wܩ,Be^]}>֥kLni߽v ҀLW^=MX՞.l~ߎ|-^eu.}|p~>"%'x{EێI_ÔN{*]V՘L8۴a#$ 9?߹H*<=13ɎDSИXܪMJ-F߃wj^K/>>RRRbbbҎⲲ666NNN &&&ⶶVVV溺jjj...־***^^^:::ZZZ^ZZnnnVRR¾¾b^b򺺾! ,vv;#"c%%c";“=-,W,FF644FB!=ފ;H,F6H;[W6ȱAU2m<#=pҧSX0a\G#@2 Iv4lЛY3%dH'(/DH#B.Z :6լ)C+&8p5d3ׄlЄғP5fj Ӏ#\8pb뿖Q'vj6aÀФ n.Yj݋ՁЗ73BEYstI4HKP'x A\ɮ[jv턲\{4-\\{e8f֪E+>_XM(h6NJCZ)]Ș٧srȕ~Un\aAZV5jM\<)(qQטTqĀMw\iǕSy` K:XIQPQ aMd`v'VLV}iRKGZ)wcCPS^i4 E@Zibi <봷sKLJ(!#C[qт ? SWf(e=[uiBKE#yԘf&0x zhfV~i`:QnXqtP 'Ml«X0iuve5mvYm$Bӫbh_I V# iV.fn*Y/WX௖f3Ait Gp u{Eש\1 ';}3͏pA&^K{" ePBb8.3`F %73]ގX{7yѯwGv_5g}0 ;ߵmSHl"ֳrD~V Lĕt0,W7;ٮ=/ e+Cc 2';n^vE+` {%jjIH4$冿ŪfH2KD44k) Er6İYk̰ L0gf/q)@ )/$(Ӑ#8A]ϓܙw݈M@b1\Q4 zQL~.8 RP,!L.wJ!, Cj;P<@zc$iJV4hɂ)0xY d|^I7$Z`vQ P),a A a ]8vqߘ + G-'{\1= Q4)x  Ilb(.Żi5#/H3d& 59Y`?9j]Va'IخwΑÄd~xA l<6&5 {Q) 'r^ɥP`. 8}l`IXw6DFv+!J 5+yM4A d+ 9x<'Jp*l)yjbw q4#l(@=i@.+c\Gr S(Bw'0H{Idn+b91Nv4`@ VUkpg+Aw/@mT`y]HB%m ]:X|giV>G̗a(t0'lW(@);i& >SMD 5_ C:t ENS{>*FJ͹A vija;ҀG5(8%YDjaȐ0PЛ UOҒ+[WL(;qt!4y AxAywIIIn IMʼn<[wrYYmI{YR<>Vd2 j+U:?r>O@$\?Q>/10BuYM xY`]D9J "TH@M[]֒PCue/KJ/~=\+Rtrx pcRwG  - *J@WzˀuYWk/W`17I]RV.!.PaUNK@LD'p`I1@ `14/bYSb}#6q }x%;vxgUL`'vtXWI'.X|F;,s}8w}8p}wSw0S])a'ace1s3@H1`~pw's 0n{5'_ax&ck5}|$`Q.]f\4x6OKU)SII w1p`# s y)0-BϒkQ/dT.Wo"p%v2@18v vŷ:53 +ETB|1zg}Z!}chMዓB`AQW!1Cq.KX[X^ژp$0F"@`4nW 0w(5- CeqYEP fII@@8" 0;1c8p)4blo7sua/vaږp&xG:DE 4`>|3-,ؔ\J5;B,6;pG6iO5'ЇvuesJhw&D#aC}]C N᏷TKaԍȐ1V2"2S3 H '}I%@)924Fm;yvPO&x`c 6IyS=x17I8CKDrJ:AkrdB5 z 3nޡ3D-UZ/V`eͪ˗#4ҩVVF$'pRxmwDFl 0'@ !;eKժwt鴥))8?&}هeAg'Ƿ Ph3e-s"Hk[-R"@īc=Qz/WA(L@Ipay륐_ih-'Bn&T8_:"cP«\)1G} ' ̻&+,5G@DSLG I]~ZP$v>KXu.^ :p(ƣ= F_ @zR$_ߊG.g^;v{v؍MU (4$I?NקԷ.tX 0mROc_㚁ҪI}6`@PUBXWkp.tӢ"F=AѼ6 *0:x \z)}(n"qY آkV䮻`f(.CDptAHCr4019!p%9Q xD8Aq"*qs5@ wWK4c9AVJi2)qyE))qedlL X^i˙Rx҄RA6hd( 4OtꂚuNQ KpgU=׉wg 6 y ̐h^JN+iIG:#M"C†Kz Ca -]@ RAQUV͓/Gice襷^l̕҉SԶ9.0CN$Đ 'B bD*`ВdBUY#GWe}/0HA4pqIkr@=gN_~#<cjd Y'O>9B MI`. )E Y8%) [hצ6sjH#1''.,$1EUQpA LN(<=l)i1XY 1|*mZҚP{j 3:mK8I/aUJS'%OBl K/pBc-R0Qg4mᦪ&8H&K0Ⓩ%npT Ȓ2 i.P/ `Nq 3K,akkYb L>* */OJ0HВڙ2.:gM{S5xk1R@nBb5˧3ي̺l8lw= [jɟ&566= /" ヲX <޲AbCI`@:5I 1p 6@.P} w}?VӬηL COĐl30Ω֯ZfjpeD~]{- ^^{q>p%d%8&^UpVP70hĦV RI*&s* `pdaB c@*Xe`f| XqG4S1R~c`t X h ؀Cb~QxfMӁ)9s)ijk;uligo-0.3.orig/gifs/end.gif0100644000000000000000000001037007723003524014321 0ustar rootrootGIF89a(2..:6bb&^&₢ڞ66ξ޺66־*&޾&&RN66ޖzvڪNN&&Άrr ҲֲJJ**nn֎ގ....΢66ޮ֎⎢ޞVV>>&&jfꆶ¶ֶ>>Ң~~njzzުڶb^BB..rn^^2.fb~~22"66撺޶2.ںƦ⢪JFZZ2.&&jjޒvvڲ־޾22ڪޢRRNJ*&nj66Ʈ^^B>ֺƮުFFrrޞZVꂮ⮖Ҋff޲➎nrbf222.־֒排⒂~ffꎢ26ΦڢvvnnzzJJޮΊꊺ""ڮަ**bb22NN6:::ںʚޚ^bZZjj~&*¢ޢrr斶޶ڢRR޺ھޖvz**BB!Created with The GIMP,( ؁  Ő!"D8"J$@3,RdG (HHED,c47s@AhQ yrZiRC;*ārF^=rd)wz(mڒm=CQ]%Th_=}.fho0/h 4Jm Ulُ 5wpm@u k$qm 8$3s2Nn$6h|n`n"tJ&zS]L 3E&(Y<)_e+⸋{gP@_%xbnqYCIY7`a tH}WQR(1~#Q4PFwYc9b=ZQJQǕI2wc{eeᐒGa-b PA ,R 4@P vI#~7cuv"u@l&e\*RD$!p?\X^!vA4P(nPITQ(N+BK#P:k.|y&iBLGځde.B5 ,PCh`ژ\gM?H XC:$P,2:x6SHiԩUPxE4f# 4Z,R5:_)A")UXE_ԡEs7w Ӏ>q{l<V&J/IE-gG H6<.Ć]5U "AAL0s_ G1bW9bhkB?d_M3 lFv&T3Gdpo8)!R J.db ;]0e64#F@,`N Ca]:Z3Ppn4c۱u "ѩ<ȒEPF$jxD6FSmCݸ qvJBΘI0+vHc@/P|)(g')2`55/6GE 8Fr5E%'zLHRbܬT"QJ4ЩklrSH̦6z `E0(BJtx)L!hAs `6#@LU-jA8p<)Ph@hHijr,P!BQEdψ"YV+4@j #ЁPQ-B*X8r|p7-[ApX p!8XQZYD ťa(M  r2JG+F5 UТw0 zY("a SIEQP! у5f'bPi)J9Hqr~ɘhO7"e鞦X&H*ֱ/; 1,IVfN( ƐAXLTJtOv6T وpF#"DCdTB P&Vh a[L l} `l-zp(`=U l8"8ϟ,*^\U\3 U5; "R&>ː7$q îav[X(b /4  P` W"PDOO`bxhTֲY.Tu@:@(rX\iXE)/<+( ;  @=m@{[ذ0.@N4杲q9Lf'J;Ip A.R}ChYwH:q*bn CX+\ [p,T[TEӨaxR%~Fd5ZǭtB( d Ȁz _ [Tp#'D٥B-pf TULUc"mtŌj @;%0d ~~g |2k8M?li)N*n(G<`žrc'hH,+]EgJd p;g0!D^whzy>]l*,>Y06Q0`X *cDl/'a4 ;0 29@-o3ClD*qQxCls "2u[Mn6rNB֤r'Ro#IvỳCwUyك,v^Y_/"C,@ !wl#=ְZ[,"`r5 *jynT/LϪ;\%7%3~X3]@C` Q X;#ûH2}+IyD삇,Nvw64IK](3̺wD#w0 B|~<`\֌f "PpWO8TEz"%&Q*ݧtU#mK7m p vVa3 =gG|&vpx&`'7 ӷTv}U$Ct x}+!9w8 Dp'0@&`y7VdTl)@UEᵀEO<Hb*F2#7}S<Ҡ F`]k&PheHk5\@II v,1YVpspe< p"f$~K\%5, S p2P;k\ pfpDHV=0 f0X`=[[ԸD@ d!zbYD$֡ 1?N2#z A`Z4 @ڠ#PF0Xp ְR-?;@Y-)Q-@VJd4pPYPS^S1 8ӲOӒO]dpJ!w]T/zq*I'/2MIۅҀ  P T ϐ B C0 zR R rTY9R 0mJE7QT,J~ɇO2f'X#u J)VtҐ HZ@ 6CAcCI L 0~vp c y :n]@=,^q7c%%%n,CmI! Lry ~` )P07*0X4"0@:" CqPY1;ElTҧ A)%E@1sr#ń.!~()F#T>! PP ʁ=ܳ%:i.|ҧEB I),0 BtWp6yWA'LjT(7JҀlB;P{h.1)VB(8alwTV @12.y2ʬmʱ'c,+c$9s;AK! "@Ѐr'&au]bm1?#`NI@؎F5z  {;uligo-0.3.orig/gifs/hint.gif0100644000000000000000000000466507723003524014527 0ustar rootrootGIF89a<(***RRRjjjvvrzzvBB>ʞ~""":::¾ֲ662ffb⾾..*JJF rrrVVV"FFB^^^22.&&"Үښ¾>>>~~~ƾZZV’Ζ榦zvv2..⦢NNN>::vrvB>>vvvFFF222b^^zzzBBB...&&&666fffZZZ!Created with The GIMP,<(袠(cCf#]=aTM2@0 J(D<%=TgqPL+\@\$$0F \<ǻſ|0=d[+l)|\x d`V| \`C$Ã@egDaqPH-<@d!u'<4\+4[B80"DɪA@A \@Y4xqGOX2XW{\r-%$ JXqS :C 2>@ N8*`c}g̓PPdV<v@y!WX`]!4!:|PߩPB#Dn{qa@B @"$۱/\q1߅թoE7Sl €&;[E Z(оY@~[pCA ג?LXH(  -@v?hA W`Z QD8BB-a#j.X@ [=Nb$W@Ji0}K@ʯ 04đLqx |BXE' X E8e@~ͻ߿i"h(bP B 4 3ʪUɆABH>L a0B@ N )Hޜ?>'[.%KMEٓ&5H!a 8TY i| ifk# `*! BҖ a8LO2Mt°p@{"}M aQ `ԗM,#YdNѠ=V5i\&,7a C G!'@P85)AK4ZK. HBl _f@"q|OG҇ld9p_Q <  8.mb+qe;͊5HB l5 fp'}._)|~/ '}`XfQ $o 8kk .`&i%K^$U P*4(#ZmojpFWНA@;uligo-0.3.orig/gifs/left.gif0100644000000000000000000000415607723003524014512 0ustar rootrootGIF89a((RRRzzz¾...^^^ҊfffJJJjjj222⦦ >>>nnn"""ނ~rrr򎒒VVV&&&662ڢ~~zFFFҲvvvbbb:::ʾNNJZZZ***BBBΚʺ֞~z~¾殮ޮΦ꒒ʺB>>fbfβnjn.**zz~"~~*&*::>nnrbbf^^bffj**.>>B~~~vvz޺jjnVVZ666梢NNNZZ^֚Ξ¾º!Created with The GIMP,((mDZR8ÆM 1PtEQԃ`R` BD >̏"7<*A`G'Ni00-R!F DMcǎDzB`\DJE`Dyp-|l(+h-긹FpOȥ @IpI"P)"UD=p@ySŨlSt-BI=>`à Ee])c )%-|"FՒ/TfL1fF1G9D 's *""\p]ji:T`b)aahZtPI'Q C^b}DW-{Gu 6Fq *d(Бrg##?x@z|Lr+/8pEBJN,y#ٶd ~ `L QDQ%? cI O(QI LrKn,gVT\"E QF1 BhI'(QCj`2| [| & M81V$\4ۉB(@ p@DJ_`R\qB(0h»j LDPy]rB; I,Bp@3B#>| 0 R Y ax@=pШ4?ȐAjP HB$1[Aj2]#5A$<@p Ll+22ih$"'  ; 0@#ljLihgRD7L!$\b)`4FZ ф md!LAt @" [$>@`A;аx, ,aD)HdaABЁ $N:;&}%D|Ȓ#@" p+X7a=An 04gA7la>0( tVH YnV; V(,0$LFtU$ [BE(B! Zp(HH` 9B%*@v `>Jh@D"7T"L da|(E)WPb]Mu*rHD` (JEA*Xź51h$ 2dŽY8_1 Մ3 %=SR."8,{˒1l\XZ-0; NLL*_MX؀ \?: r'u3TcܳZB驐4U{%;'g0Sfz`Ԃi+J\;uligo-0.3.orig/gifs/logo.gif0100644000000000000000000006740707723003524014530 0ustar rootrootGIF87a+*+kjivn]WWW,&obh5F uMLM8oZ/8 XVo>0zDDDyhtXPįyxxM,6)sǠt<<̨7|v1*R ۞d`vRK2"Bz̪ &ְovҷbU{.B.K=<_*lRGRD=к,?~jm20Q|iͶWXu@"_ж,H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjzׯ`~JY` ;ٷp X84hpUoac)A ( ;c)(l둢K.ۦpKt4& onQf&CSBdJrP@e"Ejg#Eĉ?rX$I)27l!b  ހb4фy*TiS$ HR|C;R4Wgh ׋#VP(*8cAXB9pH pd *`!-DXA(6䁽Ђ4a8Yc mHBNs D0 " #\9igbI 4f 4S,cA )sKpHB )@mG睠z+!8bN`qi((q|)H +fx@ ݜ&\aXb|azKXp2 ALH=P-{PD ʹ"x1 @Q&Y 0E-w$r*="OpH6+rY0o cV4A ~Xpl`-L\=`2/ +MP[B6]N84BF\Baph۔31U [CQͅ5/.DJM sz r#f( XCA`4vtumRդc'M 'B/sk0Y&΍{qJA;9&2 4ޞ~K6ׄ}[B̆x>,SO(x X\c3FaD(Aa;Ӈ>! [=(#^NVp` : |vȡ.79_M 1p2}`9Az,(4Z&(@3`@# }+NȮvÝ cą~  ^/AQ `*0 qS㾬@ P4x-6i XD^D (R7z! DP =聐aqK\N/R\.8D )Ȩ .+q^C!̑t|e,Y(W}ig`H(+ );qmg\ ;`!Rj2b ?q,0܋( wyp( iB)j OL?`iK 2\',<;@؇MKb 7`:H03/vY(h 2*Ms P2mTd|W&cэk| JԚr-@XrR[$ol1t+H; I2:ᯛZ]6Ύm0P-|[r61k@P9a#.>WTe̻PZv:P= )0}]lд q Pp琮xòW42º @ C0e˼* D w 7 j° 2;'[u8Tkq hQ Sp0`z3R )P)r u ,l2G@qE[ qpdy?N  cׁFh"`E P hR KȠ7`Y  7{A{ @@ ~prR4hbˢX 7p Gg˨#rk0&@~(:"u3"! \  0.b^KfXjJHPC rUWGwT77p@PE;T'Jp0 IzѨ2`]P =7`7 l&CR+h, c r0"  s=wpV6L<`.Eõ:mKMa`1|= `P@Йk,-ep_ +C9<ܻ?O|@@6`\<+,7`[UR{ @Ծ  0?!lmQ *ǔkܐw.&=U@g q m Cp<y?ͻ Q vd`nT0 1"B<| j7 K`~ wC+#|J#`Ձ ̉BLbhP> _n d~JP9s p[h蒚 ǒ\ psyr$N]0'팞3! Q `Pv9|1$p]PC [ @WSB{Z}S0M >t很^PPuQ\VG(Ƿ 0CJuet_` AˑbOx^ Qרlǀ\k\ |48  pA|s.$ي|( p @ %&qB`"" } >8JEY  5w`0?]t @BGM~(0 p057| !@#ذa p2dA/A rA GPARJRk\)!'VP+E$82kǂ[ f (#D \U8yV]~*א8e'LS %J0 @UXl)U+#A1G; XhVuA'bNdDB$w[bQ/(u/߯ԫb-H$t@1uS)L!J+!ʚ+g>R0(Q<,r}tfs\b4A >|`-Fr=n[f+ 0V/Z.(ʑ%@IV6&XYp fi#[R`$FUeL D 0́*ƍã+4Zj!@"^x!1<1gA_ f@ mJŀƔf "A@P9=KSnPbB SJbJ1a nB 8[ a%C` I@X8Lѕv X ˁIar`JRnZѣf jxī4 $!x>#'8DLLbU%1GO̟1!*D31NЃ2 H4'SKNߔJXFPqLSS4"ՓOhDAiSJ!첫BLov߈U_sE  zO:Uhb0q>ǁE#D}z<@`ĥZirťT2iP\.z`5Xhnvy]3Y\|9ϗ2m!?;!}LUPf1D #H.CsސZ PH-.?QBCk``FET6ʰ8(ADq^Hx`|'جn$5m ɔB !]ufN IKpQmD@Es\\hEL.pc/0 FxN DHjYT gAA5v@ho P`萝>@n(A4aA! A$`d9h7,x@bk\B V OBUdm}˒ H5~ K&Np |A!L1[ `۸.ff'OUd d'7 8E H)!7ʕls,'7!U@OZ"yAG'@<`-oyMps {O9cE70 (Te@=8 28 {8DF0DYT0?I -Ґ4fI;n0ȅ(UH` 5KW M,'آA Z0j!(.\@. S v]%zI TK+$ k L$“JAseC6.p_=X7$ix/ueWP5pH0=ȆN@-C, ;>2O0鮛@̢< r |06cb08P;8ғ!veȂTps%LA8K8A)e!(v5(&T`5;8'\ ?ncuпHXL(ZyHq&*b 4hNЂn@)Z`;6$zB-yf`"d ؃IA/_85%YƻsFx 5[BH/f 3,bC2Ȅs ХNe@Co0Ao@9v(ۦ `K# ]8yȀH5pDNi*3!O>z `7Ej;-;恣77(1C؞%A[$ I([deȃ~>f|3S%xD0LzzAyT(MjK0Pr -[0x)$T pjȐ  Hzޡz(J;Xn08QQ|%fDɕ@>HWq28J(E< @Á)0ʰ(2((2s;Kԃtvx T#'&I.Im Bvؔx(sUQ)4Ag=[yɤ48ћK)P!1!280\̭.X &@ h *#$ĭkWxӅ;Ct<3d{wsȄ2@N&`[E)脽S >ๅnОy#3K%@͑9N\$*t?T! =B3LT``@*8LS11ː[`vzeXVkXpKx.΄P0oІl~nlH2CD (`:n!t, Tՙ@uA".:C@k@4_Ѕf;ӯhr%rj`P<ý @n`nfHʀxҒڞ((؃?F 9}BEtOl(! %XR ~jXjXTg }pK `6j)Ak5G/OOHx 'M @YR p e@([h3@kp5YO[ftń X40a,ȁ,]jX$C]d [Ԃ.@\df<(?JK=K}V@݂n׮XN\,2̮Y%rn(EP3h X6C)HalՆ!%!(Pn;Kݭ]&?܆-] `Ƃ.UǺ4NՅ_Jh8_͓rƳ<0`X*eKD=c-E;#w‡}sЍCķb16xZԂeй _w@M_3[_X]hd^];Br–V(B 86{3eȇO"/8RQ5 rͰ,Ђm,(x`(iaidx2XȆݿ>2B 7 /82aY fc ޕ6(vPԕ0 3l?Wp8 4x^xfKXdWp`Pxk/p;3=7H8=30 hY51HW}l#C= _Vì4C@elY@Mxܕn5yӻ[qZ^n`1nI(jr}-Ϲ 0YxY" 鎘wP89VCs"h> Px?C0@ahKH._h w"S5 `9 gJ=O-3(qKu6;T4҃**1wT8.g{3N^hH*l3wNHi( A'xwy L؄ }kd+ -: SP(cQ;^Ke*t윑K/ooxyb`g 8⾳Oy,U2)!7}}Yp>H؂L0xkK^ WϷ+r^]UHL7 i]V``,Y, {drn50)q(ªR (pő"CxV9F{" B^$(DTG"Vpu !4FTׯ^s^:<Ȱbǒ-K+vXѡC $ޢYjQ#PCnv:}$A@1ƌ%ΎZdDUŌ;*uXzɂeHۏ2DŚ5 k?~sWR:<,iF^(  PXЃ]@zHB6mzi`KJLTQj5kaG$]U,RE[iwGEe h4sXB\S#z#l)ZnՁ\G"+CA9Ph&9fP9agR&U $rt2 $dr;0]UR4P*Sq/?貖 O$BuUx2;z $e, 7,; @*)7P/Z% %"iHn & 3w ơ(d聵ƊI`v!p$[W`^aE(::`#.IBu\S22T@  !Rr Vg9a, Y]ͺ/ z$ /|9 73&585L&v : d0\XA\AS62DpV,I^0 Z B8b(1.3Y)FZA GȢVPq@!9XQVԠFLp DPC$Lc2`LYс@ :O G61{b B ,ةa s`Sɧ ,)A,T }p@=ڇ>|E+4 8ta`;L( %O(&*pSz9X^^p- 4`Y)\ы,IrBxׇO+]P@)`:щ.E&a2p"PrS+ 5x4ԭx \-) bDELԆr8b"Z.0Rb!G8b%iv3?$PF]A@Ђ =tCt+\ʌ=t yD*DL|\܏*PHeO"54βkM"\%,"D  ҖN0Ep@JR'o4S, S\.@HHq)+md R,q "::**4ȒD ƕr1(Bcd( hDथ i\40 ]A!87LeXӅsӌUPGjwJ)h(4PU@XE ffPid*9QCl,P(^!`jzt^bRa:/Ђ`` o5AaK>;Ϻ`Uh~y;8>a݀(+A-v+4b4H>4ZPys7 0rq8G<6{y? CVf% buNJ4p`B)AV0iSd 7xj&.3b gR Z#؀}`)`cí|MC> !PpPM?!$3z,"Pf|Dɼ[LuCZaX1:*A'@=xx!Ԃ!tDԃ RauCX%95 [#U!R[ Qw>@T. tAyR/<2PBaH0N9.g 0 #|B11f,9ĕ!&l#?i E)[ARA*ȍlm P@V"&F=mƹB:|f9t4ۢOPV5dCbx9T'(X2,E_(JEs>''tB&2`KK,p70B'ɅU;pNiLo wLJ AC<\eJ)|RvJItB 4p8"A^PN>@A6C`If +"2\ ,.+%sEL: 4h׋EA1hz9t'N`XTʤƌL-\]Nh,8tA>F , 8蚊B4A1-)JFs!洨B%7  Ilhwqt Bݤ !`B 3,dC0k@jAP2LXҀV)#$l-7@0ch XfFXiOix ƹ¹i!`A0|6@B+tn93v p$ /3׫0:h@C#hL˜PX67B'pپrߒJ+ TY H؁} 1 K)] |!d(XQuiN<}8sF L! xV&TwݼlQveùot±"M^!WpF T BBm@@H3(VTI+f81 %5.t+PȱWٴDZ32Cނh9-eXt RǨYRwm0L`E\YSG@+@2 1=B/C8P@1tHt hg# aOAhz W$dT_j•E"֞pAy$*N*|YIS|PRzY(@  ӣ0T9%0,J2t Xm3֫ X sȷRg\l{'Z9}dtDӫ+5>| NpO4 ++u!pA:B0Q%2EY8!c3DXA@CXeB*n:?xC-pWFkvhkA 7q8oyLsrJ ADqWVr%3ԍEt2M3cB@;@S `hrPX97`PB,Acd%'x/Ѓ/! X@>P ts:>ڬ6T; 0@CZ!J1=<4F n'27f#3OdYɝ^$(Qࠂs SPj R>V у (PIziSvXB_Q_+ZQ\!MZk*VNHaƬ$ ÷U+f\Hʢnp0nתG d8XaU)7uV8rJZrzԄӮ2I(L"@l\ڥYT;ࠞf9S?zL,IcW,&XN'#r(:v@: (dPB YdUj sDZ! ky|Zj̩E14P1`LgE9$dYV%EI(F$r0QG--!5@/+*QdBRlMl N-⚳#A# aN pø\Y+9cӀ\@))&#&ivm%'H 0QOVAn 28X؁ @`z3[(:P3,`PA`  P< t.>tpʕ.Fs<E*vA`FjفC;<1$Z F;{Fx(L4nU[VJߖĕkEa1G;tÆlE9˕N6\Ѩƞ} kfj5 iы?kiNhvX큛ι4Sy$,3@ՐcR=@Q<e fCڣ`H`Qf D2kqݻa jE% vP\I@d%80j'EHP]xCNQn0Z`>LǜE92C(0J $)` :Zƈmcf4τ&gI+uRKV4pBiwE/: G@@, Ƃ@l6bF7X Bub/z"F=J  h5u"XʑCrzP$$Yp4rn-  Lq3Xc 9`EpV#uXAC#Y;.h@bAX=T< TOwVR 8D.p { *2 RN%lҎH9/A ]#Рd= "Ä1B6Rv"*+10c 7y P'x R>qJP7!` a\0B:2v-(Y:`A5h l0^4#F#y 4ܢt0C 1,0HŤD&eB&) dщ I*ƨ c7҂R BuԈA \IH@4AP!+D9Ӄm\9Q9&`1lLkU B.1@4(eXut'.t $PrP!Z2B?ִË8 c2+ʉ1ض0V foS|UR\q pvA җQpe\Qy h%Ӆ dnP ppsu)^ ɀ 4G2"YF! 0w 25E /mv=@n)p$  Y*DJRh T(`E  e@`@04؃W9~ C>ǟ-Q R` uwZ32P^uh*p!L7s 8@*āPjW 0}#*T3%Va5XЅ 6 CK8 Id]HHttӤ @i@2<̺20%ր&1btaAx L$I(w/8{jpF @޸q9J)RMA;XTȊ=L;*UP-S(,po,4(3d3 8CBC(r7QZe~̬8"Zb7G6 A~noD]:ÐD^AԢxz@QH{_n+Ƀ>yM-сVhDA pw!Yaj㪆DBwa> p.8L92@bVS5(\< 8SPVtAo$U;.cJ8eY%,DpP hS4Yʬ @@@@ax@ vj«`j`<)JA@`b&Ρ" ,c8D@#HA8((|eLFPj#¦c6D`4",ާC+˸J-33%: $`,b@״$dk >aNC #*̡9 vq 判`kv0kPN cQR# Hl!t vSj->R!$WDe0 I$ qR6`HE㔃 dezm0}wآ@|@q  Q6AɁtEj&h2 @ $Aљv |R^jD`b"" z axn`"%iz: &fA͠3a(; $$+k`?D! Z1@bc_ a/OB[/"*Z2**pa)L!TIXRRpARIjFT5ЪH6.NĜ3p(1i !&Ke`Q2AALtKU!Bp$ϨcvRiƠA ar @N` Xi D>Ap+Ara6h NȔ$֓BL~5i°,A@0@` Pi}QF`m_%. 5𔀹K%σ0NbQTT#pA(RBm$!9ar(h!014fa|Ρaa@ `d aA n!ľ ΁L@> d> O+S2nv` !>``2.|CX` ؖ>I @!| g 2,-֋ L, 1* C \@*Ar0z*O` `$ld )l)&T nZ%@ H%$D5cB4%ΘAqZ6 sbC_W8D%A5P!GoozJo3/Q 2a2a\N@! a &`KK3\5}T ^0PAk |BAndg b#A`L dAHMbipEFfw.l dRPw<|hؐ% &WT r` 0 .B,A r@&TXAa!XIT C Tcov&! 4*\fC7'qdqh O9ndBq|l-\| \N!|aDyHd7c[9go@`܁b .$OّB$7k"(TI RgX$.$|! h&@sp@ SB`DJ0IsSBDOACW @F  7P"lhR6d:ev;+2A9#/ JqG&@I{H(@V̓?)jAaTvLUN KO4 A-@A N^:tzz.. F8F7 #("E^ at3^ j  @ &,leE\AF>m,WrT 4a#- X@1BClFBElXAI3 jaQAv[1fC P8̪RcvQ.{J6*CpGᒥD!H~P!ϡ .5}av]}'`;C'|A A2|` @ z4Nɶ^kCȉC`@c6" eU^J%X";KV|b+tSt;<" %;X`UA#BۘhCb,tcd1_8T:!r;a6ZOS9$-Z;(e** @ mC$cCLA2m27^@ x sG-b3aʠ L~|a}.A2C}A ` 4"OsQ?E 'G6"C #g(ɠ`A""2W!RЄ)R a !R`.=+{LzX0 p a 3`[QX}X`Q{ZJPXx2삉jƈ!۱bp IE5ʬRgnZI#<r43kS=]w|jvN`/2KS}1fV 4uR[|gˁ0dȀ^®X I=4-E$:RB`n" RA=..@0S~-䍆X_B``1aj"f98; Y:.aG D"In:A4`҈$ ő AQDnLM꒢UV2iN;\ۥd#p,m): =4RD+'ndv. 2A)Ӊ '}%×o#jL, 7=F(Q"^Q])4!X!Îse= Ɛds"Dfcq81`x 2Y`rNKX0 7}e-DJ" "\VK-A1F-uRA~!@16ġ VsS"Ce0P_L:@k 8RD v́y.89hz 7̴Rv`*}<Ackp7ܰ !l$xN%Jb6(B\$! ШKpԃ+ш ;"@058ƹj tWBTC!'!76-X\K@܀0JA!Đ!S q5UbCYVZ7FYBqc9tCƩ>@26ճHmQP %ЫYP5dЇ  [XA6hP{vxV4G2gB{9‚bR 5M7P20! /,aBS`}vA)F"CItQN:rTF&n Iب^*W+dHg> Eino"jf/ _h߀9NC0f @ 'W0t1@vd % 9v@*s$V7  (A)ng-DjP+b|`"&"L D<^ %! )I 86 j v ft_IPנ*1 @F)@nB fȁpvFYrQ6A[`mHrШ>ZI920yAeQIn2N r22@[B␉)[7b be\qPX P$ O@?LԢTS ;tJ_HT& "')gDz rgbYp ȠIQs~ @C1C"@ F=!8<}l#Ȑ=n`p⠂`x- @E0` CcVdԏHi i pB'lĒ 9F6&rp73R}Lkql 5LlqL62qx*jTaj h@!.Or#I،~6))xwHM:(6%Rd <XTgH( `Z4A.0GvjF.|Re; D_K)A䠛,|$@tR`X zHԗj RE-Vlqd`v HEh`:PA%vCC+oܠ"AHl!؈C20WT&,#:9EQZ,hբHCZRưPsj O)_ cFP&P 11 sܠ;vA3L+O[+UgV@6ޝ^!db cИ W(E t0 ,"p@=:`7B 0Ğ(RV3?=+Ȇe QSArkA6YHn nAdcRjUQh $`o%3>!X.q k'@ݢt@"a-z"UB3Ï>E9$у c  r-A]AGᘜtD!vhHxx[+}*cuLcQ>4|8 "TMR=A|UE8Db`e| z ``Jb`v ,cHCC@EOq(<dE9(ua0OnTc i0v7+1~ 0pup # 0 x^=3TpS6Wnxef""L ̰0 /@sGrs`V`zzTpO YX[gnpZuA|gsL(&:pe ' u \10 p H@ n s1>A,@ z#cHDn39 J`qaf~ `pUyds%MƁP7{w{ pv'qnpJ7sywccy˧9;hp870/P+q'?4dw  % :` 0 @͸ q66Ngh x?`W02x  w^C6) %}f  %_FV"ut85 ;P \jA=z 9 Љ8V RqtZ"䘆_6  R >+%uǁx[{W{W[مP6xWd )z@/ۣ mGn(aHn9@ wW%0t'4h #LP& P w xP W}%"?fX diNy9 Чqɩ`@0 @ :h&PA7D7Iٯ"dA/m7`0(y^XaZ꧀jHAI{sEC Z`  ڠ`kcxuGc_kzꤟ|GrfngywZ8$ XPQp@@9 0![Ft%eHyDաtX Ep'4xI8gk?aH8@pX 0Upp߸kDIw." ׾3ȬW7u|QJLx5P z(G{ڨgn;:c9$yu_L1[I&r41hAw+仱gE 7ǨHFQڻ{ yy;q[" %qZx%|iVzdr)ÆKfʎ%@{Wx{30\yȰ3tu‰{`KfxE+ dDaNc l|z);w9|QjjT}{?$] R^) a l?M" eL d fY˾jLfL<55:" ʝ*LvƏjfI:l>蝺^V Iƶc ol,응_; 0zj/lNK¼n$ͨʒf JwZ\' Qbf-< m ^We-n[JXx#Mχ&-u fd+mƛ=y]G'{sM|lm~֍ٕy "n@}p M7,Ԯ?j٫ڭڃ ˷mW+ҷGٮۿ ܽǏkoۘ  -k n>~GpcN;D 1 "_NEa{^έ]qA`@έDES^O PjߔFj PGP^> l9A NnX$}WG@߱!J2NW>UXM N~F$*ȞԠ/M߳iA?^M~~>BCJJbD0  DN.Ů$Gp & %~ "Un?/=.4vDq/(<#^- 6?"s/ @Xp2~ `]"N@v boE߄C> $~oqy%nI NJ/>nr?o \/^% ܾOQFO=.qoz{ qNJ"n|?O ϭM}t:`oF./e>$8r$+G2( G|A A n,+ p`#!6D]TI`K8_rٳ+TI U2,XeSNo)U@Y&Ν1iIN˶\%bfڴ]yV ܏r]yILlI Hr7T{iAꉅ#_sg3|b2kZ5_xAd֮#VvXCnw1p ֮Bdh0{=Љd {J{v"PsJ*=+h,O4 N+ 8O@tPB 5PDUtQFuQH#tRJ+3 ;uligo-0.3.orig/gifs/reload.gif0100644000000000000000000000374507723003524015031 0ustar rootrootGIF89a(( FFFnnn22.VVVzzv***&&"^^Z~>>>NNNbb^΢rrnffb666¾ֶjjfJJFvvrRRNޖZZV~~z:::BB>ʾڶ2..ھ...ʮ–ƪzvvb^^"""ҺNJJVRR¾rnn~zz:66҆~~~掎vvzƖ⚚JJJ222zzzfffjjjvvvRRRZZZ檪BBB&&&rrrnnr^^^bbb!Created with The GIMP,((+T0BAh;*"F#EF ;Q"!8Kh(PA$+(1"H*iib@d8f#y1%“'E8Z(Ku4xبSr,5#p9:I&Gw@$ՠ^ˊq:+ +N54VTXؚ;MS iA7AB E^7 ($ 鬡2pkL Q k8XJDQ p&U^2| L-5 1 D Z c"%4:k& a _!L: 587$!Tǹt\>)"8!8f`  :Tjz#U p#5 `#MpA#$RtDB`cFd+1uLG4@=- )ð@[+(AUS4sE E$u " @{EpfUeyRwd^H" ܐA7( !WBT5FCQ!$h`#uD'zV'ɄR|!G{!!&|RzЀ n`Z@&<QC0  %@2hUr >Ѕ<@!^p\U! ]8כs3E$*0 h)rCPHD">I"P aHa뮂0h@a]C' ”dJFH!Ha_ H&\aT'\HACІ"Ee !Lah!'P T|28C@;uligo-0.3.orig/gifs/right.gif0100644000000000000000000000370207723003524014671 0ustar rootrootGIF89a((NNNzzz"""ZZZ...nnn~~~666fff>:>ƶ ¾JJJʮڞ^^^vvrBB>ҾVVV֚ڎFFBvrrjjjrrrbb^RRR***222&&&njjjff¾FBB>>:®~zz^Z^rnnNJJzvvfbbb^^RNRھҪvvvBBBFFFbbbƮ>>>vrvnjnjfj¾¶!Created with The GIMP,((Y# @E!b xaѢ@'8@れ4Bb ,4. @xxÞXsfʊ.3bDJ:䄠EOfeiIy4$ Z|֓(%a–$ sEi= }Y]g6zVnj,ͮxrχ{Y%/+-F2F6jVv(7(W" .ǩxTrf 7sVKtn^E*(ȇ ]d\r  z@85,\Av0@@$q%0^DMcADjF?aNX& i@M!I1N?A d l!N@E'qSL6B`%KX j&wd @  IZi$xz9wXFkL! Voy C NaTUQx`Axp! _@j9٫'DAA+L 4@wCh:{iAqW”!8ȩ'F;D7Ԁ0gH^$aD`F -Qn@Ƞ<G $EQlЂVi %@(0wQ: } /Cb80]A*@$@odt !RIyM\,Bs }49D[tY7@&r@< <7 $qF lFR1d1q w UNB,Wh@,MMhQ-@_[SЀpAS[K;tAbL6Ɇ"d衇k0DS/ ` L87ANBç0f'cB.@ /Ps2vk-D ?80 cA0M8d&MIP#lRd !lPPZ>Dd!yAr DQ"LBO@` d@̈4R1P IX#I_AR>pP$(e4aǀMdI9q" ;uligo-0.3.orig/gifs/showsol.gif0100644000000000000000000000562107723003524015254 0ustar rootrootGIF89a<(***^^^¾nnj~~~>>:֊ZZVΒNNN..*殮Қbb^662vvr BBB"""ƲJJFfffVVR&&"::6֦FFBzzv.22jjfֺrrnšRRNڶʾʪƞκ¦򢢢¾622~zzƆNJJnjnή~~zvvFBBrnnbbfRRR^ZZ2..ꦦ&"" 222vrr¾ºVRV&&*ΪƮʮrrrzzzھnnn^^bZZZNNR...666vvvJJJ&&&:::FFFjjjƲޞbbbVVV>>>¾~z~RRVNJN΂~rnr!Created with The GIMP,<(_4i0`NS:4qH3jDxǏW6flAC >0C0qbGwG(@`Dh:i$V3!M0!'86dpj dP ʼndrI5$T9 c :I,Xuft uͷ 0@) z0ZD0 vh-("PT@cH -į )0r +{0R E ) CrH]P @Cв[=w ! JAgp(!)R `gŠ+p2 )Xt B(s6b^M 1-bgtG 6p )G[1\|$yYmF+Y`*] )#(Rxv _*̗ FpB LlR bր)D^ׂ\Ѐ_w׭Q] 8-P0A ׇL] gKK &X7U"`CՉZt p)JZp}@  tTVփOe& HBX*JD(E*N*ЅQK`-lA1+,TBȊ P +@' B@TH*:I+3~Vp!`I%,, gpprB)LG\cx8A a h,4R("g )Pa 6sXtb =X@QC(yXgxHH*PqTZҔ"dD(-R @ |P(bm;ᙉ7,i D"p0+] @^"-PJ: =E BL<9#"=XlJi:9q3 BX,dPPq(J@%H v?=^A!Yh)` X\!b+: mB[W T,"@.RA @-AV {,B+B@*r@ Qf` SHE'Fa3P"P Q`@H %jQ:+p$FY NBAdwCaQ\w=!BsCR4a:a+Ơքu H`]ȁ%/ZsV4w@P4B*H Ђ0KBi~BEw,,0[VpP(Yx,ڰ tg:AKV,@F P"Rhjւ6r "la sDư%d@ m@Aڐ'4{ Fhot X  NĴmmk;O('2=#B@T獁 \^78Euo,`"pYi9e`]8+i#Yy4@s2 Rd8BC~s ^iK *SNp*8^B+wL`V``g:>#`꧀;uligo-0.3.orig/gifs/solved1.gif0100644000000000000000000001122207723003524015125 0ustar rootrootGIF89a(266NN&^&rr./22ڦֶ66޲66ڵ66޾....6624**ZZ&&ώގB>ޖ""b^ ~~22¦&&ڪڪ**ffrrҪަ::~~zzfbΚ..JJ::ڞޞ־֮NNBAZZzv޽҆ꆒrrޮjj2...&&vv>>bb^^2.np~~悺ںFFަުڪ2.ff"FF**&%ڲ62jjҶRR־⾪RQnnJFffVV޷zz^[>:ޚޢ֞➢jjǂږ~~zvNN2222ɾھƂꀞvr⒦⪺ֺ⊮ޮZZzzBFʂ^^22bbbfz~榒ޒvvֲ66FFުNRfj֦~JJvvꊶ޶.2&*BB:>zz撲޲22ڮ"">>z~!Created with The GIMP,( HP! TƐaTK"J,;32eG Z021HHFD,c4(%U7SN%@)BhQ y&2^xRTVL*\2F^=rd)Җ*mڒm3X#g8,`NJeZ]+:Z-P]qޫb.<ţ6,a]J(MtH=/`Q@U+bJ%  ;؁ځkC갖hd+Hpd`/{M~Ly%>x%a^`Ȅ V|.v\=0' C9PP.l2 ka>`7}Tab7@(,px14 j-vjKTr"ʄ$%1H3LCA޻FuDA/Q.>p:DP*V pD#p=D|s<1 `@4OnA^ ;$"hDpZ ,`A6jDB{HA2 PA9BA7adwEakQ̜L5g &JPj! FTrTwD >0 cXX䐍cx F3a9huGQ @ AICQ((Zlh #V"$S 3(E!g'GPtBrCpSA$"3p i0AFu ;6ܰpo('T-a]ny;(B;C/@2,dZ)b{-ZbMQ%ne#zZDbT@tᄹ {wa-- +$nyKa!X/80py=Nz`eӱԙ&01\J rթsK+|)J| X/ Jֹq Z7kx<YM{W4- %ɔquMt5*Snb'g5ǒeWf?Wp@%;:K|^U 9xǐv0I6R v'nCזDh3` N(0gY|=@n5m-y_`#WCa8Kdvҹ`P-BJ:̣^iWlp WY($;)l zZny]zYWm^g=MMҶ U Dх Z|{x¬j1}kvph"jg f! ԉsDA1Z,Csps`yҔ ձNDDv~IÄh_1"̞ǐ#܁zs- w;|g?H){_z ?(6wV!X7On=GrPo6yfgGrvr}/sO)zt7t^F6_t6Z,T0W"@( LgoVPegwi|ovgXBhFYwpulmd$_eBaZ5 We@  y6w+rlxvs#Gs'7}Et@WdWxlJ{IQTG&!|VW&!0 Bn  nAoOPnf+vxn{R wpMl#~%B&A*X&$2 P|"fj{׀vkmbŇ8v(n}6_6V$R (mbuS|Da8:\$`t.hsbHLa#p^@L0A`0ip'SIWԴʀ!!0b0w,z"Kp [:bhcԕc)%=B[]ҵR[9(`b`~*;Y^FɠJGxm51 {D"Ԉ#&,Kp@٠]7*z4Pمc*0@eـ P e@ n@E~]0V [p ]ELhLDb B&N2#’2!,  = znPE ` ٹn = =o x F, I F0O3@@ P \Pioکz h`֠Y -2,dRP'EeQq#vab@]0 X u.p5<*Qv` @ Pz @` p i 3)@ v :0f04`vP u֐j)̡hHh={RM>/ʁu1,!,OC!?K 7  U<  Zp @DЪ '! @ 4Tpa fif ]p!pP0 7` *$S"z%|($0a2ϒ?  ;@DpD u+80$Ae'p J?+STLx=ŭb*1qOi27񨺷T8TJS !>1m*q[%⸔&?e[ W>!; ¶ |mp ,ʡ'Lk6Q%z.g>)UKx31U{7,?% %`L .0a *RBKi,DŽ"GJ@ |p;uligo-0.3.orig/gifs/solved2.gif0100644000000000000000000001166707723003524015143 0ustar rootrootGIF89a(.>Zn⦾޺Rz:bN6J.ҖjFfҶھBކR^zr꒺梾:ڊjfB⚺ڊ⎶~~ޮ^rꞾ⎶j2Ⓐ悲VJꞺnf斺ڲ֎Ҳچ:vV⚺~b憶R־ޚֺ斺Zڪޞڞ^ުjb޺ڎچvVzޞ梾檾޾ֲjJⒶN~ꚺޒfv>:rbn~R枾Ꞻ⦾F޺ފzⒺ悮悲⎲rJnv!Created with The GIMP,( E- aF"J$C@3eG J2HHCD,c4Hј7@ȠAhQ yZjR1aB2*F^=rd) N(mڒmK}{Pb<V&J/IE-gGj'ɭ"k(x&\$rl~q(D4V*7EаQְ0QCi(PLCf4cɖamn'MwH 'p+Ѐ MI+4"& npT(|J ABG{njZ;FF,,`NJeZ]):Z+ȴ,Piq|[aUs [D Ih!D+R`ҙ< CzPB~,p~ A0b]#dիȰP"$0XW\8@= 85`` Sd#" @*F(AvB% "+)bb@4 p䐀&C̵n9P&eIuLBRLF))P׮! ׸8f Lİ#|pq\԰-V+xMW!*+ B c@!6Idb$& /"s T $ T Xwals( D!"x(" 4Tԑ2h !l4 %Y xX6@| hv0dXA =X h@p<ЁXЀ @ 5ra\1-Z1w¬RcbPx1(N=.)zacDH*3Raa@\\`~H@ AF@4 bP*@xTh!h@ Z xH@ 1q(RMTԍHڶk؂ H Z' j  y0\vp@a!DЀ4A8@kyh THEv0 vpv %Pq0bc!9)])n"*wVaK$8Tz[1vQ "NUJXB"x`U(`"q*D2! "LL@Y6~`p@ CG1K e[| sbľCV<@07P(p ,#Nlu B|ɀ5,@d.sC@ mm#LA3 JF`7 / 0 RWdL,:Fft ] =xCèEP!VIqQ*)pdb$!'Hb ?gL$I, -~ 8GFo{G/2/'2P 5 {FK_{$`(@1e?X71&|-Wra4Y.B;>>fffʮ➚ڢ¾RRNžʚvvvֺҪꆂʊ޶Ʋnnn֖&&&~z~&"":6:>::.**b^b*&&njjfbbZVVVRRnnrvrrbbfFFJRRV***ꊊ¾ƚ226~~~...FFF枚޲&&*^^^VVVbbbRRRrrr!Created with The GIMP,<(a #-""Z0aҡ36 9rDH9d9h%H"X(bTJpyFg3"RB 3̒[4 =vhi1H4ezTH,Ȇ%|a o"+3߶ ".5BE&T#gGn팈"J"bFu,r|Bn jd##EAg&STPh'(TDRF,!L2Dp% $HpEDr q0BvvC8G# aL"0P A C! 'Ā}XbgmȗVȀK1%C4$kl…"XLAQLg,ʈU@z IZPE,<80 )1.i-Sİ$.C8 @e+݀2md# `@.p;qHvD|Ao`+HΎK# x47Bxr, \Q @ @5bcr=;` 45z_H4p BE("H#p8xJ1SĖXY ^Tn2}A%g#VWGp/$ث EK1v#O`Thh O3\σ @|Ax; Hu-AJլ}}`*,v@K[$~QU}929e7>>Ҫƞ¦ꎊʊξ¢Ƣ¾–VVZvvvކ~~bbfjjn!Created with The GIMP,<()xćH6#Jd#bFƍ7Bz#(H )0ѠEl|XDKO#Q䆖E8~D'GU$|xC81q@ -(¶GA` JT DdoCBbJ'4n,bحl8B4Ҥ\(T) tvEV!k*>1C+WS&T2@!. #O^ B4QFoqHuVmG0O2[njܦN#̝1}0n-zQ0U5UY߭g^S0ctGM'u)fvAA@`z S c!F"!}e'`maC! 1YEʼn[AG_aTHч۱#!D`MQ"84g gq{ bD"XUFA! 3`@T*)ge+2SyўuYUG`dF3 3!#&Q&eeTK~F]2~ro>jGV)$P Å`8 %jSd e.*zT b:lVJ%kBzD畱  :n dEM2BQLPL y챀誛n246 TI;!q`Ap)< 6eТ;& ̼8358@ 8@t,40IL/zTa.5DF48@,Ahs/L<KDOaIhYvF/]O`k7+P,@ ,P@\Dn8Pj<@khuϼFyPK (y ShA B<[\Մv Fp,` ^ LU^ DaeT -,6{Qz)|SH:?2H)AVoYQW˛8Es|9I ) )M d0@"m.JN$ *sXD9NQUD%(Et4g;H@ HJOɁ -r:y)NM8HӧX$eP"k L1H@:!O@jB"&4!_(ag̀ )NP2A  ࡴea p2:\1Ѯ@.@A\'\ϸpZrH"*PVycPɭ6Њp6 * @D$^=WqΫ<%<8 p:L mN$$­HT- C@aA@PAbD+~ B k2ZbȮozmP`!$::At,CIx&>Sp",$m)93` bt:IH Y8T scl%4)`Yƀ`-c,ڈr6͠i t5&i3DP'M2vT0:[2c@ U"Set- $TV<62`6l9aa}f!ve .(XTR;uligo-0.3.orig/gifs/w.gif0100644000000000000000000000015107723003524014015 0ustar rootrootGIF89a! ,:πȀ1} {t4☕ˉkKމH L Ce J;uligo-0.3.orig/gifs/white.gif0100644000000000000000000000234207723003524014673 0ustar rootrootGIF89a==Ӯɝvn^)ΪD`t>Πɻ~{왐Žֺr!,=='d9 (mL+0A< 2 ׫~aH%&n9p3U6C]q`uKLx i|&~,Gc np]rtJvw YU~wx ȸkοIcԟ ʓ*ޚs }ﭼ6XZ:Xط?dZ,(X&NVruGjR?w +Io=PGFK4b7q^$@Jc&Ҥ 1R)/S4ډs*50%UHZl[[2B^(9NQ]sh/\ #*قH*F$%2TzQڼPD,shUeOlf eQgpevEvM2'w'{- d,Sˊι"EvM=WU]g^@Fx!`t܆aXouEr3ag~lmpA$v^j!BTPxI-!5w A#rͅfy#k}8PDaXX8!o@}^9.ȣk>:\HiG^"_:yG֕y"w*%u&7ߗ8r9 |nm<-Īw~S`$<|;+93z|ʻ t/v=;C觏>W;uligo-0.3.orig/gifs/wrong.gif0100644000000000000000000001067107723003524014713 0ustar rootrootGIF89a(266FBrrↆڦֶ66^&&2666¾ւ..NN66VV¾⎒&&jj悂ڪ⒒..2466 ~~ޚ>>^^&&zzޢڮ22ff־ޮ2.""榦暚&&޺ڞ⦢2.B>::b^޲ⶸvvzz⪦Ⲯ..~zޞ..**nnrr*&njRR梢>>ꆊڶ➚2.^^JJ⮪Ҫ66::22fbަꖖzvbb⊊BB޾ں⢞沲ZZ▖⚚^Z⮮ֲު**~~22vwRNꂂ6622޶JJjk.2ھnj枞&&把ڲⲶbb޶➞nrrr殮ꊊFF.2撒檪^b~⺺⾾22BFz~~>Bfj沶憆掎ꚜ涶JJzz⮲**FFz~nn斖~rv&*⦦BB⪪*.ff⢢RRnnڪ޲悆⊎^^޶榪޺Ⲳ~~޾!Created with The GIMP,( ‡ !"J!ć@3BeG pBHH\D,c4d78@aBhQ y\BpR2bĂ B*F^=rd)A!s$Rbɔ LN1nɻv}L*О>A#DqŅɤK7}i1E&=y"ݘa-1!$9/@ɹmē|^)L 0K8Q0TJ U)gd)lğNrD;- P&t-\.yVF z`33kqdVhk U0m+D;O򴬲 -4+7"N9t_ Q "/Q/W:tG=torlm5plgɄU0:VKCHрD? *Th$!jЅ%fŵ 0Aa~p?؃;؁vx& 8X-"G!@Df2(6,O>QH09a1BI8;!AYnʜ؂$F2A< H qD$ G}S@XUp6dU[,5W*V"3PkVD@%6#Ol[ g7rGu]Z!LE",NX%,  `3jg0l΀JK[h@gg[   j"j:As@|=3e823Jxc1rcƵe=r50mЀ@e:_~)_hO{@[[8 :(f+CixmV.;d⵨̭eh+1|a5_68{_>3\  0` nW*]qTR( @r Ts9U P&0VUVEH<{:./cadR'5$^p5]3R X D6N$Ӧk$7F5F11p Qi0%p f:4É%sR%RB07<4wF2oSf&6r.3g2$pC ^ p0<  ]yfc)Vi{GT1D1#@o6r욀E0rW!(u9'`] p7AY2 @! "-oq Nr!# "- u+6p91p5pݣfPS; |\ -;uligo-0.3.orig/unixinst.py0100744000000000000000000001035107723003524014367 0ustar rootroot#!/usr/bin/python # File: unixinst.py ## This file is part of uliGo, a program for exercising go problems. ## It serves to install uliGo systemwide under Unix. ## Copyright (C) 2001-3 Ulrich Goertz (uligo@g0ertz.de) ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program (gpl.txt); if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## The GNU GPL is also currently available at ## http://www.gnu.org/copyleft/gpl.html ## --------------------------------------------- # Please read the comments below carefully and edit the file where necessary. # Probably you will not have to make many changes. # If on your system, the Python interpreter is not in /usr/bin (but in # /usr/local/bin for example), you will have to change the first line # of the file uligo.py accordingly. import os import sys # this should be used only on UNIXoid systems: if os.name != 'posix': print 'This should be used only on Unix systems. On other systems,' print 'it is not necessary to execute an installation script.' sys.exit() # write global uligo.def f = open('uligo.def','w') f.write('uligo03\n') # Do NOT change this! f.write('i /tmp\n') # 'i'ndividual .def files: # Look for .opt, .def files in $HOME/.uligo, # or -if $HOME is not set- for /tmp/.uligo . # You can replace /tmp with another directory that should # be used as an alternative if $HOME is not set. # It is very unlikely that you have to change this. # f.write('d \n') # Uncomment this if .dat files should be stored in the # same directory as the corresp. sgf file. # If you leave it as it is (recommended), the .dat # files are saved in subdirectories of $HOME/.uligo # (or of /tmp/.uligo ...) # f.write('s /usr/local/share/sgf\n') # Uncomment (and change) this to set a new # default path for sgf files # (the directory you use must exist). # This might make sense if you don't want to put the # .sgf files in your bin directory. # Leave it to make the sgf subdirectory of uligo's # directory the default. # create link to uligo.py os.symlink('/usr/local/share/uligo03/uligo.py', '/usr/local/bin/uligo.py') # This creates a link in /usr/local/bin pointing # to uligo.py . # If you put the uligo03 directory not in # /usr/local/share, but somewhere else, # you must change the first entry. # You can change the second entry to put the link # somewhere else, but the link should be in a # directory which is in the PATH of the users. # The file uligo.py itself must stay in # the uligo03 subdirectory where you unpacked it, # because it needs to find the other files in # that subdirectory. # make uligo.py executable for everybody os.chmod('uligo.py', 0755) # check if the python interpreter is in the 'right' place if not os.path.exists('/usr/bin/python'): print 'Your python interpreter is not installed in /usr/bin .' print 'Please change the first line of uligo.py accordingly.' print '(You can find the location of the Python interpreter with' print '\'which python\' .)'