def yesno(self, player, desc): pl = self.players[player] old_parser = pl.connection.parser def r(caller): if caller.text.lower().startswith('y'): self.set_responsei(1) reactor.callLater(0, process_duel, self) elif caller.text.lower().startswith('n'): self.set_responsei(0) reactor.callLater(0, process_duel, self) else: pl.notify(opt) pl.notify(DuelReader, r, restore_parser=old_parser) if desc > 10000: code = desc >> 4 card = Card(code) opt = card.get_strings(pl)[desc & 0xF] if opt == "": opt = pl._("Unknown question from %s. Yes or no?") % ( card.get_name(pl)) else: opt = "String %d" % desc opt = pl.strings["system"].get(desc, opt) pl.notify(opt) pl.notify(DuelReader, r, restore_parser=old_parser)
def msg_summoning(self, data, special=False): data = io.BytesIO(data[1:]) code = self.read_u32(data) card = Card(code) card.set_location(self.read_u32(data)) self.cm.call_callbacks('summoning', card, special=special) return data.read()
def msg_set(self, data): data = io.BytesIO(data[1:]) code = self.read_u32(data) loc = self.read_u32(data) card = Card(code) card.set_location(loc) self.cm.call_callbacks('set', card) return data.read()
def msg_select_effectyn(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) card = Card(self.read_u32(data)) card.set_location(self.read_u32(data)) desc = self.read_u32(data) self.cm.call_callbacks("select_effectyn", player, card, desc) return data.read()
def msg_chaining(self, data): data = io.BytesIO(data[1:]) code = self.read_u32(data) card = Card(code) card.set_location(self.read_u32(data)) tc = self.read_u8(data) tl = self.read_u8(data) ts = self.read_u8(data) desc = self.read_u32(data) cs = self.read_u8(data) self.cm.call_callbacks('chaining', card, tc, tl, ts, desc, cs) return data.read()
def msg_sort_card(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) size = self.read_u8(data) cards = [] for i in range(size): card = Card(self.read_u32(data)) card.controller = self.read_u8(data) card.location = self.read_u8(data) card.sequence = self.read_u8(data) cards.append(card) self.cm.call_callbacks('sort_card', player, cards) return data.read()
def select_option(self, player, options): pl = self.players[player] def r(caller): idx = int(caller.text) opt = options[idx] for p in self.players + self.watchers: if opt > 10000: string = card.get_strings(p)[opt & 0xF] else: string = p._("Unknown option %d" % opt) string = p.strings["system"].get(opt, string) if p is pl: p.notify( p._("You selected option {0}: {1}").format( idx + 1, string)) else: p.notify( p._("{0} selected option {1}: {2}").format( pl.nickname, idx + 1, string)) self.set_responsei(idx) reactor.callLater(0, process_duel, self) card = None opts = [] for opt in options: if opt > 10000: code = opt >> 4 card = Card(code) string = card.get_strings(pl)[opt & 0xF] else: string = pl._("Unknown option %d" % opt) string = pl.strings["system"].get(opt, string) opts.append(string) pl.notify( pl._("Select option:"), no_abort=pl._("Invalid option."), prompt=pl._("Select option:"), persistent=True, restore_parser=DuelParser, ) for idx, opt in enumerate(opts): pl.notify(str(idx) + ": " + str(opt)) pl.notify(DuelReader, r, no_abort=pl._("Invalid command"), restore_parser=DuelParser)
def msg_select_unselect_card(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) finishable = self.read_u8(data) cancelable = self.read_u8(data) min = self.read_u8(data) max = self.read_u8(data) select_size = self.read_u8(data) select_cards = [] for i in range(select_size): code = self.read_u32(data) loc = self.read_u32(data) card = Card(code) card.set_location(loc) select_cards.append(card) unselect_size = self.read_u8(data) unselect_cards = [] for i in range(unselect_size): code = self.read_u32(data) loc = self.read_u32(data) card = Card(code) card.set_location(loc) unselect_cards.append(card) self.cm.call_callbacks('select_unselect_card', player, finishable, cancelable, min, max, select_cards, unselect_cards) return data.read()
def msg_select_position(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) code = self.read_u32(data) card = Card(code) positions = POSITION(self.read_u8(data)) self.cm.call_callbacks("select_position", player, card, positions) return data.read()
def msg_confirm_decktop(self, data): cards = [] data = io.BytesIO(data[1:]) player = self.read_u8(data) count = self.read_u8(data) for i in range(count): code = self.read_u32(data) if code & 0x80000000: code = code ^ 0x80000000 # don't know what this actually does card = Card(code) card.controller = self.read_u8(data) card.location = LOCATION(self.read_u8(data)) card.sequence = self.read_u8(data) cards.append(card) self.cm.call_callbacks('confirm_decktop', player, cards) return data.read()
def msg_decktop(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) self.read_u8(data) # don't know what this number does code = self.read_u32(data) if code & 0x80000000: code = code ^ 0x80000000 # don't know what this actually does self.cm.call_callbacks('decktop', player, Card(code)) return data.read()
def msg_draw(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) drawed = self.read_u8(data) cards = [] for i in range(drawed): c = self.read_u32(data) card = Card(c & 0x7fffffff) cards.append(card) self.cm.call_callbacks('draw', player, cards) return data.read()
def msg_select_chain(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) size = self.read_u8(data) spe_count = self.read_u8(data) forced = self.read_u8(data) hint_timing = self.read_u32(data) other_timing = self.read_u32(data) chains = [] for i in range(size): et = self.read_u8(data) code = self.read_u32(data) loc = self.read_u32(data) card = Card(code) card.set_location(loc) desc = self.read_u32(data) chains.append((et, card, desc)) self.cm.call_callbacks('select_chain', player, size, spe_count, forced, chains) return data.read()
def msg_swap(self, data): data = io.BytesIO(data[1:]) code1 = self.read_u32(data) location1 = self.read_u32(data) code2 = self.read_u32(data) location2 = self.read_u32(data) card1 = Card(code1) card1.set_location(location1) card2 = Card(code2) card2.set_location(location2) self.cm.call_callbacks('swap', card1, card2) return data.read()
def yesno(self, player, desc): pl = self.players[player] old_parser = pl.connection.parser def yes(caller): self.set_responsei(1) reactor.callLater(0, process_duel, self) def no(caller): self.set_responsei(0) reactor.callLater(0, process_duel, self) if desc > 10000: code = desc >> 4 card = Card(code) opt = card.get_strings(pl)[desc & 0xf] if opt == '': opt = pl._('Unknown question from %s. Yes or no?') % ( card.get_name(pl)) else: opt = "String %d" % desc opt = pl.strings['system'].get(desc, opt) pl.notify(yes_or_no_parser, opt, yes, no=no, restore_parser=old_parser)
def yesno(self, player, desc): pl = self.players[player] old_parser = pl.connection.parser def yes(caller): self.set_responsei(1) reactor.callLater(0, process_duel, self) def no(caller): self.set_responsei(0) reactor.callLater(0, process_duel, self) if desc > 10000: code = desc >> 4 opt = Card(code).get_strings(pl)[desc & 0xf] else: opt = "String %d" % desc opt = globals.strings[pl.language]['system'].get(desc, opt) pl.notify(yes_or_no_parser, opt, yes, no=no, restore_parser=old_parser)
def msg_pos_change(self, data): data = io.BytesIO(data[1:]) code = self.read_u32(data) card = Card(code) card.controller = self.read_u8(data) card.location = LOCATION(self.read_u8(data)) card.sequence = self.read_u8(data) prevpos = POSITION(self.read_u8(data)) card.position = POSITION(self.read_u8(data)) self.cm.call_callbacks('pos_change', card, prevpos) return data.read()
def msg_tag_swap(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) main_deck_count = self.read_u8(data) extra_deck_count = self.read_u8(data) extra_p_count = self.read_u8(data) hand_count = self.read_u8(data) top_card = self.read_u32(data) # we don't need the following information, so we trash it # that allows us to process all following messages too (if any) for i in range(hand_count): self.read_u32(data) for i in range(extra_deck_count): self.read_u32(data) self.cm.call_callbacks('tag_swap', player) if top_card > 0: self.cm.call_callbacks('decktop', player, Card(top_card)) return data.read()
def msg_select_tribute(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) cancelable = self.read_u8(data) min = self.read_u8(data) max = self.read_u8(data) size = self.read_u8(data) cards = [] for i in range(size): code = self.read_u32(data) card = Card(code) card.controller = self.read_u8(data) card.location = LOCATION(self.read_u8(data)) card.sequence = self.read_u8(data) card.position = self.get_card(card.controller, card.location, card.sequence).position card.release_param = self.read_u8(data) cards.append(card) self.cm.call_callbacks('select_tribute', player, cancelable, min, max, cards) return data.read()
def msg_select_counter(self, data): data = io.BytesIO(data[1:]) player = self.read_u8(data) countertype = self.read_u16(data) count = self.read_u16(data) size = self.read_u8(data) cards = [] for i in range(size): card = Card(self.read_u32(data)) card.controller = self.read_u8(data) card.location = LOCATION(self.read_u8(data)) card.sequence = self.read_u8(data) card.counter = self.read_u16(data) cards.append(card) self.cm.call_callbacks('select_counter', player, countertype, count, cards) return data.read()
def select_option(self, player, options): pl = self.players[player] def select(caller, idx): self.set_responsei(idx) reactor.callLater(0, process_duel, self) opts = [] for opt in options: if opt > 10000: code = opt >> 4 string = Card(code).get_strings(pl)[opt & 0xf] else: string = "Unknown option %d" % opt string = globals.strings[pl.language]['system'].get(opt, string) opts.append(string) m = Menu(pl._("Select option:"), no_abort=pl._("Invalid option."), persistent=True, prompt=pl._("Select option:"), restore_parser=DuelParser) for idx, opt in enumerate(opts): m.item(opt)(lambda caller, idx=idx: select(caller, idx)) pl.notify(m)
def move(self, code, location, newloc, reason): card = Card(code) card.set_location(location) pl = self.players[card.controller] op = self.players[1 - card.controller] plspec = card.get_spec(pl.duel_player) ploc = (location >> 8) & 0xff pnewloc = (newloc >> 8) & 0xff if reason & 0x01 and ploc != pnewloc: pl.notify(pl._("Card %s (%s) destroyed.") % (plspec, card.get_name(pl))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) w.notify(w._("Card %s (%s) destroyed.") % (s, card.get_name(w))) elif ploc == pnewloc and ploc in (LOCATION_MZONE, LOCATION_SZONE): cnew = Card(code) cnew.set_location(newloc) if (location & 0xff) != (newloc & 0xff): # controller changed too (e.g. change of heart) pl.notify(pl._("your card {spec} ({name}) changed controller to {op} and is now located at {targetspec}.").format(spec=plspec, name = card.get_name(pl), op = op.nickname, targetspec = cnew.get_spec(pl.duel_player))) op.notify(op._("you now control {plname}s card {spec} ({name}) and its located at {targetspec}.").format(plname=pl.nickname, spec=card.get_spec(op.duel_player), name = card.get_name(op), targetspec = cnew.get_spec(op.duel_player))) for w in self.watchers: s = card.get_spec(w.duel_player) ts = cnew.get_spec(w.duel_player) w.notify(w._("{plname}s card {spec} ({name}) changed controller to {op} and is now located at {targetspec}.").format(plname=pl.nickname, op=op.nickname, spec=s, targetspec=ts, name=card.get_name(w))) else: # only place changed (alien decks e.g.) pl.notify(pl._("your card {spec} ({name}) switched its zone to {targetspec}.").format(spec=plspec, name=card.get_name(pl), targetspec=cnew.get_spec(pl.duel_player))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) ts = cnew.get_spec(w.duel_player) w.notify(w._("{plname}s card {spec} ({name}) changed its zone to {targetspec}.").format(plname=pl.nickname, spec=s, targetspec=ts, name=card.get_name(w))) elif reason & 0x4000 and ploc != pnewloc: pl.notify(pl._("you discarded {spec} ({name}).").format(spec = plspec, name = card.get_name(pl))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) w.notify(w._("{plname} discarded {spec} ({name}).").format(plname=pl.nickname, spec=s, name=card.get_name(w))) elif ploc == LOCATION_REMOVED and pnewloc in (LOCATION_SZONE, LOCATION_MZONE): cnew = Card(code) cnew.set_location(newloc) pl.notify(pl._("your banished card {spec} ({name}) returns to the field at {targetspec}.").format(spec=plspec, name=card.get_name(pl), targetspec=cnew.get_spec(pl.duel_player))) for w in self.watchers+[op]: s=card.get_spec(w.duel_player) ts = cnew.get_spec(w.duel_player) w.notify(w._("{plname}'s banished card {spec} ({name}) returned to their field at {targetspec}.").format(plname=pl.nickname, spec=s, targetspec=ts, name=card.get_name(w))) elif ploc == LOCATION_GRAVE and pnewloc in (LOCATION_SZONE, LOCATION_MZONE): cnew = Card(code) cnew.set_location(newloc) pl.notify(pl._("your card {spec} ({name}) returns from the graveyard to the field at {targetspec}.").format(spec=plspec, name=card.get_name(pl), targetspec=cnew.get_spec(pl.duel_player))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) ts = cnew.get_spec(w.duel_player) w.notify(w._("{plname}s card {spec} ({name}) returns from the graveyard to the field at {targetspec}.").format(plname = pl.nickname, spec=s, targetspec=ts, name = card.get_name(w))) elif pnewloc == LOCATION_HAND and ploc != pnewloc: pl.notify(pl._("Card {spec} ({name}) returned to hand.") .format(spec=plspec, name=card.get_name(pl))) for w in self.watchers+[op]: if card.position in (POS_FACEDOWN_DEFENSE, POS_FACEDOWN): name = w._("Face-down card") else: name = card.get_name(w) s = card.get_spec(w.duel_player) w.notify(w._("{plname}'s card {spec} ({name}) returned to their hand.") .format(plname=pl.nickname, spec=s, name=name)) elif reason & 0x12 and ploc != pnewloc: pl.notify(pl._("You tribute {spec} ({name}).") .format(spec=plspec, name=card.get_name(pl))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) if card.position in (POS_FACEDOWN_DEFENSE, POS_FACEDOWN): name = w._("%s card") % card.get_position(w) else: name = card.get_name(w) w.notify(w._("{plname} tributes {spec} ({name}).") .format(plname=pl.nickname, spec=s, name=name)) elif ploc == LOCATION_OVERLAY+LOCATION_MZONE and pnewloc in (LOCATION_GRAVE, LOCATION_REMOVED): pl.notify(pl._("you detached %s.")%(card.get_name(pl))) for w in self.watchers+[op]: w.notify(w._("%s detached %s")%(pl.nickname, card.get_name(w))) elif ploc != pnewloc and pnewloc == LOCATION_GRAVE: pl.notify(pl._("your card {spec} ({name}) was sent to the graveyard.").format(spec=plspec, name=card.get_name(pl))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) w.notify(w._("{plname}'s card {spec} ({name}) was sent to the graveyard.").format(plname=pl.nickname, spec=s, name=card.get_name(w))) elif ploc != pnewloc and pnewloc == LOCATION_REMOVED: pl.notify(pl._("your card {spec} ({name}) was banished.").format(spec=plspec, name=card.get_name(pl))) for w in self.watchers+[op]: if card.position in (POS_FACEDOWN_DEFENSE, POS_FACEDOWN): name = w._("%s card")%(card.get_position(w)) else: name = card.get_name(w) s = card.get_spec(w.duel_player) w.notify(w._("{plname}'s card {spec} ({name}) was banished.").format(plname=pl.nickname, spec=s, name=name)) elif ploc != pnewloc and pnewloc == LOCATION_DECK: pl.notify(pl._("your card {spec} ({name}) returned to your deck.").format(spec=plspec, name=card.get_name(pl))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) w.notify(w._("{plname}'s card {spec} ({name}) returned to their deck.").format(plname=pl.nickname, spec=s, name=card.get_name(w))) elif ploc != pnewloc and pnewloc == LOCATION_EXTRA: pl.notify(pl._("your card {spec} ({name}) returned to your extra deck.").format(spec=plspec, name=card.get_name(pl))) for w in self.watchers+[op]: s = card.get_spec(w.duel_player) w.notify(w._("{plname}'s card {spec} ({name}) returned to their extra deck.").format(plname=pl.nickname, spec=s, name=card.get_name(w)))
def msg_select_sum(self, data): data = io.BytesIO(data[1:]) mode = self.read_u8(data) player = self.read_u8(data) val = self.read_u32(data) select_min = self.read_u8(data) select_max = self.read_u8(data) count = self.read_u8(data) must_select = [] for i in range(count): code = self.read_u32(data) card = Card(code) card.controller = self.read_u8(data) card.location = LOCATION(self.read_u8(data)) card.sequence = self.read_u8(data) param = self.read_u32(data) card.param = ( param & 0xff, param >> 16, ) must_select.append(card) count = self.read_u8(data) select_some = [] for i in range(count): code = self.read_u32(data) card = Card(code) card.controller = self.read_u8(data) card.location = LOCATION(self.read_u8(data)) card.sequence = self.read_u8(data) param = self.read_u32(data) card.param = ( param & 0xff, param >> 16, ) select_some.append(card) self.cm.call_callbacks('select_sum', mode, player, val, select_min, select_max, must_select, select_some) return data.read()
def move(self, code, location, newloc, reason): card = Card(code) card.set_location(location) cnew = Card(code) cnew.set_location(newloc) pl = self.players[card.controller] op = self.players[1 - card.controller] plspec = card.get_spec(pl) opspec = card.get_spec(op) plnewspec = cnew.get_spec(pl) opnewspec = cnew.get_spec(op) getspec = lambda p: plspec if p.duel_player == pl.duel_player else opspec getnewspec = lambda p: plnewspec if p.duel_player == pl.duel_player else opnewspec card_visible = True if card.position & POSITION.FACEDOWN and cnew.position & POSITION.FACEDOWN: card_visible = False getvisiblename = lambda p: card.get_name(p) if card_visible else p._( "Face-down card") if reason & REASON.DESTROY and card.location != cnew.location: self.inform( pl, (INFORM.ALLIES, lambda p: p._("Card %s (%s) destroyed.") % (plspec, card.get_name(p))), (INFORM.OPPONENTS, lambda p: p._("Card %s (%s) destroyed.") % (opspec, card.get_name(p)))) elif card.location == cnew.location and card.location & LOCATION.ONFIELD: if card.controller != cnew.controller: # controller changed too (e.g. change of heart) self.inform( pl, (INFORM.PLAYER, lambda p: p. _("your card {spec} ({name}) changed controller to {op} and is now located at {targetspec}." ).format(spec=plspec, name=card.get_name(p), op=op.nickname, targetspec=plnewspec)), (INFORM.OPPONENT, lambda p: p. _("you now control {plname}s card {spec} ({name}) and its located at {targetspec}." ).format(plname=pl.nickname, spec=opspec, name=card.get_name(p), targetspec=opnewspec)), (INFORM.WATCHERS | INFORM.TAG_PLAYERS, lambda p: p. _("{plname}s card {spec} ({name}) changed controller to {op} and is now located at {targetspec}." ).format(plname=pl.nickname, op=op.nickname, spec=getspec(p), targetspec=getnewspec(p), name=card.get_name(p))), ) else: # only column changed (alien decks e.g.) self.inform( pl, (INFORM.PLAYER, lambda p: p. _("your card {spec} ({name}) switched its zone to {targetspec}." ).format(spec=plspec, name=card.get_name(p), targetspec=plnewspec)), (INFORM.OTHER, lambda p: p. _("{plname}s card {spec} ({name}) changed its zone to {targetspec}." ).format(plname=pl.nickname, spec=getspec(p), targetspec=getnewspec(p), name=card.get_name(p))), ) elif reason & REASON.DISCARD and card.location != cnew.location: self.inform( pl, (INFORM.PLAYER, lambda p: p._("you discarded {spec} ({name})."). format(spec=plspec, name=card.get_name(p))), (INFORM.OTHER, lambda p: p._("{plname} discarded {spec} ({name}).").format( plname=pl.nickname, spec=getspec(p), name=card.get_name(p))), ) elif card.location == LOCATION.REMOVED and cnew.location & LOCATION.ONFIELD: self.inform( pl, (INFORM.PLAYER, lambda p: p. _("your banished card {spec} ({name}) returns to the field at {targetspec}." ).format( spec=plspec, name=card.get_name(p), targetspec=plnewspec)), (INFORM.OTHER, lambda p: p. _("{plname}'s banished card {spec} ({name}) returned to their field at {targetspec}." ).format(plname=pl.nickname, spec=getspec(p), targetspec=getnewspec(p), name=card.get_name(p))), ) elif card.location == LOCATION.GRAVE and cnew.location & LOCATION.ONFIELD: self.inform( pl, (INFORM.PLAYER, lambda p: p. _("your card {spec} ({name}) returns from the graveyard to the field at {targetspec}." ).format( spec=plspec, name=card.get_name(p), targetspec=plnewspec)), (INFORM.OTHER, lambda p: p. _("{plname}s card {spec} ({name}) returns from the graveyard to the field at {targetspec}." ).format(plname=pl.nickname, spec=getspec(p), targetspec=getnewspec(p), name=card.get_name(p))), ) elif cnew.location == LOCATION.HAND and card.location != cnew.location: self.inform( pl, (INFORM.PLAYER | INFORM.TAG_PLAYER, lambda p: p._("Card {spec} ({name}) returned to hand.").format( spec=plspec, name=card.get_name(p))), (INFORM.WATCHERS | INFORM.OPPONENTS, lambda p: p._( "{plname}'s card {spec} ({name}) returned to their hand."). format(plname=pl.nickname, spec=getspec(p), name=getvisiblename(p))), ) elif reason & (REASON.RELEASE | REASON.SUMMON) and card.location != cnew.location: self.inform( pl, (INFORM.PLAYER, lambda p: p._("You tribute {spec} ({name})."). format(spec=plspec, name=card.get_name(p))), (INFORM.OTHER, lambda p: p._("{plname} tributes {spec} ({name}).").format( plname=pl.nickname, spec=getspec(p), name=getvisiblename(p))), ) elif card.location == LOCATION.OVERLAY | LOCATION.MZONE and cnew.location & LOCATION.ONFIELD: self.inform( pl, (INFORM.PLAYER, lambda p: p._("you detached %s.") % (card.get_name(p))), (INFORM.OTHER, lambda p: p._("%s detached %s") % (pl.nickname, card.get_name(p))), ) elif card.location != cnew.location and cnew.location == LOCATION.GRAVE: self.inform( pl, (INFORM.PLAYER, lambda p: p._( "your card {spec} ({name}) was sent to the graveyard.").format( spec=plspec, name=card.get_name(p))), (INFORM.OTHER, lambda p: p._( "{plname}'s card {spec} ({name}) was sent to the graveyard."). format(plname=pl.nickname, spec=getspec(p), name=card.get_name(p)) ), ) elif card.location != cnew.location and cnew.location == LOCATION.REMOVED: self.inform( pl, (INFORM.PLAYER, lambda p: p._("your card {spec} ({name}) was banished.").format( spec=plspec, name=card.get_name(p))), (INFORM.OTHER, lambda p: p. _("{plname}'s card {spec} ({name}) was banished.").format( plname=pl.nickname, spec=getspec(p), name=getvisiblename(p))), ) elif card.location != cnew.location and cnew.location == LOCATION.DECK: self.inform( pl, (INFORM.PLAYER, lambda p: p._("your card {spec} ({name}) returned to your deck." ).format(spec=plspec, name=card.get_name(p))), (INFORM.OTHER, lambda p: p._( "{plname}'s card {spec} ({name}) returned to their deck."). format(plname=pl.nickname, spec=getspec(p), name=getvisiblename(p))), ) elif card.location != cnew.location and cnew.location == LOCATION.EXTRA: self.inform( pl, (INFORM.PLAYER, lambda p: p._( "your card {spec} ({name}) returned to your extra deck."). format(spec=plspec, name=card.get_name(pl))), (INFORM.OTHER, lambda p: p ._("{plname}'s card {spec} ({name}) returned to their extra deck." ).format( plname=pl.nickname, spec=getspec(p), name=card.get_name(p)) ), ) elif card.location == LOCATION.DECK and cnew.location == LOCATION.SZONE: def fn(p): if p.soundpack and cnew.type & TYPE.SPELL: p.notify("### activate_spell") elif p.soundpack and cnew.type & TYPE.TRAP: p.notify("### activate_trap") if p is pl: if cnew.position & POSITION.FACEDOWN: return p._("You set %s (%s) in %s position.") % ( cnew.get_spec(p), cnew.get_name(p), cnew.get_position(p)) else: return p._("Activating {0} ({1})").format( cnew.get_spec(p), cnew.get_name(p)) else: if cnew.position & POSITION.FACEDOWN: return p._("%s sets %s in %s position.") % ( pl.nickname, cnew.get_spec(p), cnew.get_position(p)) else: return p._("{0} activating {1} ({2})").format( pl.nickname, cnew.get_spec(p), cnew.get_name(p)) self.inform(pl, (INFORM.ALL, fn)) elif cnew.location == (LOCATION.OVERLAY | LOCATION.MZONE): attached_to = self.get_card(cnew.controller, cnew.location ^ LOCATION.OVERLAY, cnew.sequence) self.inform( pl, (INFORM.PLAYER, lambda p: p. _("your card {spec} ({name}) was attached to {targetspec} ({targetname}) as XYZ material" ).format(spec=getspec(p), name=card.get_name(p), targetspec=attached_to.get_spec(p), targetname=attached_to.get_name(p))), (INFORM.OTHER, lambda p: p. _("{plname}'s card {spec} ({name}) was attached to {targetspec} ({targetname}) as XYZ material" ).format(spec=getspec(p), name=card.get_name(p), targetspec=attached_to.get_spec(p), targetname=attached_to.get_name(p), plname=pl.nickname)), )