from random import * from os import system, name def clear(): if name == 'nt': _ = system('cls') else: _ = system('clear') class Square: def __init__(self, location, name): self.location = location #where the square is as an [x,y] pair self.x = location[0] self.y = location[1] self.state = "empty" #behind the scenes data self.display = " " #what the user will see self.name = name #There's gotta be a better way! #The names of the squares are according to chess convention, #but the coordinates are according to usual matrix notation. a1 = Square([0,3], "a1") a2 = Square([0,2], "a2") a3 = Square([0,1], "a3") a4 = Square([0,0], "a4") b1 = Square([1,3], "b1") b2 = Square([1,2], "b2") b3 = Square([1,1], "b3") b4 = Square([1,0], "b4") c1 = Square([2,3], "c1") c2 = Square([2,2], "c2") c3 = Square([2,1], "c3") c4 = Square([2,0], "c4") d1 = Square([3,3], "d1") d2 = Square([3,2], "d2") d3 = Square([3,1], "d3") d4 = Square([3,0], "d4") board=[a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4] setup_seed = sample(board, 4) #We pick four squares for initial amazon placement setup_seed[0].state = "ba1" #black amazon 1 setup_seed[1].state = "ba2" #black amazon 2 setup_seed[2].state = "wa1" #white amazon 1 setup_seed[3].state = "wa2" #white amazon 2 turn = "w" #White moves first. turn_counter = 1 def display(): #This interprets the states of the squares for display global turn, turn_counter, board for box in board: if box.state == "empty": box.display = " " if box.state == "ba1": box.display = "B" if box.state == "ba2": box.display = "B" if box.state == "wa1": box.display = "W" if box.state == "wa2": box.display = "W" if box.state == "fire": box.display = "X" def gui(): #This displays the board state to the user global turn, turn_counter, board clear() display() print(" a b c d") print("4 "+a4.display+" "+b4.display+" "+c4.display+" "+d4.display) print("3 "+a3.display+" "+b3.display+" "+c3.display+" "+d3.display) print("2 "+a2.display+" "+b2.display+" "+c2.display+" "+d2.display) print("1 "+a1.display+" "+b1.display+" "+c1.display+" "+d1.display) if turn_counter%2 == 0: print("It's black's turn.") else: print("It's white's turn.") def choice_translate(box): #Takes the string inputs of the user and outputs corresponding square global turn, turn_counter, board if box == "a1": return a1 if box == "a2": return a2 if box == "a3": return a3 if box == "a4": return a4 if box == "b1": return b1 if box == "b2": return b2 if box == "b3": return b3 if box == "b4": return b4 if box == "c1": return c1 if box == "c2": return c2 if box == "c3": return c3 if box == "c4": return c4 if box == "d1": return d1 if box == "d2": return d2 if box == "d3": return d3 if box == "d4": return d4 else: return False def valid_move(start, end): #Checks to see if a mvoe is valid (for both amazons and arrows) global turn, turn_counter, board test_set=[] #This will be the set of squares between the start and end of the move. #For reasons unknown, the test set always finds each eligible square twice. How to fix? #There are three reasons to immediately reject a move: if end.state != "empty": #If the ending square isn't empty return False if start == end: #If the ending square is the starting square return False #If the start and end aren't in the same row, column, or diagonal. if (start.x != end.x) and (start.y != end.y) and (abs(start.x - end.x) != abs(start.y - end.y)): return False #If they are in the same column... if start.x == end.x: if start.y > end.y: #If we are going down.... for box in board: #...find the squares... if box.x == start.x: #...in that column... for i in range(1, abs(start.y-end.y)): #... between the start and end... if box.y == start.y-i: test_set.append(box) #... and add it to the list. if start.y < end.y: #If we are going up... etc... for box in board: if box.x == start.x: for i in range(1, abs(start.y-end.y)): if box.y == start.y+i: test_set.append(box) #If they are in the same row... if start.y == end.y: if start.x > end.x: #going right.... for box in board: if box.y == start.y: for i in range(1, abs(start.x-end.x)): if box.x == start.x-i: test_set.append(box) if start.x < end.x: #going left... for box in board: if box.y == start.y: for i in range(1, abs(start.x-end.x)): if box.x == start.x+i: test_set.append(box) #If they are on the same diagonal if abs(start.x - end.x) == abs(start.y - end.y): if (start.x < end.x) and (start.y < end.y): #going up and right for box in board: for i in range(1, abs(start.x-end.x)): if ((box.x == start.x+i) and (box.y == start.y+i)): test_set.append(box) if (start.x > end.x) and (start.y > end.y): #going down and left for box in board: for i in range(1, abs(start.x-end.x)): if ((box.x == start.x-i) and (box.y == start.y-i)): test_set.append(box) if (start.x > end.x) and (start.y < end.y): #going up and left for box in board: for i in range(1, abs(start.x-end.x)): if ((box.x == start.x-i) and (box.y == start.y+i)): test_set.append(box) if (start.x < end.x) and (start.y > end.y): #going down and right for box in board: for i in range(1, abs(start.x-end.x)): if ((box.x == start.x+i) and (box.y == start.y-i)): test_set.append(box) for test in test_set: #now make sure all of the squares we've selected are indeed empty if test.state != "empty": return False return True def possible_moves(amazon): #outputs a list of squares that can be reached by an amazon moves=[] for box in board: if valid_move(amazon, box): moves.append(box) return(moves) def play(): global turn, turn_counter, board gui() #We check which amazons can legally move movable_amazons=[] for box in board: if box.state == turn+"a1": if len(possible_moves(box)) != 0: movable_amazons.append(box.name) if box.state == turn+"a2": if len(possible_moves(box)) != 0: movable_amazons.append(box.name) #If none can move, then the game is over! if len(movable_amazons)==0: if turn_counter%2 == 0: input("White wins!") exit(0) if turn_counter%2 == 1: input("Black wins!") exit(0) #Otherwise, the player chooses an amazon to move if len(movable_amazons) == 2: #If both can move they have a choice amazon_choice = input("Choose a square containing one of your amazons, either "+movable_amazons[0]+" or "+movable_amazons[1]+": ") while amazon_choice not in movable_amazons: amazon_choice = input("That's not one of the options. Try again: ") if len(movable_amazons) == 1: #If only one can move, they have no choice amazon_choice = movable_amazons[0] gui() #The player chooses a square to move to print("You must move the amazon on "+amazon_choice+". Choose the square you want to move to.") print("Which of the following would you like to move to?") amazon_choice = choice_translate(amazon_choice) choices = [] #We have a list to display to the user... for option in possible_moves(amazon_choice): #...consisting of their possible moves. choices.append(option.name) move_choice = choice_translate(input(choices)) #The following three while statements only catch exemptions if made in this order. #So if the user first inputs a square correctly, but it's not a possible move, #and then they enter in gibberish, it wigs out. How to fix? while move_choice == False: #choice_translate outputs False when the input isn't a square name move_choice = choice_translate(input("That's not a valid move. Try again: ")) while move_choice.name not in choices: move_choice = choice_translate(input("That's not an option. Try again: ")) while valid_move(amazon_choice, move_choice) == False: move_choice = choice_translate(input("That amazon can't move there. Try again: ")) #If all goes well, we make the move by changing the states of the squares. if valid_move(amazon_choice, move_choice): move_choice.state = amazon_choice.state amazon_choice.state = "empty" gui() #The player chooses a square to shoot choices = [] for option in possible_moves(move_choice): choices.append(option.name) print("Choose the square you want to set aflame: ") burn_choice = choice_translate(input(choices)) #These three statements have the same problem as those above. while burn_choice == False: burn_choice = choice_translate(input("That's not the name of any square. Try again: ")) while burn_choice.state != "empty": burn_choice = choice_translate(input("That's square isn't empty. Try again: ")) while valid_move(move_choice, burn_choice) == False: burn_choice = choice_translate(input("You can't shoot there. Try again: ")) burn_choice.state = "fire" #Bookkeepping for turn taking turn_counter+=1 if turn_counter%2 == 0: turn = "b" if turn_counter%2 == 1: turn = "w" while True: play() #Next Steps: #have students change the abilities of the amazons, size of the board, etc. #Add a class to record game state!?!?!?