def testBuildChoices(self): import logging from thb.common import build_choices import random from thb.characters.baseclasses import get_characters from thb import characters from game import autoenv # def build_choices(g, items, candidates, players, num, akaris, shared): log = logging.getLogger('test') g = ObjectDict({ 'players': BatchList([ObjectDict({ 'account': ObjectDict({'userid': i}), 'reveal': lambda o, i=i: log.info('Reveal to %s: %s', i, o), }) for i in xrange(8)]), 'random': random.Random(12341234), 'SERVER_SIDE': True, 'CLIENT_SIDE': False, }) autoenv.Game.getgame = staticmethod(lambda: g) chars = get_characters('common', '3v3') assert chars choices, imperial = build_choices(g, {}, chars, g.players, 10, 3, True) eq_(len(choices.items()), len(g.players)) eq_(len(set([id(i) for i in choices.values()])), 1) eq_(set(choices.keys()), set(g.players)) eq_(imperial, []) choices, imperial = build_choices(g, {0: ['imperial-choice:SpAya', 'foo']}, chars, g.players, 10, 3, True) eq_(len(choices.items()), len(g.players)) eq_(len(set([id(i) for i in choices.values()])), 1) eq_(set(choices.keys()), set(g.players)) p, c = imperial[0] eq_((p, c.char_cls), (g.players[0], characters.sp_aya.SpAya)) assert c in choices[p] del c eq_(sum([c.akari for c in choices[p]]), 3) choices, imperial = build_choices(g, {0: ['imperial-choice:SpAya', 'foo']}, chars, g.players, [4] * 8, [1] * 8, False) eq_(len(choices.items()), len(g.players)) eq_(len(set([id(i) for i in choices.values()])), 8) eq_(set(choices.keys()), set(g.players)) eq_([len(i) for i in choices.values()], [4] * 8) eq_([len([j for j in i if j.akari]) for i in choices.values()], [1] * 8) p, c = imperial[0] eq_((p, c.char_cls), (g.players[0], characters.sp_aya.SpAya)) assert c in choices[p]
def testBuildChoices(self): import logging from thb.common import build_choices import random from thb.characters.baseclasses import get_characters from thb import characters from game import autoenv # def build_choices(g, items, candidates, players, num, akaris, shared): log = logging.getLogger('test') g = ObjectDict({ 'players': BatchList([ ObjectDict({ 'account': ObjectDict({'userid': i}), 'reveal': lambda o, i=i: log.info('Reveal to %s: %s', i, o), }) for i in xrange(8) ]), 'random': random.Random(12341234), 'SERVER_SIDE': True, 'CLIENT_SIDE': False, }) autoenv.Game.getgame = staticmethod(lambda: g) chars = get_characters('common', '3v3') assert chars choices, imperial = build_choices(g, {}, chars, g.players, 10, 3, True) eq_(len(choices.items()), len(g.players)) eq_(len(set([id(i) for i in choices.values()])), 1) eq_(set(choices.keys()), set(g.players)) eq_(imperial, []) choices, imperial = build_choices( g, {0: ['imperial-choice:SpAya', 'foo']}, chars, g.players, 10, 3, True) eq_(len(choices.items()), len(g.players)) eq_(len(set([id(i) for i in choices.values()])), 1) eq_(set(choices.keys()), set(g.players)) p, c = imperial[0] eq_((p, c.char_cls), (g.players[0], characters.sp_aya.SpAya)) assert c in choices[p] del c eq_(sum([c.akari for c in choices[p]]), 3) choices, imperial = build_choices( g, {0: ['imperial-choice:SpAya', 'foo']}, chars, g.players, [4] * 8, [1] * 8, False) eq_(len(choices.items()), len(g.players)) eq_(len(set([id(i) for i in choices.values()])), 8) eq_(set(choices.keys()), set(g.players)) eq_([len(i) for i in choices.values()], [4] * 8) eq_([len([j for j in i if j.akari]) for i in choices.values()], [1] * 8) p, c = imperial[0] eq_((p, c.char_cls), (g.players[0], characters.sp_aya.SpAya)) assert c in choices[p]
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.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_rst = roll(g, self.items) first = roll_rst[0] # choose girls --> from . import characters chars = characters.get_characters('common', 'faith') choices, _ = build_choices( g, self.items, candidates=chars, players=g.players, num=[4] * 6, akaris=[1] * 6, shared=False, ) rst = user_input(g.players, SortCharacterInputlet(g, choices, 2), timeout=30, type='all') for p in g.players: a, b = [choices[p][i] for i in rst[p][:2]] b.chosen = None p.force.reveal(b) g.switch_character(p, a) p.force.pool.append(b) 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
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.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_rst = roll(g, self.items) first = roll_rst[0] # choose girls --> from . import characters chars = characters.get_characters('common', 'faith') choices, _ = build_choices( g, self.items, candidates=chars, players=g.players, num=[4] * 6, akaris=[1] * 6, shared=False, ) rst = user_input(g.players, SortCharacterInputlet(g, choices, 2), timeout=30, type='all') for p in g.players: a, b = [choices[p][i] for i in rst[p][:2]] b.chosen = None p.force.reveal(b) g.switch_character(p, a) p.force.pool.append(b) 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
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