3 Commits 61476851ed ... 9f9224c5fe

Author SHA1 Message Date
  Bence DOMONKOS 9f9224c5fe game: single round game with lobby works 1 year ago
  Bence DOMONKOS b507edcf51 quick refactor 1 year ago
  akoshofmeister 5454dff64f Refactor game flow 1 year ago
4 changed files with 91 additions and 64 deletions
  1. 88 61
      game.py
  2. 1 1
      main.py
  3. 1 1
      player.py
  4. 1 1
      server_socket.py

+ 88 - 61
game.py

@@ -1,122 +1,150 @@
-#!usr/bin/python
 import enum
 import json
+import random
+import string
 
 import board
 import server_socket
 from player import Player
 
-class CONTROL_MSG_TYPE(enum.Enum):
+
+class MSG_TYPE(enum.Enum):
 	ERROR = -1
 	UNKNOWN = 0
 	START = 1
+	QUIT = 2
+	GIVE_CARD = 3
+
+class GAME_STATE(enum.Enum):
+	LOBBY = 0
+	QUIT = 1
+	PLAY = 2
 
 class Game:
-	def __init__(self, serversocket, score_limit = 66, nturn = 10):
+	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
+		self.cards_dealt = nturn  # CARDS In Hand
+		self.game_state = GAME_STATE.LOBBY
 
-	def get_controll_message_action(self, msg): #TODO: classmethod
+	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
+				return MSG_TYPE.START
+			elif action == 'quit':
+				return MSG_TYPE.QUIT
+			return MSG_TYPE.UNKNOWN
 		except(json.decoder.JSONDecodeError):
-			print('json decode error...')
-			return CONTROL_MSG_TYPE.ERROR
+			print('json decode error...', msg)
+			return MSG_TYPE.ERROR
 
 	def run(self):
 		print('game: running')
 		print('waiting to start...')
+
+		while self.game_state != GAME_STATE.QUIT:
+			if self.game_state == GAME_STATE.LOBBY:
+				self.lobby()
+			else:
+				self.game()
+
+	def lobby(self):
 		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:
+				if action == MSG_TYPE.START:
+					self.game_state = GAME_STATE.PLAY
+					break
+				elif action == MSG_TYPE.QUIT:
+					self.game_state = GAME_STATE.QUIT
 					break
 			else:
 				self.process_connections(client, msg, op)
+
+	def game(self):
 		self.new_game()
-		self.broadcast_turn()
+		while self.turn <= self.cards_dealt:
+			#print('beginning of turn:', self.turn)
+			self.broadcast_turn()
+			self.play_turn()
+
+		print('game ended - returning to lobby')
+		self.game_state = GAME_STATE.LOBBY
+		self.print_scoreboard()
+
+	def play_turn(self):
 		for client, msg, op in self.ssock.listen():
 			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()
+			break #TODO
 
 	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)
+		scoreboard = [ { 'name': p.name, 'score': p.score, 'place': i + 1 } for i, p in enumerate(sorted(self.players.values(), key=lambda p: p.name))]
+		scoreboard['type'] = 'info'
+		self.ssock.broadcast(self.players.keys(), json.dumps(scoreboard))
 
 	def process_connections(self, client, data_in_bytes, playerOperation):
 		if playerOperation == server_socket.SOCKET_OP.NEW_CONNECTION:
 			self.handle_new_connection(client)
 		elif playerOperation == server_socket.SOCKET_OP.HANGUP:
 			self.handle_disconnect(client)
-		#elif playerOperation == server_socket.SOCKET_OP.DATA_IN:
+		# elif playerOperation == server_socket.SOCKET_OP.DATA_IN:
 		#	return
 		else:
 			print('process_connections: unknown operation:', playerOperation)
 			exit(1)
 
 	def handle_new_connection(self, client):
-		self.players[client] = Player(client)
+		self.players[client] = Player(client, ''.join(random.sample(string.ascii_uppercase, 10)))
 
 	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 = msg[0] == 's'
-		is_give_card = msg[0] == 'g'
+		msg_type, payload = self.parse_message(bmsg)
 
-		if is_start:
-			self.start()
-			self.broadcast_game_format()
-			self.broadcast_turn()
-		elif is_give_card:
+		if msg_type == MSG_TYPE.GIVE_CARD:
 			try:
-				current_cards = int(msg[1:])
+				current_card = int(payload)
 			except:
+				print('error parsing GIVE_CARD', payload)
 				return
-			self.giveCard(client, current_cards)
+			self.get_card(client, current_card)
 		else:
-			print('unknown:', msg)
+			print('unknown command')
 
-	def is_valid_msg(self, msg):
+	def parse_message(self, bmsg):
 		try:
-			res = json.loads(msg)
-			print('type', res.get('type'))
-			return True
-		except(json.decoder.JSONDecodeError):
-			print('json decode error...')
-			return False
+			msg = json.loads(str(bmsg, 'utf-8').strip())
+
+			if msg.get('action') == 'give_card':
+				return MSG_TYPE.GIVE_CARD, msg.get('card')
+
+			return MSG_TYPE.ERROR, None
+		except json.decoder.JSONDecodeError:
+			print('json decode error...', bmsg)
+			return MSG_TYPE.ERROR, None
 
 	def new_game(self):
 		self.board = board.Board()
+		self.turn = 1
+		self.broadcast_game_format()
 		for player in self.players.values():
 			player.set_hand(self.board.draw(self.cards_dealt))
 
-	def giveCard(self, client, card):
+	def get_card(self, client, card):
 		if not self.players[client].set_card(card):
-			send_json = json.dumps({'type' : 'error', 'Not in your hand' : str(card)})
-			self.ssock.broadcast([client], send_json) # TODO: broadcast?
+			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]
 		if len(players_ready) != len(self.players):
@@ -126,42 +154,41 @@ class Game:
 	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)
+			ret, penalty_for_5_card = self.board.place_card(p.card)
 			if ret == board.CANDIDATE.TOO_LOW:
 				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)
+				p.score += penalty_for_5_card
+			# 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)
+		# print(self.board.rows)
 		for p in players_ready:
-			p.hand.remove(p.card) # TODO: move to player.py
+			p.hand.remove(p.card)  # TODO: move to player.py
 			p.card = None
+		print('turn ending...')
 		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) }
+			'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 broadcast_turn(self):
-		board = { 'type' : 'query', 'action' : 'give_card', 'board' : self.board.rows }
+		board = {'type': 'query', 'action': 'give_card', 'board': self.board.rows, 'turn': self.turn}
 		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, 66, 5)
+		game = game.Game(serversock, 66, 2)
 		game.run()
 
 	except KeyboardInterrupt:

+ 1 - 1
player.py

@@ -33,7 +33,7 @@ class Player:
 		return num
 
 	def select_row(self, rows):
-		return self.query_user('\n'.join(map(str, enumerate(rows))), list(range(len(rows))))
+		return self.query_user('  '.join(map(str, enumerate(rows))), list(range(len(rows))))
 
 	def __del__(self):
 		self.socket.close()

+ 1 - 1
server_socket.py

@@ -41,7 +41,7 @@ class Server_Socket:
 						op = SOCKET_OP.HANGUP
 					else:
 						op = SOCKET_OP.DATA_IN
-				yield (client, data, op)
+				yield client, data, op
 
 	def addConnection(self, serversock):
 		print('serversock in')