def getInputletInstances(self): from thb.cards import AttackCard from thb.characters.youmu import Youmu from thb.common import CharChoice from thb.inputlets import ActionInputlet from thb.inputlets import ChooseGirlInputlet from thb.inputlets import ChooseIndividualCardInputlet from thb.inputlets import ChooseOptionInputlet from thb.inputlets import ChoosePeerCardInputlet from thb.inputlets import ProphetInputlet g, p = self.makeGame() ilets = [ ActionInputlet(self, ['cards', 'showncards'], []), ChooseGirlInputlet(self, {p: [CharChoice(Youmu)]}), ChooseIndividualCardInputlet(self, [AttackCard()]), ChooseOptionInputlet(self, (False, True)), ChoosePeerCardInputlet(self, p, ['cards']), ProphetInputlet(self, [AttackCard()]), ] for i in ilets: i.actor = p return g, p, ilets
def switch(p): g = Game.getgame() mapping = {p: p.choices} with InputTransaction('ChooseGirl', [p], mapping=mapping) as trans: rst = user_input([p], ChooseGirlInputlet(g, mapping), timeout=30, trans=trans) rst = rst or p.choices[0] p = g.next_character(p, rst) p.choices.remove(rst) return p
def testChooseGirlInputlet(self): from game.autoenv import user_input from thb.common import CharChoice from thb.characters.youmu import Youmu from thb.characters.seiga import Seiga from 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])
def handle(self, evt_type, act): if evt_type == 'action_apply' and isinstance(act, PlayerDeath): g = Game.getgame() tgt = act.target force = tgt.force if len(force.pool) <= 1: forces = g.forces[:] forces.remove(force) g.winners = forces[0][:] g.game_end() elif evt_type == 'action_after' and isinstance(act, PlayerDeath): g = Game.getgame() tgt = act.target pool = tgt.force.pool assert pool mapping = {tgt: pool} with InputTransaction('ChooseGirl', [tgt], mapping=mapping) as trans: c = user_input([tgt], ChooseGirlInputlet(g, mapping), timeout=30, trans=trans) c = c or [_c for _c in pool if not _c.chosen][0] c.chosen = tgt pool.remove(c) trans.notify('girl_chosen', (tgt, c)) tgt = g.switch_character(tgt, c) c = getattr(g, 'current_player', None) g.process_action(DistributeCards(tgt, 4)) if user_input([tgt], ChooseOptionInputlet(self, (False, True))): g.process_action(RedrawCards(tgt, tgt)) return act
def apply_action(self): g = Game.getgame() params = self.params from thb.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_rst = roll(g, self.items) f1, f2 = partition(lambda p: p.force is roll_rst[0].force, roll_rst) final_order = [f1[0], f2[0], f2[1], f1[1]] g.players[:] = final_order g.emit_event('reseat', None) # ban / choose girls --> from . import characters chars = characters.get_characters('common', '2v2') seed = get_seed_for(g.players) random.Random(seed).shuffle(chars) # ANCHOR(test) testing = list(settings.TESTING_CHARACTERS) testing, chars = partition(lambda c: c.__name__ in testing, chars) 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
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 thb.characters import get_characters chars = get_characters('common', 'kof') A, B = roll(g, self.items) order = [A, B, B, A, A, B, B, A, A, B] choices, imperial_choices = build_choices( g, self.items, candidates=chars, players=[A, B], num=10, akaris=4, shared=True, ) chosen = {A: [], B: []} with InputTransaction('ChooseGirl', g.players, mapping=choices) as trans: for p, c in imperial_choices: c.chosen = p chosen[p].append(c) trans.notify('girl_chosen', (p, c)) order.remove(p) for p in order: c = user_input([p], ChooseGirlInputlet(g, choices), 10, 'single', trans) c = c or first(choices[p], lambda c: not c.chosen) c.chosen = p chosen[p].append(c) trans.notify('girl_chosen', (p, c)) # reveal akaris for themselves for p in [A, B]: for c in chosen[p]: c.akari = False p.reveal(c) del c.chosen list_shuffle(chosen[A], A) list_shuffle(chosen[B], B) with InputTransaction('ChooseGirl', g.players, mapping=chosen) as trans: ilet = ChooseGirlInputlet(g, chosen) ilet.with_post_process(lambda p, rst: trans.notify('girl_chosen', (p, rst)) or rst) rst = user_input([A, B], ilet, type='all', trans=trans) def s(p): c = rst[p] or chosen[p][0] chosen[p].remove(c) p.choices = chosen[p] p.remaining = [2] p = g.next_character(p, c) return p A, B = s(A), s(B) order = [1, 0] if A is g.players[0] else [0, 1] for p in [A, B]: g.process_action(RevealIdentity(p, g.players)) g.emit_event('game_begin', g) g.process_action(DistributeCards(A, amount=4)) g.process_action(DistributeCards(B, amount=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
def apply_action(self): g = Game.getgame() params = self.params from thb.cards import Deck g.deck = Deck() g.ehclasses = [] # arrange identities --> g.double_curtain = params['double_curtain'] mapping = { 'B': Identity.TYPE.BOSS, '!': Identity.TYPE.ATTACKER, '&': Identity.TYPE.ACCOMPLICE, '?': Identity.TYPE.CURTAIN, } if g.double_curtain: identities = 'B!!!&&??' else: identities = 'B!!!!&&?' pl = g.players[:] identities = [mapping[i] for i in identities] g.identities = identities[:] imperial_identities = ImperialIdentity.get_chosen(self.items, pl) for p, i in imperial_identities: pl.remove(p) identities.remove(i) g.random.shuffle(identities) if Game.CLIENT_SIDE: identities = [Identity.TYPE.HIDDEN for _ in identities] for p, i in imperial_identities + zip(pl, identities): p.identity = Identity() p.identity.type = i g.process_action(RevealIdentity(p, p)) del identities is_boss = sync_primitive([p.identity.type == Identity.TYPE.BOSS for p in g.players], g.players) boss_idx = is_boss.index(True) boss = g.boss = g.players[boss_idx] boss.identity = Identity() boss.identity.type = Identity.TYPE.BOSS g.process_action(RevealIdentity(boss, g.players)) # choose girls init --> from .characters import get_characters pl = g.players.rotate_to(boss) choices, _ = build_choices( g, self.items, candidates=get_characters('common', 'id', 'id8', '-boss'), players=[boss], num=[5], akaris=[1], shared=False, ) choices[boss][:0] = [CharChoice(cls) for cls in get_characters('boss')] with InputTransaction('ChooseGirl', [boss], mapping=choices) as trans: c = user_input([boss], ChooseGirlInputlet(g, choices), 30, 'single', trans) c = c or choices[boss][-1] c.chosen = boss c.akari = False g.players.reveal(c) trans.notify('girl_chosen', (boss, c)) chars = get_characters('common', 'id', 'id8') try: chars.remove(c.char_cls) except: pass # 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 # choose boss dedicated skill g.process_action(ChooseBossSkillAction(boss, boss)) # reseat seed = get_seed_for(g.players) random.Random(seed).shuffle(g.players) g.emit_event('reseat', None) # others choose girls pl = g.players.exclude(boss) choices, _ = build_choices( g, self.items, candidates=chars, players=pl, num=[4] * len(pl), akaris=[1] * len(pl), shared=False, ) with InputTransaction('ChooseGirl', pl, mapping=choices) as trans: ilet = ChooseGirlInputlet(g, choices) ilet.with_post_process(lambda p, rst: trans.notify('girl_chosen', (p, rst)) or rst) result = user_input(pl, ilet, type='all', trans=trans) # mix char class with player --> for p in pl: c = result[p] or choices[p][-1] c.akari = False g.players.reveal(c) 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)) for i, p in enumerate(cycle(g.players.rotate_to(boss))): if i >= 6000: break if not p.dead: try: g.process_action(PlayerTurn(p)) except InterruptActionFlow: pass return True
def apply_action(self): g = Game.getgame() params = self.params from thb.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)) from . import characters chars = characters.get_characters('common', '3v3') choices, imperial_choices = build_choices( g, self.items, candidates=chars, players=g.players, num=16, akaris=4, shared=True, ) roll_rst = roll(g, self.items) first = roll_rst[0] 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 = [] with InputTransaction('ChooseGirl', g.players, mapping=choices) as trans: chosen = set() for p, c in imperial_choices: chosen.add(p) c.chosen = p g.set_character(p, c.char_cls) trans.notify('girl_chosen', (p, c)) for p in order: if p in chosen: continue c = user_input([p], ChooseGirlInputlet(g, choices), timeout=30, trans=trans) c = c or [_c for _c in reversed(choices[p]) if not _c.chosen][0] c.chosen = p if c.akari: c.akari = False akaris.append((p, c)) else: g.set_character(p, c.char_cls) trans.notify('girl_chosen', (p, c)) # reveal akaris if akaris: 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
def apply_action(self): g = Game.getgame() params = self.params from thb.cards import Deck g.deck = Deck() g.ehclasses = [] # arrange identities --> g.double_curtain = params['double_curtain'] mapping = { 'B': Identity.TYPE.BOSS, '!': Identity.TYPE.ATTACKER, '&': Identity.TYPE.ACCOMPLICE, '?': Identity.TYPE.CURTAIN, } if g.double_curtain: identities = 'B!!!&&??' else: identities = 'B!!!!&&?' pl = g.players[:] identities = [mapping[i] for i in identities] g.identities = identities[:] imperial_identities = ImperialIdentity.get_chosen(self.items, pl) for p, i in imperial_identities: pl.remove(p) identities.remove(i) g.random.shuffle(identities) if Game.CLIENT_SIDE: identities = [Identity.TYPE.HIDDEN for _ in identities] for p, i in imperial_identities + zip(pl, identities): p.identity = Identity() p.identity.type = i g.process_action(RevealIdentity(p, p)) del identities is_boss = sync_primitive( [p.identity.type == Identity.TYPE.BOSS for p in g.players], g.players) boss_idx = is_boss.index(True) boss = g.boss = g.players[boss_idx] boss.identity = Identity() boss.identity.type = Identity.TYPE.BOSS g.process_action(RevealIdentity(boss, g.players)) # choose girls init --> from .characters import get_characters pl = g.players.rotate_to(boss) choices, _ = build_choices( g, self.items, candidates=get_characters('common', 'id', 'id8', '-boss'), players=[boss], num=[5], akaris=[1], shared=False, ) choices[boss][:0] = [CharChoice(cls) for cls in get_characters('boss')] with InputTransaction('ChooseGirl', [boss], mapping=choices) as trans: c = user_input([boss], ChooseGirlInputlet(g, choices), 30, 'single', trans) c = c or choices[boss][-1] c.chosen = boss c.akari = False g.players.reveal(c) trans.notify('girl_chosen', (boss, c)) chars = get_characters('common', 'id', 'id8') try: chars.remove(c.char_cls) except: pass # 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 # choose boss dedicated skill g.process_action(ChooseBossSkillAction(boss, boss)) # reseat seed = get_seed_for(g.players) random.Random(seed).shuffle(g.players) g.emit_event('reseat', None) # others choose girls pl = g.players.exclude(boss) choices, _ = build_choices( g, self.items, candidates=chars, players=pl, num=[4] * len(pl), akaris=[1] * len(pl), shared=False, ) with InputTransaction('ChooseGirl', pl, mapping=choices) as trans: ilet = ChooseGirlInputlet(g, choices) ilet.with_post_process( lambda p, rst: trans.notify('girl_chosen', (p, rst)) or rst) result = user_input(pl, ilet, type='all', trans=trans) # mix char class with player --> for p in pl: c = result[p] or choices[p][-1] c.akari = False g.players.reveal(c) 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)) for i, p in enumerate(cycle(g.players.rotate_to(boss))): if i >= 6000: break if not p.dead: try: g.process_action(PlayerTurn(p)) except InterruptActionFlow: pass return True