ECS170 AI Python
import numpy as np
import math
Copyright By PowCoder代写 加微信 powcoder
import os, sys
import pygame
import random
import time
from threading import Thread
from thread import KillableThread, thread_with_exception, thread_with_trace
import multiprocessing
import signal
from copy import deepcopy
import threading
def time_limit(func, args, time_):
”’Python tries very, very hard to make sure you can’t kill threads,
but with enough effort, anything is possible. Here, we uses traces
to inject a system exit exception on the next line of whatever the
thread is executing. I am fairly certain this can kill anything.
You probably should not use this function because killing threads
is bad practice. I am only doing it here because we need to make sure
we have a level playing field ie no agent can cheat and get extra time
per moves. If you want to do something similar you should keep an exit
flag in your code, but asking every student to keep exit flags in their
code in not feasible. This took an embarassingly long time to figure out.”’
t = thread_with_trace(target=func, args=args)
t.join(time_)
if t.is_alive():
class connect4():
def __init__(self, player1, player2, board_shape=(6,7), visualize=False, game=0, save=False,
limit_players=[-1,-1], time_limit=[-1,-1], verbose=False):
global screen
self.shape = board_shape
width = self.shape[1] * SQUARESIZE
height = (self.shape[0] + 1) * SQUARESIZE
pygame.init()
screen = pygame.display.set_mode(size)
# Continue initialization
self.board = np.zeros(board_shape).astype(‘int32’)
self.topPosition = (np.ones(board_shape[1]) * (board_shape[0]-1)).astype(‘int32’)
self.player1 = player1
self.player2 = player2
self.player1.opponent = self.player2
self.player2.opponent = self.player1
self.visualize = visualize
self.turnPlayer = self.player1
self.history = [[], []]
self.game = game
self.save = save
self.limit = limit_players
self.time_limits = time_limit
self.verbose = verbose
# Make sure time limits are formatted acceptably
if len(self.time_limits) != 2:
self.time_limits = [0.5,0.5]
if self.time_limits[0] <= 0:
self.time_limits[0] = 0.5
if self.time_limits[1] <= 0:
self.time_limits[1] = 0.5
def playTurn(self):
move = self.randMove()
if self.turnPlayer.position in self.limit:
time_limit(self.turnPlayer.play, (self,move,), self.time_limits[self.turnPlayer.position-1])
self.turnPlayer.play(self, move)
# Move returned as list because lists are mutable
move = move[0]
# Correct illegal move (assign random)
if self.topPosition[move] < 0:
possible = self.topPosition >= 0
indices = []
for i, p in enumerate(possible):
if p: indices.append(i)
move = random.choice(indices)
self.board[self.topPosition[move]][move] = self.turnPlayer.position
self.topPosition[move] -= 1
playerID = self.turnPlayer.position
self.history[playerID-1].append(move)
self.turnPlayer = self.turnPlayer.opponent
if self.visualize:
self.draw_board()
if self.verbose:
print(self.board)
return move
def play(self):
if self.visualize:
self.draw_board()
player = self.turnPlayer.position
move = self.playTurn()
while not self.gameOver(move, player):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
player = self.turnPlayer.position
move = self.playTurn()
if self.save:
self.saveGame()
if self.verbose:
if len(self.history[0]) + len(self.history[1]) == self.shape[0] * self.shape[1]:
print(‘The game has tied’)
print(‘Player ‘, self.turnPlayer.opponent.position, ‘ has won’)
spectating = True
while spectating and self.visualize:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
spectating = False
def gameOver(self, j, player):
# Find extrema to consider
i = self.topPosition[j] + 1
minRowIndex = max(j – 3, 0)
maxRowIndex = min(j + 3, self.shape[1]-1)
maxColumnIndex = max(i – 3, 0)
minColumnIndex = min(i + 3, self.shape[0]-1)
minLeftDiag = [max(j – 3, j), min(i + 3, self.shape[0]-1)]
maxLeftDiag = [min(j + 3, self.shape[1]-1), max(i – 3, 0)]
minRightDiag = [min(j + 3, j), min(i + 3, self.shape[0]-1)]
maxRightDiag = [max(j – 3, 0), max(i – 3, 0)]
# Iterate over extrema to find patterns
# Horizontal solutions
for s in range(minRowIndex, maxRowIndex+1):
if self.board[i, s] == player:
count += 1
if count == 4:
if self.visualize:
pygame.draw.line(screen, WHITE, (int(s*SQUARESIZE+SQUARESIZE/2), int((i+1.5)*SQUARESIZE)), (int((s-4)*SQUARESIZE+SQUARESIZE+SQUARESIZE/2), int((i+1.5)*SQUARESIZE)), 5)
pygame.display.update()
return True
# Verticle solutions
for s in range(maxColumnIndex, minColumnIndex+1):
if self.board[s, j] == player:
count += 1
if count == 4:
if self.visualize:
pygame.draw.line(screen, WHITE, (int(j*SQUARESIZE+SQUARESIZE/2), int((s+2)*SQUARESIZE)), (int(j*SQUARESIZE+SQUARESIZE/2), int((s-2)*SQUARESIZE)), 5)
pygame.display.update()
return True
# Left diagonal
while row > -1 and col > -1 and self.board[row][col] == player:
count += 1
down_count = count
row = i + 1
col = j + 1
while row < self.shape[0] and col < self.shape[1] and self.board[row][col] == player:
count += 1
if count >= 4:
if self.visualize:
# top, bottom
pygame.draw.line(screen, WHITE, (int((j+0.5-(down_count-1))*SQUARESIZE), int((i+1.5-(down_count-1))*SQUARESIZE)), (int((j+0.5+(4-down_count))*SQUARESIZE), int((i+1.5+(4-down_count))*SQUARESIZE)), 5)
pygame.display.update()
return True
# Right diagonal
while row < self.shape[0] and col > -1 and self.board[row][col] == player:
count += 1
down_count = count
row = i – 1
col = j + 1
while row > -1 and col < self.shape[1] and self.board[row][col] == player:
count += 1
if count >= 4:
if self.visualize:
# top, bottom
pygame.draw.line(screen, WHITE, (int((j+0.5-(down_count-1))*SQUARESIZE), int((i+1.5+(down_count-1))*SQUARESIZE)), (int((j+0.5+(4-down_count))*SQUARESIZE), int((i+1.5-(4-down_count))*SQUARESIZE)), 5)
pygame.display.update()
return True
return len(self.history[0]) + len(self.history[1]) == self.shape[0]*self.shape[1]
def saveGame(self):
with open(os.path.join(‘history’, ‘game’+str(self.game)+’P1.txt’), ‘w’) as filehandle:
for item in self.history[0]:
filehandle.write(‘%s\n’ % item)
with open(os.path.join(‘history’, ‘game’+str(self.game)+’P2.txt’), ‘w’) as filehandle:
for item in self.history[1]:
filehandle.write(‘%s\n’ % item)
def randMove(self):
possible = self.topPosition >= 0
indices = []
for i, p in enumerate(possible):
if p: indices.append(i)
return [random.choice(indices)]
def getBoard(self):
return deepcopy(self.board)
def getEnv(self):
return deepcopy(self)
”’Pygame code used with permission from .
Refer to https://github.com/KeithGalli/Connect4-Python for licensing”’
def draw_board(self):
for c in range(self.shape[1]):
for r in range(self.shape[0]):
pygame.draw.rect(screen, BLUE, (c*SQUARESIZE, r*SQUARESIZE+SQUARESIZE, SQUARESIZE, SQUARESIZE))
pygame.draw.circle(screen, BLACK, (int(c*SQUARESIZE+SQUARESIZE/2), int(r*SQUARESIZE+SQUARESIZE+SQUARESIZE/2)), RADIUS)
for c in range(self.shape[1]):
for r in range(self.shape[0]):
if self.board[r][c] == 1:
pygame.draw.circle(screen, RED, (int((c)*SQUARESIZE+SQUARESIZE/2), height-int((5-r)*SQUARESIZE+SQUARESIZE/2)), RADIUS)
elif self.board[r][c] == 2:
pygame.draw.circle(screen, YELLOW, (int((c)*SQUARESIZE+SQUARESIZE/2), height-int((5-r)*SQUARESIZE+SQUARESIZE/2)), RADIUS)
pygame.display.update()
SQUARESIZE = 100
BLUE = (0,0,255)
BLACK = (0,0,0)
RED = (255,0,0)
YELLOW = (255,255,0)
WHITE = (255,255,255)
ROW_COUNT = 6
COLUMN_COUNT = 7
SQUARESIZE = 100
width = COLUMN_COUNT * SQUARESIZE
height = (ROW_COUNT+1) * SQUARESIZE
size = (width, height)
RADIUS = int(SQUARESIZE/2 – 5)
screen = None
import argparse
from connect4 import connect4
from players import human2, stupidAI, randomAI, human, minimaxAI, alphaBetaAI
from montecarlo import monteCarloAI
parser = argparse.ArgumentParser(description=’Run programming assignment 1′)
parser.add_argument(‘-w’, default=6, type=int, help=’Rows of game’)
parser.add_argument(‘-l’, default=7, type=int, help=’Columns of game’)
parser.add_argument(‘-p1′, default=’human’, type=str, help=’Player 1 agent. Use any of the following: [human, humanTxt, stupidAI, randomAI, monteCarloAI, minimaxAI, alphaBetaAI]’)
parser.add_argument(‘-p2′, default=’human’, type=str, help=’Player 2 agent. Use any of the following: [human, humanTxt, stupidAI, randomAI, monteCarloAI, minimaxAI, alphaBetaAI]’)
parser.add_argument(‘-seed’, default=0, type=int, help=’Seed for random algorithms’)
parser.add_argument(‘-visualize’, default=’True’, type=str, help=’Use GUI’)
parser.add_argument(‘-verbose’, default=’True’, type=str, help=’Print boards to shell’)
parser.add_argument(‘-limit_players’, default=’1,2′, type=str, help=’Players to limit time for. List players as numbers eg [1,2]’)
parser.add_argument(‘-time_limit’, default=’0.5,0.5′, type=str, help=’Time limits for each player. Must be list of 2 elements > 0. Not used if player is not listed’)
# Bools and argparse are not friends
bool_dict = {‘True’: True, ‘False’: False}
args = parser.parse_args()
w = args.w
l = args.l
seed = args.seed
visualize = bool_dict[args.visualize]
verbose = bool_dict[args.verbose]
limit_players = args.limit_players.split(‘,’)
for i, v in enumerate(limit_players):
limit_players[i] = int(v)
time_limit = args.time_limit.split(‘,’)
for i, v in enumerate(time_limit):
time_limit[i] = float(v)
agents = {‘human’: human2, ‘humanTxt’: human, ‘stupidAI’: stupidAI, ‘randomAI’: randomAI, ‘monteCarloAI’: monteCarloAI, ‘minimaxAI’: minimaxAI, ‘alphaBetaAI’: alphaBetaAI}
if __name__ == ‘__main__’:
player1 = agents[args.p1](1, seed)
player2 = agents[args.p2](2, seed)
c4 = connect4(player1, player2, board_shape=(w,l), visualize=visualize, limit_players=limit_players, time_limit=time_limit, verbose=verbose)
c4.play()import numpy as np
import random
import sys
import signal
from players import connect4Player
from copy import deepcopy
class monteCarloAI(connect4Player):
def play(self, env, move):
random.seed(self.seed)
# Find legal moves
env = deepcopy(env)
env.visualize = False
possible = env.topPosition >= 0
indices = []
for i, p in enumerate(possible):
if p: indices.append(i)
# Init fitness trackers
vs = np.zeros(7)
# Play until told to stop
counter = 0
while True:
first_move = random.choice(indices)
turnout = self.playRandomGame(deepcopy(env), first_move)
if turnout == self.position:
vs[first_move] += 1
elif turnout != 0:
vs[first_move] -= 1
if counter % 100 == 0:
move[:] = [np.argmax(vs)]
counter += 1
def playRandomGame(self, env, first_move):
switch = {1:2,2:1}
move = first_move
player = self.position
self.simulateMove(env, move, player)
while not env.gameOver(move, player):
player = switch[player]
possible = env.topPosition >= 0
indices = []
for i, p in enumerate(possible):
if p: indices.append(i)
move = random.choice(indices)
self.simulateMove(env, move, player)
if len(env.history[0]) == 42: return 0
return player
def simulateMove(self, env, move, player):
env.board[env.topPosition[move]][move] = player
env.topPosition[move] -= 1
env.history[0].append(move)
def signal_handler(self):
print(“SIGTERM ENCOUNTERED”)
sys.exit(0)
import random
import time
import pygame
import math
class connect4Player(object):
def __init__(self, position, seed=0):
self.position = position
self.opponent = None
self.seed = seed
random.seed(seed)
def play(self, env, move):
move = [-1]
class human(connect4Player):
def play(self, env, move):
move[:] = [int(input(‘Select next move: ‘))]
while True:
if int(move[0]) >= 0 and int(move[0]) <= 6 and env.topPosition[int(move[0])] >= 0:
move[:] = [int(input(‘Index invalid. Select next move: ‘))]
class human2(connect4Player):
def play(self, env, move):
done = False
while(not done):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.MOUSEMOTION:
pygame.draw.rect(screen, BLACK, (0,0, width, SQUARESIZE))
posx = event.pos[0]
if self.position == 1:
pygame.draw.circle(screen, RED, (posx, int(SQUARESIZE/2)), RADIUS)
pygame.draw.circle(screen, YELLOW, (posx, int(SQUARESIZE/2)), RADIUS)
pygame.display.update()
if event.type == pygame.MOUSEBUTTONDOWN:
posx = event.pos[0]
col = int(math.floor(posx/SQUARESIZE))
move[:] = [col]
done = True
class randomAI(connect4Player):
def play(self, env, move):
possible = env.topPosition >= 0
indices = []
for i, p in enumerate(possible):
if p: indices.append(i)
move[:] = [random.choice(indices)]
class stupidAI(connect4Player):
def play(self, env, move):
possible = env.topPosition >= 0
indices = []
for i, p in enumerate(possible):
if p: indices.append(i)
if 3 in indices:
move[:] = [3]
elif 2 in indices:
move[:] = [2]
elif 1 in indices:
move[:] = [1]
elif 5 in indices:
move[:] = [5]
elif 6 in indices:
move[:] = [6]
move[:] = [0]
class minimaxAI(connect4Player):
def play(self, env, move):
class alphaBetaAI(connect4Player):
def play(self, env, move):
SQUARESIZE = 100
BLUE = (0,0,255)
BLACK = (0,0,0)
RED = (255,0,0)
YELLOW = (255,255,0)
ROW_COUNT = 6
COLUMN_COUNT = 7
pygame.init()
SQUARESIZE = 100
width = COLUMN_COUNT * SQUARESIZE
height = (ROW_COUNT+1) * SQUARESIZE
size = (width, height)
RADIUS = int(SQUARESIZE/2 – 5)
screen = pygame.display.set_mode(size)
# Ad-hoc garbage code for threads that can be killed
# From https://www.geeksforgeeks.org/python-different-ways-to-kill-a-thread/
import threading
from threading import Thread, Event
import ctypes
import sys
class KillableThread(Thread):
def __init__(self, sleep_interval=0, target=None, name=None, args=(), kwargs={}):
super().__init__(None, target, name, args, kwargs)
self._kill = Event()
self._interval = sleep_interval
def run(self):
while True:
# Call custom function with arguments
self._target(*self._args)
# If no kill signal is set, sleep for the interval,
# If kill signal comes in while sleeping, immediately
# wake up and handle
is_killed = self._kill.wait(self._interval)
if is_killed:
print(“Killing Thread”)
def kill(self):
self._kill.set()
class thread_with_exception(threading.Thread):
def __init__(self, target, args):
threading.Thread.__init__(self)
self.func = target
self.args = args
def run(self):
# target function of the thread class
while True:
self.func(*self.args)
def get_id(self):
# returns id of the respective thread
if hasattr(self, ‘_thread_id’):
return self._thread_id
for id, thread in threading._active.items():
if thread is self:
def raise_exception(self):
raise Exception
import sys
import trace
import threading
import time
class thread_with_trace(threading.Thread):
def __init__(self, *args, **keywords):
threading.Thread.__init__(self, *args, **keywords)
self.killed = False
def start(self):
self.__run_backup = self.run
self.run = self.__run
threading.Thread.start(self)
def __run(self):
sys.settrace(self.globaltrace)
self.__run_backup()
self.run = self.__run_backup
def globaltrace(self, frame, event, arg):
if event == ‘call’:
return self.localtrace
return None
def localtrace(self, frame, event, arg):
if self.killed:
if event == ‘line’:
raise SystemExit()
return self.localtrace
def kill(self):
self.killed = True
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com