Example #1
0
    def getInputletInstances(self):
        from gamepack.thb.cards import AttackCard
        from gamepack.thb.characters.youmu import Youmu
        from gamepack.thb.common import CharChoice
        from gamepack.thb.inputlets import ActionInputlet
        from gamepack.thb.inputlets import ChooseGirlInputlet
        from gamepack.thb.inputlets import ChooseIndividualCardInputlet
        from gamepack.thb.inputlets import ChooseOptionInputlet
        from gamepack.thb.inputlets import ChoosePeerCardInputlet
        from gamepack.thb.inputlets import ProphetInputlet

        g, p = self.makeGame()

        ilets = [
            ActionInputlet(self, ['cards', 'showncards'], []),
            ChooseGirlInputlet(self, {p: [CharChoice(Youmu)]}),
            ChooseIndividualCardInputlet(self, [AttackCard()]),
            ChooseOptionInputlet(self),
            ChoosePeerCardInputlet(self, p, ['cards']),
            ProphetInputlet(self, [AttackCard()]),
        ]

        for i in ilets:
            i.actor = p

        return g, p, ilets
Example #2
0
    def testChooseGirlInputlet(self):
        from game.autoenv import user_input
        from gamepack.thb.common import CharChoice
        from gamepack.thb.characters.youmu import Youmu
        from gamepack.thb.characters.seiga import Seiga
        from gamepack.thb.inputlets import ChooseGirlInputlet

        g, p = self.makeGame()
        choices = [CharChoice(Youmu), CharChoice(Seiga)]
        mapping = {p: choices}

        ilet = ChooseGirlInputlet(self, mapping)
        ilet.actor = p
        ilet.set_choice(choices[0])
        eq_(ilet.data(), 0)

        p.client.gdlist.append([r'>I:ChooseGirl:\d+', 0])
        ilet = ChooseGirlInputlet(self, mapping)
        eq_(user_input([p], ilet), choices[0])
Example #3
0
    def apply_action(self):
        # WHOLE BUNCH OF MEGA HACK
        old = self.target
        g = Game.getgame()
        old_life, maxlife_delta = old.life, old.maxlife - old.__class__.maxlife

        ActionStage.force_break()
        '''
        turn = PlayerTurn.get_current(old)
        try:
            turn.pending_stages[:] = []
        except Exception:
            pass
        '''

        tgt = KOFCharacterSwitchHandler.switch(old)
        tgt.life = old_life
        tgt.maxlife += maxlife_delta

        for l in ('cards', 'showncards', 'equips', 'fatetell', 'special'):
            s, t = getattr(old, l), getattr(tgt, l)
            for i in list(s):
                i.move_to(t)

        for s in old.skills:
            if 'character' not in s.skill_category:
                tgt.skills.append(s)

        for act in g.action_stack:
            # Meh... good enough
            if act.source is old:
                act.source = tgt

            if act.target is old:
                act.target = tgt

            if isinstance(act, LaunchCard):
                act.target_list[:] = [
                    tgt if p is old else p for p in act.target_list
                ]

        tgt.tags = old.tags

        tgt.choices.append(CharChoice(old.__class__))

        if tgt.life > tgt.maxlife:
            g.process_action(LifeLost(tgt, tgt, tgt.life - tgt.maxlife))

        self.transition = [old, tgt]

        g.emit_event('character_debut', (old, tgt))

        return True
Example #4
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
Example #5
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
Example #6
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
Example #7
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
Example #8
0
 def apply_action(self):
     src, tgt = self.source, self.target
     src.choices.append(CharChoice(tgt.__class__))
     return True
Example #9
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
Example #10
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