From 2d6180ad745be08872cdaa6dca02385491dea8d9 Mon Sep 17 00:00:00 2001 From: spirkelmann Date: Sat, 19 Sep 2020 21:15:23 +0200 Subject: [PATCH] moved game logic to a separate file --- roborally.py | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 roborally.py diff --git a/roborally.py b/roborally.py new file mode 100644 index 0000000..4f71c21 --- /dev/null +++ b/roborally.py @@ -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 + 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) +