From 3b5feb0d9f78550a1f2a1b99497a60f16653e779 Mon Sep 17 00:00:00 2001 From: Adrian Gunnar Lauterer Date: Sun, 25 Aug 2024 01:33:00 +0200 Subject: [PATCH] fixed --- main.py | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 156 insertions(+), 13 deletions(-) diff --git a/main.py b/main.py index 9352515..b8ae681 100755 --- a/main.py +++ b/main.py @@ -6,6 +6,7 @@ import numpy as np import random import argparse + ozai_url = 'http://localhost:8000/api/' @@ -108,6 +109,8 @@ def init_game(names=["a", "b"]): if response.status_code == 200: game_id = response.json() print("Game ID:", game_id) + #delay + sleep(7) return game_id else: return None @@ -127,7 +130,7 @@ def create_game(names=["a", "b"]): join_game(game_id, name) return game_id -def submit_action(game_id, player_name, source=0, destination=0, color="start", policy="strict"): +def submit_action(game_id, player_name, source=0, destination=0, color="start", policy="random"): # Submit an action to the game. The action is a dictionary with the keys being the action type and the values being the arguments. # Example: {"player": 0, "market": true, "factory": 0, "color": "blue", "patternLine": 0} if source != "market": @@ -143,11 +146,20 @@ def submit_action(game_id, player_name, source=0, destination=0, color="start", 'source': source, 'destination': destination } + + print(f"action {action}") response = requests.put(ozai_url + 'game/' + game_id, json=action) - if response.status_code == 200: - return True - else: - return False + print(f"response {response}") + if response.status_code != 200: + action = { + 'player': str(player_name), + 'policy': "loose", + 'color': str(color).lower(), + 'source': source, + 'destination': destination + } + response = requests.put(ozai_url + 'game/' + game_id, json=action) + return response def get_gamestate(game_id) -> GameState: response = requests.get(ozai_url + 'game/' + game_id) @@ -247,6 +259,125 @@ def strategy_2(move,GameState,player): return True return False + +def strategy_advanced_old(move, GameState, player): + if move[1] == 'floor': + # Avoid overfilling the floor + if sum(player.floor.values()) + move[3] > 7: + return False + return True + + remaining_space = move[1] + 1 - player.pattern_lines[move[1]]['number'] + + # Prioritize moves that fill the pattern line exactly, enabling a wall tile placement. + if move[3] == remaining_space: + return True + + # Deprioritize moves that will overfill a pattern line + if move[3] > remaining_space: + return False + + # Ensure that placing the tile does not block you from placing other colors on the same row + row_color_in_wall = any(player.wall[move[1]][i] == move[2] for i in range(5)) + if row_color_in_wall: + return False + + # Prioritize moves that fill pattern lines near completion (1 tile left) + if player.pattern_lines[move[1]]['number'] == remaining_space - 1: + return True + + return True + + +def strategy_advanced(move, GameState, player): + # Destructure move for clarity + factory, pattern_line, tile_color, tile_count = move + + # Floor management: Avoid overfilling the floor line + if pattern_line == 'floor': + if sum(player.floor.values()) + tile_count > 7: + return False + return True + + # Calculate the remaining space in the selected pattern line + remaining_space = pattern_line + 1 - player.pattern_lines[pattern_line]['number'] + + # If the move exactly fills the pattern line, prioritize it + if tile_count == remaining_space: + return True + + # Deprioritize moves that overfill a pattern line (tiles that would spill over) + if tile_count > remaining_space: + return False + + # Check if placing the tile blocks placing other colors in the same row + # This prevents placing a tile in a pattern line where the corresponding wall row already has that color + if any(player.wall[pattern_line][i] == tile_color for i in range(5)): + return False + + # Prioritize filling pattern lines that are close to completion (one tile away) + if remaining_space == 1: + return True + + # If none of the conditions above trigger, accept the move + return True + + + + +def strategy_lookahead(move, GameState, player): + def simulate_future_state(GameState, move, player): + """ + Simulate the GameState after making the current move and return the hypothetical player's state. + """ + future_GameState = GameState # Assume deep copy or similar for actual implementation + # Apply the move + if move[1] == 'floor': + future_floor_count = sum(player.floor.values()) + move[3] + if future_floor_count > 7: + return None # Overfilling the floor is a bad move + else: + player.pattern_lines[move[1]]['number'] += move[3] + if player.pattern_lines[move[1]]['number'] == move[1] + 1: + # Tile will be placed on the wall in the next turn + player.wall[move[1]][player.wall[move[1]].index(False)] = move[2] + player.pattern_lines[move[1]]['number'] = 0 # Reset the pattern line + + # Simulate scoring or any other immediate effect + # (Depending on how your game state works, update this appropriately) + + return player + + def evaluate_future_state(future_player): + """ + Evaluate the future state for the player and return a score. + """ + # Simple heuristic: prioritize a mix of empty spaces filled, tiles on the wall, and penalty on the floor + score = sum(sum(row) for row in future_player.wall) - sum(future_player.floor.values()) + return score + + # Evaluate the immediate impact + immediate_impact = strategy_advanced(move, GameState, player) + + if not immediate_impact: + return False + + # Simulate the game state after the current move + future_player_state = simulate_future_state(GameState, move, player) + + if future_player_state is None: + return False # Avoid moves that lead to a bad future state + + # Evaluate the future state + future_score = evaluate_future_state(future_player_state) + + # Set a threshold or comparison logic to decide whether the move is good enough + if future_score > evaluate_future_state(player): # Basic comparison with current state + return True + + return False + + def strategy_random(move, GameState,player): return True #do not filter any moves @@ -259,21 +390,25 @@ def do_move(game_id, player_name, filter_strategy=strategy_random): for move in moves: if filter_strategy(move,GameState,player): filtered_moves.append(move) + + if len(filtered_moves) <= 1: + raise Exception("No valid moves") # Submit a random move, of the filtered ones. move = random.choice(filtered_moves) - submit_action(game_id, player_name, move[0], move[1], move[2]) return move except: #if filtered all moves, just submit a random move from the moves - result = random.choice(moves) - return result + move = random.choice(moves) + return move def play_game(gameid, players, strategy): print(f"Playing game {gameid} with players {players} and strategy {strategy.__name__}") while not game_over(gameid): for player in players: mov = do_move(gameid, player, filter_strategy=strategy) - if game_over(game_id): + submit_action(gameid, player, mov[0], mov[1], mov[2]) + print(f"Player {player} did move {mov}, current score: {get_score(gameid, player)}, current round {get_gamestate(gameid).rounds}") + if game_over(gameid): #get the score of the players score = [] for player in players: @@ -283,9 +418,9 @@ def play_game(gameid, players, strategy): if __name__ == "__main__": parser = argparse.ArgumentParser(description='Play a game with specified strategies.') - parser.add_argument('--game_id', type=int, default=0, help='The id of the game to play.') + parser.add_argument('--game_id', type=str, default="", help='The id of the game to play.') parser.add_argument('--players', nargs='+', default=["a", "b"], help='The names of the players.') - parser.add_argument('--strategy', type=str, default="", help='The strategy to use. Can be "1", "2", or "" for random.') + parser.add_argument('--strategy', type=str, default="", help='The strategy to use. Can be "1", "2", "advanced", "lookahead", or "" for random.') parser.add_argument('--ozai_url', type=str, default='http://localhost:8000/api/', help='The url to the ozai server.') args = parser.parse_args() @@ -297,11 +432,19 @@ if __name__ == "__main__": #use global ozai url and update it ozai_url = args.ozai_url - if game_id == 0: + if game_id == "": game_id = create_game(names=players) + if strategy == "1": play_game(game_id, players, strategy_1) elif strategy == "2": play_game(game_id, players, strategy_2) + elif strategy == "advanced": + play_game(game_id, players, strategy_advanced) + elif strategy == "lookahead": + play_game(game_id, players, strategy_lookahead) + elif strategy == "ai": + import ml + play_game(game_id, players, ml.strategy_ai) else: - play_game(game_id, players, strategy_random) \ No newline at end of file + play_game(game_id, players, strategy_random)