Last active
December 30, 2021 18:19
-
-
Save agagniere/0c2c9519ebc5e883626b5f6f6fb477e4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from random import choice | |
import sys | |
EOC = "\033[0m" | |
BOLD = "\033[1m" | |
RED = "\033[31m" | |
GREEN = "\033[32m" | |
YELLOW = "\033[33m" | |
BLUE = "\033[34m" | |
def print_error(s): | |
print(BOLD, RED, s, EOC, sep='', file=sys.stderr) | |
class Point: | |
def __init__(self, x, y): | |
self.x, self.y = x, y | |
def distance(self, other): | |
return max(abs(self.x - other[0]), abs(self.y - other[1])) | |
def __eq__(self, other): | |
return self.x == other[0] and self.y == other[1] | |
def __getitem__(self, i): | |
return self.y if i else self.x | |
def __str__(self): | |
return "({}, {})".format(self.x, self.y) | |
def __hash__(self): | |
return (self.x, self.y).__hash__() | |
class Player: | |
def __init__(self, position, name, color): | |
self.pos = position | |
self.name = name | |
self.color = color | |
def __str__(self): | |
return "{}{}{}{}".format(BOLD, self.color, self.name, EOC) | |
class Human(Player): | |
def play(self, action, possible_moves, opponent): | |
display_board() | |
while True: | |
try: | |
response = input(f"Time to {action} : quit | x y > ").strip() | |
play = Point(*map(int, response.split())) | |
if play in possible_moves: | |
return play | |
print_error("Illegal move") | |
except: | |
if response == "quit": | |
exit(0) | |
print_error("Wrong format") | |
class RandomBot(Player): | |
def play(self, action, possible_moves, opponent): | |
display_board() | |
return choice(list(possible_moves)) | |
class HarasserBot(Player): | |
def play(self, action, possible_moves, opponent): | |
return sorted(possible_moves, key=lambda p:opponent.pos.distance(p))[0] | |
while True: | |
try: | |
W, H = map(int, input("Board dimension : W H > ").split()) | |
if W in range(3, 11) and H in range(3, 11) and W <= H: | |
break | |
print_error("Illegal or unsupported size") | |
except: | |
print_error("Wrong format") | |
X = W // 2 | |
B = HarasserBot(Point(X, 0), 'B', YELLOW) | |
A = Human(Point(W - 1 - X, H - 1), 'A', GREEN) | |
GRAD = " |{}|".format(' '.join(map(str, range(W)))) | |
BORDER = "-+{}+-".format('-'.join("-" * W)) | |
possible = set([Point(x, y) for x in range(W) for y in range(H)]) - set([A.pos, B.pos]) | |
def display_board(): | |
print('\n'.join([GRAD, BORDER] + ["{0}|{1}|{0}".format(str(y), ' '.join(['\u00b7' if (x, y) in possible else {A.pos:str(A), B.pos:str(B)}.get((x, y), RED+'X') + EOC for x in range(W)])) for y in range(H)] + [BORDER, GRAD])) | |
turn = 0 | |
while True: | |
turn += 1 | |
player, opponent = ((B, A), (A, B))[turn % 2] | |
for action in ("move", "delete"): | |
possible_moves = set(filter(lambda x: player.pos.distance(x) == 1, possible)) if action == "move" else possible | |
if not possible_moves: | |
print("Player", opponent, "wins !") | |
exit(0) | |
play = player.play(action, possible_moves, opponent) | |
print(player, ':', action, play) | |
if action == "move": | |
possible.add(player.pos) | |
player.pos = play | |
possible.remove(play) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment