2 Komitmen 4650986605 ... 61476851ed

Pembuat SHA1 Pesan Tanggal
  Bence DOMONKOS 61476851ed nimmt: partial rounds and json support part 2 1 tahun lalu
  Bence DOMONKOS e0eebf5391 game: partial rounds and json support 1 tahun lalu
4 mengubah file dengan 116 tambahan dan 48 penghapusan
  1. 2 2
      board.py
  2. 105 41
      game.py
  3. 1 1
      main.py
  4. 8 4
      player.py

+ 2 - 2
board.py

@@ -13,9 +13,9 @@ class Board:
 		self.ncards = deck_size
 		self.deck = list(range(1, deck_size + 1))
 		random.shuffle(self.deck)
-		print(self.deck)
+		#print(self.deck)
 		self.rows = [[c] for c in self.draw(nrows)]
-		print(self.rows)
+		#print(self.rows)
 		self.max_row_len = max_row_len
 
 	@classmethod

+ 105 - 41
game.py

@@ -1,67 +1,121 @@
 #!usr/bin/python
+import enum
 import json
 
 import board
 import server_socket
 from player import Player
 
+class CONTROL_MSG_TYPE(enum.Enum):
+	ERROR = -1
+	UNKNOWN = 0
+	START = 1
+
 class Game:
-	def __init__(self, serversocket):
+	def __init__(self, serversocket, score_limit = 66, nturn = 10):
 		self.players = {}
 		self.board = None
 		self.ssock = serversocket
+		self.turn = 1
+		self.score_limit = score_limit
+		self.cards_dealt = nturn
+
+	def get_controll_message_action(self, msg): #TODO: classmethod
+		try:
+			print('json:', msg)
+			res = json.loads(msg)
+			action = res.get('action')
+			print('action:', action)
+			if action == 'start':
+				return CONTROL_MSG_TYPE.START
+			return CONTROL_MSG_TYPE.UNKNOWN
+		except(json.decoder.JSONDecodeError):
+			print('json decode error...')
+			return CONTROL_MSG_TYPE.ERROR
 
 	def run(self):
 		print('game: running')
+		print('waiting to start...')
+		for client, msg, op in self.ssock.listen():
+			if op == server_socket.SOCKET_OP.DATA_IN:
+				action = self.get_controll_message_action(msg)
+				if action == CONTROL_MSG_TYPE.START:
+					break
+			else:
+				self.process_connections(client, msg, op)
+		self.new_game()
+		self.broadcast_turn()
 		for client, msg, op in self.ssock.listen():
-			print(client, msg, op)
-			self.process_data(client, msg, op)
+			if op != server_socket.SOCKET_OP.DATA_IN:
+				print('Unexpected socket messages!')
+				continue
+			self.process_message(client, msg)
+			if self.turn == self.cards_dealt:
+				print('This round ended!')
+				self.print_scoreboard()
+				break
+		#print('Game ended!')
+		#print('Final scores:')
+		#self.print_scoreboard()
+
+	def print_scoreboard(self):
+		for i, p in enumerate(sorted(self.players.values(), key=lambda p: p.score)):
+			print(i + 1, ':', p.name, '-', p.score)
 
-	def process_data(self, client, data_in_bytes, playerOperation):
+	def process_connections(self, client, data_in_bytes, playerOperation):
 		if playerOperation == server_socket.SOCKET_OP.NEW_CONNECTION:
-			self.players[client] = Player(client)
-			return
+			self.handle_new_connection(client)
 		elif playerOperation == server_socket.SOCKET_OP.HANGUP:
-			del self.players[client]
-			return
-		elif playerOperation == server_socket.SOCKET_OP.DATA_IN:
-			pass
+			self.handle_disconnect(client)
+		#elif playerOperation == server_socket.SOCKET_OP.DATA_IN:
+		#	return
 		else:
-			print('process_data: unknown operation:', playerOperation)
+			print('process_connections: unknown operation:', playerOperation)
 			exit(1)
 
-		data = str(data_in_bytes, 'utf-8').strip()
+	def handle_new_connection(self, client):
+		self.players[client] = Player(client)
+
+	def handle_disconnect(self, client):
+		del self.players[client]
+
+	def process_message(self, client, bmsg):
+		msg = str(bmsg, 'utf-8').strip()
 
 		#TODO: refactor
-		is_start = data[0] == 's'
-		is_give_card = data[0] == 'g'
-		is_choice = data[0] in "cr"
+		is_start = msg[0] == 's'
+		is_give_card = msg[0] == 'g'
 
 		if is_start:
 			self.start()
+			self.broadcast_game_format()
+			self.broadcast_turn()
 		elif is_give_card:
 			try:
-				current_cards = int(data[1:])
+				current_cards = int(msg[1:])
 			except:
 				return
 			self.giveCard(client, current_cards)
-		elif is_choice:
-			self.choice()
 		else:
-			print('unknown:', data)
+			print('unknown:', msg)
 
-	def start(self):
-		self.board = board.Board(4, 104, 5) #TODO: def parameters
+	def is_valid_msg(self, msg):
+		try:
+			res = json.loads(msg)
+			print('type', res.get('type'))
+			return True
+		except(json.decoder.JSONDecodeError):
+			print('json decode error...')
+			return False
 
+	def new_game(self):
+		self.board = board.Board()
 		for player in self.players.values():
-			player.set_hand(self.board.draw(10))
-
-		data = json.dumps(self.board.rows)
-		self.ssock.broadcast(list(self.players.keys()), data)
+			player.set_hand(self.board.draw(self.cards_dealt))
 
 	def giveCard(self, client, card):
 		if not self.players[client].set_card(card):
-			send_json = '{"Not in your hand":' + str(card) + '}' # TODO
+			send_json = json.dumps({'type' : 'error', 'Not in your hand' : str(card)})
 			self.ssock.broadcast([client], send_json) # TODO: broadcast?
 			return
 		players_ready = [p for p in self.players.values() if p.card]
@@ -69,35 +123,45 @@ class Game:
 			return
 		self.place_all_cards()
 
-	def player2card(self, card):
-		for p in self.players:
-			if card in p.hand:
-				return p
-		return None
-
 	def place_all_cards(self):
 		players_ready = sorted(self.players.values(), key=lambda p: p.card)
 		for p in players_ready:
 			ret, arg = self.board.place_card(p.card)
 			if ret == board.CANDIDATE.TOO_LOW:
-				selection = p.select_row(len(self.board.rows))
+				selection = p.select_row(self.board.rows)
 				penalty = self.board.reset_row(selection, p.card)
 				p.score = p.score + penalty
-				print(p.name, p.card, 'low: ', p.score)
+				#print(p.name, p.card, 'low: ', p.score)
 			elif ret == board.CANDIDATE.PENALTY:
 				p.score = p.score + arg
-				print(p.name, p.card, 'penalty:', p.score)
+				#print(p.name, p.card, 'penalty:', p.score)
 			elif ret == board.CANDIDATE.PUT:
-				print(p.name, p.card, 'ok')
+				#print(p.name, p.card, 'ok')
 				pass
 			else:
 				print('place_cards: unknown operation:', ret)
 				exit(1)
-		print(self.board.rows)
-		self.ssock.broadcast(list(self.players.keys()), "megvagyunk\n")
+		#print(self.board.rows)
 		for p in players_ready:
-			p.hand.remove(p.card)
+			p.hand.remove(p.card) # TODO: move to player.py
 			p.card = None
+		self.turn = self.turn + 1
+		self.broadcast_turn()
+
+	def broadcast_game_format(self):
+		msg = {
+			'type' : 'info',
+			'score_limit' : self.score_limit,
+			'nturns' : self.cards_dealt,
+			'nrows' : len(self.board.rows),
+			'row_len' : self.board.max_row_len,
+			'nplayers' : len(self.players) }
+		self.ssock.broadcast(self.players.keys(), json.dumps(msg))
 
-	def choice(self):
-		pass
+	def broadcast_turn(self):
+		board = { 'type' : 'query', 'action' : 'give_card', 'board' : self.board.rows }
+		for p in self.players.values():
+			msg = board.copy()
+			msg['hand'] = p.hand
+			msg['turn'] = self.turn
+			self.ssock.broadcast([p.socket], json.dumps(msg))

+ 1 - 1
main.py

@@ -9,7 +9,7 @@ PORT = 6546
 if __name__ == '__main__':
 	try:
 		serversock = Server_Socket(HOST, PORT)
-		game = game.Game(serversock)
+		game = game.Game(serversock, 66, 5)
 		game.run()
 
 	except KeyboardInterrupt:

+ 8 - 4
player.py

@@ -10,7 +10,7 @@ class Player:
 
 	def set_hand(self, hand):
 		self.hand = hand
-		self.socket.send(bytes(json.dumps(hand), 'utf-8'))
+		#self.socket.send(bytes(json.dumps(hand), 'utf-8'))
 
 	def set_card(self, card):
 		if card in self.hand:
@@ -20,7 +20,11 @@ class Player:
 
 	def query_user(self, msg, options):
 		num = None
-		bmsg = bytes(msg + str(options), 'utf-8')
+		jmsg = {
+			'type' : 'query',
+			'action' : 'select_row',
+			'rows' : msg}
+		bmsg = bytes(json.dumps(jmsg), 'utf-8')
 		while True:
 			self.socket.send(bmsg)
 			num = int(self.socket.recv(1024).strip())
@@ -28,8 +32,8 @@ class Player:
 				break
 		return num
 
-	def select_row(self, nrows):
-		return self.query_user('Pick up a row!', list(range(nrows)))
+	def select_row(self, rows):
+		return self.query_user('\n'.join(map(str, enumerate(rows))), list(range(len(rows))))
 
 	def __del__(self):
 		self.socket.close()