From 5663a9352149694eb8f8682d896189d1eb1ab108 Mon Sep 17 00:00:00 2001 From: bpot Date: Fri, 12 Jun 2026 10:49:57 -0400 Subject: [PATCH] da thang --- .envrc | 1 + Snake/Bike.py | 98 ++++++++++++ Snake/Trail.py | 56 +++++++ Snake/__pycache__/bike.cpython-311.pyc | Bin 0 -> 5232 bytes Snake/__pycache__/trail.cpython-311.pyc | Bin 0 -> 3085 bytes Snake/nav_game.py | 67 ++++++++ Tron/Bike.py | 144 ++++++++++++++++++ Tron/Trail.py | 62 ++++++++ Tron/__pycache__/Bike.cpython-311.pyc | Bin 0 -> 6433 bytes Tron/__pycache__/Trail.cpython-311.pyc | Bin 0 -> 3151 bytes Tron/__pycache__/bike.cpython-311.pyc | Bin 0 -> 5232 bytes Tron/__pycache__/trail.cpython-311.pyc | Bin 0 -> 3085 bytes Tron/nav_game.py | 18 +++ Tron_arcade/Bike.py | 143 +++++++++++++++++ Tron_arcade/Trail.py | 62 ++++++++ Tron_arcade/__pycache__/Bike.cpython-311.pyc | Bin 0 -> 6419 bytes Tron_arcade/__pycache__/Trail.cpython-311.pyc | Bin 0 -> 3246 bytes Tron_arcade/__pycache__/bike.cpython-311.pyc | Bin 0 -> 5232 bytes Tron_arcade/__pycache__/trail.cpython-311.pyc | Bin 0 -> 3085 bytes Tron_arcade/nav_game.py | 18 +++ poetry.lock | 81 ++++++++++ pyproject.toml | 10 +- 22 files changed, 755 insertions(+), 5 deletions(-) create mode 100644 .envrc create mode 100644 Snake/Bike.py create mode 100644 Snake/Trail.py create mode 100644 Snake/__pycache__/bike.cpython-311.pyc create mode 100644 Snake/__pycache__/trail.cpython-311.pyc create mode 100644 Snake/nav_game.py create mode 100644 Tron/Bike.py create mode 100644 Tron/Trail.py create mode 100644 Tron/__pycache__/Bike.cpython-311.pyc create mode 100644 Tron/__pycache__/Trail.cpython-311.pyc create mode 100644 Tron/__pycache__/bike.cpython-311.pyc create mode 100644 Tron/__pycache__/trail.cpython-311.pyc create mode 100644 Tron/nav_game.py create mode 100644 Tron_arcade/Bike.py create mode 100644 Tron_arcade/Trail.py create mode 100644 Tron_arcade/__pycache__/Bike.cpython-311.pyc create mode 100644 Tron_arcade/__pycache__/Trail.cpython-311.pyc create mode 100644 Tron_arcade/__pycache__/bike.cpython-311.pyc create mode 100644 Tron_arcade/__pycache__/trail.cpython-311.pyc create mode 100644 Tron_arcade/nav_game.py create mode 100644 poetry.lock 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 0000000000000000000000000000000000000000..a8aa030d216f0838b5b19b8ab782ac1addf93ae8 GIT binary patch literal 5232 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 UKa*wb`u6tUV*Wqxcq=yjAA^KTg8%>k literal 0 HcmV?d00001 diff --git a/Snake/__pycache__/trail.cpython-311.pyc b/Snake/__pycache__/trail.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83d9fffa37966dfddfe3f389a942b6f7dabb04b5 GIT binary patch literal 3085 zcma)8O>Y}T7@qY<^U)1$X%H#>$dDo>u2P#ql}b?sDpV~68VMx=DVN>N?l|6Lz2nZV z>n2L29D1lwB{+bJgphJT1yl|_aNyXV(4a^}mN;?ZW>ii+@w~I%O`HUY@p|m}dgpnc zciw0AhoPZChVuT`g{9*IjQvTCv=q93o^$+p$a3sD^VmJ+8IN*|J;paF^UTZ5vQpkn zJLoqZeLjK4Lnhd~;j#IgXUyll++=rXGv@oeJZ$v0kIsh9vUpE= zE3;y;F2dLu$uoA%51k-bndB|OLm@owg#5}PMtM~#9@hkqXxVtg7qF5?$h-=b=ec?LINNBr$ z3^2Ea()IvpC9e75B9|fevSmrlkG=mjhm$ya4TQw1Cv>MR|!to|)L&D!s;aBlRWWz4zv9b{Z5cgD0hjAW92V2V-Zbfc-)!;iejOr`S`i=r@=z^SO zQPDQr#<>|6`H>Y$J8D0lLiLcX8EeeS20dfV_?CT_L!Xg$u2CyZR-`wQFgLS$Tzk-y zOuUqD5AK|?c7cN3?oR`N(LyAGsyYPAsvlKEIN=_A~vbaDH&F9jQyb8SZViL76sR`R!{8Z zxttE2r2WsLT4&p@y>Y+r;K=sy)Q{($4Nu`gb6|Uf<7enTKF=|YU2{{hqgD}L&EgsG z1Qyv6_3CoB(90>tGA`BV?$$=eYPyzw*9u@f|FiK3_8-$8x){tW%(At-`ZVrK`!JU+ zWvIN|DhAdHz0%to$qmB2uk6P32v{Fycn!9eTcUXB;^pt;?&MCS%>#B{9b(MQySdAl zLwM<1Dmqhe<1GYn>niD~GBxa~g)G~V$w!J%-ZM&qAx!9Og$03mVs=@VP+oaT)-gi}l z(pIZratrWg!*d`ZIz#uKK^RGMqKriXj{4Odm9}lll5#H~Qdd#{5|&B+zkuynyip|_ z3X(xa5}E8eq@~!l7nN**X?TSxbE=6wup*?(6yeEuIvAQ3v{1D6iCQ92J2D2xW#DDj zQWBE;AYn`sMk$TCkt>zh#qU8^8u5;;t<=^&l_y;3V6QyVE_~uTYFva@dIcKJbGNA= z*fFPhdsZfF@reZ~11z4nDymL1i1{^KYNEvTQO{URUOa$O;N<{ZW&RU(DvpQSki1Aw z*{<8GWVHLb!TF1_vR%}y%#`}Hg0{`w$E01Lqp6T=Op9!L0H!U6-h!|$#(^vq6<*;O zE!*L&T_6|LOL_nS%E*jJEi^<$uYl@hRI9J-J_lt^X$~7IhAy7>LL8^^ufB`LYV+uGOppJ5?2P@R+iNsw5+=Hns~Xh+NNdQ zYC1u8q|dTE>7siedmm88U_l+GipcqiX_EU!>Af#$A;H$ zY#)Dh{o_s{Uwj?N(rR#|2%!H_B|DM*nUayj{4^Rn0ABQ8P8@khoxuQ|p6C*)PTnw# Uj`@}W+xx4(sqdcy2DIUS0XbY#(f|Me literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..ed9ea92915d9c82f69259bc8777fa20cea5d91b6 GIT binary patch literal 6433 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 literal 0 HcmV?d00001 diff --git a/Tron/__pycache__/Trail.cpython-311.pyc b/Tron/__pycache__/Trail.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a54d2a316950c026d39a9241acd83d347e3159a5 GIT binary patch literal 3151 zcma)8%ZnUE7_Xj3_BBfqU6c3-mWw7kVKRd#2#cr*At64Nz%B@T>F(*S+3B60u1R%I z#tkFvA%|5IFJc4{a*9ekc=YI>u#p9a20`%TZ6qGVlfSR}F|$boYiFywUcdU)_kH#I z`kTeYd4}@Q7cXr8J;&JZ)W}LHeR;s~a+?*{73Q*A%r)*77`uo6q--*`u+FMQC+nbR zHu_)%joVDHO~YlI1=rXtx`oY>Tih(WrCV(Ch&$sRxn*q5xJ6*h#+40ad;YrE>WUz; zj};la>;<;(@6`A}@IVNc+X26@g;Cy;ibrk1!@%x{vmtLvcZY|`(y-3wIm$YXUBo~N z$z3VJ;B3U(_6@-;tLNK0X4F@KWpTh+R@)9-Uzi=S6GlpQ1p2!oYD*XR!m<0I(70X% zGB{toZT8zSU`wg@!ai(W_6XfLAPQ{sjv`=Q26 zsn>WUd_M#bkEC9Wv*-yI)K;JD60RnPqXVXkOwZ*jUJzAR`8z`NLLMpG>2TTNZ8_jA zTk$5f!7|L2aJ;sZ>}n!yVY_v`34v1CpsD!b#4Zup@?bD+?!>~}=Ka9C-iKH0E=~ly zaoZ0i&Fz3f%HR-YN~a5Z@ty=-@FXk12{5IwRRBsbjj$uKCXEH+gNWO`o-b0561ScV zy~u;H>Bu#noO=Vay#W2TpHHZ#hKnNQHT#hWS93m2+lGlEp;r0Xb7%8z+Rsdly2`I6 zc<`cSt;qn<0Pm!RvAGg0p+w-oE)wRL4&5A&=%&6uZ2CaLzo6{fAq5I?*X=BtHQHg9 zXwcX=x8`J5ldc-Q=#@rK$!+08<`#BrY$zF^ zf*jR*JMpY(QgE5(&8MdQT+h0nrOnq-?XuA`FYc8-IXXIhZm)DO`^;}k7r$KGU%H6j z58KHT!*iok9FN7(!qJ0;(|3;lys*5#usnMD%-*F>-rmFCZ%@CJy*>aeyL`y$W%OvL zkMRPhvu&EA%ZH_hLSV|7>iKEc-pSpct)=I%gkUIsZ`=j`y*wlgMhZPFsyCyV$!wra z0-|s;SV->7OBV^1goW;ZYSv?iFJCrvuQ{lArwzy zipu+P#1+e$mJ!RUYHkj;Cc(3brcQ83T9!rmAZJu@I{W~T z-HSRF2prREO_GCU(G{s5CPSi5;zN2?fZ6!J~OwtK&pLad7FoIa+3fBn>6j(#E2jjJcsBm6)>a z<1#7P99x?i)+5P|6Vwp7jSs)^cC_%#A)6`D-&z+m8O(F7Oz|q zExYeW{4#Q>sOn&xSTXt30ZW0;5!fm}KXIpGyGX)xiY&sWl4jM2XHw@Vy25MK8LgXf zWja3M62+s!^Z+F2QR=~>iK*feolGt10r(}iVMt1#nWy2DRV?XvMQJN4Y>AMRB~r$|K;eSB`rN^|v5<=8>x^e>g=pDW9EUjJd~ z$H9JO`F`cfLFLMR_8ToOjagx?{wuG2yYapGQ7n7G~;>G>`J$fPee1WnCA7q z?WZF%rs+xt-E;Y;g?b7I>Nr(&^6!|2OiZCIOclvs_#Ud={BK-1R-PR*s+QUDrQNHe zCr|FaJ1)(Y&x~1Koj6$r(f_EDod|!eY9#LDXiNzFGy8gSkT=u|7$BJqUqdx68ip~h Syk-FV(dtj?`|B|S8u(u-!e$l# literal 0 HcmV?d00001 diff --git a/Tron/__pycache__/bike.cpython-311.pyc b/Tron/__pycache__/bike.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8aa030d216f0838b5b19b8ab782ac1addf93ae8 GIT binary patch literal 5232 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 UKa*wb`u6tUV*Wqxcq=yjAA^KTg8%>k literal 0 HcmV?d00001 diff --git a/Tron/__pycache__/trail.cpython-311.pyc b/Tron/__pycache__/trail.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83d9fffa37966dfddfe3f389a942b6f7dabb04b5 GIT binary patch literal 3085 zcma)8O>Y}T7@qY<^U)1$X%H#>$dDo>u2P#ql}b?sDpV~68VMx=DVN>N?l|6Lz2nZV z>n2L29D1lwB{+bJgphJT1yl|_aNyXV(4a^}mN;?ZW>ii+@w~I%O`HUY@p|m}dgpnc zciw0AhoPZChVuT`g{9*IjQvTCv=q93o^$+p$a3sD^VmJ+8IN*|J;paF^UTZ5vQpkn zJLoqZeLjK4Lnhd~;j#IgXUyll++=rXGv@oeJZ$v0kIsh9vUpE= zE3;y;F2dLu$uoA%51k-bndB|OLm@owg#5}PMtM~#9@hkqXxVtg7qF5?$h-=b=ec?LINNBr$ z3^2Ea()IvpC9e75B9|fevSmrlkG=mjhm$ya4TQw1Cv>MR|!to|)L&D!s;aBlRWWz4zv9b{Z5cgD0hjAW92V2V-Zbfc-)!;iejOr`S`i=r@=z^SO zQPDQr#<>|6`H>Y$J8D0lLiLcX8EeeS20dfV_?CT_L!Xg$u2CyZR-`wQFgLS$Tzk-y zOuUqD5AK|?c7cN3?oR`N(LyAGsyYPAsvlKEIN=_A~vbaDH&F9jQyb8SZViL76sR`R!{8Z zxttE2r2WsLT4&p@y>Y+r;K=sy)Q{($4Nu`gb6|Uf<7enTKF=|YU2{{hqgD}L&EgsG z1Qyv6_3CoB(90>tGA`BV?$$=eYPyzw*9u@f|FiK3_8-$8x){tW%(At-`ZVrK`!JU+ zWvIN|DhAdHz0%to$qmB2uk6P32v{Fycn!9eTcUXB;^pt;?&MCS%>#B{9b(MQySdAl zLwM<1Dmqhe<1GYn>niD~GBxa~g)G~V$w!J%-ZM&qAx!9Og$03mVs=@VP+oaT)-gi}l z(pIZratrWg!*d`ZIz#uKK^RGMqKriXj{4Odm9}lll5#H~Qdd#{5|&B+zkuynyip|_ z3X(xa5}E8eq@~!l7nN**X?TSxbE=6wup*?(6yeEuIvAQ3v{1D6iCQ92J2D2xW#DDj zQWBE;AYn`sMk$TCkt>zh#qU8^8u5;;t<=^&l_y;3V6QyVE_~uTYFva@dIcKJbGNA= z*fFPhdsZfF@reZ~11z4nDymL1i1{^KYNEvTQO{URUOa$O;N<{ZW&RU(DvpQSki1Aw z*{<8GWVHLb!TF1_vR%}y%#`}Hg0{`w$E01Lqp6T=Op9!L0H!U6-h!|$#(^vq6<*;O zE!*L&T_6|LOL_nS%E*jJEi^<$uYl@hRI9J-J_lt^X$~7IhAy7>LL8^^ufB`LYV+uGOppJ5?2P@R+iNsw5+=Hns~Xh+NNdQ zYC1u8q|dTE>7siedmm88U_l+GipcqiX_EU!>Af#$A;H$ zY#)Dh{o_s{Uwj?N(rR#|2%!H_B|DM*nUayj{4^Rn0ABQ8P8@khoxuQ|p6C*)PTnw# Uj`@}W+xx4(sqdcy2DIUS0XbY#(f|Me literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5518f71a4829af30572b3016ebfdf93fd49af2c6 GIT binary patch literal 6419 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 literal 0 HcmV?d00001 diff --git a/Tron_arcade/__pycache__/Trail.cpython-311.pyc b/Tron_arcade/__pycache__/Trail.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a7d7147d4c1b8fc9ef70df80a89371effeab001 GIT binary patch literal 3246 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 UKa*wb`u6tUV*Wqxcq=yjAA^KTg8%>k literal 0 HcmV?d00001 diff --git a/Tron_arcade/__pycache__/trail.cpython-311.pyc b/Tron_arcade/__pycache__/trail.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83d9fffa37966dfddfe3f389a942b6f7dabb04b5 GIT binary patch literal 3085 zcma)8O>Y}T7@qY<^U)1$X%H#>$dDo>u2P#ql}b?sDpV~68VMx=DVN>N?l|6Lz2nZV z>n2L29D1lwB{+bJgphJT1yl|_aNyXV(4a^}mN;?ZW>ii+@w~I%O`HUY@p|m}dgpnc zciw0AhoPZChVuT`g{9*IjQvTCv=q93o^$+p$a3sD^VmJ+8IN*|J;paF^UTZ5vQpkn zJLoqZeLjK4Lnhd~;j#IgXUyll++=rXGv@oeJZ$v0kIsh9vUpE= zE3;y;F2dLu$uoA%51k-bndB|OLm@owg#5}PMtM~#9@hkqXxVtg7qF5?$h-=b=ec?LINNBr$ z3^2Ea()IvpC9e75B9|fevSmrlkG=mjhm$ya4TQw1Cv>MR|!to|)L&D!s;aBlRWWz4zv9b{Z5cgD0hjAW92V2V-Zbfc-)!;iejOr`S`i=r@=z^SO zQPDQr#<>|6`H>Y$J8D0lLiLcX8EeeS20dfV_?CT_L!Xg$u2CyZR-`wQFgLS$Tzk-y zOuUqD5AK|?c7cN3?oR`N(LyAGsyYPAsvlKEIN=_A~vbaDH&F9jQyb8SZViL76sR`R!{8Z zxttE2r2WsLT4&p@y>Y+r;K=sy)Q{($4Nu`gb6|Uf<7enTKF=|YU2{{hqgD}L&EgsG z1Qyv6_3CoB(90>tGA`BV?$$=eYPyzw*9u@f|FiK3_8-$8x){tW%(At-`ZVrK`!JU+ zWvIN|DhAdHz0%to$qmB2uk6P32v{Fycn!9eTcUXB;^pt;?&MCS%>#B{9b(MQySdAl zLwM<1Dmqhe<1GYn>niD~GBxa~g)G~V$w!J%-ZM&qAx!9Og$03mVs=@VP+oaT)-gi}l z(pIZratrWg!*d`ZIz#uKK^RGMqKriXj{4Odm9}lll5#H~Qdd#{5|&B+zkuynyip|_ z3X(xa5}E8eq@~!l7nN**X?TSxbE=6wup*?(6yeEuIvAQ3v{1D6iCQ92J2D2xW#DDj zQWBE;AYn`sMk$TCkt>zh#qU8^8u5;;t<=^&l_y;3V6QyVE_~uTYFva@dIcKJbGNA= z*fFPhdsZfF@reZ~11z4nDymL1i1{^KYNEvTQO{URUOa$O;N<{ZW&RU(DvpQSki1Aw z*{<8GWVHLb!TF1_vR%}y%#`}Hg0{`w$E01Lqp6T=Op9!L0H!U6-h!|$#(^vq6<*;O zE!*L&T_6|LOL_nS%E*jJEi^<$uYl@hRI9J-J_lt^X$~7IhAy7>LL8^^ufB`LYV+uGOppJ5?2P@R+iNsw5+=Hns~Xh+NNdQ zYC1u8q|dTE>7siedmm88U_l+GipcqiX_EU!>Af#$A;H$ zY#)Dh{o_s{Uwj?N(rR#|2%!H_B|DM*nUayj{4^Rn0ABQ8P8@khoxuQ|p6C*)PTnw# Uj`@}W+xx4(sqdcy2DIUS0XbY#(f|Me literal 0 HcmV?d00001 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" }