from flask import Flask, render_template, request, session, make_response import random import socket import time import roborally import numpy as np app = Flask(__name__) app.secret_key = b'RoboRallyRolling' probabilities = [0.21428571428571427, 0.14285714285714285, 0.07142857142857142, 0.07142857142857142, 0.21428571428571427, 0.21428571428571427, 0.07142857142857142] deck = roborally.CardDeck() class Game: def __init__(self): self.action_stack = {} self.processing_done = False # indicates whether all commands in the current round have been processed self.board = roborally.Board() self.comm_socket = socket.socket() # socket for communicating with the program controlling the robots try: self.comm_socket.connect(('192.168.1.222', 1337)) pass print("connected!") except socket.error: print("could not connect to robot control socket!") self.comm_socket = None def ready(self): # have all players chosen an action? return len(self.action_stack.keys()) == Player.player_counter def register_actions(self, player_id, actions): # store the selected actions for the given player if not player_id in self.action_stack.keys(): # make sure that the actions have not been registered before print("registered actions: ", [str(a) for a in actions]) self.action_stack[player_id] = actions deck.return_cards(actions) # put cards back into the deck self.processing_done = False return True else: print("actions already chosen!") return False def process_actions(self): l = [] for p in self.action_stack.keys(): l.append(zip([p] * len(self.action_stack[p]), self.action_stack[p])) chosen_cards = list(zip(*l)) # process the chosen commands and generate a list of robot commands to send to the controller program cmd_list = self.board.apply_actions(chosen_cards) if self.comm_socket is not None: # send movements to the controller program for c in cmd_list: if not 'nop' in c: self.comm_socket.sendall((c + "\n").encode()) data = self.comm_socket.recv(32) if data != b'OK\n': print("an error occurred while processing the commands") self.processing_done = True self.action_stack = {} return # for c in current_actions: # if c[0] == 0: # print("{}, {}\n".format(c[1].action, 11)) # self.comm_socket.sendall("{}, {}\n".format(c[1].action, 11).encode()) # elif c[0] == 1: # print("{}, {}\n".format(c[1].action, 14)) # self.comm_socket.sendall("{}, {}\n".format(c[1].action, 14).encode()) # data = self.comm_socket.recv(32) # time.sleep(0.5) # clear the action stack for the next round self.action_stack = {} self.processing_done = True players = {} game = Game() class Player: MAX_PLAYERS = 3 player_counter = 0 def __init__(self): if Player.player_counter < Player.MAX_PLAYERS: self.id = Player.player_counter Player.player_counter += 1 self.max_cards = 9 self.player_hand = deck.draw_cards(self.max_cards) print("current hand: ", [str(c) for c in self.player_hand]) self.action_count = 5 self.action_chosen = False self.robot = None else: print("max players reached!") def initialize_robot(self, x, y, orientation, marker_id): self.robot = game.board.create_robot(x, y, orientation, self.id, marker_id) if game.comm_socket is not None: # TODO: general form # (1,1) <-> (-6, 3) # (1,2) <-> (-6, 2) -> y_ctrl = y_game - 4 # (2,1) <-> (-5, 3) -> x_ctrl = x_game - 7 x_trans = x - 7 y_trans = 4 - y angle_trans = {'>': 0.0, 'v': -np.pi/2, '<': -np.pi, '^': np.pi/2} cmd = "set position, {}, ({}, {}, {})\n".format(marker_id, x_trans, y_trans, angle_trans[orientation]) game.comm_socket.sendall(cmd.encode()) data = game.comm_socket.recv(32) print("data from set position: ", data) cmd2 = "turn left, {}\n".format(marker_id) game.comm_socket.sendall(cmd2.encode()) data = game.comm_socket.recv(32) print("data from turn left: ", data) cmd3 = "turn right, {}\n".format(marker_id) game.comm_socket.sendall(cmd3.encode()) data = game.comm_socket.recv(32) print("data from turn right: ", data) def draw_new_cards(self): self.player_hand += deck.draw_cards(self.max_cards - len(self.player_hand)) @app.route('/send_cmds', methods=['POST', 'GET']) def send_cmds(): if request.method == 'POST': # POST is used for submitting commands player_id = session['player_id'] p = players[player_id] if p.robot is None: x = int(request.form.get('x')) y = int(request.form.get('y')) orient = request.form.get('orient') marker_id = int(request.form.get('marker_id')) p.initialize_robot(x, y, orient, marker_id) number_of_cards = p.action_count - p.robot.damage if game.register_actions(p.id, p.player_hand[0:number_of_cards]): p.player_hand = p.player_hand[number_of_cards:] # discard used cards p.draw_new_cards() if game.ready(): game.process_actions() return 'OK' else: return 'please wait' elif request.method == 'GET': # GET is used when we have to wait for other players to finish while not game.processing_done: # wait for other players to choose commands and processing to finish pass return 'OK' @app.route('/', methods=['GET', 'POST']) def hello_world(): if not 'player_id' in session: if Player.player_counter < Player.MAX_PLAYERS: # new player p = Player() session['player_id'] = p.id players[p.id] = p player_id = session['player_id'] else: return "Sorry, maximum number of players reached!" else: player_id = session['player_id'] if Player.player_counter < player_id + 1: session.clear() response = make_response('Please reload the page!') #response.set_cookie('player_id', '', expires=0) return response player_hand = players[player_id].player_hand if request.method == 'GET': robot = players[player_id].robot if robot is not None: robot_info = (robot.x, robot.y, robot.orientation, robot.marker_id, robot.damage, robot.collected_flags) else: robot_info = None return render_template('drag_example.html', cmds=player_hand, player_id=player_id, robot_info=robot_info) elif request.method == 'POST': #print(request.form) if request.form.get('drag') and request.form.get('drop'): # swap cards in the current hand i1 = int(request.form.get('drag')) # number of first card i2 = int(request.form.get('drop')) # number of second card card1 = deck.deck[i1] # get card by number card2 = deck.deck[i2] print("swapping {} and {}".format(card1, card2)) j1 = player_hand.index(card1) # get index of card in the hand j2 = player_hand.index(card2) player_hand[j1], player_hand[j2] = player_hand[j2], player_hand[j1] # swap the cards in the list #print("current hand: ", [str(c) for c in player_hand[player_id]]) return 'OK' else: return render_template('drag_example.html', cmds=player_hand, player_id=player_id) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)