forked from JRoegit/battleship
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtemp2.py
337 lines (252 loc) · 10.4 KB
/
temp2.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
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
from bauhaus import Encoding, proposition, constraint, Or, And
from bauhaus.utils import count_solutions, likelihood
import string
import random
import pprint
pp = pprint.PrettyPrinter(indent=4)
# import numpy as np
# import seaborn as sn
# import matplotlib.pyplot as plt
# These two lines make sure a faster SAT solver is used.
from nnf import config
config.sat_backend = "kissat"
# Encoding that will store all of your constraints
E = Encoding()
# To create propositions, create classes for them first, annotated with "@proposition" and the Encoding
@proposition(E)
class BasicPropositions:
def __init__(self, data):
self.data = data
def __repr__(self):
return f"A.{self.data}"
class Hashable:
def __hash__(self):
return hash(str(self))
def __eq__(self, __value: object) -> bool:
return hash(self) == hash(__value)
def __repr__(self):
return str(self)
BOARD_SIZE = 6
# ----------------------------------------- Propositions -----------------------------------------
@proposition(E)
class Boat(Hashable):
def __init__(self, coords: tuple, length: int, orientation: str):
self.coords = coords
self.length = length
self.orientation = orientation
def __str__(self):
boat_coords = ""
for coord in self.coords:
boat_coords += (f"({coord[0]},{coord[1]}),")
boat_coords.rstrip(",")
return f"{boat_coords} + {self.length} + {self.orientation}"
@proposition(E)
class Game(Hashable):
def __init__(self, boats:tuple):
self.boats = boats
def __str__(self):
game = ""
for boat in self.boats:
game+=(f"({boat}, ")
game.rstrip(", ")
game+=")"
return f"{game}"
@proposition(E)
class Guess(Hashable):
def __init__(self, coords: tuple):
self.coords = coords
def __str__(self):
return f"Guess({self.coords})"
# ----------------------------------------- Variables -----------------------------------------
board_status = [[' ' for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
guesses = []
# Mini-Game will have one boat of lengths 5, 4, and 3
all_games = []
# ----------------------------------------- Create all variations -----------------------------------------
def create_coords(length, orientation, board_size):
boats = []
if orientation == "vertical":
for start in range((board_size + 1) - length):
for r in range(board_size):
temp_coords = []
for c in range(length):
temp_coords.append((r, c + start))
coords = tuple(temp_coords)
boats.append(Boat(coords, length, orientation))
elif orientation == "horizontal":
for start in range((board_size + 1) - length):
for r in range(board_size):
temp_coords = []
for c in range(length):
temp_coords.append((r, c + start))
coords = tuple(temp_coords)
boats.append(Boat(coords, length, orientation))
return boats
# Boats by size and orientation
all_boats_5_horizontal = create_coords(5, "horizontal", BOARD_SIZE)
all_boats_5_vertical = create_coords(5, "vertical", BOARD_SIZE)
all_boats_4_horizontal = create_coords(4, "horizontal", BOARD_SIZE)
all_boats_4_vertical = create_coords(4, "vertical", BOARD_SIZE)
all_boats_3_horizontal = create_coords(3, "horizontal", BOARD_SIZE)
all_boats_3_vertical = create_coords(3, "vertical", BOARD_SIZE)
# Boats by size
all_boats_5 = all_boats_5_horizontal + all_boats_5_vertical
all_boats_4 = all_boats_4_horizontal + all_boats_4_vertical
all_boats_3 = all_boats_3_horizontal + all_boats_3_vertical
# All the boats
all_boats = all_boats_5 + all_boats_4 + all_boats_3
# there is only one boat of length 5,4, and 3 in each game
for boat1 in all_boats_5:
for boat2 in all_boats_4:
for boat3 in all_boats_3:
all_games.append(Game(tuple([boat1, boat2, boat3])))
# ----------------------------------------- Guessing Stuff -----------------------------------------
def get_user_guess(board_status):
while True:
try:
col_input = input("Enter column (A, B, C, etc.): ").upper()
row_input = input("Enter row (1, 2, 3, etc.): ")
col = string.ascii_uppercase.index(col_input)
row = int(row_input) - 1
if 0 <= row < BOARD_SIZE and 0 <= col < BOARD_SIZE:
if board_status[row][col] in ['H', 'M']:
print("Spot already guessed. Please choose another spot.")
else:
return (row, col) # Return row and column as zero-indexed values
else:
print("Invalid input. Please enter a valid coordinate.")
except (ValueError, IndexError):
print("Invalid input. Please enter a valid coordinate.")
def process_guess(game_board, player_board, x, y):
"""
Check if the guess is a hit or a miss and update the player's board accordingly.
"""
if game_board[x][y] == 1:
player_board[x][y] = 'H' # Mark as hit on the player's board
return True
else:
player_board[x][y] = 'M' # Mark as miss on the player's board
return False
# ----------------------------------------- Generate Random Game -----------------------------------------
BOAT_LENGTHS = [5, 4, 3] # Lengths of boats to be placed
def is_valid_placement(board, boat_coords):
for x, y in boat_coords:
if x < 0 or x >= BOARD_SIZE or y < 0 or y >= BOARD_SIZE or board[x][y] == 1:
return False
# Check surrounding cells
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
adj_x, adj_y = x + dx, y + dy
if 0 <= adj_x < BOARD_SIZE and 0 <= adj_y < BOARD_SIZE and board[adj_x][adj_y] == 1:
return False
return True
def place_boat(board, length, max_attempts=1000):
attempts = 0
while attempts < max_attempts:
orientation = random.choice(['horizontal', 'vertical'])
if orientation == 'horizontal':
x = random.randint(0, BOARD_SIZE - 1)
y = random.randint(0, BOARD_SIZE - length)
boat_coords = [(x, y + i) for i in range(length)]
else:
x = random.randint(0, BOARD_SIZE - length)
y = random.randint(0, BOARD_SIZE - 1)
boat_coords = [(x + i, y) for i in range(length)]
if is_valid_placement(board, boat_coords):
for coord in boat_coords:
board[coord[0]][coord[1]] = 1 # Mark the boat position
return True
attempts += 1
return False # Failed to place the boat
def generate_game():
board = [[0 for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
for length in BOAT_LENGTHS:
if not place_boat(board, length):
# Could not place a boat, so start over or handle it differently
return generate_game() # This is a simple recursive approach to start over
return board
# ----------------------------------------- Frequency Map Stuff -----------------------------------------
def is_valid_game(game):
# Check each pair of boats for separation
for i in range(len(game.boats)):
for j in range(i + 1, len(game.boats)):
if not boats_are_separated(game.boats[i], game.boats[j]):
return False
return True
def boats_are_separated(boat1, boat2):
for x1, y1 in boat1.coords:
for x2, y2 in boat2.coords:
if abs(x1 - x2) <= 1 and abs(y1 - y2) <= 1:
return False
return True
def count_boat_occupancy(solutions):
occupancy_count = [[0 for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
if solutions is None:
return occupancy_count # Return empty or default occupancy count
for sol in solutions:
if hasattr(sol, 'boats') and sol:
for boat in sol.boats:
for coord in boat.coords:
x, y = coord
occupancy_count[x][y] += 1
return occupancy_count
# ----------------------------------------- Display -----------------------------------------
def print_board(board_status):
# Print column headers
print(" ", end=" ")
for col in range(BOARD_SIZE):
print(chr(ord('A') + col), end=" ")
print()
# Print each row
for row in range(BOARD_SIZE):
# Print row number
print(f"{row + 1}", end=" ")
# Print each cell in the row
for col in range(BOARD_SIZE):
print(board_status[row][col], end=" ")
print()
# ----------------------------------------- Main -----------------------------------------
def build_theory():
E._custom_constraints.clear()
valid_games = []
# First, find all valid games (with separated boats)
all_valid = 0
for game in all_games:
if is_valid_game(game):
all_valid += 1
valid_games.append(game)
print(all_valid)
for x, y, is_hit in guesses:
invalid_games = 0
for game in valid_games:
boat_at_guess = any(coord == (x, y) for boat in game.boats for coord in boat.coords)
if (is_hit and not boat_at_guess) or (not is_hit and boat_at_guess):
invalid_games += 1
valid_games.remove(game)
# E.add_constraint(~Game(game.boats))
print(f"Guess at ({x},{y}), Hit: {is_hit}, Invalidated Games: {invalid_games}")
for game in valid_games:
E.add_constraint(Game(game.boats))
return E
if __name__ == "__main__":
board_status = generate_game()
print_board(board_status)
player_board = [[0 for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
game_over = False
while not game_over:
# Recompile the theory with the updated constraints
T = build_theory()
T_new = T.compile()
new_solution = T_new.solve()
# pp.pprint(new_solution)
# Count boat occupancy based on the solutions
occupancy_count = count_boat_occupancy(new_solution)
for row in occupancy_count:
print(row)
print_board(player_board) # Print the current board status
guess_coord = get_user_guess(player_board) # Get user guessA
x, y = guess_coord
# determine if the guess is a hit or miss
result = process_guess(board_status, player_board, x, y)
guesses.append((x, y, result))
print(guesses)