CS 5 Lecture 19

Download Report

Transcript CS 5 Lecture 19

EXAM 2
Mon/Tue
"Intelligent" CS 5
Hw 10 due 11/15
An object is structured data that is
alive, responsible, and intelligent.
Sound too friendly?
This week’s objects and classes will be just the opposite ...
X to move.
Is there a
way to win?
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |X| | | |
| |X| |X|O| | |
|X|O|O|O|X|O| |
--------------0 1 2 3 4 5 6
Coding Style
def tomorrow(self):
"""Changes the calling object so that it represents one calendar
day after the date it originally represented.
"""
if self.month in [1,3,5,7,8,10] and self.day == 31:
self.day = 0
self.month += 1
elif self.month in [4,6,9,11] and self.day == 30:
self.day = 0
self.month += 1
elif self.month == 2:
if self.isLeapYear() and self.day == 29:
self.day = 0
self.month += 1
elif (self.isLeapYear() == False) and self.day == 28:
self.day = 0
self.month += 1
elif self.month == 12 and self.day == 31:
self.day = 0
self.month = 1
self.year += 1
self.day += 1
Better Style, But...
def tomorrow(self):
"""Changes the calling object so that it represents one calendar
day after the date it originally represented.
"""
DIM = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if self.isLeapYear() == True:
DIM = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
self.day += 1
if self.day > DIM[self.month]:
self.day = 1
self.month += 1
if self.month > 12:
self.month = 1
self.year += 1
else:
self.day += 1
if self.day > DIM[self.month]:
self.day = 1
self.month += 1
if self.month > 12:
self.month = 1
self.year += 1
An Elegant Solution
def tomorrow(self):
"""Changes the calling object so that it represents one calendar
day after the date it originally represented.
"""
DIM = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if self.isLeapYear():
DIM[2] = 29
self.day += 1
if self.day > DIM[self.month]:
self.day = 1
self.month += 1
if self.month > 12:
self.month = 1
self.year += 1
isBefore/isAfter
def isBefore(self, d2):
""" Returns true if self is before d2 """
if self.year < d2.year:
return True
if self.month < d2.month and self.year == d2.year:
return True
if self.day < d2.day and d2.month == self.month and \
self.year == d2.year:
return True
return False
def isAfter(self, d2):
""" Returns true if self is after d2 """
if self.year > d2.year:
return True
if self.month > d2.month and self.year == d2.year:
return True
if self.day > d2.day and d2.month == self.month and \
self.year == d2.year:
return True
return False
An Elegant Solution
def isBefore(self, d2):
""" Returns true if self is before d2 """
if self.year < d2.year:
return True
if self.month < d2.month and self.year == d2.year:
return True
if self.day < d2.day and d2.month == self.month and \
self.year == d2.year:
return True
return False
def isAfter(self, d2):
""" Returns true if self is after d2 """
return d2.isBefore(self)
Another Elegant Solution
def isBefore(self, d2):
""" Returns true if self is before d2 """
return ([self.year, self.month, self.day] <
[d2.year, d2.month, d2.day])
def isAfter(self, d2):
""" Returns true if self is after d2 """
return d2.isBefore(self)
diff
def diff( self, d2 ):
""" Returns the number of days between self and d2 """
dcopy = self.copy()
difference = 0
if dcopy.isBefore(d2) == True:
while dcopy.isBefore(d2) == True:
dcopy.tomorrow()
difference -= 1
else:
while dcopy.isAfter(d2):
dcopy.yesterday()
difference += 1
return difference
An Elegant Solution
def diff( self, d2 ):
""" Returns the number of days between self and d2 """
dcopy = self.copy()
difference = 0
while dcopy.isBefore(d2):
dcopy.tomorrow()
difference -= 1
while dcopy.isAfter(d2):
dcopy.yesterday()
difference += 1
return difference
Aargh!
Python has no Connect-four datatype…
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |X| | | |
| |X| |X|O| | |
|X|O|O|O|X| |O|
--------------0 1 2 3 4 5 6
… but we can correct that!
Can I see a
demo?
Designing classes
1) What data? (Data Members)
Not limited to 7x6!
2) What are objects' crucial capabilities? (Methods)
Connect Four:
Board
b
list
data
the object b
str
str
str
str
str
str
str
str
str
str
str
str
int
width
int
height
data
What is the name of the method
that will construct this data?
Connect Four:
constructor
class Board:
""" a datatype representing a C4 board
with an arbitrary number of rows and cols
"""
def __init__( self, width, height ):
""" the constructor for objects of type Board """
self.width = width
self.height = height
self.data = []
# this will be the board
for row in range( 6 ):
boardRow = []
for col in range( 7 ):
boardRow += [' ']
# add a space to this row
self.data += [boardRow]
Bad magic?
Connect Four:
Board
b
list
data
str
str
str
str
str
str
str
str
str
What is the name of the method
that will print this data?
the object b
str
str
str
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |X| | | |
| |X| |X|O| | |
|X|O|O|O|X| |O|
--------------0 1 2 3 4 5 6
int
width
int
height
Connect Four:
__repr__
def __repr__(self):
""" this method returns a string representation
for an object of type Board
"""
s = ''
which row is row 0,
for row in range( 6 ):
row 1, and so on?
s += '|'
for col in range( 7 ):
s += self.data[row][col] + '|'
s += '\n'
To change?
To add?
return s
NAME:
class Board:
def allowsMove(self, col):
"Quiz"
Write allowsMove to return
True if col is a valid move;
False otherwise.
a C4
board
col #
'X' or 'O'
def addMove(self, col, ox):
for row in range( self.height ):
if self.data[row][col] != ' ':
self.data[row-1][col] = ox
self.data[self.height-1][col] = ox
Step through this
addMove method.
What is each line doing?
How many problems
are there?
C4 Board class:
methods
the “constructor”
__init__( self, width, height )
checks if allowed
allowsMove( self, col )
places a checker
removes a checker
outputs a string
checks if any space is left
checks if a player has won
play (person vs. person)!
addMove( self, col, ox )
delMove( self, col )
__repr__( self )
isFull( self )
winsFor( self, ox )
hostGame( self )
Which of these will require
the most thought?
winsFor( self, ox )
b.winsFor( 'X' )
b
or 'O'
X
O
Thoughts?
corner cases?
?
Strategic thinking == intelligence
Two-player games have been a key focus of AI as
long as computers have been around…
In 1945, Alan Turing
predicted that computers
would be better chess
players than people in
~ 50 years…
and thus would have
achieved intelligence.
Alan Turing memorial
Manchester, England
?
Strategic thinking == intelligence
Two-player games have been a key focus of AI as
long as computers have been around…
computers
good at looking ahead in
the game to find winning
combinations of moves
humans
good at evaluating the
strength of a board
for a player
… humans and computers have different
relative strengths in these games.
How humans play games…
An experiment (by A. deGroot) was performed
in which chess positions were shown to novice
and expert players…
- experts could reconstruct these perfectly
- novice players did far worse…
How humans play games…
An experiment (by A. deGroot) was performed
in which chess positions were shown to novice
and expert players…
- experts could reconstruct these perfectly
- novice players did far worse…
Random chess positions (not legal ones) were
then shown to the two groups
- experts and novices did equally
well (badly) at reconstructing them!
?
Strategic thinking == intelligence
Two-player games have been a key focus of AI as
long as computers have been around…
computers
good at looking ahead in
the game to find winning
combinations of moves
building an AI chess player
humans
good at evaluating the
strength of a board
for a player
emulating a human by
evaluating a board position
… humans and computers have different
relative strengths in these games.
The Player class
Details
Player
pForX
(data and methods)
What data and methods are needed to
construct and implement a Player object?
Let's see a demo!
Player
Picture of a Player object
DATA
Player
pForX
3
'LEFT'
'X'
string
ox
string
tbt
checker, O or X
tiebreakType
int
ply
__init__(self, ox, tbt, ply)
__repr__(self)
oppCh(self)
scoreBoard(self, b)
scoresFor(self, b)
tiebreakMove(self, scores)
nextMove(self, b)
METHODS
scoreBoard
‘X’
‘O’
Assigns a score to any board, b
A simple system:
Score for
Score for
100.0
50.0
0.0
for a win
for anything else
for a loss
Score for
Score for
scoreBoard
Assigns a score to any board, b
A simple system:
100.0
50.0
0.0
for a win
for anything else
for a loss
-1.0
illegal board
Implementation ideas…
scoreBoard(self, b)
How can there be no
'X' or 'O' input?
What class is
this method in?
What methods that
already exist will
come in handy?
This doesn't seem
to be looking very
far ahead !
Looking further ahead…
scoreBoard looks ahead 0 moves
The "Zen" approach -we are excellent at this!
0-ply
If you look one move ahead, how many
possibilities are there to consider?
A 1-ply lookahead
player will "see" an
impending victory.
to move…
1-ply
score
A score for
each column…?
Looking further ahead…
scoreBoard looks ahead 0 moves
The "Zen" approach -we are excellent at this!
0-ply
If you look one move ahead, how many
possibilities are there to consider?
A 2-ply lookahead
player will also "see"
an opponent's
impending victory.
to move…
1-ply
score
What about 3-ply?
2-ply
score
Looking further ahead…
scoreBoard looks ahead 0 moves
If you look one move ahead, how many
possibilities are there to consider?
The "Zen" approach -we are excellent at this!
0-ply
1-ply
2-ply
scoresFor( self, b ) returns a LIST of scores,
one for each column you can choose to move next…
Example 1-ply and 2-ply lookahead scores
|O| | | | | | |
|X| | | |O| |X|
|O| | | |X|O|X|
|X| | | |O|O|X|
|X| |X| |X|O|O|
|X| |O|O|O|X|X|
--------------0 1 2 3 4 5 6
| | | | | | |O|
| | | | | | |O|
| | | | | | |X|
|X| |X|O| | |O|
|X|O|O|X| |X|X|
|X|O|O|O| |O|X|
--------------0 1 2 3 4 5 6
It is O’s move. What scores does a 1-ply
lookahead for O assign to each move?
col 0
col 1
col 2
col 3
col 4
col 5
col 6
Which change at 2-ply?
It is X’s move. What scores does a 2-ply
lookahead for X assign to each move?
col 0
col 1
col 2
col 3
col 4
col 5
col 6
Which change at 3-ply?
Practice
b
‘X’
‘O’
col 0
col 1
col 2
col 3
col 4
col 5
col 6
col 0
col 1
col 2
col 3
col 4
col 5
col 6
col 0
col 1
col 2
col 3
col 4
col 5
col 6
col 0
col 1
col 2
col 3
col 4
col 5
col 6
0-ply scores for O:
1-ply scores for O:
2-ply scores for O:
3-ply scores for O:
Solutions
0-ply scores for O:
1-ply scores for O:
2-ply scores for O:
3-ply scores for O:
b
‘X’
‘O’
col 0
col 1
col 2
col 3
col 4
col 5
col 6
-1
50
50
50
50
50
50
col 0
col 1
col 2
col 3
col 4
col 5
col 6
-1
50
50
100
50
50
50
col 0
col 1
col 2
col 3
col 4
col 5
col 6
-1
0
0
100
0
0
50
col 0
col 1
col 2
col 3
col 4
col 5
col 6
-1
0
0
100
0
0
100
Computer Chess
Computers cut their teeth playing chess…
first paper: 1950
Ranking
beginner
500
early programs ~ 1960’s
100’s of moves/sec
amateur
1200
MacHack (1100) ~ 1967 MIT
10,000’s of moves/sec
1,000,000’s moves/sec
world ranked
2000
Slate (2070) ~ 1970’s Northwestern
Deep Thought ~ 1989 Carnegie Mellon
Deep Blue ~ 1996
2800
IBM
world champion
Deep Blue rematch ~ 1997 IBM
3,500,000 moves/sec
Deep Fritz: 2002
X3D Fritz: 2003
Hydra: 2006
What is Hydra's
chess rating?
200,000,000 moves/sec
Games’ Branching Factors
• On average, there are fewer than 40 possible moves that a
chess player can make from any board configuration…
0 Ply
1 Ply
2 Ply
Branching Factor Estimates
for different two-player games
Hydra at home in
the United Arab
Emirates…
Hydra looks ahead 18 ply !
Tic-tac-toe
4
Connect Four
7
Checkers
10
Othello
30
Chess
40
Go
300
Games’ Branching Factors
0 Ply
1 Ply
2 Ply
Branching Factor Estimates
for different two-player games
Boundaries for
qualitatively
different games…
Tic-tac-toe
4
Connect Four
7
Checkers
10
Othello
30
Chess
40
Go
300
Games’ Branching Factors
0 Ply
1 Ply
2 Ply
Branching Factor Estimates
for different two-player games
Progress
“solved” games
computer-dominated
human-dominated
Tic-tac-toe
4
Connect Four
7
Checkers
10
Othello
30
Chess
40
Go
300
‘X’
‘O’
new‘X’
scoresFor each column
b
(1) For each possible move
(2) Add it to the board
Col 6
Col 0
Col 5
Col 1
Col 2
Col 3
Col 4
‘X’
‘O’
new‘X’
scoresFor each column
b
(1) For each possible move
(2) Add it to the board
(3) Ask OPPONENT to
score each board
At what ply?
0.0
50.0
Col 6
Col 0
Col 5
Col 1
Col 2
Col 3
Col 4
50.0
50.0
0.0
0.0
0.0
‘X’
‘O’
new‘X’
scoresFor each column
b
(1) For each possible move
(2) Add it to the board
What to assign for a score?
(3) Ask OPPONENT to
score each board
(4) Take the opponent's
MAX
0.0
50.0
Col 6
Col 0
Col 5
Col 1
Col 2
Col 3
Col 4
50.0
50.0
0.0
0.0
0.0
scoresFor
def scoresFor(self, b):
(1) For each possible move
(2) Add it to the board
(3) Ask OPPONENT to
score each board - at ? ply
(4) the score is 100-max
def tiebreakMove(self, scores):
Write tiebreakMove to
return the leftmost best score
inside the list scores
if self.tbt == 'LEFT':
How would 'RANDOM' and 'RIGHT' work differently?
hw11 this week
http://www.stanford.edu/~ccecka/research/C4.html
• Problem 2: A Connect Four Board…
• Problem 3: A Connect Four Player…
• Extra: scoreBoard4Tourney and a CS 5 C4 round-robin
Using more scores
than 0, 50, and 100 !
don't give this board a 50.0 !
“Quiz”
Names:
|O| | | | | | |
|X| | | |O| |X|
|O| | | |X|O|X|
|X| | | |O|O|X|
|X| |X| |X|O|O|
|X| |O|O|O|X|X|
--------------0 1 2 3 4 5 6
It is O’s move. What scores does a 1-ply
lookahead for O assign to each move?
col 0
col 1
col 2
col 3
col 4
col 5
col 6
-1
100
50
100
50
100
50
Which change at 2-ply?
0
0
| | | | | | |O|
| | | | | | |O|
| | | | | | |X|
|X| |X|O| | |O|
|X|O|O|X| |X|X|
|X|O|O|O| |O|X|
--------------0 1 2 3 4 5 6
It is X’s move. What scores does a 2-ply
lookahead for X assign to each move?
be careful!
col 0
col 1
col 2
col 3
col 4
col 5
col 6
100
0
0
0
50
0
-1
0
Which change at 3-ply?
|O| | | | | | |
|X| | | |O| |X|
|O| | | |X|O|X|
|X| | | |O|O|X|
|X| |X| |X|O|O|
|X| |O|O|O|X|X|
--------------0 1 2 3 4 5 6
It is O’s move. What scores does a 1-ply
lookahead for O assign to each move?
col 0
col 1
col 2
col 3
col 4
col 5
col 6
Which change at 2-ply?
Looking further ahead …
0 ply: Zen choice of move: here and now
1 ply:
2 ply:
3 ply:
X’s move
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| |O|X| | | | |
|O|X|X|X| |O|O|
--------------0 1 2 3 4 5 6
X’s move
| | | | | | | |
| | | | | | | |
|O| | | | | | |
|X| | | | | | |
|X|O|O| | |X| |
|O|X|X|O|X|O| |
--------------0 1 2 3 4 5 6
X‘s move
| | | | | | | |
| | | | | | | |
| | | | |X| | |
| | | | |O|O| |
| |X|X| |X|O| |
|O|X|O| |O|X| |
--------------0 1 2 3 4 5 6
(1) Player will win
(2) Player will avoid losing
(3) Player will set up
a win by forcing the
opponent to avoid losing
‘X’
‘O’
new‘X’
Choosing the best move
b
(1) For each possible move
(2) Add it to the board
(3) Ask OPPONENT to
score each board - ply?
(4) Reverse the scores
100.0
50.0
Col 6
Col 0
Col 5
Col 1
Col 2
Col 3
Col 4
50.0
50.0
100.0
100.0
100.0
‘X’
‘O’
new‘X’
Choosing the best move
b
(1) For each possible move
(2) Add it to the board
(3) Ask OPPONENT to
score each board - ply?
(4) Reverse the scores
(5) Find one max - that's it!
100.0
50.0
Col 6
Col 0
Col 5
Col 1
Col 2
Col 3
Col 4
50.0
50.0
100.0
100.0
100.0
Connect Four
For your convenience, the creators of Python’s library have included
a Board class that can represent any size of Connect Four board... !
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |X| | | |
| |X| |X|O| | |
|X|O|O|O|X| |O|
--------------0 1 2 3 4 5 6
Suppose our Board class's 2d list of
lists is named self.data. What is
the name of this single spot?
Connect Four: the object b
This is true for sufficiently broad definitions of “the creators of Python’s library” ...
data members
int
NROWS
Board
b
What is
player ?
int
NCOLS
list
data
char
char
char
char
char
char
char
char
char
char
char
char
def addMove(self, col, player)
def allowsMove(self, col)
def winsFor(self, player)
methods
Connect Four: the object b
This is true for sufficiently broad definitions of “the creators of Python’s library” ...
data members
int
NROWS
Board
b
Which methods will
alter b? Which
leave it alone?
int
NCOLS
list
data
char
char
char
char
char
char
char
char
char
char
char
char
def addMove(self, col, player)
def allowsMove(self, col)
def winsFor(self, player)
methods
Connect Four: Board
class Board:
def __init__( self, numRows, numCols ):
""" our Board's constructor """
self.NROWS = numRows
self.NCOLS = numCols
self.data = []
for r in range(self.NROWS):
look familiar?
onerow = [' ']*self.NCOLS
self.data += [onerow]
def __repr__(self):
""" thoughts? """
Starting code for the Board class
Connect Four: Board
class Board:
def __init__( self, numRows, numCols ):
""" our Board's constructor """
self.NROWS = numRows
self.NCOLS = numCols
self.data = []
for r in range(self.NR):
look familiar?
onerow = [' ']*self.NC
self.data += [onerow]
def __repr__(self):
""" thoughts? """
s = '\n'
for r in range(self.NROWS):
s += '|'
for c in range(self.NCOLS):
s += self.data[r][c] + '|'
a bit more to go !
return s
Problem 2
Hw11 Pr2: Connect Four Board
class Board
__init__
the “constructor”
allowsMove
checks if allowed
addMove
places a checker
__repr__
outputs to screen
isFull
winsFor
hostGame
checks if space left
checks if a player has won
play!
What's trickiest here?
Problem 2
Hw11 Pr2: Connect Four Board
class Board
__init__
the “constructor”
allowsMove
checks if allowed
addMove
places a checker
__repr__
outputs to screen
isFull
winsFor
hostGame
checks if space left
checks if a player has won
play!
What's trickiest here?
What's wrong here?
def winsForHoriz(self, player):
inarow = 0
for r in range(self.NROWS):
for c in range(self.NCOLS):
if self.data[r][c] == player:
inarow += 1
else:
inarow = 0
if inarow == 4:
return True
return False
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |O|O| | |
|X|X| |O|X|X|X|
|X|O|O|O|O|X|X|
--------------0 1 2 3 4 5 6
Strategies?
horizontals
verticals
diagonals ??
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |O|O| | |
|X|X| |O|X|X|X|
|X|O|O|O|O|X|X|
--------------0 1 2 3 4 5 6
class
{
#
#
#
#
#
“Quiz”
Board
__init__ and __repr__ methods here…
3 data members:
self.NR == number of rows
self.NC == number of cols
self.data == the 2d list of lists of chars
Briefly, what is each line of
the mysteryMethod doing?
Which method is it?
1
def mysteryMethod(self, col, ox):
r = 0
while r < self.NR and self.data[r][col] == ' ':
r += 1
self.data[r-1][col] = ox
2
3
Could it go wrong?
def allowsMove(self, col):
Write allowsMove to return
whether the input col is a
valid column to move.
(True or False)
}
Problem 2
Hw11 Pr2: Connect Four Board
class Board
__init__
the “constructor”
allowsMove
checks if allowed
addMove
places a checker
__repr__
outputs to screen
isFull
winsFor
hostGame
checks if space left
checks if a player has won
play!
What's trickiest here?
Problem 2
Hw11 Pr2: Connect Four Board
class Board
__init__
the “constructor”
allowsMove
checks if allowed
addMove
places a checker
__repr__
outputs to screen
isFull
winsFor
hostGame
checks if space left
checks if a player has won
play!
What's trickiest here?
Strategies?
horizontals
verticals
diagonals ??
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |X| | | |
| |X| |X|O| | |
|X|O|O|O|O| |O|
--------------0 1 2 3 4 5 6