#!/usr/bin/env python import pyglet from pyglet.window import mouse from pyglet import clock from pyglet.gl import * import board from random import randint from time import time class AiTurn: def __init__(self, word, path, ai_select): self.word = word self.path = path self.start_time = time() self.time_buffer = 1 self.next_move = self.start_time + self.time_buffer self.done = False self.waiting = False self.ai_select = ai_select def update(self): # See if time for next action: if time() > self.next_move: # See if done placing move if self.waiting: self.done = True elif len(self.path) == 0: # Wait a little longer / TODO display funny message self.next_move = time() + 2.5 self.waiting = True else: red = self.path[0] self.path.pop(0) chain.append(red) make_red_highlight(red) self.next_move = time() + self.time_buffer self.ai_select.play() class Tile: def __init__(self, letter, start_pos, goal_y): self.letter = letter self.value = self.get_score(letter) self.goal_y = goal_y self.x = start_pos[0] self.y = start_pos[1] self.image = pyglet.resource.image('tile.png') # Center anchor point for rotation self.image.anchor_x = self.image.width // 2 self.image.anchor_y = self.image.height // 2 self.image = self.image.get_transform(rotate=(90 * randint(0, 3))) # Undo anchor point self.image.anchor_x = 0 self.image.anchor_y = 0 self.label = self.create_label() def create_label(self): x = self.x y = self.y letter_label = pyglet.text.Label(self.letter.upper(), 'Times New Roman', 42, x=x + 40, y=y + 40, color=(0, 0, 0, 255)) return letter_label def update(self): if self.y > self.goal_y: self.y -= 10 self.label.y -= 10 if self.y < self.goal_y: self.y = self.goal_y self.label.y = self.goal_y + 40 def draw(self): self.image.blit(self.x, self.y) self.label.draw() def get_score(self, letter): score = {"a": 1, "b": 3, "c": 3, "d": 2, "e": 1, "f": 4, "g": 2, "h": 4, "i": 1, "j": 8, "k": 5, "l": 1, "m": 3, "n": 1, "o": 1, "p": 3, "q": 10, "r": 1, "s": 1, "t": 1, "u": 1, "v": 4, "w": 4, "x": 8, "y": 4, "z": 10} return score[letter] window = pyglet.window.Window(1400, 800, "Wacky Words") # Load resources pyglet.resource.path = ['../resources'] pyglet.resource.reindex() title_image = pyglet.resource.image('Title.PNG') main_screen = pyglet.resource.image('WackyWordsMainScreenv1.png') highlight = pyglet.resource.image('highlight.png') red_highlight = pyglet.resource.image('red_highlight.png') tile = pyglet.resource.image('tile.png') player_select = pyglet.resource.media('AI_select.wav', streaming=False) ai_select = pyglet.resource.media('Player_select.wav', streaming=False) wow = pyglet.resource.media('wow.wav') ai_word_finish = pyglet.resource.media('AI_word_finish.wav') title_music = pyglet.resource.media('Title_music.wav') new_board = pyglet.resource.media('New_Board.wav') # Object lists bg_list = [] chain = [] player_chain = [] highlights = [] red_highlights = [] AI_objects = [] tile_grid = {} # Global Variables eww SCENE = 'title' NEWGAME = False preloaded = False MOUSE = False MOUSE_POS = (0, 0) STARTCLICK = False CHAIN = False CURRENT_WORD_SCORE = 0 CURRENT_WORD = '' WORD_HISTORY = [] AI_WORD_HISTORY = [] POINTS = 0 AI_POINTS = 0 AI_TURN = False AI_PAUSE = 0 # Board variables BOARD = board.Board() def create_tile(grid_id): letter = BOARD.board[grid_id[1]][grid_id[0]] x = 606 + (grid_id[0] * 113) y = 900 + (grid_id[1] * 111) tile_grid[grid_id] = Tile(letter, (x, y), 683 - (113 * grid_id[1])) def make_highlight(grid_pos): """Creates the x and y positions for a highlight""" increment = 110 x_start = 606 y_start = 794 - increment buffer = 3 x_start += (increment * grid_pos[0]) + (buffer * grid_pos[0]) y_start -= (increment * grid_pos[1]) + (buffer * grid_pos[1]) highlights.append((x_start, y_start)) def make_red_highlight(grid_pos): """Creates the x and y positions for a highlight""" increment = 110 x_start = 606 y_start = 794 - increment buffer = 3 x_start += (increment * grid_pos[0]) + (buffer * grid_pos[0]) y_start -= (increment * grid_pos[1]) + (buffer * grid_pos[1]) red_highlights.append((x_start, y_start)) @window.event def on_draw(): window.clear() glEnable(GL_BLEND) for bg in bg_list: bg.blit(0, 0) for tile in tile_grid.values(): tile.draw() for highlight_pos in highlights: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) highlight.blit(highlight_pos[0], highlight_pos[1]) for highlight_pos in red_highlights: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) red_highlight.blit(highlight_pos[0], highlight_pos[1]) # Word score if SCENE == 'main': score = pyglet.text.Label(str(CURRENT_WORD_SCORE), 'Times New Roman', 50, x=468, y=224, anchor_x='center', anchor_y='center', color=(0, 0, 255, 255)) score.draw() # Display current word if SCENE == 'main': word = pyglet.text.Label(str(CURRENT_WORD.upper()), 'Comic Sans', 40, x=300, y=487, anchor_x='center', anchor_y='center', color=(0, 0, 0, 255)) word.draw() # Display word history if SCENE == 'main': x = 80 y = 30 inc = 38 for word in WORD_HISTORY: hist_label = pyglet.text.Label(word.capitalize(), 'Arial', 20, color=(50, 50, 255, 255), x=x, y=y, anchor_x='center', anchor_y='center') hist_label.draw() y += inc # AI WORD HISTORY x = 275 y = 30 for word in AI_WORD_HISTORY: hist_label = pyglet.text.Label(word.capitalize(), 'Arial', 20, color=(255, 50, 50, 255), x=x, y=y, anchor_x='center', anchor_y='center') hist_label.draw() y += inc # Display total score if SCENE == 'main': points_label = pyglet.text.Label(str(POINTS), 'Impact', 35, color=(0, 0, 0, 255), x=100, y=615, anchor_x='center', anchor_y='center') points_label.draw() points_label = pyglet.text.Label(str(AI_POINTS), 'Impact', 35, color=(0, 0, 0, 255), x=500, y=615, anchor_x='center', anchor_y='center') points_label.draw() @window.event def on_mouse_press(x, y, button, modifiers): global MOUSE if button == mouse.LEFT: MOUSE = True @window.event def on_mouse_release(x, y, button, modifiers): global MOUSE if button == mouse.LEFT: MOUSE = False def get_grid_pos_from_mouse_click(): x = MOUSE_POS[0] y = MOUSE_POS[1] x_start = 606 y_start = 794 increment = 110 buffer = 3 if x < x_start or x > x_start + (increment * 7): return False if y > y_start or y < y_start - (increment * 7): return False x_val = 0 right = x_start + increment + buffer while x > right: right += increment + buffer x_val += 1 y_val = 0 top = y_start - increment - buffer while y < top: top -= increment - buffer y_val += 1 return x_val, y_val @window.event def on_mouse_motion(x, y, dx, dy): global MOUSE_POS MOUSE_POS = (x, y) def preload(): global preloaded title_music.play() bg_list.append(title_image) preloaded = True def get_grid_neighbors(grid_pos): x = grid_pos[0] y = grid_pos[1] neighbors = [(x, y - 1), (x + 1, y - 1), (x + 1, y), (x + 1, y + 1), (x, y + 1), (x - 1, y + 1), (x - 1, y), (x - 1, y - 1)] return neighbors def build_word_from_chain(): word = '' for pos in chain: word += BOARD.board[pos[1]][pos[0]] return word def update_positions_of_tiles(): """Traverse up the grid counting empty spots. If you meet a tile, tell it to drop""" for x in range(7): drop_count = 0 y = 6 while y >= 0: if (x, y) in tile_grid: # Change x, y if drop_count > 0: tile_grid[(x, y)].goal_y -= 113 * drop_count tile_grid[(x, y + drop_count)] = tile_grid[(x, y)] del tile_grid[(x, y)] else: drop_count += 1 y -= 1 def update(dt): global NEWGAME global BOARD global SCENE global STARTCLICK global chain global CURRENT_WORD_SCORE global CURRENT_WORD global POINTS global player_chain global AI_objects global AI_TURN global AI_WORD_HISTORY global AI_POINTS global AI_PAUSE if not preloaded: preload() if SCENE == 'main': CURRENT_WORD = build_word_from_chain() if AI_TURN and time() > AI_PAUSE: # 0101010101 ---------AI Turn -------------- 0101010010101 if len(AI_objects) == 0: ai_word, ai_path = BOARD.get_best_scoring_move_and_path() AI_objects.append(AiTurn(ai_word, ai_path, ai_select)) if AI_objects[0].done: AI_objects.clear() if len(AI_objects) == 0: # AI TURN OVER AI_WORD_HISTORY.append(CURRENT_WORD) AI_POINTS += CURRENT_WORD_SCORE red_highlights.clear() on_draw() window.flip() AI_TURN = False ai_word_finish.play() # Remove tile object from chained words for grid_pos in chain: BOARD.bag.append(tile_grid[grid_pos].letter) del tile_grid[grid_pos] # Have to rename the tiles too update_positions_of_tiles() # ---------- Update board from tiles BOARD.update_from_tiles(tile_grid) new_tiles = BOARD.restock_board() for pos in new_tiles: create_tile(pos) chain.clear() update_positions_of_tiles() # Check if it's time to change the level # TODO LEVEL CHANGE MECHANICS else: # Player's Turn if MOUSE: # If the mouse was clicked if SCENE == 'title': bg_list.clear() bg_list.append(main_screen) SCENE = 'main' new_board.play() elif SCENE == 'main': STARTCLICK = True else: # If the mouse is not clicked if STARTCLICK: # Mouseclick finished STARTCLICK = False # ---------- Main game mouse code-------------- result = get_grid_pos_from_mouse_click() if result: # -----------User clicked on the grid------------------ # Check to see if that gridspot is already highlighted # and if the gridchain is not longer than 15 grid_pos = result if len(chain) == 0: # Start a new chain player_select.play() chain.append(grid_pos) make_highlight(grid_pos) elif grid_pos in chain: # Clicked on an existing square if grid_pos == chain[-1]: # Click on the last square they made # Try to submit the word if CURRENT_WORD in BOARD.words[CURRENT_WORD[0]]: # TODO: Add a sound based on the epicness of the word wow.play() WORD_HISTORY.append(CURRENT_WORD) POINTS += CURRENT_WORD_SCORE highlights.clear() on_draw() window.flip() player_chain = chain.copy() # Remove tile object from chained words for grid_pos in chain: BOARD.bag.append(tile_grid[grid_pos].letter) del tile_grid[grid_pos] # Have to rename the tiles too update_positions_of_tiles() # ---------- Update board from tiles BOARD.update_from_tiles(tile_grid) new_tiles = BOARD.restock_board() for pos in new_tiles: create_tile(pos) chain.clear() update_positions_of_tiles() AI_TURN = True AI_PAUSE = time() + 3 else: pass # WORD IS NOT VALID, play BAD sounds or something # TODO INCORRECT WORD SOUND AND MECHANIC else: # Get rid of all highlights after that one delete_count = 0 while not chain[-1] == grid_pos: chain.pop() delete_count += 1 for _ in range(delete_count): highlights.pop() else: # Get the neighbors of the last added in the chain neighbors = get_grid_neighbors(chain[-1]) if grid_pos in neighbors: if len(chain) < 15: # Should be able to add a new highlight player_select.play() chain.append(grid_pos) make_highlight(grid_pos) else: # Start a new chain player_select.play() chain.clear() highlights.clear() chain.append(grid_pos) make_highlight(grid_pos) # ---------------- Point Handling ------------------ if len(chain) > 0: word = build_word_from_chain() score = BOARD.get_word_value((word, chain)) if score >= 0: CURRENT_WORD_SCORE = score if SCENE == 'main': # Update the tile positions for tile in tile_grid.values(): tile.update() # Update the AI for AI in AI_objects: AI.update() # See if you need to create a board if not NEWGAME: NEWGAME = True loading = pyglet.text.Label('LOADING', 'Impact', 50, x=window.width // 2, y=window.height // 2, anchor_x='center', anchor_y='center', color=(0, 0, 0, 255)) loading.background_group = 100 loading.draw() BOARD = board.Board() BOARD.fun_board() for y in range(7): for x in range(7): create_tile((x, y)) clock.schedule_interval(update, 1.0 / 60) pyglet.app.run()