def __init__(self, actr=False):
            self.actr = actr
            if ACTR6 and self.actr:
                self.state = self.STATE_WAIT_CONNECT
                self.actr = JNI_Server(self, clock=Twisted_MPClock())
                self.actr.addDispatcher(self.d)
                print "Waiting for connection fron JNI module"
                reactor.listenTCP(5555, self.actr)

            self.lc1 = LoopingCall(self.update_env)
            self.lc1.start(1.0 / 30)
    def __init__(self, actr=False):

        self.screen_rect = pygame.Rect(0, 0, 350, 350)
        self.screen = pygame.display.set_mode(
            (self.screen_rect.width, self.screen_rect.height), 0)

        self.grid_color = (128, 128, 128)
        self.max_font_size = int(
            min([self.screen_rect.width, self.screen_rect.height]) / 4)

        self.font = pygame.font.Font(pygame.font.match_font("Monospace", True),
                                     self.max_font_size / 5)
        self.spinner = ['|', '|', '/', '/', '-', '-', '\\', '\\']
        self.spinner_index = 0

        self.intro_t = self.font.render("Click the red 'X' to start!", True,
                                        (0, 0, 0))
        self.intro_ts = self.intro_t.get_rect()
        self.intro_ts.center = self.screen_rect.center
        self.intro_x = self.font.render("X", True, (255, 0, 0))
        self.intro_xs = self.intro_x.get_rect()
        self.intro_xs.center = (randint(0, self.screen_rect.width),
                                randint(0, self.screen_rect.height))
        while not self.screen_rect.contains(
                self.intro_xs) or self.intro_ts.colliderect(self.intro_xs):
            self.intro_xs.center = (randint(0, self.screen_rect.width),
                                    randint(0, self.screen_rect.height))

        self.snd_correct = pygame.mixer.Sound("beep-3.wav")
        self.snd_incorrect = pygame.mixer.Sound("beep-5.wav")

        self.trial = 0
        self.fake_cursor = self.screen_rect.center

        self.state = self.STATE_INTRO
        self.actr = actr
        self.actr_time_lock = False
        if ACTR6 and self.actr:
            self.state = self.STATE_WAIT_CONNECT
            self.actr = JNI_Server(self, clock=Twisted_MPClock())
            self.actr.addDispatcher(self.d)
            reactor.listenTCP(5555, self.actr)

        self.lc1 = LoopingCall(self.update_env)
        self.lc1.start(1.0 / 30)

        self.coop = Cooperator()
        self.coop.coiterate(self.process_event())
        def __init__(self, actr = False):
            self.actr = actr
            if ACTR6 and self.actr:
                self.state = self.STATE_WAIT_CONNECT
                self.actr = JNI_Server(self, clock=Twisted_MPClock())
                self.actr.addDispatcher(self.d)
                print "Waiting for connection fron JNI module"
                reactor.listenTCP(5555, self.actr)

            self.lc1 = LoopingCall(self.update_env)
            self.lc1.start(1.0 / 30)
    def __init__(self, actr=False):

        self.screen_rect = pygame.Rect(0, 0, 350, 350)
        self.screen = pygame.display.set_mode((self.screen_rect.width, self.screen_rect.height), 0)

        self.grid_color = (128, 128, 128)
        self.max_font_size = int(min([self.screen_rect.width, self.screen_rect.height]) / 4)

        self.font = pygame.font.Font(pygame.font.match_font("Monospace", True), self.max_font_size / 5)
        self.spinner = ['|', '|', '/', '/', '-', '-', '\\', '\\']
        self.spinner_index = 0
        
        self.intro_t = self.font.render("Click the red 'X' to start!", True, (0, 0, 0))
        self.intro_ts = self.intro_t.get_rect()
        self.intro_ts.center = self.screen_rect.center
        self.intro_x = self.font.render("X", True, (255, 0, 0))
        self.intro_xs = self.intro_x.get_rect()
        self.intro_xs.center = (randint(0, self.screen_rect.width), randint(0, self.screen_rect.height))
        while not self.screen_rect.contains(self.intro_xs) or self.intro_ts.colliderect(self.intro_xs):
            self.intro_xs.center = (randint(0, self.screen_rect.width), randint(0, self.screen_rect.height))

        self.snd_correct = pygame.mixer.Sound("beep-3.wav")
        self.snd_incorrect = pygame.mixer.Sound("beep-5.wav")

        self.trial = 0
        self.fake_cursor = self.screen_rect.center

        self.state = self.STATE_INTRO
        self.actr = actr
        self.actr_time_lock = False
        if ACTR6 and self.actr:
            self.state = self.STATE_WAIT_CONNECT
            self.actr = JNI_Server(self, clock=Twisted_MPClock())
            self.actr.addDispatcher(self.d)
            reactor.listenTCP(5555, self.actr)

        self.lc1 = LoopingCall(self.update_env)
        self.lc1.start(1.0 / 30)

        self.coop = Cooperator()
        self.coop.coiterate(self.process_event())
class Environment(object):
    if ACTR6:
        d = Dispatcher()

        # A bunch of states for Environment
        STATE_WAIT_CONNECT = -3
        STATE_WAIT_MODEL = -2
        STATE_INTRO = -1
        STATE_RESET = 0
        STATE_FIXATION = 1
        STATE_UPDATE = 2
        STATE_SEARCH = 3
        STATE_DONE = 4
        
        '''
            Initiate environment
        '''
        def __init__(self, actr = False):
            self.actr = actr
            if ACTR6 and self.actr:
                self.state = self.STATE_WAIT_CONNECT
                self.actr = JNI_Server(self, clock=Twisted_MPClock())
                self.actr.addDispatcher(self.d)
                print "Waiting for connection fron JNI module"
                reactor.listenTCP(5555, self.actr)

            self.lc1 = LoopingCall(self.update_env)
            self.lc1.start(1.0 / 30)

        def reset(self):
            pass

        def validate(self):
            pass

        def update(self):
            pass

        def handle_key_press(self, key, code):
            print "key"

        def update_env(self):
            pass

        def process_event(self):
            pass
        

        def setDefaultClock(self):
            self.lc1.stop()
            self.lc1.clock = reactor
            self.lc1.start(1.0 / 30)
            print "Clock reset"

        '''
            Handling ACTR request
        '''
        if ACTR6:

            @d.listen('connectionMade')
            def ACTR6_JNI_Event(self, model, params):
                self.state = self.STATE_WAIT_MODEL
                print "Connection has been made"

            @d.listen('connectionLost')
            def ACTR6_JNI_Event(self, model, params):
                self.setDefaultClock()
                self.state = self.STATE_WAIT_CONNECT

            @d.listen('reset')
            def ACTR6_JNI_Event(self, model, params):
                self.actr_time_lock = params['time-lock']
                self.setDefaultClock()
                self.state = self.STATE_WAIT_MODEL
                
            @d.listen('model-run')
            def ACTR6_JNI_Event(self, model, params):
                pass

            @d.listen('model-stop')
            def ACTR6_JNI_Event(self, model, params):
                pass

            @d.listen('keypress')
            def ACTR6_JNI_Event(self, model, params):
                self.handle_key_press(params['keycode'], chr(params['keycode']))

            @d.listen('mousemotion')
            def ACTR6_JNI_Event(self, model, params):
                pass

            @d.listen('mouseclick')
            def ACTR6_JNI_Event(self, model, params):
                pass
class Environment(object):
    if ACTR6:
        d = Dispatcher()

        # A bunch of states for Environment
        STATE_WAIT_CONNECT = -3
        STATE_WAIT_MODEL = -2
        STATE_INTRO = -1
        STATE_RESET = 0
        STATE_FIXATION = 1
        STATE_UPDATE = 2
        STATE_SEARCH = 3
        STATE_DONE = 4
        '''
            Initiate environment
        '''
        def __init__(self, actr=False):
            self.actr = actr
            if ACTR6 and self.actr:
                self.state = self.STATE_WAIT_CONNECT
                self.actr = JNI_Server(self, clock=Twisted_MPClock())
                self.actr.addDispatcher(self.d)
                print "Waiting for connection fron JNI module"
                reactor.listenTCP(5555, self.actr)

            self.lc1 = LoopingCall(self.update_env)
            self.lc1.start(1.0 / 30)

        def reset(self):
            pass

        def validate(self):
            pass

        def update(self):
            pass

        def handle_key_press(self, key, code):
            print "key"

        def update_env(self):
            pass

        def process_event(self):
            pass

        def setDefaultClock(self):
            self.lc1.stop()
            self.lc1.clock = reactor
            self.lc1.start(1.0 / 30)
            print "Clock reset"

        '''
            Handling ACTR request
        '''
        if ACTR6:

            @d.listen('connectionMade')
            def ACTR6_JNI_Event(self, model, params):
                self.state = self.STATE_WAIT_MODEL
                print "Connection has been made"

            @d.listen('connectionLost')
            def ACTR6_JNI_Event(self, model, params):
                self.setDefaultClock()
                self.state = self.STATE_WAIT_CONNECT

            @d.listen('reset')
            def ACTR6_JNI_Event(self, model, params):
                self.actr_time_lock = params['time-lock']
                self.setDefaultClock()
                self.state = self.STATE_WAIT_MODEL

            @d.listen('model-run')
            def ACTR6_JNI_Event(self, model, params):
                pass

            @d.listen('model-stop')
            def ACTR6_JNI_Event(self, model, params):
                pass

            @d.listen('keypress')
            def ACTR6_JNI_Event(self, model, params):
                self.handle_key_press(params['keycode'],
                                      chr(params['keycode']))

            @d.listen('mousemotion')
            def ACTR6_JNI_Event(self, model, params):
                pass

            @d.listen('mouseclick')
            def ACTR6_JNI_Event(self, model, params):
                pass
class Environment(object):

    if ACTR6:
        d = Dispatcher()

    STATE_WAIT_CONNECT = -3
    STATE_WAIT_MODEL = -2
    STATE_INTRO = -1
    STATE_RESET = 0
    STATE_FIXATION = 1
    STATE_UPDATE = 2
    STATE_SEARCH = 3
    STATE_DONE = 4

    colors = {':white': (255, 255, 255), ':black': (0, 0, 0)}

    def __init__(self, actr=False):

        self.screen_rect = pygame.Rect(0, 0, 350, 350)
        self.screen = pygame.display.set_mode(
            (self.screen_rect.width, self.screen_rect.height), 0)

        self.grid_color = (128, 128, 128)
        self.max_font_size = int(
            min([self.screen_rect.width, self.screen_rect.height]) / 4)

        self.font = pygame.font.Font(pygame.font.match_font("Monospace", True),
                                     self.max_font_size / 5)
        self.spinner = ['|', '|', '/', '/', '-', '-', '\\', '\\']
        self.spinner_index = 0

        self.intro_t = self.font.render("Click the red 'X' to start!", True,
                                        (0, 0, 0))
        self.intro_ts = self.intro_t.get_rect()
        self.intro_ts.center = self.screen_rect.center
        self.intro_x = self.font.render("X", True, (255, 0, 0))
        self.intro_xs = self.intro_x.get_rect()
        self.intro_xs.center = (randint(0, self.screen_rect.width),
                                randint(0, self.screen_rect.height))
        while not self.screen_rect.contains(
                self.intro_xs) or self.intro_ts.colliderect(self.intro_xs):
            self.intro_xs.center = (randint(0, self.screen_rect.width),
                                    randint(0, self.screen_rect.height))

        self.snd_correct = pygame.mixer.Sound("beep-3.wav")
        self.snd_incorrect = pygame.mixer.Sound("beep-5.wav")

        self.trial = 0
        self.fake_cursor = self.screen_rect.center

        self.state = self.STATE_INTRO
        self.actr = actr
        self.actr_time_lock = False
        if ACTR6 and self.actr:
            self.state = self.STATE_WAIT_CONNECT
            self.actr = JNI_Server(self, clock=Twisted_MPClock())
            self.actr.addDispatcher(self.d)
            reactor.listenTCP(5555, self.actr)

        self.lc1 = LoopingCall(self.update_env)
        self.lc1.start(1.0 / 30)

        self.coop = Cooperator()
        self.coop.coiterate(self.process_event())

    def reset(self):
        self.trial += 1
        self.intro_xs.center = (randint(0, self.screen_rect.width),
                                randint(0, self.screen_rect.height))
        while not self.screen_rect.contains(
                self.intro_xs) or self.intro_ts.colliderect(self.intro_xs):
            self.intro_xs.center = (randint(0, self.screen_rect.width),
                                    randint(0, self.screen_rect.height))
        self.start = sample([1, 0, 0, 0], 4)
        colors = sample([":red", ":blue"], 2)
        self.letters = sample(string.ascii_uppercase, 4)
        self.objects = [
            Letter(self.letters[i], i + 1, self.start[i], colors,
                   self.max_font_size) for i in range(0, len(self.letters))
        ]
        self.clockwise = choice([True, False])
        if self.clockwise:
            self.bgcolorname = ':black'
        else:
            self.bgcolorname = ':white'
        self.bgcolor = self.colors[self.bgcolorname]
        start = self.start.index(True)
        if self.clockwise:
            self.answer = [self.letters[(start + i) % 4] for i in range(0, 4)]
        else:
            self.answer = [self.letters[(start - i) % 4] for i in range(0, 4)]
        self.response = []

    def validate(self):
        if self.answer == self.response:
            self.snd_correct.play()
            if self.actr:
                self.actr.tone_sound(1320, .25)
        else:
            self.snd_incorrect.play()
            if self.actr:
                self.actr.tone_sound(440, .25)
        self.state = self.STATE_DONE

    def update_objects(self):
        for i in range(0, len(self.objects)):
            if self.objects[i].quad == 1 or self.objects[i].quad == 2:
                basey = self.screen_rect.height / 4
            else:
                basey = self.screen_rect.height / 4 * 3
            if self.objects[i].quad == 1 or self.objects[i].quad == 4:
                basex = self.screen_rect.width / 4
            else:
                basex = self.screen_rect.width / 4 * 3
            self.objects[i].rect.centerx = randint(
                basex - self.screen_rect.width / 8,
                basex + self.screen_rect.width / 8)
            self.objects[i].rect.centery = randint(
                basey - self.screen_rect.height / 8,
                basey + self.screen_rect.height / 8)

    def draw_intro(self):
        self.screen.fill((128, 128, 128))
        self.screen.blit(self.intro_t, self.intro_ts)
        self.screen.blit(self.intro_x, self.intro_xs)
        pygame.display.flip()

    def draw_actr_wait_connect(self):
        self.screen.fill((255, 0, 0))
        f = self.font.render("Waiting for ACT-R to connect", True, (0, 0, 0))
        fs = f.get_rect()
        fs.midbottom = self.screen_rect.center
        self.screen.blit(f, fs)
        f = self.font.render(self.spinner[self.spinner_index], True, (0, 0, 0))
        fs = f.get_rect()
        fs.midtop = self.screen_rect.center
        self.screen.blit(f, fs)
        self.spinner_index = (self.spinner_index + 1) % 8
        pygame.display.flip()

    def draw_actr_wait_model(self):
        self.screen.fill((0, 255, 0))
        f = self.font.render("Waiting for ACT-R model", True, (0, 0, 0))
        fs = f.get_rect()
        fs.midbottom = self.screen_rect.center
        self.screen.blit(f, fs)
        f = self.font.render(self.spinner[self.spinner_index], True, (0, 0, 0))
        fs = f.get_rect()
        fs.midtop = self.screen_rect.center
        self.screen.blit(f, fs)
        self.spinner_index = (self.spinner_index + 1) % 8
        pygame.display.flip()

    def draw_fixation(self):
        self.screen.fill(self.bgcolor)
        pygame.draw.line(
            self.screen, self.grid_color,
            (self.screen_rect.centerx - 10, self.screen_rect.centery),
            (self.screen_rect.centerx + 10, self.screen_rect.centery), 1)
        pygame.draw.line(
            self.screen, self.grid_color,
            (self.screen_rect.centerx, self.screen_rect.centery - 10),
            (self.screen_rect.centerx, self.screen_rect.centery + 10), 1)
        pygame.display.flip()

    def draw_search(self):
        self.screen.fill(self.bgcolor)
        pygame.draw.line(self.screen, self.grid_color, self.screen_rect.midtop,
                         self.screen_rect.midbottom, 1)
        pygame.draw.line(self.screen, self.grid_color,
                         self.screen_rect.midleft, self.screen_rect.midright,
                         1)
        for o in self.objects:
            self.screen.blit(o.surf, o.rect)
        pygame.display.flip()

    def update_env(self):
        if self.state == self.STATE_WAIT_CONNECT:
            self.draw_actr_wait_connect()
        if self.state == self.STATE_WAIT_MODEL:
            self.draw_actr_wait_model()
        if self.state == self.STATE_INTRO:
            self.draw_intro()
        if self.state == self.STATE_RESET:
            self.reset()
            self.state = self.STATE_FIXATION
            if self.actr:
                fix = VisualChunk("f%d" % self.trial, "fixation-cross",
                                  self.screen_rect.centerx,
                                  self.screen_rect.centery)
                self.actr.update_display([fix], clear=True)
        if self.state == self.STATE_UPDATE:
            self.update_objects()
            self.state = self.STATE_SEARCH
            if self.actr:
                chunks = [obj.toChunk() for obj in self.objects]
                chunks.append(
                    VisualChunk(None, "background", self.screen_rect.centerx,
                                self.screen_rect.centery,
                                self.screen_rect.width,
                                self.screen_rect.height, self.bgcolorname))
                self.actr.update_display(chunks, clear=True)
        if self.state == self.STATE_FIXATION:
            self.draw_fixation()
        elif self.state == self.STATE_SEARCH:
            self.draw_search()

    def handle_mouse_event(self, pos):
        if self.state == self.STATE_INTRO:
            if self.intro_xs.collidepoint(pos):
                self.state = self.STATE_RESET

    def handle_key_press(self, key, code):
        if key == pygame.K_ESCAPE:
            reactor.stop()
        elif key == pygame.K_SPACE:
            if self.state == self.STATE_FIXATION:
                self.state = self.STATE_UPDATE
            elif self.state == self.STATE_DONE:
                self.state = self.STATE_RESET
        elif key >= pygame.K_a and key <= pygame.K_z:
            if self.state == self.STATE_SEARCH:
                self.response.append(str.upper(str(code)))
                if len(self.response) == 4:
                    self.validate()

    def process_event(self):
        while True:
            for e in pygame.event.get():
                if e.type == pygame.KEYDOWN:
                    self.handle_key_press(e.key, e.unicode)
                elif e.type == pygame.MOUSEBUTTONDOWN:
                    self.handle_mouse_event(e.pos)
            yield

    def setDefaultClock(self):
        self.lc1.stop()
        self.lc1.clock = reactor
        self.lc1.start(1.0 / 30)

    if ACTR6:

        @d.listen('connectionMade')
        def ACTR6_JNI_Event(self, model, params):
            self.state = self.STATE_WAIT_MODEL
            self.actr.setup(self.screen_rect.width, self.screen_rect.height)

        @d.listen('connectionLost')
        def ACTR6_JNI_Event(self, model, params):
            self.setDefaultClock()
            self.state = self.STATE_WAIT_CONNECT

        @d.listen('reset')
        def ACTR6_JNI_Event(self, model, params):
            self.actr_time_lock = params['time-lock']
            self.setDefaultClock()
            self.state = self.STATE_WAIT_MODEL

        @d.listen('model-run')
        def ACTR6_JNI_Event(self, model, params):
            if not params['resume']:
                self.state = self.STATE_INTRO
                X = VisualChunk(None,
                                "letterobj",
                                self.intro_xs.centerx,
                                self.intro_xs.centery,
                                color=":red")
                self.actr.update_display([X], clear=True)
                self.actr_running = True
            if self.actr_time_lock:
                self.lc1.stop()
                self.lc1.clock = self.actr.clock
                self.lc1.start(1.0 / 30)

        @d.listen('model-stop')
        def ACTR6_JNI_Event(self, model, params):
            pass

        @d.listen('keypress')
        def ACTR6_JNI_Event(self, model, params):
            self.handle_key_press(params['keycode'], chr(params['keycode']))

        @d.listen('mousemotion')
        def ACTR6_JNI_Event(self, model, params):
            # Store "ACT-R" cursor in variable since we are
            # not going to move the real mouse
            self.fake_cursor = params['loc']

        @d.listen('mouseclick')
        def ACTR6_JNI_Event(self, model, params):
            # Simulate a button press using the "ACT-R" cursor loc
            self.handle_mouse_event(self.fake_cursor)
class Environment(object):
    
    if ACTR6:
        d = Dispatcher()

    STATE_WAIT_CONNECT = -3
    STATE_WAIT_MODEL = -2
    STATE_INTRO = -1
    STATE_RESET = 0
    STATE_FIXATION = 1
    STATE_UPDATE = 2
    STATE_SEARCH = 3
    STATE_DONE = 4

    colors = {':white':(255, 255, 255), ':black':(0, 0, 0)}

    def __init__(self, actr=False):

        self.screen_rect = pygame.Rect(0, 0, 350, 350)
        self.screen = pygame.display.set_mode((self.screen_rect.width, self.screen_rect.height), 0)

        self.grid_color = (128, 128, 128)
        self.max_font_size = int(min([self.screen_rect.width, self.screen_rect.height]) / 4)

        self.font = pygame.font.Font(pygame.font.match_font("Monospace", True), self.max_font_size / 5)
        self.spinner = ['|', '|', '/', '/', '-', '-', '\\', '\\']
        self.spinner_index = 0
        
        self.intro_t = self.font.render("Click the red 'X' to start!", True, (0, 0, 0))
        self.intro_ts = self.intro_t.get_rect()
        self.intro_ts.center = self.screen_rect.center
        self.intro_x = self.font.render("X", True, (255, 0, 0))
        self.intro_xs = self.intro_x.get_rect()
        self.intro_xs.center = (randint(0, self.screen_rect.width), randint(0, self.screen_rect.height))
        while not self.screen_rect.contains(self.intro_xs) or self.intro_ts.colliderect(self.intro_xs):
            self.intro_xs.center = (randint(0, self.screen_rect.width), randint(0, self.screen_rect.height))

        self.snd_correct = pygame.mixer.Sound("beep-3.wav")
        self.snd_incorrect = pygame.mixer.Sound("beep-5.wav")

        self.trial = 0
        self.fake_cursor = self.screen_rect.center

        self.state = self.STATE_INTRO
        self.actr = actr
        self.actr_time_lock = False
        if ACTR6 and self.actr:
            self.state = self.STATE_WAIT_CONNECT
            self.actr = JNI_Server(self, clock=Twisted_MPClock())
            self.actr.addDispatcher(self.d)
            reactor.listenTCP(5555, self.actr)

        self.lc1 = LoopingCall(self.update_env)
        self.lc1.start(1.0 / 30)

        self.coop = Cooperator()
        self.coop.coiterate(self.process_event())

    def reset(self):
        self.trial += 1
        self.intro_xs.center = (randint(0, self.screen_rect.width), randint(0, self.screen_rect.height))
        while not self.screen_rect.contains(self.intro_xs) or self.intro_ts.colliderect(self.intro_xs):
            self.intro_xs.center = (randint(0, self.screen_rect.width), randint(0, self.screen_rect.height))
        self.start = sample([1, 0, 0, 0], 4)
        colors = sample([":red", ":blue"], 2)
        self.letters = sample(string.ascii_uppercase, 4)
        self.objects = [Letter(self.letters[i], i + 1, self.start[i], colors, self.max_font_size) for i in range(0, len(self.letters))]
        self.clockwise = choice([True, False])
        if self.clockwise:
            self.bgcolorname = ':black'
        else:
            self.bgcolorname = ':white'
        self.bgcolor = self.colors[self.bgcolorname]
        start = self.start.index(True)
        if self.clockwise:
            self.answer = [self.letters[(start + i) % 4] for i in range(0, 4)]
        else:
            self.answer = [self.letters[(start - i) % 4]  for i in range(0, 4)]
        self.response = []

    def validate(self):
        if self.answer == self.response:
            self.snd_correct.play()
            if self.actr:
                self.actr.tone_sound(1320, .25)
        else:
            self.snd_incorrect.play()
            if self.actr:
                self.actr.tone_sound(440, .25)
        self.state = self.STATE_DONE

    def update_objects(self):
        for i in range(0, len(self.objects)):
            if self.objects[i].quad == 1 or self.objects[i].quad == 2:
                basey = self.screen_rect.height / 4
            else:
                basey = self.screen_rect.height / 4 * 3
            if self.objects[i].quad == 1 or self.objects[i].quad == 4:
                basex = self.screen_rect.width / 4
            else:
                basex = self.screen_rect.width / 4 * 3
            self.objects[i].rect.centerx = randint(basex - self.screen_rect.width / 8, basex + self.screen_rect.width / 8)
            self.objects[i].rect.centery = randint(basey - self.screen_rect.height / 8, basey + self.screen_rect.height / 8)

    def draw_intro(self):
        self.screen.fill((128, 128, 128))
        self.screen.blit(self.intro_t, self.intro_ts)
        self.screen.blit(self.intro_x, self.intro_xs)
        pygame.display.flip()

    def draw_actr_wait_connect(self):
        self.screen.fill((255, 0, 0))
        f = self.font.render("Waiting for ACT-R to connect", True, (0, 0, 0))
        fs = f.get_rect()
        fs.midbottom = self.screen_rect.center
        self.screen.blit(f, fs)
        f = self.font.render(self.spinner[self.spinner_index], True, (0, 0, 0))
        fs = f.get_rect()
        fs.midtop = self.screen_rect.center
        self.screen.blit(f, fs)
        self.spinner_index = (self.spinner_index + 1) % 8
        pygame.display.flip()
        
    def draw_actr_wait_model(self):
        self.screen.fill((0, 255, 0))
        f = self.font.render("Waiting for ACT-R model", True, (0, 0, 0))
        fs = f.get_rect()
        fs.midbottom = self.screen_rect.center
        self.screen.blit(f, fs)
        f = self.font.render(self.spinner[self.spinner_index], True, (0, 0, 0))
        fs = f.get_rect()
        fs.midtop = self.screen_rect.center
        self.screen.blit(f, fs)
        self.spinner_index = (self.spinner_index + 1) % 8
        pygame.display.flip()

    def draw_fixation(self):
        self.screen.fill(self.bgcolor)
        pygame.draw.line(self.screen, self.grid_color, (self.screen_rect.centerx - 10, self.screen_rect.centery), (self.screen_rect.centerx + 10, self.screen_rect.centery), 1)
        pygame.draw.line(self.screen, self.grid_color, (self.screen_rect.centerx, self.screen_rect.centery - 10), (self.screen_rect.centerx, self.screen_rect.centery + 10), 1)
        pygame.display.flip()

    def draw_search(self):
        self.screen.fill(self.bgcolor)
        pygame.draw.line(self.screen, self.grid_color, self.screen_rect.midtop, self.screen_rect.midbottom, 1)
        pygame.draw.line(self.screen, self.grid_color, self.screen_rect.midleft, self.screen_rect.midright, 1)
        for o in self.objects:
            self.screen.blit(o.surf, o.rect)
        pygame.display.flip()

    def update_env(self):
        if self.state == self.STATE_WAIT_CONNECT:
            self.draw_actr_wait_connect()
        if self.state == self.STATE_WAIT_MODEL:
            self.draw_actr_wait_model()
        if self.state == self.STATE_INTRO:
            self.draw_intro()
        if self.state == self.STATE_RESET:
            self.reset()
            self.state = self.STATE_FIXATION
            if self.actr:
                fix = VisualChunk("f%d" % self.trial, "fixation-cross", self.screen_rect.centerx, self.screen_rect.centery)
                self.actr.update_display([fix], clear=True)
        if self.state == self.STATE_UPDATE:
            self.update_objects()
            self.state = self.STATE_SEARCH
            if self.actr:
                chunks = [obj.toChunk() for obj in self.objects]
                chunks.append(VisualChunk(None, "background", self.screen_rect.centerx, self.screen_rect.centery, self.screen_rect.width, self.screen_rect.height, self.bgcolorname))
                self.actr.update_display(chunks, clear=True)
        if self.state == self.STATE_FIXATION:
            self.draw_fixation()
        elif self.state == self.STATE_SEARCH:
            self.draw_search()
            
    def handle_mouse_event(self, pos):
        if self.state == self.STATE_INTRO:
            if self.intro_xs.collidepoint(pos):
                self.state = self.STATE_RESET
                
    def handle_key_press(self, key, code):
        if key == pygame.K_ESCAPE:
            reactor.stop()
        elif key == pygame.K_SPACE:
            if self.state == self.STATE_FIXATION:
                self.state = self.STATE_UPDATE
            elif self.state == self.STATE_DONE:
                self.state = self.STATE_RESET
        elif key >= pygame.K_a and key <= pygame.K_z:
            if self.state == self.STATE_SEARCH:
                self.response.append(str.upper(str(code)))
                if len(self.response) == 4:
                    self.validate()

    def process_event(self):
        while True:
            for e in pygame.event.get():
                if e.type == pygame.KEYDOWN:
                    self.handle_key_press(e.key, e.unicode)
                elif e.type == pygame.MOUSEBUTTONDOWN:
                    self.handle_mouse_event(e.pos)
            yield

    def setDefaultClock(self):
        self.lc1.stop()
        self.lc1.clock = reactor
        self.lc1.start(1.0 / 30)

    if ACTR6:

        @d.listen('connectionMade')
        def ACTR6_JNI_Event(self, model, params):
            self.state = self.STATE_WAIT_MODEL
            self.actr.setup(self.screen_rect.width, self.screen_rect.height)

        @d.listen('connectionLost')
        def ACTR6_JNI_Event(self, model, params):
            self.setDefaultClock()
            self.state = self.STATE_WAIT_CONNECT

        @d.listen('reset')
        def ACTR6_JNI_Event(self, model, params):
            self.actr_time_lock = params['time-lock']
            self.setDefaultClock()
            self.state = self.STATE_WAIT_MODEL
            
        @d.listen('model-run')
        def ACTR6_JNI_Event(self, model, params):
            if not params['resume']:
                self.state = self.STATE_INTRO
                X = VisualChunk(None, "letterobj", self.intro_xs.centerx, self.intro_xs.centery, color=":red")
                self.actr.update_display([X], clear=True)
                self.actr_running = True
            if self.actr_time_lock:
                self.lc1.stop()
                self.lc1.clock = self.actr.clock
                self.lc1.start(1.0 / 30)

        @d.listen('model-stop')
        def ACTR6_JNI_Event(self, model, params):
            pass

        @d.listen('keypress')
        def ACTR6_JNI_Event(self, model, params):
            self.handle_key_press(params['keycode'], chr(params['keycode']))

        @d.listen('mousemotion')
        def ACTR6_JNI_Event(self, model, params):
            # Store "ACT-R" cursor in variable since we are 
            # not going to move the real mouse
            self.fake_cursor = params['loc']

        @d.listen('mouseclick')
        def ACTR6_JNI_Event(self, model, params):
            # Simulate a button press using the "ACT-R" cursor loc
            self.handle_mouse_event(self.fake_cursor)