RoboRallyGUI/app.py

231 lines
8.1 KiB
Python

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)