Commit 8bcae0a7 authored by Prathisha Kunnumbrath Manden's avatar Prathisha Kunnumbrath Manden
Browse files

Separated game and agent classes, experiments on parameters

parent f591bb61
......@@ -3,12 +3,106 @@ import collections
import random
import time
board_horizontal_matches = []
board_vertical_matches = []
def check_matches(board, get_matches_flag):
global board_horizontal_matches
global board_vertical_matches
# function for checking all the matches in the board
if not get_matches_flag:
# check the whole board for vertical matches and return true if match found
for j in range(len(board[0])):
count = 1
for i in range(len(board) - 1):
if (board[i][j] == board[i + 1][j]):
count += 1
else:
count = 1
if (count >= 3):
return True
# check the whole board for horizontal matches and return true if match found
for i in range(len(board)):
count = 1
for j in range(len(board[0]) - 1):
if (board[i][j] == board[i][j+1]):
count += 1
else:
count = 1
if (count >= 3):
return True
else:
board_horizontal_matches = []
for i in range(len(board)):
horizontal_chain = []
for j in range(len(board[0])-1):
chain_continue_flag = False
if (board[i][j] == board[i][j+1]):
if (i,j) not in horizontal_chain:
horizontal_chain.append((i,j))
horizontal_chain.append((i,j+1))
chain_continue_flag = True
if (j == len(board[0]) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(horizontal_chain)>=3:
board_horizontal_matches.append(horizontal_chain)
break
else:
horizontal_chain.clear()
board_vertical_matches = []
for j in range(len(board[0])):
vertical_chain = []
for i in range(len(board) - 1):
chain_continue_flag = False
if (board[i][j] == board[i+1][j]):
if((i,j) not in vertical_chain):
vertical_chain.append((i, j))
vertical_chain.append((i+1, j))
chain_continue_flag = True
if (i == len(board) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(vertical_chain)>=3:
board_vertical_matches.append(vertical_chain)
break
else:
vertical_chain.clear()
if (board_horizontal_matches or board_vertical_matches):
return True
return False
def find_moves(board):
# function for checking if there is any possible move in the board
global co_ords
co_ords = []
# vertical swap and check for matches
for i in range(len(board) - 1):
for j in range(len(board[0])):
board_copy = board.copy()
board_copy[i][j], board_copy[i+1][j] = board_copy[i+1][j], board_copy[i][j]
match = check_matches(board_copy, False)
if match:
co_ords.append([(i, j), (i+1, j)])
# horizontal swap and check for matches
for i in range(len(board)):
for j in range(len(board[0]) - 1):
board_copy = board.copy()
board_copy[i][j], board_copy[i][j+1] = board_copy[i][j+1], board_copy[i][j]
match = check_matches(board_copy, False)
if match:
co_ords.append([(i, j), (i, j+1)])
return co_ords
class Game:
score = 0
game_grid = []
possible_move_positions = []
board_horizontal_matches = []
board_vertical_matches = []
# grid size and range of colors
grid_size = 5, 5
......@@ -23,12 +117,15 @@ class Game:
print("Generated Board : ")
print(self.game_grid)
self.possible_move_positions = self.get_possible_move_positions(self.game_grid)
self.input_tiles()
print("self.possible_move_positions==", self.possible_move_positions)
def get_board(self):
return self.game_grid
def validate_board(self, board):
new_board = board
# check whether the board contains any 3-matches
while self.check_matches(new_board, False):
while check_matches(new_board, False):
new_board = self.shuffle_board(new_board)
return new_board
......@@ -38,116 +135,23 @@ class Game:
board = board.reshape(self.grid_size)
return board
def check_matches(self, board, get_matches_flag):
# function for checking all the matches in the board
if not get_matches_flag:
# check the whole board for vertical matches and return true if match found
for j in range(len(board[0])):
count = 1
for i in range(len(board) - 1):
if (board[i][j] == board[i + 1][j]):
count += 1
else:
count = 1
if (count >= 3):
return True
# check the whole board for horizontal matches and return true if match found
for i in range(len(board)):
count = 1
for j in range(len(board[0]) - 1):
if (board[i][j] == board[i][j+1]):
count += 1
else:
count = 1
if (count >= 3):
return True
else:
self.board_horizontal_matches = []
for i in range(len(board)):
horizontal_chain = []
for j in range(len(board[0])-1):
chain_continue_flag = False
if (board[i][j] == board[i][j+1]):
if (i,j) not in horizontal_chain:
horizontal_chain.append((i,j))
horizontal_chain.append((i,j+1))
chain_continue_flag = True
if (j == len(self.game_grid[0]) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(horizontal_chain)>=3:
self.board_horizontal_matches.append(horizontal_chain)
break
else:
horizontal_chain.clear()
self.board_vertical_matches = []
for j in range(len(board[0])):
vertical_chain = []
for i in range(len(board) - 1):
chain_continue_flag = False
if (board[i][j] == board[i+1][j]):
if((i,j) not in vertical_chain):
vertical_chain.append((i, j))
vertical_chain.append((i+1, j))
chain_continue_flag = True
if (i == len(board) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(vertical_chain)>=3:
self.board_vertical_matches.append(vertical_chain)
break
else:
vertical_chain.clear()
if (self.board_horizontal_matches or self.board_vertical_matches):
return True
return False
def get_possible_move_positions(self, board):
self.possible_move_positions = self.find_moves(board)
self.possible_move_positions = find_moves(board)
while not self.possible_move_positions:
board = self.shuffle_board(board)
self.possible_move_positions = self.find_moves(board)
self.possible_move_positions = find_moves(board)
return self.possible_move_positions
def input_tiles(self):
# move = self.possible_move_positions.pop() #pop the last pair of co-ordinates from the possible moves for swap
move = random.choice(self.possible_move_positions)
def input_tiles(self, move):
(coord1, coord2) = move
print("One move taken from possible moves: ", coord1, coord2)
is_valid_move = self.validate_move(coord1, coord2)
if is_valid_move:
self.swap_tiles(coord1, coord2)
else:
print("Invalid move!!")
return is_valid_move
def find_moves(self, board):
# function for checking if there is any possible move in the board
global co_ords
co_ords = []
# vertical swap and check for matches
for i in range(len(board) - 1):
for j in range(len(board[0])):
board_copy = board.copy()
board_copy[i][j], board_copy[i+1][j] = board_copy[i+1][j], board_copy[i][j]
match = self.check_matches(board_copy, False)
if match:
co_ords.append([(i, j), (i+1, j)])
# horizontal swap and check for matches
for i in range(len(board)):
for j in range(len(board[0]) - 1):
board_copy = board.copy()
board_copy[i][j], board_copy[i][j+1] = board_copy[i][j+1], board_copy[i][j]
match = self.check_matches(board_copy, False)
if match:
co_ords.append([(i, j), (i, j+1)])
return co_ords
def swap_tiles(self, coord1, coord2):
# function for swapping the valid move and checking for the matches in
# corresponding rows and columns
......@@ -278,15 +282,15 @@ class Game:
print("Tiles added:")
print(self.game_grid)
avalanche = self.check_matches(self.game_grid, True)
avalanche = check_matches(self.game_grid, True)
if avalanche:
print("Avalanche matches!")
self.shift_tiles(self.board_horizontal_matches, self.board_vertical_matches)
self.shift_tiles(board_horizontal_matches, board_vertical_matches)
else:
self.game_grid = self.validate_board(self.game_grid)
time.sleep(2)
self.possible_move_positions = self.get_possible_move_positions(self.game_grid)
self.input_tiles()
Agent().select_move(self.game_grid)
def add_score(self, removed_tiles):
self.score += len(removed_tiles)
......@@ -296,6 +300,30 @@ class Game:
if ([coord1[0], coord1[1]], [coord2[0], coord2[1]]) or ([coord2[0], coord2[1]], [coord1[0], coord1[1]]) in self.possible_move_positions:
return True
if __name__ == "__main__":
g = Game()
g.init_board()
\ No newline at end of file
class Agent:
moves = []
game_board = []
def select_move(self, config):
print("board is:", config)
move = random.choice(find_moves(config))
return move
next_move = []
g = Game()
g.init_board()
current_config= g.get_board()
agent = Agent()
game_length = int(input("Enter number of switches to perform (or endless) : "))
move_validity = False
while(game_length > 0):
next_move = agent.select_move(current_config)
move_validity = g.input_tiles(next_move)
if not move_validity:
print ("Invalid move. Try again!")
else:
game_length = game_length-1
current_config = g.get_board()
Grid Size,Number of Colors,Average time taken to generate a valid board (in milliseconds)
"(5, 5)",3,3.16770792
"(5, 5)",4,3.267569542
"(5, 5)",5,3.380012512
"(5, 5)",6,3.086788654
"(5, 5)",7,2.874000072
"(5, 5)",8,5.23014307
"(5, 5)",9,3.571920395
"(5, 5)",10,3.746647835
"(5, 5)",11,4.589476585
"(5, 5)",12,4.572501183
"(5, 5)",13,4.627959728
"(5, 5)",14,8.046340942
"(5, 5)",15,8.740139008
"(5, 5)",16,11.72768116
"(5, 5)",17,7.936470509
"(5, 5)",18,8.710339069
"(5, 5)",19,8.044569492
"(7, 7)",3,134.7087598
"(7, 7)",4,12.1767807
"(7, 7)",5,21.85652256
"(7, 7)",6,13.68294239
"(7, 7)",7,12.69861221
"(7, 7)",8,10.73697805
"(7, 7)",9,12.66907215
"(7, 7)",10,10.71184158
"(7, 7)",11,11.39477015
"(7, 7)",12,13.56379032
"(7, 7)",13,18.3227396
"(7, 7)",14,15.33020258
"(7, 7)",15,12.37864971
"(7, 7)",16,16.99441195
"(7, 7)",17,16.27599239
"(7, 7)",18,16.45984888
"(7, 7)",19,15.88099003
"(7, 7)",20,18.46929073
"(7, 7)",21,19.28073883
"(7, 7)",22,20.83427191
"(7, 7)",23,22.36753941
\ No newline at end of file
import numpy as np
import collections
import random
import time
import csv
import os
import math
board_horizontal_matches = []
board_vertical_matches = []
num_shuffles = 0 # count for getting total number of shuffles
total_moves = 0 # count for getting average number of moves per shuffle
#three_matches_count = 0 # count of occurences of three-matches
no_moves_count = 0 # count of occurences of no moves
config_count = 0 #count of total number of board configurations
possible_moves_count = 0 # count of total number of possible moves
avalanche_match_count = 0 # count the number of avalanche matches occurred
score = 0
def check_matches(board, get_matches_flag):
global board_horizontal_matches
global board_vertical_matches
# function for checking all the matches in the board
if not get_matches_flag:
# check the whole board for vertical matches and return true if match found
for j in range(len(board[0])):
count = 1
for i in range(len(board) - 1):
if (board[i][j] == board[i + 1][j]):
count += 1
else:
count = 1
if (count >= 3):
return True
# check the whole board for horizontal matches and return true if match found
for i in range(len(board)):
count = 1
for j in range(len(board[0]) - 1):
if (board[i][j] == board[i][j+1]):
count += 1
else:
count = 1
if (count >= 3):
return True
else:
board_horizontal_matches = []
for i in range(len(board)):
horizontal_chain = []
for j in range(len(board[0])-1):
chain_continue_flag = False
if (board[i][j] == board[i][j+1]):
if (i,j) not in horizontal_chain:
horizontal_chain.append((i,j))
horizontal_chain.append((i,j+1))
chain_continue_flag = True
if (j == len(board[0]) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(horizontal_chain)>=3:
board_horizontal_matches.append(horizontal_chain)
break
else:
horizontal_chain.clear()
board_vertical_matches = []
for j in range(len(board[0])):
vertical_chain = []
for i in range(len(board) - 1):
chain_continue_flag = False
if (board[i][j] == board[i+1][j]):
if((i,j) not in vertical_chain):
vertical_chain.append((i, j))
vertical_chain.append((i+1, j))
chain_continue_flag = True
if (i == len(board) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(vertical_chain)>=3:
board_vertical_matches.append(vertical_chain)
break
else:
vertical_chain.clear()
if (board_horizontal_matches or board_vertical_matches):
return True
return False
def find_moves(board):
# function for checking if there is any possible move in the board
global co_ords
co_ords = []
# vertical swap and check for matches
for i in range(len(board) - 1):
for j in range(len(board[0])):
board_copy = board.copy()
board_copy[i][j], board_copy[i+1][j] = board_copy[i+1][j], board_copy[i][j]
match = check_matches(board_copy, False)
if match:
co_ords.append([(i, j), (i+1, j)])
# horizontal swap and check for matches
for i in range(len(board)):
for j in range(len(board[0]) - 1):
board_copy = board.copy()
board_copy[i][j], board_copy[i][j+1] = board_copy[i][j+1], board_copy[i][j]
match = check_matches(board_copy, False)
if match:
co_ords.append([(i, j), (i, j+1)])
return co_ords
class Game:
game_grid = []
possible_move_positions = []
# grid size and range of colors
grid_size = 20, 20
color_start_range = 1
color_end_range = 101
def init_board(self):
# generate a 2D array with values between color_start_range and color_end_range
# value 0 is used later to show removed tiles and empty spaces on top of the grid
self.game_grid = np.random.randint(self.color_start_range, self.color_end_range, size=self.grid_size)
# self.game_grid = self.validate_board(init_board)
while check_matches(self.game_grid, False) or not find_moves(self.game_grid):
self.game_grid = np.random.randint(self.color_start_range, self.color_end_range, size=self.grid_size)
# print("Generated Board : ")
# print(self.game_grid)
# self.possible_move_positions = self.get_possible_move_positions(self.game_grid)
def get_board(self):
return self.game_grid
def validate_board(self, board):
#global three_matches_count
new_board = board
# check whether the board contains any 3-matches
while check_matches(new_board, False):
#three_matches_count += 1
new_board = self.shuffle_board(new_board)
return new_board
def shuffle_board(self, board):
global num_shuffles
num_shuffles += 1
# print("num shuffles : ", num_shuffles)
board = board.ravel()
np.random.shuffle(board)
board = board.reshape(self.grid_size)
return board
def get_possible_move_positions(self, board):
global no_moves_count
global config_count
global possible_moves_count
self.possible_move_positions = find_moves(board)
while not self.possible_move_positions:
no_moves_count += 1
print("No possible moves. Shuffling...")
board = self.shuffle_board(board)
self.possible_move_positions = find_moves(board)
self.game_grid = board
config_count += 1
possible_moves_count += len(self.possible_move_positions)
return self.possible_move_positions
def input_tiles(self, move):
(coord1, coord2) = move
print("One move taken from possible moves: ", coord1, coord2)
is_valid_move = self.validate_move(coord1, coord2)
if is_valid_move:
self.swap_tiles(coord1, coord2)
return is_valid_move
def swap_tiles(self, coord1, coord2):
# function for swapping the valid move and checking for the matches in
# corresponding rows and columns
self.game_grid[coord1[0]][coord1[1]], self.game_grid[coord2[0]][coord2[1]] = self.game_grid[coord2[0]][coord2[1]], self.game_grid[coord1[0]][coord1[1]]
print("Board after swapping the tiles:")
print(self.game_grid)
horizontal_matches = []
vertical_matches = []
if coord1[1] == coord2[1]: # if vertical swap is performed
for i in [coord1[0], coord2[0]]: # check the 2 rows
horizontal_chain = []
for j in range(len(self.game_grid[0])-1):
chain_continue_flag = False
if (self.game_grid[i][j] == self.game_grid[i][j+1]):
if((i,j) not in horizontal_chain):
horizontal_chain.append((i, j))
horizontal_chain.append((i, j + 1))
chain_continue_flag = True
if (j == len(self.game_grid[0]) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(horizontal_chain)>=3:
horizontal_matches.append(horizontal_chain)
break
else:
horizontal_chain.clear()
vertical_chain = []
for i in range(len(self.game_grid)-1): # check the 1 column
chain_continue_flag = False
if (self.game_grid[i][coord1[1]] == self.game_grid[i+1][coord1[1]]):
if ((i, coord1[1]) not in vertical_chain):
vertical_chain.append((i, coord1[1]))
vertical_chain.append((i+1, coord1[1]))
chain_continue_flag = True
if (i == len(self.game_grid) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(vertical_chain)>=3:
vertical_matches.append(vertical_chain)
break
else:
vertical_chain.clear()
if coord1[0] == coord2[0]: # if horizontal swap is performed
for j in [coord1[1], coord2[1]]: #check the 2 columns
vertical_chain = []
for i in range(len(self.game_grid) - 1):
chain_continue_flag = False
if (self.game_grid[i][j] == self.game_grid[i+1][j]):
if((i,j) not in vertical_chain):
vertical_chain.append((i, j))
vertical_chain.append((i+1, j))
chain_continue_flag = True
if (i == len(self.game_grid) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(vertical_chain)>=3:
vertical_matches.append(vertical_chain)
break
else:
vertical_chain.clear()
horizontal_chain = []
for j in range(len(self.game_grid[0])-1): #check the 1 row
chain_continue_flag = False
if (self.game_grid[coord1[0]][j] == self.game_grid[coord1[0]][j+1]):
if ((coord1[0], j) not in horizontal_chain):
horizontal_chain.append((coord1[0], j))
horizontal_chain.append((coord1[0],j+1))
chain_continue_flag = True
if (j == len(self.game_grid[0]) - 2):
chain_continue_flag = False
if (not chain_continue_flag):
if len(horizontal_chain)>=3:
horizontal_matches.append(horizontal_chain)
break
else:
horizontal_chain.clear()
self.shift_tiles(horizontal_matches, vertical_matches)
def shift_tiles(self, row_matches, column_matches):
# Function for shifting tiles above removed tiles
global score
matched_cells = {}
if row_matches:
for match in row_matches:
score = self.add_score(match)
for (row, col) in match:
self.game_grid[row][col] = 0