-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgame.py
More file actions
225 lines (182 loc) · 5.75 KB
/
Copy pathgame.py
File metadata and controls
225 lines (182 loc) · 5.75 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
"""
To Do:
"""
import numpy as np
import os
import math
import time
import random
# Define Constants
LEFT = 0
UP = 1
RIGHT = 2
DOWN = 3
class Game:
def __init__(self, highscore=0, board=None):
# Read in high score from file and initialize
# f = open("highscore.txt", "r")
# self.highscore = int(f.read())
# f.close()
self.highscore = highscore
# Initialize current score as 0
self.score = 0
# Initialize the board with two random tiles
if board:
self.board = board
else:
self.board = np.zeros((4, 4), dtype=int)
self.totalTiles = 0 # Incremented by add_tile
self.add_tile()
self.add_tile()
# Use boolean to check if the game is over
self.gameOver = False
# Add a new tile to an empty cell of the board
def add_tile(self):
# Make a list of tuples of all the empty cells
xVal, yVal = np.where(self.board == 0)
emptyCells = list(zip(xVal,yVal))
# Select one of these cells at random
emptyCell = emptyCells[np.random.choice(len(emptyCells))]
# Select a value of 2 or 4 with a ratio of 9:1
tileVal = np.random.choice([2, 4], p=[0.9, 0.1])
# Update the board
self.board[emptyCell[0]][emptyCell[1]] = tileVal
# Update totalTiles
self.totalTiles += 1
# Check for game over
self.check_for_game_over()
# Print the board and all other necessary information
def display(self):
# Clear the screen and print the score
os.system('clear')
print()
print("Current Score: " + str(self.score))
print("High Score: " + str(self.highscore))
print()
# Iterate through each tile and print accordingly
for row in range(4):
print(end=" ")
for col in range(4):
if self.board[row][col] == 0:
print(end=". ")
elif int(math.log10(self.board[row][col])) == 0:
print(self.board[row][col], end=" ")
elif int(math.log10(self.board[row][col])) == 1:
print(self.board[row][col], end=" ")
elif int(math.log10(self.board[row][col])) == 2:
print(self.board[row][col], end=" ")
elif self.board[row][col] == 1024:
print("1k", end=" ")
elif self.board[row][col] == 2048:
print("2k", end=" ")
elif self.board[row][col] == 4096:
print("4k", end=" ")
else:
print(self.board[row][col])
print()
print()
# Implements slide logic by rotating the board as necessary, sliding left,
# and rotating back. If the move is valid, change the board of this object,
# otherwise create a new state with the new board.
def move(self, input_action, validMove = True):
board = self.board
score = self.score
totalTiles = self.totalTiles
# The logic slides left, so to slide up, for example, rotate counter-clockwise
num_rotations = input_action
board = np.rot90(board, num_rotations)
# The cells changed counter makes sure we don't make moves where the
# board does not change.
cells_changed = 0
# Store the previous score to later determine how many points were earned
# from this turn specifically.
self.prevScore = score
# Iterate through each row to perform sliding logic
for row in range(4):
# As we move across the row, we will keep track of the value that
# a tile "could be merged with".
possible_merge_val = 0
next_open_index = 0
for col in range(4):
currVal = board[row][col]
# If the tile is not empty (i.e. curr_val is not 0), check if
# merge logic is necessary.
if currVal != 0:
# If the value of the current column is the mergable value,
# then merge.
if currVal == possible_merge_val:
# Change the left cell to be merged to 2 times itself
board[row][next_open_index-1] = (currVal * 2)
# Set the current cell to 0
board[row][col] = 0
# Update the score
score += (currVal * 2)
# Decrement the counter for total tiles on the board
totalTiles -= 1
# Increment the counter for cells changed
cells_changed += 1
# After we've merged, no more cells can merge with this
possible_merge_val = 0
# If the current tile is empty,
else:
# If there's an open spot somewhere to the left, slide.
if next_open_index != col:
# Put this tile in the leftmost open spot
board[row][next_open_index] = currVal
# Empty the current cell
board[row][col] = 0
# Increment the cell changed counter
cells_changed += 1
# Update the "mergable value"
possible_merge_val = currVal
# Update the next open index
next_open_index += 1
# Rotate the board back to its original orientation
board = np.rot90(board, 4-num_rotations)
if validMove:
self.board = board
self.score = score
self.totalTiles = totalTiles
self.check_high_score()
# Add a new tile only if the board has changed
if cells_changed != 0:
self.add_tile()
return self.score - self.prevScore
def getReward(self):
return self.score - self.prevScore
def check_high_score(self):
# If the score is greater than the high score...
if self.score > self.highscore:
# Update high score
self.highscore = self.score
def check_for_game_over(self):
# If there are 16 non-zero tiles...
if self.totalTiles == 16:
# The game is over
self.gameOver = True
def update_high_score(self):
# Write high score to file
f = open("highscore.txt", "w")
f.write(str(self.highscore))
f.close()
def reset(self):
# Set score back to 0
self.score = 0
# Clear board and re-initilize with two random tiles
self.board = np.zeros((4, 4), dtype=np.int)
self.totalTiles = 0 # Incremented by add_tile
self.add_tile()
self.add_tile()
self.gameOver = False
if __name__ == "__main__":
start = time.time()
for i in range(1000):
g = Game()
count = 0
while not g.gameOver:
g.move(random.choice([0,1,2,3]))
count += 1
print(f"{count=}", end = " | ")
end = time.time()
print()
print("time ", end - start)