Exemple #1
0
    def handle(self, evt_type, act):
        if evt_type == 'action_after' and isinstance(act, PrepareStage):
            src = act.target
            if not src.has_skill(LunaDial):
                return act

            PlayerTurn.get_current(src).pending_stages.insert(0, LunaDialActionStage)

        return act
Exemple #2
0
    def apply_action(self):
        tgt = self.target
        ActionStage.force_break()
        turn = PlayerTurn.get_current(tgt)
        try:
            turn.pending_stages.remove(DropCardStage)
            turn.pending_stages.remove(FinalizeStage)
        except Exception:
            pass

        return True
Exemple #3
0
    def fatetell_action(self, ft):
        if ft.succeeded:
            turn = PlayerTurn.get_current(self.target)
            try:
                turn.pending_stages.remove(DrawCardStage)
            except Exception:
                pass

            return True

        return False
Exemple #4
0
    def fatetell_action(self, ft):
        if ft.succeeded:
            turn = PlayerTurn.get_current(self.target)
            try:
                turn.pending_stages.remove(DrawCardStage)
            except Exception:
                pass

            return True

        return False
Exemple #5
0
    def apply_action(self):
        tgt = self.target
        ActionStage.force_break()
        turn = PlayerTurn.get_current(tgt)
        try:
            turn.pending_stages.remove(DropCardStage)
            turn.pending_stages.remove(FinalizeStage)
        except Exception:
            pass

        return True
Exemple #6
0
    def apply_action(self):
        src = self.source

        g = Game.getgame()
        g.process_action(DrawCards(src, 1))

        turn = PlayerTurn.get_current(src)
        try:
            turn.pending_stages.remove(DropCardStage)
        except Exception:
            pass

        return True
Exemple #7
0
    def apply_action(self):
        src = self.source

        g = Game.getgame()
        g.process_action(DrawCards(src, 1))

        turn = PlayerTurn.get_current(src)
        try:
            turn.pending_stages.remove(DropCardStage)
        except Exception:
            pass

        return True
Exemple #8
0
    def handle(self, evt_type, arg):
        if evt_type == 'card_migration':
            act, cards, _from, to, _ = arg
            if isinstance(act, (DistributeCards, DrawCardStage)):
                return arg

            if to is None or not to.owner:
                return arg

            if to.type not in ('cards', 'showncards', 'equips'):
                return arg

            if _from is not None and _from.owner is to.owner:
                return arg

            g = Game.getgame()
            a, b = g.players

            if not a.has_skill(SanaeFaithKOF):
                a, b = b, a

            if not a.has_skill(SanaeFaithKOF):
                return arg

            if b is not to.owner:
                return arg

            turn = PlayerTurn.get_current()
            if not turn:
                return arg

            stage = turn.current_stage
            if stage.target is not b or not isinstance(stage, ActionStage):
                return arg

            g = Game.getgame()

            g.process_action(SanaeFaithKOFDrawCards(a, 1))

        return arg
Exemple #9
0
    def handle(self, evt_type, arg):
        if evt_type == 'card_migration':
            act, cards, _from, to, _ = arg
            if isinstance(act, (DistributeCards, DrawCardStage)):
                return arg

            if to is None or not to.owner:
                return arg

            if to.type not in ('cards', 'showncards', 'equips'):
                return arg

            if _from is not None and _from.owner is to.owner:
                return arg

            g = Game.getgame()
            a, b = g.players

            if not a.has_skill(SanaeFaithKOF):
                a, b = b, a

            if not a.has_skill(SanaeFaithKOF):
                return arg

            if b is not to.owner:
                return arg

            stage = PlayerTurn.get_current().current_stage
            if stage.target is not b or not isinstance(stage, ActionStage):
                return arg

            g = Game.getgame()

            g.process_action(SanaeFaithKOFDrawCards(a, 1))

        return arg
Exemple #10
0
    def apply_action(self):
        g = Game.getgame()
        params = self.params

        from cards import Deck

        g.deck = Deck()
        g.ehclasses = []

        g.double_curtain = params['double_curtain']

        if g.double_curtain:
            g.identities = g.identities[1:] + g.identities[-1:]

        # choose girls init -->
        from .characters import get_characters
        chars = get_characters(*g.character_categories)
        from .characters.akari import Akari

        # ANCHOR(test)
        testing = list(settings.TESTING_CHARACTERS)
        testing = filter_out(chars, lambda c: c.__name__ in testing)

        def choosed(char):
            try:
                chars.remove(char)
            except:
                pass

            try:
                testing.remove(char)
            except:
                pass

        def random_char():
            return g.random.choice(testing + chars)

        # choose boss
        candidates = g.random.sample(chars, 4)
        candidates.extend(testing)

        if Game.CLIENT_SIDE:
            candidates = [None] * len(candidates)

        idx = sync_primitive(g.random.randrange(len(g.players)), g.players)
        boss = g.boss = g.players[idx]

        boss.identity = Identity()
        boss.identity.type = Identity.TYPE.BOSS

        g.process_action(RevealIdentity(boss, g.players))

        boss.choices = [CharChoice(c) for c in candidates]
        boss.choices.append(CharChoice(Akari))
        boss.reveal(boss.choices)

        mapping = {boss: boss.choices}
        with InputTransaction('ChooseGirl', [boss], mapping=mapping) as trans:
            c = user_input([boss], ChooseGirlInputlet(g, mapping), 30,
                           'single', trans)

            c = c or boss.choices[-1]
            c.chosen = boss
            g.players.reveal(c)
            trans.notify('girl_chosen', (boss, c))

            if c.char_cls is Akari:
                c = CharChoice(random_char())
                g.players.reveal(c)

            choosed(c.char_cls)

            # mix it in advance
            # so the others could see it

            boss = g.switch_character(boss, c.char_cls)

            # boss's hp bonus
            if g.n_persons > 5:
                boss.maxlife += 1

            boss.life = boss.maxlife

        # reseat
        seed = get_seed_for(g.players)
        random.Random(seed).shuffle(g.players)
        g.emit_event('reseat', None)

        # tell the others their own identity
        il = list(g.identities)
        g.random.shuffle(il)
        for p in g.players.exclude(boss):
            p.identity = Identity()
            id = il.pop()
            if Game.SERVER_SIDE:
                p.identity.type = id
            g.process_action(RevealIdentity(p, p))

        # others choose girls
        pl = g.players.exclude(boss)

        candidates = g.random.sample(chars, 3 * len(pl) - len(testing))
        candidates.extend(testing)
        g.random.shuffle(candidates)

        if Game.CLIENT_SIDE:
            candidates = [None] * len(candidates)

        del c
        for p in pl:
            p.choices = [CharChoice(c) for c in candidates[:3]]
            p.choices.append(CharChoice(Akari))
            p.reveal(p.choices)
            del candidates[:3]

        mapping = {p: p.choices for p in pl}  # CAUTION, DICT HERE
        with InputTransaction('ChooseGirl', pl, mapping=mapping) as trans:
            ilet = ChooseGirlInputlet(g, mapping)
            ilet.with_post_process(
                lambda p, rst: trans.notify('girl_chosen', (p, rst)) or rst)
            result = user_input(pl, ilet, type='all', trans=trans)

        # not enough chars for random, reuse unselected
        for p in pl:
            if result[p]:
                result[p].chosen = p
                choosed(result[p].char_cls)

        # mix char class with player -->
        for p in pl:
            c = result[p]
            c = c or p.choices[-1]
            g.players.reveal(c)

            if c.char_cls is Akari:
                c = CharChoice(random_char())
                g.players.reveal(c)

            choosed(c.char_cls)
            p = g.switch_character(p, c.char_cls)

        # -------
        for p in g.players:
            log.info(
                u'>> Player: %s:%s %s',
                p.__class__.__name__,
                Identity.TYPE.rlookup(p.identity.type),
                p.account.username,
            )
        # -------

        g.emit_event('game_begin', g)

        for p in g.players:
            g.process_action(DistributeCards(p, amount=4))

        pl = g.players.rotate_to(boss)

        for i, p in enumerate(cycle(pl)):
            if i >= 6000: break
            if not p.dead:
                try:
                    g.process_action(PlayerTurn(p))
                except InterruptActionFlow:
                    pass

        return True
Exemple #11
0
    def apply_action(self):
        g = Game.getgame()

        from cards import Deck

        g.deck = Deck()
        g.ehclasses = list(action_eventhandlers) + g.game_ehs.values()

        H, M, A = Identity.TYPE.HAKUREI, Identity.TYPE.MORIYA, Identity.TYPE.ADMIN
        idlist = [A, H, H, M, M]
        del H, M, A

        pl = g.players[1:]
        seed = sync_primitive(g.random.getrandbits(32), g.players)
        random.Random(seed).shuffle(pl)
        g.players[1:] = pl
        g.emit_event('reseat', None)

        for p, identity in zip(g.players, idlist):
            p.identity = Identity()
            p.identity.type = identity
            g.process_action(RevealIdentity(p, g.players))

        force_hakurei = BatchList(g.players[1:3])
        force_moriya  = BatchList(g.players[3:5])
        g.forces = BatchList([force_hakurei, force_moriya])

        from . import characters

        g.switch_character(g.players[0], CharChoice(characters.koakuma.Koakuma))
        g.koakuma = koakuma = g.players[0]
        koakuma.tags['books'] = g.total_books
        koakuma.maxlife += 4
        koakuma.life += 4

        # choose girls -->
        chars = characters.get_characters('book')
        try:
            chars.remove(characters.koakuma.Koakuma)
        except:
            pass

        g.random.shuffle(chars)

        testing = list(settings.TESTING_CHARACTERS)
        testing = filter_out(chars, lambda c: c.__name__ in testing)
        chars = g.random.sample(chars, 24)

        if Game.SERVER_SIDE:
            choices = [CharChoice(cls) for cls in chars[-20:]]
        else:
            choices = [CharChoice(None) for _ in xrange(20)]

        del chars[-20:]

        for p in g.players[1:]:
            c = choices[-4:]
            del choices[-4:]
            akari = CharChoice(characters.akari.Akari)
            akari.real_cls = chars.pop()
            c.append(akari)
            c.extend([CharChoice(cls) for cls in testing])
            p.choices = c
            p.reveal(c)

        pl = g.players[1:]
        mapping = {p: p.choices for p in pl}

        with InputTransaction('ChooseGirl', pl, mapping=mapping) as trans:
            ilet = ChooseGirlInputlet(g, mapping)
            ilet.with_post_process(lambda p, rst: trans.notify('girl_chosen', (p, rst)) or rst)
            rst = user_input(pl, ilet, timeout=30, type='all', trans=trans)

        for p in pl:
            c = rst[p] or p.choices[0]
            g.switch_character(p, c)

        g.emit_event('game_begin', g)

        for p in g.players:
            g.process_action(DistributeCards(p, amount=4))

        pl = g.players
        for i, idx in enumerate(cycle(range(len(pl)))):
            if i >= 6000: break
            p = pl[idx]
            if p.dead:
                g.process_action(PlayerRevive(p, p, 2))
                g.process_action(DrawCards(p, 2))
                continue

            g.emit_event('player_turn', p)
            try:
                g.process_action(PlayerTurn(p))
            except InterruptActionFlow:
                pass
Exemple #12
0
    def apply_action(self):
        g = Game.getgame()
        params = self.params

        from cards import Deck

        g.picks = []
        g.deck = Deck()

        g.ehclasses = list(action_eventhandlers) + g.game_ehs.values()

        H, M = Identity.TYPE.HAKUREI, Identity.TYPE.MORIYA
        if params['random_seat']:
            # reseat
            seed = get_seed_for(g.players)
            random.Random(seed).shuffle(g.players)
            g.emit_event('reseat', None)

            L = [[H, H, M, M, H, M], [H, M, H, M, H, M]]
            rnd = random.Random(get_seed_for(g.players))
            L = rnd.choice(L) * 2
            s = rnd.randrange(0, 6)
            idlist = L[s:s+6]
            del L, s, rnd
        else:
            idlist = [H, M, H, M, H, M]

        del H, M

        for p, identity in zip(g.players, idlist):
            p.identity = Identity()
            p.identity.type = identity
            g.process_action(RevealIdentity(p, g.players))

        force_hakurei      = BatchList()
        force_moriya       = BatchList()
        force_hakurei.pool = []
        force_moriya.pool  = []

        for p in g.players:
            if p.identity.type == Identity.TYPE.HAKUREI:
                force_hakurei.append(p)
                p.force = force_hakurei
            elif p.identity.type == Identity.TYPE.MORIYA:
                force_moriya.append(p)
                p.force = force_moriya

        g.forces = BatchList([force_hakurei, force_moriya])

        # ----- roll ------
        roll = range(len(g.players))
        g.random.shuffle(roll)
        pl = g.players
        roll = sync_primitive(roll, pl)
        roll = [pl[i] for i in roll]
        g.emit_event('game_roll', roll)
        first = roll[0]
        g.emit_event('game_roll_result', first)
        # ----

        # choose girls -->
        from . import characters
        chars = characters.get_characters('faith')
        g.random.shuffle(chars)

        # ANCHOR(test)
        testing = list(settings.TESTING_CHARACTERS)
        testing = filter_out(chars, lambda c: c.__name__ in testing)
        chars = g.random.sample(chars, 30 - len(testing))
        chars.extend(testing)

        if Game.SERVER_SIDE:
            choices = [CharChoice(cls) for cls in chars[-24:]]
        else:
            choices = [CharChoice(None) for _ in xrange(24)]

        del chars[-24:]

        for p in g.players:
            c = choices[-3:]
            del choices[-3:]
            akari = CharChoice(characters.akari.Akari)
            akari.real_cls = chars.pop()
            c.append(akari)
            p.choices = c
            p.choices_chosen = []
            p.reveal(c)

        mapping = {p: p.choices for p in g.players}

        rst = user_input(g.players, SortCharacterInputlet(g, mapping, 2), timeout=30, type='all')
        for p in g.players:
            p.choices_chosen = [mapping[p][i] for i in rst[p][:2]]

        for p in g.players:
            a, b = p.choices_chosen
            b.chosen = None
            p.force.reveal(b)
            g.switch_character(p, a)
            p.force.pool.append(b)
            del p.choices_chosen

        for p in g.players:
            if p.player is first:
                first = p
                break

        pl = g.players
        first_index = pl.index(first)
        order = BatchList(range(len(pl))).rotate_to(first_index)

        for p in pl:
            g.process_action(RevealIdentity(p, pl))

        g.emit_event('game_begin', g)

        for p in pl:
            g.process_action(DistributeCards(p, amount=4))

        pl = g.players.rotate_to(first)
        rst = user_input(pl[1:], ChooseOptionInputlet(DeathHandler(), (False, True)), type='all')

        for p in pl[1:]:
            rst.get(p) and g.process_action(RedrawCards(p, p))

        pl = g.players
        for i, idx in enumerate(cycle(order)):
            if i >= 6000: break
            p = pl[idx]
            if p.dead: continue

            g.emit_event('player_turn', p)
            try:
                g.process_action(PlayerTurn(p))
            except InterruptActionFlow:
                pass

        return True
Exemple #13
0
    def apply_action(self):
        g = Game.getgame()

        from . import cards

        g.pick_history = []

        g.deck = cards.Deck(cards.kof_card_definition)
        g.ehclasses = []
        g.current_player = None

        for i, p in enumerate(g.players):
            p.identity = Identity()
            p.identity.type = (Identity.TYPE.HAKUREI,
                               Identity.TYPE.MORIYA)[i % 2]

        # choose girls -->
        from characters import get_characters
        chars = get_characters('kof')

        testing = list(settings.TESTING_CHARACTERS)
        testing = filter_out(chars, lambda c: c.__name__ in testing)

        _chars = g.random.sample(chars, 10)
        _chars.extend(testing)

        from characters.akari import Akari
        if Game.SERVER_SIDE:
            choice = [CharChoice(cls) for cls in _chars[-10:]]

            for c in g.random.sample(choice, 4):
                c.real_cls = c.char_cls
                c.char_cls = Akari

        elif Game.CLIENT_SIDE:
            choice = [CharChoice(None) for i in xrange(10)]

        # -----------

        g.players.reveal(choice)

        # roll
        roll = range(len(g.players))
        g.random.shuffle(roll)
        pl = g.players
        roll = sync_primitive(roll, pl)

        roll = [pl[i] for i in roll]

        g.emit_event('game_roll', roll)

        first = roll[0]
        second = roll[1]

        g.emit_event('game_roll_result', first)
        # ----

        # akaris = {}  # DO NOT USE DICT! THEY ARE UNORDERED!
        akaris = []

        A, B = first, second
        order = [A, B, B, A, A, B, B, A, A, B]
        A.choices = []
        B.choices = []
        A.remaining = [2]
        B.remaining = [2]
        choice_mapping = {A: choice, B: choice}
        del A, B

        with InputTransaction('ChooseGirl', g.players,
                              mapping=choice_mapping) as trans:
            for p in order:
                c = user_input([p], ChooseGirlInputlet(g, choice_mapping), 10,
                               'single', trans)
                if not c:
                    # first non-chosen char
                    for c in choice:
                        if not c.chosen:
                            c.chosen = p
                            break

                if issubclass(c.char_cls, Akari):
                    akaris.append((p, c))

                c.chosen = p
                p.choices.append(c)

                trans.notify('girl_chosen', (p, c))

        # reveal akaris for themselves
        for p, c in akaris:
            c.char_cls = c.real_cls
            p.reveal(c)

        for c in choice:
            del c.chosen

        list_shuffle(first.choices, first)
        list_shuffle(second.choices, second)

        mapping = {first: first.choices, second: second.choices}

        with InputTransaction('ChooseGirl', g.players,
                              mapping=mapping) as trans:
            ilet = ChooseGirlInputlet(g, mapping)
            ilet.with_post_process(
                lambda p, rst: trans.notify('girl_chosen', (p, rst)) or rst)
            rst = user_input(pl, ilet, type='all', trans=trans)

        def s(p):
            c = rst[p] or p.choices[0]
            p = g.next_character(p, c)
            p.choices.remove(c)
            return p

        first, second = s(first), s(second)

        order = [1, 0] if first is g.players[0] else [0, 1]

        pl = g.players
        for p in pl:
            g.process_action(RevealIdentity(p, pl))

        g.emit_event('game_begin', g)

        for p in pl:
            g.process_action(DistributeCards(p, amount=4 if p is first else 3))

        for i in order:
            g.emit_event('character_debut', (None, g.players[i]))

        for i, idx in enumerate(cycle(order)):
            p = g.players[idx]
            if i >= 6000: break
            if p.dead:
                KOFCharacterSwitchHandler.do_switch_dead()
                p = g.players[idx]  # player changed

            assert not p.dead

            try:
                g.emit_event('player_turn', p)
                g.process_action(PlayerTurn(p))
            except InterruptActionFlow:
                pass
Exemple #14
0
    def apply_action(self):
        g = Game.getgame()
        params = self.params

        from cards import Deck

        g.stats = []

        g.deck = Deck()
        g.ehclasses = []

        if params['random_force']:
            seed = get_seed_for(g.players)
            random.Random(seed).shuffle(g.players)

        g.draw_extra_card = params['draw_extra_card']

        f1 = BatchList()
        f2 = BatchList()
        g.forces = BatchList([f1, f2])

        H, M = Identity.TYPE.HAKUREI, Identity.TYPE.MORIYA
        for p, id, f in zip(g.players, [H, H, M, M], [f1, f1, f2, f2]):
            p.identity = Identity()
            p.identity.type = id
            p.force = f
            f.append(p)

        pl = g.players
        for p in pl:
            g.process_action(RevealIdentity(p, pl))

        # ----- roll ------
        roll = range(len(pl))
        g.random.shuffle(roll)
        roll = sync_primitive(roll, pl)
        roll = [pl[i] for i in roll]
        g.emit_event('game_roll', roll)
        for i in range(1, 3):
            if roll[i].force == roll[0].force:
                roll.append(roll.pop(i))

        g.players[:] = roll
        g.emit_event('game_roll_result', g.players[0])
        g.emit_event('reseat', None)
        # ----

        # ban / choose girls -->
        from . import characters
        chars = characters.get_characters('2v2')

        seed = get_seed_for(g.players)
        random.Random(seed).shuffle(chars)

        # ANCHOR(test)
        testing = list(settings.TESTING_CHARACTERS)
        testing = filter_out(chars, lambda c: c.__name__ in testing)
        chars.extend(testing)

        chars = chars[-20:]
        choices = [CharChoice(cls) for cls in chars]

        banned = set()
        mapping = {p: choices for p in g.players}
        with InputTransaction('BanGirl', g.players, mapping=mapping) as trans:
            for p in g.players:
                c = user_input([p],
                               ChooseGirlInputlet(g, mapping),
                               timeout=30,
                               trans=trans)
                c = c or [_c for _c in choices if not _c.chosen][0]
                c.chosen = p
                banned.add(c.char_cls)
                trans.notify('girl_chosen', (p, c))

        assert len(banned) == 4

        g.stats.extend([{
            'event': 'ban',
            'attributes': {
                'gamemode': g.__class__.__name__,
                'character': i.__name__
            }
        } for i in banned])

        chars = [_c for _c in chars if _c not in banned]

        g.random.shuffle(chars)

        if Game.CLIENT_SIDE:
            chars = [None] * len(chars)

        for p in g.players:
            p.choices = [CharChoice(cls) for cls in chars[-4:]]
            p.choices[-1].as_akari = True

            del chars[-4:]

            p.reveal(p.choices)

        g.pause(1)

        mapping = {p: p.choices for p in g.players}
        with InputTransaction('ChooseGirl', g.players,
                              mapping=mapping) as trans:
            ilet = ChooseGirlInputlet(g, mapping)

            @ilet.with_post_process
            def process(p, c):
                c = c or p.choices[0]
                trans.notify('girl_chosen', (p, c))
                return c

            rst = user_input(g.players,
                             ilet,
                             timeout=30,
                             type='all',
                             trans=trans)

        # reveal
        for p, c in rst.items():
            c.as_akari = False
            g.players.reveal(c)
            g.set_character(p, c.char_cls)

        # -------
        for p in g.players:
            log.info(
                u'>> Player: %s:%s %s',
                p.__class__.__name__,
                Identity.TYPE.rlookup(p.identity.type),
                p.account.username,
            )
        # -------

        g.emit_event('game_begin', g)

        for p in g.players:
            g.process_action(DistributeCards(p, amount=4))

        for i, p in enumerate(cycle(pl)):
            if i >= 6000: break
            if not p.dead:
                g.emit_event('player_turn', p)
                try:
                    g.process_action(PlayerTurn(p))
                except InterruptActionFlow:
                    pass

        return True
Exemple #15
0
    def apply_action(self):
        g = Game.getgame()
        params = self.params

        from cards import Deck

        g.deck = Deck()
        g.ehclasses = []

        if params['random_seat']:
            seed = get_seed_for(g.players)
            random.Random(seed).shuffle(g.players)
            g.emit_event('reseat', None)

        for i, p in enumerate(g.players):
            p.identity = Identity()
            p.identity.type = (Identity.TYPE.HAKUREI,
                               Identity.TYPE.MORIYA)[i % 2]

        g.forces = forces = BatchList([BatchList(), BatchList()])
        for i, p in enumerate(g.players):
            f = i % 2
            p.force = f
            forces[f].append(p)

        pl = g.players
        for p in pl:
            g.process_action(RevealIdentity(p, pl))

        # choose girls -->
        from . import characters
        chars = characters.get_characters('3v3')

        seed = get_seed_for(g.players)
        random.Random(seed).shuffle(chars)

        # ANCHOR(test)
        testing = list(settings.TESTING_CHARACTERS)
        testing = filter_out(chars, lambda c: c.__name__ in testing)
        chars.extend(testing)

        choices = [CharChoice(cls) for cls in chars[-16:]]
        del chars[-12:]

        for c in choices[:4]:
            c.char_cls = characters.akari.Akari

        if Game.SERVER_SIDE:
            for c, cls in zip(choices[:4],
                              g.random.sample(chars,
                                              4)):  # yes, must random.sample
                c.real_cls = cls

        # ----- roll ------
        roll = range(len(g.players))
        g.random.shuffle(roll)
        pl = g.players
        roll = sync_primitive(roll, pl)
        roll = [pl[i] for i in roll]
        g.emit_event('game_roll', roll)
        first = roll[0]
        g.emit_event('game_roll_result', first)
        # ----

        first_index = g.players.index(first)

        order_list = (0, 5, 3, 4, 2, 1)
        n = len(order_list)
        order = [g.players[(first_index + i) % n] for i in order_list]

        # akaris = {}  # DO NOT USE DICT! THEY ARE UNORDERED!
        akaris = []
        mapping = {p: choices for p in g.players}
        with InputTransaction('ChooseGirl', g.players,
                              mapping=mapping) as trans:
            for p in order:
                c = user_input([p],
                               ChooseGirlInputlet(g, mapping),
                               timeout=30,
                               trans=trans)
                c = c or [_c for _c in choices if not _c.chosen][0]
                c.chosen = p

                if issubclass(c.char_cls, characters.akari.Akari):
                    akaris.append((p, c))
                else:
                    g.set_character(p, c.char_cls)

                trans.notify('girl_chosen', (p, c))

        # reveal akaris
        if akaris:
            for p, c in akaris:
                c.char_cls = c.real_cls

            g.players.reveal([i[1] for i in akaris])

            for p, c in akaris:
                g.set_character(p, c.char_cls)

        # -------
        for p in g.players:
            log.info(
                u'>> Player: %s:%s %s',
                p.__class__.__name__,
                Identity.TYPE.rlookup(p.identity.type),
                p.account.username,
            )
        # -------

        first = g.players[first_index]

        g.emit_event('game_begin', g)

        for p in g.players:
            g.process_action(DrawCards(p, amount=3 if p is first else 4))

        pl = g.players.rotate_to(first)

        for i, p in enumerate(cycle(pl)):
            if i >= 6000: break
            if not p.dead:
                g.emit_event('player_turn', p)
                try:
                    g.process_action(PlayerTurn(p))
                except InterruptActionFlow:
                    pass

        return True