# -*- coding: latin-1 -*-

# -*- coding: utf-8 -*-

# Copyright (c) 2007 Stas Zykiewicz <stas.zytkiewicz@gmail.com>
#
#           multiTables.py
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 3 of the GNU General Public License
# as published by the Free Software Foundation.  A copy of this license should
# be included in the file GPL-3.
#
# 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 Library 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.

## Activity to learn the multiplication tables (1 up to 10)
## This is a rather 'hardcore' activity, the focus lies on learning
## the tables.

# Todo: implement a goto next level button
# it could be a menuitem and the loop checks for a return from this button.

RCFILE = 1# Used to signal the core if we have a rc file
DEBUG = 0# Use like this: if DEBUG: print 'useful message'

import os,sys,random,pickle,time
import pygame
from pygame.constants import *

import utils
from SpriteUtils import CPSprite,CPGroup,CPinit,MySprite
from CPConstants import *
from CPMenu import MenuItem

import pyassetmlSDL
import Timer

if os.name == 'posix':
    TEMPPATH = '/tmp/multiTables'
else:
    TEMPPATH = os.environ['TEMP']

# colors used
GREEN = (0,255,0)
RED = (255,0,0)
BLACK = (0,0,0)
YELLOW = (255,255,0)
BLUE = (0,0,255)

# text used for the diploma
HEADER=\
_("""Multitable, as part of the childsplay project, 
declares that %s has passed the multiplication
tables exam by finishing %d exercises in a time
of %d minutes and %d seconds.

Date: %s""")

class Img:
    """ Container to store image objects"""
    pass
class Snd:
    """ Container to store sound objects"""
    pass
class Misc:
    """ Container to store all kind of stuff"""
    pass

class LevelArrow(MenuItem):
    def __init__(self,img,pos,data):
        MenuItem.__init__(self,img,pos,data)

class TableButton(CPSprite):
    def __init__(self,img,name,status='red',time='00:00'):
        CPSprite.__init__(self)
        self.image = img
        self.rect = self.image.get_rect()
        self.connect_callback(self.callback, event_type=MOUSEBUTTONDOWN)
        # this attribute is returnt by the update call in the eventloop
        # and we use it to check which button is hit
        self._name = name
        self.name = name
        #st_icon_pos = (self.rect.midbottom[0]-3,self.rect.midbottom[1])
        self.status_icon = StatusIcon((12,12),col=status,time=time)
        self.status_icon.set_position((self.rect.bottomleft[0],
                                        self.rect.midbottom[1]-3))
        # When actives.refresh is called by the Game object the status_icon
        # is displayed
        Misc.actives.add(self.status_icon)
        
    def set_position(self,pos):
        self.rect.move_ip(pos)
        self.status_icon.set_position(pos)
    
    def callback(self,*args):
        """If this is called the user hits us"""
        return (self.name,self)

class StatusIcon(CPSprite):
    def __init__(self,size=(6,6),col='red',time='',pos=(0,0)):
        CPSprite.__init__(self)
        if time:
            size = (60,24)
        self.image = pygame.Surface(size)
        self.rect = self.image.get_rect()
        self.set_status(col,time)
        self.set_position(pos)
    
    def set_status(self,color,time=''):
        if color == 'red':
            col = RED
        else:
            col = GREEN
        if time:
            self.image.fill(BLACK)
            self.image.blit(utils.char2surf(time,32,col),(0,0))
        else:            
            self.image.fill(col)
        self.current_color = color
    
    def set_position(self,pos):
        self.rect.move_ip(pos)

    def get_position(self):
        return (self.rect[0],self.rect[1])

class Exercise(CPSprite):
    def __init__(self,exercise,name='',pos=(0,0),fontsize=48):
        """exercise must be complete, '2 X 2 = 4'"""
        CPSprite.__init__(self)
        self.image = pygame.Surface((300,fontsize)).convert()
        self.rect = self.image.get_rect()
        self.fontsize = fontsize
        exerc, self.solution = exercise.split('=')
        c = "%s = " % exerc
        self.exercise_surf = utils.char2surf(c,self.fontsize,GREEN)
        self.image.blit(self.exercise_surf,(0,0))
        self.solution_pos = (0,0)
        self.set_position(pos)
        self.solution_start_pos = (self.rect[0]+self.exercise_surf.get_width(),
                                    self.rect[1])
        self.solution_user = ''
        self.solution_objects = []
        self._name = name
        
    def set_position(self,pos):
        self.rect.move_ip(pos)
        self.solution_pos = (self.exercise_surf.get_width() + pos[0],pos[1])
        
    def set_solution(self,char):
        if len(self.solution_user) >= 3:
            return
        self.solution_user += char
        # change this to be a number object
        c = utils.char2surf(char,self.fontsize,GREEN)
        obj = Number(c,pos=self.solution_pos)
        self.solution_objects.append(obj)
        obj.display_sprite()
        self.solution_pos = (self.solution_pos[0] + c.get_width(),
                            self.solution_pos[1])
    
    def remove_solution(self):
        for obj in self.solution_objects:
            obj.erase_sprite()
        self.solution_objects = []
        self.solution_user = ''
        self.solution_pos = self.solution_start_pos
        
    def check_solution(self):
        try:
            if int(self.solution) == int(self.solution_user):
                return True
        except Exception,info:
            print info
            return 

class Arrow(StatusIcon):
    def __init__(self,img,pos=(0,0)):
        StatusIcon.__init__(self)
        self.image = img
        self.rect = self.image.get_rect()
        self.set_position(pos)
    def reset_position(self,pos):
        self.rect[0],self.rect[1] = pos[0],pos[1]

class Number(Arrow):
    def __init__(self,img,pos=(0,0)):
        Arrow.__init__(self,img)
        self.image = img
        self.rect = self.image.get_rect()
        self.reset_position(pos)
        
class Counter(Arrow):
    def __init__(self,n,count=1,pos=(0,0)):
        print "n",n
        self.counter = n
        self.count = count
        self.image = pygame.Surface((130,150))
        self.image.blit(utils.char2surf(_("exercises:"),28,BLUE),(4,0))
        self.image.blit(utils.char2surf(str(self.counter),48,BLUE),(40,30))
        self.rect = self.image.get_rect()
        Arrow.__init__(self,self.image)
        self.reset_position(pos)
        
    def update(self):
        self.counter += self.count
        self.image.fill(BLACK,(40,30,130,150))
        self.image.blit(utils.char2surf(str(self.counter),48,BLUE),(40,30))
        self.display_sprite()

class Game(Img,Snd):
    """  multiTables - part of childsplay.py, a suite of educational games for
  young children. """
    def __init__(self,screen,backgr,rc_dic,basepath,libdir,cpg):
        if DEBUG: print "rc_dic >",rc_dic
        screen.fill(BLACK)
        backgr.fill(BLACK)
        Img.black_screen = screen.convert()
        self.screen = screen# SDL screen representing the visible screen
        self.backgr = backgr# A SDL surface which holds a copy of 'screen'
        Img.screen = self.screen# Add some 'global' references
        Img.backgr = self.backgr
        self.cpg = cpg
        
        try:
            self.rc_dic = rc_dic['default']# reference to the rcfile, if we have one, otherwise {}
        except KeyError,info:
            print info
            print "rc_dic",rc_dic
            print "using default values"
            self.rc_dic = {'examtime':5,'examexercises':50,'resultspath':TEMPPATH}
        
        self.basedir  = basepath# path to the childsplay core directory
        self.libdir = libdir# path to the 'lib' directory which holds this file.
        ## This is only needed when you decide to use assetml files.
        ## If you don't know what 'Assetml' you probably don't need it :-)
        # create two assetmlSDL instances one for parsing images and one for sounds
        self.Assets_img = pyassetmlSDL.AssetmlSDL()
        self.Assets_img.set_mldir('childsplay/childsplay-images/childsplay-images.assetml')
        self.Assets_snd = pyassetmlSDL.AssetmlSDL()
        self.Assets_snd.set_mldir('childsplay/childsplay-sounds/childsplay-sounds.assetml')
        self.gamelevels =[1,2]# used by childsplay core (see childsplaytest.py)
        self.gameitems = [None]# used by childsplay core
        # You MUST call CPinit BEFORE using any of the SpriteUtils stuff
        # it returns a reference to the special CPGroup
        # This group is also the group on which you should call the refresh
        # method in your event loop. (see also fallingletters)
        Misc.actives = CPinit(self.screen,self.backgr)# Init SpritUtils stuff.
        self._setup()
       
    def __del__(self):
        """If you use the timer object you MUST stop it."""
        try:
            self.clock.stop_clock()
        except:
            pass

    def _setup(self):
        """ Set all the stuff we need"""
        img  = utils.load_image(os.path.join\
                        (self.libdir,'MultiTablesData','arrow.gif'),1)
        self.arrow = Arrow(img)
        file = os.path.join(self.libdir,'MultiTablesData','correct.wav')
        Snd.correct = utils.load_sound(file) 
        self.Assets_snd.get_assets(('bummer.wav','wahoo.wav'),Snd)# becomes Snd.wahoo
        # filename used to store user data
        self.USERSFILE = os.path.join(HOMEDIR,'multiTables')
        if not os.path.exists(self.USERSFILE):
            # makedirs is needed on windows but it doesn't matter for Linux
            os.makedirs(self.USERSFILE)
        self.USERSFILE = os.path.join(self.USERSFILE,'mt_users')
        self.users_sheet = self._fetch_sheet()
        # ask_usersname also loads the user data from disk
        self.ask_usersname()
        
        self.timer = None # will hold the timer object
        
    def start(self,levels,items):
        """Learning the multiplication tables."""
        #print "levels,items",levels,items
        Misc.actives.empty()
        self.levelarrow = None# checked in loop
        # make sure we don't have clocks running
        self.__del__()
        self.screen.fill(BLACK)
        self.backgr.fill(BLACK)
        pygame.display.update()
        self.score, self.stop = 0, 0
        self.levels = levels
        if self.levels == 1:
            self._make_sidebar()
        if self.levels == 2:
            self.start_random_exercises(int(self.rc_dic['examexercises']))

    def ask_usersname(self):
        # needed for EntryEdit
        self.sc_fsize = 40
        self.sc_fcol = YELLOW
        self.hsc_ttf = None
        # This is the new RTL aware entry box
        entry = utils.EntryEdit(self,self.screen,(100,220),\
                        _("Please give your name: "),\
                        loc=('',''))
        name = entry.ask()
        pygame.display.update(self.screen.blit(self.backgr,(100,200),(100,200,800,500)))
        try:
            self.user_data = self.users_sheet[name]
        except Exception,info:
            sheet = {}
            for i in range(1,11):
                sheet[str(i)] = (False,'00:00')
            sheet['level1'] = False
            sheet['level2'] = False
            sheet['level3'] = False
            self.user_data= sheet
        self.user_name = name
        # test code
        #print self.users_sheet
    
    def _make_default_sheet(self):
        sheet = {}
        try:
            f = open(self.USERSFILE,'w')
            pickle.dump(sheet,f)
            f.close()
        except IOError,info:
            trace_error()
            print >> sys.stderr,'Error in writing usersfile'
            MyError.name = 'Error in writing usersfile'
            MyError.line = info
        return sheet
    
    def _fetch_sheet(self):
        """ Load the users file, makes a default sheet when the load fails."""
        try:
            f = open(self.USERSFILE,'r')
            sheet = pickle.load(f)
            f.close()
        except (IOError,EOFError):
            utils.trace_error()
            print >> sys.stderr,'Error in fetching users file, using bogus sheet'
            return self._make_default_sheet()
        return sheet

    def _put_sheet(self):
        """ Saves the users file to disk, prints error when it fails but continue anyway"""
        try:
            f = open(self.USERSFILE,'w')
            pickle.dump(self.users_sheet,f)
            f.close()
        except IOError,info:
            trace_error()
            print >> sys.stderr,'Error in writing usersfile'
            MyError.name = 'Error in writing usersfile'
            MyError.line = info
    

    def __str__(self):
        """Must return the original, not translated, title of this game.
        It's needed by the high score class of childsplay."""        
        return "Multitable"
        
    ########### methods used for the first level ###############    
    def _make_sidebar(self):
        # make sure we don't have clocks running
        self.__del__()
        Misc.actives.empty()
        objs = []
        border_rect = pygame.Rect(10,50,150,360)
        Img.screen.fill(BLACK,border_rect.inflate(4,4))
        pygame.draw.rect(Img.screen,GREEN,border_rect,1)
        text = _("Pick a table")
        c = utils.char2surf(text,32,YELLOW)
        Img.screen.blit(c,(12,12))
        pygame.display.update()
        fontsize = 48
        for i in range(1,11):
            time = '00:00'
            img = utils.char2surf("X%d" % i,fontsize,GREEN)
            if self.user_data[str(i)][0]:
                col = 'green'
                time = self.user_data[str(i)][1]
            else:
                col = 'red'
            obj = TableButton(img,"%d" % i,col,time)
            Misc.actives.add(obj)
            objs.insert(0,obj)
        for y in range(60,400,70):
            for x in range(20,140,70):
                obj = objs.pop()
                obj.set_position((x,y))
        # here we check if we display a 'goto level2' arrow.
        print "user_data",self.user_data['level1']
        if self.user_data['level1']:
            im = utils.load_image(os.path.join\
                    (self.libdir,'MultiTablesData','levelarrow.gif'),1)
            t = _("Second level")
            s = utils.char2surf(t,24,RED)
            im.blit(s,(8,20))
            self.levelarrow = LevelArrow(im,(600,400),('levelarrow','foobar'))
            Misc.actives.add(self.levelarrow)
        Misc.actives.refresh()
        
    def start_table(self,t):
        # make sure we don't have clocks running
        self.__del__()
        self.clock = Timer.Clock(start='00:00',
                            end='05:00',
                            counting=1,
                            clockpos=(4,460),
                            clockcolor=BLUE,
                            text=_("How fast are you?"),
                            textsize=28,
                            textcolor=BLUE)
        r = self.screen.blit(self.backgr,(240,40),(240,40,800,500))
    
        n,self.table_but = t[0],t[1]
        self.start_pos_arrow = (250,80)
        self.arrow.reset_position(self.start_pos_arrow)
        fontsize = 28
        self.exercise_objs = []
        text = _("Use the 'Enter' key to go to the next exercise.")
        c = utils.char2surf(text,fontsize,YELLOW)
        Img.screen.blit(c,(200,12))
        text = _("Backspace or Delete key will remove your input")
        c = utils.char2surf(text,fontsize,YELLOW)
        Img.screen.blit(c,(200,40))
        pygame.display.update()
        x =300
        for i in range(1,11):
            obj = Exercise("%d X %s = %d" % (i,n,i*int(n)),n,pos=(x,i*40+40))
            obj.display_sprite()
            self.exercise_objs.append(obj)
        self.current_exercise = 0
        self.arrow.display_sprite()
        if self.levelarrow:
            self.levelarrow.display_sprite()
        Misc.actives.add(self.arrow)
        self.clock.start_clock()
        
    def check_tables_finished(self):
        print "check_tables_finished",self.user_data
        exercises = range(1,11)
        for key in range(1,11):
            if self.user_data[str(key)][0]:
                pass
            else:
                # if we reach this not all keys are set true (not all tables are done)
                return
        self.user_data['level1'] = True
        self.users_sheet[self.user_name] = self.user_data
        self._put_sheet()
        # rebuild sidebar which also start the second level arrow
        self._make_sidebar()
        
    ############# end first level ######################
    
    ############## second level #####################
    def start_random_exercises(self,n,pos=(300,200)):
        """ n is the number of exercises"""
        
        if n > 100:
            n = 100
        if n <= 50:
            step = 2
        else:
            step = 1
        self.number_of_exercises = n
        ##### test code
        #self._offer_diploma('01:30')
        #return
        ################
        pbar = utils.ProgressBar(start=0,
                                end=100,
                                step=step,
                                header=_("Starting exercises..."))
        self.exercise_objs = []
        exercise_list = []
        for a in range(1,11):
            for b in range(1,11):
                exercise_list.append("%d X %s = %d" % (a,b,a*b))
        random.shuffle(exercise_list)
        for i in range(n):
            self.exercise_objs.append(Exercise(exercise_list.pop(),
                                        i,
                                        pos=pos,
                                        fontsize=64))
            pbar.update()
            pygame.display.update(self.screen.blit(pbar.get_bar(),(200,200)))
        pygame.display.update(self.screen.fill(BLACK,(200,200,700,400)))
        
        text = _("Use the 'Enter' key to go to the next exercise.")
        c = utils.char2surf(text,32,YELLOW)
        Img.screen.blit(c,(200,12))
        text = _("Backspace or Delete key will remove your input")
        c = utils.char2surf(text,32,YELLOW)
        Img.screen.blit(c,(200,40))
        pygame.display.update()
        
        self._make_sidebar_level2()
        
        self.current_exercise = 0 
        self.exercise_objs[self.current_exercise].display_sprite()
        # the rest of the game flow is mostly handled by check()
    
    def _make_sidebar_level2(self):
        border_rect = pygame.Rect(10,50,150,360)
        Img.screen.fill(BLACK,border_rect.inflate(4,4))
        pygame.draw.rect(Img.screen,GREEN,border_rect,1)
        pygame.display.update()
        self.clock = Timer.Clock(start='%02d:00' % int(self.rc_dic['examtime']),
                            end='00:00',
                            counting=-1,
                            clockpos=(30,110),
                            clockcolor=BLUE,
                            clocksize=48,
                            text=_("Time left:"),
                            textsize=32,
                            textcolor=BLUE,
                            alarm=self._clockalarm)
        self.exercise_counter = Counter(self.number_of_exercises,-1,pos=(12,220))
        self.exercise_counter.display_sprite()
        self.clock.start_clock()
        
    def level2_finished(self):
        print "No next level yet"
        timeleft = self.clock.get_time()        
        self.__del__()
        self.stop = -1
        self._offer_diploma(timeleft)
    
    def _offer_diploma(self,timeleft):
        # the idea is to prepare a surface with the cp logo and some text
        # like " <user> has passed the tables exam......"
        # then we save it like cp saves screenshots and from there we call
        # cups or lpr to print it. On windows we just call the image and hope
        # windows will lauch some app to show the image.
        # XXX we could also have some print dialog
        m,s = timeleft.split(':')
        # we calculate the time spend by turning everything into seconds
        exam_time = int(self.rc_dic['examtime']) * 60
        time_left = int(m) * 60 + int(s)
        time_spend = exam_time - time_left
        minutes = time_spend / 60
        seconds = time_spend % 60
        
        self.user_data['level2'] = '%s:%s' % (minutes,seconds)
        self.users_sheet[self.user_name] = self.user_data
        self._put_sheet()
        
        text = HEADER % (self.user_name,self.number_of_exercises,
                            minutes,seconds,time.asctime())
        ttfpath = os.path.join(self.cpg.childsplay_data_path,'Domestic_Manners.ttf')
        
        diplomasurf = utils.load_image(os.path.join\
                        (self.libdir,'MultiTablesData','tablesdiploma.png'),0)
        x,y,step = 50,200,20
        for line in text.split('\n'):
            s = utils.char2surf(line,18,ttf=ttfpath)
            diplomasurf.blit(s,(x,y))
            y += step
        
        path = os.path.join(os.path.expanduser(self.rc_dic['resultspath']),
                                    '%s_multiTables_diploma.BMP' % self.user_name)
        try:
            pygame.image.save(diplomasurf,path)
        except Exception,info:
            txt = _("Failled to save your diploma to %s") % path
            print txt
            print info
        else:
            txt = _("Saved your diploma to %s") % path
            print txt
        self.screen.fill(BLACK)
        self.screen.blit(utils.char2surf(txt,24,fcol=GREEN,ttf=ttfpath),(10,4))
        self.screen.blit(diplomasurf,(20,60))
        pygame.display.update()
        
        OKbut = self.Assets_img.get_assets(('OK_but.png',))
        OKrect = self.screen.blit(OKbut,(620,420))
        pygame.display.update(OKrect)
        snd = utils.load_music(os.path.join(self.libdir,'MultiTablesData','victory.ogg'))
        snd.play(-1)
        clock = pygame.time.Clock()# prevent 'while 1' to eat all CPU cycles
        # starts a basic eventloop for the OK button
        stop = 0
        while stop == 0:
            clock.tick(40)
            pygame.event.pump()
            events = pygame.event.get()
            for event in events:
                if event.type is MOUSEBUTTONDOWN:
                    pos = pygame.Rect(pygame.mouse.get_pos() + (4,4))
                    if OKrect.contains(pos):
                        stop = 1
                        break
        snd.stop()

    def _clockalarm(self):
        """Called by the timer clock when it's finished"""
        # if this is called by the clock, the exercises are not finished in
        # time otherwise level2_finished would be called which stops the clock.
        # but make sure :-)
        if self.current_exercise > len(self.exercise_objs):
            self.level2_finished()
        self.exercise_counter.erase_sprite()
        snd = utils.load_music(os.path.join(self.libdir,'MultiTablesData','failed.ogg'))
        snd.play()
        self.screen.fill(BLACK)
        txt = _("Sorry, you failed the exam :-(")
        self.screen.blit(utils.char2surf(txt,48,fcol=RED),(60,200))
        pygame.display.update()
        
        pygame.time.wait(10000)
        self.stop = -1
        
    ############## end second level #################
    
    
    ############ used by all levels ##################
    def show_input(self,char):
        #print "input",char, "ord",ord(char)
        obj = self.exercise_objs[self.current_exercise]
        if ord(char) == 13:# hit enter
            self.check()
            return
        elif ord(char) in (8,127):
            obj.remove_solution()
            return
        obj.set_solution(char)
    
    def check(self):
        # check is responsible for a lot of things
        # To grok the game-flow check this thing
        obj = self.exercise_objs[self.current_exercise]
        if obj.check_solution():
            Snd.correct.play()
            if self.levels == 1:
                self.arrow.erase_sprite()
                status_icon = StatusIcon((16,16),col='green')
                pos = self.arrow.get_position()
                pos = (pos[0]+12,pos[1]+12)
                status_icon.set_position(pos)
                status_icon.display_sprite()
                self.arrow.set_position((0,40))
                self.arrow.display_sprite()
                self.current_exercise += 1
            else:
                obj.erase_sprite()
                self.current_exercise += 1
                # displays the next exercise
                try:
                    self.exercise_objs[self.current_exercise].display_sprite()
                except IndexError:
                    self.level2_finished()
                else:
                    self.exercise_counter.update()
            # here we do checks when the user reaches the 10xn (level 1 only)
            if self.levels == 1 and self.current_exercise == 10:
                self.clock.stop_clock()
                Snd.wahoo.play()
                # check if we improve our time.
                oldtime = self.user_data[self.table_but._name][1]
                if oldtime == '00:00':
                    self.table_but.status_icon.set_status('green',self.clock.get_time())
                else:
                    newtime = self.clock.get_time()
                    n_m,n_s = newtime.split(':')
                    o_m,o_s = oldtime.split(':')
                    if int(n_m) < int(o_m) or (int(n_m) == int(o_m) and int(n_s) < int(o_s)):
                        self.table_but.status_icon.set_status('green',newtime)
                self.table_but.status_icon.display_sprite()
                self.arrow.erase_sprite()
                self.user_data[self.table_but._name] = (True,self.clock.get_time())
                self.users_sheet[self.user_name] = self.user_data
                self._put_sheet()
                if not self.user_data['level1']:
                    self.check_tables_finished()
        else:
            Snd.bummer.play()
            if 0 < self.levels < 3:
                obj.remove_solution()
    
        
    def helptitle(self):
        return _("Multitable")
    
    def help(self):
        text = [_("The aim of the game:"),
        _("Learning the multiplication tables."),
        _("The game consist of two levels. The first level holds the tables 1 till 10."),
        _("You can click on the right hand buttons to select the table you wich to exercise."),
        _("You must finish all the tables before you can go to the second level"),
        _("The second level is a multiplication tables exam where you have to finish 50 exercises within 8 minutes."),
        _("The values of the exam can be changed in the config file."),
        " ",
        _("Difficulty : 6-9 years"),
        " ",
        _("Number of levels : 2")]
        return text

    def loop(self,events):
        """events is a copy of the current pygame event queue"""
        item,self.score,v = None,0,None
        for event in events:
            if event.type is MOUSEBUTTONDOWN:
                item=event
                break
            elif event.type is KEYDOWN:
                try:
                    #print "input",event.unicode, "ord",ord(event.unicode)
                    c = ord(event.unicode)
                except Exception,info:
                    print info
                    break
                else:
                    if c in (8,13,127) or 47 < c < 58:
                        self.show_input(event.unicode)
        try:
            # this calls the sprites update method
            # and a call to pygame.display.update
            v = Misc.actives.update(item)
            # check the return val from a callback or on_update method
            # for the format see the reference
            if v:
                #print "return from actives",v
                self.score = 0
                if v[0][1][0] == 'levelarrow':
                    self.__del__()
                    self.stop = -1
                else:
                    self.start_table(v[0][1])
        except:
            print utils.trace_error()
            raise utils.MyError
        return self.stop,self.score
        
