almost done, just one issue with display score

This commit is contained in:
Chris Mekelburg 2024-12-11 22:34:22 -05:00
parent 5980c6bb22
commit 60a4069e87
11 changed files with 70 additions and 137 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -2,14 +2,23 @@ from man import Man
from snack import Snack from snack import Snack
from mine import Mine from mine import Mine
from random import shuffle 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 = [ LEVELS = [
[5, 10], [5, 10],
[10, 20], [10, 20],
[15, 30], [15, 30],
[100, 40] [20, 40],
[30,50],
[40,60],
[50,70],
[60,80],
[70,90]
] ]
class Board: class Board:
@ -17,24 +26,19 @@ class Board:
snack=False snack=False
mine=False mine=False
def __init__(self,width, height,num_snacks): def __init__(self,width, height,num_snacks,state):
self.width = width self.width = width
self.height = height self.height = height
self.num_snacks = num_snacks self.num_snacks = num_snacks
self.state = state
#self.num_mines = 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
def mine_counter(self,game): calling the mine_counter function. Then generates a list of all posiitons, randomizes them, and assigns
current_score_dict = game.state the man to the first random position, the snacks to the next num_snack positions, and then the mines
current_score = current_score_dict['Score'] to the required number of posiitons as specified in mine_counter. Returns these agents so they can be
for limit, n in LEVELS: positioned on the board.'''
if current_score < limit: num_mines = self.mine_counter(state)
return n
return MAX_MINES
def get_agents(self,num_snacks):
num_mines = int(self.mine_counter)
print(num_mines)
all_positions = self.get_all_positions() all_positions = self.get_all_positions()
shuffle(all_positions) shuffle(all_positions)
man= [Man(all_positions[0])] man= [Man(all_positions[0])]
@ -44,13 +48,28 @@ class Board:
return agents return agents
def play_turn(self,game): 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): while self.game_needs_snacks(game):
self.add_snack(game) self.add_snack(game)
while self.game_needs_mines(game): while self.game_needs_mines(game):
self.add_mine(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): 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() all_positions=self.get_all_positions()
shuffle(all_positions) shuffle(all_positions)
index =0 index =0
@ -60,14 +79,18 @@ class Board:
game.add_agent(mine) game.add_agent(mine)
def count_mines(self,game): def count_mines(self,game):
'''Counts the number of mines currently in the game.'''
mines= [a for a in game.agents if a.mine] mines= [a for a in game.agents if a.mine]
return len(mines) return len(mines)
def game_needs_mines(self,game): 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): 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() all_positions=self.get_all_positions()
shuffle(all_positions) shuffle(all_positions)
index =0 index =0
@ -77,52 +100,17 @@ class Board:
game.add_agent(snack) game.add_agent(snack)
def count_snacks(self,game): def count_snacks(self,game):
'''Counts the number of snacks currently in the game.'''
snacks= [a for a in game.agents if a.snack] snacks= [a for a in game.agents if a.snack]
return len(snacks) return len(snacks)
def game_needs_snacks(self,game): 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 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): def get_all_positions(self):
'''Finds all coordinate positions in the game and adds them to a list of positions.'''
positions=[] positions=[]
for i in range(self.width): for i in range(self.width):
for j in range(self.height): for j in range(self.height):

View File

@ -1,12 +1,12 @@
from retro.agent import ArrowKeyAgent from retro.agent import ArrowKeyAgent
#from retro.game import Game
#from helpers import add, get_occupant
from retro.game import Game from retro.game import Game
from random import shuffle from random import shuffle
from snack import Snack from snack import Snack
width=25 width=25
height=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 = { direction_vectors = {
"KEY_RIGHT": (1, 0), "KEY_RIGHT": (1, 0),
"KEY_UP": (0, -1), "KEY_UP": (0, -1),
@ -15,7 +15,7 @@ direction_vectors = {
} }
class Man: class Man:
character = "&" #try google asci full table?, character = "&"
color = "blue" color = "blue"
snack=False snack=False
mine=False mine=False
@ -23,18 +23,17 @@ class Man:
def __init__(self,position): def __init__(self,position):
self.position = position self.position = position
'''Describes how a keystroke is received'''
def handle_keystroke(self, keystroke, game): def handle_keystroke(self, keystroke, game):
'''Describes how a keystroke is received'''
if keystroke.name in direction_vectors: if keystroke.name in direction_vectors:
vector = direction_vectors[keystroke.name] vector = direction_vectors[keystroke.name]
self.try_to_move(vector, game) self.try_to_move(vector, game)
def try_to_move(self, vector, game):
'''Checks if a space is avialable to move. Also adds 1 point if the space '''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 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 space contains a mine. Checks that the score is not negative and if it
is, ends the game.''' is, ends the game. Also stores the score so it can be used to determine if more mines are needed'''
def try_to_move(self, vector, game):
x,y = self.position x,y = self.position
vx,vy = vector vx,vy = vector
future_position = (x +vx, y+vy) future_position = (x +vx, y+vy)
@ -45,7 +44,6 @@ class Man:
obstacle = agents[0] obstacle = agents[0]
else: else:
obstacle= None obstacle= None
if on_board: if on_board:
if obstacle: if obstacle:
if obstacle.snack: if obstacle.snack:
@ -61,38 +59,8 @@ class Man:
else: else:
self.position = future_position self.position = future_position
def die(self,game): def die(self,game):
'''Indicates what happens when the game is over.''' '''Indicates what happens when the game is over.'''
game.state["message"] = "Game Over" game.state["Message"] = "Game Over"
self.color = "black" self.color = "black"
game.end() 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'''

View File

@ -1,3 +1,6 @@
'''Sets up the mine object.'''
class Mine: class Mine:
character = "*" character = "*"
color = "green" color = "green"

View File

@ -1,30 +1,2 @@
'''Not currently in use, may use if minecounter needs to be more complex
but for now it is included in board.py'''
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
'''

View File

@ -1,18 +1,18 @@
from retro.game import Game from retro.game import Game
from board import Board from board import Board
'''This contains the main info for setting up and running the game.'''
width = 25 width = 25
height = 25 height = 25
state= {"Score":0} state= {"Score":00}
score = state["Score"]
num_snacks = 10 num_snacks = 10
board = Board(width,height,num_snacks) board = Board(width,height,num_snacks,state) #sets the original board
game = Game( game = Game(
board.get_agents(num_snacks), board.get_agents(num_snacks,state),
state, state,
board_size = (width, height),debug=True board_size = (width, height),debug=True
) )
game.play() game.play()
#print(board.num_mines)

View File

@ -1,3 +1,5 @@
'''Sets up the snack object'''
class Snack: class Snack:
character = "o" character = "o"
color = "red" color = "red"