From 60a4069e871822a1d88664d8277fb0264169c085 Mon Sep 17 00:00:00 2001 From: Chris Mekelburg Date: Wed, 11 Dec 2024 22:34:22 -0500 Subject: [PATCH] almost done, just one issue with display score --- .DS_Store | Bin 6148 -> 6148 bytes gamefiles/__pycache__/board.cpython-312.pyc | Bin 4981 -> 7023 bytes gamefiles/__pycache__/man.cpython-312.pyc | Bin 2591 -> 2584 bytes gamefiles/__pycache__/mine.cpython-312.pyc | Bin 575 -> 617 bytes gamefiles/__pycache__/snack.cpython-312.pyc | Bin 576 -> 618 bytes gamefiles/board.py | 108 +++++++++----------- gamefiles/man.py | 50 ++------- gamefiles/mine.py | 3 + gamefiles/minecounter.py | 32 +----- gamefiles/nav_game.py | 12 +-- gamefiles/snack.py | 2 + 11 files changed, 70 insertions(+), 137 deletions(-) diff --git a/.DS_Store b/.DS_Store index 4ed28b7112922c872e821632758eff414ac98073..0e32e6aa2228159da0815e5a9c27a3377db6ee3f 100644 GIT binary patch delta 18 acmZoMXfc?uYU9Q*_K6Mbo7p-3@&f=#j0Z>n delta 20 ccmZoMXfc?uiji^S#xVAY4Q!j)IsWnk08ZxzNdN!< diff --git a/gamefiles/__pycache__/board.cpython-312.pyc b/gamefiles/__pycache__/board.cpython-312.pyc index 3d1da771dcbe20d6eabcad0590f38b8f950b472f..6257f33c7129021d8fd939f6b9c7289169d875dd 100644 GIT binary patch literal 7023 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 delta 2192 zcmZuyO>7fK6rR~1d;PnK<7{jv*aq^0lQjGk5~%n|(*!7$Qi+JFL_p+vjj>1^I=c}K zvK1eY8YEgs=Kz(Eiqs1cs_3EZu@bjR?IBT+uoluH^^{8+IsH+&wD0Zax9v#&=DoM` z-n{qC%=53^zqhu19|(8}jMIO-n@g*N{EW)lkXMBjbEfS;zfN>{R2lOOdnnOe!(QF3 zD>*?|bPu3c_W}C#Ku*X>!#;tWAbRjR(bb276J*#wS(B=r`DRxrMJ@kWzK|Wsj87EI zEL++)^I}_4hhR?hLg^h}3`=>F?uxMnht3R-gCc$(?QGtwpp+)RYu zN*8}bcORW3vve>eTJqJrZeFrnm$LcXCDZa2CdNjLLOOHVNJ*AtWJfQuFnF7j^SOi4o=IKB~t`S7z z5CD|6ZTn}#pAOF{u}Y-ZC@vp#ECeOnS zccrJ1)O;kh5N@CLJXZqK`6o(*|KNU;?^I64+$1zW|FUW>7=CbgTp#LdlpY@n^(7^~ z-KSAMzo#_u&$W8KpggN3lZ4gb?k-Cl9nY~2zTev$!i&g~00!o5C-9*+(b$ESivVz= z6#p&dhH^W6Cq5H@q9plu-ZN4RKJj#|#(xYw3z1pTA%L}lIVH1pzF%!=TMx}T!EDL- zf}Z`rlCWbKNP}H86kJv#!2_ThSpe8ii}5eR$N4X6HtBL#4g4*&xdK8=u&a2&XO1J%f)(Dv*>@ciHB4A?plGqUh2?3LV zPg~hx$G{3L!fs`o$U%p0fNQGVBfHYN?)1CkVB8?=sn$8KbuMUK(}CxT%D)W{ZK1Ab z3w0+kC|0$ZI`#%ycVkq{a+N$;Yw^F0wl(s)wN5&KeR2zZr_dL>?Z4=oZP?y6gzlT@ zOU|pw`{4z(^+EViViw3eIHw$BF}~99b+ePEWXUXD$YnP=x#db z68lJ|=pyCOZ`>T>Dw^V~JIa;mp$l6p@ljUSJ=$5xt zLxLQuDpc;NDsDNBY9p$Lmc7lgd*u|B<*2h4?l71NuvcJa*n62>g?(#!QN@d4xquvf ze9XR9mJeUk>ff(ZWC9n)i->mG@1TUw)h^|wa(HZ9pBT*^WoN;L4a>kymPJbGBB@&> z4U43Hk;E2B^9z5l?0G?ja$nh9pJ8D@I29$yFRP z+4zAfi%lm>a_TT;Fiv*k?B%xxihN*ZWMsU{pn8`4BO~K?CJsi$PYgh!h#M#d0BlSX A4*&oF diff --git a/gamefiles/__pycache__/snack.cpython-312.pyc b/gamefiles/__pycache__/snack.cpython-312.pyc index 2f281a5dd756cd780dc27590c63d869a8a40fdc6..f3b738e9e0135c5e3afadbbdd653e0f12bc2e5a8 100644 GIT binary patch delta 149 zcmX@W@`{D`G%qg~0}wd)MWyeW$SY|h1LRC+NMVR#U}A7*NMUSYNMTyd1X9Al5XD%@ ztjSU(5u935tWa8@P?C|VP@I>ToUM?bl$DxXve8ADk&$b11YLAn}2jk&*ExgWPu(4o1aK3_zlY8z>9_8&)BW delta 108 zcmaFGa)5>RG%qg~0}$9G1f|cK$SWx)0pv_)U}A7*NMUGUNMT&f1d?W8h+?Q@(q!J4 zB+SUjF}aMfoRM+zJ4SsVsm>&?C<0W#2*kzwK;i>4BO~K?CJsi$PYgh!h#M#d0Bms+ A5dZ)H diff --git a/gamefiles/board.py b/gamefiles/board.py index 3798bcd..b5ff948 100644 --- a/gamefiles/board.py +++ b/gamefiles/board.py @@ -2,14 +2,23 @@ from man import Man from snack import Snack from mine import Mine from random import shuffle -from minecounter import mine_counter -MAX_MINES = 50 +'''This class sets up the board initially, but also is responsible for adding snacks +and mines after they are consumed. Also increases mines as game gets more difficult.''' + +'''Values to call later, sets no more than 100 mines, and each list represent a level [score, num_mines], +which is called in mine_counter below.''' +MAX_MINES = 100 LEVELS = [ [5, 10], [10, 20], [15, 30], -[100, 40] +[20, 40], +[30,50], +[40,60], +[50,70], +[60,80], +[70,90] ] class Board: @@ -17,24 +26,19 @@ class Board: snack=False mine=False - def __init__(self,width, height,num_snacks): + def __init__(self,width, height,num_snacks,state): self.width = width self.height = height self.num_snacks = num_snacks - - #self.num_mines = num_mines - - def mine_counter(self,game): - current_score_dict = game.state - current_score = current_score_dict['Score'] - for limit, n in LEVELS: - if current_score < limit: - return n - return MAX_MINES + self.state = state - def get_agents(self,num_snacks): - num_mines = int(self.mine_counter) - print(num_mines) + def get_agents(self,num_snacks,state): + '''Sets up all the agents (snacks, mines, and man) in the game. First, determines mines needed by + calling the mine_counter function. Then generates a list of all posiitons, randomizes them, and assigns + the man to the first random position, the snacks to the next num_snack positions, and then the mines + to the required number of posiitons as specified in mine_counter. Returns these agents so they can be + positioned on the board.''' + num_mines = self.mine_counter(state) all_positions = self.get_all_positions() shuffle(all_positions) man= [Man(all_positions[0])] @@ -44,13 +48,28 @@ class Board: return agents def play_turn(self,game): - game.log(self.num_mines) + '''Checks after every turn (turn is length of time specified in retro) if the game needs snacks + or mines.''' + game.log(game.state['Score']) while self.game_needs_snacks(game): self.add_snack(game) while self.game_needs_mines(game): self.add_mine(game) - + + def mine_counter(self,state): + '''Determines how many mines should be in the game, based on the score of the game. Refers to the + LEVELS list above which contains the score and a correspponding number of mines. This function + puts a certain number of mines down based on the score. Currently, does not reduce the number + of mines when the score lowers after hitting a mine. Returns the number of mines needed. ''' + score = state['Score'] + for limit, n in LEVELS: + if score < limit: + return n + return MAX_MINES + def add_mine(self,game): + '''Adds a mine by finding all positions, randomizing them, and then adding a mine to the + first non-occupied position.''' all_positions=self.get_all_positions() shuffle(all_positions) index =0 @@ -60,14 +79,18 @@ class Board: game.add_agent(mine) def count_mines(self,game): + '''Counts the number of mines currently in the game.''' mines= [a for a in game.agents if a.mine] return len(mines) def game_needs_mines(self,game): - return self.count_mines(game) < self.num_mines - + '''Returns true when the number of mines in the game is less than the number of mines + required based on the score.''' + return self.count_mines(game) < self.mine_counter(game.state) def add_snack(self,game): + '''Adds a snack by finding all positions, randomizing them, and then adding a snack to the + first non-occupied position.''' all_positions=self.get_all_positions() shuffle(all_positions) index =0 @@ -77,52 +100,17 @@ class Board: game.add_agent(snack) def count_snacks(self,game): + '''Counts the number of snacks currently in the game.''' snacks= [a for a in game.agents if a.snack] return len(snacks) def game_needs_snacks(self,game): + '''Returns true when the number of snacks in the game is less than the number of snacks specified + in nav-game.py. In a future version, this number of snacks could vary as the game gets more difficult.''' return self.count_snacks(game) < self.num_snacks - - - ''' - def get_agents(self,num_snacks,num_mines): - man = self.get_man(num_snacks,num_mines) - snacks = self.get_snacks(num_snacks) - mines = self.get_mines(num_mines,num_snacks) - - agents = snacks + mines + man - return agents - - def get_man(self,num_snacks,num_mines): - - #man_location = [Man(all_positions[0])] - #return man_location - shuffle(all_positions) - for position in all_positions: - #if position in self.get_snacks(num_snacks): - # all_positions.remove(position) - if position in self.get_mines(num_mines,num_snacks): - all_positions.remove(position) - man_location = [Man(all_positions[0])] - return man_location - - def get_mines(self,num_mines, num_snacks): - all_positions = self.get_all_positions() - shuffle(all_positions) - for position in all_positions: - if position in self.get_snacks(num_snacks): - all_positions.remove(position) - mines = [Mine(p) for p in all_positions[1:num_mines+1]] - return mines - - def get_snacks(self,num_snacks): - all_positions = self.get_all_positions() - shuffle(all_positions) - snacks = [Snack(p) for p in all_positions[1:num_snacks+1]] - return snacks - ''' def get_all_positions(self): + '''Finds all coordinate positions in the game and adds them to a list of positions.''' positions=[] for i in range(self.width): for j in range(self.height): diff --git a/gamefiles/man.py b/gamefiles/man.py index bb9a9a4..5078fa4 100644 --- a/gamefiles/man.py +++ b/gamefiles/man.py @@ -1,12 +1,12 @@ from retro.agent import ArrowKeyAgent -#from retro.game import Game -#from helpers import add, get_occupant from retro.game import Game from random import shuffle from snack import Snack width=25 height=25 +'''Establishes keyboard arrow keys as direction vectors so each arrow key corresponds with movement +in a certain direction on the board.''' direction_vectors = { "KEY_RIGHT": (1, 0), "KEY_UP": (0, -1), @@ -15,7 +15,7 @@ direction_vectors = { } class Man: - character = "&" #try google asci full table?, + character = "&" color = "blue" snack=False mine=False @@ -23,18 +23,17 @@ class Man: def __init__(self,position): self.position = position - '''Describes how a keystroke is received''' - def handle_keystroke(self, keystroke, game): + '''Describes how a keystroke is received''' if keystroke.name in direction_vectors: vector = direction_vectors[keystroke.name] self.try_to_move(vector, game) - '''Checks if a space is avialable to move. Also adds 1 point if the space - contains a snack and then removes the snack. Deducts 10 points if the - space contains a mine. Checks that the score is not negative and if it - is, ends the game.''' def try_to_move(self, vector, game): + '''Checks if a space is avialable to move. Also adds 1 point if the space + contains a snack and then removes the snack. Deducts 10 points if the + space contains a mine. Checks that the score is not negative and if it + is, ends the game. Also stores the score so it can be used to determine if more mines are needed''' x,y = self.position vx,vy = vector future_position = (x +vx, y+vy) @@ -45,7 +44,6 @@ class Man: obstacle = agents[0] else: obstacle= None - if on_board: if obstacle: if obstacle.snack: @@ -61,38 +59,8 @@ class Man: else: self.position = future_position - def die(self,game): '''Indicates what happens when the game is over.''' - game.state["message"] = "Game Over" + game.state["Message"] = "Game Over" self.color = "black" game.end() - - - - -''' - def __init__(self, position): - self.position = position - - def handle_keystroke(self, keystroke, game): - if keystroke.name in direction_vectors: - vector = direction_vectors[keystroke.name] - self.try_to_move(vector, game) - - def try_to_move(self, vector, game): - """Tries to move the player in the direction of vector. - If the space is empty and it's on the board, then the move succeeds. - If the space is occupied, then if the occupant can be pushed, it gets - pushed and the move succeeds. Otherwise, the move fails. - """ - future_position = add(self.position, vector) - on_board = game.on_board(future_position) - obstacle = get_occupant(game, future_position) - if obstacle: - if obstacle.deadly: - self.die(game) - elif obstacle.handle_push(vector, game): - self.position = future_position - elif on_board: - self.position = future_position''' \ No newline at end of file diff --git a/gamefiles/mine.py b/gamefiles/mine.py index 480292a..ca10ae3 100644 --- a/gamefiles/mine.py +++ b/gamefiles/mine.py @@ -1,3 +1,6 @@ + +'''Sets up the mine object.''' + class Mine: character = "*" color = "green" diff --git a/gamefiles/minecounter.py b/gamefiles/minecounter.py index 2852778..11e3b2e 100644 --- a/gamefiles/minecounter.py +++ b/gamefiles/minecounter.py @@ -1,30 +1,2 @@ - - -MAX_MINES = 50 -LEVELS = [ -[5, 10], -[10, 20], -[15, 30], -[100, 40] -] - -def mine_counter(state): - current_score = state['Score'] - for limit, n in LEVELS: - if current_score < limit: - return n - return MAX_MINES - -''' - if score < 5: - num_mines = 10 - if 10 <= score <50: - num_mines = 20 - if 50 <= score <75: - num_mines = 30 - if 75 <= score <100: - num_mines = 40 - #else: - #num_mines = 50 - return num_mines - ''' \ No newline at end of file +'''Not currently in use, may use if minecounter needs to be more complex +but for now it is included in board.py''' \ No newline at end of file diff --git a/gamefiles/nav_game.py b/gamefiles/nav_game.py index 07a729f..f809190 100644 --- a/gamefiles/nav_game.py +++ b/gamefiles/nav_game.py @@ -1,18 +1,18 @@ from retro.game import Game from board import Board +'''This contains the main info for setting up and running the game.''' width = 25 height = 25 -state= {"Score":0} -score = state["Score"] +state= {"Score":00} num_snacks = 10 -board = Board(width,height,num_snacks) +board = Board(width,height,num_snacks,state) #sets the original board + game = Game( - board.get_agents(num_snacks), + board.get_agents(num_snacks,state), state, board_size = (width, height),debug=True ) -game.play() -#print(board.num_mines) \ No newline at end of file +game.play() \ No newline at end of file diff --git a/gamefiles/snack.py b/gamefiles/snack.py index f522c8e..629fa4e 100644 --- a/gamefiles/snack.py +++ b/gamefiles/snack.py @@ -1,3 +1,5 @@ +'''Sets up the snack object''' + class Snack: character = "o" color = "red"