Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don't worry, you can still create the pull request.
  • 3 commits
  • 14 files changed
  • 0 commit comments
  • 1 contributor
View
BIN  resources/Vera-Bold.ttf
Binary file not shown
View
13 risk/ai/bots.py
@@ -10,10 +10,15 @@ def __init__(self, title):
def choose_territories(self, board):
raise NotImplementedError
- def take_turn(self, game_master):
+ def reinforce(self, game_master):
self._deploy_reserves(game_master)
+
+ def attack(self, game_master):
self._attack_all_possible_targets(game_master)
+ def fortify(self, game_master):
+ pass
+
def deploy_reserves(self, game_master):
# evenly distributes
territories = game_master.player_territories(self)
@@ -41,8 +46,6 @@ def move_after_attack(self, game_master, origin_name, target_name):
risk.logger.debug("%s now has: %s armies" %(origin_name, origin_armies))
risk.logger.debug("%s now has: %s armies" %(target_name, destination_armies))
-
-
def _attack_all_possible_targets(self, game_master):
territories = game_master.player_territories(self)
for name, territory in territories.iteritems():
@@ -124,8 +127,10 @@ class IanRiskBot(BasicRiskBot):
def __init__(self, title):
BasicRiskBot.__init__(self, "group bot[%s]" % title)
- def take_turn(self, game_master):
+ def reinforce(self, game_master):
self.deploy_reserves(game_master)
+
+ def attack(self, game_master):
self.attack_others(game_master)
def attack_others(self, game_master):
View
3  risk/errors/game_master.py
@@ -7,7 +7,8 @@ def __init__(self, msg):
class NoSuchPlayerError(GameMasterError):
def __init__(self, attempted_player, number_of_players):
- GameMasterError.__init__("attempted to access player: %s but only have" \
+ GameMasterError.__init__(self,
+ "attempted to access player: %s but only have" \
" %s players" % (attempted_player, number_of_players))
class NotEnoughReserves(GameMasterError):
View
45 risk/game_master.py
@@ -12,11 +12,16 @@
from risk.errors.battle import *
from risk.player import HumonRiskPlayer
+REINFORCE = 'reinforce'
+ATTACK = 'attack'
+FORTIFY = 'fortify'
+UNDEFINED = 'undefined'
+
class GameMaster(object):
_RISK_RULE_STARTING_RESERVES = 40
_DEPLOYS_PER_TURN = 5
- def __init__(self, board, settings, num_players=5):
+ def __init__(self, board, settings, num_players=6):
MIN_PLAYERS = 2
MAX_PLAYERS = 6
if not MIN_PLAYERS <= num_players <= MAX_PLAYERS:
@@ -24,6 +29,7 @@ def __init__(self, board, settings, num_players=5):
num_players)
self.board = board
+ self.phase = UNDEFINED
# need to setup with settings later
self.ended = False
self.end_turn_callbacks = []
@@ -37,6 +43,7 @@ def __init__(self, board, settings, num_players=5):
'start_turn': [],
'end_action': [],
'end_turn': [],
+ 'end_phase': [],
'end_game': [],
}
self.add_end_action_callback(GameMaster.check_player_elimination)
@@ -92,6 +99,9 @@ def add_start_turn_callback(self, callback):
def add_end_action_callback(self, callback):
self.callbacks['end_action'].append(callback)
+ def add_end_phase_callback(self, callback):
+ self.callbacks['end_phase'].append(callback)
+
def generate_players(self, number_of_human_players, cli=False):
risk.logger.debug("Generating %s human players" % \
number_of_human_players)
@@ -156,12 +166,14 @@ def function_with_callback(self, *args):
def check_player_elimination(self, function, result, args):
if function == 'player_attack':
+ _PLAYER_ARG_INDEX = 0
if result == True:
for player in self.players:
if len(self.player_territories(player)) == 0:
self.eliminate_player(player)
+ self._recalculate_current_player_index(
+ args[_PLAYER_ARG_INDEX])
- # TODO fix select next player bug
def eliminate_player(self, player):
self.players.remove(player)
for _ in xrange(10):
@@ -172,6 +184,12 @@ def eliminate_player(self, player):
print "%s WINS!!!!" % self.current_player().name
self.end_game()
+ def set_phase(self, new_phase):
+ previous = self.phase
+ self.phase = new_phase
+ for callback in self.callbacks['end_phase']:
+ callback(self, previous, new_phase)
+
###########################################################################
## Game state queries
#
@@ -191,20 +209,29 @@ def _get_player_with_index(self, index):
try:
return self.players[index]
except IndexError:
- raise NoSuchPlayerError(index, self.number_of_players)
+ raise NoSuchPlayerError(index, self.number_of_players())
+ def _recalculate_current_player_index(self, current_player):
+ self._current_player = self.players.index(current_player)
###########################################################################
## Player actions
#
- @event_action
+ #@event_action
def player_take_turn(self):
self.call_start_turn_callbacks()
+ self.set_phase(UNDEFINED)
player = self._get_player_with_index(self._current_player)
player.reserves += len(self.player_territories(player))
- player.take_turn(self)
+ self.set_phase(REINFORCE)
+ player.reinforce(self)
+ self.set_phase(ATTACK)
+ player.attack(self)
+ self.set_phase(FORTIFY)
+ player.fortify(self)
+ self.set_phase(UNDEFINED)
- @event_action
+ #@event_action
def player_territories(self, player):
# O(n) lookup
player_territories = {}
@@ -213,6 +240,12 @@ def player_territories(self, player):
player_territories[name] = territory
return player_territories
+ def player_total_armies(self, player):
+ count = 0
+ for name, territory in self.player_territories(player).iteritems():
+ count += territory.armies
+ return count
+
@event_action
def player_attack(self, player, origin_name, target_name):
origin = self.player_territories(player)[origin_name]
View
24 risk/graphics/assets/clickable.py
@@ -67,3 +67,27 @@ def _normal_surface(self):
def _highlighted_surface(self):
return self.highlighted
+
+class ImageButtonAsset(ClickableAsset):
+ def __init__(self, x, y, normal_image, pressed_image):
+ normal_image = pygame.image.load(normal_image).convert_alpha()
+ pressed_image = pygame.image.load(pressed_image).convert_alpha()
+ width, height = normal_image.get_size()
+
+ ClickableAsset.__init__(self, x, y, width, height, "")
+ self.normal = normal_image
+ self.pressed = pressed_image
+ self.current = self.normal
+
+ def confirmed_click(self):
+ self.current = self.pressed
+ result = ClickableAsset.confirmed_click(self)
+ self.current = self.normal
+ return result
+
+ def _normal_surface(self):
+ return self.current
+
+ def _highlighted_surface(self):
+ return self.current
+
View
54 risk/graphics/assets/gameplay.py
@@ -0,0 +1,54 @@
+import pygame
+
+import risk
+
+import risk.graphics.assets
+
+from .base import PicassoAsset
+from .base import WHITE, LIGHT_BROWN
+from .text import TextAsset
+from .territory import TerritoryAsset
+
+DEFAULT_WIDTH = 250
+DEFAULT_HEIGHT = 140
+DEFAULT_X_OFFSET = 5
+COLOUR_BLOCK_WIDTH = 10
+
+class PlayersAsset(PicassoAsset):
+ def __init__(self, x, y, game_master):
+ PicassoAsset.__init__(self, None, x, y)
+
+ self.game_master = game_master
+ self.known_players = self.game_master.players
+ self.update()
+
+ def draw(self):
+ return self.surface
+
+ # TODO CLEANUP, SRSLY!
+ def update(self):
+ current_step = 0
+ stride = DEFAULT_HEIGHT / len(self.known_players)
+ new_view = pygame.Surface((DEFAULT_WIDTH, DEFAULT_HEIGHT),
+ pygame.SRCALPHA, 32)
+ for player in self.known_players:
+ if player == self.game_master.current_player():
+ highlight = pygame.Surface((new_view.get_width(),
+ stride - 5))
+ highlight.fill(LIGHT_BROWN)
+ new_view.blit(highlight, (0, current_step))
+ # account for player elimination
+ if player in self.game_master.players:
+ text_asset = TextAsset(0, 0, player.name, size=16, bold=True)
+ army_count_asset = TextAsset(0, 0, str(len(self.game_master.player_territories(player))), size=16,
+ bold=True)
+ colour_block = pygame.Surface((COLOUR_BLOCK_WIDTH, stride))
+ colour = TerritoryAsset.mapping[player]
+ colour_block.fill(colour)
+ new_view.blit(text_asset.draw(), (DEFAULT_X_OFFSET + COLOUR_BLOCK_WIDTH,
+ current_step))
+ new_view.blit(army_count_asset.draw(), (new_view.get_width() - army_count_asset.get_width() - 5, current_step))
+ new_view.blit(colour_block, (0, current_step - 5))
+ current_step += stride
+
+ self.surface = new_view
View
21 risk/graphics/assets/image.py
@@ -3,6 +3,9 @@
import risk
from risk.graphics.assets.base import PicassoAsset
+ON=True
+OFF=False
+
class ImageAsset(PicassoAsset):
def __init__(self, x, y, path, scale_x=1.0, scale_y=1.0):
self.path = path
@@ -12,3 +15,21 @@ def __init__(self, x, y, path, scale_x=1.0, scale_y=1.0):
(int(self.surface.get_width() * scale_x),
int(self.surface.get_height() * scale_y)))
PicassoAsset.__init__(self, self.surface, x, y)
+
+class ToggleImageAsset(ImageAsset):
+ def __init__(self, x, y, path, start_state=ON):
+ ImageAsset.__init__(self, x, y, path)
+ self.state = start_state
+ self.blank = pygame.Surface((0, 0), pygame.SRCALPHA, 32)
+
+ def draw(self):
+ if self.state == ON:
+ return self.surface
+ else:
+ return self.blank
+
+ def toggle(self):
+ self.state = not self.state
+
+ def set_state(self, state):
+ self.state = state
View
4 risk/graphics/assets/territory.py
@@ -23,7 +23,7 @@ def build_territory_asset(continent, territory, x, y):
def build_player_colour_mapping(players):
overflow_colour = base.BLACK
colours = [
- base.BROWN,
+ base.BLUE,
base.PURPLE,
base.ORANGE,
base.YELLOW,
@@ -120,7 +120,7 @@ def draw(self):
pygame.draw.circle(self.surface, base.BLACK,
(circle_radius, circle_radius),
circle_radius)
- pygame.draw.circle(self.surface, base.WHITE,
+ pygame.draw.circle(self.surface, base.LIGHT_BROWN,
(circle_radius, circle_radius),
circle_radius - 2)
font_surface = font.render(str(self.count), False,
View
5 risk/graphics/assets/text.py
@@ -9,14 +9,17 @@
class TextAsset(PicassoAsset):
- def __init__(self, x, y, msg, colour=assets.base.BLACK, size=32):
+ def __init__(self, x, y, msg, colour=assets.base.BLACK, size=32,
+ bold=False):
self.colour = colour
self.size = size
+ self.bold = bold
PicassoAsset.__init__(self, None, x, y)
self.render_text(msg)
def render_text(self, msg):
font = Font(_FONT, self.size)
+ font.set_bold(self.bold)
self.surface = font.render(msg, False, self.colour)
class CurrentPlayerAsset(TextAsset):
View
55 risk/graphics/graphics.py
@@ -12,8 +12,10 @@
import risk.graphics.assets.territory
import risk.graphics.assets.dialog
import risk.graphics.assets.image
+import risk.graphics.assets.gameplay
from risk.logger import *
+from risk.game_master import UNDEFINED, REINFORCE, ATTACK, FORTIFY
from risk.graphics import assets
from risk.graphics.event import wait_for_event, get_events
from risk.graphics.datastore import Datastore
@@ -111,11 +113,15 @@ def shutdown(*args):
def add_graphic_hooks(game_master):
game_master.add_start_turn_callback(check_picasso_liveness)
- game_master.add_start_turn_callback(show_human_player)
+ #game_master.add_start_turn_callback(show_human_player)
game_master.add_start_turn_callback(delay)
game_master.add_start_turn_callback(check_gui_quit_event)
game_master.add_end_turn_callback(check_gui_quit_event)
game_master.add_end_action_callback(release_control)
+ game_master.add_start_turn_callback(update_game_info_panel)
+ game_master.add_end_action_callback(update_game_info_panel)
+ game_master.add_end_phase_callback(update_current_phase)
+ #game_master.add_end_action_callback(delay)
def initialize_territories(picasso, game_master):
datastore = Datastore()
@@ -132,19 +138,43 @@ def initialize_territories(picasso, game_master):
build_player_colour_mapping(game_master.players)
def initialize_other_graphic_assets(picasso, game_master):
+ picasso = get_picasso()
datastore = Datastore()
- current_player_asset = assets.text.CurrentPlayerAsset(
- 100, 100, game_master)
- picasso.add_asset('4_current_player', current_player_asset)
- datastore.add_entry('current_player', current_player_asset)
+ #current_player_asset = assets.text.CurrentPlayerAsset(
+ # 100, 100, game_master)
+ #picasso.add_asset('4_current_player', current_player_asset)
+ #datastore.add_entry('current_player', current_player_asset)
feedback_asset = assets.text.TextAsset(100, 650,
'choose territory to attack')
datastore.add_entry('attack_feedback', feedback_asset)
-
+ game_info_asset = assets.gameplay.PlayersAsset(30, 550, game_master)
+ picasso.add_asset('999_ontop', game_info_asset)
+ datastore.add_entry('game_info', game_info_asset)
+ add_state_indicators(picasso, game_master)
+
+def add_state_indicators(picasso, game_master):
+ datastore = Datastore()
+ pos_x = 867
+ state_indicators = {
+ 'reinforce': (pos_x, 548),
+ 'attack': (pos_x, 600),
+ 'fortify': (pos_x, 652),
+ }
+ for state, coordinate in state_indicators.iteritems():
+ asset = assets.image.ToggleImageAsset(coordinate[0], coordinate[1],
+ "assets/art/gui/button_%s_highlight.png" % state)
+ datastore.add_entry(state, asset, 'states')
+ picasso.add_asset('999_ontop', asset)
+
def add_buttons(picasso):
datastore = Datastore()
- next_button = assets.clickable.ClickableAsset(
- 1000, 635, 120, 65, 'NEXT')
+ #next_button = assets.clickable.ClickableAsset(
+ # 1000, 635, 120, 65, 'NEXT')
+ next_button = assets.clickable.ImageButtonAsset(
+ 1000, 635,
+ 'assets/art/gui/button_next_up.png',
+ 'assets/art/gui/button_next_down.png'
+ )
datastore.add_entry('next', next_button, 'buttons')
for button in datastore.get_storage('buttons').values():
@@ -172,7 +202,7 @@ def is_human_player(game_master):
return isinstance(game_master.current_player(),
risk.player.HumonRiskPlayer)
-def delay(game_master):
+def delay(game_master, *args):
if not is_human_player(game_master):
time.sleep(1)
@@ -186,6 +216,13 @@ def check_gui_quit_event(game_master):
if event.type == pygame.QUIT:
game_master.end_game()
+def update_game_info_panel(*args):
+ Datastore().get_entry('game_info').update()
+
+def update_current_phase(game_master, previous, current):
+ for state, asset in Datastore().get_storage('states').iteritems():
+ asset.set_state(state == current)
+
def release_control(game_master, *args):
# release CPU for faster screen update
time.sleep(0)
View
6 risk/graphics/input.py
@@ -109,8 +109,8 @@ def reinforce_phase(player, game_master):
# state init vector
datastore = Datastore()
picasso = get_picasso()
- reserve_count_asset = ReserveCountAsset(player)
- picasso.add_asset(LAYER, reserve_count_asset)
+ #reserve_count_asset = ReserveCountAsset(player)
+ #picasso.add_asset(LAYER, reserve_count_asset)
# core state machine
disable_enemy_territories(player)
while player.reserves > 0:
@@ -126,7 +126,7 @@ def reinforce_phase(player, game_master):
reinforce_add_army_fail(player, game_master, territory)
# exit state
enable_all_clickables()
- picasso.remove_asset(LAYER, reserve_count_asset)
+ #picasso.remove_asset(LAYER, reserve_count_asset)
def reinforce_add_army(player, game_master, territory, number_of_armies=1):
game_master.player_add_army(player, territory.name, number_of_armies)
View
2  risk/graphics/picasso.py
@@ -96,7 +96,7 @@ def end(self):
self.ended = True
def get_fps_asset(self):
- asset = TextAsset(1050, 16, "%s FPS" % int(self.clock.get_fps()),
+ asset = TextAsset(1000, 16, "%s FPS" % int(self.clock.get_fps()),
(255, 255, 0), 32)
return asset
View
18 risk/graphics/player.py
@@ -20,21 +20,25 @@ class HumonGuiRiskPlayer(HumonRiskPlayer):
def __init__(self, name):
HumonRiskPlayer.__init__(self, name)
- def take_turn(self, game_master):
+ def reinforce(self, game_master):
#self.reserves = 0
#for territory in game_master.player_territories(self).values():
# territory.armies = 100
- picasso = get_picasso()
- phase_asset = TextAsset(400, 600, 'reinforcing...')
- picasso.add_asset(LAYER, phase_asset)
+ #picasso = get_picasso()
+ #phase_asset = TextAsset(400, 600, 'reinforcing...')
+ #picasso.add_asset(LAYER, phase_asset)
risk.logger.debug("starting reinforcement phase")
risk.graphics.input.handle_user_mouse_input(game_master,
reinforce_phase)
+
+ def attack(self, game_master):
risk.logger.debug("starting attack phase")
- phase_asset.render_text('attacking...')
+ #phase_asset.render_text('attacking...')
risk.graphics.input.handle_user_mouse_input(game_master, attack_phase)
+
+ def fortify(self, game_master):
risk.logger.debug("starting fortify phase")
- phase_asset.render_text('fortifying...')
+ #phase_asset.render_text('fortifying...')
risk.graphics.input.handle_user_mouse_input(game_master, fortify_phase)
risk.logger.debug("GUI player finished turn!")
- picasso.remove_asset(LAYER, phase_asset)
+ #picasso.remove_asset(LAYER, phase_asset)
View
13 risk/player/player.py
@@ -16,7 +16,13 @@ def __init__(self, name):
self.is_bot = False
self.reserves = 0
- def take_turn(self, game_master):
+ def reinforce(self, game_master):
+ raise NotImplementedError
+
+ def attack(self, game_master):
+ raise NotImplementedError
+
+ def fortify(self, game_master):
raise NotImplementedError
def choose_territory(self, available):
@@ -31,7 +37,7 @@ def __init__(self, name):
# Python sucks at this, base refers to base class
AbstractRiskPlayer.__init__(self, name)
- def take_turn(self, game_master):
+ def reinforce(self, game_master):
while self.reserves > 0:
print 'player has armies to deploy'
print "%s's territories: " % self.name
@@ -41,8 +47,11 @@ def take_turn(self, game_master):
game_master.player_territories(self))
commands.prompt_user(self, game_master,
reinforce_commands, HumonRiskPlayer._no_more_reserves)
+ def attack(self, game_master):
print "Attack phase, next to enter fortification phase"
commands.prompt_user(self, game_master, attack_commands)
+
+ def fortify(self, game_master):
print "Fortification phase, next to end turn"
commands.prompt_user(self, game_master, fortify_commands)

No commit comments for this range

Something went wrong with that request. Please try again.