-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathship_game.py
200 lines (171 loc) · 4.84 KB
/
ship_game.py
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
import random
try:
import cPickle as pickle
except:
import pickle
class BoardSerializer:
def __init__(self, board):
self.board = board
@staticmethod
def get_path(id, player_id):
return "data/%s_%s.pickle" % (str(id), player_id)
def store(self, id, player_id):
path = self.get_path(id, player_id)
with open(path, 'wb') as f:
pickle.dump(self.board, f)
@staticmethod
def load(id, player_id):
path = BoardSerializer.get_path(id, player_id)
with open(path, 'rb') as f:
board_data = pickle.load(f)
return board_data
class Ship:
ORIENTATION_VERTICAL=1
ORIENTATION_HORIZONTAL=2
def __init__(self, length, orientation, name="Ship"):
self.length = length
self.orientation = orientation
self.name = name
self.y = -1
self.x = -1
self.points = {}
def update_points(self):
self.points = {}
x = self.x
y = self.y
for i in xrange(self.length):
self.points[(y,x)] = 1
if self.orientation == Ship.ORIENTATION_VERTICAL:
y += 1
else:
x += 1
def set_location(self, y, x):
self.y = y
self.x = x
self.update_points()
def get_points(self):
return self.points.keys()
def has_point(self, y, x):
return (y, x) in self.points
def as_json(self):
"""
This is in fact not JSON, but a dict that is ready to be converted to JSON
with jsonify().
"""
d = {}
d['name'] = self.name
d['length'] = self.length
if self.orientation == Ship.ORIENTATION_VERTICAL:
d['orientation'] = "vertical"
else:
d['orientation'] = "horizontal"
d['y'] = self.y
d['x'] = self.x
return d
def place_ships_randomly(board):
"""
Place ships randomly onto the board for the user
"""
def random_orientation():
r = random.randint(0,1)
return (Ship.ORIENTATION_VERTICAL, Ship.ORIENTATION_HORIZONTAL)[r]
ships = []
ships.append(Ship(2, random_orientation(), "Destroyer"))
ships.append(Ship(2, random_orientation(), "Destroyer"))
ships.append(Ship(3, random_orientation(), "Submarine"))
ships.append(Ship(3, random_orientation(), "Submarine"))
ships.append(Ship(3, random_orientation(), "Cruiser"))
ships.append(Ship(3, random_orientation(), "Cruiser"))
ships.append(Ship(4, random_orientation(), "Battleship"))
ships.append(Ship(5, random_orientation(), "Carrier"))
while len(ships) > 0:
ship = ships.pop()
y, x = random.randint(0,board.ROWS-1), random.randint(0,board.COLS-1)
while not board.place_ship(y, x, ship):
y, x = random.randint(0,board.ROWS-1), random.randint(0,board.COLS-1)
class GameBoard(object):
def __init__(self):
self.ROWS=16
self.COLS=16
self.board = []
self.init_board()
self.ships = []
self.ship_sunk = None
# for now, we will place ships for the user
place_ships_randomly(self)
def init_board(self):
"""
A board is stored as a list of strings. The key for objects on the grid is:
* - Water
o - Battleship
X - Hit
- - Miss
"""
for i in xrange(self.ROWS):
self.board.append(['*' for i in xrange(self.COLS)])
def get_opponent_view(self):
"""
Get the view of the board from opponent's view.
"""
return None
def place_ship(self, y, x, ship):
"""
Place a ship onto the board.
Returns True if successful, False otherwise
"""
steps = []
for i in xrange(ship.length):
steps.append((y, x))
if self.out_of_bounds(y, x) or self.board[y][x] != '*':
return False
if ship.orientation == Ship.ORIENTATION_VERTICAL:
y += 1
elif ship.orientation == Ship.ORIENTATION_HORIZONTAL:
x += 1
# now place the ship
for y, x in steps:
self.board[y][x] = 'o'
ship.set_location(steps[0][0], steps[0][1])
self.ships.append(ship)
return True
def all_ships_are_placed(self):
pass
def out_of_bounds(self, y, x):
return y < 0 or y >= self.ROWS or x < 0 or x >= self.COLS
def fire_shot(self, y, x):
"""
Fire a shot onto this board. Returns HIT, MISS, or INVALID
"""
self.ship_sunk = None
if self.out_of_bounds(y, x):
return "INVALID"
if self.board[y][x] == 'X' or self.board[y][x] == '-':
return "INVALID"
if self.board[y][x] == '*':
self.board[y][x] = '-'
return "MISS"
self.board[y][x] = 'X'
result = "HIT"
sunk = True
#check which ship was hit
for ship in self.ships:
if ship.has_point(y,x):
#check if sunk
for y,x in ship.get_points():
if self.board[y][x] != 'X':
sunk = False
break
if sunk:
self.ship_sunk = ship
break
return result
def is_game_over(self):
for row in self.board:
if 'o' in row:
return False
return True
def __str__(self):
s = ""
for row in self.board:
s += "".join(row) + "\n"
return s