예제 #1
0
 def accept_player_connections(self):
     self.server = SocketServer(HOST, PORT, 2)
     self.server.establish_client_connections()
     self.player_attributes = [
         json.loads(info) for info in self.server.receive_from_all()
     ]
     self.player_idx = 0 if self.player_attributes[0]['is_player'] else 1
     self.matchmaker_idx = 1 if self.player_attributes[0]['is_player'] else 0
     self.play_game()
예제 #2
0
 def accept_player_connections(self, front_end=None, web_server=None):
     if front_end:
         print('~~ WE GOT A FRONT END ~~')
     self.server = SocketServer(HOST, PORT, 2)
     self.server.establish_client_connections()
     self.player_attributes = [
         json.loads(info) for info in self.server.receive_from_all()
     ]
     self.trench_idx = 0 if self.player_attributes[0][
         'is_trench_manager'] else 1
     self.submarine_idx = 1 if self.player_attributes[0][
         'is_trench_manager'] else 0
     self.play_game()
예제 #3
0
class GameServer(object):
    def __init__(self, d=36, y=6, r=6, m=250, L=4, p=2, gui=False):
        self.d = d
        self.y = y
        self.r = r
        self.m = m
        self.L = L
        self.p = p
        self.trench_cost = 0
        self.trench_condition_achieved = True
        self.red_alert = [i % 100 for i in range(d, d + 6)]
        self.submarine_time_left = self.trench_time_left = 120
        self.submarine_location = randint(0, 99)
        self.is_submarine_in_red = self.submarine_location in self.red_alert
        self.web_server = None
        print('Waiting on port %s for players...' % PORT)
        if gui:
            self.web_server = WebsocketServer(WEB_PORT, host=WEB_HOST)
            self.web_server.new_client = self.accept_player_connections
            self.web_server.run_forever()
        else:
            self.accept_player_connections()

    def accept_player_connections(self, front_end=None, web_server=None):
        if front_end:
            print('~~ WE GOT A FRONT END ~~')
        self.server = SocketServer(HOST, PORT, 2)
        self.server.establish_client_connections()
        self.player_attributes = [
            json.loads(info) for info in self.server.receive_from_all()
        ]
        self.trench_idx = 0 if self.player_attributes[0][
            'is_trench_manager'] else 1
        self.submarine_idx = 1 if self.player_attributes[0][
            'is_trench_manager'] else 0
        self.play_game()

    def timed_request(self, request_data, client_idx):
        self.server.send_to(json.dumps(request_data), client_idx)
        start = time()
        move = json.loads(self.server.receive_from(client_idx))
        stop = time()
        return move, (stop - start)

    def decrement_time(self, submarine_time_spent, trench_time_spent):
        self.submarine_time_left -= submarine_time_spent
        self.trench_time_left -= trench_time_spent

    def check_time_left(self):
        if self.submarine_time_left < 0:
            raise Exception('Submarine Captain ran out of time')

        if self.trench_time_left < 0:
            raise Exception('Trench Manager ran out of time')

    def complete_submarine_move(self, submarine_move):
        if type(submarine_move
                ) != int or submarine_move > 1 or submarine_move < -1:
            raise ValueError('Submarine Captain made an illegal move')

        self.submarine_location = (self.submarine_location +
                                   submarine_move) % 100
        self.is_submarine_in_red = self.submarine_location in self.red_alert

    def trench_region_check(self, region):
        if region not in ('red', 'yellow'):
            raise ValueError('Trench Manager chose an illegal region')

        if self.is_submarine_in_red and region != 'red':
            self.trench_condition_achieved = False

        self.trench_cost += self.r if region == 'red' else self.y

    def deploy_probes(self, probes):
        probe_results = []
        times_submarine_probed = 0
        for probe in probes:
            if type(probe) != int or probe < 0 or probe > 99:
                raise ValueError(
                    'Trench Manager placed a probe at an illegal position')

            range_start = (probe - self.L) if (probe - self.L) > 0 else (
                100 + (probe - self.L))
            probe_range = [
                i % 100
                for i in range(range_start, range_start + (self.L * 2) + 1)
            ]

            probe_results.append(self.submarine_location in probe_range)
            if probe_results[-1]:
                times_submarine_probed += 1
            self.trench_cost += self.p
        return probe_results, times_submarine_probed

    def play_game(self):
        submarine_move, submarine_time_spent = self.timed_request(
            {
                'm': self.m,
                'L': self.L,
                'pos': self.submarine_location
            }, self.submarine_idx)

        trench_probe_move, trench_time_spent = self.timed_request(
            {
                'd': self.d,
                'y': self.y,
                'r': self.r,
                'm': self.m,
                'L': self.L,
                'p': self.p
            }, self.trench_idx)

        self.decrement_time(submarine_time_spent, trench_time_spent)

        m = self.m
        while m > 0:
            self.check_time_left()

            self.complete_submarine_move(submarine_move['move'])

            probe_results, times_submarine_probed = self.deploy_probes(
                trench_probe_move['probes'])

            trench_move, trench_time_spent = self.timed_request(
                {'probe_results': probe_results}, self.trench_idx)

            self.trench_region_check(trench_move['region'])

            if self.web_server:
                self.web_server.send_message_to_all(
                    json.dumps({
                        'red_region':
                        self.d,
                        'position':
                        self.submarine_location,
                        'is_safety_condition_achieved':
                        self.trench_condition_achieved,
                        'submarine_region':
                        'red' if self.is_submarine_in_red else 'yellow',
                        'trench_alert':
                        trench_move['region'],
                        'probes':
                        trench_probe_move['probes']
                    }))

            print("**********************************************")
            print(
                f"Submarine moved by {submarine_move['move']} (current position: {self.submarine_location})"
            )
            print(
                f"Submarine is {'not' if not self.is_submarine_in_red else ''} in red region"
            )
            print(f"Probes were placed at {trench_probe_move['probes']}")
            print(f"The results were: {probe_results}")
            print(f"Trench manager sent {trench_move['region']} alert")
            print(
                f"Safety condition {'not' if not self.trench_condition_achieved else ''} achieved"
            )
            print("**********************************************")

            if m > 1:
                submarine_move, submarine_time_spent = self.timed_request(
                    {'times_probed': times_submarine_probed},
                    self.submarine_idx)

                trench_probe_move, trench_time_spent = self.timed_request(
                    {}, self.trench_idx)

                self.decrement_time(submarine_time_spent, trench_time_spent)

            m -= 1

        if not self.trench_condition_achieved:
            self.trench_cost = (self.m * self.r) + (self.m * 5 * self.p)

        self.server.send_to_all(
            json.dumps({
                'game_over': True,
                'trench_cost': self.trench_cost,
                'was_condition_achieved': self.trench_condition_achieved
            }))
예제 #4
0
 def accept_player_connections(self):
     self.server = SocketServer(HOST, PORT, 1)
     self.server.establish_client_connections()
     self.player_attributes = json.loads(self.server.receive_from(0, size=2048))
     self.player_name = self.player_attributes['name']
예제 #5
0
class GameServer(object):
    def __init__(self, input_file=None):
        if input_file is None:
            print('No input given')
            exit(1)

        print('Waiting on port %s for player...' % PORT)
        self.accept_player_connections()

        print('Preparing input data')
        parsed_data = self.input_parsing(input_file)
        self.patients = parsed_data[0]
        self.hospitals = parsed_data[1]
        self.ambulances = parsed_data[2]
        self.total_patients = parsed_data[3]
        self.total_hospitals = parsed_data[4]
        self.total_ambulances = parsed_data[5]

        print('Starting Game with player: ' + str(self.player_name))
        self.play_game()

    def input_parsing(self, input_file):
        ### Create dictionaries of patient, hospital, and ambulances

        patients = {}
        hospitals = {}
        ambulances = {}

        patient_id = 0
        hospital_id = 0
        ambulance_id = 0

        # Parse input txt file
        mode = None  # 0 = patient description, 1 = hostpital ambulance number
        f = open(input_file, 'r')
        for line in f:
            if line == '\n':
                continue
            line = line.strip('\n')
            if line[0] == 'p':
                mode = 0
                continue
            if line[0] == 'h':
                mode = 1
                continue

            # Patient information
            if mode == 0:
                mytuple = tuple(map(int, line.split(',')))
                patients[patient_id] = {'xloc': mytuple[0], 'yloc': mytuple[1], 'rescuetime': mytuple[2]}
                patient_id += 1
            elif mode == 1:
                hospitals[hospital_id] = {'xloc': None, 'yloc': None}
                num_ambulances = int(line)
                ambulances_at_hospital = []
                for amb in range(0, num_ambulances):
                    ambulances[ambulance_id] = {'starting_hospital': hospital_id}
                    ambulances_at_hospital += [ambulance_id]
                    ambulance_id += 1
                hospitals[hospital_id]['ambulances_at_start'] = ambulances_at_hospital
                hospital_id += 1
            else:
                print('Error parsing input file')
                exit(1)

        return (patients, hospitals, ambulances, patient_id, hospital_id, ambulance_id)

    def accept_player_connections(self):
        self.server = SocketServer(HOST, PORT, 1)
        self.server.establish_client_connections()
        self.player_attributes = json.loads(self.server.receive_from(0, size=2048))
        self.player_name = self.player_attributes['name']

    def route_time(self, c_loc, n_loc):
        return abs(n_loc[0] - c_loc[0]) + abs(n_loc[1] - c_loc[1])

    def game_over(self, message, patients_saved, finished=False):
        self.server.send_to_all(
            json.dumps({
                'game_completed': finished,
                'message': message,
                'patients_saved': patients_saved,
                'number_saved': len(patients_saved)
            }))
        exit(1)

    def play_game(self):
        input_data = {'patients': self.patients, 'hospitals': self.hospitals, 'ambulances': self.ambulances}
        print(input_data)
        print('---------')
        buff_size_needed = sys.getsizeof(json.dumps(input_data))
        buff_size_needed = 1<<(buff_size_needed-1).bit_length()
        buff_size_message = {'buffer_size': buff_size_needed}
        self.server.send_to(json.dumps(buff_size_message), 0)
        time.sleep(2)
        self.server.send_to(json.dumps(input_data), 0)
        start = tm()
        buff_size_message = json.loads(self.server.receive_from(0, size=2048))
        buff_size_needed = int(buff_size_message['buffer_size'])
        print(buff_size_needed)
        moves = json.loads(self.server.receive_from(0, size=buff_size_needed))
        stop = tm()

        if (stop-start) > 122:
            m = 'Player ' + str(self.player_name) + ' ran for more than 2 minutes'
            self.game_over(m, [])

        hospital_locations = moves['hospital_loc']
        ambulance_moves = moves['ambulance_moves']
        print(hospital_locations)
        print('------')
        print(ambulance_moves)

        for hos_id in range(0, self.total_hospitals):
            try:
                xloc = hospital_locations[str(hos_id)]['xloc']
                yloc = hospital_locations[str(hos_id)]['yloc']
            except Exception as e:
                m = 'Didn\'t get hospital location for hospital #' + str(hos_id)
                self.game_over(m, [])

            if xloc < 0 or yloc < 0 or xloc > 1000 or yloc > 1000:
                m = 'Invalid hospital location'
                self.game_over(m, [])

            self.hospitals[hos_id]['xloc'] = xloc
            self.hospitals[hos_id]['yloc'] = yloc

        patients_saved = []
        patients_picked_up = []

        for amb_id in range(0, self.total_ambulances):
            try:
                amb_route = ambulance_moves[str(amb_id)]
            except Exception as e:
                continue
            current_loc = (self.hospitals[self.ambulances[amb_id]['starting_hospital']]['xloc'], self.hospitals[self.ambulances[amb_id]['starting_hospital']]['yloc'])

            time_counter = 0
            p_inside_amb = []

            for amb_stop in amb_route:
                if amb_stop[0].lower() == 'p':
                    if len(p_inside_amb) >= 4:
                        m = 'Cannot pick up more than 4 patients'
                        self.game_over(m, [])
                    try:
                        p_id = int(amb_stop[1:])
                        if p_id >= self.total_patients or p_id < 0:
                            m = 'Invalid patient id'
                            print(p_id)
                            self.game_over(m, [])
                    except Exception as e:
                        m = 'Error reading patient id'
                        self.game_over(m, [])
                    if p_id in patients_picked_up:
                        print('Patient ' + str(patient) + ' has already been picked up')
                    else:
                        p_inside_amb += [p_id]
                        patients_picked_up += [p_id]
                        time_counter += 1
                    new_loc = (self.patients[p_id]['xloc'], self.patients[p_id]['yloc'])
                    time_taken = self.route_time(current_loc, new_loc)
                    time_counter += time_taken
                    current_loc = new_loc
                    continue
                elif amb_stop[0].lower() == 'h':
                    try:
                        h_id = int(amb_stop[1:])
                        if h_id >= self.total_hospitals or h_id < 0:
                            m = 'Invalid hospital id'
                            self.game_over(m, [])
                    except Exception as e:
                        m = 'Error reading hospital id'
                        self.game_over(m, [])
                    new_loc = (self.hospitals[h_id]['xloc'], self.hospitals[h_id]['yloc'])
                    time_taken = self.route_time(current_loc, new_loc)
                    time_counter += time_taken
                    if len(p_inside_amb) > 0:
                        time_counter += 1
                    current_loc = new_loc
                    for patient in p_inside_amb:
                        if time_counter <= self.patients[patient]['rescuetime']:
                            print('Ambulance ' + str(amb_id) + ' saved patient ' + str(patient))
                            patients_saved += [patient]
                        # else:
                        #     print('Patient ' + str(patient) + ' died before reaching the hospital')

                    p_inside_amb = []
                    continue
                else:
                    m = 'Invalid route stop'
                    self.game_over(m, [])

        print('All ambulances have finished their routes')
        print('------------')
        print('Congratulations!')
        print('Patients that lived:')
        print(patients_saved)
        print('Total number of patients saved: ' + str(len(patients_saved)))
        self.game_over('Congratulations!', patients_saved, finished=True)
예제 #6
0
class GameServer(object):
    def __init__(self, n):
        self.n = int(n)
        # self.randomFile = randomFile
        self.iterations = 20
        self.weights = None
        self.candidate_history = []
        self.score_history = []
        self.weight_history = []
        self.perfect_candidate_found = False
        self.maxScore = 0
        self.previousCandidate = []

        self.player_time_left = self.matchmaker_time_left = 120
        self.web_server = None
        print('Waiting on port %s for players...' % PORT)
        self.accept_player_connections()

    def accept_player_connections(self):
        self.server = SocketServer(HOST, PORT, 2)
        self.server.establish_client_connections()
        self.player_attributes = [
            json.loads(info) for info in self.server.receive_from_all()
        ]
        self.player_idx = 0 if self.player_attributes[0]['is_player'] else 1
        self.matchmaker_idx = 1 if self.player_attributes[0]['is_player'] else 0
        self.play_game()

    def timed_request(self, request_data, client_idx):
        self.server.send_to(json.dumps(request_data), client_idx)
        start = time()
        vector = json.loads(self.server.receive_from(client_idx))
        stop = time()
        return vector, (stop - start)

    def decrement_time(self, player_time_spent, matchmaker_time_spent):
        self.player_time_left -= player_time_spent
        self.matchmaker_time_left -= matchmaker_time_spent

    def check_time_left(self):
        if self.player_time_left < 0:
            raise Exception('Player ran out of time')

        if self.matchmaker_time_left < 0:
            raise Exception('Matchmaker ran out of time')

    def compute_score(self, weights, candidate):
        score = 0
        for i in range(len(candidate)):
            score += weights[i] * candidate[i]
        return round(score, 4)

    def check_precision(self, candidate):
        getcontext().prec = 4

        for i in range(0, len(candidate)):
            w = candidate[i]
            a = Decimal(w) / Decimal(1)
            if ((float)(a) != w):
                return False
        return True

    def check_weights_validity(self, orig_weights, cur_weights, prev_weights):

        # check weights have atmost precision 2
        getcontext().prec = 2

        for i in range(0, len(cur_weights)):
            w = cur_weights[i]
            a = Decimal(w) / Decimal(1)
            if (float)(a) != w:
                raise ValueError("decimals")
                return False

        # check whether change of every weight is in 20% range
        for i in range(0, self.n):
            if abs(cur_weights[i] -
                   orig_weights[i]) > 0.2 * abs(orig_weights[i]):
                raise ValueError("percentage")
                return False

        # check atmost 5% of weights changed from previous turn
        modified_weights = 0
        for i in range(self.n):
            if cur_weights[i] != prev_weights[i]:
                modified_weights += 1

        if (modified_weights > 0.05 * self.n):
            raise ValueError("number")
            return False

        # check pos weights sum to 1, neg weights sum to -1
        pos_sum = Decimal(0)
        neg_sum = Decimal(0)

        for w in cur_weights:
            if w > 0:
                pos_sum += Decimal(w)
            else:
                neg_sum += Decimal(w)

        if pos_sum != 1:
            raise ValueError("positive")
            return False
        if neg_sum != -1:
            raise ValueError("negative")
            return False

        return True

    def load_obj(self, name):
        with open(name, 'rb') as f:
            return pickle.load(f)

    def play_game(self):

        self.weights, player_time_spent = self.timed_request({'n': self.n},
                                                             self.player_idx)

        if not self.check_weights_validity(self.weights, self.weights,
                                           self.weights):
            raise ValueError('Invalid Weights provided by Player')

        # Generate 40 random candidates and scores

        random_candidates = {}

        for i in range(0, 40):
            # rand_cand = self.load_obj(self.randomFile)
            rand_cand = []
            for j in range(0, self.n):
                r = randint(0, 1)
                rand_cand.append(r)
            cscore = self.compute_score(rand_cand, self.weights)
            random_candidates[i] = {'Score': cscore, 'Attributes': rand_cand}

        self.server.send_to(
            json.dumps({
                'n': self.n,
                'randomCandidateAndScores': random_candidates
            }), self.matchmaker_idx)

        iterations = 0
        new_weights = self.weights
        self.weight_history.append(new_weights)
        new_candidate = []
        score = 0

        while iterations < self.iterations and self.perfect_candidate_found == False:
            self.check_time_left()

            new_candidate, matchmaker_time_spent = self.timed_request(
                {
                    'prev_candidate': {
                        'candidate': new_candidate,
                        'score': score,
                        'iter': iterations
                    },
                    'time_left': self.matchmaker_time_left
                }, self.matchmaker_idx)

            if (not self.check_precision(new_candidate)):
                raise ValueError("Invalid precision of candidates")

            self.candidate_history.append(new_candidate)

            new_weights, player_time_spent = self.timed_request(
                {
                    'new_candidate': new_candidate,
                    'weight_history': self.weight_history,
                    'time_left': self.player_time_left
                }, self.player_idx)

            # check weights validity
            if not self.check_weights_validity(self.weights, new_weights,
                                               self.weight_history[-1]):
                print(
                    'Invalid Weights provided by Player at iteration {iterations}. Maximum score so far: {self.maxScore}'
                )
                raise ValueError()

            self.weight_history.append(new_weights)

            score = max(
                self.compute_score(weights=new_weights,
                                   candidate=new_candidate),
                self.compute_score(weights=self.weights,
                                   candidate=new_candidate))
            self.score_history.append(score)

            print("**********************************************")
            print("Iteration Number: ", iterations + 1)
            print("New Candidate: ", new_candidate)
            print("New Weights: ", new_weights)
            print("Score History: ", self.score_history)
            print("**********************************************")

            if score > self.maxScore:
                self.maxScore = score

            if score == 1:
                self.perfect_candidate_found = True

            self.decrement_time(player_time_spent, matchmaker_time_spent)

            iterations += 1

        self.server.send_to_all(
            json.dumps({
                'game_over': True,
                'final_score': self.maxScore,
                'match_found': self.perfect_candidate_found,
                'num_iterations': iterations,
                'total_candidates': self.candidate_history.__len__()
            }))