-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathHuman.py
122 lines (108 loc) · 4.99 KB
/
Human.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
import numpy as np
from Player import Player, in_bounds
import socket
FORMAT = 'utf-8'
BOARD_SIZE = 10
class Human(Player):
"""options for battleships size and quantity"""
set1 = {5: 1, 4: 1, 3: 2, 2: 1}
set2 = {4: 1, 3: 2, 2: 3, 1: 4}
def __init__(self, conn: socket.socket = None):
"""
:param conn: socket to communicate with the second player
"""
super().__init__()
self.conn = conn
if conn:
self.input = self.__socket_input
self.output = self.__socket_output
else:
self.input = self.__normal_input
self.output = self.__normal_output
def __normal_output(self, msg):
print(msg)
def __normal_input(self, msg):
return input(msg)
def __socket_output(self, msg):
"""0 at start of message means only to read"""
self.conn.send(bytes('0' + msg, FORMAT))
def __socket_input(self, msg):
"""1 at start of message means to write as well"""
self.conn.send(bytes('1' + msg, FORMAT))
return self.conn.recv(128).decode(FORMAT)
def __legal(self, x, y, direction, battleship_size):
"""
checks if input is valid and the location is available for placing battleship
"""
if direction not in ['horizontal', 'vertical'] or not in_bounds((x, y)) or not 1 <= battleship_size <= 5:
return False
horizontal_offset = 1 if direction == 'horizontal' else 0
vertical_offset = 1 if direction == 'vertical' else 0
for i in range(battleship_size):
if not (x + i * vertical_offset, y + i * horizontal_offset) in self.available_places:
return False
return True
def place_battleships(self):
while True:
location = self.input("\nenter battleship point, direction and size: \n")
if location.lower() == 'done':
if self.battleships_set != Human.set1 and self.battleships_set != Human.set2:
self.battleships_set = {}
self.player_board = np.full((BOARD_SIZE, BOARD_SIZE), ' ')
self.available_places = [(i, j) for i in range(BOARD_SIZE) for j in range(BOARD_SIZE)]
self.output("incorrect board placement, please try place all battleships again\n")
continue
break
try:
start_point, direction, battleship_size = location.split()
battleship_size = int(battleship_size)
start_x, start_y = start_point.split(',')
start_x, start_y = int(start_x), int(start_y)
except:
self.output('please enter valid parameters')
continue
if not self.__legal(start_x, start_y, direction, battleship_size):
self.output("incorrect placement, please try again")
continue
self._place_battleship(direction, start_x, start_y, battleship_size)
self.battleships_set[battleship_size] = self.battleships_set.get(battleship_size, 0) + 1
self.output('\n' + str(self.player_board))
if self.battleships_set == Human.set1 or self.battleships_set == Human.set2:
return
def print_boards(self):
"""print the player board and known opponent board for the player"""
boards = 'player board:' + '\t' * 10 + 'opponent board:' + '\n'
for r1, r2 in zip(self.player_board, self.opponent_board):
boards += str(r1) + 3*'\t' + str(r2) + '\n'
self.output(boards)
def turn(self, opponent: Player):
while True:
self.print_boards()
try:
location = self.input("\nEnter place to shoot: ").split(',')
location = (int(location[0]), int(location[1]))
except:
self.output('please enter a valid location\n')
continue
if location not in self.opponent_available_places:
self.output('location already chosen\n')
continue
self.opponent_available_places.remove(location)
result = opponent.hit(location)
if result == 'sank':
self.output('ship sank!')
self.opponent_board[location] = 'X'
opponent.output('Opponent hit your battleship!\n\n' + str(opponent.player_board)) \
if isinstance(opponent, Human) else None
continue
elif result == 'hit':
self.opponent_board[location] = 'X'
self.output('hit!\n')
opponent.output('Opponent hit your battleship!\n\n' + str(opponent.player_board)) \
if isinstance(opponent, Human) else None
continue
elif result == 'miss':
self.opponent_board[location] = 'M'
self.output('missed!\n')
opponent.output('Opponent missed!\n') if isinstance(opponent, Human) else None
return result