Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from collections import defaultdict
- from random import shuffle
- import numpy as np
- start_time = time()
- class Board():
- def __init__(self):
- self.bag = self.create_new_bag()
- self.board = self.create_new_board()
- self.words = self.get_first_letter_wordlist()
- self.level = 3
- self.move_history = []
- self.points = 0
- self.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}
- self.level1_bonus = {
- (1, 1): ('L', 3),
- (5, 1): ('L', 3),
- (2, 2): ('L', 2),
- (4, 4): ('L', 2),
- (3, 3): ('W', 2),
- (2, 4): ('L', 2),
- (4, 4): ('L', 2),
- (1, 5): ('L', 3),
- (5, 5): ('L', 3)
- }
- self.level2_bonus = {
- (1, 1): ('L', 3),
- (5, 1): ('L', 3),
- (2, 2): ('L', 2),
- (4, 4): ('L', 2),
- (3, 3): ('W', 2),
- (2, 4): ('L', 2),
- (4, 4): ('L', 2),
- (1, 5): ('L', 3),
- (5, 5): ('L', 3),
- (3, 0): ('W', 2),
- (3, 6): ('W', 2),
- (0, 3): ('W', 2),
- (6, 3): ('W', 2)
- }
- self.level3_bonus = {
- (1, 1): ('L', 3),
- (5, 1): ('L', 3),
- (2, 2): ('L', 2),
- (4, 4): ('L', 2),
- (3, 3): ('W', 2),
- (2, 4): ('L', 2),
- (4, 4): ('L', 2),
- (1, 5): ('L', 3),
- (5, 5): ('L', 3),
- (3, 0): ('W', 2),
- (3, 6): ('W', 2),
- (0, 3): ('W', 2),
- (6, 3): ('W', 2),
- (0, 0): ('W', 3),
- (6, 0): ('W', 3),
- (0, 6): ('W', 3),
- (6, 6): ('W', 3)
- }
- def get_wordlist(self):
- # TODO Change word to a dictionary for faster stuff?
- with open('game_words.txt') as f:
- words = []
- for line in f:
- line = line.rstrip()
- i = line.index('"')
- line = line[i + 2:-3]
- split_words = line.split('_')
- words += split_words
- return words
- def get_first_letter_wordlist(self):
- with open('game_words.txt') as f:
- words = defaultdict(list)
- for line in f:
- line = line.rstrip()
- i = line.index('"')
- line = line[i + 2:-3]
- split_words = line.split('_')
- for word in split_words:
- if len(word) > 2:
- words[word[0]].append(word)
- return words
- def create_new_board(self):
- board = []
- for x in range(7):
- board.append([])
- for y in range(7):
- for x in range(7):
- board[y].append(self.bag.pop())
- board = np.array(board)
- return board
- def update_board_from_textfile(self):
- with open('blast_board.txt') as f:
- y = 0
- x = 0
- for line in f:
- for letter in line.rstrip():
- self.board[y][x] = letter
- x += 1
- x = 0
- y += 1
- def create_new_bag(self):
- bag = []
- tiles = 'A-9, B-2, C-2, D-4, E-12, F-2, G-3, H-2, I-9, J-1, K-1, L-4, M-2, N-6, O-8, P-2, Q-1, R-6, S-4, T-6, U-4, V-2, W-2, X-1, Y-2, Z-1'
- tiles = tiles.split(',')
- for pair in tiles:
- letter, num = pair.split('-')
- letter = letter.lower()
- letter = letter.replace(' ', '')
- num = int(num)
- for x in range(num):
- bag.append(letter)
- shuffle(bag)
- return bag
- def display_ascii_board(self):
- print(self.board)
- def get_all_unconnected_words(self):
- ans = {}
- letter_counts = self.get_letter_counts_of_board()
- for word in self.words:
- if self.check_if_enough_letters_for_word(letter_counts, word):
- ans[word] = 1
- return ans
- def get_letter_counts_of_board(self):
- letters = defaultdict(int)
- for row in self.board:
- for letter in row:
- letters[letter] += 1
- return letters
- def check_if_enough_letters_for_word(self, letter_counts, word):
- for letter in word:
- if word.count(letter) > letter_counts[letter]:
- return False
- return True
- def check_if_move_valid(self, pos):
- x = pos[0]
- y = pos[1]
- if x < 0 or x >= 6:
- return False
- if y < 0 or y >= 6:
- return False
- return self.board[y][x] != '!'
- def get_neighbors_of_pos(self, board, pos):
- x = pos[0]
- y = pos[1]
- possible_moves = [(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)]
- valid_moves = []
- for move in possible_moves:
- if self.check_if_move_valid(move):
- valid_moves.append(move)
- return valid_moves
- def check_if_word_is_possible(self, word, constraints):
- start_positions = self.get_pos_of_letter_on_board(word[0][0])
- if len(start_positions) == 0:
- return False
- for pos in start_positions:
- copy_board = self.board.copy()
- result = self.try_to_build_word(word, '', copy_board, pos)
- if result != False:
- # Check for constraints
- for pos in constraints:
- if pos not in word[1]:
- return False
- return result
- return False
- def check_if_words_are_possible_from_pos(self, constraints, pos):
- possible_words = []
- x = pos[0]
- y = pos[1]
- start_letter = self.board[y][x]
- for word in self.words[start_letter]:
- word = (word, [])
- copy_board = self.board.copy()
- result = self.try_to_build_word(word, '', copy_board, pos)
- if result != False:
- # Check for constraints
- for pos in constraints:
- if pos not in word[1]:
- return False
- possible_words.append(result)
- return possible_words
- def check_if_string_is_a_substring_of_words(self, s, words):
- for word in list(words.keys()):
- if word.startswith(s):
- return True
- return False
- def get_pos_of_letter_on_board(self, letter):
- ans = []
- for y in range(7):
- for x in range(7):
- if self.board[y][x] == letter:
- ans.append((x, y))
- return ans
- def try_to_build_word(self, goal, s, board, pos):
- """Recursive, do not reference self.board"""
- x = pos[0]
- y = pos[1]
- s += board[y][x]
- goal[1].append(pos)
- # If it matches the goal, got a match
- if s == goal[0]:
- return goal
- # If it isn't the correct substring, cancel out
- if not goal[0].startswith(s):
- goal[1].pop()
- return False
- # Isn't a match, but could be. Continue
- copy_board = board.copy()
- copy_board[y][x] = '!'
- # Get possible moves
- moves = self.get_neighbors_of_pos(copy_board, (x, y))
- # No more possible moves, no bueno
- if len(moves) == 0:
- goal[1].pop()
- return False
- # Check through other possiblities
- for move in moves:
- result = self.try_to_build_word(goal, s, copy_board, move)
- if result != False:
- return result
- goal[1].pop()
- return False
- def get_word_value(self, word_path):
- """Returns the value of the word. Word_path is a tuple of word and list of paths"""
- word, path = word_path
- value = 0
- multiplier = 0
- for letter, p in zip(word, path):
- base_letter_value = self.score[letter]
- if self.level == 1:
- if p in self.level1_bonus:
- bonus = self.level1_bonus[p]
- if bonus[0] == 'L':
- base_letter_value *= bonus[1]
- else:
- multiplier += bonus[1]
- elif self.level == 2:
- if p in self.level2_bonus:
- bonus = self.level2_bonus[p]
- if bonus[0] == 'L':
- base_letter_value *= bonus[1]
- else:
- multiplier += bonus[1]
- elif self.level == 3:
- if p in self.level3_bonus:
- bonus = self.level3_bonus[p]
- if bonus[0] == 'L':
- base_letter_value *= bonus[1]
- else:
- multiplier += bonus[1]
- value += base_letter_value
- if multiplier > 0:
- value *= multiplier
- if len(word) == 4:
- value += 10
- if len(word) == 5:
- value += 20
- if len(word) == 6:
- value += 30
- if len(word) == 7:
- value += 50
- if len(word) == 8:
- value += 60
- if len(word) == 9:
- value += 70
- if len(word) == 10:
- value += 80
- if len(word) == 11:
- value += 90
- if len(word) == 12:
- value += 100
- if len(word) == 13:
- value += 110
- if len(word) == 14:
- value += 120
- if len(word) == 15:
- value += 130
- return value
- def get_playable_moves(self, constraints):
- """Constraints is a list of positions that must be included in the result"""
- unconnected_words = self.get_all_unconnected_words()
- playable_words = []
- for word in unconnected_words:
- word = (word, [])
- result = self.check_if_word_is_possible(word, constraints)
- if result != False:
- playable_words.append(result)
- playable_words.sort(key=lambda x: len(x[0]), reverse=True)
- return playable_words
- def get_playable_moves_via_squares(self, constraints):
- """Constraints is a list of positions that must be included in the result"""
- playable_words = []
- for y in range(7):
- for x in range(7):
- result = self.check_if_words_are_possible_from_pos(constraints, (x, y))
- if result != False:
- playable_words += result
- return playable_words
- def get_best_scoring_move_and_path(self, constraints=[]):
- #playable_words = self.get_playable_moves(constraints)
- playable_words = self.get_playable_moves_via_squares(constraints)
- top_scoring = 0
- best = None
- for word in playable_words:
- value = self.get_word_value(word)
- if value > top_scoring:
- best = word
- top_scoring = value
- return best
- def play_move(self, path):
- for pos in path:
- x = pos[0]
- y = pos[1]
- self.bag.append(self.board[y][x])
- self.board[y][x] = '!'
- shuffle(self.bag)
- def update_from_tiles(self, tile_grid):
- for y in range(7):
- for x in range(7):
- if (x, y) in tile_grid:
- self.board[y][x] = tile_grid[(x, y)].letter
- else:
- self.board[y][x] = '!'
- def restock_board(self):
- shuffle(self.bag)
- ans = []
- for y in range(7):
- for x in range(7):
- if self.board[y][x] == '!':
- self.board[y][x] = self.bag.pop()
- ans.append((x, y))
- return ans
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement