def render(self) -> pimg.PImg: i = pimg.PImg.filled(self.size * 16, (100, 100, 100)) for pos, s in self.squares.items(): i.blit(s.img, pos * 16) for pos, l in self.letters.items(): i.blit(l.img, pos * 16) if self.size.x == 15 and self.size.y == 15: b = standardback.copy() b.blit(i, V2(8, 8)) return b return i
def check_1(cls, spc, p): if len(spc) <= 1: return True for i, _ in enumerate(spc): if i == len(spc) - 1: break if V2.intersection( a=spc[i], b=spc[i + 1], c=spc[-1], d=p, ): return False return True
def init(self, p): def popl(): self.history.insert_left(self.hull.popleft()) def popr(): self.history.insert_right(self.hull.pop()) self.rotation = V2.rotation(self.hull[1], self.hull[-1], p) if len(self.hull) >= 2 else 0 self.history.new(index=self.iter.i) if (len(self.hull) >= 3) and (self.rotation == 0): popr() if self.hull: popl() self.hull.appendleft(p) self.hull.append(p)
async def run(self, *modifiers): if modifiers: try: self.rounds = max(1, int(modifiers[0])) except ValueError: pass hardcore = "hardcore" in modifiers if hardcore: await self.send(":warning: HARDCORE MODE ACTIVE :warning:") self.rewards = 5 * self.rounds for r in range(self.rounds): if self.rounds > 1: await self.send(f"ROUND {r+1}/{self.rounds}") board = BoggleBoard(V2(4, 4)) await self.send("TWO MINUTES REMAIN!") await self.pump() try: await asyncio.wait_for( dib.gather([ p.submission_phase(self, board, hardcore) for p in self.players ]), 120) except asyncio.TimeoutError: for p in self.players: await p.dm("TIME'S UP FOLKS") for p in self.players: valid_words = [ w for w in p.words if not any(w in op.words for op in self.players if op != p) ] score = sum(get_score(len(w)) for w in valid_words) - p.penalty await self.send( "%s got %s/%s unique words, and gets %s points!\n%s" % (p.name, len(valid_words), len( p.words), score, ", ".join(valid_words))) p.points += score p.penalty = 0 await self.send("The best word anyone could have gotten was %s!" % board.longest_possible().upper()) await self.show_scoreboard(r == self.rounds - 1) if r != self.rounds - 1: await self.pump() await asyncio.sleep(20) await self.end_points()
def __init__(self, size=V2(5, 5)): self.size = size total_words = size.x * size.y self.RED_WORDS = total_words // 3 + 1 self.BLUE_WORDS = total_words // 3 self.words = random.sample(codewords, total_words) self.grid = [ self.words[n * size.x:n * size.x + size.x] for n in range(size.y) ] self.flipped = set() self.wcols = {} temp_words = self.words.copy() random.shuffle(temp_words) for r in range(self.RED_WORDS): self.wcols[temp_words[r]] = "RED" for b in range(self.BLUE_WORDS): self.wcols[temp_words[b + self.RED_WORDS]] = "BLUE" self.wcols[temp_words[self.RED_WORDS + self.BLUE_WORDS]] = "ASSASSIN" for w in temp_words[self.RED_WORDS + self.BLUE_WORDS + 1:]: self.wcols[w] = "NEUTRAL"
def print(self): return "\n".join("".join( dib.to_emoji(self.board[V2(x, y)]) for x in range(self.size.x)) for y in range(self.size.y))
async def run(self, *modifiers): self.grid = CodeGrid(V2(7, 7) if "extreme" in modifiers else V2(5, 5)) await self.send("Speak now if you wish to become master of the codes.") left_master = await self.wait_for_shout("") await self.send("%s has volunteered for red codemaster" % left_master.name) right_master = await self.wait_for_shout( "", [p for p in self.players if p != left_master]) remaining = [ p for p in self.players if p not in (left_master, right_master) ] random.shuffle(remaining) left_team = remaining[:len(remaining) // 2] right_team = remaining[len(remaining) // 2:] await self.send( "Red team: %s; lead by %s.\nBlue team: %s; led by %s." % (dib.smart_list([p.name for p in left_team]), left_master.name, dib.smart_list([p.name for p in right_team]), right_master.name)) masters = [left_master, right_master] teams = [left_team, right_team] self.grid.render_img(True) await right_master.dm("THE BOARD:", file=discord.File("codenames/board.png")) turn = 0 while not self.done: self.grid.render_img() await self.send("Current Board:", file=discord.File("codenames/board.png")) await self.send("%s's codemaster is thinking of a clue..." % self.team_names[turn].capitalize()) self.grid.render_img(True) await masters[turn].dm("Current Board:", file=discord.File("codenames/board.png")) clue = await self.wait_for_text(masters[turn], "Submit your clue!", True, self.grid.is_valid_clue) await self.send("THE CLUE: %s" % clue.upper()) word, num = clue.lower().split() guesses = 0 while num == "0" or num == "inf" or guesses <= int(num): guesses += 1 word = await self.choose_option( teams[turn], False, self.grid.leftover_words + ["pass"], "Guessing time!" if guesses == 1 else "The guessing continues...", True) if word == "pass": break colour = self.grid.wcols[word] self.grid.flipped.add(word) if colour in self.team_names: await self.send("%s was a %s team word!" % (word.upper(), colour)) if colour == self.team_names[ turn] and not self.grid.team_won( self.team_names[turn]): continue elif colour == "ASSASSIN": await self.send("%s was the assassin! Bad luck!" % word.upper()) await self.end_game(teams[not turn] + [masters[not turn]]) return else: await self.send("%s was neutral." % word.upper()) break if self.grid.team_won("RED"): await self.send("RED TEAM WINS!") await self.end_game(left_team + [left_master]) elif self.grid.team_won("BLUE"): await self.send("BLUE TEAM WINS!") await self.end_game(right_team + [right_master]) await self.send("Guessing phase over!") turn = 1 - turn
import dib import word_list import random import pimg import discord from vector import V2 from PIL import ImageFont MAX_WORD_LENGTH = 9 codewords = [ w for w in word_list.common if len(w) <= MAX_WORD_LENGTH and w != "pass" ] CARD_SIZE = V2(24, 16) BACK = (50, ) * 3 bigbas = ImageFont.truetype("fonts/bebas.ttf", 20) class CodeGrid(object): SCALE = 4 word_cards = [pimg.load(f"codenames/word{n+1}.png") for n in range(5)] def __init__(self, size=V2(5, 5)): self.size = size total_words = size.x * size.y self.RED_WORDS = total_words // 3 + 1 self.BLUE_WORDS = total_words // 3 self.words = random.sample(codewords, total_words) self.grid = [ self.words[n * size.x:n * size.x + size.x] for n in range(size.y) ] self.flipped = set() self.wcols = {}
def add_special(self, off: V2, bsc, *args): for o in off.rots() + V2(off.x, -off.y).rots(): self.squares[self.size // 2 + o] = bsc(*args)
def __init__(self, sz: vector.V2): self.size = sz self.squares = {pos: BoardSquare() for pos in sz.iter_locs()} self.letters = {}
def coords_to_v(coords: str): return V2(word_list.alphabet.index(coords[0]), int(coords[1:]) - 1)
async def run(self, *modifiers): spr = "super" in modifiers board = Board(V2(21, 21) if spr else V2(15, 15)) board.add_special(V2(7, 7), WordMult, 3) board.add_special(V2(7, 0), WordMult, 3) for n in range(3, 7): board.add_special(V2(n, n), WordMult, 2) board.add_special(vector.zero, WordMult, 2) for off in [V2(2, 2), V2(6, 2)]: board.add_special(off, LetterMult, 3) for off in [V2(7, 4), V2(4, 0), V2(5, 1), V2(1, 1)]: board.add_special(off, LetterMult, 2) if spr: board.add_special(V2(10, 10), WordMult, 4) board.add_special(V2(10, 3), WordMult, 3) board.add_special(V2(9, 2), WordMult, 2) board.add_special(V2(8, 1), WordMult, 2) board.add_special(V2(9, 9), WordMult, 2) board.add_special(V2(8, 8), WordMult, 2) board.add_special(V2(10, 0), LetterMult, 2) board.add_special(V2(10, 7), LetterMult, 2) board.add_special(V2(9, 6), LetterMult, 3) board.add_special(V2(8, 5), LetterMult, 4) bag = list("".join((super_ldist if spr else ldist).values())) random.shuffle(self.players) random.shuffle(bag) turn = 0 bag_empty_msg = False while bag or all(p.hand for p in self.players): for p in self.players: while bag and len(p.hand) < 7: p.hand.append(bag.pop()) if not (bag or bag_empty_msg): await self.send("The bag is empty!") bag_empty_msg = True await p.send_hand() img = board.render().xn(3).img img.save("scrabble.png") playing = self.players[turn] await self.channel.send("It's %s's turn!" % playing.name, file=discord.File("scrabble.png")) while True: move = await self.wait_for_text( playing, "Make a move (e.g. h8 down gherkin), discard tiles, or pass.", False) move = move.lower() msplit = move.split() if move == "pass": break elif msplit[0] == "discard": if len(msplit) != 2: await self.send( "Invalid discard - example: discard etofg") elif not bag: await self.send( "The bag is empty - discarding wouldn't do anything!" ) else: old_hand = playing.hand.copy() for l in msplit[1]: if l in playing.hand: playing.hand.remove(l) else: await self.send("You don't have a %s!" % l.upper()) playing.hand = old_hand break else: bag.extend(list(msplit[1])) random.shuffle(bag) await self.send("Discard successful!") break else: try: old_hand = playing.hand.copy() coords, d, word = move.split() coords = coords_to_v(coords) d = {"down": vector.down, "right": vector.right}[d] try: b = board.copy() placed, score = b.place_and_score( coords, d, word, [ n for n, l in enumerate(word) if l not in playing.hand ]) for l in placed: if l in playing.hand: playing.hand.remove(l) elif "*" in playing.hand: playing.hand.remove("*") else: playing.hand = old_hand raise WordError( "You don't have those letters!") else: board = b playing.points += score await self.send("Move successful: %s %s" % (word.upper(), score)) break except WordError as e: await self.send(e.msg) except (ValueError, KeyError): await self.send("Invalid move format!") turn += 1 turn %= len(self.players) await self.show_scoreboard() #TODO - subtract points for letters left await self.end_points()
def rotend(): return V2.rotation(self.hull[-2], self.hull[-1], p) == self.rotation
def rotstart(): return V2.rotation(self.hull[0], self.hull[1], p) == self.rotation
def render_card_array(ca: typing.List[pimg.PImg]): img = pimg.PImg.filled(V2(WIDTH * len(ca), HEIGHT + EXTRA), BACK) for n, c in enumerate(ca): img.blit(c, V2(WIDTH * n, EXTRA)) img.write(str(n + 1), bigbas, V2(WIDTH * n + WIDTH / 2, EXTRA / 2)) return img