mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-27 05:03:27 -08:00
MAINT: Apply pre-commit
Remove byte-order-marker pre-commit check as there would be many adjustments necessary
This commit is contained in:
@@ -8,7 +8,8 @@ from enum import Enum
|
||||
|
||||
|
||||
class Move(Enum):
|
||||
""" Game status and types of machine move """
|
||||
"""Game status and types of machine move"""
|
||||
|
||||
HUMAN_WIN = 0
|
||||
MACHINE_WIN = 1
|
||||
DRAW = 2
|
||||
@@ -20,104 +21,107 @@ class Move(Enum):
|
||||
NICE_TRY = 8
|
||||
CONCEDES = 9
|
||||
|
||||
|
||||
class Player(Enum):
|
||||
EMPTY = 0
|
||||
HUMAN = 1
|
||||
MACHINE = 2
|
||||
|
||||
|
||||
class TicTacToe3D:
|
||||
""" The game logic for 3D Tic Tac Toe and the machine opponent """
|
||||
"""The game logic for 3D Tic Tac Toe and the machine opponent"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
|
||||
# 4x4x4 board keeps track of which player occupies each place
|
||||
# and used by machine to work out its strategy
|
||||
self.board = [0] * 64
|
||||
|
||||
# starting move
|
||||
self.corners = [0, 48, 51, 3, 12, 60, 63, 15,
|
||||
21, 38, 22, 37, 25, 41, 26, 42]
|
||||
self.corners = [0, 48, 51, 3, 12, 60, 63, 15, 21, 38, 22, 37, 25, 41, 26, 42]
|
||||
|
||||
# lines to check for end game
|
||||
self.lines = [[0, 1, 2, 3],
|
||||
[4, 5, 6, 7],
|
||||
[8, 9, 10, 11],
|
||||
[12, 13, 14, 15],
|
||||
[16, 17, 18, 19],
|
||||
[20, 21, 22, 23],
|
||||
[24, 25, 26, 27],
|
||||
[28, 29, 30, 31],
|
||||
[32, 33, 34, 35],
|
||||
[36, 37, 38, 39],
|
||||
[40, 41, 42, 43],
|
||||
[44, 45, 46, 47],
|
||||
[48, 49, 50, 51],
|
||||
[52, 53, 54, 55],
|
||||
[56, 57, 58, 59],
|
||||
[60, 61, 62, 63],
|
||||
[0, 16, 32, 48],
|
||||
[4, 20, 36, 52],
|
||||
[8, 24, 40, 56],
|
||||
[12, 28, 44, 60],
|
||||
[1, 17, 33, 49],
|
||||
[5, 21, 37, 53],
|
||||
[9, 25, 41, 57],
|
||||
[13, 29, 45, 61],
|
||||
[2, 18, 34, 50],
|
||||
[6, 22, 38, 54],
|
||||
[10, 26, 42, 58],
|
||||
[14, 30, 46, 62],
|
||||
[3, 19, 35, 51],
|
||||
[7, 23, 39, 55],
|
||||
[11, 27, 43, 59],
|
||||
[15, 31, 47, 63],
|
||||
[0, 4, 8, 12],
|
||||
[16, 20, 24, 28],
|
||||
[32, 36, 40, 44],
|
||||
[48, 52, 56, 60],
|
||||
[1, 5, 9, 13],
|
||||
[17, 21, 25, 29],
|
||||
[33, 37, 41, 45],
|
||||
[49, 53, 57, 61],
|
||||
[2, 6, 10, 14],
|
||||
[18, 22, 26, 30],
|
||||
[34, 38, 42, 46],
|
||||
[50, 54, 58, 62],
|
||||
[3, 7, 11, 15],
|
||||
[19, 23, 27, 31],
|
||||
[35, 39, 43, 47],
|
||||
[51, 55, 59, 63],
|
||||
[0, 5, 10, 15],
|
||||
[16, 21, 26, 31],
|
||||
[32, 37, 42, 47],
|
||||
[48, 53, 58, 63],
|
||||
[12, 9, 6, 3],
|
||||
[28, 25, 22, 19],
|
||||
[44, 41, 38, 35],
|
||||
[60, 57, 54, 51],
|
||||
[0, 20, 40, 60],
|
||||
[1, 21, 41, 61],
|
||||
[2, 22, 42, 62],
|
||||
[3, 23, 43, 63],
|
||||
[48, 36, 24, 12],
|
||||
[49, 37, 25, 13],
|
||||
[50, 38, 26, 14],
|
||||
[51, 39, 27, 15],
|
||||
[0, 17, 34, 51],
|
||||
[4, 21, 38, 55],
|
||||
[8, 25, 42, 59],
|
||||
[12, 29, 46, 63],
|
||||
[48, 33, 18, 3],
|
||||
[52, 37, 22, 7],
|
||||
[56, 41, 26, 11],
|
||||
[60, 45, 30, 15],
|
||||
[0, 21, 42, 63],
|
||||
[15, 26, 37, 48],
|
||||
[3, 22, 41, 60],
|
||||
[12, 25, 38, 51]]
|
||||
self.lines = [
|
||||
[0, 1, 2, 3],
|
||||
[4, 5, 6, 7],
|
||||
[8, 9, 10, 11],
|
||||
[12, 13, 14, 15],
|
||||
[16, 17, 18, 19],
|
||||
[20, 21, 22, 23],
|
||||
[24, 25, 26, 27],
|
||||
[28, 29, 30, 31],
|
||||
[32, 33, 34, 35],
|
||||
[36, 37, 38, 39],
|
||||
[40, 41, 42, 43],
|
||||
[44, 45, 46, 47],
|
||||
[48, 49, 50, 51],
|
||||
[52, 53, 54, 55],
|
||||
[56, 57, 58, 59],
|
||||
[60, 61, 62, 63],
|
||||
[0, 16, 32, 48],
|
||||
[4, 20, 36, 52],
|
||||
[8, 24, 40, 56],
|
||||
[12, 28, 44, 60],
|
||||
[1, 17, 33, 49],
|
||||
[5, 21, 37, 53],
|
||||
[9, 25, 41, 57],
|
||||
[13, 29, 45, 61],
|
||||
[2, 18, 34, 50],
|
||||
[6, 22, 38, 54],
|
||||
[10, 26, 42, 58],
|
||||
[14, 30, 46, 62],
|
||||
[3, 19, 35, 51],
|
||||
[7, 23, 39, 55],
|
||||
[11, 27, 43, 59],
|
||||
[15, 31, 47, 63],
|
||||
[0, 4, 8, 12],
|
||||
[16, 20, 24, 28],
|
||||
[32, 36, 40, 44],
|
||||
[48, 52, 56, 60],
|
||||
[1, 5, 9, 13],
|
||||
[17, 21, 25, 29],
|
||||
[33, 37, 41, 45],
|
||||
[49, 53, 57, 61],
|
||||
[2, 6, 10, 14],
|
||||
[18, 22, 26, 30],
|
||||
[34, 38, 42, 46],
|
||||
[50, 54, 58, 62],
|
||||
[3, 7, 11, 15],
|
||||
[19, 23, 27, 31],
|
||||
[35, 39, 43, 47],
|
||||
[51, 55, 59, 63],
|
||||
[0, 5, 10, 15],
|
||||
[16, 21, 26, 31],
|
||||
[32, 37, 42, 47],
|
||||
[48, 53, 58, 63],
|
||||
[12, 9, 6, 3],
|
||||
[28, 25, 22, 19],
|
||||
[44, 41, 38, 35],
|
||||
[60, 57, 54, 51],
|
||||
[0, 20, 40, 60],
|
||||
[1, 21, 41, 61],
|
||||
[2, 22, 42, 62],
|
||||
[3, 23, 43, 63],
|
||||
[48, 36, 24, 12],
|
||||
[49, 37, 25, 13],
|
||||
[50, 38, 26, 14],
|
||||
[51, 39, 27, 15],
|
||||
[0, 17, 34, 51],
|
||||
[4, 21, 38, 55],
|
||||
[8, 25, 42, 59],
|
||||
[12, 29, 46, 63],
|
||||
[48, 33, 18, 3],
|
||||
[52, 37, 22, 7],
|
||||
[56, 41, 26, 11],
|
||||
[60, 45, 30, 15],
|
||||
[0, 21, 42, 63],
|
||||
[15, 26, 37, 48],
|
||||
[3, 22, 41, 60],
|
||||
[12, 25, 38, 51],
|
||||
]
|
||||
|
||||
def get(self, x, y, z):
|
||||
m = self.board[4*(4*z + y) + x]
|
||||
m = self.board[4 * (4 * z + y) + x]
|
||||
if m == 40:
|
||||
return Player.MACHINE
|
||||
elif m == 8:
|
||||
@@ -126,13 +130,13 @@ class TicTacToe3D:
|
||||
return Player.EMPTY
|
||||
|
||||
def move3D(self, x, y, z, player):
|
||||
m = 4*(4*z + y) + x
|
||||
m = 4 * (4 * z + y) + x
|
||||
return self.move(m, player)
|
||||
|
||||
def move(self, m, player):
|
||||
if self.board[m] > 1:
|
||||
return False
|
||||
|
||||
|
||||
if player == Player.MACHINE:
|
||||
self.board[m] = 40
|
||||
else:
|
||||
@@ -165,7 +169,7 @@ class TicTacToe3D:
|
||||
self.board[i] = 0
|
||||
|
||||
def markAndMove(self, vlow, vhigh, vmove):
|
||||
"""
|
||||
"""
|
||||
mark lines that can potentially win the game for the human
|
||||
or the machine and choose best place to play
|
||||
"""
|
||||
@@ -187,13 +191,15 @@ class TicTacToe3D:
|
||||
return None
|
||||
|
||||
def machineMove(self):
|
||||
""" machine works out what move to play """
|
||||
"""machine works out what move to play"""
|
||||
self.clearStrategyMarks()
|
||||
|
||||
self.evaluateLines()
|
||||
for value, event in [(32, self.humanWin),
|
||||
(120, self.machineWin),
|
||||
(24, self.blockHumanWin)]:
|
||||
for value, event in [
|
||||
(32, self.humanWin),
|
||||
(120, self.machineWin),
|
||||
(24, self.blockHumanWin),
|
||||
]:
|
||||
for i in range(76):
|
||||
if self.lineValues[i] == value:
|
||||
return event(i)
|
||||
@@ -210,12 +216,12 @@ class TicTacToe3D:
|
||||
|
||||
for k in range(18):
|
||||
value = 0
|
||||
for i in range(4*k, 4*k+4):
|
||||
for i in range(4 * k, 4 * k + 4):
|
||||
for j in range(4):
|
||||
value += self.board[self.lines[i][j]]
|
||||
if (32 <= value < 40) or (72 <= value < 80):
|
||||
for s in [1, 0]:
|
||||
for i in range(4*k, 4*k+4):
|
||||
for i in range(4 * k, 4 * k + 4):
|
||||
m = self.moveDiagonals(i, s)
|
||||
if m != None:
|
||||
return m
|
||||
@@ -231,7 +237,7 @@ class TicTacToe3D:
|
||||
return (Move.LIKES, i)
|
||||
|
||||
return (Move.DRAW, -1)
|
||||
|
||||
|
||||
def humanWin(self, i):
|
||||
return (Move.HUMAN_WIN, -1, i)
|
||||
|
||||
@@ -249,9 +255,8 @@ class TicTacToe3D:
|
||||
return (Move.NICE_TRY, m)
|
||||
return None
|
||||
|
||||
|
||||
def moveTriple(self, i):
|
||||
""" make two lines-of-3 or prevent human from doing this """
|
||||
"""make two lines-of-3 or prevent human from doing this"""
|
||||
for j in range(4):
|
||||
m = self.lines[i][j]
|
||||
if self.board[m] == 1:
|
||||
@@ -273,12 +278,12 @@ class TicTacToe3D:
|
||||
return (Move.TAKES, m)
|
||||
return None
|
||||
|
||||
|
||||
class Qubit:
|
||||
|
||||
def moveCode(self, board, m):
|
||||
x, y, z = board.get3DPosition(m)
|
||||
return "{:d}{:d}{:d}".format(z+1, y+1, x+1)
|
||||
|
||||
return f"{z + 1:d}{y + 1:d}{x + 1:d}"
|
||||
|
||||
def showWin(self, board, i):
|
||||
for m in board.lines[i]:
|
||||
print(self.moveCode(board, m))
|
||||
@@ -290,10 +295,10 @@ class Qubit:
|
||||
print(" " * y, end="")
|
||||
for x in range(4):
|
||||
p = board.get(x, y, z)
|
||||
print("({}) ".format(c[p.value]), end="")
|
||||
print(f"({c[p.value]}) ", end="")
|
||||
print("\n")
|
||||
print("\n")
|
||||
|
||||
|
||||
def humanMove(self, board):
|
||||
print("")
|
||||
c = "1234"
|
||||
@@ -310,13 +315,13 @@ class Qubit:
|
||||
z = c.find(h[0])
|
||||
if board.move3D(x, y, z, Player.HUMAN):
|
||||
break
|
||||
|
||||
|
||||
print("That square is used. Try again.")
|
||||
else:
|
||||
print("Incorrect move. Retype it--")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def play(self):
|
||||
print("Qubic\n")
|
||||
print("Create Computing Morristown, New Jersey\n\n\n")
|
||||
@@ -325,9 +330,9 @@ class Qubit:
|
||||
if len(c) >= 1 and (c[0] in "ynYN"):
|
||||
break
|
||||
print("Incorrect answer. Please type 'yes' or 'no.")
|
||||
|
||||
|
||||
c = c.lower()
|
||||
if c[0] == 'y':
|
||||
if c[0] == "y":
|
||||
print("The game is Tic-Tac-Toe in a 4 x 4 x 4 cube.")
|
||||
print("Each move is indicated by a 3 digit number, with each")
|
||||
print("digit between 1 and 4 inclusive. The digits indicate the")
|
||||
@@ -341,8 +346,6 @@ class Qubit:
|
||||
|
||||
print("To stop the program run, type 1 as your move.\n\n")
|
||||
|
||||
|
||||
|
||||
play_again = True
|
||||
while play_again:
|
||||
board = TicTacToe3D()
|
||||
@@ -355,12 +358,14 @@ class Qubit:
|
||||
|
||||
skipHuman = s[0] in "nN"
|
||||
|
||||
move_text = ["Machine moves to",
|
||||
"Machine likes",
|
||||
"Machine takes",
|
||||
"Let's see you get out of this: Machine moves to",
|
||||
"You fox. Just in the nick of time, machine moves to",
|
||||
"Nice try. Machine moves to"]
|
||||
move_text = [
|
||||
"Machine moves to",
|
||||
"Machine likes",
|
||||
"Machine takes",
|
||||
"Let's see you get out of this: Machine moves to",
|
||||
"You fox. Just in the nick of time, machine moves to",
|
||||
"Nice try. Machine moves to",
|
||||
]
|
||||
|
||||
while True:
|
||||
if not skipHuman:
|
||||
@@ -374,7 +379,11 @@ class Qubit:
|
||||
self.showWin(board, m[2])
|
||||
break
|
||||
elif m[0] == Move.MACHINE_WIN:
|
||||
print("Machine moves to {}, and wins as follows".format(self.moveCode(board, m[1])))
|
||||
print(
|
||||
"Machine moves to {}, and wins as follows".format(
|
||||
self.moveCode(board, m[1])
|
||||
)
|
||||
)
|
||||
self.showWin(board, m[2])
|
||||
break
|
||||
elif m[0] == Move.DRAW:
|
||||
@@ -398,8 +407,7 @@ class Qubit:
|
||||
print("Incorrect answer. Please Type 'yes' or 'no'.")
|
||||
|
||||
play_again = x[0] in "yY"
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
game = Qubit()
|
||||
|
||||
Reference in New Issue
Block a user