Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding computer players #30

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Custom Ignores
data/saved
data/leaderboard

# Pycharm IDE
.idea
Expand Down
Binary file removed assets/images/menu/addslot-hover.png
Binary file not shown.
Binary file removed assets/images/menu/addslot.png
Binary file not shown.
Binary file added assets/images/menu/computer-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/menu/human-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"o": [10, 100, 50],
"c": [100, 50, 25], # default of settlement store (level 1)
}
MAP_WALLS = ["s", "w", "m", "o"] # used in path algorithms to distinguish where the player can move.


UNIT_SPECS = {
Expand Down
Empty file removed data/leaderboard
Empty file.
69 changes: 69 additions & 0 deletions project/game/breadth_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Ben-Ryder 2019

"""
Currently not true Breadth First Search Algorithm. It will not return a path to the target. Currently it can use a
breadth first style search to find the nearest occurrence of a value in a 2d-array grid based on a start position.
"""


class BreadthSearch:
def __init__(self, grid):
self.grid = grid
self.size = [len(self.grid), len(self.grid[0])]

def get_value(self, location):
return self.grid[location[0]][location[1]]

def get_nearest(self, position, target_value):
open_queue = [position]
closed_queue = []

while len(open_queue) > 0:
current_location = open_queue[0]

# See if current location is equal to the target value
if self.get_value(current_location) == target_value and current_location != position:
return current_location

# Add remaining neighbours to queue
neighbours = self.get_neighbours(current_location)
for location in neighbours:
if location not in closed_queue and location not in open_queue and \
location[0] in range(0, self.size[0]) and \
location[1] in range(0, self.size[1]): # stops infinite expansion
open_queue.append(location)

closed_queue.append(open_queue.pop(0)) # close the current location

return None # no occurrences of the value

def get_all(self, position, target_value):
open_queue = [position]
closed_queue = []
occurrences = []

while len(open_queue) > 0:
current_location = open_queue[0]

# See if current location is equal to the target value
if self.get_value(current_location) == target_value:
occurrences.append(current_location)

# Add remaining neighbours to queue
neighbours = self.get_neighbours(current_location)
for location in neighbours:
if location not in closed_queue and location not in open_queue and \
location[0] in range(0, self.size[0]) and \
location[1] in range(0, self.size[1]): # stops infinite expansion
open_queue.append(location)

closed_queue.append(open_queue.pop(0)) # close the current location

return occurrences

def get_neighbours(self, location): # CAN RETURN LOCATIONS OUT OF RANGE.
neighbours = []
for x in range(location[0] - 1, location[0] + 2):
for y in range(location[1] - 1, location[1] + 2):
neighbours.append([x, y])
return neighbours
69 changes: 51 additions & 18 deletions project/game/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ def __init__(self, control, display, model):
def run(self):
while self.state == "game":

if self.model_link.game_ended():
# Check for human defeat before game over as human defeat also means game over.
if self.model_link.humans_are_defeated():
if HumansDefeatedMessage not in [type(obj) for obj in self.persistent_guis]:
self.humans_defeated_message()
elif self.model_link.game_ended():
# game ended at deletion of game over message (called in GameOverMessage on its "ok")
if GameOverMessage not in [type(obj) for obj in self.persistent_guis]: # stops recalling when active
self.game_over_message()
Expand Down Expand Up @@ -177,10 +181,31 @@ def next_turn_message(self):

def game_over_message(self):
self.persistent_guis.clear() # To remove conquer message caused by taking last settlement
self.persistent_guis.insert(0, GameOverMessage(self,
"Game Over!", ["Well Done %s" % self.model_link.get_winner(),
"You conquered all the other players",
"and won the game!"]))

# Constructing Message Content
player = self.model_link.get_winner()
if player.get_control() == "human":
title = "Game Over!"
message = ["Well Done %s." % player.get_name(),
"You conquered all the other players",
"and won the game!"]
else:
title = "%s won!" % player.get_name()
message = ["They managed to conquer all the cities",
"and won the game.",
"Better luck next time!"]

self.persistent_guis.insert(0, GameOverMessage(self, title, message))

def humans_defeated_message(self):
self.persistent_guis.clear()

title = "All humans have been destroyed!"
message = ["The computer players have defeated ",
"all humans so the game is now over.",
"Better luck next time!"]

self.persistent_guis.insert(0, HumansDefeatedMessage(self, title, message))

def quit_message(self):
self.save()
Expand All @@ -194,9 +219,14 @@ def game_menu(self):
def next_turn(self):
self.save()
self.model_link.next_turn()
self.update()
self.save()

def update(self):
self.player_tracker.update_player()
self.update_camera_focus()
self.save()
self.mini_map.refresh()
self.game_view.world.refresh()

def save(self):
self.model_link.get_current_player().set_camera_focus(self.camera.get_position())
Expand Down Expand Up @@ -577,20 +607,19 @@ def check_clicked(self, mouse_x, mouse_y):
self.GUI.launch_settlement_menu(self.city_link.get_position(), [self.x, self.y])

elif self.upgrade_option.check_clicked():
if not self.city_link.at_max():
level = self.city_link.get_level() # must save level to detect change and display message
if self.city_link.afford_upgrade():
self.city_link.add_sub_level()
level = self.city_link.get_level() # must save level to detect change and display message
if self.city_link.can_upgrade():
self.city_link.add_sub_level()

if self.city_link.get_level() != level:
self.GUI.send_message("Level Up!", [
"%s has reached Level %s" % (self.city_link.get_name(), self.city_link.get_level()),
"It now earns %s ap per turn" % self.city_link.get_ap_value()])
if self.city_link.get_level() != level:
self.GUI.send_message("Level Up!", [
"%s has reached Level %s" % (self.city_link.get_name(), self.city_link.get_level()),
"It now earns %s ap per turn" % self.city_link.get_ap_value()])

self.update()
else:
self.GUI.send_message("Not Enough!", ["Sorry, you don't have enough ap to",
"upgrade this city."])
self.update()
else:
self.GUI.send_message("Not Enough!", ["Sorry, you don't have enough ap to",
"upgrade this city."])

return True
return False
Expand Down Expand Up @@ -727,6 +756,10 @@ def handle_click(self):
self.GUI.end_game()


class HumansDefeatedMessage(GameOverMessage):
pass


class NextTurnMessage(Message):
def handle_click(self):
if self.ok_button.check_clicked():
Expand Down
Loading