diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..4a96c22 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +source .venv/bin/activate \ No newline at end of file diff --git a/Snake/Bike.py b/Snake/Bike.py new file mode 100644 index 0000000..c10faa2 --- /dev/null +++ b/Snake/Bike.py @@ -0,0 +1,98 @@ +""" + +from trail import SnakeBodySegment + + + + + +class SnakeHead: + """An Agent representing the snake's head. When the game starts, you control + the snake head using the arrow keys. The SnakeHead always has a direction, and + will keep moving in that direction every turn. When you press an arrow key, + you change the SnakeHead's direction. + + Attributes: + name: "Snake head" + position: (0,0) + character: ``'v'`` Depending on the snake head's direction, its character + changes to ``'<'``, ``'^'``, ``'>'``, or ``'v'``. + next_segment: Initially ``None``, this is a reference to a SnakeBodySegment. + growing: When set to True, the snake will grow a new segment on its next move. + """ + RIGHT = (1, 0) + UP = (0, -1) + LEFT = (-1, 0) + DOWN = (0, 1) + name = "Snake head" + position = (0, 0) + direction = DOWN + character = 'v' + next_segment = None + growing = False + + def play_turn(self, game): + """On each turn, the snake head uses its position and direction to figure out + its next position. If the snake head is able to move there (it's on the board and + not occuppied by part of the snake's body), it moves. + + Then, if the snake head is on the Apple, the Apple moves to a new random position + and ``growing`` is set to True. + + Now we need to deal with two situations. First, if ``next_segment`` is not None, there is + a SnakeBodySegment attached to the head. We need the body to follow the head, + so we call ``self.next_segment.move``, passing the head's old position + (this will be the body's new position), a reference to the game, and a value for + ``growing``. If the snake needs to grow, we need to pass this information along + the body until it reaches the tail--this is where the next segment will be attached. + + If there is no ``next_segment`` but ``self.growing`` is True, it's time to add + a body! We set ``self.next_segment`` to a new SnakeBodySegment, set its + position to the head's old position, and add it to the game. We also add 1 to the + game's score. + """ + x, y = self.position + dx, dy = self.direction + if self.can_move((x+dx, y+dy), game): + self.position = (x+dx, y+dy) + if self.is_on_apple(self.position, game): + apple = game.get_agent_by_name("Apple") + apple.relocate(game) + self.growing = True + if self.next_segment: + self.next_segment.move((x, y), game, growing=self.growing) + elif self.growing: + self.next_segment = SnakeBodySegment(1, (x, y)) + game.add_agent(self.next_segment) + game.state['score'] += 1 + self.growing = False + + + def handle_keystroke(self, keystroke, game): + """Checks whether one of the arrow keys has been pressed. + If so, sets the SnakeHead's direction and character. + """ + x, y = self.position + if keystroke.name == "KEY_RIGHT": + self.direction = self.RIGHT + self.character = '>' + elif keystroke.name == "KEY_UP": + self.direction = self.UP + self.character = '^' + elif keystroke.name == "KEY_LEFT": + self.direction = self.LEFT + self.character = '<' + elif keystroke.name == "KEY_DOWN": + self.direction = self.DOWN + self.character = 'v' + + + def can_move(self, position, game): + on_board = game.on_board(position) + empty = game.is_empty(position) + on_apple = self.is_on_apple(position, game) + return on_board and (empty or on_apple) + + def is_on_apple(self, position, game): + apple = game.get_agent_by_name("Apple") + return apple.position == position \ No newline at end of file diff --git a/Snake/Trail.py b/Snake/Trail.py new file mode 100644 index 0000000..d2e38f0 --- /dev/null +++ b/Snake/Trail.py @@ -0,0 +1,56 @@ +""" + + + + +class SnakeBodySegment: + """Finally, we need an Agent for the snake's body segments. + SnakeBodySegment doesn't have ``play_turn`` or ``handle_keystroke`` methods because + it never does anything on its own. It only moves when the SnakeHead, or the previous + segment, tells it to move. + + Arguments: + segment_id (int): Keeps track of how far back this segment is from the head. + This is used to give the segment a unique name, and also to keep track + of how many points the player earns for eating the next apple. + position (int, int): The initial position. + + Attributes: + character: '*' + next_segment: Initially ``None``, this is a reference to a SnakeBodySegment + when this segment is not the last one in the snake's body. + + """ + character = '*' + next_segment = None + + def __init__(self, segment_id, position): + self.segment_id = segment_id + self.name = f"Snake body segment {segment_id}" + self.position = position + + def move(self, new_position, game, growing=False): + """When SnakeHead moves, it sets off a chain reaction, moving all its + body segments. Whenever the head or a body segment has another segment + (``next_segment``), it calls that segment's ``move`` method. + + This method updates the SnakeBodySegment's position. Then, if + ``self.next_segment`` is not None, calls that segment's ``move`` method. + If there is no next segment and ``growing`` is True, then we set + ``self.next_segment`` to a new SnakeBodySegment in this segment's old + position, and update the game's score. + + Arguments: + new_position (int, int): The new position. + game (Game): A reference to the current game. + growing (bool): (Default False) When True, the snake needs to + add a new segment. + """ + old_position = self.position + self.position = new_position + if self.next_segment: + self.next_segment.move(old_position, game, growing=growing) + elif growing: + self.next_segment = SnakeBodySegment(self.segment_id + 1, old_position) + game.add_agent(self.next_segment) + game.state['score'] += self.segment_id + 1 \ No newline at end of file diff --git a/Snake/__pycache__/bike.cpython-311.pyc b/Snake/__pycache__/bike.cpython-311.pyc new file mode 100644 index 0000000..a8aa030 Binary files /dev/null and b/Snake/__pycache__/bike.cpython-311.pyc differ diff --git a/Snake/__pycache__/trail.cpython-311.pyc b/Snake/__pycache__/trail.cpython-311.pyc new file mode 100644 index 0000000..83d9fff Binary files /dev/null and b/Snake/__pycache__/trail.cpython-311.pyc differ diff --git a/Snake/nav_game.py b/Snake/nav_game.py new file mode 100644 index 0000000..8a8b7e0 --- /dev/null +++ b/Snake/nav_game.py @@ -0,0 +1,67 @@ +""" + + + +from random import randint +from retro.game import Game +from bike import SnakeHead + + +class Apple: + """An agent representing the Apple. + Note how Apple doesn't have ``play_turn`` or + ``handle_keystroke`` methods: the Apple doesn't need to do + anything in this game. It just sits there waiting to get + eaten. + + Attributes: + name: "Apple" + character: '@' + color: "red_on_black" (`Here's documentation on how colors + work `_ + position: (0, 0). The Apple will choose a random position + as soon as the game starts, but it needs an initial + position to be assigned. + + """ + name = "Apple" + character = '@' + color = "red_on_black" + position = (0, 0) + + def relocate(self, game): + """Sets position to a random empty position. This method is + called whenever the snake's head touches the apple. + + Arguments: + game (Game): The current game. + """ + self.position = self.random_empty_position(game) + + + def random_empty_position(self, game): + """Returns a randomly-selected empty position. Uses a very + simple algorithm: Get the game's board size, choose a + random x-value between 0 and the board width, and choose + a random y-value between 0 and the board height. Now use + the game to check whether any Agents are occupying this + position. If so, keep randomly choosing a new position + until the position is empty. + """ + bw, bh = game.board_size + occupied_positions = game.get_agents_by_position() + while True: + position = (randint(0, bw-1), randint(0, bh-1)) + if position not in occupied_positions: + return position + + + + + +if __name__ == '__main__': + head = SnakeHead() + apple = Apple() + game = Game([head, apple], {'score': 0}, board_size=(32, 16), framerate=12) + apple.relocate(game) + game.play() \ No newline at end of file diff --git a/Tron/Bike.py b/Tron/Bike.py new file mode 100644 index 0000000..ef0907f --- /dev/null +++ b/Tron/Bike.py @@ -0,0 +1,144 @@ +from Trail import TrailSegment + + + + + +class Bike: + + + + """An Agent representing the snake's head. When the game starts, you control + the snake head using the arrow keys. The Bike always has a direction, and + will keep moving in that direction every turn. When you press an arrow key, + you change the Bike's direction. + + Attributes: + name: "Snake head" + position: (0,0) + character: ``'v'`` Depending on the snake head's direction, its character + changes to ``'<'``, ``'^'``, ``'>'``, or ``'v'``. + next_segment: Initially ``None``, this is a reference to a SnakeBodySegment. + growing: When set to True, the snake will grow a new segment on its next move. + """ + RIGHT = (1, 0) + UP = (0, -1) + LEFT = (-1, 0) + DOWN = (0, 1) + next_segment = None + growing = False + turn_counter = 0 + GROW_INTERVAL = 5 # The bike will grow 1 segment longer every 5 turns. + + + + + def __init__(self, player_number, start_position, start_direction): + self.player_number = player_number + self.position = start_position + self.direction = start_direction + self.name = f"Bike {player_number}" + if self.player_number == 1: + self.color = "bright_blue" + else: + self.color = "bright_red" + + # Adjust starting character based on starting direction + if start_direction == self.RIGHT: self.character = '>' + elif start_direction == self.LEFT: self.character = '<' + elif start_direction == self.UP: self.character = '^' + elif start_direction == self.DOWN: self.character = 'v' + + + def play_turn(self, game): + """On each turn, the snake head uses its position and direction to figure out + its next position. If the snake head is able to move there (it's on the board and + not occuppied by part of the snake's body), it moves. + + Then, if the snake head is on the Apple, the Apple moves to a new random position + and ``growing`` is set to True. + + Now we need to deal with two situations. First, if ``next_segment`` is not None, there is + a SnakeBodySegment attached to the head. We need the body to follow the head, + so we call ``self.next_segment.move``, passing the head's old position + (this will be the body's new position), a reference to the game, and a value for + ``growing``. If the snake needs to grow, we need to pass this information along + the body until it reaches the tail--this is where the next segment will be attached. + + If there is no ``next_segment`` but ``self.growing`` is True, it's time to add + a body! We set ``self.next_segment`` to a new SnakeBodySegment, set its + position to the head's old position, and add it to the game. We also add 1 to the + game's score. + """ + # 1. Increment turn counter and check if it's time to grow + self.turn_counter += 1 + if self.turn_counter >= self.GROW_INTERVAL: + self.growing = True + self.turn_counter = 0 # Reset the counter for the next growth cycle + + + x, y = self.position + dx, dy = self.direction + if self.can_move((x+dx, y+dy), game): + self.position = (x+dx, y+dy) + if self.next_segment: + self.next_segment.move((x, y), game, growing=self.growing) + elif self.growing: + self.next_segment = TrailSegment(1, (x, y), self.player_number) + game.add_agent(self.next_segment) + self.growing = False + else: + game.end() + print(f"Player {self.player_number} died") + + + def handle_keystroke(self, keystroke, game): + """Checks whether one of the arrow keys has been pressed. + If so, sets the Bike's direction and character. + """ + + + x, y = self.position + # --- PLAYER 1 CONTROLS (Arrow Keys) --- + if self.player_number == 1: + if keystroke.name == "KEY_RIGHT" and self.direction != self.LEFT: + self.direction = self.RIGHT + self.character = '>' + elif keystroke.name == "KEY_UP" and self.direction != self.DOWN: + self.direction = self.UP + self.character = '^' + elif keystroke.name == "KEY_LEFT" and self.direction != self.RIGHT: + self.direction = self.LEFT + self.character = '<' + elif keystroke.name == "KEY_DOWN" and self.direction != self.UP: + self.direction = self.DOWN + self.character = 'v' + + # --- PLAYER 2 CONTROLS (WASD Keys) --- + elif self.player_number == 2: + + key_name = str(keystroke) + + if keystroke == "d" and self.direction != self.LEFT: + self.direction = self.RIGHT + self.character = '>' + elif keystroke == "w" and self.direction != self.DOWN: + self.direction = self.UP + self.character = '^' + elif keystroke == "a" and self.direction != self.RIGHT: + self.direction = self.LEFT + self.character = '<' + elif keystroke == "s" and self.direction != self.UP: + self.direction = self.DOWN + self.character = 'v' + + + def can_move(self, position, game): + on_board = game.on_board(position) + empty = game.is_empty(position) + return on_board and empty +''' + def is_on_apple(self, position, game): + apple = game.get_agent_by_name("Apple") + return apple.position == position +''' \ No newline at end of file diff --git a/Tron/Trail.py b/Tron/Trail.py new file mode 100644 index 0000000..eff403c --- /dev/null +++ b/Tron/Trail.py @@ -0,0 +1,62 @@ + + + + + +class TrailSegment: + """Finally, we need an Agent for the snake's body segments. + SnakeBodySegment doesn't have ``play_turn`` or ``handle_keystroke`` methods because + it never does anything on its own. It only moves when the Bike, or the previous + segment, tells it to move. + + Arguments: + segment_id (int): Keeps track of how far back this segment is from the head. + This is used to give the segment a unique name, and also to keep track + of how many points the player earns for eating the next apple. + position (int, int): The initial position. + + Attributes: + character: '*' + next_segment: Initially ``None``, this is a reference to a TrailSegment + when this segment is not the last one in the snake's Trail. + + """ + character = '*' + next_segment = None + + def __init__(self, segment_id, position, player_number): # Added player_number + self.segment_id = segment_id + self.player_number = player_number + # Give it a completely unique name per player + self.name = f"P{player_number} Trail segment {segment_id}" + self.position = position + if self.player_number == 1: + self.color = "bright_blue" + else: + self.color = "bright_red" + + def move(self, new_position, game, growing=False): + """When Bike moves, it sets off a chain reaction, moving all its + Trail segments. Whenever the head or a Trail segment has another segment + (``next_segment``), it calls that segment's ``move`` method. + + This method updates the TrailSegment's position. Then, if + ``self.next_segment`` is not None, calls that segment's ``move`` method. + If there is no next segment and ``growing`` is True, then we set + ``self.next_segment`` to a new SnakeBodySegment in this segment's old + position, and update the game's score. + + Arguments: + new_position (int, int): The new position. + game (Game): A reference to the current game. + growing (bool): (Default False) When True, the snake needs to + add a new segment. + """ + old_position = self.position + self.position = new_position + if self.next_segment: + self.next_segment.move(old_position, game, growing=growing) + elif growing: + self.next_segment = TrailSegment(self.segment_id + 1, old_position, self.player_number) + game.add_agent(self.next_segment) + \ No newline at end of file diff --git a/Tron/__pycache__/Bike.cpython-311.pyc b/Tron/__pycache__/Bike.cpython-311.pyc new file mode 100644 index 0000000..ed9ea92 Binary files /dev/null and b/Tron/__pycache__/Bike.cpython-311.pyc differ diff --git a/Tron/__pycache__/Trail.cpython-311.pyc b/Tron/__pycache__/Trail.cpython-311.pyc new file mode 100644 index 0000000..a54d2a3 Binary files /dev/null and b/Tron/__pycache__/Trail.cpython-311.pyc differ diff --git a/Tron/__pycache__/bike.cpython-311.pyc b/Tron/__pycache__/bike.cpython-311.pyc new file mode 100644 index 0000000..a8aa030 Binary files /dev/null and b/Tron/__pycache__/bike.cpython-311.pyc differ diff --git a/Tron/__pycache__/trail.cpython-311.pyc b/Tron/__pycache__/trail.cpython-311.pyc new file mode 100644 index 0000000..83d9fff Binary files /dev/null and b/Tron/__pycache__/trail.cpython-311.pyc differ diff --git a/Tron/nav_game.py b/Tron/nav_game.py new file mode 100644 index 0000000..a52a213 --- /dev/null +++ b/Tron/nav_game.py @@ -0,0 +1,18 @@ +# cd ~/Desktop/making_with_code/mwc1/unit3/project_game/Tron +# python nav_game.py + + +from random import randint +from retro.game import Game +from Bike import Bike + +if __name__ == '__main__': + # Initialize Player 1: Player #1, starting at position (5, 8), moving RIGHT + p1 = Bike(player_number=1, start_position=(5, 8), start_direction=Bike.RIGHT) + + # Initialize Player 2: Player #2, starting at position (25, 8), moving LEFT + p2 = Bike(player_number=2, start_position=(25, 8), start_direction=Bike.LEFT) + + # Create and start the game with both bikes + game = Game([p1, p2], {"*": "Play on!"}, board_size=(32, 16), framerate=8) + game.play() \ No newline at end of file diff --git a/Tron_arcade/Bike.py b/Tron_arcade/Bike.py new file mode 100644 index 0000000..b866627 --- /dev/null +++ b/Tron_arcade/Bike.py @@ -0,0 +1,143 @@ +from Trail import TrailSegment + + + + + +class Bike: + + + + """An Agent representing the snake's head. When the game starts, you control + the snake head using the arrow keys. The Bike always has a direction, and + will keep moving in that direction every turn. When you press an arrow key, + you change the Bike's direction. + + Attributes: + name: "Snake head" + position: (0,0) + character: ``'v'`` Depending on the snake head's direction, its character + changes to ``'<'``, ``'^'``, ``'>'``, or ``'v'``. + next_segment: Initially ``None``, this is a reference to a SnakeBodySegment. + growing: When set to True, the snake will grow a new segment on its next move. + """ + RIGHT = (1, 0) + UP = (0, -1) + LEFT = (-1, 0) + DOWN = (0, 1) + next_segment = None + growing = False + turn_counter = 0 + GROW_INTERVAL = 5 # The bike will grow 1 segment longer every 5 turns. + + + + + def __init__(self, player_number, start_position, start_direction): + self.player_number = player_number + self.position = start_position + self.direction = start_direction + self.name = f"Bike {player_number}" + if self.player_number == 1: + self.color = "bright_blue" + else: + self.color = "bright_red" + + # Adjust starting character based on starting direction + if start_direction == self.RIGHT: self.character = '>' + elif start_direction == self.LEFT: self.character = '<' + elif start_direction == self.UP: self.character = '^' + elif start_direction == self.DOWN: self.character = 'v' + + + def play_turn(self, game): + """On each turn, the snake head uses its position and direction to figure out + its next position. If the snake head is able to move there (it's on the board and + not occuppied by part of the snake's body), it moves. + + Then, if the snake head is on the Apple, the Apple moves to a new random position + and ``growing`` is set to True. + + Now we need to deal with two situations. First, if ``next_segment`` is not None, there is + a SnakeBodySegment attached to the head. We need the body to follow the head, + so we call ``self.next_segment.move``, passing the head's old position + (this will be the body's new position), a reference to the game, and a value for + ``growing``. If the snake needs to grow, we need to pass this information along + the body until it reaches the tail--this is where the next segment will be attached. + + If there is no ``next_segment`` but ``self.growing`` is True, it's time to add + a body! We set ``self.next_segment`` to a new SnakeBodySegment, set its + position to the head's old position, and add it to the game. We also add 1 to the + game's score. + """ + # 1. Increment turn counter and check if it's time to grow + self.turn_counter += 1 + if self.turn_counter >= self.GROW_INTERVAL: + self.growing = True + self.turn_counter = 0 # Reset the counter for the next growth cycle + + + x, y = self.position + dx, dy = self.direction + if self.can_move((x+dx, y+dy), game): + self.position = (x+dx, y+dy) + if self.next_segment: + self.next_segment.move((x, y), game, growing=self.growing) + elif self.growing: + self.next_segment = TrailSegment(1, (x, y), self.player_number) + game.add_agent(self.next_segment) + self.growing = False + else: + game.end() + + + def handle_keystroke(self, keystroke, game): + """Checks whether one of the arrow keys has been pressed. + If so, sets the Bike's direction and character. + """ + + + x, y = self.position + # --- PLAYER 1 CONTROLS (Arrow Keys) --- + if self.player_number == 1: + if keystroke.name == "d" and self.direction != self.LEFT: + self.direction = self.RIGHT + self.character = '>' + elif keystroke.name == "w" and self.direction != self.DOWN: + self.direction = self.UP + self.character = '^' + elif keystroke.name == "a" and self.direction != self.RIGHT: + self.direction = self.LEFT + self.character = '<' + elif keystroke.name == "s" and self.direction != self.UP: + self.direction = self.DOWN + self.character = 'v' + + # --- PLAYER 2 CONTROLS (WASD Keys) --- + elif self.player_number == 2: + + key_name = str(keystroke) + + if keystroke == "6" and self.direction != self.LEFT: + self.direction = self.RIGHT + self.character = '>' + elif keystroke == "8" and self.direction != self.DOWN: + self.direction = self.UP + self.character = '^' + elif keystroke == "4" and self.direction != self.RIGHT: + self.direction = self.LEFT + self.character = '<' + elif keystroke == "2" and self.direction != self.UP: + self.direction = self.DOWN + self.character = 'v' + + + def can_move(self, position, game): + on_board = game.on_board(position) + empty = game.is_empty(position) + return on_board and empty +''' + def is_on_apple(self, position, game): + apple = game.get_agent_by_name("Apple") + return apple.position == position +''' \ No newline at end of file diff --git a/Tron_arcade/Trail.py b/Tron_arcade/Trail.py new file mode 100644 index 0000000..eff403c --- /dev/null +++ b/Tron_arcade/Trail.py @@ -0,0 +1,62 @@ + + + + + +class TrailSegment: + """Finally, we need an Agent for the snake's body segments. + SnakeBodySegment doesn't have ``play_turn`` or ``handle_keystroke`` methods because + it never does anything on its own. It only moves when the Bike, or the previous + segment, tells it to move. + + Arguments: + segment_id (int): Keeps track of how far back this segment is from the head. + This is used to give the segment a unique name, and also to keep track + of how many points the player earns for eating the next apple. + position (int, int): The initial position. + + Attributes: + character: '*' + next_segment: Initially ``None``, this is a reference to a TrailSegment + when this segment is not the last one in the snake's Trail. + + """ + character = '*' + next_segment = None + + def __init__(self, segment_id, position, player_number): # Added player_number + self.segment_id = segment_id + self.player_number = player_number + # Give it a completely unique name per player + self.name = f"P{player_number} Trail segment {segment_id}" + self.position = position + if self.player_number == 1: + self.color = "bright_blue" + else: + self.color = "bright_red" + + def move(self, new_position, game, growing=False): + """When Bike moves, it sets off a chain reaction, moving all its + Trail segments. Whenever the head or a Trail segment has another segment + (``next_segment``), it calls that segment's ``move`` method. + + This method updates the TrailSegment's position. Then, if + ``self.next_segment`` is not None, calls that segment's ``move`` method. + If there is no next segment and ``growing`` is True, then we set + ``self.next_segment`` to a new SnakeBodySegment in this segment's old + position, and update the game's score. + + Arguments: + new_position (int, int): The new position. + game (Game): A reference to the current game. + growing (bool): (Default False) When True, the snake needs to + add a new segment. + """ + old_position = self.position + self.position = new_position + if self.next_segment: + self.next_segment.move(old_position, game, growing=growing) + elif growing: + self.next_segment = TrailSegment(self.segment_id + 1, old_position, self.player_number) + game.add_agent(self.next_segment) + \ No newline at end of file diff --git a/Tron_arcade/__pycache__/Bike.cpython-311.pyc b/Tron_arcade/__pycache__/Bike.cpython-311.pyc new file mode 100644 index 0000000..5518f71 Binary files /dev/null and b/Tron_arcade/__pycache__/Bike.cpython-311.pyc differ diff --git a/Tron_arcade/__pycache__/Trail.cpython-311.pyc b/Tron_arcade/__pycache__/Trail.cpython-311.pyc new file mode 100644 index 0000000..2a7d714 Binary files /dev/null and b/Tron_arcade/__pycache__/Trail.cpython-311.pyc differ diff --git a/Tron_arcade/__pycache__/bike.cpython-311.pyc b/Tron_arcade/__pycache__/bike.cpython-311.pyc new file mode 100644 index 0000000..a8aa030 Binary files /dev/null and b/Tron_arcade/__pycache__/bike.cpython-311.pyc differ diff --git a/Tron_arcade/__pycache__/trail.cpython-311.pyc b/Tron_arcade/__pycache__/trail.cpython-311.pyc new file mode 100644 index 0000000..83d9fff Binary files /dev/null and b/Tron_arcade/__pycache__/trail.cpython-311.pyc differ diff --git a/Tron_arcade/nav_game.py b/Tron_arcade/nav_game.py new file mode 100644 index 0000000..a52a213 --- /dev/null +++ b/Tron_arcade/nav_game.py @@ -0,0 +1,18 @@ +# cd ~/Desktop/making_with_code/mwc1/unit3/project_game/Tron +# python nav_game.py + + +from random import randint +from retro.game import Game +from Bike import Bike + +if __name__ == '__main__': + # Initialize Player 1: Player #1, starting at position (5, 8), moving RIGHT + p1 = Bike(player_number=1, start_position=(5, 8), start_direction=Bike.RIGHT) + + # Initialize Player 2: Player #2, starting at position (25, 8), moving LEFT + p2 = Bike(player_number=2, start_position=(25, 8), start_direction=Bike.LEFT) + + # Create and start the game with both bikes + game = Game([p1, p2], {"*": "Play on!"}, board_size=(32, 16), framerate=8) + game.play() \ No newline at end of file diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..62ede7f --- /dev/null +++ b/poetry.lock @@ -0,0 +1,81 @@ +# This file is automatically @generated by Poetry 2.3.1 and should not be changed by hand. + +[[package]] +name = "ansicon" +version = "1.89.0" +description = "Python wrapper for loading Jason Hood's ANSICON" +optional = false +python-versions = "*" +groups = ["main"] +markers = "platform_system == \"Windows\"" +files = [ + {file = "ansicon-1.89.0-py2.py3-none-any.whl", hash = "sha256:f1def52d17f65c2c9682cf8370c03f541f410c1752d6a14029f97318e4b9dfec"}, + {file = "ansicon-1.89.0.tar.gz", hash = "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1"}, +] + +[[package]] +name = "blessed" +version = "1.28.0" +description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "blessed-1.28.0-py3-none-any.whl", hash = "sha256:51e386b8ec85a0ce2177ffd7269d0121218c380d793196d87333cba97271a79f"}, + {file = "blessed-1.28.0.tar.gz", hash = "sha256:91620abe30549a32720fb0d2359100247cb279f84c4974becd789aac4818695c"}, +] + +[package.dependencies] +jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""} +wcwidth = ">=0.5" + +[package.extras] +docs = ["Pillow", "Sphinx (>3)", "sphinx-paramlinks", "sphinx_rtd_theme", "sphinxcontrib-manpage"] + +[[package]] +name = "jinxed" +version = "1.3.0" +description = "Jinxed Terminal Library" +optional = false +python-versions = "*" +groups = ["main"] +markers = "platform_system == \"Windows\"" +files = [ + {file = "jinxed-1.3.0-py2.py3-none-any.whl", hash = "sha256:b993189f39dc2d7504d802152671535b06d380b26d78070559551cbf92df4fc5"}, + {file = "jinxed-1.3.0.tar.gz", hash = "sha256:1593124b18a41b7a3da3b078471442e51dbad3d77b4d4f2b0c26ab6f7d660dbf"}, +] + +[package.dependencies] +ansicon = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "retro-games" +version = "1.1.3" +description = "A simple framework for Terminal-based games" +optional = false +python-versions = "<4.0,>=3.10" +groups = ["main"] +files = [ + {file = "retro_games-1.1.3-py3-none-any.whl", hash = "sha256:4bdd27241b5cb3ee72e69a042d301ff58df2a2ade7e3c29400a538fa54e30148"}, + {file = "retro_games-1.1.3.tar.gz", hash = "sha256:4f91ff725e551820aa4e30c12c0264e2da41967ed34252122b7136bc2a8ed311"}, +] + +[package.dependencies] +blessed = ">=1.20.0,<2.0.0" + +[[package]] +name = "wcwidth" +version = "0.5.0" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "wcwidth-0.5.0-py3-none-any.whl", hash = "sha256:1efe1361b83b0ff7877b81ba57c8562c99cf812158b778988ce17ec061095695"}, + {file = "wcwidth-0.5.0.tar.gz", hash = "sha256:f89c103c949a693bf563377b2153082bf58e309919dfb7f27b04d862a0089333"}, +] + +[metadata] +lock-version = "2.1" +python-versions = ">=3.10,<4.0" +content-hash = "03cc38c17964eb2c920ecf014cbfcf966c0c719418a127947b33382f086a0a6e" diff --git a/pyproject.toml b/pyproject.toml index 2506d56..f4ac39a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ -[project] -name = "project-game" -version = "5.0.0" -description = "" -authors = [{ name = "Chris Proctor", email = "chris@chrisproctor.net" }] +[Tron] +name = "Tron" +version = "1.0.0" +description = "This is like a V.S. snake game. Needs two players. P1 is blue and P2 is red." +authors = [{ name = "Benjamin Potocki", email = "wpotocki@lockportschools.net" }] requires-python = ">=3.10,<4.0" readme = "README.md" license = { text = "MIT" }