Skip to content

Commit 470ecbb

Browse files
mashashtivZoeSasportas
authored andcommitted
Introduce the --seed flag
This patch makes each map generated from a random seed, the length of the seed is controllerd by config.seed_length. Since each run is seeded, it is possible to use a custom seed to start the server, using: ``` $ ./rose-server --seed <seed> ``` This makes every run reproducible for debugging and testing. Co-authored-by: Masha Shtivelberg <[email protected]> Co-authored-by: Zoe Sasportas <[email protected]>
1 parent 4c9b4aa commit 470ecbb

File tree

5 files changed

+36
-15
lines changed

5 files changed

+36
-15
lines changed

rose/common/config.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
game_duration = 60
1212
number_of_cars = 4
1313
is_track_random = True
14+
seed_length = 5
1415

1516
# Matrix
1617

rose/common/obstacles.py

-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
""" Game obstacles """
22

3-
import random
4-
53
NONE = "" # NOQA
64
CRACK = "crack" # NOQA
75
TRASH = "trash" # NOQA
@@ -11,7 +9,3 @@
119
BARRIER = "barrier" # NOQA
1210

1311
ALL = (NONE, CRACK, TRASH, PENGUIN, BIKE, WATER, BARRIER)
14-
15-
16-
def get_random_obstacle():
17-
return random.choice(ALL)

rose/server/game.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ class Game(object):
1717
Implements the server for the car race
1818
"""
1919

20-
def __init__(self):
20+
def __init__(self, seed):
2121
self.hub = None
22-
self.track = track.Track()
22+
self.rng = random.Random(seed)
23+
self.track = track.Track(seed=seed)
2324
self.looper = task.LoopingCall(self.loop)
2425
self.players = {}
2526
self.free_cars = set(range(config.number_of_cars))
@@ -68,9 +69,9 @@ def add_player(self, name):
6869
raise error.PlayerExists(name)
6970
if not self.free_cars:
7071
raise error.TooManyPlayers()
71-
car = random.choice(tuple(self.free_cars))
72+
car = self.rng.choice(tuple(self.free_cars))
7273
self.free_cars.remove(car)
73-
lane = random.choice(tuple(self.free_lanes))
74+
lane = self.rng.choice(tuple(self.free_lanes))
7475
self.free_lanes.remove(lane)
7576
log.info("add player: %r, lane: %r, car: %r", name, lane, car)
7677
self.players[name] = player.Player(name, car, lane)

rose/server/main.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import random
12
import socket
23
import logging
34
import argparse
5+
import string
46

57
from twisted.internet import reactor
68
from twisted.web import server, static
@@ -25,6 +27,13 @@ def main():
2527
help="Definition of driver tracks: random or same."
2628
"If not specified, random will be used.",
2729
)
30+
parser.add_argument(
31+
"--seed",
32+
"-s",
33+
dest="seed",
34+
default="",
35+
help="Optional, use a custom seed for the map generation",
36+
)
2837

2938
args = parser.parse_args()
3039
"""
@@ -37,8 +46,16 @@ def main():
3746
else:
3847
config.is_track_random = True
3948

49+
if args.seed:
50+
seed = args.seed
51+
else:
52+
seed = generate_seed(config.seed_length)
53+
54+
log.info(f"Seed for map: {seed}")
55+
g = game.Game(seed=seed)
56+
4057
log.info("starting server")
41-
g = game.Game()
58+
4259
h = net.Hub(g)
4360
reactor.listenTCP(config.game_port, net.PlayerFactory(h))
4461
root = static.File(config.web_root)
@@ -51,3 +68,7 @@ def main():
5168
site = server.Site(root)
5269
reactor.listenTCP(config.web_port, site)
5370
reactor.run()
71+
72+
73+
def generate_seed(seed_length=5):
74+
return ''.join(random.choice(string.ascii_lowercase) for _ in range(seed_length))

rose/server/track.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33

44

55
class Track(object):
6-
def __init__(self):
6+
def __init__(self, seed):
77
self._matrix = None
8+
self.rng = random.Random(seed)
89
self.reset()
910

1011
# Game state interface
@@ -53,15 +54,18 @@ def _generate_row(self):
5354
Otherwise, the tracks will be identical.
5455
"""
5556
row = [obstacles.NONE] * config.matrix_width
56-
obstacle = obstacles.get_random_obstacle()
57+
obstacle = self.get_random_obstacle()
5758
if config.is_track_random:
5859
for lane in range(config.max_players):
5960
low = lane * config.cells_per_player
6061
high = low + config.cells_per_player
61-
cell = random.choice(range(low, high))
62+
cell = self.rng.choice(range(low, high))
6263
row[cell] = obstacle
6364
else:
64-
cell = random.choice(range(0, config.cells_per_player))
65+
cell = self.rng.choice(range(0, config.cells_per_player))
6566
for lane in range(config.max_players):
6667
row[cell + lane * config.cells_per_player] = obstacle
6768
return row
69+
70+
def get_random_obstacle(self):
71+
return self.rng.choice(obstacles.ALL)

0 commit comments

Comments
 (0)