示例#1
0
def fill_status_panel(player, log) -> None:
    log.messages.clear()
    #Fill out char stats
    entries = gen_status_panel(player)
    for entry in entries:
        log.add_message(Message(entry))
示例#2
0
    def place_entities(self, area, entities, max_monsters_per_area,
                       max_items_per_area, kolors, current_roster, current_mm):
        # Get a random number of monsters
        number_of_monsters = randint(0, max_monsters_per_area)
        number_of_items = randint(0, max_items_per_area)

        for i in range(0, number_of_monsters):
            #This and the one for items should be a function
            tile_clear = False
            x = 0
            y = 0
            while tile_clear != True:
                # Choose a random location in the area
                x = randint(area.x1 + 1, area.x2 - 1)
                y = randint(area.y1 + 1, area.y2 - 1)
                if self.tiles[x][y].blocked == False:
                    tile_clear = True

            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                #Roll for what monster to populate
                monster_name = roll_monster('dungeon', current_roster)
                #Pull in the dictionary entry for this monster
                m_loader = gen_monster(monster_name, current_mm)
                #Set the monster stats
                fighter_component = Fighter(hp=m_loader['hp'],
                                            protection=m_loader['protection'],
                                            power=m_loader['power'])
                #Set the ai
                if m_loader['ai_component'] == 'basic':
                    ai_component = BasicMonster()
                #Create the monster entity
                monster = Entity(x,
                                 y,
                                 m_loader['display_char'],
                                 kolors[m_loader['color']],
                                 m_loader['display_name'],
                                 blocks=True,
                                 fighter=fighter_component,
                                 render_order=RenderOrder.ACTOR,
                                 ai=ai_component)
                #Append the monster to the list of entities
                entities.append(monster)

        for i in range(0, number_of_items):
            #This and the one for monsters should be a function
            tile_clear = False
            x = 0
            y = 0
            while tile_clear != True:
                # Choose a random location in the area
                x = randint(area.x1 + 1, area.x2 - 1)
                y = randint(area.y1 + 1, area.y2 - 1)
                if self.tiles[x][y].blocked == False:
                    tile_clear = True

            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                item_chance = randint(0, 99)
                #Create the item entity
                if item_chance < 70:
                    item_component = Item(use_function=heal, amount=4)
                    item = Entity(x,
                                  y,
                                  '!',
                                  kolors['potion_violet'],
                                  'Healing Potion',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_chance < 80:
                    item_component = Item(
                        use_function=cast_fireball,
                        targeting=True,
                        targeting_message=Message(
                            'Left-click a target tile for the fireball, or right-click to cancel.',
                            kolors['targeting_cyan']),
                        damage=12,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  '?',
                                  kolors['scroll_amber'],
                                  'Fireball Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_chance < 90:
                    item_component = Item(
                        use_function=cast_confuse,
                        targeting=True,
                        targeting_message=Message(
                            'Left-click an enemy to confuse it, or right-click to cancel.',
                            kolors['targeting_cyan']))
                    item = Entity(x,
                                  y,
                                  '?',
                                  kolors['scroll_amber'],
                                  'Confusion Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                else:
                    item_component = Item(use_function=cast_lightning,
                                          damage=20,
                                          maximum_range=5)
                    item = Entity(x,
                                  y,
                                  '?',
                                  kolors['scroll_amber'],
                                  'Lightning Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)

                #Append the item to the list of entities
                entities.append(item)
示例#3
0
def kill_player(player):
    player.char = '%'
    player.color = libtcod.dark_red

    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD
示例#4
0
def kill_player(player):
    player.char = '%'
    player.color = 'red'

    return Message('You died!', 'red'), GameStates.PLAYER_DEAD
示例#5
0
 def exit_world_tile(self):
     self.engine.message_log.add_message(Message('There is nowhere to climb here', color_vars.warning))
示例#6
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    fov_algorithm = 'BASIC'
    fov_light_walls = True
    fov_radius = 10

    colors = {
        'dark_wall': (0, 0, 100),
        'dark_ground': (50, 50, 150),
        'light_wall': (130, 110, 50),
        'light_ground': (200, 180, 50),
        'white': (255, 255, 255),
        'black': (0, 0, 0),
        'light red': (255, 100, 100),
        'red': (255, 0, 0),
        'yellow': (255, 255, 0),
        'orange': (255, 127, 0),
        'green': (
            0,
            255,
            0,
        ),
        'light_red': (255, 114, 114),
        'darker_red': (127, 0, 0),
        'highlight': (199, 234, 70)
    }

    mech_component = Mech(hp=30, peak_momentum=6)
    weapon_component = Weapon(name="Laser",
                              damage=5,
                              min_targets=0,
                              max_targets=5,
                              color=colors.get('green'),
                              range=10)
    player = Entity(int(screen_width / 2),
                    int(screen_height / 2),
                    '@',
                    colors.get('white'),
                    "player",
                    mech=mech_component,
                    weapon=weapon_component)
    npc = Entity(int(screen_width / 2 - 5), int(screen_height / 2), '@',
                 colors.get('yellow'), "NPC")
    cursor_component = Cursor()
    cursor = Entity(
        -1, -1, ' ', colors.get('red'), "cursor", cursor=cursor_component
    )  # The ' ' isn't actually "nothing". To have nothing, I would have to mess with a render order.
    entities = [npc, player, cursor]

    tdl.set_font('arial10x10.png', greyscale=True, altLayout=True)

    root_console = tdl.init(screen_width, screen_height, title='MVP v0.0')
    con = tdl.Console(screen_width, screen_height)
    panel = tdl.Console(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    make_map(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    mouse_coordinates = (0, 0)

    game_state = GameStates.PLAYER_TURN
    previous_game_state = game_state
    turn_state = TurnStates.UPKEEP_PHASE

    fov_recompute = True

    while not tdl.event.is_window_closed():
        if fov_recompute:
            game_map.compute_fov(player.x,
                                 player.y,
                                 fov=fov_algorithm,
                                 radius=fov_radius,
                                 light_walls=fov_light_walls)

        render_all(con, panel, entities, game_map, fov_recompute, root_console,
                   message_log, screen_width, screen_height, bar_width,
                   panel_height, panel_y, mouse_coordinates, colors)

        tdl.flush()

        clear_all(con, entities)

        for event in tdl.event.get():
            if event.type == 'KEYDOWN':
                user_input = event
                break
            elif event.type == 'MOUSEMOTION':
                mouse_coordinates = event.cell
        else:
            user_input = None

        fov_recompute = False

        action = handle_keys(user_input, game_state)
        impulse = None  # This is to avoid logic problems.
        change_game_state = None  # This is to avoid logic problems.

        move = action.get('move')  # Attempt to move.
        impulse = action.get('impulse')  # Adjust mech impulse.
        next_turn_phase = action.get(
            'next turn phase')  # Move to the next phase.
        change_game_state = action.get(
            'change game state')  # Go to different game_state
        select = action.get(
            'select')  # A target has been selected via keyboard.
        exit = action.get('exit')  # Exit whatever screen is open.
        fullscreen = action.get('fullscreen')  # Set game to full screen.

        if exit:
            if game_state == GameStates.TARGETING:
                # Turn off cursor
                cursor.char = ' '
                cursor.x = -1
                cursor.y = -1

                fov_recompute = True
                game_state = previous_game_state

            else:
                return True

        if fullscreen:
            tdl.set_fullscreen(not tdl.get_fullscreen())

        if game_state == GameStates.PLAYER_TURN:
            # See game_states.py for the turn structure.
            # Turns order is reversed so ensure that the loop runs once for each
            if turn_state == TurnStates.POST_ATTACK_PHASE:
                # Reset map flags and remove targets.
                reset_flags(game_map)
                for x, y in player.weapon.targets:
                    erase_cell(con, x, y)
                turn_state = TurnStates.UPKEEP_PHASE
                game_state = GameStates.ENEMY_TURN

            if turn_state == TurnStates.ATTACK_PHASE:
                if change_game_state == GameStates.TARGETING:
                    # Turn on cursor.
                    cursor.char = 'X'
                    # If there were no previous targets, start on the player.
                    if len(player.weapon.targets) == 0:
                        cursor.x = player.x
                        cursor.y = player.y
                    else:
                        cursor.x, cursor.y = player.weapon.targets[-1]

                    fov_recompute = True
                    previous_game_state = game_state
                    game_state = GameStates.TARGETING

                if next_turn_phase:
                    turn_state = TurnStates.POST_ATTACK_PHASE

            if turn_state == TurnStates.PRE_ATTACK_PHASE:
                message_log.add_message(
                    Message('Begin ATTACK PHASE.', colors.get('white')))
                message_log.add_message(
                    Message(
                        'Press f to target. Press ESC to stop targeting. Enter to change phase.',
                        colors.get('orange')))
                fov_recompute = True

                turn_state = TurnStates.ATTACK_PHASE

            if turn_state == TurnStates.POST_MOVEMENT_PHASE:
                reset_flags(game_map)
                player.reset(
                )  # Reset the mech for the next turn. ### Move this to the post-attack phase
                fov_recompute = True

                turn_state = TurnStates.PRE_ATTACK_PHASE

            if turn_state == TurnStates.MOVEMENT_PHASE:
                if move:
                    dx, dy = move
                    if game_map.walkable[player.x + dx, player.y + dy]:
                        player.move(dx, dy)

                        fov_recompute = True

                if next_turn_phase and player.mech.has_spent_minimum_momentum(
                ):
                    turn_state = TurnStates.POST_MOVEMENT_PHASE
                elif next_turn_phase and not player.mech.has_spent_minimum_momentum(
                ):
                    message_log.add_message(
                        Message('Must spend more momentum.',
                                colors.get('red')))

            if turn_state == TurnStates.PRE_MOVEMENT_PHASE:
                if impulse is not None:
                    player.mech.impulse = impulse
                    turn_state = TurnStates.MOVEMENT_PHASE
                    message_log.add_message(
                        Message('Impulse set to {0}.'.format(impulse),
                                colors.get('orange')))
                    fov_recompute = True
                    highlight_legal_moves(player, game_map)

            if turn_state == TurnStates.UPKEEP_PHASE and game_state == GameStates.PLAYER_TURN:  # This is added to avoid starting the Upkeep Phase when the turn just ended.
                message_log.add_message(
                    Message('Begin PLAYER TURN.', colors.get('white')))
                message_log.add_message(
                    Message('Begin MOVEMENT PHASE.', colors.get('white')))
                message_log.add_message(
                    Message('Choose impulse. PAGEUP, PAGEDOWN or HOME.',
                            colors.get('orange')))
                turn_state = TurnStates.PRE_MOVEMENT_PHASE
                fov_recompute = True

        if game_state == GameStates.ENEMY_TURN:
            message_log.add_message(
                Message('Begin ENEMY TURN.', colors.get('white')))
            fov_recompute = True

            game_state = GameStates.PLAYER_TURN

        if game_state == GameStates.TARGETING:
            if move:
                dx, dy = move
                # Ensure the first target is in firing range.
                if len(player.weapon.targets) == 0:
                    if player.distance(cursor.x + dx,
                                       cursor.y + dy) <= player.weapon.range:
                        cursor.fly(dx, dy)
                        fov_recompute = True
                    else:
                        message_log.add_message(
                            Message('Out of range.', colors.get('red')))
                # Ensure that the next targets are adjacent to the previous target
                elif len(player.weapon.targets) > 0:
                    tar_x, tar_y = player.weapon.targets[
                        -1]  # Get the most recent target added.
                    if abs(tar_x -
                           (cursor.x + dx)) + abs(tar_y -
                                                  (cursor.y + dy)) <= 1:
                        cursor.fly(dx, dy)
                        fov_recompute = True
                    else:
                        message_log.add_message(
                            Message('Invalid target.', colors.get('red')))

            if select:
                if len(player.weapon.targets) < player.weapon.max_targets:
                    if set_targeted(
                            game_map, cursor.x, cursor.y
                    ):  # At the moment, this always returns True. In the future, this may change.
                        fov_recompute = True
                        player.weapon.targets.append((cursor.x, cursor.y))
                else:
                    message_log.add_message(
                        Message('Targeting failed.', colors.get('red')))
示例#7
0
    def place_entities(self, room, entities):
        '''Place monsters and items randomly into a room on the map.'''
        max_monsters_per_room = from_dungeon_level([[2, 1], [3, 4], [5, 6]],
                                                   self.dlevel)
        max_items_per_room = from_dungeon_level([[1, 1], [2, 4]], self.dlevel)
        number_of_monsters = randint(0, max_monsters_per_room)
        number_of_items = randint(0, max_items_per_room)

        monster_chances = {
            "orc": 80,
            "troll": from_dungeon_level([[15, 3], [30, 5], [60, 7]],
                                        self.dlevel)
        }
        item_chances = {
            "healing_potion": 35,
            "sword": from_dungeon_level([[5, 4]], self.dlevel),
            "shield": from_dungeon_level([[15, 8]], self.dlevel),
            "lightning_scroll": from_dungeon_level([[25, 4]], self.dlevel),
            "fireball_scroll": from_dungeon_level([[25, 6]], self.dlevel),
            "confusion_scroll": from_dungeon_level([[10, 2]], self.dlevel)
        }

        # place monsters
        for i in range(number_of_monsters):
            x, y = choice(room.coords)
            if not any([e for e in entities if e.x == x and e.y == y]):
                monster_choice = random_choice_from_dict(monster_chances)
                if monster_choice == "orc":
                    fighter_component = Fighter(hp=20,
                                                defense=0,
                                                power=4,
                                                xp=35)
                    ai_component = BasicMonster()
                    inv_component = Inventory(5)
                    soul_char = choice([".", "*", "+"])
                    soul_color = choice([tcod.red, tcod.orange, tcod.yellow])
                    m_soul = Soul(soul_char, soul_color)
                    m_name = "Orc" + str(len(entities))
                    monster = Entity(len(entities),
                                     x,
                                     y,
                                     'o',
                                     tcod.desaturated_green,
                                     m_name,
                                     blocks=True,
                                     soul=m_soul,
                                     fighter=fighter_component,
                                     ai=ai_component,
                                     inventory=inv_component,
                                     render_order=RenderOrder.ACTOR)
                else:
                    fighter_component = Fighter(hp=30,
                                                defense=2,
                                                power=8,
                                                xp=100)
                    ai_component = BasicMonster()
                    inv_component = Inventory(10)
                    soul_char = choice(["*", "+"])
                    soul_color = choice([tcod.orange, tcod.yellow, tcod.green])
                    m_soul = Soul(soul_char, soul_color)
                    m_name = "Troll" + str(len(entities))
                    monster = Entity(len(entities),
                                     x,
                                     y,
                                     'T',
                                     tcod.darker_green,
                                     m_name,
                                     blocks=True,
                                     soul=m_soul,
                                     fighter=fighter_component,
                                     ai=ai_component,
                                     inventory=inv_component,
                                     render_order=RenderOrder.ACTOR)

                entities.append(monster)

        # place items
        for i in range(number_of_items):
            x, y = choice(room.coords)
            if not any([e for e in entities if e.x == x and e.y == y]):
                item_choice = random_choice_from_dict(item_chances)
                if item_choice == "healing_potion":
                    item_component = Item(use_function=heal, amount=40)
                    item = Entity(len(entities),
                                  x,
                                  y,
                                  '!',
                                  tcod.violet,
                                  "Healing Potion",
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == "sword":
                    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                      power_bonus=3)
                    item = Entity(len(entities),
                                  x,
                                  y,
                                  "/",
                                  tcod.sky,
                                  "Sword",
                                  equippable=equippable_component)
                elif item_choice == "shield":
                    equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                                      defense_bonus=1)
                    item = Entity(len(entities),
                                  x,
                                  y,
                                  "[",
                                  tcod.dark_orange,
                                  "Shield",
                                  equippable=equippable_component)
                elif item_choice == "fireball_scroll":
                    msg_str = (f"Left-click a target tile for the fireball, "
                               f"or right-click to cancel.")
                    msg = Message(msg_str, tcod.light_cyan)
                    item_component = Item(use_function=cast_fireball,
                                          targeting=True,
                                          targeting_message=msg,
                                          damage=25,
                                          radius=3)
                    item = Entity(len(entities),
                                  x,
                                  y,
                                  "#",
                                  tcod.red,
                                  "Fireball Scroll",
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == "confusion_scroll":
                    msg_str = (f"Left-click an enemy to confuse it, "
                               f"or right-click to cancel")
                    msg = Message(msg_str, tcod.light_cyan)
                    item_component = Item(use_function=cast_confuse,
                                          targeting=True,
                                          targeting_message=msg)
                    item = Entity(len(entities),
                                  x,
                                  y,
                                  "#",
                                  tcod.light_pink,
                                  "Confusion Scroll",
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                else:
                    item_component = Item(use_function=cast_lightning,
                                          damage=40,
                                          max_range=5)
                    item = Entity(len(entities),
                                  x,
                                  y,
                                  "#",
                                  tcod.yellow,
                                  "Lightning Scroll",
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                entities.append(item)
示例#8
0
文件: engine.py 项目: nebiont/rogue
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants):
	# Intialize FOV map.
	fov_recompute = True # Recompute FOV after the player moves
	fov_map = initialize_fov(game_map)
	target_fov_map = initialize_fov(game_map)
	fov_map_no_walls = initialize_fov(game_map)


	# Capture keyboard and mouse input
	key = libtcod.Key()
	mouse = libtcod.Mouse()
	game_state = GameStates.PLAYERS_TURN
	previous_game_state = game_state

	# Store the item that the player used to enter targeting mode (ie lightning scroll). This is so that we know what item we need to remove from inventory etc.
	targeting_item = None
	cursor_radius = 1

	# For showing object descriptions
	description_recompute = True
	description_list = []
	description_index = 0	
	prev_mouse_y = None
	prev_mouse_x = None

	# Start music
	mixer.init()
	mixer.music.load(os.path.join(definitions.ROOT_DIR, 'data', 'music', 'bgm2.mp3'))
	#mixer.music.play(loops=-1)

	#Our main loop
	while not libtcod.console_is_window_closed():
		# Check for input
		libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)
		for animator in Animator.animators:
			animator.update()
		if Animator.blocking > 0:
			if not game_state == GameStates.BLOCKING_ANIMATION:
				previous_game_state = game_state
			game_state = GameStates.BLOCKING_ANIMATION

		if Animator.blocking == 0 and game_state == GameStates.BLOCKING_ANIMATION:
				game_state = previous_game_state

		# Recompute FOV
		if fov_recompute:
			recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'], constants['fov_algorithm'])
			recompute_fov(fov_map_no_walls, player.x, player.y, constants['fov_radius'], light_walls=False, algorithm=constants['fov_algorithm'])
		
	
		# Show object descriptions
		if description_recompute == True:

			for entity in entities:

				if (prev_mouse_x != mouse.cx) or (prev_mouse_y != mouse.cy):
					description_list = []
					description_index = 0
				if entity.x == mouse.cx and entity.y == mouse.cy:
					description_list.append(entity)
					prev_mouse_x = mouse.cx
					prev_mouse_y = mouse.cy

			
		if len(description_list) > 0:
			description_recompute = False
			# We need to check to see if the mouse position changed and then clear our description list if it did, otherwise it will keep growing
			if (prev_mouse_x != mouse.cx) or (prev_mouse_y != mouse.cy):
				description_list = []
				description_index = 0
				description_recompute = True
			if mouse.lbutton_pressed:
				description_index += 1
			if description_index > (len(description_list) - 1):
				description_index = 0


		
		# Draw our scene
		render_all(con, panel, mouse, entities, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], constants['colors'], game_state, description_list, description_index, cursor_radius, target_fov_map, fov_map_no_walls)
		fov_recompute = False
		libtcod.console_flush()

		# Clear our 'drawing consoles' so we dont leave a trail on the main console screen
		clear_all(con, entities)


		# Store input results
		action = handle_keys(key, game_state)
		mouse_action = handle_mouse(mouse)
		key = libtcod.Key()
		mouse = libtcod.Mouse()
		move = action.get('move')
		pickup = action.get('pickup')
		show_inventory = action.get('show_inventory')
		drop_inventory = action.get('drop_inventory')
		inventory_index = action.get('inventory_index')
		take_stairs = action.get('take_stairs')
		level_up = action.get('level_up')
		show_character_screen = action.get('show_character_screen')
		ability_1 = action.get('ability_1')
		exit = action.get('exit')
		fullscreen = action.get('fullscreen')
		left_click = mouse_action.get('left_click')
		right_click = mouse_action.get('right_click')
		


		#Instatiate our message queue for the players turn
		player_turn_results = []

		# Player Actions
		# Move
		if move and game_state == GameStates.PLAYERS_TURN:
			if not move == 'wait':
				dx, dy = move
				destination_x = player.x + dx
				destination_y = player.y + dy

				# Check to see if the location we want to move to is blocked by a wall or inhabited by a creature
				if not game_map.is_blocked(destination_x, destination_y):
					target = get_blocking_entities_at_location(entities, destination_x, destination_y)

					# If blocked by a creature, attack
					if target:
						attack_results = player.fighter.attack(target)
						player_turn_results.extend(attack_results)
					# Otherwise, move.
					else:
						player.move(dx, dy)
						fov_recompute = True
					game_state = GameStates.ENEMY_TURN
			else:
				game_state = GameStates.ENEMY_TURN

		elif pickup and game_state == GameStates.PLAYERS_TURN:
			for entity in entities:
				if entity.item and entity.x == player.x and entity.y == player.y:
					pickup_results = player.inventory.add_item(entity)
					player_turn_results.extend(pickup_results)

					break
			else:
				message_log.add_message(Message('There is nothing here to pick up.', libtcod.yellow))
		#Ability complete checks:
		for ability in player.abilities:
			if player.animator.caller == ability and player.animator.complete:
				player_turn_results.extend(ability.use(complete=True))
				player.animator.caller = None
				player.animator.complete = None

		if ability_1:
			player_turn_results.extend(player.abilities[0].use())


		if show_inventory:
			if game_state != GameStates.SHOW_INVENTORY:
				previous_game_state = game_state
			player.inventory.sort_items()
			game_state = GameStates.SHOW_INVENTORY

		if drop_inventory:
			if game_state != GameStates.DROP_INVENTORY:
				previous_game_state = game_state
			game_state = GameStates.DROP_INVENTORY

		#Use or drop item in inventory
		if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(player.inventory.items):
			item = player.inventory.items[inventory_index]
			if game_state == GameStates.SHOW_INVENTORY:
				player_turn_results.extend(player.inventory.use(item, entities=entities, fov_map=fov_map))

			elif game_state == GameStates.DROP_INVENTORY:
				player_turn_results.extend(player.inventory.drop_item(item))

		if take_stairs and game_state == GameStates.PLAYERS_TURN:
			for entity in entities:
				if entity.stairs and entity.x == player.x and entity.y == player.y: 
					entities = game_map.next_floor(player, message_log, constants)
					fov_map = initialize_fov(game_map)
					target_fov_map = initialize_fov(game_map)
					fov_map_no_walls = initialize_fov(game_map)
					fov_recompute = True
					libtcod.console_clear(con)

					break
			else:
				message_log.add_message(Message('There are no stairs here.', libtcod.yellow))

		if level_up:
			if level_up == 'hp':
				player.fighter.con += 1
				message_log.add_message(Message('Your Constitution has increased by 1!', libtcod.yellow))
			elif level_up == 'str':
				player.fighter.base_power += 1
				message_log.add_message(Message('Your Strength has increased by 1!', libtcod.yellow))
			elif level_up == 'def':
				player.fighter.base_defense += 1
				message_log.add_message(Message('Your Defense has increased by 1!', libtcod.yellow))

			hp_increase = randint(player.fighter.hitdie[0], player.fighter.hitdie[1]) + int((player.fighter.con - 10) / 2)
			player.fighter.base_max_hp += hp_increase
			player.fighter.hp += hp_increase
			message_log.add_message(Message('Your HP has increased by {0}'.format(hp_increase) + '!', libtcod.yellow))
			game_state = previous_game_state

		if show_character_screen:
			if not game_state == GameStates.CHARACTER_SCREEN:
				previous_game_state = game_state
			game_state = GameStates.CHARACTER_SCREEN

		if game_state == GameStates.TARGETING:

			if hasattr(targeting_item, 'item'):
				cursor_radius = targeting_item.item.function_kwargs.get('radius')
			else:
				cursor_radius = targeting_item.function_kwargs.get('radius')
			if left_click:
				target_x, target_y = left_click
				if hasattr(targeting_item, 'item'):
					item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_fov_map=target_fov_map,target_x=target_x, target_y=target_y)
				else:
					item_use_results = targeting_item.use(entities=entities, fov_map=fov_map, target_fov_map=target_fov_map,target_x=target_x, target_y=target_y)
				player_turn_results.extend(item_use_results)
				cursor_radius = 1
			
			elif right_click:
				player_turn_results.append({'targeting_cancelled': True})
				cursor_radius = 1		
						
		if exit:
			if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN):
				game_state = previous_game_state
			elif game_state == GameStates.TARGETING:
				player_turn_results.append({'targeting_cancelled': True})
				cursor_radius = 1
			else:
				save_game(player, entities, game_map, message_log, game_state)
				return True


		if fullscreen:
			libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

		# Check player message queue and react accordingly
		for player_turn_result in player_turn_results:
			message = player_turn_result.get('message')
			dead_entity = player_turn_result.get('dead')
			item_added = player_turn_result.get('item_added')
			item_consumed = player_turn_result.get('consumed')
			item_dropped = player_turn_result.get('item_dropped')
			equip = player_turn_result.get('equip')
			targeting = player_turn_result.get('targeting')
			targeting_cancelled = player_turn_result.get('targeting_cancelled')
			ability_used = player_turn_result.get("ability_used")
			xp = player_turn_result.get('xp')

			if message:
				message_log.add_message(message)

			if targeting_cancelled:
				game_state = previous_game_state

				message_log.add_message(Message('Targeting cancelled'))

			if dead_entity:
				if dead_entity == player:
					message, game_state = kill_player(dead_entity)
				else:
					message = kill_monster(dead_entity)

				message_log.add_message(message)

			if item_added:
				entities.remove(item_added)

				game_state = GameStates.ENEMY_TURN

			if item_consumed:
				game_state = GameStates.ENEMY_TURN
			
			if targeting:
				previous_game_state = GameStates.PLAYERS_TURN
				game_state = GameStates.TARGETING

				targeting_item = targeting
				if hasattr(targeting_item, 'item'):
					message_log.add_message(targeting_item.item.targeting_message)
				else:
					message_log.add_message(targeting_item.targeting_message)

			if ability_used:
				if Animator.blocking == 0:
					game_state = GameStates.ENEMY_TURN

			if item_dropped:
				entities.append(item_dropped)
				game_state = GameStates.ENEMY_TURN

			if equip:
				equip_results = player.equipment.toggle_equip(equip)

				for equip_result in equip_results:
					equipped = equip_result.get('equipped')
					dequipped = equip_result.get('dequipped')

					if equipped:
						message_log.add_message(Message('You equipped the {0}'.format(equipped.name)))

					if dequipped:
						message_log.add_message(Message('You removed the {0}'.format(dequipped.name)))

				game_state = GameStates.ENEMY_TURN

			if xp:
				leveled_up = player.level.add_xp(xp)
				message_log.add_message(Message('You gain {0} experience points.'.format(xp)))

				if leveled_up:
					message_log.add_message(Message('Your battle skills grow stronger! You reached level {0}'.format(
													player.level.current_level) + '!', libtcod.yellow))
					if (player.level.current_level % 2) == 0:
						previous_game_state = game_state
						game_state = GameStates.LEVEL_UP
					else:
						hp_increase = randint(player.fighter.hitdie[0], player.fighter.hitdie[1]) + int((player.fighter.con - 10) / 2)
						player.fighter.base_max_hp += hp_increase
						player.fighter.hp += hp_increase
						message_log.add_message(Message('Your HP has increased by {0}'.format(hp_increase) + '!', libtcod.yellow))


		# Enemy Turn
		if game_state == GameStates.ENEMY_TURN:
			for entity in entities:
				if entity.ai:
					enemy_turn_results = entity.ai.take_turn(player, fov_map, game_map, entities)

					# Capture enemy turn message queue, analyze and react accordingly.
					for enemy_turn_result in enemy_turn_results:
						message = enemy_turn_result.get('message')
						dead_entity = enemy_turn_result.get('dead')

						if message:
							message_log.add_message(message)

						if dead_entity:
							if dead_entity == player:
								message, game_state = kill_player(dead_entity)
							else:
								message = kill_monster(dead_entity)

							message_log.add_message(message)

							if game_state == GameStates.PLAYER_DEAD:
								break
					if game_state == GameStates.PLAYER_DEAD:
						break

				
			else:            

				game_state = GameStates.PLAYERS_TURN
示例#9
0
def main():
    screen_width = 80
    screen_height = 50

    bar_width = 20
    panel_height = 7
    panel_y = screen_height - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    map_width = 80
    map_height = 43

    room_max_size = 10
    room_min_size = 6
    max_rooms = 30

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10

    max_monsters_per_room = 3
    max_items_per_room = 2

    colors = {
        'dark_wall': libtcod.Color(0, 0, 100),
        'dark_ground': libtcod.Color(50, 50, 150),
        'light_wall': libtcod.Color(130, 110, 50),
        'light_ground': libtcod.Color(200, 180, 50)
    }

    fighter_component = Fighter(hp=30, defense=2, power=5)
    inventory_component = Inventory(26)
    player = Entity(0,
                    0,
                    '@',
                    libtcod.white,
                    "Player",
                    blocks=True,
                    render_order=RenderOrder.ACTOR,
                    fighter=fighter_component,
                    inventory=inventory_component)
    entities = [player]

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)

    libtcod.console_init_root(screen_width, screen_height,
                              'libtcod tutorial revised', False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    game_map = GameMap(map_width, map_height)
    game_map.make_map(max_rooms, room_min_size, room_max_size, map_width,
                      map_height, player, entities, max_monsters_per_room,
                      max_items_per_room)

    fov_recompute = True

    fov_map = initialize_fov(game_map)

    message_log = MessageLog(message_x, message_width, message_height)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors, game_state)

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        move = action.get('move')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.',
                            libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})
        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')

            if message:
                message_log.add_message(message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))
            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting
                message_log.add_message(targeting_item.item.targeting_message)
            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN
示例#10
0
def main():
    """
    사전 준비 작업
    """
    SYS_LOG = init_data()

    player, entities = init_player_and_entities(SYS_LOG['player_name'])

    game_map, fov_map, fov_radius, \
    fov_algorithm, fov_recompute, light_recompute, camera = init_game_map(player, entities)

    message_log, game_state, previous_game_state, targeting_item = init_message_and_states(
    )

    root, console, panel, animation, context = init_console()

    debug, mouse, keyboard = init_others()

    quit = False
    """
    메인 루프
    """
    while not quit:
        #root = tcod.Console(*context.recommended_console_size())
        """
        화면 표시
        """
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        if light_recompute:
            light_map = initialize_light(game_map, fov_map, entities)
        render_all(
            game_state,
            root,
            console,
            panel,
            entities,
            player,
            mouse,
            game_map,
            fov_map,
            light_map,
            camera,
            message_log,
            fov_recompute,
        )

        context.present(root, keep_aspect=True,
                        align=(0.5,
                               0.5))  # integer_scaling=True align=(0.5,1))

        #print(*context.recommended_console_size())
        clear_all_entities(console, entities, camera)

        fov_recompute = False
        light_recompute = False
        """
        입력에 대한 상호작용
        """

        action = handle_input_per_state(keyboard, mouse, context, game_state)
        #print(f'Mx:{mouse.x} My:{mouse.y} Clk:{mouse.click}')

        #Ridiculous failsafe
        if action == None:
            action = {}

        move = action.get('move')
        rest = action.get('rest')
        pickup = action.get('pickup')

        show_inventory = action.get('show_inventory')
        inventory_index = action.get('inventory_index')
        drop_inventory = action.get('drop_inventory')
        show_character_screen = action.get('show_character_screen')

        toggle_light = action.get('toggle_light')
        create_luminary = action.get('create_light')
        toggle_wall = action.get('toggle_wall')

        exit = action.get('exit')
        quit = action.get('quit')

        #print(action)
        player_turn_results = []

        if exit:
            # 게임으로 돌아오기
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                pass

        # 최대화면이 True일 시, 전체화면이 아니라면 콘솔을 전체화면으로 전환함
        if action.get('fullscreen'):
            toggle_fullscreen(context)

        #print(f'center x{CENTER_X},y{CENTER_Y}')
        """
        플레이어 차례에 플레이어가 할 수 있는 행동들
        """
        # move변수에 대입된 값이 있을 시 이동
        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = action.get('move')
            destix = player.x + dx
            destiy = player.y + dy

            if debug.passwall == False:
                # 가려는 곳이 지형으로 안 막혀있으면
                if not game_map.is_blocked(destix, destiy):
                    # 거기에 이미 엔티티가 있나 확인
                    target = get_blocking_entities_at_location(
                        entities, destix, destiy)

                    if target:

                        battle = target._Fighter

                        if target.name == "메리":
                            pass
                        elif battle:
                            attack_results = player._Fighter.attack(target)
                            player_turn_results.extend(attack_results)
                        else:
                            """
                            다음 층으로
                            """
                            if target._Portal:
                                entities = game_map.next_depth(
                                    player, message_log)
                                fov_map = initialize_fov(game_map)
                                fov_recompute = True
                                light_recompute = True
                                console.clear()
                            else:
                                print(
                                    "This is the weirdest bug I've ever seen")

                    else:
                        player.move(dx, dy)
                        camera.update(player)
                        fov_recompute = True
                        light_recompute = True

                    game_state = GameStates.ENEMY_TURN
            else:
                if game_map.is_blocked(player.x + dx, player.y + dy):
                    debug.dbg_msg("You magically pass through solid wall.")
                player.move(dx, dy)
                camera.update(player)

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity._Item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player._Inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)
                    break
            else:
                message_log.log(
                    Message(SYS_LOG['cannot_get_item'], tcod.yellow))

        if toggle_light:
            if player._Luminary.luminosity:
                player._Luminary.luminosity = 0
                fov_radius = 1
                fov_algorithm = fov_algorithm_dark
            else:
                player._Luminary.luminosity = player._Luminary.init_luminosity
                fov_radius = max_fov_radius
                fov_algorithm = fov_algorithm_lit

            fov_recompute = True
            light_recompute = True

            game_state = GameStates.ENEMY_TURN

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player._Inventory.items):
            item = player._Inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player._Inventory.use(item,
                                          camera=camera,
                                          entities=entities,
                                          animation=animation,
                                          root=root,
                                          context=context,
                                          fov_map=fov_map,
                                          game_map=game_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player._Inventory.drop_item(item))

        if game_state == GameStates.TARGETING:
            if mouse.click == "L":
                target_x = mouse.x - camera.x - CENTER_X
                target_y = mouse.y - camera.y - CENTER_Y
                #print(f"타게팅 x,y: {target_x},{target_y}")

                item_use_results = player._Inventory.use(targeting_item,
                                                         entities=entities,
                                                         fov_map=fov_map,
                                                         camera=camera,
                                                         animation=animation,
                                                         root=root,
                                                         context=context,
                                                         target_x=target_x,
                                                         target_y=target_y)

                player_turn_results.extend(item_use_results)
            elif mouse.click == "R":
                player_turn_results.append({'targeting_cancelled': True})

        if rest:
            game_state = GameStates.ENEMY_TURN

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if player._Fighter.sanity <= 0:
            message, game_state = insane_player(player)
            message_log.log(message)

        for r in player_turn_results:
            message = r.get('message')
            dead_entity = r.get('dead')

            equip = r.get('equip')
            item_added = r.get('item_added')
            item_consumed = r.get('consumed')
            item_used = r.get('used')
            item_dropped = r.get('item_dropped')
            targeting = r.get('targeting')
            targeting_cancelled = r.get('targeting_cancelled')

            if message:
                message_log.log(message)

            if targeting_cancelled:
                game_state = previous_game_state
                message_log.log(Message('Targeting cancelled'))

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity, game_map)

                message_log.log(message)

            if equip:
                equip_results = player._Equipment.toggle_equip(equip)

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    equip_log = SYS_LOG['equip_log']

                    if equipped:
                        way = equipped._Equippable.slot.name
                        msg = cout(equip_log, equip_log['ways_to_wear'][way],
                                   받침(equipped.name, 1))
                        message_log.log(Message(msg))

                    if dequipped:
                        way = dequipped._Equippable.slot.name
                        msg = cout(equip_log, equip_log['ways_to_unwear'][way],
                                   받침(dequipped.name, 1))
                        message_log.log(Message(msg))

                game_state = GameStates.ENEMY_TURN

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN

            if item_consumed or item_used:
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)
                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING
                targeting_item = targeting
                message_log.log(targeting_item._Item.targeting_message)
        """
        적의 차례에 적이 할 수 있는 행동들
        """
        if game_state == GameStates.ENEMY_TURN:
            # 정신력 고갈 기능. 따로 변수로 넣던가 Gamemap에 넣어야 하나.
            if not game_map.monsters == 0:

                clear_message_shown = False
                """
                정신력 피해 계산
                """
                sanity_damage = random.randint(
                    int(-30 / math.sqrt(game_map.depth)), game_map.monsters)
                s_resist_percent = int(
                    (100 + 3 * (fov_radius - 1) +
                     player._Equipment.total_sanity_resist) / 100)
                sanity_resistance = random.randint(0,
                                                   int(10 * s_resist_percent))
                sanity_damage -= sanity_resistance  #광기저항을 계산 안 했네

                if sanity_damage < 0:
                    sanity_damage = 0
                else:
                    sanity_damage = int(math.sqrt(sanity_damage))
                player._Fighter.heal_sanity(-sanity_damage)
                if sanity_damage > 3:
                    log = SYS_LOG['enemies_exist']
                    message_log.log(
                        Message(log[random.randint(0,
                                                   len(log) - 1)],
                                tcod.dark_chartreuse))
            else:
                if not clear_message_shown:
                    clear_message_shown = True
                    message_log.log(
                        Message(SYS_LOG['enemies_nonexistant'], tcod.green))

            for entity in entities:
                if entity.name == 'light source':
                    pass
                    #message_log.log(f"The {entity.name} is glowing")
                elif entity._Ai:
                    enemy_turn_results = entity._Ai.take_turn(
                        player, fov_map, game_map, entities)

                    for er in enemy_turn_results:
                        message = er.get('message')
                        dead_entity = er.get('dead')
                        game_won = er.get('game_won')

                        if game_won:
                            message_log.log(
                                Message(SYS_LOG['found_mary_log'], tcod.green))
                            message_log.log(
                                Message(SYS_LOG['game_won_log'], tcod.green))
                            game_state = GameStates.GOOD_ENDING

                        if message:
                            message_log.log(message)

                        if player._Fighter.sanity <= 0:
                            message, game_state = insane_player(player)
                            message_log.log(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)
                                game_map.monsters -= 1

                            message_log.log(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                if not game_state == GameStates.GOOD_ENDING:
                    game_state = GameStates.PLAYERS_TURN
        """
        디버그 기능들
        """
        # 플레이어 위치 표시
        if debug.showpos: debug.show_pos(player, 'player')

        # 벽 설치
        if toggle_wall:
            game_map.toggle_wall(player.x, player.y)
            # 지형이 변했으니 새로 지형 맵을 짜야 함
            fov_map = initialize_fov(game_map)
            light_recompute = True

        if create_luminary:
            game_map.create_luminary(entities, player.x, player.y, 15)
            # 광원이 새로 생겼으니 다시 계산
            light_recompute = True
示例#11
0
def kill_player(player, colors):
    player.char = "%"
    player.color = colors.get("dark_red")

    return Message("It's a sad thing that your adventures have ended here!",
                   colors.get("red")), GameStates.PLAYER_DEAD
示例#12
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants, root_con):
    tcod.console_set_custom_font(
        "arial10x10.png", tcod.FONT_LAYOUT_TCOD | tcod.FONT_TYPE_GREYSCALE)
    fov_recompute = True
    fov_map = initialize_fov(game_map)
    previous_game_state = game_state
    targeting_item = None
    while True:
        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])
        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants["screen_width"],
                   constants["screen_height"], constants["bar_width"],
                   constants["panel_y"], constants["colors"], root_con,
                   game_state)
        tcod.console_flush()
        clear_all(con, entities)
        for event in tcod.event.get():
            move = None
            pickup = None
            look_enemy = None
            left_click = None
            right_click = None
            show_inventory = None
            drop_inventory = None
            inventory_index = None
            take_stairs = None
            leave = None
            fullscreen = None
            show_character_screen = None
            player_turn_results = []
            if isinstance(event, tcod.event.KeyDown):
                action = handle_keys(event, game_state)
                move = action.get("move")
                pickup = action.get("pickup")
                look_enemy = action.get("look_enemy")
                show_inventory = action.get("show_inventory")
                drop_inventory = action.get("drop_inventory")
                inventory_index = action.get("inventory_index")
                take_stairs = action.get('take_stairs')
                leave = action.get("leave")
                fullscreen = action.get("fullscreen")
                show_character_screen = action.get('show_character_screen')
            if isinstance(event, tcod.event.MouseButtonDown):
                mouse_action = handle_mouse(event)
                left_click = mouse_action.get("left_click")
                right_click = mouse_action.get("right_click")
            if look_enemy and game_state == GameStates.PLAYER_TURN:
                game_state = GameStates.LOOK_ENEMY
                player_turn_results.extend([{
                    'message':
                    Message('You are in the looking mode', tcod.green)
                }])
            elif look_enemy and game_state == GameStates.LOOK_ENEMY:
                game_state = GameStates.PLAYER_TURN
                player_turn_results.extend([{
                    'message':
                    Message('You left the looking mode', tcod.green)
                }])
            elif left_click and game_state == GameStates.LOOK_ENEMY:
                entities_at_location = check_entity_at_location(
                    entities, left_click[0], left_click[1])
                player_turn_results.extend(entities_at_location)
            elif pickup and game_state == GameStates.PLAYER_TURN:
                for entity in entities:
                    if entity.item and entity.x == player.x and entity.y == player.y:
                        pickup_results = player.inventory.add_item(entity)
                        player_turn_results.extend(pickup_results)
                        break
                else:
                    message_log.add_message(
                        Message('There is nothing here to pick up.',
                                tcod.yellow))
            elif show_inventory:
                previous_game_state = game_state
                game_state = GameStates.SHOW_INVENTORY
                MenuState.menu_state = 0
            elif drop_inventory:
                previous_game_state = game_state
                game_state = GameStates.DROP_INVENTORY
            elif inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                    player.inventory.items):
                item = player.inventory.items[inventory_index]
                if game_state == GameStates.SHOW_INVENTORY:
                    player_turn_results.extend(
                        player.inventory.use(item,
                                             entities=entities,
                                             fov_map=fov_map))
                elif game_state == GameStates.DROP_INVENTORY:
                    player_turn_results.extend(
                        player.inventory.drop_item(item))
            elif game_state == GameStates.TARGETING:
                if left_click and targeting_item:
                    target_x, target_y = left_click
                    item_use_results = player.inventory.use(targeting_item,
                                                            entities=entities,
                                                            fov_map=fov_map,
                                                            target_x=target_x,
                                                            target_y=target_y)
                    player_turn_results.extend(item_use_results)
                elif right_click:
                    player_turn_results.append({'targeting_cancelled': True})
            elif move and game_state == GameStates.PLAYER_TURN:
                dx, dy = move
                destination_x = player.x + dx
                destination_y = player.y + dy
                if not game_map.is_blocked(destination_x, destination_y):
                    target = get_blocking_entities_at_location(
                        entities, destination_x, destination_y)
                    if target:
                        attack_results = player.fighter.melee_attack(target)
                        player_turn_results.extend(attack_results)
                    else:
                        player.move(dx, dy)

                        fov_recompute = True
                    game_state = GameStates.ENEMY_TURN
            elif take_stairs and game_state == GameStates.PLAYER_TURN:
                for entity in entities:
                    if entity.stairs and entity.x == player.x and entity.y == player.y:
                        entities = game_map.next_floor(player, message_log,
                                                       constants)
                        fov_map = initialize_fov(game_map)
                        fov_recompute = True
                        con.clear(fg=(63, 127, 63))

                        break
                else:
                    message_log.add_message(
                        Message('There are no stairs here.', tcod.yellow))
            elif game_state == GameStates.LEVEL_UP:
                player.fighter.max_hp += DiceRoll("1d8").roll_dice()
                game_state = previous_game_state
            elif show_character_screen:
                previous_game_state = game_state
                game_state = GameStates.CHARACTER_SCREEN
            if leave:
                if game_state in (GameStates.SHOW_INVENTORY,
                                  GameStates.DROP_INVENTORY,
                                  GameStates.CHARACTER_SCREEN):
                    game_state = previous_game_state
                elif game_state == GameStates.TARGETING:
                    player_turn_results.append({'targeting_cancelled': True})
                else:
                    save_game(player, entities, game_map, message_log,
                              game_state)
                    return True

            if fullscreen:
                tcod.console_set_fullscreen(not tcod.console_is_fullscreen())

            for player_turn_result in player_turn_results:
                message = player_turn_result.get('message')
                dead_entity = player_turn_result.get('dead')
                entity_identified = player_turn_result.get("entity_identified")
                item_added = player_turn_result.get('item_added')
                item_consumed = player_turn_result.get('consumed')
                item_dropped = player_turn_result.get('item_dropped')
                targeting = player_turn_result.get('targeting')
                targeting_cancelled = player_turn_result.get(
                    'targeting_cancelled')
                xp = player_turn_result.get('xp')
                if message:
                    message_log.add_message(message)

                if dead_entity:
                    if dead_entity == player:
                        message, game_state = kill_player(dead_entity)
                    else:
                        message = kill_monster(dead_entity)

                    message_log.add_message(message)

                if item_added:
                    entities.remove(item_added)
                    game_state = GameStates.ENEMY_TURN

                if item_consumed:
                    game_state = GameStates.ENEMY_TURN

                if item_dropped:
                    entities.append(item_dropped)
                    game_state = GameStates.ENEMY_TURN

                if entity_identified:
                    game_state = GameStates.PLAYER_TURN

                if targeting:
                    previous_game_state = GameStates.PLAYER_TURN
                    game_state = GameStates.TARGETING
                    targeting_item = targeting
                    message_log.add_message(
                        targeting_item.item.targeting_message)

                if targeting_cancelled:
                    game_state = previous_game_state
                    message_log.add_message(Message('Targeting cancelled'))

                if xp:
                    leveled_up = player.level.add_xp(xp)
                    message_log.add_message(
                        Message('You gain {0} experience points.'.format(xp)))

                    if leveled_up:
                        message_log.add_message(
                            Message(
                                'Your battle skills grow stronger! You reached level {0}'
                                .format(player.level.current_level) + '!',
                                tcod.yellow))
                        player.fighter.cr = str(player.level.current_level / 4)
                        previous_game_state = game_state
                        game_state = GameStates.LEVEL_UP

            if game_state == GameStates.ENEMY_TURN:
                for entity in entities:
                    if entity.ai:
                        enemy_turn_results = entity.ai.take_turn(
                            player, fov_map, game_map, entities)

                        for enemy_turn_result in enemy_turn_results:
                            message = enemy_turn_result.get('message')
                            dead_entity = enemy_turn_result.get('dead')

                            if message:
                                message_log.add_message(message)

                            if dead_entity:
                                if dead_entity == player:
                                    message, game_state = kill_player(
                                        dead_entity)
                                else:
                                    message = kill_monster(dead_entity)

                                message_log.add_message(message)

                                if game_state == GameStates.PLAYER_DEAD:
                                    break

                        if game_state == GameStates.PLAYER_DEAD:
                            break
                else:
                    game_state = GameStates.PLAYER_TURN
示例#13
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    # game loop
    while not libtcod.console_is_window_closed():
        # captures user input - will update the key and mouse variables with what the user inputs
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])

        # draw the entities and blit the changes to the screen - only render the item inventory when the game state is in the inventory state
        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   constants['colors'], game_state)

        fov_recompute = False

        # present everything on the screen
        libtcod.console_flush()

        # clear entities after drawing to screen - this makes it so that when entities move, they do not leave a trail behind
        clear_all(con, entities)

        # gives a way to gracefully exit program by hitting the ESC key
        # gets any keyboard input to the program and stores in the key variable
        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        # move the player only on the players turn
        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            # check if there is something at the destination that would block the player - if not, move the player there
            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)
                    fov_recompute = True

                # change to enemy's turn after player's move
                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

        # if the player did not move and performed the pickup action by pressing the key 'g'...
        elif pickup and game_state == GameStates.PLAYERS_TURN:
            # loop through each entity on the map, check if it is an item and occupies the same space as the player
            for entity in entities:
                # if the entity is an item and in the same position as the player
                if entity.item and entity.x == player.x and entity.y == player.y:
                    # add the item to the inventory and append the results to player_turn_results
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break  # makes it so the player only picks up one item at a time
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.',
                            libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        # take the index selected, use the item selected
        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(
                    Message('There are no stairs here.', libtcod.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.power += 1
            elif level_up == 'def':
                player.fighter.defense += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        # checks if the key pressed was the Esc key - if it was, then exit the loop
        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                save_game(player, entities, game_map, message_log, game_state)
                return True

        if fullscreen:
            libtcod.console_set_fullscreen(
                (not libtcod.console_is_fullscreen()))

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(
                    Message('You gain {0} experience points.'.format(xp)))

                if leveled_up:
                    message_log.add_message(
                        Message(
                            'Your battle skills grow stronger! You reached level {0}'
                            .format(player.level.current_level) + '!',
                            libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            # note that this is a for-else statement; without a break statement, this else will always happen
            else:
                game_state = GameStates.PLAYERS_TURN
示例#14
0
def place_entities(room, entities, dungeon_level, colors):
    max_monsters_per_room = from_dungeon_level([[2, 1], [3, 4], [5, 6]],
                                               dungeon_level)
    max_items_per_room = from_dungeon_level([[1, 1], [2, 4]], dungeon_level)

    number_of_monsters = randint(0, max_monsters_per_room)
    number_of_items = randint(0, max_items_per_room)

    monster_chances = {
        "husk":
        60,
        "rusted_automaton":
        from_dungeon_level([[25, 3], [40, 5], [60, 7]], dungeon_level),
        "kobold_bandit":
        from_dungeon_level([[10, 3], [20, 5], [25, 7]], dungeon_level)
    }

    item_chances = {
        "health_drink": 40,
        "wicked_blade": from_dungeon_level([[15, 3]], dungeon_level),
        "battered_armor": from_dungeon_level([[15, 4]], dungeon_level),
        "hp_ring": from_dungeon_level([[10, 5]], dungeon_level),
        "seeker_orb": from_dungeon_level([[25, 4]], dungeon_level),
        "flame_grenade": from_dungeon_level([[25, 6]], dungeon_level),
        "scrambler": from_dungeon_level([[10, 2]], dungeon_level),
        "pearl": 10
    }

    for i in range(number_of_monsters):
        # get a random location in the room
        x = randint(room.x1 + 1, room.x2 - 1)
        y = randint(room.y1 + 1, room.y2 - 1)

        if not any(
            [entity
             for entity in entities if entity.x == x and entity.y == y]):
            monster_choice = random_choice_from_dict(monster_chances)
            if monster_choice == "husk":
                fighter_component = Fighter(hp=15, defense=0, power=5, xp=50)
                ai_component = BasicMonster()
                # husk

                monster = Entity(x,
                                 y,
                                 "h",
                                 colors.get("dark_gray"),
                                 "husk",
                                 blocks=True,
                                 render_order=RenderOrder.ACTOR,
                                 fighter=fighter_component,
                                 ai=ai_component)
            elif monster_choice == "rusted_automaton":
                # rusted automaton
                fighter_component = Fighter(hp=20, defense=2, power=6, xp=75)
                ai_component = BasicMonster()

                monster = Entity(x,
                                 y,
                                 "a",
                                 colors.get("brass"),
                                 "rusted automaton",
                                 blocks=True,
                                 render_order=RenderOrder.ACTOR,
                                 fighter=fighter_component,
                                 ai=ai_component)
            elif monster_choice == "kobold_bandit":
                # kobold bandit
                fighter_component = Fighter(hp=35, defense=1, power=8, xp=100)
                ai_component = BasicMonster()

                monster = Entity(x,
                                 y,
                                 "b",
                                 colors.get("darker_flame"),
                                 "kobold bandit",
                                 blocks=True,
                                 render_order=RenderOrder.ACTOR,
                                 fighter=fighter_component,
                                 ai=ai_component)

            entities.append(monster)

    for i in range(number_of_items):
        x = randint(room.x1 + 1, room.x2 - 1)
        y = randint(room.y1 + 1, room.y2 - 1)

        if not any(
            [entity
             for entity in entities if entity.x == x and entity.y == y]):
            item_choice = random_choice_from_dict(item_chances)

            if item_choice == "health_drink":
                item_component = Item(use_function=heal, amount=50)
                item = Entity(x,
                              y,
                              "!",
                              colors.get("violet"),
                              "health drink",
                              render_order=RenderOrder.ITEM,
                              item=item_component)
            elif item_choice == "wicked_blade":
                equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                  power_bonus=3)
                item = Entity(x,
                              y,
                              ")",
                              colors.get("darker_flame"),
                              "wicked blade",
                              equippable=equippable_component)
            elif item_choice == "battered_armor":
                equippable_component = Equippable(EquipmentSlots.BODY,
                                                  defense_bonus=1)
                item = Entity(x,
                              y,
                              "T",
                              colors.get("darker_orange"),
                              "battered armor",
                              equippable=equippable_component)
            elif item_choice == "hp_ring":
                equippable_component = Equippable(EquipmentSlots.RING,
                                                  max_hp_bonus=30)
                item = Entity(x,
                              y,
                              "o",
                              colors.get("copper"),
                              "stalwart ring",
                              equippable=equippable_component)
            elif item_choice == "flame_grenade":
                item_component = Item(
                    use_function=flame_grenade,
                    targeting=True,
                    targeting_message=Message(
                        "Left-click where you'd like to throw the grenade, or right-click to cancel.",
                        colors.get("light_cyan")),
                    damage=25,
                    radius=3)
                item = Entity(x,
                              y,
                              ".",
                              colors.get("red"),
                              "flame grenade",
                              render_order=RenderOrder.ITEM,
                              item=item_component)
            elif item_choice == "scrambler":
                item_component = Item(
                    use_function=confuse,
                    targeting=True,
                    targeting_message=Message(
                        "Left-click an enemy you'd like to confuse, or right-click to cancel.",
                        colors.get("light_cyan")))
                item = Entity(x,
                              y,
                              ".",
                              colors.get("light_pink"),
                              "scrambler",
                              render_order=RenderOrder.ITEM,
                              item=item_component)
            elif item_choice == "pearl":
                item_component = Item(use_function=xpboost, amount=100)
                item = Entity(x,
                              y,
                              ".",
                              colors.get("silver"),
                              "pearl",
                              render_order=RenderOrder.ITEM,
                              item=item_component)
            elif item_choice == "seeker_orb":
                item_component = Item(use_function=seeker_bolt,
                                      damage=30,
                                      maximum_range=5)
                item = Entity(x,
                              y,
                              ".",
                              colors.get("sky"),
                              "seeker orb",
                              render_order=RenderOrder.ITEM,
                              item=item_component)

            entities.append(item)
示例#15
0
def main():
    screen_width = 80
    screen_height = 80

    bar_width = 20
    panel_height = 10
    panel_y = screen_height - panel_height

    map_width = 80
    map_height = 80 - panel_height

    message_x = bar_width + 2
    message_width = screen_width - bar_width - 2
    message_height = panel_height - 1

    fov_algorithm = 0
    fov_light_walls = True
    fov_radius = 10
    fov_recompute = True

    colors = 0

    entities = []
    items = []
    effects = []

    libtcod.console_set_custom_font(
        'arial10x10.png',
        libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD)
    libtcod.console_init_root(screen_width, screen_height,
                              'Project Magic Circle', False)

    con = libtcod.console_new(screen_width, screen_height)
    panel = libtcod.console_new(screen_width, panel_height)

    seed = 1000

    map = GameMap(map_width, map_height)
    map.create_map(seed)
    fov_map = initialize_fov(map)
    nav_map = initialize_fov(map)
    nav_map_recompute = False
    message_log = MessageLog(message_x, message_width, message_height)

    map.place_entities(entities, 5, 5)
    player = entities[0]

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.STANDART
    realtime = False
    action_buffer = None

    message = Message('To get help press "?"', libtcod.white)
    message_log.add_message(message)
    targeting_item = None
    danger_level = 1

    while not libtcod.console_is_window_closed():
        if nav_map_recompute:
            fov_map = initialize_fov(map)
            nav_map = initialize_fov(map)
            fov_recompute = True
            nav_map_recompute = False

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, effects, map, fov_map, fov_radius,
                   fov_recompute, message_log, screen_width, screen_height,
                   bar_width, panel_height, panel_y, mouse, colors, game_state)
        fov_recompute = False
        libtcod.console_flush()
        clear_all(con, entities + effects)

        for entity in entities:
            try:
                entity.give_energy(int(entity.speed / 5))
            except:
                pass

        for entity in entities:
            if entity == player:

                if action_buffer == None:
                    if realtime:
                        libtcod.sys_check_for_event(
                            libtcod.EVENT_KEY_PRESS or libtcod.EVENT_MOUSE,
                            key, mouse)
                    else:
                        while True:
                            libtcod.sys_check_for_event(
                                libtcod.EVENT_KEY_PRESS or libtcod.EVENT_MOUSE,
                                key, mouse)
                            render_all(con, panel, entities, effects, map,
                                       fov_map, fov_radius, fov_recompute,
                                       message_log, screen_width,
                                       screen_height, bar_width, panel_height,
                                       panel_y, mouse, colors, game_state)
                            libtcod.console_flush()
                            clear_all(con, entities)
                            if is_valid_input(key, mouse):
                                break
                    keys_action = handle_keys(key, game_state)
                    mouse_action = handle_mouse(mouse, game_state)
                    action_buffer = (keys_action, mouse_action)

                if game_state != GameStates.TARGETING:
                    targeting_item = None
                turn_results = entity.ai.take_action(action_buffer[0],
                                                     action_buffer[1], map,
                                                     fov_map, entities,
                                                     game_state,
                                                     targeting_item)

                if turn_results:
                    for turn_result in turn_results:
                        message = turn_result.get('message')
                        dead_entity = turn_result.get('dead')
                        fov_recompute = turn_result.get('fov_recompute')
                        energy = turn_result.get('not_enough_energy')
                        exit = turn_result.get('exit')
                        fullscreen = turn_result.get('fullscreen')
                        effect = turn_result.get('create effect')
                        item_added = turn_result.get('item_added')
                        item_dropped = turn_result.get('item_dropped')
                        show_inventory = turn_result.get('show_inventory')
                        drop_inventory = turn_result.get('drop_inventory')
                        targeting = turn_result.get('targeting')
                        show_help = turn_result.get('show_help')
                        toggle_realtime = turn_result.get('toggle_realtime')
                        go_deeper = turn_result.get('go_deeper')

                        if message:
                            message = Message(message, libtcod.white)
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                                message = Message(message, libtcod.red)
                            else:
                                message = kill_monster(dead_entity)
                                message = Message(message, libtcod.white)
                            message_log.add_message(message)

                        if effect:
                            superimpose_effect(effect, effects)

                        if energy == None:
                            action_buffer = None

                        if fov_recompute == None:
                            fov_recompute = False

                        if item_added:
                            entities.remove(item_added)

                        if show_inventory:
                            previous_game_state = game_state
                            game_state = GameStates.SHOW_INVENTORY

                        if drop_inventory:
                            previous_game_state = game_state
                            game_state = GameStates.DROP_INVENTORY

                        if item_dropped:
                            entities.append(item_dropped)

                        if targeting:
                            targeting_item = targeting
                            message = Message(
                                targeting_item.item_aspect.targeting_message,
                                libtcod.yellow)
                            message_log.add_message(message)
                            previous_game_state = GameStates.STANDART
                            game_state = GameStates.TARGETING

                        if exit:
                            if game_state in {
                                    GameStates.SHOW_INVENTORY,
                                    GameStates.DROP_INVENTORY,
                                    GameStates.TARGETING, GameStates.HELP
                            }:
                                if game_state == GameStates.TARGETING:
                                    message = Message('Exited targeting',
                                                      libtcod.yellow)
                                    message_log.add_message(message)
                                game_state = previous_game_state
                            else:
                                return True

                        if fullscreen:
                            libtcod.console_set_fullscreen(
                                not libtcod.console_is_fullscreen())

                        if show_help:
                            previous_game_state = game_state
                            game_state = GameStates.HELP

                        if toggle_realtime:
                            message = Message('Gamemode changed',
                                              libtcod.green)
                            message_log.add_message(message)
                            realtime = not realtime

                        if go_deeper:
                            '''clear_all(con, entities)
								items = []
								effects = []
								map = GameMap(map_width, map_height)
								map.initialize_tiles()
								map.create_map(seed+danger_level)
								fov_map = initialize_fov(map)
								nav_map = initialize_fov(map)
								map.place_entities(entities, 5+danger_level, 5+danger_level, player = player)
								player = entities[0]
								danger_level += 2'''
                            pass

                else:
                    action_buffer = None

            else:
                if entity.ai:
                    turn_results = entity.ai.take_action(
                        nav_map, entities, game_state)

                    if turn_results:
                        for turn_result in turn_results:
                            message = turn_result.get('message')
                            dead_entity = turn_result.get('dead')
                            exit = turn_result.get('exit')
                            fullscreen = turn_result.get('fullscreen')
                            effect = turn_result.get('create effect')

                            if message:
                                message = Message(message, libtcod.white)
                                message_log.add_message(message)

                            if dead_entity:
                                if dead_entity == player:
                                    message, game_state = kill_player(
                                        dead_entity)
                                    message = Message(message, libtcod.red)
                                else:
                                    message = kill_monster(dead_entity)
                                    message = Message(message, libtcod.white)
                                message_log.add_message(message)

                            if effect:
                                superimpose_effect(effect, effects)

                            if game_state == GameStates.PLAYER_DEAD:
                                break
示例#16
0
    def attack(self, target):
        results = []

        attack_roll = roll_dice(self.attack_die['dice_count'],
                                self.attack_die['die_faces'])

        if attack_roll == 1:
            damage = 0
            results.append({
                'message':
                Message(
                    '{0} fumbles the strike on {1}!'.format(
                        self.owner.name.capitalize(), target.name),
                    libtcod.yellow)
            })
            #Need to have a critical miss
        elif attack_roll == 20:
            if self.owner and self.owner.equipment and self.owner.equipment.main_hand:
                damage = 2 * max({
                    1,
                    (self.owner.equipment.main_hand.equippable.
                     damage_dice_count *
                     self.owner.equipment.main_hand.equippable.damage_die_face
                     + self.main_hand_damage_bonus)
                })
            else:
                damage = 2 * max(
                    {1, (1 + self.str_mod)}
                )  #unarmed strike, max needed to ensure always do at least one pt of dmg

            results.append({
                'message':
                Message(
                    '{0} critically hits {1}! ({2})'.format(
                        self.owner.name.capitalize(), target.name,
                        str(damage)), libtcod.red)
            })
            results.extend(target.fighter.take_damage(damage))
        elif attack_roll + self.attack_die[
                'die_bonus'] >= target.fighter.defense:
            if self.owner and self.owner.equipment and self.owner.equipment.main_hand:
                damage = max({
                    1,
                    (roll_dice(
                        self.owner.equipment.main_hand.equippable.
                        damage_dice_count, self.owner.equipment.main_hand.
                        equippable.damage_die_face) +
                     self.main_hand_damage_bonus)
                })
            else:
                damage = max(
                    {1, (1 + self.str_mod)}
                )  #unarmed strike, max needed to ensure always do at least one pt of dmg

            results.append({
                'message':
                Message(
                    '{0} hits {1}! ({2})'.format(self.owner.name.capitalize(),
                                                 target.name, str(damage)),
                    libtcod.red)
            })
            results.extend(target.fighter.take_damage(damage))
        else:
            damage = 0
            results.append({
                'message':
                Message(
                    '{0} misses {1}!'.format(self.owner.name.capitalize(),
                                             target.name), libtcod.yellow)
            })

        return results
示例#17
0
    def place_entities(self, room, entities, max_monsters_per_room, max_items_per_room):
        # Get a random number of monsters
        number_of_monsters = randint(0, max_monsters_per_room)
        number_of_items = randint(0, max_items_per_room)
        for i in range(number_of_monsters):
            # Choose a random location in the room
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            if not any([entity for entity in entities if entity.x == x and entity.y == y]):
                if randint(0, 100) < 80:
                    fighter_component = Fighter(hp=10, defense=0, power=3)
                    ai_component = BasicMonster()
                    monster = Entity(x, y, 'o', libtcod.desaturated_green, 'Orc', blocks=True,
                                     render_order=RenderOrder.ACTOR, fighter=fighter_component, ai=ai_component)
                else:
                    fighter_component = Fighter(hp=16, defense=1, power=4)
                    ai_component = BasicMonster()

                    monster = Entity(x, y, 'T', libtcod.darker_green, 'Troll', blocks=True, fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR, ai=ai_component)


                entities.append(monster)
        for i in range(number_of_items):
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)
            if not any([entity for entity in entities if entity.x == x and entity.y == y]):
                item_chance = randint(0, 100)

                if item_chance < 70:
                    item_component = Item(use_function=heal, amount=4)
                    item = Entity(x, y, '!', libtcod.violet, 'Healing Potion', render_order=RenderOrder.ITEM,
                                    item=item_component)
                elif item_chance < 80:
                    item_component = Item(use_function=cast_fireball, targeting=True, targeting_message=Message(
                        'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan),
                                          damage=12, radius=3)
                    item = Entity(x, y, '#', libtcod.red, 'Fireball Scroll', render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_chance < 90:
                    item_component = Item(use_function=cast_confuse, targeting=True, targeting_message=Message(
                        'Left-click an enemy to confuse it, or right-click to cancel.', libtcod.light_cyan))
                    item = Entity(x, y, '#', libtcod.light_pink, 'Confusion Scroll', render_order=RenderOrder.ITEM,
                                  item=item_component)
                else:
                    item_component = Item(use_function=cast_lightning, damage=20, maximum_range=5)
                    item = Entity(x, y, '#', libtcod.yellow, 'Lightning Scroll', render_order=RenderOrder.ITEM,
                                  item=item_component)
                entities.append(item)
示例#18
0
    def place_entities(self, room, entities):
        # [NUMBER OF ITEMS/MONSTERS PER ROOM, DUNGEON LEVEL]
        max_monsters_per_room = from_dungeon_level([[2, 1], [3, 4], [5, 6]],
                                                   self.dungeon_level)
        max_items_per_room = from_dungeon_level([[10, 1], [2, 4]],
                                                self.dungeon_level)
        # Get a random number of monsters
        number_of_monsters = randint(0, max_monsters_per_room)

        # Get a random number of items
        number_of_items = randint(0, max_items_per_room)

        # [CHANCE OF SPAWNING, DUNGEON LEVEL]
        monster_chances = {
            'ragged_sailor':
            60,
            'skeleton':
            from_dungeon_level([[30, 1], [40, 2], [50, 3]],
                               self.dungeon_level),
            'troll':
            from_dungeon_level([[15, 1], [30, 2], [60, 3]], self.dungeon_level)
        }

        item_chances = {
            'healing_potion': 35,
            'rapier': from_dungeon_level([[5, 1]], self.dungeon_level),
            'buckler': from_dungeon_level([[15, 1]], self.dungeon_level),
            'fancy_hat': from_dungeon_level([[5, 1]], self.dungeon_level),
            'fancy_shirt': from_dungeon_level([[5, 1]], self.dungeon_level),
            'lightning_scroll': from_dungeon_level([[25, 1]],
                                                   self.dungeon_level),
            'fireball_scroll': from_dungeon_level([[25, 1]],
                                                  self.dungeon_level),
            'confusion_scroll': from_dungeon_level([[10, 1]],
                                                   self.dungeon_level),
            'flintlock': from_dungeon_level([[50, 1]], self.dungeon_level)
        }

        for i in range(number_of_monsters):
            #Choose a random location in the room
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            # Check if an entity is already at that lockation
            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                monster_choice = random_choice_from_dict(monster_chances)

                if monster_choice == 'ragged_sailor':
                    fighter_component = Fighter(hp=15,
                                                defense=1,
                                                power=4,
                                                xp=35)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     's',
                                     libtcod.desaturated_green,
                                     'Ragged Sailor',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component)
                elif monster_choice == 'skeleton':
                    fighter_component = Fighter(hp=20,
                                                defense=3,
                                                power=4,
                                                xp=100)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'k',
                                     libtcod.darker_green,
                                     'Skeleton',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     ai=ai_component)
                else:
                    fighter_component = Fighter(hp=30,
                                                defense=4,
                                                power=8,
                                                xp=100)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'T',
                                     libtcod.darker_green,
                                     'Troll',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     ai=ai_component)

                entities.append(monster)

        for i in range(number_of_items):
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                item_choice = random_choice_from_dict(item_chances)
                ## ADD SOME ITEMS HERE FOR FUN
                if item_choice == 'healing_potion':
                    item_component = Item(use_function=heal, amount=40)
                    item = Entity(x,
                                  y,
                                  '!',
                                  libtcod.violet,
                                  'Healing Potion',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == 'rapier':
                    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                      power_bonus=3)
                    item = Entity(x,
                                  y,
                                  '/',
                                  libtcod.sky,
                                  'Rapier',
                                  equippable=equippable_component)
                elif item_choice == 'buckler':
                    equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                                      defense_bonus=1)
                    item = Entity(x,
                                  y,
                                  '[',
                                  libtcod.darker_orange,
                                  'Buckler',
                                  equippable=equippable_component)
                elif item_choice == 'fancy_hat':
                    equippable_component = Equippable(EquipmentSlots.HEAD,
                                                      defense_bonus=1)
                    item = Entity(x,
                                  y,
                                  '^',
                                  libtcod.crimson,
                                  'Fancy Hat',
                                  equippable=equippable_component)
                elif item_choice == 'fancy_shirt':
                    equippable_component = Equippable(EquipmentSlots.TORSO,
                                                      defense_bonus=1)
                    item = Entity(x,
                                  y,
                                  ';',
                                  libtcod.crimson,
                                  'Fancy Shirt',
                                  equippable=equippable_component)
                elif item_choice == 'fireball_scroll':
                    item_component = Item(
                        use_function=cast_fireball,
                        targeting=True,
                        targeting_message=Message(
                            'Left-click a target for the fireball, or right-click to cancel.',
                            libtcod.light_cyan),
                        damage=25,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.red,
                                  'Fireball Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == 'confusion_scroll':
                    item_component = Item(
                        use_function=cast_confuse,
                        targeting=True,
                        targeting_message=Message(
                            'Left-click an enemy to confuse it, or right-click to cancel.',
                            libtcod.light_cyan))
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.light_pink,
                                  'Confusion Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == 'flintlock':
                    item_component = Item(
                        use_function=cast_bullet,
                        targeting=True,
                        targeting_message=Message(
                            'Left-click an enemy to shoot it, or right-click to cancel.',
                            libtcod.light_cyan),
                        damage=40,
                        maximum_range=5)
                    item = Entity(x,
                                  y,
                                  '+',
                                  libtcod.light_pink,
                                  'Flintlock',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                else:
                    item_component = Item(
                        use_function=cast_lightning,
                        targeting=True,
                        targeting_message=Message(
                            'Left-click an enemy to lightning strike it, or right-click to cancel.',
                            libtcod.light_cyan),
                        damage=40,
                        maximum_range=5)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.yellow,
                                  'Lightning Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)

                entities.append(item)
示例#19
0
def play_game(player, entities, game_map, message_log, game_state, con, hud, panel, constants):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'],
                          constants['fov_algorithm'])

        render_all(con, hud, panel, entities, player, game_map, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['map_x'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse, constants['colors'], constants['map_chars'], game_state)

        colors = constants['colors']

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities, constants['map_chars'], game_map, colors)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        move = action.get('move')
        wait = action.get('wait')
        a_attack = action.get('a_attack')
        s_attack = action.get('s_attack')
        gab = action.get('gab')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy
            previous_facing = player.facing

            if dx > 0:
                player.set_char('>')
                player.set_facing('Left')

            elif dx < 0:
                player.set_char('<')
                player.set_facing('Right')

            elif dy > 0:
                player.set_char('v')
                player.set_facing('Down')

            elif dy < 0:
                player.set_char('^')
                player.set_facing('Up')

            if not game_map.is_blocked(destination_x, destination_y) and player.facing == previous_facing:
                target = get_blocking_entities_at_location(entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)

                else:
                    player.move(dx, dy)

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(Message('There is nothing here to pick up.', libtcod.yellow))

        elif a_attack and game_state == GameStates.PLAYERS_TURN:
            attack_results = player.fighter.forward_attack(entities)
            player_turn_results.extend(attack_results)
            game_state = GameStates.ENEMY_TURN

        elif s_attack and game_state == GameStates.PLAYERS_TURN:
            attack_results = player.fighter.circle_attack(entities)
            player_turn_results.extend(attack_results)
            game_state = GameStates.ENEMY_TURN

        elif gab and game_state == GameStates.PLAYERS_TURN:
            entities_near_player = get_blocking_entities_in_rectangle(entities, player.x, player.y, 3, 3)
            npcs_near_player = get_npcs_in_list(entities_near_player)
            remove_entity_from_sublist_of_entities(player, entities_near_player)
            if npcs_near_player:
                remove_entity_from_sublist_of_entities(npcs_near_player, entities_near_player)
            if npcs_near_player:
                you_said = [{'message': Message('You say hello, and you get a wave back!', libtcod.white)}]
                player_turn_results.extend(you_said)
                game_state = GameStates.ENEMY_TURN
            elif entities_near_player:
                you_said = [{'message': Message('You say hello, but you only get a growl in return!', libtcod.white)}]
                player_turn_results.extend(you_said)
                game_state = GameStates.ENEMY_TURN
            else:        
                you_said = [{'message': Message('You say hello, but no one responds. No one is near!', libtcod.white)}]
                player_turn_results.extend(you_said)
                game_state = GameStates.ENEMY_TURN
          
        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(player.inventory.use(item, entities=entities, fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    entities = game_map.next_floor(player, message_log, constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_set_default_background(con, libtcod.black)
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(Message('There are no stairs here.', libtcod.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map,
                                                        target_x=target_x, target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            else:
                save_game(player, entities, game_map, message_log, game_state)

                return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity, colors.get('bad_alert'), colors.get('bad_alert'))
                else:
                    message = kill_monster(dead_entity, colors.get('moderate_alert'), colors.get('moderate_alert'))

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if equip:
                equip_results = player.equipment.toggle_equip(equip)

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message_log.add_message(Message('You equipped the {0}'.format(equipped.name)))

                    if dequipped:
                        message_log.add_message(Message('You dequipped the {0}'.format(dequipped.name)))

                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(Message('You gain {0} experience points.'.format(xp)))

                if leveled_up:

                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity, colors.get('bad_alert'), colors.get('bad_alert'))
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
            fov_recompute = True
示例#20
0
    def return_scrolls(self, x, y):
        item_chances = {
            'a': 10,
            'b': from_dungeon_level([[2, 4]], self.dungeon_level),
            'c': from_dungeon_level([[3, 4]], self.dungeon_level),
            'd': from_dungeon_level([[4, 4]], self.dungeon_level),
            'e': from_dungeon_level([[5, 4]], self.dungeon_level),
            'f': from_dungeon_level([[6, 4]], self.dungeon_level),
            'g': from_dungeon_level([[7, 4]], self.dungeon_level),
            'h': 10,
            'i': from_dungeon_level([[2, 4]], self.dungeon_level),
            'j': from_dungeon_level([[3, 4]], self.dungeon_level),
            'k': from_dungeon_level([[4, 4]], self.dungeon_level),
            'l': from_dungeon_level([[5, 4]], self.dungeon_level),
            'm': from_dungeon_level([[6, 4]], self.dungeon_level)
            }

        item_choice = random_choice_from_dict(item_chances)

        if item_choice == 'a':
            item_component = Item(use_function=cast_fireball, targeting=True, targeting_message=Message( 'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=12, radius=2)
            item = Entity(x, y, '#', libtcod.red, 'Smudged Burnt Fireball Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'b':
            item_component = Item(use_function=cast_fireball, targeting=True, targeting_message=Message( 'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=15, radius=2)
            item = Entity(x, y, '#', libtcod.red, 'Burnt Fireball Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'c':
            item_component = Item(use_function=cast_fireball, targeting=True, targeting_message=Message( 'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=17, radius=3)
            item = Entity(x, y, '#', libtcod.red, 'Smudged Fireball Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'd':
            item_component = Item(use_function=cast_fireball, targeting=True, targeting_message=Message( 'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=25, radius=3)
            item = Entity(x, y, '#', libtcod.red, 'Fireball Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'e':
            item_component = Item(use_function=cast_fireball, targeting=True, targeting_message=Message( 'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=35, radius=3)
            item = Entity(x, y, '#', libtcod.red, 'Calculated Fireball Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'f':
            item_component = Item(use_function=cast_fireball, targeting=True, targeting_message=Message( 'Left-click a target tile for the fireball, or right-click to cancel.', libtcod.light_cyan), damage=50, radius=5)
            item = Entity(x, y, '#', libtcod.red, 'Bloodfeud Fireball Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'g':
            item_component = Item(use_function=cast_confuse, targeting=True, targeting_message=Message('Left-click an enemy to confuse it, or right-click to cancel.', libtcod.light_cyan))
            item = Entity(x, y, '#', libtcod.light_pink, 'Confusion Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'h':
            item_component = Item(use_function=cast_lightning, damage=15, maximum_range=4)
            item = Entity(x, y, '#', libtcod.yellow, 'Smudged Burnt Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'i':
            item_component = Item(use_function=cast_lightning, damage=20, maximum_range=4)
            item = Entity(x, y, '#', libtcod.yellow, 'Burnt Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'j':
            item_component = Item(use_function=cast_lightning, damage=25, maximum_range=5)
            item = Entity(x, y, '#', libtcod.yellow, 'Smudged Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'k':
            item_component = Item(use_function=cast_lightning, damage=40, maximum_range=5)
            item = Entity(x, y, '#', libtcod.yellow, 'Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'l':
            item_component = Item(use_function=cast_lightning, damage=60, maximum_range=5)
            item = Entity(x, y, '#', libtcod.yellow, 'Calculated Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component)
        elif item_choice == 'm':
            item_component = Item(use_function=cast_lightning, damage=80, maximum_range=7)
            item = Entity(x, y, '#', libtcod.yellow, 'Bloodfeud Lightning Scroll', render_order=RenderOrder.ITEM, item=item_component)

        return item
示例#21
0
    def place_entities(self, room, entities):
        # 部屋のオブジェクト数の決定
        max_monsters_per_room = from_dungeon_level(
            [[2, 1], [3, 4], [5, 6], [6, 12]], self.dungeon_level)
        max_items_per_room = from_dungeon_level([[1, 1], [2, 6]],
                                                self.dungeon_level)

        number_of_monsters = randint(0, max_monsters_per_room)
        number_of_items = randint(0, max_items_per_room)

        # [確率,発生する階数]
        monster_chances = {
            'goblin':
            from_dungeon_level([[80, 1], [60, 7], [30, 10], [0, 14]],
                               self.dungeon_level),
            'troll':
            from_dungeon_level([[15, 3], [60, 5], [80, 14]],
                               self.dungeon_level),
            'ogre':
            from_dungeon_level([[15, 6], [30, 10], [60, 14]],
                               self.dungeon_level)
        }

        item_chances = {
            'healing_potion':
            15,
            'bronze_sword':
            from_dungeon_level([[5, 4]], self.dungeon_level),
            'shield':
            from_dungeon_level([[5, 6]], self.dungeon_level),
            'iron_sword':
            from_dungeon_level([[5, 8]], self.dungeon_level),
            'lightning_scroll':
            from_dungeon_level([[25, 4], [40, 8]], self.dungeon_level),
            'fireball_scroll':
            from_dungeon_level([[25, 6], [40, 10]], self.dungeon_level),
            'confusion_scroll':
            from_dungeon_level([[10, 2], [20, 4]], self.dungeon_level)
        }

        # モンスターの数だけ実行
        for i in range(number_of_monsters):
            # 部屋のランダムな位置を取得
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            # 得られた座標に既にEntitiyが存在しないならば
            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                monster_choice = random_choice_from_dict(monster_chances)

                if monster_choice == 'goblin':
                    fighter_component = Fighter(hp=25,
                                                defense=0,
                                                power=3,
                                                xp=35)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'g',
                                     libtcod.desaturated_green,
                                     'goblin',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component)
                elif monster_choice == 'troll':
                    fighter_component = Fighter(hp=40,
                                                defense=2,
                                                power=4,
                                                xp=70)
                    ai_component = BasicMonster()

                    monster = Entity(x,
                                     y,
                                     'T',
                                     libtcod.darker_green,
                                     'Troll',
                                     blocks=True,
                                     fighter=fighter_component,
                                     render_order=RenderOrder.ACTOR,
                                     ai=ai_component)
                elif monster_choice == 'ogre':
                    fighter_component = Fighter(hp=70,
                                                defense=1,
                                                power=4,
                                                xp=120)
                    ai_component = BasicMonster()
                    equipment_component = Equipment()
                    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                      power_daice=2,
                                                      daice=2,
                                                      base_power=3)
                    club = Entity(0,
                                  0,
                                  'l',
                                  libtcod.sky,
                                  'club',
                                  equippable=equippable_component)

                    monster = Entity(x,
                                     y,
                                     'O',
                                     libtcod.darker_green,
                                     'Ogre',
                                     blocks=True,
                                     fighter=fighter_component,
                                     equipment=equipment_component,
                                     render_order=RenderOrder.ACTOR,
                                     ai=ai_component)
                    monster.equipment.toggle_equip(club)

                entities.append(monster)
            else:
                i -= 1

            # アイテムの数だけ実行
            for i in range(number_of_items):
                x = randint(room.x1 + 1, room.x2 - 1)
                y = randint(room.y1 + 1, room.y2 - 1)

                # 得られた座標に既にEntitiyが存在しないならば
                if not any([
                        entity for entity in entities
                        if entity.x == x and entity.y == y
                ]):
                    item_choice = random_choice_from_dict(item_chances)

                    if item_choice == 'healing_potion':
                        item_component = Item(use_function=heal, amount=40)
                        item = Entity(x,
                                      y,
                                      '!',
                                      libtcod.violet,
                                      'Healing Potion',
                                      render_order=RenderOrder.ITEM,
                                      item=item_component)

                    elif item_choice == 'fireball_scroll':
                        item_component = Item(
                            use_function=cast_fireball,
                            targeting=True,
                            targeting_message=Message(
                                'Left-click a target tile for the fireball, or right-click to cancel.',
                                libtcod.light_cyan),
                            damage=25,
                            radius=3)
                        item = Entity(x,
                                      y,
                                      '#',
                                      libtcod.red,
                                      'Fireball Scroll',
                                      render_order=RenderOrder.ITEM,
                                      item=item_component)

                    elif item_choice == 'confusion_scroll':
                        item_component = Item(
                            use_function=cast_confuse,
                            targeting=True,
                            targeting_message=Message(
                                'Left-click an enemy to confuse it, or right-click to cancel.',
                                libtcod.light_cyan))
                        item = Entity(x,
                                      y,
                                      '#',
                                      libtcod.light_pink,
                                      'Confusion Scroll',
                                      render_order=RenderOrder.ITEM,
                                      item=item_component)

                    elif item_choice == 'bronze_sword':
                        equippable_component = Equippable(
                            EquipmentSlots.MAIN_HAND,
                            power_daice=2,
                            daice=3,
                            base_power=1)
                        item = Entity(x,
                                      y,
                                      '/',
                                      libtcod.sky,
                                      'Bronze Sword',
                                      equippable=equippable_component)

                    elif item_choice == 'shield':
                        equippable_component = Equippable(
                            EquipmentSlots.OFF_HAND, defense_bonus=1)
                        item = Entity(x,
                                      y,
                                      '[',
                                      libtcod.darker_orange,
                                      'Shield',
                                      equippable=equippable_component)

                    elif item_choice == 'iron_sword':
                        equippable_component = Equippable(
                            EquipmentSlots.MAIN_HAND,
                            power_daice=4,
                            daice=3,
                            base_power=2)
                        item = Entity(x,
                                      y,
                                      '/',
                                      libtcod.sky,
                                      'Iron Sword',
                                      equippable=equippable_component)

                    else:
                        item_component = Item(use_function=cast_lightning,
                                              damage=40,
                                              maximum_range=5)
                        item = Entity(x,
                                      y,
                                      '#',
                                      libtcod.yellow,
                                      'Lightning Scroll',
                                      render_order=RenderOrder.ITEM,
                                      item=item_component)

                    entities.append(item)
                else:
                    i -= 1
示例#22
0
def main():
    #initialize constants, game variables, fov, message log, and font
    const = get_constants()
    player, entities, game_map, fov_recompute, fov_map, message_log, hp_regen_tick, mp_regen_tick = get_game_variables(
        const)

    # font from: http://rogueliketutorials.com/tutorials/tcod/part-0/
    tcod.console_set_custom_font(
        'arial10x10.png', tcod.FONT_TYPE_GREYSCALE | tcod.FONT_LAYOUT_TCOD)

    #sets game state to be players turn to begin with
    game_state = GameStates.PLAYERS_TURN

    # main game loop. Root console being created in context with 'with' so that it closes nicely instead of freezing and crashing
    with tcod.console_init_root(const['screen_width'],
                                const['screen_height'],
                                const['window_title'],
                                fullscreen=False,
                                order='F',
                                vsync=True) as root_console:
        # initializes main console and console for UI elements
        con = tcod.console.Console(const['screen_width'],
                                   const['screen_height'],
                                   order='F')
        panel = tcod.console.Console(const['screen_width'],
                                     const['panel_height'],
                                     order='F')

        # main game loop
        while True:
            # gets user input and sends input events to a handler that returns a dictionary of actions
            for event in tcod.event.wait():
                action = event_dispatcher(event)

            # recomputes fov when necessary
            if (fov_recompute == True):
                recompute_fov(fov_map, player.x, player.y, player.fov_range,
                              const['fov_light_walls'], const['fov_algorithm'])

            # renders whole map on console
            render_all(con, panel, message_log, entities, player, game_map,
                       fov_map, fov_recompute, const['screen_width'],
                       const['screen_height'], const['bar_width'],
                       const['panel_height'], const['panel_y'])
            tcod.console_flush()

            # resets fov_recompute to prevent wasteful computation
            fov_recompute = False

            # clears console to avoid trails when moving
            clear_all(con, entities)

            # gets actions inputted by player from dictionary
            move = action.get('move')
            exit_game = action.get('exit_game')
            fullscreen = action.get('fullscreen')
            restart = action.get('restart')
            take_stairs = action.get('take_stairs')
            toggle_lights = action.get('toggle_lights')
            spell = action.get('spell')

            # player's turn taken only if player gives input
            if (move != None) and (game_state == GameStates.PLAYERS_TURN) and (
                    player.is_dead == False):
                dx, dy = move
                # only move player if the cell is unblocked and moving within the map
                if ((player.x + dx < game_map.width - 1)
                        and (player.y + dy < game_map.height - 1) and
                    (not game_map.is_blocked(player.x + dx, player.y + dy))):
                    # checks for entities that block movement in destination being moved to
                    target = get_blocking_entities_at_location(
                        entities, player.x + dx, player.y + dy)

                    # space is empty so player moves. if player is waiting in place it is treated as a normal move to prevent them from atacking themselves
                    if (target == None) or (dx == 0 and dy == 0):
                        player.move(dx, dy)
                        # only recomputes fov when player moves to avoid unnecessary computation
                        fov_recompute = True
                    # attack target
                    else:
                        player.attack(target, message_log)

                # increments tick by one if the player is below full health/mp. Player must always wait for the full delay after losing hp/mp at max
                if (player.hp < player.max_hp):
                    hp_regen_tick += 1
                if (player.mp < player.max_mp):
                    mp_regen_tick += 1

                # player statically regenerates hp and mp periodically
                if (hp_regen_tick == const['hp_regen_delay']):
                    player.heal(1)
                    hp_regen_tick = 0  # resets tick
                if (mp_regen_tick == const['mp_regen_delay']):
                    player.restore_mp(1)
                    mp_regen_tick = 0  # resets tick

                # resets players fov range in case they have casted flash
                player.fov_range = const['default_fov_radius']

                # passes turn to enemies. this happens even if player walks into a wall
                game_state = GameStates.ENEMY_TURN

            # handles spells
            if (spell != None) and (game_state == GameStates.PLAYERS_TURN
                                    ) and (player.is_dead == False):
                # f key casts a fireball spell that does damage in a radius around the player
                if (spell == 'fireball'):
                    player.cast_fireball(entities, message_log)
                # h key casts cure which heals for a portion of players max hp
                elif (spell == 'cure'):
                    player.cast_cure(message_log)
                # v key casts clairvoyance which reveals position of stairs
                elif (spell == 'clairvoyance'):
                    player.cast_clairvoyance(game_map, message_log)
                # g key casts flash which increases the distance the player can see for a turn
                elif (spell == 'flash'):
                    player.cast_flash(message_log)
                # arrow keys cast in appropriate direction
                elif (spell == 'tunnel_up'):
                    player.cast_tunnel(game_map, fov_map, message_log, 0, -1)
                elif (spell == 'tunnel_down'):
                    player.cast_tunnel(game_map, fov_map, message_log, 0, 1)
                elif (spell == 'tunnel_left'):
                    player.cast_tunnel(game_map, fov_map, message_log, -1, 0)
                elif (spell == 'tunnel_right'):
                    player.cast_tunnel(game_map, fov_map, message_log, 1, 0)

                # increments tick by one if the player is below full health.
                if (player.hp < player.max_hp):
                    hp_regen_tick += 1
                # resets mp regen tick so a player must wait full delay after casting a spell to start mp regen
                mp_regen_tick = 0

                # hp regen unaffected by casting a spell
                if (hp_regen_tick == const['hp_regen_delay']):
                    player.heal(1)
                    hp_regen_tick = 0  # resets tick

                # resets player's fov range unless they cast flash. this makes flash only last one turn
                if (spell != 'flash'):
                    player.fov_range = const['default_fov_radius']

                # recomputes fov since some spells affect the map/fov
                fov_recompute = True

                game_state = GameStates.ENEMY_TURN

            # enemy's turn
            if (game_state == GameStates.ENEMY_TURN):
                # loops through all enemies
                for entity in entities:
                    if (isinstance(entity, Enemy)):
                        # enemy gets a real turn if they are within the players fov, or if they have seen the player
                        if ((fov_map.fov[entity.y, entity.x])
                                or (entity.knows_player_location == True)):
                            # attacks player if they are adjacent or moves towards player using bfs pathfinding algorithm
                            entity.take_turn(player, game_map, entities,
                                             message_log)

                            # enemy will continue to follow the player after being seen for the first time, regardless of fov
                            if entity.knows_player_location == False:
                                entity.knows_player_location = True

                        # enemies outside of fov just move around at random
                        else:
                            entity.random_move(game_map, entities)

                # checks to see if the player died
                if (player.is_dead == True):
                    game_state = GameStates.PLAYER_DEATH
                else:
                    # passes turn back to player even if the enemies didn't do anything
                    game_state = GameStates.PLAYERS_TURN

            # handles death of player
            if (game_state == GameStates.PLAYER_DEATH):
                message_log.add_message(Message('You Lose', tcod.darker_red))

            # takes player to new floor
            if (take_stairs == True) and (player.x == game_map.stairs.x) and (
                    player.y == game_map.stairs.y):
                # makes new floor and resets entities list
                entities = game_map.stairs.take_stairs(player, game_map,
                                                       entities, message_log)

                # resets fov
                fov_map = initialize_fov(game_map)
                fov_recompute = True

                # clears the console to remove the last floor from the screen
                clear_console(con, const['screen_width'],
                              const['screen_height'])

                # player wins if they make it to the 4th floor
                if (game_map.depth == const['winning_floor']):
                    game_state = GameStates.PLAYER_WINS

            # player wins after getting to a set floor
            if game_state == GameStates.PLAYER_WINS:
                message_log.add_message(Message('You Win!', tcod.yellow))

            # restarts game
            if (restart == True):
                # resets everything to beginning state
                const = get_constants()
                player, entities, game_map, fov_recompute, fov_map, message_log, hp_regen_tick, mp_regen_tick = get_game_variables(
                    const)

                # clears the console to remove the last floor from the screen
                clear_console(con, const['screen_width'],
                              const['screen_height'])

                # new game starts with players turn
                game_state = GameStates.PLAYERS_TURN

            # toggles lights to see the whole map for deomonstration
            if (toggle_lights == True):
                game_map.lights_on = not game_map.lights_on
                if game_map.lights_on == False:
                    clear_console(con, const['screen_width'],
                                  const['screen_height'])
                fov_recompute = True

            # breaks loop if player exits
            if (exit_game == True):
                raise SystemExit()

            # toggles fullscreen
            if (fullscreen == True):
                tcod.console_set_fullscreen(not tcod.console_is_fullscreen())
示例#23
0
    def attacktarget(self, target, attack):
        results = []

        # determine if it's even a hit, otherwise, damage is zero.
        lowlevel_equalizer = 2
        speed_calc = float(self.speed + lowlevel_equalizer) / \
         float(target.fighter.speed + lowlevel_equalizer)
        dodge_chance = speed_calc - 0.5
        dodged = False
        critical = False
        if (dodge_chance >= 1.0):
            dodged = True
        elif (dodge_chance <= 0.0):
            dodged = False
            critical = True
        else:
            dodged = (random() >= dodge_chance)

        damage = 0
        if (not dodged):
            # pokemon damage calc
            dmg_mod = (random() * 0.15) + 0.85  # [0.85,1.0)
            if (critical):
                dmg_mod *= 1.5
            effective_atkdef = 0
            assert (attack.atk_type == AttackType.PHYSICAL
                    or attack.atk_type == AttackType.SPECIAL)
            if (attack.atk_type == AttackType.PHYSICAL):
                effective_atkdef = float(self.attack) / float(
                    target.fighter.defense)
            elif (attack.atk_type == AttackType.SPECIAL):
                effective_atkdef = float(self.spattack) / float(
                    target.fighter.spdefense)
            damage = int(
                float(attack.atk_power) * effective_atkdef * dmg_mod * 0.5) + 1

        # if AI attacks non-hostile AI, fight back!
        if (not target.ai is None):
            if ((target.ai.aistate != AI.AIStates.FOLLOWING)
                    or (target.ai.targetentity != self.owner)):
                target.ai.aistate = AI.AIStates.FOLLOWING
                target.ai.targetentity = self.owner

        if damage > 0:
            if (critical):
                results.append({'message': Message(
                 '%s uses its %s attack on the %s for %s hit points. It\'s a critical hit!' % \
                 (self.owner.name, attack.name, target.name, str(damage)),
                 libtcod.white)})
            else:
                results.append({'message': Message(
                 '%s uses its %s attack on the %s for %s hit points.' % \
                 (self.owner.name, attack.name, target.name, str(damage)),
                 libtcod.white)})
            results.extend(target.fighter.take_damage(damage))
        elif (dodged):
            results.append({'message': Message(
             '%s uses its %s attack, but the %s completely dodges it.' % \
             (self.owner.name, attack.name, target.name),
             libtcod.white)})
        else:
            results.append({'message': Message(
             '%s uses its %s attack on the %s, but does no damage.' % \
             (self.owner.name, attack.name, target.name),
             libtcod.white)})

        return results
示例#24
0
def kill_player(player):
    player.char = "%"
    player.color = libtcod.dark_red
    player.name = 'Remains of ' + player.name

    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD
示例#25
0
    def place_entities(self, room, entities):
        num_monsters = from_dungeon_level([[2, 1], [3, 4], [5, 6]],
                                          self.dungeon_level)
        num_items = from_dungeon_level([[1, 1], [2, 4]], self.dungeon_level)

        monster_chances = {
            'orc':
            80,
            'troll':
            from_dungeon_level([[15, 3], [30, 5], [60, 7]], self.dungeon_level)
        }
        item_chances = {
            'healing_potion': 35,
            'sword': from_dungeon_level([[5, 4]], self.dungeon_level),
            'shield': from_dungeon_level([[15, 8]], self.dungeon_level),
            'lightning_scroll': from_dungeon_level([[25, 4]],
                                                   self.dungeon_level),
            'fireball_scroll': from_dungeon_level([[25, 6]],
                                                  self.dungeon_level),
            'confusion_scroll': from_dungeon_level([[10, 2]],
                                                   self.dungeon_level)
        }

        for i in range(num_monsters):
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                monster_choice = random_choice_from_dict(monster_chances)

                if monster_choice == 'orc':
                    fighter_component = Fighter(hp=20,
                                                defense=0,
                                                power=4,
                                                xp=35)
                    ai_component = BasicMonster()
                    monster = Entity(x,
                                     y,
                                     'o',
                                     libtcod.desaturated_green,
                                     'Orc',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component)
                else:
                    fighter_component = Fighter(hp=30,
                                                defense=2,
                                                power=8,
                                                xp=100)
                    ai_component = BasicMonster()
                    monster = Entity(x,
                                     y,
                                     'T',
                                     libtcod.darker_green,
                                     'Troll',
                                     blocks=True,
                                     render_order=RenderOrder.ACTOR,
                                     fighter=fighter_component,
                                     ai=ai_component)

                entities.append(monster)

        for i in range(num_items):
            x = randint(room.x1 + 1, room.x2 - 1)
            y = randint(room.y1 + 1, room.y2 - 1)

            if not any([
                    entity
                    for entity in entities if entity.x == x and entity.y == y
            ]):
                item_choice = random_choice_from_dict(item_chances)

                if item_choice == 'healing_potion':
                    item_component = Item(use_function=heal, amount=40)
                    item = Entity(x,
                                  y,
                                  '!',
                                  libtcod.violet,
                                  'Healing Potion',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == 'sword':
                    equippable_component = Equippable(EquipmentSlots.MAIN_HAND,
                                                      power_bonus=3)
                    item = Entity(x,
                                  y,
                                  '/',
                                  libtcod.sky,
                                  'Sword',
                                  equippable=equippable_component)
                elif item_choice == 'shield':
                    equippable_component = Equippable(EquipmentSlots.OFF_HAND,
                                                      defense_bonus=1)
                    item = Entity(x,
                                  y,
                                  ']',
                                  libtcod.darker_orange,
                                  'Shield',
                                  equippable=equippable_component)
                elif item_choice == 'fireball_scroll':
                    item_component = Item(
                        use_function=cast_fireball,
                        targeting=True,
                        targeting_message=Message(
                            'Left click a target tile for the fireball, or right-click to cancel.',
                            libtcod.light_cyan),
                        damage=25,
                        radius=3)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.red,
                                  'Fireball Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                elif item_choice == 'confusion_scroll':
                    item_component = Item(
                        use_function=cast_confuse,
                        targeting=True,
                        targeting_message=Message(
                            'Left click on an enemy to confuse it, or right-click to cancel.',
                            libtcod.light_cyan))
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.light_pink,
                                  'Confusion Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                else:
                    item_component = Item(use_function=cast_lightning,
                                          damage=40,
                                          max_range=5)
                    item = Entity(x,
                                  y,
                                  '#',
                                  libtcod.yellow,
                                  'Lightning Scroll',
                                  render_order=RenderOrder.ITEM,
                                  item=item_component)
                entities.append(item)
示例#26
0
def play_game(con, player, entities, animator: Animator, turn_count: int,
              game_map: GameMap, message_log, game_state, panel, constants):
    target_x, target_y = player.x, player.y
    targeting_item = None
    target_entity = None

    while True:
        fov_algorithm = 2
        fov_light_walls = True
        fov_radius = 20
        fov_recompute = True
        fov_map = initialize_fov(game_map)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, fov_radius,
                          fov_light_walls, fov_algorithm)

        render_all(con, panel, entities, animator, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], game_state,
                   target_x, target_y, target_entity, turn_count)

        tcod.console_flush()

        clear_all(con, entities)

        player_turn_results = []

        animator.advance_frame()

        # Handle Game State
        if game_state == GameStates.ENEMY_TURN:
            turn_count += 1

            # Generate path map with all static tiles (ignore entities for now)
            path_map = generate_path_map(game_map,
                                         entities=None,
                                         player=player)

            for entity in entities:
                if entity.ai and entity.ai != Player:
                    recompute_walkable(fov_map, game_map, entities, entity)
                    entity_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities, path_map)

                    for entity_turn_result in entity_turn_results:
                        message = entity_turn_result.get('message')
                        dead_entity = entity_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(player)
                            else:
                                message = kill_entity(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYER_TURN

        # Handle Events
        for event in tcod.event.wait():
            if event.type == "QUIT":
                save_game(player, entities, animator, turn_count, game_map,
                          message_log, game_state)
                raise SystemExit()

            if event.type == "KEYDOWN":
                action: [Action, None] = handle_keys(event.sym, game_state)

                if action is None:
                    continue

                action_type: ActionType = action.action_type

                if action_type == ActionType.EXECUTE:
                    if game_state == GameStates.TARGETING:
                        item_use_results = player.body.use_selected_appendage(
                            entities=entities,
                            fov_map=fov_map,
                            game_map=game_map,
                            target_x=target_x,
                            target_y=target_y)
                        player_turn_results.extend(item_use_results)
                        game_state = GameStates.ENEMY_TURN
                    elif game_state == GameStates.LOOKING:
                        look_results = []

                        looked_at_entities = get_entities_at_location(
                            entities, target_x, target_y)
                        if tcod.map_is_in_fov(fov_map, target_x, target_y):
                            if looked_at_entities:
                                for entity in looked_at_entities:
                                    look_results.extend(
                                        entity.get_description())
                                    target_entity = entity
                            else:
                                if game_map.tiles[target_x][target_y].blocked:
                                    look_results.append({
                                        'message':
                                        Message("You stare at the wall.")
                                    })
                                else:
                                    look_results.append({
                                        'message':
                                        Message("You stare into empty space.")
                                    })
                        else:
                            look_results.append({
                                'message':
                                Message("You can't see that far.")
                            })

                        game_state = GameStates.PLAYER_TURN
                        player_turn_results.extend(look_results)

                if action_type == ActionType.MOVEMENT:
                    dx: int = action.kwargs.get("dx", 0)
                    dy: int = action.kwargs.get("dy", 0)

                    # Player Movement
                    if game_state == GameStates.PLAYER_TURN:
                        destination_x = player.x + dx
                        destination_y = player.y + dy

                        tile_results = game_map.tiles[destination_x][
                            destination_y].overlap_entity(player)
                        player_turn_results.extend(tile_results)

                        if not game_map.is_blocked(destination_x,
                                                   destination_y):
                            target_appendage = get_blocking_entities_at_location(
                                entities, destination_x, destination_y)

                            if target_appendage:
                                if target_appendage.body:
                                    player_fighter = player.body.selected_appendage.fighter

                                    if player_fighter:
                                        target_entity = target_appendage
                                        game_state = GameStates.TARGET_APPENDAGE
                                    else:
                                        player_turn_results.append({
                                            'message':
                                            Message(
                                                "You cannot attack with your {0}."
                                                .format(
                                                    player.body.
                                                    selected_appendage.name),
                                                tcod.yellow)
                                        })
                                elif target_appendage.structure:
                                    structure_interact_results = target_appendage.structure.interact(
                                        player)
                                    player_turn_results.extend(
                                        structure_interact_results)
                            else:
                                player.move(dx, dy)
                        else:
                            player_turn_results.append({
                                'message':
                                Message("You slam yourself into the wall!",
                                        tcod.orange)
                            })

                        if game_state != GameStates.TARGET_APPENDAGE:
                            game_state = GameStates.ENEMY_TURN

                    # Targeting
                    elif game_state in (GameStates.TARGETING,
                                        GameStates.LOOKING):
                        new_x = target_x + dx
                        new_y = target_y + dy
                        if player.distance(new_x, new_y) < targeting_radius:
                            target_x = new_x
                            target_y = new_y

                elif action_type == ActionType.GRAB:
                    for entity in entities:
                        if entity.item and entity.x == player.x and entity.y == player.y:
                            pickup_result = player.body.grab_entity(entity)
                            player_turn_results.extend(pickup_result)
                            break
                    else:
                        player_turn_results.append({
                            'message':
                            Message('You grab at the air', tcod.yellow)
                        })

                    game_state = GameStates.ENEMY_TURN

                elif action_type == ActionType.LOOK:
                    game_state = GameStates.LOOKING
                    target_x, target_y = player.x, player.y
                    targeting_radius = 100

                elif action_type == ActionType.WAIT:
                    player_turn_results.append({
                        'message':
                        Message('You stare blankly into space', tcod.yellow)
                    })
                    game_state = GameStates.ENEMY_TURN

                elif action_type == ActionType.CHOOSE_OPTION:
                    option_index = action.kwargs.get("option_index", None)

                    if game_state == GameStates.SWAP_APPENDAGE:
                        if option_index < len(player.body.appendages):
                            item = player.body.appendages[option_index]
                            swap_results = player.body.select_appendage(item)
                            player_turn_results.extend(swap_results)
                            game_state = GameStates.PLAYER_TURN

                    elif game_state == GameStates.TARGET_APPENDAGE:
                        if option_index < len(target_entity.body.appendages):
                            target_appendage = target_entity.body.appendages[
                                option_index]
                            attack_results = player.body.selected_appendage.fighter.attack_appendage(
                                target_appendage)
                            player_turn_results.extend(attack_results)
                            game_state = GameStates.ENEMY_TURN

                elif action_type == ActionType.INTERACT:
                    for entity in entities:
                        if entity.structure and entity.x == player.x and entity.y == player.y:
                            interact_results = entity.structure.interact(
                                player)
                            player_turn_results.extend(interact_results)
                            break
                    else:
                        if game_state == GameStates.PLAYER_TURN:
                            activate_item_results = player.body.use_selected_appendage(
                                fov_map=fov_map,
                                game_map=game_map,
                                entities=entities)
                            if activate_item_results:
                                player_turn_results.extend(
                                    activate_item_results)
                                game_state = GameStates.ENEMY_TURN

                elif action_type == ActionType.DROP_INVENTORY_ITEM:
                    grabber = player.body.selected_appendage.grabber
                    if grabber:
                        player_turn_results.extend(grabber.drop())
                    # game_state = GameStates.DROP_INVENTORY

                elif action_type == ActionType.SWAP_APPENDAGE:
                    game_state = GameStates.SWAP_APPENDAGE

                elif action_type == ActionType.ESCAPE:
                    if game_state == GameStates.TARGETING:
                        game_state = GameStates.PLAYER_TURN
                    elif game_state == GameStates.PLAYER_TURN:
                        save_game(player, entities, animator, turn_count,
                                  game_map, message_log, game_state)
                        main()
                elif action_type == ActionType.RESTART:
                    main()

        # Process player turn results
        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            targeting = player_turn_result.get('targeting')
            next_floor = player_turn_result.get('next_floor')

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(player)
                else:
                    message_log.add_message(kill_entity(dead_entity))

            if item_added:
                entities.remove(item_added)
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if targeting:
                game_state = GameStates.TARGETING

                targeting_item = targeting
                targeting_radius = targeting.item.targeting_radius
                target_x = player.x
                target_y = player.y

                message_log.add_message(
                    Message("You begin aiming the {0}.".format(
                        targeting.name)))
                # TODO: Replace occurrences of add_message with player_turn_result approach
                # player_turn_results.append({'message': Message("You begin aiming the {0}.".format(targeting.name))})

            if next_floor:
                entities = game_map.next_floor(player, constants)
                fov_map = initialize_fov(game_map)
                tcod.console_clear(con)
示例#27
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   constants['colors'], game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        move = action.get('move')
        wait = action.get('wait')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        show_equipment_inventory = action.get('show_equipment_inventory')
        show_bag = action.get('show_bag')
        inventory_index = action.get('inventory_index')
        equipment_inventory_index = action.get('equipment_inventory_index')
        take_stairs = action.get('take_stairs')
        level_up = action.get('level_up')
        show_character_screen = action.get('show_character_screen')
        show_help_menu = action.get('show_help_menu')
        exit = action.get('exit')
        fullscreen = action.get('fullscreen')
        cast_magic_wand = action.get('cast_magic_wand')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if target:
                    attack_results = player.fighter.attack(target)
                    player_turn_results.extend(attack_results)
                else:
                    player.move(dx, dy)

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        elif wait:
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break

                elif entity.equipment_item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.equipment_inventory.add_equipment_item(
                        entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(
                    Message("There is nothing here to pick up...",
                            libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if show_equipment_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_EQUIPMENT_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if show_bag:
            previous_game_state = game_state
            game_state = GameStates.SHOW_BAG

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if equipment_inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and equipment_inventory_index < len(
                player.equipment_inventory.equipment_items):
            equipment_item = player.equipment_inventory.equipment_items[
                equipment_inventory_index]
            player_turn_results.extend(
                player.equipment_inventory.use_equipment(equipment_item))

        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(
                    Message("There are no stairs here...", libtcod.yellow))

        if cast_magic_wand and game_state == GameStates.PLAYERS_TURN:
            #item_component = Item(use_function=cast_magic, damage=2, maximum_range=3)
            message_log.add_message(
                Message("You use the magic wand...", libtcod.orange))
            game_state = GameStates.ENEMY_TURN

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1
            elif level_up == 'mgc':
                player.fighter.base_magic += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if show_help_menu:
            previous_game_state = game_state
            game_state = GameStates.HELP_MENU

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN,
                              GameStates.HELP_MENU,
                              GameStates.SHOW_EQUIPMENT_INVENTORY):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})
            elif game_state == GameStates.SHOW_BAG:
                game_state = GameStates.PLAYERS_TURN
            else:
                save_game(player, entities, game_map, message_log, game_state)

                return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            item_added = player_turn_result.get('item_added')
            equipment_item_added = player_turn_result.get(
                'equipment_item_added')
            item_consumed = player_turn_result.get('consumed')
            equipment_consumed = player_turn_result.get('equipment_consumed')
            item_dropped = player_turn_result.get('item_dropped')
            staff_used = player_turn_result.get('staff_used')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')

            if message:
                message_log.add_message(message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(
                    Message("You gain {0} experience points.".format(xp)))

                if leveled_up:
                    message_log.add_message(
                        Message(
                            "Your battle skills grow stronger! You reached level {0}"
                            .format(player.level.current_level) + "!",
                            libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)

                message_log.add_message(message)

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if equipment_item_added:
                entities.remove(equipment_item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if equipment_consumed:
                game_state = GameStates.ENEMY_TURN

            if staff_used:
                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if equip:
                equip_results = player.equipment.toggle_equip(equip)

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message_log.add_message(
                            Message("You equipped the {0}".format(
                                equipped.name)))

                    if dequipped:
                        message_log.add_message(
                            Message("You dequipped the {0}".format(
                                dequipped.name)))

                game_state = GameStates.ENEMY_TURN

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:

                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break
                    if game_state == GameStates.PLAYER_DEAD:
                        break
            else:
                game_state = GameStates.PLAYERS_TURN
示例#28
0
def play_game(player, entities, game_map, message_log, game_state, con, panel,
              constants):
    fov_recompute = True

    fov_map = initialize_fov(game_map)

    key = libtcod.Key()
    mouse = libtcod.Mouse()

    game_state = GameStates.PLAYERS_TURN
    previous_game_state = game_state

    targeting_item = None

    while not libtcod.console_is_window_closed():
        libtcod.sys_check_for_event(
            libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse)

        if fov_recompute:
            recompute_fov(fov_map, player.x, player.y, constants['fov_radius'],
                          constants['fov_light_walls'],
                          constants['fov_algorithm'])

        render_all(con, panel, entities, player, game_map, fov_map,
                   fov_recompute, message_log, constants['screen_width'],
                   constants['screen_height'], constants['bar_width'],
                   constants['panel_height'], constants['panel_y'], mouse,
                   constants['colors'], game_state)

        fov_recompute = False

        libtcod.console_flush()

        clear_all(con, entities)

        action = handle_keys(key, game_state)
        mouse_action = handle_mouse(mouse)

        move = action.get('move')
        aim_weapon = action.get('aim_weapon')
        wait = action.get('wait')
        pickup = action.get('pickup')
        show_inventory = action.get('show_inventory')
        drop_inventory = action.get('drop_inventory')
        inventory_index = action.get('inventory_index')
        take_stairs = action.get('take_stairs')
        show_character_screen = action.get('show_character_screen')
        exit = action.get('exit')
        level_up = action.get('level_up')
        fullscreen = action.get('fullscreen')
        exit_menu = action.get('exit_menu')

        left_click = mouse_action.get('left_click')
        right_click = mouse_action.get('right_click')

        player_turn_results = []

        if move and game_state == GameStates.PLAYERS_TURN:
            dx, dy = move
            destination_x = player.x + dx
            destination_y = player.y + dy

            if not game_map.is_blocked(destination_x, destination_y):
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)

                if dx == 0 and dy == 0:
                    player.move(dx, dy)

                    fov_recompute = True
                elif target:  # ATTACK!

                    if player.equipment.power_bonus == 4:
                        attack_results = player.fighter.basic_bow_attack(
                            target)
                        player_turn_results.extend(attack_results)

                    else:
                        attack_results = player.fighter.attack(target)
                        player_turn_results.extend(attack_results)

                else:
                    player.move(dx, dy)

                    fov_recompute = True

                game_state = GameStates.ENEMY_TURN

        elif aim_weapon and game_state == GameStates.PLAYERS_TURN:  # ALSO ATTACK! Working on this at the moment
            if player.equipment.power_bonus == 4 and game_state == GameStates.PLAYERS_TURN:
                message_log.add_message(
                    Message(
                        'Left click a tile to fire at it or right click to cancel!',
                        libtcod.yellow))
                game_state = GameStates.AIMING
            else:
                message_log.add_message(
                    Message('You do not have a ranged weapon equipped!',
                            libtcod.yellow))

        elif wait:
            game_state = GameStates.ENEMY_TURN

        elif pickup and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.item and entity.x == player.x and entity.y == player.y:
                    pickup_results = player.inventory.add_item(entity)
                    player_turn_results.extend(pickup_results)

                    break
            else:
                message_log.add_message(
                    Message('There is nothing here to pick up.',
                            libtcod.yellow))

        if show_inventory:
            previous_game_state = game_state
            game_state = GameStates.SHOW_INVENTORY

        if drop_inventory:
            previous_game_state = game_state
            game_state = GameStates.DROP_INVENTORY

        if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len(
                player.inventory.items):
            item = player.inventory.items[inventory_index]

            if game_state == GameStates.SHOW_INVENTORY:
                player_turn_results.extend(
                    player.inventory.use(item,
                                         entities=entities,
                                         fov_map=fov_map))
            elif game_state == GameStates.DROP_INVENTORY:
                player_turn_results.extend(player.inventory.drop_item(item))

        if take_stairs and game_state == GameStates.PLAYERS_TURN:
            for entity in entities:
                if entity.stairs and entity.x == player.x and entity.y == player.y:
                    entities = game_map.next_floor(player, message_log,
                                                   constants)
                    fov_map = initialize_fov(game_map)
                    fov_recompute = True
                    libtcod.console_clear(con)

                    break
            else:
                message_log.add_message(
                    Message('There are no stairs here.', libtcod.yellow))

        if level_up:
            if level_up == 'hp':
                player.fighter.base_max_hp += 20
                player.fighter.hp += 20
            elif level_up == 'str':
                player.fighter.base_power += 1
            elif level_up == 'def':
                player.fighter.base_defense += 1

            game_state = previous_game_state

        if show_character_screen:
            previous_game_state = game_state
            game_state = GameStates.CHARACTER_SCREEN

        if game_state == GameStates.TARGETING:
            if left_click:
                target_x, target_y = left_click

                item_use_results = player.inventory.use(targeting_item,
                                                        entities=entities,
                                                        fov_map=fov_map,
                                                        target_x=target_x,
                                                        target_y=target_y)
                player_turn_results.extend(item_use_results)
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if game_state == GameStates.AIMING:
            if left_click:
                target_x, target_y = left_click
                coordinates = target_x, target_y  # OKAY NOW WHAT THE F**K I DONT UNDESTAND WHY THIS WORKS OR HOW THE
                # VARIABLES GET FROM HERE TO THE FUNCTION I NEED THEM I MEAN JESUS CHRIST I JUST WOUND UP WITH THIS
                # ARRANGEMENT BY F*****G AROUND I MEAN IT WORKS BUT SERIOUSLY I DONT UNDERSTAND WHY THIS WORKS
                player_turn_results.append({'fire_weapon': True})
            elif right_click:
                player_turn_results.append({'targeting_cancelled': True})

        if exit_menu:
            if game_state in (GameStates.SHOW_INVENTORY,
                              GameStates.DROP_INVENTORY,
                              GameStates.CHARACTER_SCREEN):
                game_state = previous_game_state
            elif game_state == GameStates.TARGETING:
                player_turn_results.append({'targeting_cancelled': True})

        if exit:
            save_game(player, entities, game_map, message_log, game_state)

            return True

        if fullscreen:
            libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen())

        for player_turn_result in player_turn_results:
            message = player_turn_result.get('message')
            dead_entity = player_turn_result.get('dead')
            fire_weapon = player_turn_result.get('fire_weapon')
            item_added = player_turn_result.get('item_added')
            item_consumed = player_turn_result.get('consumed')
            item_dropped = player_turn_result.get('item_dropped')
            equip = player_turn_result.get('equip')
            targeting = player_turn_result.get('targeting')
            targeting_cancelled = player_turn_result.get('targeting_cancelled')
            xp = player_turn_result.get('xp')

            if fire_weapon:
                destination_x, destination_y = coordinates
                target = get_blocking_entities_at_location(
                    entities, destination_x, destination_y)
                try:
                    if target == player:
                        message_log.add_message(
                            Message(
                                'No hitting yourself. Targeting cancelled.',
                                libtcod.yellow))
                        game_state = previous_game_state
                    elif target.ai and libtcod.map_is_in_fov(
                            fov_map, target.x, target.y):
                        attack_results = player.fighter.basic_bow_attack(
                            target)
                        player_turn_results.extend(attack_results)
                        game_state = GameStates.ENEMY_TURN
                    elif target.ai and not libtcod.map_is_in_fov(
                            fov_map, target.x, target.y):
                        message_log.add_message(
                            Message(
                                'That cannot be targeted. Targeting cancelled.',
                                libtcod.yellow))
                        game_state = previous_game_state
                except:
                    message_log.add_message(
                        Message(
                            'That cannot be targeted. Targeting cancelled.',
                            libtcod.yellow))
                    game_state = previous_game_state

            if message:
                message_log.add_message(message)

            if dead_entity:
                if dead_entity == player:
                    message, game_state = kill_player(dead_entity)
                else:
                    message = kill_monster(dead_entity)
                message_log.add_message(message)
                if config.win == True:
                    game_state = GameStates.PLAYER_DEAD

            if game_state == GameStates.PLAYER_DEAD:
                break

            if item_added:
                entities.remove(item_added)

                game_state = GameStates.ENEMY_TURN

            if item_consumed:
                game_state = GameStates.ENEMY_TURN

            if item_dropped:
                entities.append(item_dropped)

                game_state = GameStates.ENEMY_TURN

            if equip:
                equip_results = player.equipment.toggle_equip(equip)

                for equip_result in equip_results:
                    equipped = equip_result.get('equipped')
                    dequipped = equip_result.get('dequipped')

                    if equipped:
                        message_log.add_message(
                            Message('You equipped the {0}'.format(
                                equipped.name)))

                    if dequipped:
                        message_log.add_message(
                            Message('You dequipped the {0}'.format(
                                dequipped.name)))

                game_state = GameStates.ENEMY_TURN

            if targeting:
                previous_game_state = GameStates.PLAYERS_TURN
                game_state = GameStates.TARGETING

                targeting_item = targeting

                message_log.add_message(targeting_item.item.targeting_message)

            if targeting_cancelled:
                game_state = previous_game_state

                message_log.add_message(Message('Targeting cancelled'))

            if xp:
                leveled_up = player.level.add_xp(xp)
                message_log.add_message(
                    Message('You gain {0} experience points.'.format(xp)))

                if leveled_up:
                    message_log.add_message(
                        Message(
                            'Your battle skills grow stronger! You reached level {0}'
                            .format(player.level.current_level) + '!',
                            libtcod.yellow))
                    previous_game_state = game_state
                    game_state = GameStates.LEVEL_UP

        if game_state == GameStates.ENEMY_TURN:
            for entity in entities:
                if entity.ai:
                    enemy_turn_results = entity.ai.take_turn(
                        player, fov_map, game_map, entities)

                    for enemy_turn_result in enemy_turn_results:
                        message = enemy_turn_result.get('message')
                        dead_entity = enemy_turn_result.get('dead')

                        if message:
                            message_log.add_message(message)

                        if dead_entity:
                            if dead_entity == player:
                                message, game_state = kill_player(dead_entity)
                            else:
                                message = kill_monster(dead_entity)

                            message_log.add_message(message)

                            if game_state == GameStates.PLAYER_DEAD:
                                break

                    if game_state == GameStates.PLAYER_DEAD:
                        break

            else:
                game_state = GameStates.PLAYERS_TURN
示例#29
0
def cast_sleep_aura(*args, **kwargs):
    caster = args[0]
    entities = kwargs.get('entities')
    fov_map = kwargs.get('fov_map')
    radius = kwargs.get('radius') + math.floor(caster.fighter.magic / 2)
    target_x = kwargs.get('target_x')
    target_y = kwargs.get('target_y')
    mana_cost = kwargs.get('mana_cost')

    if caster.fighter.magic + 5 >= 20:
        turns_asleep = 20
    else:
        turns_asleep = 5 + caster.fighter.magic

    results = []

    if caster.fighter.mana >= mana_cost:
        if not libtcod.map_is_in_fov(fov_map, target_x, target_y):
            results.append({
                'consumed':
                False,
                'message':
                Message(
                    "You can't target a location outside your field of view.",
                    libtcod.red)
            })
            return results

        results.append({
            'consumed':
            True,
            'message':
            Message(
                "You cast the sleeping aura, putting everything to sleep within {0} tiles!"
                .format(radius), libtcod.orange)
        })

        for entity in entities:
            if entity.distance(target_x, target_y) <= radius and entity.ai:
                asleep_ai = AsleepMonster(entity.ai, turns_asleep)

                asleep_ai.owner = entity
                entity.ai = asleep_ai

                results.append({
                    'message':
                    Message(
                        "The {0} is asleep for {1} turns.".format(
                            entity.name, turns_asleep), libtcod.orange)
                })
                results.extend(caster.fighter.use_mana(mana_cost))

    else:
        results.append({
            'consumed':
            False,
            'target':
            None,
            'message':
            Message("You don't have enough mana!", libtcod.orange)
        })

    return results
def kill_player(player):
    """Change char and color for death."""
    player.char = '%'
    player.color = libtcod.dark_red

    return Message('You died!', libtcod.red), GameStates.PLAYER_DEAD