still not working

This commit is contained in:
Heli-o 2024-01-06 19:56:48 +01:00
parent 56b3f0a6f1
commit fc5b73c771
5 changed files with 130 additions and 197 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
images/* images/*
*.png *.png
moves/*

Binary file not shown.

Binary file not shown.

156
assets.py
View file

@ -1,137 +1,31 @@
from enum import Enum from player import Player
from collections import deque import ast
def get_neighbors(p, q): def update_player(b, m, t, mp, rp):
directions = [(0, -1), (1, -1), (1, 0), (0, 1), (-1, 1), (-1, 0)] p = Player("p", t, 13, mp, rp)
return [(p + dp, q + dq) for dp, dq in directions] p.myMove = m
p.board = b
p.update()
return p
class Piece: def insert():
def get_valid_jumps() -> list: board = input("insert board: ").strip()
raise NotImplementedError move = input("insert move: ").strip()
mp = input("insert my team: ").strip()
rp = input("insert rival team: ").strip()
team = input("insert team: ").strip()
board = ast.literal_eval(board.split(" = ")[1])
move = ast.literal_eval(move.split(" = ")[1])
team = ast.literal_eval(team.split(" = ")[1])
mp = ast.literal_eval(mp.split(" = ")[1])
rp = ast.literal_eval(rp.split(" = ")[1])
p = update_player(board, move, team, mp, rp)
return p, [board, move, team, mp, rp]
class Bee(Piece): def update(pkg):
def __init__(self, board, p, q, team): return update_player(*pkg)
self.board = board
self.p = p
self.q = q
self.team = team # 'team' should be 'upper' or 'lower' based on the piece case.
def get_valid_jumps(self) -> list:
# The bee can move to an adjacent empty space.
valid_moves = []
for neighbor in get_neighbors(self.p, self.q):
# Check if the neighbor is within the bounds of the board and is empty
if neighbor in self.board and self.board[neighbor] == "":
valid_moves.append(neighbor)
return valid_moves
class Beetle(Piece):
def __init__(self, p, q, team):
self.p = p
self.q = q
self.team = team
def get_valid_jumps(self, board):
# The beetle can move to an adjacent space whether it is empty or not.
valid_moves = get_neighbors(self.p, self.q)
return valid_moves
class Spider(Piece):
def __init__(self, p, q, team):
self.p = p
self.q = q
self.team = team
def get_valid_jumps(self, board):
# Use BFS to find all tiles exactly three moves away
start = (self.p, self.q)
visited = set() # Keep track of visited tiles
queue = deque([(start, 0)]) # Queue of (position, distance)
valid_moves = []
while queue:
current_position, current_distance = queue.popleft()
if current_distance == 3:
# We have found a tile exactly three moves away
valid_moves.append(current_position)
continue # We don't want to move further from this tile
if current_position in visited:
continue # Already visited this tile
visited.add(current_position)
# Get all neighboring positions
for neighbor in get_neighbors(*current_position):
if (
neighbor in board
and board[neighbor] == ""
and neighbor not in visited
):
queue.append((neighbor, current_distance + 1))
return valid_moves
class Grasshopper(Piece):
def __init__(self, p, q, team):
self.p = p
self.q = q
self.team = team
def get_valid_jumps(self, board):
# Generator function to yield valid moves
def generate_moves():
# Check each direction for possible jumps
for dp, dq in get_neighbors(0, 0): # Use (0, 0) to get direction vectors
pos = (self.p + dp, self.q + dq)
# Continue in the direction until we find a piece to jump over
while pos in board and board[pos] != "":
pos = (pos[0] + dp, pos[1] + dq)
# If we jumped over at least one piece and landed on an empty space, yield the move
if (
pos in board
and board[pos] == ""
and (pos[0] != self.p or pos[1] != self.q)
):
yield pos
return list(generate_moves())
class Ant(Piece):
def __init__(self, p, q, team):
self.p = p
self.q = q
self.team = team
def get_valid_jumps(self, board):
visited = set() # Keep track of visited nodes to prevent cycles
# Recursive function to explore all valid moves
def explore(p, q):
for dp, dq in get_neighbors(0, 0): # Get direction vectors
new_p, new_q = p + dp, q + dq
next_pos = (new_p, new_q)
# Continue in this direction while there are pieces to slide around
while (
next_pos in board
and board[next_pos] != ""
and next_pos not in visited
):
visited.add(next_pos)
next_pos = (next_pos[0] + dp, next_pos[1] + dq)
# If we found an empty space, add it as a valid move and explore from there
if next_pos in board and board[next_pos] == "":
visited.add(next_pos)
yield next_pos
# Explore further moves from this new position
yield from explore(next_pos[0], next_pos[1])
# Start exploring from the Ant's current position
return list(explore(self.p, self.q))

148
player.py
View file

@ -1,21 +1,38 @@
import base as Base import base as Base
import copy, random, time, math import copy
import random
import time
import math
from PIL import Image, ImageDraw from PIL import Image, ImageDraw
from collections import deque from collections import deque
# Player template for HIVE --- ALP semestral work # Player template for HIVE --- ALP semestral work
# Vojta Vonasek, 2023 # Vojta Vonasek, 2023
# PUT ALL YOUR IMPLEMENTATION INTO THIS FILE # PUT ALL YOUR IMPLEMENTATION INTO THIS FILE
def inBoard(p, q, size):
""" return True if (p,q) is valid coordinate """
return (q >= 0) and (q < size) and (p >= -(q//2)) and (p < (size - q//2))
def get_neighbors(p, q): def get_neighbors(p, q):
directions = [(0, -1), (1, -1), (1, 0), (0, 1), (-1, 1), (-1, 0)] directions = [(0, -1), (1, -1), (1, 0), (0, 1), (-1, 1), (-1, 0)]
return [(p + dp, q + dq) for dp, dq in directions] return [(p + dp, q + dq) for dp, dq in directions]
def has_neighbors(p, q, board, pp, pq):
# Check if the position (p, q) has at least one neighbor
board = copy.deepcopy(board)
board[pp][pq] = ""
for dp, dq in get_neighbors(0, 0):
neighbor_p, neighbor_q = p + dp, q + dq
if inBoard(neighbor_p, neighbor_q, 13) and board[neighbor_p][neighbor_q] != "":
return True
return False
class Piece: class Piece:
def get_piece_info(self, myisupper): def get_piece_info(self, myisupper):
class_to_letter = { class_to_letter = {
@ -49,7 +66,8 @@ class Piece:
board_copy = {p: {q: board[p][q] for q in board[p]} for p in board} board_copy = {p: {q: board[p][q] for q in board[p]} for p in board}
# See if the hive falls apart without the piece (if so, then the move wasnt valid) # See if the hive falls apart without the piece (if so, then the move wasnt valid)
board_copy[self.p][self.q] = None # Remove the piece from its current position # Remove the piece from its current position
board_copy[self.p][self.q] = None
# Get all remaining pieces on the board # Get all remaining pieces on the board
remaining_pieces = [ remaining_pieces = [
@ -102,7 +120,9 @@ class Beetle(Piece):
def get_valid_jumps(self, board): def get_valid_jumps(self, board):
valid_moves = get_neighbors(self.p, self.q) valid_moves = get_neighbors(self.p, self.q)
return valid_moves checked = [v for v in valid_moves if has_neighbors(
v[0], v[1], board, self.p, self.q)]
return checked
class Spider(Piece): class Spider(Piece):
@ -120,6 +140,7 @@ class Spider(Piece):
while queue: while queue:
current_position, current_distance = queue.popleft() current_position, current_distance = queue.popleft()
if current_distance == 3: if current_distance == 3:
if has_neighbors(*current_position, board, self.p, self.q):
valid_moves.append(current_position) valid_moves.append(current_position)
continue continue
@ -128,13 +149,11 @@ class Spider(Piece):
visited.add(current_position) visited.add(current_position)
for neighbor in get_neighbors(*current_position): for p, q in get_neighbors(*current_position):
if ( next_pos = (p, q)
neighbor in board if (inBoard(p, q, 13) and board[p][q] == "" and next_pos not in visited
and board[neighbor] == "" and has_neighbors(p, q, board, self.p, self.q)):
and neighbor not in visited queue.append((next_pos, current_distance + 1))
):
queue.append((neighbor, current_distance + 1))
return valid_moves return valid_moves
@ -170,28 +189,35 @@ class Ant(Piece):
self.team = team self.team = team
def get_valid_jumps(self, board): def get_valid_jumps(self, board):
visited = set() # Keep track of visited nodes to prevent cycles visited = set()
# Just a recursive, eh? def explore(p, q, depth=0):
def explore(p, q): if depth >= 5: # Limit recursion depth
return []
valid_moves = []
for dp, dq in get_neighbors(0, 0): for dp, dq in get_neighbors(0, 0):
new_p, new_q = p + dp, q + dq new_p, new_q = p + dp, q + dq
next_pos = (new_p, new_q) next_pos = (new_p, new_q)
while (
next_pos in board while (inBoard(next_pos[0], next_pos[1], 13) and
and board[next_pos] != "" board[next_pos[0]][next_pos[1]] != "" and
and next_pos not in visited next_pos not in visited):
):
visited.add(next_pos) visited.add(next_pos)
next_pos = (next_pos[0] + dp, next_pos[1] + dq) next_pos = (next_pos[0] + dp, next_pos[1] + dq)
if next_pos in board and board[next_pos] == "":
visited.add(next_pos)
yield next_pos
yield from explore(next_pos[0], next_pos[1])
valid_moves = list(explore(self.p, self.q)) if (inBoard(next_pos[0], next_pos[1], 13) and
board[next_pos[0]][next_pos[1]] == "" and
has_neighbors(next_pos[0], next_pos[1], board, self.p, self.q)):
visited.add(next_pos)
valid_moves.append(next_pos)
valid_moves.extend(
explore(next_pos[0], next_pos[1], depth + 1))
return valid_moves return valid_moves
return explore(self.p, self.q)
class Player(Base.Board): class Player(Base.Board):
def __init__( def __init__(
@ -203,7 +229,7 @@ class Player(Base.Board):
self.playerName = playerName self.playerName = playerName
self.myIsUpper = myIsUpper self.myIsUpper = myIsUpper
self.algorithmName = "just roll the dice, eh?" self.algorithmName = "just roll the dice, eh?"
self.transated_board = dict() self.tboard = dict()
self.can_place = lambda: sum([v for v in self.myPieces.values()]) self.can_place = lambda: sum([v for v in self.myPieces.values()])
def getAllEmptyCells(self): def getAllEmptyCells(self):
@ -241,9 +267,11 @@ class Player(Base.Board):
if tile_content.isalpha(): if tile_content.isalpha():
topmost_piece_letter = tile_content[-1] topmost_piece_letter = tile_content[-1]
is_upper = topmost_piece_letter.isupper() is_upper = topmost_piece_letter.isupper()
piece_class = piece_class_mapping.get(topmost_piece_letter.upper()) piece_class = piece_class_mapping.get(
topmost_piece_letter.upper())
if piece_class: if piece_class:
piece_instance = piece_class(p, q, is_upper == self.myIsUpper) piece_instance = piece_class(
p, q, is_upper == self.myIsUpper)
translated_board[p][q] = piece_instance translated_board[p][q] = piece_instance
total_pieces_count += 1 total_pieces_count += 1
if is_upper == self.myIsUpper: if is_upper == self.myIsUpper:
@ -259,7 +287,6 @@ class Player(Base.Board):
def queen_placed(self): def queen_placed(self):
return any(isinstance(p, Bee) for p in self.myPieces) return any(isinstance(p, Bee) for p in self.myPieces)
def random_piece(self, pieces): def random_piece(self, pieces):
return random.choice(pieces) if pieces else None return random.choice(pieces) if pieces else None
@ -275,6 +302,7 @@ class Player(Base.Board):
piece_class = self.get_piece_class(piece_letter) piece_class = self.get_piece_class(piece_letter)
unplaced_pieces.append(piece_class(None, None, True)) unplaced_pieces.append(piece_class(None, None, True))
return unplaced_pieces return unplaced_pieces
def get_valid_placements(self, translated_board, piece_to_place): def get_valid_placements(self, translated_board, piece_to_place):
valid_placements = [] valid_placements = []
@ -305,25 +333,26 @@ class Player(Base.Board):
return valid_placements return valid_placements
def mover(self): def mover(self):
movable_pieces = [ movable_pieces = list()
piece for row in self.tboard.values():
for row in self.translated_board.values() for piece in row.values():
for piece in row.values() if piece and piece.team:
if piece and piece.team and piece.validate_jumps(self.translated_board) jumps = piece.validate_jumps(self.tboard)
] if jumps:
chosen_piece = self.random_piece(movable_pieces) # -> can be None, usually the cause for an error movable_pieces.append((piece, jumps))
# -> can be None, usually the cause for an error
chosen_piece = self.random_piece(movable_pieces)
if chosen_piece: if chosen_piece:
new_p, new_q = random.choice( new_p, new_q = random.choice(chosen_piece[1])
chosen_piece.validate_jumps(self.translated_board) return chosen_piece[0].get_piece_info(self.myIsUpper) + [new_p, new_q]
) return "failed"
return chosen_piece.get_piece_info(self.myIsUpper) + [new_p, new_q]
def placer(self): def placer(self):
piece_to_place = self.random_piece(self.get_unplaced_pieces()) piece_to_place = self.random_piece(self.get_unplaced_pieces())
if piece_to_place is None:
return self.mover()
if piece_to_place: if piece_to_place:
valid_placements = self.get_valid_placements(self.translated_board, piece_to_place) valid_placements = self.get_valid_placements(
self.tboard, piece_to_place)
new_p, new_q = random.choice(valid_placements) new_p, new_q = random.choice(valid_placements)
return piece_to_place.get_piece_info(self.myIsUpper)[:1] + [ return piece_to_place.get_piece_info(self.myIsUpper)[:1] + [
None, None,
@ -333,46 +362,55 @@ class Player(Base.Board):
] ]
def update(self): def update(self):
self.translated_board, total_pieces_count, my_pieces_count = self.translate_board(self.board) trb, total_pieces_count, my_pieces_count = self.translate_board(
self.board)
self.tboard = trb
p = self
return total_pieces_count, my_pieces_count return total_pieces_count, my_pieces_count
def move(self): def move(self):
total_pieces_count, my_pieces_count = self.update() total_pieces_count, my_pieces_count = self.update()
bee_unplaced = "q" in [k.lower() for k in self.myPieces.keys()] and {k.lower(): v for k,v in self.myPieces.items()}["q"]!=0 bee_unplaced = "q" in [k.lower() for k in self.myPieces.keys()] and {
k.lower(): v for k, v in self.myPieces.items()}["q"] != 0
if bee_unplaced and (total_pieces_count > 3 or random.choice([True, False])): if bee_unplaced and (total_pieces_count > 3 or random.choice([True, False])):
queen_bee = self.get_piece_class('Q')(None, None, True) queen_bee = self.get_piece_class('Q')(None, None, True)
valid_placements = self.get_valid_placements(self.translated_board, queen_bee) valid_placements = self.get_valid_placements(
self.tboard, queen_bee)
if valid_placements: if valid_placements:
new_p, new_q = random.choice(valid_placements) new_p, new_q = random.choice(valid_placements)
return queen_bee.get_piece_info(self.myIsUpper)[:1] + [None, None, new_p, new_q] return queen_bee.get_piece_info(self.myIsUpper)[:1] + [None, None, new_p, new_q]
if total_pieces_count == 0: elif total_pieces_count == 0:
piece_to_place = self.random_piece(self.get_unplaced_pieces()) piece_to_place = self.random_piece(self.get_unplaced_pieces())
return ( return (
piece_to_place.get_piece_info(self.myIsUpper)[:1] + [None, None, 3, 6] piece_to_place.get_piece_info(self.myIsUpper)[
:1] + [None, None, 3, 6]
) )
elif total_pieces_count == 1: elif total_pieces_count == 1:
for _, row in self.translated_board.items(): for _, row in self.tboard.items():
for _, piece in row.items(): for _, piece in row.items():
if piece: if piece:
adjacent_positions = get_neighbors(piece.p, piece.q) adjacent_positions = get_neighbors(piece.p, piece.q)
random_position = self.random_piece(adjacent_positions) random_position = self.random_piece(adjacent_positions)
piece_to_place = self.random_piece(self.get_unplaced_pieces()) piece_to_place = self.random_piece(
self.get_unplaced_pieces())
return ( return (
piece_to_place.get_piece_info(self.myIsUpper)[:1] piece_to_place.get_piece_info(self.myIsUpper)[:1]
+ [None, None, *random_position] + [None, None, *random_position]
) )
elif self.myMove <= 4: elif self.myMove <= 4:
return self.placer() return self.placer()
else:
move_or_place = random.choice(["move", "place"]) if self.can_place else "move" choice = random.choice(["move", "place"])
if move_or_place == "place": print(choice)
if choice == "place" and bool(self.can_place):
return self.placer() return self.placer()
else: else:
return self.mover() return self.mover()
return []
def updatePlayers(move, activePlayer, passivePlayer): def updatePlayers(move, activePlayer, passivePlayer):
@ -421,13 +459,13 @@ if __name__ == "__main__":
move = P1.move() move = P1.move()
print("P1 returned", move) print("P1 returned", move)
updatePlayers(move, P1, P2) # update P1 and P2 according to the move updatePlayers(move, P1, P2) # update P1 and P2 according to the move
filename = "move-{:03d}-player1.png".format(moveIdx) filename = "moves/move-{:03d}-player1.png".format(moveIdx)
P1.saveImage(filename) P1.saveImage(filename)
move = P2.move() move = P2.move()
print("P2 returned", move) print("P2 returned", move)
updatePlayers(move, P2, P1) # update P2 and P1 according to the move updatePlayers(move, P2, P1) # update P2 and P1 according to the move
filename = "move-{:03d}-player2.png".format(moveIdx) filename = "moves/move-{:03d}-player2.png".format(moveIdx)
P1.saveImage(filename) P1.saveImage(filename)
moveIdx += 1 moveIdx += 1