예제 #1
0
    def game_start(g):
        # game started, init state
        from cards import Card, CardList

        g.action_types[LaunchCard] = RaidLaunchCard
        g.action_types[ActionStageLaunchCard] = RaidActionStageLaunchCard

        ehclasses = g.ehclasses = []

        for p in g.players:
            p.cards = CardList(p, 'handcard')  # Cards in hand
            p.showncards = CardList(p, 'showncard')  # Cards which are shown to the others, treated as 'Cards in hand'
            p.equips = CardList(p, 'equips')  # Equipments
            p.fatetell = CardList(p, 'fatetell')  # Cards in the Fatetell Zone
            p.faiths = CardList(p, 'faiths')  # 'faith' cards
            p.special = CardList(p, 'special')  # used on special purpose

            p.showncardlists = [p.showncards, p.faiths, p.fatetell]  # cardlists should shown to others

            p.tags = defaultdict(int)
            p.tags['faithcounter'] = True

            p.dead = False

        # reveal identities
        mutant = g.mutant = g.players[0]
        attackers = g.attackers = PlayerList(g.players[1:])

        mutant.identity = Identity()
        mutant.identity.type = Identity.TYPE.MUTANT

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

        for p in attackers:
            p.identity = Identity()
            p.identity.type = Identity.TYPE.ATTACKER

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

        # choose girl init
        chosen_girls = []
        pl = PlayerList(g.players)
        def process(p, cid):
            try:
                check(isinstance(cid, int))
                check(0 <= cid < len(choice))
                c = choice[cid]
                if c.chosen:
                    raise ValueError

                c.chosen = p
                chosen_girls.append(c)
                g.emit_event('girl_chosen', c)
                pl.remove(p)
                return c

            except CheckFailed:
                raise ValueError

        # mutant's choose
        from characters import ex_characters as ex_chars

        choice = [CharChoice(cls, cid) for cid, cls in enumerate(ex_chars)]

        g.emit_event('choose_girl_begin', ([mutant], choice))
        PlayerList([mutant]).user_input_all('choose_girl', process, choice, timeout=5)

        if not chosen_girls:
            # didn't choose
            c = choice[0]
            c.chosen = mutant
            g.emit_event('girl_chosen', c)
            pl.remove(mutant)
        else:
            c = chosen_girls.pop()

        assert c.chosen is mutant

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

        mixin_character(mutant, c.char_cls)
        mutant.skills = list(mutant.skills)  # make it instance variable
        ehclasses.extend(mutant.eventhandlers_required)

        mutant.life = mutant.maxlife
        mutant.morphed = False

        g.emit_event('choose_girl_end', None)

        # init deck & mutant's initial equip
        # (SinsackCard, SPADE, 1)
        # (SinsackCard, HEART, Q)
        from cards import Deck, SinsackCard, card_definition
        raid_carddef = [
            carddef for carddef in card_definition
            if carddef[0] is not SinsackCard
        ]

        g.deck = Deck(raid_carddef)

        # attackers' choose
        from characters import characters as chars

        if Game.SERVER_SIDE:
            choice = [
                CharChoice(cls, cid) for cid, cls in
                enumerate(g.random.sample(chars, 16))
            ]

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

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

        g.players.reveal(choice)
        g.emit_event('choose_girl_begin', (attackers, choice))
        attackers.user_input_all('choose_girl', process, choice, timeout=30)
        g.emit_event('choose_girl_end', None)

        # if there's any person didn't make a choice -->
        if pl:
            choice = [c for c in choice if not c.chosen]
            sample = sync_primitive(
                g.random.sample(xrange(len(choice)), len(pl)), g.players
            )
            for p, i in zip(pl, sample):
                c = choice[i]
                c.chosen = p
                chosen_girls.append(c)
                g.emit_event('girl_chosen', c)

        # mix char class with player -->
        for c in chosen_girls:
            p = c.chosen
            mixin_character(p, c.char_cls)
            p.skills = list(p.skills)  # make it instance variable
            p.skills.extend([
                Cooperation, Protection,
                Parry, OneUp,
            ])
            p.life = p.maxlife
            ehclasses.extend(p.eventhandlers_required)

        g.update_event_handlers()

        g.emit_event('game_begin', g)

        # -------
        log.info(u'>> Game info: ')
        log.info(u'>> Mutant: %s', mutant.char_cls.__name__)
        for p in attackers:
            log.info(u'>> Attacker: %s', p.char_cls.__name__)

        # -------

        try:
            g.process_action(DrawCards(mutant, amount=6))
            for p in attackers:
                g.process_action(DrawCards(p, amount=4))

            # stage 1
            try:
                for i in xrange(500):
                    g.process_action(CollectFaith(mutant, mutant, 1))

                    g.emit_event('round_start', False)
                    for p in attackers:
                        p.tags['action'] = True

                    while True:
                        avail = PlayerList([p for p in attackers if p.tags['action'] and not p.dead])
                        if not avail:
                            break

                        p, _ = avail.user_input_any(
                            tag='choose_option',
                            expects=lambda p, data: bool(data),
                            attachment=RequestAction,
                            timeout=15,
                        )

                        p = p or avail[0]

                        p.tags['action'] = False
                        try:
                            g.process_action(PlayerTurn(p))
                        except InterruptActionFlow:
                            pass

                        try:
                            g.process_action(PlayerTurn(mutant))
                        except InterruptActionFlow:
                            pass

            except MutantMorph:
                pass

            # morphing
            stage1 = mutant.__class__
            stage2 = stage1.stage2

            for s in stage1.skills:
                try:
                    mutant.skills.remove(s)
                except ValueError:
                    pass

            mutant.skills.extend(stage2.skills)

            ehclasses = g.ehclasses
            for s in stage1.eventhandlers_required:
                try:
                    ehclasses.remove(s)
                except ValueError:
                    pass

            ehclasses.extend(stage2.eventhandlers_required)

            g.process_action(
                MaxLifeChange(mutant, mutant, -(stage1.maxlife // 2))
            )
            mutant.morphed = True

            mixin_character(mutant, stage2)

            g.update_event_handlers()

            for p in attackers:
                g.process_action(CollectFaith(p, p, 1))

            g.process_action(DropCards(mutant, mutant.fatetell))

            g.emit_event('mutant_morph', mutant)

            g.pause(4)

            # stage 2
            for i in xrange(500):
                g.process_action(CollectFaith(mutant, mutant, 1))

                g.emit_event('round_start', False)
                for p in attackers:
                    p.tags['action'] = True

                try:
                    g.process_action(PlayerTurn(mutant))
                except InterruptActionFlow:
                    pass

                while True:
                    avail = PlayerList([p for p in attackers if p.tags['action'] and not p.dead])
                    if not avail:
                        break

                    p, _ = avail.user_input_any(
                        tag='choose_option',
                        expects=lambda p, data: bool(data),
                        attachment=RequestAction,
                        timeout=15,
                    )

                    p = p or avail[0]

                    p.tags['action'] = False
                    try:
                        g.process_action(PlayerTurn(p))
                    except InterruptActionFlow:
                        pass

        except GameEnded:
            pass

        winner_force = 'Mutant' if g.winners == [mutant] else 'Attackers'
        log.info(u'>> Winner: %s', winner_force)
예제 #2
0
    def game_start(g):
        # game started, init state
        from cards import Card, Deck, CardList

        g.deck = Deck()

        ehclasses = list(action_eventhandlers) + _game_ehs.values()

        np = g.n_persons

        for p in g.players:
            p.cards = CardList(p, 'handcard') # Cards in hand
            p.showncards = CardList(p, 'showncard') # Cards which are shown to the others, treated as 'Cards in hand'
            p.equips = CardList(p, 'equips') # Equipments
            p.fatetell = CardList(p, 'fatetell') # Cards in the Fatetell Zone
            p.special = CardList(p, 'special') # used on special purpose

            p.showncardlists = [p.showncards, p.fatetell] # cardlists should shown to others

            p.tags = defaultdict(int)

            p.dead = False

        # choose girls init -->
        from characters import characters as chars

        if Game.SERVER_SIDE:
            choice = [
                CharChoice(cls, cid)
                for cls, cid in zip(g.random.sample(chars, 3*np+2), xrange(3*np+2))
            ]
        elif Game.CLIENT_SIDE:
            choice = [
                CharChoice(None, i)
                for i in xrange(3*np+2)
            ]

        chosen_girls = []
        pl = PlayerList(g.players)
        def process(p, cid):
            try:
                retry = p._retry
            except AttributeError:
                retry = 3

            retry -= 1
            try:
                check(isinstance(cid, int))
                i = p._choose_tag
                if p is boss:
                    assert p is pl[-1]
                    check(i*3 <= cid< (i+1)*3+2)
                else:
                    check(i*3 <= cid < (i+1)*3)
                c = choice[cid]
                if c.chosen and retry > 0:
                    p._retry = retry
                    raise ValueError
                c.chosen = p
                chosen_girls.append(c)
                g.emit_event('girl_chosen', c)
                pl.remove(p)
                return c

            except CheckFailed as e:
                return None

            finally:
                try:
                    del p._retry
                    del p._choose_tag
                except AttributeError:
                    pass

        # choose boss
        idx = sync_primitive(g.random.randrange(len(g.players)), g.players)
        pl[-1], pl[idx] = pl[idx], pl[-1]
        boss = g.boss = pl[-1]

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

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

        for i, p in enumerate(pl):
            p._choose_tag = i
            p.reveal(choice[i*3:(i+1)*3])

        boss.reveal(choice[-2:])

        g.emit_event('choose_girl_begin', ([boss], choice))
        PlayerList([boss]).user_input_all('choose_girl', process, choice, timeout=30)

        if not chosen_girls:
            # didn't choose
            offs = sync_primitive(g.random.randrange(5), g.players)
            c = choice[(len(pl)-1)*3+offs]
            c.chosen = boss
            g.emit_event('girl_chosen', c)
            pl.remove(boss)
        else:
            c = chosen_girls.pop()

        assert c.chosen is boss

        g.players.reveal(c)

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

        mixin_character(boss, c.char_cls)
        boss.skills = list(boss.skills) # make it instance variable
        ehclasses.extend(boss.eventhandlers_required)

        # boss's hp bonus
        if len(g.players) > 5:
            boss.maxlife += 1

        boss.life = boss.maxlife

        g.emit_event('choose_girl_end', None)

        # reseat
        opl = g.players
        loc = range(len(opl))
        g.random.shuffle(loc)
        loc = sync_primitive(loc, opl)
        npl = opl[:]
        for i, l in zip(range(len(opl)), loc):
            npl[i] = opl[l]
        g.players[:] = npl

        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))

        pl = g.players.exclude(boss)
        g.emit_event('choose_girl_begin', (pl, choice))
        pl.user_input_all('choose_girl', process, choice, timeout=30)
        g.emit_event('choose_girl_end', None)

        # now you can have them all.
        g.players.reveal(choice)

        # if there's any person didn't make a choice -->
        # FIXME: this can choose girl from the other force!
        if pl:
            choice = [c for c in choice if not c.chosen]
            sample = sync_primitive(
                g.random.sample(xrange(len(choice)), len(pl)), g.players
            )
            for p, i in zip(pl, sample):
                c = choice[i]
                c.chosen = p
                chosen_girls.append(c)
                g.emit_event('girl_chosen', c)

        # mix char class with player -->
        for c in chosen_girls:
            p = c.chosen
            mixin_character(p, c.char_cls)
            p.skills = list(p.skills)  # make it instance variable
            p.life = p.maxlife
            ehclasses.extend(p.eventhandlers_required)

        g.event_handlers = EventHandler.make_list(ehclasses)

        g.emit_event('game_begin', g)

        try:
            for p in g.players:
                g.process_action(DrawCards(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

        except GameEnded:
            pass