Skip to content

Instantly share code, notes, and snippets.

@agagniere
Last active December 30, 2021 18:19
Show Gist options
  • Save agagniere/0c2c9519ebc5e883626b5f6f6fb477e4 to your computer and use it in GitHub Desktop.
Save agagniere/0c2c9519ebc5e883626b5f6f6fb477e4 to your computer and use it in GitHub Desktop.
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