moved game logic to a separate file
This commit is contained in:
parent
a4857c720a
commit
2d6180ad74
216
roborally.py
Normal file
216
roborally.py
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
import random
|
||||||
|
random.seed(0)
|
||||||
|
|
||||||
|
|
||||||
|
class Card:
|
||||||
|
possible_moves = ['forward', 'forward x2', 'forward x3', 'backward', 'turn left', 'turn right', 'turn around']
|
||||||
|
card_counter = 0
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.number = Card.card_counter
|
||||||
|
Card.card_counter += 1
|
||||||
|
self.action = random.choice(Card.possible_moves)
|
||||||
|
self.priority = random.randint(0, 100)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Card No. " + str(self.number) + " " + self.action + " " + str(self.priority)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.action + " (" + str(self.priority) + ")"
|
||||||
|
|
||||||
|
|
||||||
|
class CardDeck:
|
||||||
|
def __init__(self, n=84):
|
||||||
|
self.deck = {}
|
||||||
|
# generate cards
|
||||||
|
for i in range(0, n):
|
||||||
|
self.deck[i] = Card()
|
||||||
|
self.dealt = set()
|
||||||
|
self.discard_pile = set()
|
||||||
|
|
||||||
|
def draw_cards(self, n=1):
|
||||||
|
available = set(self.deck.keys()).difference(self.dealt)
|
||||||
|
# print("{} cards are available".format(len(available)))
|
||||||
|
|
||||||
|
if len(available) < n:
|
||||||
|
drawn = list(available) # give out remaining cards
|
||||||
|
# print("drawing remaining {} cards".format(len(drawn)))
|
||||||
|
self.dealt = self.dealt.union(drawn)
|
||||||
|
|
||||||
|
# put the cards from the discard pile back into the game
|
||||||
|
self.dealt = self.dealt - self.discard_pile
|
||||||
|
self.discard_pile = set() # reset the discard pile
|
||||||
|
|
||||||
|
# draw rest of cards
|
||||||
|
available = set(self.deck.keys()).difference(self.dealt)
|
||||||
|
# print("drawing another {} cards".format(n - len(drawn)))
|
||||||
|
drawn += random.sample(available, n - len(drawn))
|
||||||
|
else:
|
||||||
|
drawn = random.sample(available, n)
|
||||||
|
# print("cards drawn: {}".format(drawn))
|
||||||
|
|
||||||
|
self.dealt = self.dealt.union(drawn)
|
||||||
|
|
||||||
|
return [self.deck[i] for i in drawn]
|
||||||
|
|
||||||
|
def return_cards(self, cards):
|
||||||
|
self.discard_pile = self.discard_pile.union(set([c.number for c in cards]))
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
deck = CardDeck()
|
||||||
|
|
||||||
|
|
||||||
|
class Robot:
|
||||||
|
def __init__(self, x, y, orientation, id, board):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.orientation = orientation
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
self.board = board
|
||||||
|
|
||||||
|
def get_accessed_tiles(self, count):
|
||||||
|
tiles = []
|
||||||
|
if self.orientation == '>':
|
||||||
|
tiles = [self.board.get((self.x + i, self.y)) for i in range(1, count + 1)]
|
||||||
|
elif self.orientation == '<':
|
||||||
|
tiles = [self.board.get((self.x - i, self.y)) for i in range(1, count + 1)]
|
||||||
|
elif self.orientation == '^':
|
||||||
|
tiles = [self.board.get((self.x, self.y - i)) for i in range(1, count + 1)]
|
||||||
|
elif self.orientation == 'v':
|
||||||
|
tiles = [self.board.get((self.x, self.y + i)) for i in range(1, count + 1)]
|
||||||
|
return tiles
|
||||||
|
|
||||||
|
def move(self, type):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.id)
|
||||||
|
|
||||||
|
|
||||||
|
class Tile:
|
||||||
|
# possible modifiers:
|
||||||
|
# conveyors: <, >, ^, v
|
||||||
|
# repair station: r
|
||||||
|
# flag: f<number>
|
||||||
|
def __init__(self, x, y, modifier=None):
|
||||||
|
self.modifier = modifier
|
||||||
|
self.occupant = None
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return self.occupant is None
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.is_empty():
|
||||||
|
if self.modifier is None:
|
||||||
|
return ' '
|
||||||
|
else:
|
||||||
|
return self.modifier
|
||||||
|
else:
|
||||||
|
return str(self.occupant)
|
||||||
|
|
||||||
|
|
||||||
|
class Board:
|
||||||
|
x_dims = 12 # number of tiles in x direction
|
||||||
|
y_dims = 6 # number of tiles in y direction
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.board = {}
|
||||||
|
for x in range(Board.x_dims):
|
||||||
|
for y in range(Board.y_dims):
|
||||||
|
if x == 0 and (y >= 1) and (y <= 4):
|
||||||
|
self.board[(x, y)] = Tile(x, y, 'v')
|
||||||
|
else:
|
||||||
|
self.board[(x, y)] = Tile(x, y)
|
||||||
|
|
||||||
|
self.robots = {}
|
||||||
|
self.robots[0] = Robot(0, 0, '<', 0, self.board)
|
||||||
|
self.robots[1] = Robot(2, 0, '^', 1, self.board)
|
||||||
|
|
||||||
|
def handle_single_action(self, action, robot):
|
||||||
|
if 'forward' in action: # driving forward
|
||||||
|
if "x2" in action:
|
||||||
|
move_count = 2
|
||||||
|
elif "x3" in action:
|
||||||
|
move_count = 3
|
||||||
|
else:
|
||||||
|
move_count = 1
|
||||||
|
accessed_tiles = robot.get_accessed_tiles(move_count)
|
||||||
|
|
||||||
|
for tile in accessed_tiles:
|
||||||
|
if tile is None: # robot tries to access a tile outside of the board
|
||||||
|
# TODO take robot out of the game
|
||||||
|
pass
|
||||||
|
elif any([(tile.x, tile.y) == (r.x, r.y) for r in
|
||||||
|
self.robots]): # robots hits a tile occupied by another robot
|
||||||
|
# TODO move "pushed" robot by one tile:
|
||||||
|
# -> get current orientation
|
||||||
|
# -> turn the "pushed" robot to face in the same direction as the "pushing" robot
|
||||||
|
# -> move the "pushed" robot one step forward (while handling the move action of the robot recursively and pushing other robots as required)
|
||||||
|
# -> turn the "pushed" robot back to the original orientation
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# now the tile should be empty so the robot can move into the tile
|
||||||
|
# -> register move action to process
|
||||||
|
pass
|
||||||
|
elif action == 'backward':
|
||||||
|
# basically do the same as with forward
|
||||||
|
pass
|
||||||
|
elif action == 'turn left':
|
||||||
|
pass
|
||||||
|
elif action == 'turn right':
|
||||||
|
pass
|
||||||
|
elif action == 'turn around':
|
||||||
|
pass
|
||||||
|
|
||||||
|
def apply_actions(self, cards):
|
||||||
|
# apply the actions to the board and generate a list of movement commands
|
||||||
|
|
||||||
|
for i, phase in enumerate(cards): # process register phases
|
||||||
|
print("processing phase {}".format(i+1))
|
||||||
|
# sort actions by priority
|
||||||
|
sorted_actions = sorted(phase, key=lambda a: a[1].priority)
|
||||||
|
|
||||||
|
for a in sorted_actions:
|
||||||
|
robot_id = a[0]
|
||||||
|
robot = self.robots[robot_id]
|
||||||
|
action = a[1].action
|
||||||
|
|
||||||
|
print("robot {} action {}".format(robot, action))
|
||||||
|
|
||||||
|
self.handle_single_action(action, robot)
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
output = '#' * (Board.x_dims + 2) + '\n'
|
||||||
|
for y in range(Board.y_dims):
|
||||||
|
output += '#'
|
||||||
|
for x in range(Board.x_dims):
|
||||||
|
if any((r.x, r.y) == (x,y) for r in self.robots.values()):
|
||||||
|
r = list(filter(lambda r: (r.x,r.y) == (x,y), self.robots.values()))[0]
|
||||||
|
output += str(r.id)
|
||||||
|
else:
|
||||||
|
output += str(self.board[(x, y)])
|
||||||
|
output += '#\n'
|
||||||
|
output += '#' * (Board.x_dims + 2)
|
||||||
|
return output
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
n = 5
|
||||||
|
player_1_cards = deck.draw_cards(3)
|
||||||
|
player_2_cards = deck.draw_cards(3)
|
||||||
|
|
||||||
|
cards_1 = [(0, c) for c in player_1_cards]
|
||||||
|
cards_2 = [(1, c) for c in player_2_cards]
|
||||||
|
|
||||||
|
chosen_cards = list(zip(cards_1, cards_2))
|
||||||
|
|
||||||
|
b = Board()
|
||||||
|
print(b)
|
||||||
|
|
||||||
|
b.apply_actions(chosen_cards)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user