diff --git a/examples/masha_and_zoe_driver.py b/examples/masha_and_zoe_driver.py new file mode 100644 index 00000000..1b7de412 --- /dev/null +++ b/examples/masha_and_zoe_driver.py @@ -0,0 +1,62 @@ +from rose.common import obstacles, actions + +driver_name = "Zoe and Masha" +running = True + +# Define valid lane ranges based on the starting position +def get_lane_range(starting_position): + if starting_position == 1: + return 0, 2 + elif starting_position == 4: + return 3, 5 + else: + # Default to a range that includes only the starting position if not 1 or 4 + return starting_position, starting_position + +def run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x): + if cur_pos_x == min_x: + return actions.RIGHT + elif cur_pos_x == max_x: + return actions.LEFT + else: + if min_x < cur_pos_x < max_x: + if obs != obstacles.PENGUIN and obs != obstacles.NONE: + next_obs = world.get((cur_pos_x - 1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN or next_obs == obstacles.NONE: + return actions.LEFT + else: + return actions.NONE + else: + next_obs = world.get((cur_pos_x + 1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN or next_obs == obstacles.NONE: + return actions.RIGHT + else: + return actions.NONE + else: + return actions.NONE + +def drive(world): + cur_pos_x = world.car.x + cur_pos_y = world.car.y + + # Determine the lane range based on the starting position + min_x, max_x = get_lane_range(cur_pos_x) + + obs = world.get((cur_pos_x, cur_pos_y - 1)) + match obs: + case obstacles.NONE: + return actions.NONE + case obstacles.PENGUIN: + return actions.PICKUP + case obstacles.WATER: + return actions.BRAKE + case obstacles.CRACK: + return actions.JUMP + case obstacles.TRASH: + return run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case obstacles.BIKE: + return run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case obstacles.BARRIER: + return run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case _: + return actions.NONE diff --git a/examples/new_driver.py b/examples/new_driver.py new file mode 100644 index 00000000..76558238 --- /dev/null +++ b/examples/new_driver.py @@ -0,0 +1,117 @@ +from rose.common import obstacles, actions +driver_name = "Zoe and Masha" +running = True +def drive(world): + cur_pos_x = world.car.x + cur_pos_y = world.car.y + obs = world.get((cur_pos_x, cur_pos_y - 1)) + match obs: + case obstacles.NONE: + return actions.NONE + case obstacles.PENGUIN: + return actions.PICKUP + case obstacles.WATER: + return actions.BRAKE + case obstacles.CRACK: + return actions.JUMP + case obstacles.TRASH: + return actions.NONE + case obstacles.BIKE: + return actions.NONE + case obstacles.BARRIER: + return actions.NONE + + +# #""" +# This driver does not do any action. +# """ +# from rose.common import obstacles, actions # NOQA +# +# driver_name = "No Driver" +# +# +# def drive(world): +# return actions.NONE + + +from rose.common import obstacles, actions + +driver_name = "Zoe and Masha" +running = True + + +# Define valid lane ranges based on the starting position +def get_lane_range(starting_position): + if starting_position == 1: + return 0, 2 + elif starting_position == 4: + return 3, 5 + else: + # Default to a range that includes only the starting position if not 1 or 4 + return starting_position, starting_position +def penguin_l(cur_pos_x, cur_pos_y, world, min_x, max_x): + next_obs = world.get((cur_pos_x-1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN: + return actions.LEFT + return actions.NONE + + +def penguin_r(cur_pos_x, cur_pos_y, world, min_x, max_x): + next_obs = world.get((cur_pos_x +1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN: + return actions.RIGHT + return actions.NONE + +def run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x): + if cur_pos_x == min_x: + return actions.RIGHT + elif cur_pos_x == max_x: + return actions.LEFT + else: + if min_x < cur_pos_x < max_x: + if obs != obstacles.PENGUIN and obs != obstacles.NONE: + next_obs = world.get((cur_pos_x - 1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN or next_obs == obstacles.NONE: + return actions.LEFT + else: + return actions.NONE + else: + next_obs = world.get((cur_pos_x + 1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN or next_obs == obstacles.NONE: + return actions.RIGHT + else: + return actions.NONE + else: + return actions.NONE + +def drive(world): + cur_pos_x = world.car.x + cur_pos_y = world.car.y + + # Determine the lane range based on the starting position + min_x, max_x = get_lane_range(cur_pos_x) + + obs = world.get((cur_pos_x, cur_pos_y - 1)) + p_act_1 = penguin_l(cur_pos_x,cur_pos_y,world,min_x,max_x) + if p_act_1 != actions.NONE: + return p_act_1 + p_act_2 = penguin_r(cur_pos_x, cur_pos_y, world, min_x, max_x) + if p_act_2 != actions.NONE: + return p_act_2 + match obs: + case obstacles.NONE: + return actions.NONE + case obstacles.PENGUIN: + return actions.PICKUP + case obstacles.WATER: + return actions.BRAKE + case obstacles.CRACK: + return actions.JUMP + case obstacles.TRASH: + return run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case obstacles.BIKE: + return run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case obstacles.BARRIER: + return run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case _: + return actions.NONE diff --git a/examples/none.py b/examples/none.py index 3904818a..04022276 100644 --- a/examples/none.py +++ b/examples/none.py @@ -1,10 +1,115 @@ -""" -This driver does not do any action. -""" -from rose.common import obstacles, actions # NOQA +from rose.common import obstacles, actions -driver_name = "No Driver" +driver_name = "Zoe and Masha" +running = True + +# Define valid lane ranges based on the starting position +def get_lane_range(starting_position): + if starting_position == 1: + return 0, 2 + elif starting_position == 4: + return 3, 5 + else: + # Default to a range that includes only the starting position if not 1 or 4 + return starting_position, starting_position + +def run(cur_pos_x, cur_pos_y, obs, world, min_x, max_x): + if cur_pos_x == min_x: + return actions.RIGHT + elif cur_pos_x == max_x: + return actions.LEFT + else: + if min_x < cur_pos_x < max_x: + if obs != obstacles.PENGUIN and obs != obstacles.NONE: + next_obs = world.get((cur_pos_x - 1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN or next_obs == obstacles.NONE: + return actions.LEFT + else: + return actions.NONE + else: + next_obs = world.get((cur_pos_x + 1, cur_pos_y - 1)) + if next_obs == obstacles.PENGUIN or next_obs == obstacles.NONE: + return actions.RIGHT + else: + return actions.NONE + else: + return actions.NONE + +def score(obs): + match obs: + case obstacles.NONE: + return 0 + case obstacles.PENGUIN: + return 10 + case obstacles.WATER: + return 5 + case obstacles.CRACK: + return 4 + case obstacles.TRASH: + return -10 + case obstacles.BIKE: + return -10 + case obstacles.BARRIER: + return -10 + case _: + return 0 + +def new(cur_pos_x, cur_pos_y, obs, world, min_x, max_x): + left = [world.get((cur_pos_x - 1, cur_pos_y - 1))] + left.append(score(left[0])) + print(f"Left lane: {left}") + + right = [world.get((cur_pos_x + 1, cur_pos_y - 1))] + right.append(score(right[0])) + print(f"Right lane: {right}") + + middle = [world.get((cur_pos_x, cur_pos_y - 1))] + middle.append(score(middle[0])) + print(f"Middle lane: {middle}") + + best_lane = better(left, right, middle) + if best_lane == left: + return actions.LEFT + elif best_lane == right: + return actions.RIGHT + else: # best_lane == middle + return actions.NONE + +def better(left, right, middle): + higher = max(left[1], right[1], middle[1]) + if higher == left[1]: + return left + elif higher == right[1]: + return right + elif higher == middle[1]: + return middle + else: + print('fgbfrewrererg') + return middle def drive(world): - return actions.NONE + cur_pos_x = world.car.x + cur_pos_y = world.car.y + + # Determine the lane range based on the starting position + min_x, max_x = get_lane_range(cur_pos_x) + + obs = world.get((cur_pos_x, cur_pos_y - 1)) + match obs: + case obstacles.NONE: + return actions.NONE + case obstacles.PENGUIN: + return actions.PICKUP + case obstacles.WATER: + return actions.BRAKE + case obstacles.CRACK: + return actions.JUMP + case obstacles.TRASH: + return new(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case obstacles.BIKE: + return new(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case obstacles.BARRIER: + return new(cur_pos_x, cur_pos_y, obs, world, min_x, max_x) + case _: + return actions.NONE diff --git a/examples/zoe.py b/examples/zoe.py new file mode 100644 index 00000000..81601c81 --- /dev/null +++ b/examples/zoe.py @@ -0,0 +1,93 @@ +from none import * + + +def find_lane(cur_pos_x, cur_pos_y): + min_x, max_x = 0, 2 + return min_x, max_x + + +def count(points, op): + sum_points = 0 + for i in points[op]: + sum_points += i + + return sum_points + + +def merge(op_1, op_2, op_3, points): + + if op_1 == 'no' and op_2 == 'no' and op_3 == 'no': + return ['no'] + + if op_1 == 'no' and op_2 == 'no' and op_3 != 'no': + return [op_3] + + if op_1 == 'no' and op_2 != 'no' and op_3 == 'no': + return [op_2] + + if op_1 != 'no' and op_2 == 'no' and op_3 == 'no': + return [op_1] + + if count(points, op_1) >= count(points, op_2): + if count(points, op_1) >= count(points, op_3): + return [op_1] + else: + return [op_3] + elif count(points, op_2) >= count(points, op_3): + return [op_2] + else: + return [op_3] + + + + + + + +def priorities(lane, step, points, bord, cur_pos_x , cur_pos_y): + min_x, max_x = find_lane(cur_pos_x, cur_pos_y) + if lane > max_x or lane < min_x: + return ['no'] + if step <= 0: + return ["finish"] + + points += (bord[cur_pos_x][cur_pos_y]) + + R = ['r'] + priorities(lane+1, step-1, points, bord, cur_pos_x +1, cur_pos_y +1) + M = ['m'] + priorities(lane, step - 1, points, bord, cur_pos_x, cur_pos_y +1) + L = ['m'] + priorities(lane -1, step - 1, points, bord, cur_pos_x -1, cur_pos_y +1) + + return merge(R, M, L, points) + + + +points = +bord = [[[-10], [+5], [+10]], [[+10], [0], [-10]]] +lane = 1 +step = 1 +cur_pos_x = 1 +cur_pos_y = 0 + +print(priorities(lane, step, points, bord, cur_pos_x, cur_pos_y)) + + +def pen(cur_pos_x, cur_pos_y, obs, world, min_x, max_x): + if min_x < cur_pos_x < max_x: + right_next_obs = world.get((cur_pos_x + 1, cur_pos_y - 2)) + left_next_obs = world.get((cur_pos_x - 1, cur_pos_y - 2)) + right_obs = world.get((cur_pos_x + 1, cur_pos_y - 1)) + left_obs = world.get((cur_pos_x + 1, cur_pos_y - 1)) + if right_next_obs == obstacles.PENGUIN and right_obs not in [obstacles.BIKE, obstacles.TRASH, + obstacles.BARRIER]: + return actions.RIGHT + elif left_next_obs == obstacles.PENGUIN and left_obs not in [obstacles.BIKE, obstacles.TRASH, + obstacles.BARRIER]: + return actions.LEFT + elif right_obs == obstacles.PENGUIN: + return actions.RIGHT, actions.PICKUP + elif left_obs == obstacles.PENGUIN: + return actions.LEFT, actions.PICKUP + else: + return actions.NONE + return actions.NONE + diff --git a/rose/common/config.py b/rose/common/config.py index 613a2459..cae7f128 100644 --- a/rose/common/config.py +++ b/rose/common/config.py @@ -10,7 +10,7 @@ game_rate = 1.0 game_duration = 60 number_of_cars = 4 -is_track_random = True +is_track_random = False # Matrix diff --git a/rose/common/obstacles.py b/rose/common/obstacles.py index 3b84f9ca..66e10cdb 100644 --- a/rose/common/obstacles.py +++ b/rose/common/obstacles.py @@ -13,5 +13,3 @@ ALL = (NONE, CRACK, TRASH, PENGUIN, BIKE, WATER, BARRIER) -def get_random_obstacle(): - return random.choice(ALL) diff --git a/rose/server/game.py b/rose/server/game.py index 9c72daa1..23d5413d 100644 --- a/rose/server/game.py +++ b/rose/server/game.py @@ -19,7 +19,8 @@ class Game(object): def __init__(self): self.hub = None - self.track = track.Track() + self.seed = "" + self.track = track.Track(seed=self.seed) self.looper = task.LoopingCall(self.loop) self.players = {} self.free_cars = set(range(config.number_of_cars)) @@ -70,7 +71,7 @@ def add_player(self, name): raise error.TooManyPlayers() car = random.choice(tuple(self.free_cars)) self.free_cars.remove(car) - lane = random.choice(tuple(self.free_lanes)) + lane = 1 self.free_lanes.remove(lane) log.info("add player: %r, lane: %r, car: %r", name, lane, car) self.players[name] = player.Player(name, car, lane) diff --git a/rose/server/main.py b/rose/server/main.py index 1f8774ba..6f7ee95e 100644 --- a/rose/server/main.py +++ b/rose/server/main.py @@ -1,6 +1,8 @@ +import random import socket import logging import argparse +import string from twisted.internet import reactor from twisted.web import server, static @@ -25,6 +27,12 @@ def main(): help="Definition of driver tracks: random or same." "If not specified, random will be used.", ) + parser.add_argument( + "--imported_seed", + "-ps", + dest = "imported_seed", + help = "Optianal, providing a predefined seed to use an already existing map", + ) args = parser.parse_args() """ @@ -32,13 +40,23 @@ def main(): same place for both drivers, otherwise, the obstacles will be genrated in random locations for each driver. """ + if args.track_definition == "same": config.is_track_random = False else: config.is_track_random = True + if args.imported_seed is None: + seed = generate_seed() + elif len(args.imported_seed) > 0: + seed = args.imported_seed + else: + print("error seed option was not selected") + log.info(f"This is the map seed {seed}") log.info("starting server") + g = game.Game() + g.seed = seed h = net.Hub(g) reactor.listenTCP(config.game_port, net.PlayerFactory(h)) root = static.File(config.web_root) @@ -51,3 +69,15 @@ def main(): site = server.Site(root) reactor.listenTCP(config.web_port, site) reactor.run() + + +def generate_seed(): + lenght = 5 + lis = [] + for x in range(lenght): + ramdom_generate = (random.choice(string.ascii_lowercase)) + lis.append(ramdom_generate) + randon_seed = ''.join(lis) + return randon_seed + + diff --git a/rose/server/track.py b/rose/server/track.py index 308283db..8eef31ce 100644 --- a/rose/server/track.py +++ b/rose/server/track.py @@ -3,9 +3,10 @@ class Track(object): - def __init__(self): + def __init__(self, seed): self._matrix = None self.reset() + self.rand = random.Random(seed) # Game state interface @@ -53,15 +54,18 @@ def _generate_row(self): Otherwise, the tracks will be identical. """ row = [obstacles.NONE] * config.matrix_width - obstacle = obstacles.get_random_obstacle() + obstacle = self.get_random_obstacle() if config.is_track_random: for lane in range(config.max_players): low = lane * config.cells_per_player high = low + config.cells_per_player - cell = random.choice(range(low, high)) + cell = self.rand.choice(range(low, high)) row[cell] = obstacle else: - cell = random.choice(range(0, config.cells_per_player)) + cell = self.rand.choice(range(0, config.cells_per_player)) for lane in range(config.max_players): row[cell + lane * config.cells_per_player] = obstacle return row + + def get_random_obstacle(self): + return self.rand.choice(obstacles.ALL) \ No newline at end of file