Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import random
- import sys
- import math
- from copy import deepcopy
- def idebug(*args):
- return
- print(*args, file=sys.stderr)
- def debug(*args):
- # return
- print(*args, file=sys.stderr)
- WIDTH, HEIGHT = 9, 7
- ALIGNEMENT = 4
- def get_valid_actions(board: list):
- actions = []
- for action in range(WIDTH):
- room = [i for i in range(HEIGHT) if board[i][action] == '.']
- if room:
- actions.append(action)
- return actions
- def poids_cases():
- """Calcule le poids des cases en fonction de la dimension de la grille et du nombre de pions à aligner pour gagner"""
- """[3,4,5,7,5,4,3,4,6,8,10,8,6,4,5,8,11,13,11,8,5,5,8,11,13,11,8,5,4,6,8,10,8,6,4,3,4,5,7,5,4,3] pour une grille 7x6 avec 4 pions à aligner"""
- poids = [0] * WIDTH * HEIGHT
- # Sur les horizontales
- for j in range(HEIGHT):
- for i in range(WIDTH - ALIGNEMENT + 1):
- for k in range(ALIGNEMENT):
- poids[WIDTH * j + i + k] += 1
- # Sur les verticales
- for j in range(HEIGHT - ALIGNEMENT + 1):
- for i in range(WIDTH):
- for k in range(ALIGNEMENT):
- poids[WIDTH * j + i + k * WIDTH] += 1
- # Sur les diagonales montantes
- for j in range(HEIGHT - ALIGNEMENT + 1):
- for i in range(WIDTH - ALIGNEMENT + 1):
- for k in range(ALIGNEMENT):
- poids[WIDTH * j + i + k * WIDTH + k] += 1
- # Sur les diagonales descendantes
- for j in range(ALIGNEMENT - 1, HEIGHT):
- for i in range(WIDTH - ALIGNEMENT + 1):
- for k in range(ALIGNEMENT):
- poids[WIDTH * j + i - k * WIDTH + k] += 1
- return poids
- # Drop chips in the columns.
- # Connect at least 4 of your chips in any direction to win.
- def display_board(board: list):
- board_print = ""
- for i in range(HEIGHT):
- for j in range(WIDTH):
- board_print += board[i][j] + " "
- board_print += "\n"
- debug(board_print)
- def update_board(board: list, col: int, player_id: int):
- row = max([i for i in range(HEIGHT) if board[i][col] == '.'])
- board[row][col] = str(player_id)
- def three_check(p: str, board: list):
- for i in range(HEIGHT):
- for j in range(WIDTH):
- if board[i][j] == p:
- if i + 2 < HEIGHT and j + 2 < WIDTH and board[i + 1][j + 1] == p and board[i + 2][j + 2] == p: # Diagonal Right Down Check
- debug(f'Diagonal Right Down Check')
- return p
- elif j + 2 < WIDTH and board[i][j + 1] == p and board[i][j + 2] == p: # Horizontal Check
- debug(f'Horizontal Check')
- return p
- elif i >= 2 and i - 2 < HEIGHT and j + 3 < WIDTH and board[i - 1][j + 1] == p and board[i - 2][j + 2] == p: # Diagonal Right Up Check
- debug(f'Diagonal Right Up Check')
- return p
- elif i + 2 < HEIGHT and board[i + 1][j] == p and board[i + 2][j] == p: # Vertical Check
- debug(f'Vertical Check')
- return p
- def win_check(p: str, board: list):
- for i in range(HEIGHT):
- for j in range(WIDTH):
- if board[i][j] == p:
- if i + 3 < HEIGHT and j + 3 < WIDTH and board[i + 1][j + 1] == p and board[i + 2][j + 2] == p and board[i + 3][j + 3] == p: # Diagonal Right Down Check
- debug(f'Diagonal Right Down Check')
- return p
- elif j + 3 < WIDTH and board[i][j + 1] == p and board[i][j + 2] == p and board[i][j + 3] == p: # Horizontal Check
- debug(f'Horizontal Check')
- return p
- elif i >= 3 and i - 3 < HEIGHT and j + 3 < WIDTH and board[i - 1][j + 1] == p and board[i - 2][j + 2] == p and board[i - 3][j + 3] == p: # Diagonal Right Up Check
- debug(f'Diagonal Right Up Check')
- return p
- elif i + 3 < HEIGHT and board[i + 1][j] == p and board[i + 2][j] == p and board[i + 3][j] == p: # Vertical Check
- debug(f'Vertical Check')
- return p
- def count_three_chips(p: str, board: list):
- count = 0
- for i in range(HEIGHT):
- for j in range(WIDTH):
- if board[i][j] == p:
- if i + 2 < HEIGHT and j + 2 < WIDTH and board[i + 1][j + 1] == p and board[i + 2][j + 2] == p: # Diagonal Right Down Check
- # debug(f'Diagonal Right Down Check')
- count += 1
- if j + 2 < WIDTH and board[i][j + 1] == p and board[i][j + 2] == p: # Horizontal Check
- # debug(f'Horizontal Check')
- count += 1
- if i >= 2 and i - 2 < HEIGHT and j + 3 < WIDTH and board[i - 1][j + 1] == p and board[i - 2][j + 2] == p: # Diagonal Right Up Check
- # debug(f'Diagonal Right Up Check')
- count += 1
- if i + 2 < HEIGHT and board[i + 1][j] == p and board[i + 2][j] == p: # Vertical Check
- # debug(f'Vertical Check')
- count += 1
- return count
- def count_two_chips(p: str, board: list):
- count = 0
- for i in range(HEIGHT):
- for j in range(WIDTH):
- if board[i][j] == p:
- if i + 1 < HEIGHT and j + 1 < WIDTH and board[i + 1][j + 1] == p: # Diagonal Right Down Check
- # debug(f'Diagonal Right Down Check')
- count += 1
- if j + 1 < WIDTH and board[i][j + 1] == p: # Horizontal Check
- # debug(f'Horizontal Check')
- count += 1
- if i >= 1 and i - 1 < HEIGHT and j + 3 < WIDTH and board[i - 1][j + 1] == p: # Diagonal Right Up Check
- # debug(f'Diagonal Right Up Check')
- count += 1
- if i + 1 < HEIGHT and board[i + 1][j] == p: # Vertical Check
- # debug(f'Vertical Check')
- count += 1
- return count
- ''' poids = [3, 4, 5, 7, 7, 7, 5, 4, 3,
- 4, 6, 8, 10, 10, 10, 8, 6, 4,
- 5, 8, 11, 13, 13, 13, 11, 8, 5,
- 7, 10, 13, 16, 16, 16, 13, 10, 7,
- 5, 8, 11, 13, 13, 13, 11, 8, 5,
- 4, 6, 8, 10, 10, 10, 8, 6, 4,
- 3, 4, 5, 7, 7, 7, 5, 4, 3]
- '''
- ''' 3 4 5 7 5 4 3
- 4 6 8 10 8 6 4
- 5 8 11 13 11 8 5
- 5 8 11 13 11 8 5
- 4 6 8 10 8 6 4
- 3 4 5 7 5 4 3
- '''
- def get_action_score(player_id: int, action: int, board: list):
- row = max([i for i in range(HEIGHT) if board[i][action] == '.'])
- weight = poids[row * WIDTH + action]
- p = str(player_id)
- two_chips_count = count_two_chips(p, board)
- three_chips_count = count_three_chips(p, board)
- score = 1
- new_board = deepcopy(board)
- update_board(new_board, action, player_id)
- if win_check(p, new_board) == p:
- return math.inf
- else:
- three_chips_new_count = count_three_chips(p, new_board)
- new_three_chips = three_chips_new_count - three_chips_count
- score += new_three_chips * 100
- two_chips_new_count = count_two_chips(p, new_board)
- new_two_chips = two_chips_new_count - two_chips_count
- score += new_two_chips * 10
- return score + weight
- # my_id: 0 or 1 (Player 0 plays first)
- # opp_id: if your index is 0, this will be 1, and vice versa
- my_id, opp_id = [int(i) for i in input().split()]
- idebug(my_id, opp_id)
- is_start = True
- poids = poids_cases()
- # game loop
- while True:
- board = []
- actions = []
- turn_index = int(input()) # starts from 0; As the game progresses, first player gets [0,2,4,...] and second player gets [1,3,5,...]
- idebug(turn_index)
- for i in range(7):
- board_row = input() # one row of the board (from top to bottom)
- idebug(board_row)
- board.append(list(board_row))
- num_valid_actions = int(input()) # number of unfilled columns in the board
- idebug(num_valid_actions)
- valid_actions = []
- for i in range(num_valid_actions):
- action = int(input()) # a valid column index into which a chip can be dropped
- idebug(action)
- valid_actions.append(action)
- opp_previous_action = int(input()) # opponent's previous chosen column index (will be -1 for first player in the first turn)
- idebug(opp_previous_action)
- player_wins = False
- opponent_wins = False
- best_action = None
- action = None
- if is_start:
- if opp_previous_action in range(3, 6):
- action = 'STEAL'
- else:
- action = random.choice([3, 4, 5])
- is_start = False
- else:
- # check if player wins
- for action in valid_actions:
- new_board = deepcopy(board)
- # debug(f'action = {action}')
- update_board(new_board, action, my_id)
- p = str(my_id)
- if win_check(p, new_board) == p:
- best_action = action
- player_wins = True
- break
- if player_wins:
- action = best_action
- else:
- # check if opponent wins
- for action in valid_actions:
- new_board = deepcopy(board)
- update_board(new_board, action, opp_id)
- p = str(opp_id)
- if win_check(p, new_board) == p:
- debug(f'Player #{opp_id} wins with action {action}!')
- display_board(new_board)
- best_action = action
- opponent_wins = True
- break
- if opponent_wins:
- action = best_action
- else:
- actions_candidates = []
- debug(f'valid_actions: {valid_actions}')
- debug(f'board = {board}')
- for max_action in valid_actions:
- opponent_wins = False
- max_board = deepcopy(board)
- update_board(max_board, max_action, my_id)
- min_valid_actions = get_valid_actions(max_board)
- # debug(f'opp_valid_actions after p action {action} = {opp_valid_actions}')
- for min_action in min_valid_actions:
- min_board = deepcopy(max_board)
- update_board(min_board, min_action, opp_id)
- p = str(opp_id)
- if win_check(p, min_board) == p:
- debug(f'Opp WINS after action {min_action}!!!')
- opponent_wins = True
- break
- if not opponent_wins:
- actions_candidates.append(max_action)
- ''' Easiest way '''
- op_actions = [(action, get_action_score(opp_id, action, board)) for action in actions_candidates]
- op_best_action, op_best_score = max(op_actions, key=lambda x: x[1])
- debug(f'op_best_action = {op_best_action}')
- player_actions = [(action, get_action_score(my_id, action, board)) for action in actions_candidates]
- player_best_action, player_best_score = max(op_actions, key=lambda x: x[1])
- debug(f'op_best_action = {op_best_action}')
- ''' Other way '''
- # debug(f'actions_candidates: {actions_candidates}')
- # player_actions = [(action, get_action_score(my_id, action, board)) for action in actions_candidates]
- # best_score = max(player_actions, key=lambda x: x[1])[1]
- # actions_candidates = [action for action, score in player_actions if score == best_score]
- # player_best_action = random.choice(actions_candidates)
- # # player_best_action, player_best_score = max(player_actions, key=lambda x: x[1])
- # debug(f'player_best_action = {player_best_action}')
- ''' Set action '''
- action = player_best_action if player_best_score > op_best_score else op_best_action
- if action != 'STEAL':
- row = max([i for i in range(HEIGHT) if board[i][action] == '.'])
- weight = poids[row * WIDTH + action]
- debug(f'score action {action}, weight {weight} = {get_action_score(my_id, action, board)}')
- # debug(poids)
- # display_board(board)
- # Output a column index to drop the chip in. Append message to show in the viewer.
- print(f'{action}')
- ''' poids = [3, 4, 5, 7, 7, 7, 5, 4, 3,
- 4, 6, 8, 10, 10, 10, 8, 6, 4,
- 5, 8, 11, 13, 13, 13, 11, 8, 5,
- 7, 10, 13, 16, 16, 16, 13, 10, 7,
- 5, 8, 11, 13, 13, 13, 11, 8, 5,
- 4, 6, 8, 10, 10, 10, 8, 6, 4,
- 3, 4, 5, 7, 7, 7, 5, 4, 3]
- '''
Advertisement
Add Comment
Please, Sign In to add comment