# your code goes here
Open this file in GitHub Desktop You must be signed in to make or propose changes You must be signed in to make or propose changes
"""Pacman, classic arcade game.
Exercises
1. Change the board.
6 2. Change the number of ghosts.
7 3. Change where pacman starts.
8 4. Make the ghosts faster/slower.
9 5. Make the ghosts smarter.
10
11 """
12
13 from random import choice
14 from turtle import *
15 from freegames import floor, vector
16
17 state = { 'score' : 0 }
18 path = Turtle( visible= False )
19 writer = Turtle( visible= False )
20 aim = vector( 5 , 0 )
21 pacman = vector( -40 , -80 )
22 ghosts = [
23 [ vector( -180 , 160 ) , vector( 5 , 0 ) ] ,
24 [ vector( -180 , -160 ) , vector( 0 , 5 ) ] ,
25 [ vector( 100 , 160 ) , vector( 0 , -5 ) ] ,
26 [ vector( 100 , -160 ) , vector( -5 , 0 ) ] ,
27 ]
28 tiles = [
29 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
30 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ,
31 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ,
32 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ,
33 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ,
34 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ,
35 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
36 0 , 1 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
37 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ,
38 0 , 0 , 0 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ,
39 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ,
40 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ,
41 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ,
42 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 ,
43 0 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 ,
44 0 , 1 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ,
45 0 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 ,
46 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ,
47 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
48 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
49 ]
50
51 def square( x, y) :
52 "Draw square using path at (x, y)."
53 path.up ( )
54 path.goto ( x, y)
55 path.down ( )
56 path.begin_fill ( )
57
58 for count in range ( 4 ) :
59 path.forward ( 20 )
60 path.left ( 90 )
61
62 path.end_fill ( )
63
64 def offset( point) :
65 "Return offset of point in tiles."
66 x = ( floor( point.x , 20 ) + 200 ) / 20
67 y = ( 180 - floor( point.y , 20 ) ) / 20
68 index = int ( x + y * 20 )
69 return index
70
71 def valid( point) :
72 "Return True if point is valid in tiles."
73 index = offset( point)
74
75 if tiles[ index] == 0 :
76 return False
77
78 index = offset( point + 19 )
79
80 if tiles[ index] == 0 :
81 return False
82
83 return point.x % 20 == 0 or point.y % 20 == 0
84
85 def world( ) :
86 "Draw world using path."
87 bgcolor( 'black' )
88 path.color ( 'blue' )
89
90 for index in range ( len ( tiles) ) :
91 tile = tiles[ index]
92
93 if tile > 0 :
94 x = ( index % 20 ) * 20 - 200
95 y = 180 - ( index // 20 ) * 20
96 square( x, y)
97
98 if tile == 1 :
99 path.up ( )
100 path.goto ( x + 10 , y + 10 )
101 path.dot ( 2 , 'white' )
102
103 def move( ) :
104 "Move pacman and all ghosts."
105 writer.undo ( )
106 writer.write ( state[ 'score' ] )
107
108 clear( )
109
110 if valid( pacman + aim) :
111 pacman.move ( aim)
112
113 index = offset( pacman)
114
115 if tiles[ index] == 1 :
116 tiles[ index] = 2
117 state[ 'score' ] += 1
118 x = ( index % 20 ) * 20 - 200
119 y = 180 - ( index // 20 ) * 20
120 square( x, y)
121
122 up( )
123 goto( pacman.x + 10 , pacman.y + 10 )
124 dot( 20 , 'yellow' )
125
126 for point, course in ghosts:
127 if valid( point + course) :
128 point.move ( course)
129 else :
130 options = [
131 vector( 5 , 0 ) ,
132 vector( -5 , 0 ) ,
133 vector( 0 , 5 ) ,
134 vector( 0 , -5 ) ,
135 ]
136 plan = choice( options)
137 course.x = plan.x
138 course.y = plan.y
139
140 up( )
141 goto( point.x + 10 , point.y + 10 )
142 dot( 20 , 'red' )
143
144 update( )
145
146 for point, course in ghosts:
147 if abs ( pacman - point) < 20 :
148 return
149
150 ontimer( move, 100 )
151
152 def change( x, y) :
153 "Change pacman aim if valid."
154 if valid( pacman + vector( x, y) ) :
155 aim.x = x
156 aim.y = y
157
158 setup( 420 , 420 , 370 , 0 )
159 hideturtle( )
160 tracer( False )
161 writer.goto ( 160 , 160 )
162 writer.color ( 'white' )
163 writer.write ( state[ 'score' ] )
164 listen( )
165 onkey( lambda : change( 5 , 0 ) , 'Right' )
166 onkey( lambda : change( -5 , 0 ) , 'Left' )
167 onkey( lambda : change( 0 , 5 ) , 'Up' )
168 onkey( lambda : change( 0 , -5 ) , 'Down' )
169 world( )
170 move( )
171 done( )
CiMgeW91ciBjb2RlIGdvZXMgaGVyZQoKCiBPcGVuIHRoaXMgZmlsZSBpbiBHaXRIdWIgRGVza3RvcCAgWW91IG11c3QgYmUgc2lnbmVkIGluIHRvIG1ha2Ugb3IgcHJvcG9zZSBjaGFuZ2VzICBZb3UgbXVzdCBiZSBzaWduZWQgaW4gdG8gbWFrZSBvciBwcm9wb3NlIGNoYW5nZXMgCgoKICIiIlBhY21hbiwgY2xhc3NpYyBhcmNhZGUgZ2FtZS4gCiAgCiBFeGVyY2lzZXMgCiAgCiAxLiBDaGFuZ2UgdGhlIGJvYXJkLiAKNiAyLiBDaGFuZ2UgdGhlIG51bWJlciBvZiBnaG9zdHMuIAo3IDMuIENoYW5nZSB3aGVyZSBwYWNtYW4gc3RhcnRzLiAKOCA0LiBNYWtlIHRoZSBnaG9zdHMgZmFzdGVyL3Nsb3dlci4gCjkgNS4gTWFrZSB0aGUgZ2hvc3RzIHNtYXJ0ZXIuIAoxMCAgCjExICIiIiAKMTIgCiAKMTMgZnJvbSByYW5kb20gaW1wb3J0IGNob2ljZSAKMTQgZnJvbSB0dXJ0bGUgaW1wb3J0ICogCjE1IGZyb20gZnJlZWdhbWVzIGltcG9ydCBmbG9vciwgdmVjdG9yIAoxNiAKIAoxNyBzdGF0ZSA9IHsnc2NvcmUnOiAwfSAKMTggcGF0aCA9IFR1cnRsZSh2aXNpYmxlPUZhbHNlKSAKMTkgd3JpdGVyID0gVHVydGxlKHZpc2libGU9RmFsc2UpIAoyMCBhaW0gPSB2ZWN0b3IoNSwgMCkgCjIxIHBhY21hbiA9IHZlY3RvcigtNDAsIC04MCkgCjIyIGdob3N0cyA9IFsgCjIzICAgICBbdmVjdG9yKC0xODAsIDE2MCksIHZlY3Rvcig1LCAwKV0sIAoyNCAgICAgW3ZlY3RvcigtMTgwLCAtMTYwKSwgdmVjdG9yKDAsIDUpXSwgCjI1ICAgICBbdmVjdG9yKDEwMCwgMTYwKSwgdmVjdG9yKDAsIC01KV0sIAoyNiAgICAgW3ZlY3RvcigxMDAsIC0xNjApLCB2ZWN0b3IoLTUsIDApXSwgCjI3IF0gCjI4IHRpbGVzID0gWyAKMjkgICAgIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIAozMCAgICAgMCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMCwgMCwgMCwgMCwgCjMxICAgICAwLCAxLCAwLCAwLCAxLCAwLCAwLCAxLCAwLCAxLCAwLCAwLCAxLCAwLCAwLCAxLCAwLCAwLCAwLCAwLCAKMzIgICAgIDAsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAsIDAsIDAsIDAsIAozMyAgICAgMCwgMSwgMCwgMCwgMSwgMCwgMSwgMCwgMCwgMCwgMSwgMCwgMSwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgCjM0ICAgICAwLCAxLCAxLCAxLCAxLCAwLCAxLCAxLCAwLCAxLCAxLCAwLCAxLCAxLCAxLCAxLCAwLCAwLCAwLCAwLCAKMzUgICAgIDAsIDEsIDAsIDAsIDEsIDAsIDAsIDEsIDAsIDEsIDAsIDAsIDEsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIAozNiAgICAgMCwgMSwgMCwgMCwgMSwgMCwgMSwgMSwgMSwgMSwgMSwgMCwgMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgCjM3ICAgICAwLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAwLCAwLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAwLCAwLCAwLCAKMzggICAgIDAsIDAsIDAsIDAsIDEsIDAsIDEsIDEsIDEsIDEsIDEsIDAsIDEsIDAsIDAsIDEsIDAsIDAsIDAsIDAsIAozOSAgICAgMCwgMCwgMCwgMCwgMSwgMCwgMSwgMCwgMCwgMCwgMSwgMCwgMSwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgCjQwICAgICAwLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAwLCAwLCAwLCAKNDEgICAgIDAsIDEsIDAsIDAsIDEsIDAsIDAsIDEsIDAsIDEsIDAsIDAsIDAsIDAsIDAsIDEsIDAsIDAsIDAsIDAsIAo0MiAgICAgMCwgMSwgMSwgMCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMCwgMSwgMSwgMCwgMCwgMCwgMCwgCjQzICAgICAwLCAwLCAxLCAwLCAxLCAwLCAxLCAwLCAwLCAwLCAxLCAwLCAxLCAwLCAxLCAwLCAwLCAwLCAwLCAwLCAKNDQgICAgIDAsIDEsIDEsIDEsIDEsIDAsIDEsIDEsIDAsIDEsIDEsIDAsIDEsIDEsIDEsIDEsIDAsIDAsIDAsIDAsIAo0NSAgICAgMCwgMSwgMCwgMCwgMCwgMCwgMCwgMSwgMCwgMSwgMCwgMCwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgCjQ2ICAgICAwLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAwLCAwLCAwLCAKNDcgICAgIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIAo0OCAgICAgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgCjQ5IF0gCjUwIAogCjUxIGRlZiBzcXVhcmUoeCwgeSk6IAo1MiAgICAgIkRyYXcgc3F1YXJlIHVzaW5nIHBhdGggYXQgKHgsIHkpLiIgCjUzICAgICBwYXRoLnVwKCkgCjU0ICAgICBwYXRoLmdvdG8oeCwgeSkgCjU1ICAgICBwYXRoLmRvd24oKSAKNTYgICAgIHBhdGguYmVnaW5fZmlsbCgpIAo1NyAKIAo1OCAgICAgZm9yIGNvdW50IGluIHJhbmdlKDQpOiAKNTkgICAgICAgICBwYXRoLmZvcndhcmQoMjApIAo2MCAgICAgICAgIHBhdGgubGVmdCg5MCkgCjYxIAogCjYyICAgICBwYXRoLmVuZF9maWxsKCkgCjYzIAogCjY0IGRlZiBvZmZzZXQocG9pbnQpOiAKNjUgICAgICJSZXR1cm4gb2Zmc2V0IG9mIHBvaW50IGluIHRpbGVzLiIgCjY2ICAgICB4ID0gKGZsb29yKHBvaW50LngsIDIwKSArIDIwMCkgLyAyMCAKNjcgICAgIHkgPSAoMTgwIC0gZmxvb3IocG9pbnQueSwgMjApKSAvIDIwIAo2OCAgICAgaW5kZXggPSBpbnQoeCArIHkgKiAyMCkgCjY5ICAgICByZXR1cm4gaW5kZXggCjcwIAogCjcxIGRlZiB2YWxpZChwb2ludCk6IAo3MiAgICAgIlJldHVybiBUcnVlIGlmIHBvaW50IGlzIHZhbGlkIGluIHRpbGVzLiIgCjczICAgICBpbmRleCA9IG9mZnNldChwb2ludCkgCjc0IAogCjc1ICAgICBpZiB0aWxlc1tpbmRleF0gPT0gMDogCjc2ICAgICAgICAgcmV0dXJuIEZhbHNlIAo3NyAKIAo3OCAgICAgaW5kZXggPSBvZmZzZXQocG9pbnQgKyAxOSkgCjc5IAogCjgwICAgICBpZiB0aWxlc1tpbmRleF0gPT0gMDogCjgxICAgICAgICAgcmV0dXJuIEZhbHNlIAo4MiAKIAo4MyAgICAgcmV0dXJuIHBvaW50LnggJSAyMCA9PSAwIG9yIHBvaW50LnkgJSAyMCA9PSAwIAo4NCAKIAo4NSBkZWYgd29ybGQoKTogCjg2ICAgICAiRHJhdyB3b3JsZCB1c2luZyBwYXRoLiIgCjg3ICAgICBiZ2NvbG9yKCdibGFjaycpIAo4OCAgICAgcGF0aC5jb2xvcignYmx1ZScpIAo4OSAKIAo5MCAgICAgZm9yIGluZGV4IGluIHJhbmdlKGxlbih0aWxlcykpOiAKOTEgICAgICAgICB0aWxlID0gdGlsZXNbaW5kZXhdIAo5MiAKIAo5MyAgICAgICAgIGlmIHRpbGUgPiAwOiAKOTQgICAgICAgICAgICAgeCA9IChpbmRleCAlIDIwKSAqIDIwIC0gMjAwIAo5NSAgICAgICAgICAgICB5ID0gMTgwIC0gKGluZGV4IC8vIDIwKSAqIDIwIAo5NiAgICAgICAgICAgICBzcXVhcmUoeCwgeSkgCjk3IAogCjk4ICAgICAgICAgICAgIGlmIHRpbGUgPT0gMTogCjk5ICAgICAgICAgICAgICAgICBwYXRoLnVwKCkgCjEwMCAgICAgICAgICAgICAgICAgcGF0aC5nb3RvKHggKyAxMCwgeSArIDEwKSAKMTAxICAgICAgICAgICAgICAgICBwYXRoLmRvdCgyLCAnd2hpdGUnKSAKMTAyIAogCjEwMyBkZWYgbW92ZSgpOiAKMTA0ICAgICAiTW92ZSBwYWNtYW4gYW5kIGFsbCBnaG9zdHMuIiAKMTA1ICAgICB3cml0ZXIudW5kbygpIAoxMDYgICAgIHdyaXRlci53cml0ZShzdGF0ZVsnc2NvcmUnXSkgCjEwNyAKIAoxMDggICAgIGNsZWFyKCkgCjEwOSAKIAoxMTAgICAgIGlmIHZhbGlkKHBhY21hbiArIGFpbSk6IAoxMTEgICAgICAgICBwYWNtYW4ubW92ZShhaW0pIAoxMTIgCiAKMTEzICAgICBpbmRleCA9IG9mZnNldChwYWNtYW4pIAoxMTQgCiAKMTE1ICAgICBpZiB0aWxlc1tpbmRleF0gPT0gMTogCjExNiAgICAgICAgIHRpbGVzW2luZGV4XSA9IDIgCjExNyAgICAgICAgIHN0YXRlWydzY29yZSddICs9IDEgCjExOCAgICAgICAgIHggPSAoaW5kZXggJSAyMCkgKiAyMCAtIDIwMCAKMTE5ICAgICAgICAgeSA9IDE4MCAtIChpbmRleCAvLyAyMCkgKiAyMCAKMTIwICAgICAgICAgc3F1YXJlKHgsIHkpIAoxMjEgCiAKMTIyICAgICB1cCgpIAoxMjMgICAgIGdvdG8ocGFjbWFuLnggKyAxMCwgcGFjbWFuLnkgKyAxMCkgCjEyNCAgICAgZG90KDIwLCAneWVsbG93JykgCjEyNSAKIAoxMjYgICAgIGZvciBwb2ludCwgY291cnNlIGluIGdob3N0czogCjEyNyAgICAgICAgIGlmIHZhbGlkKHBvaW50ICsgY291cnNlKTogCjEyOCAgICAgICAgICAgICBwb2ludC5tb3ZlKGNvdXJzZSkgCjEyOSAgICAgICAgIGVsc2U6IAoxMzAgICAgICAgICAgICAgb3B0aW9ucyA9IFsgCjEzMSAgICAgICAgICAgICAgICAgdmVjdG9yKDUsIDApLCAKMTMyICAgICAgICAgICAgICAgICB2ZWN0b3IoLTUsIDApLCAKMTMzICAgICAgICAgICAgICAgICB2ZWN0b3IoMCwgNSksIAoxMzQgICAgICAgICAgICAgICAgIHZlY3RvcigwLCAtNSksIAoxMzUgICAgICAgICAgICAgXSAKMTM2ICAgICAgICAgICAgIHBsYW4gPSBjaG9pY2Uob3B0aW9ucykgCjEzNyAgICAgICAgICAgICBjb3Vyc2UueCA9IHBsYW4ueCAKMTM4ICAgICAgICAgICAgIGNvdXJzZS55ID0gcGxhbi55IAoxMzkgCiAKMTQwICAgICAgICAgdXAoKSAKMTQxICAgICAgICAgZ290byhwb2ludC54ICsgMTAsIHBvaW50LnkgKyAxMCkgCjE0MiAgICAgICAgIGRvdCgyMCwgJ3JlZCcpIAoxNDMgCiAKMTQ0ICAgICB1cGRhdGUoKSAKMTQ1IAogCjE0NiAgICAgZm9yIHBvaW50LCBjb3Vyc2UgaW4gZ2hvc3RzOiAKMTQ3ICAgICAgICAgaWYgYWJzKHBhY21hbiAtIHBvaW50KSA8IDIwOiAKMTQ4ICAgICAgICAgICAgIHJldHVybiAKMTQ5IAogCjE1MCAgICAgb250aW1lcihtb3ZlLCAxMDApIAoxNTEgCiAKMTUyIGRlZiBjaGFuZ2UoeCwgeSk6IAoxNTMgICAgICJDaGFuZ2UgcGFjbWFuIGFpbSBpZiB2YWxpZC4iIAoxNTQgICAgIGlmIHZhbGlkKHBhY21hbiArIHZlY3Rvcih4LCB5KSk6IAoxNTUgICAgICAgICBhaW0ueCA9IHggCjE1NiAgICAgICAgIGFpbS55ID0geSAKMTU3IAogCjE1OCBzZXR1cCg0MjAsIDQyMCwgMzcwLCAwKSAKMTU5IGhpZGV0dXJ0bGUoKSAKMTYwIHRyYWNlcihGYWxzZSkgCjE2MSB3cml0ZXIuZ290bygxNjAsIDE2MCkgCjE2MiB3cml0ZXIuY29sb3IoJ3doaXRlJykgCjE2MyB3cml0ZXIud3JpdGUoc3RhdGVbJ3Njb3JlJ10pIAoxNjQgbGlzdGVuKCkgCjE2NSBvbmtleShsYW1iZGE6IGNoYW5nZSg1LCAwKSwgJ1JpZ2h0JykgCjE2NiBvbmtleShsYW1iZGE6IGNoYW5nZSgtNSwgMCksICdMZWZ0JykgCjE2NyBvbmtleShsYW1iZGE6IGNoYW5nZSgwLCA1KSwgJ1VwJykgCjE2OCBvbmtleShsYW1iZGE6IGNoYW5nZSgwLCAtNSksICdEb3duJykgCjE2OSB3b3JsZCgpIAoxNzAgbW92ZSgpIAoxNzEgZG9uZSgpIAo=