Skip to content

Commit

Permalink
Add aggressive monsters
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-arold committed Jun 23, 2019
1 parent 31d36b5 commit 700c6a4
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 21 deletions.
3 changes: 1 addition & 2 deletions src/main/kotlin/org/hexworks/cavesofzircon/GameConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ object GameConfig {
const val BATS_PER_LEVEL = 10
const val ZIRCONS_PER_LEVEL = 20
const val MAXIMUM_FUNGUS_SPREAD = 20
const val WEAPONS_PER_LEVEL = 3
const val ARMOR_PER_LEVEL = 3
const val ZOMBIES_PER_LEVEL = 3

fun buildAppConfig() = AppConfigs.newConfig()
.enableBetaFeatures()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class Equipment(initialWeapon: GameEntity<Weapon>,
val weaponName: String
get() = weaponProperty.value.name

private val weapon: GameEntity<Weapon> by weaponProperty.asDelegate()
private val armor: GameEntity<Armor> by armorProperty.asDelegate()
val weapon: GameEntity<Weapon> by weaponProperty.asDelegate()
val armor: GameEntity<Armor> by armorProperty.asDelegate()

private val weaponStats: String
get() = " A: ${weapon.attackValue} D: ${weapon.defenseValue}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ object Fungus : BaseEntityType(
object Bat : BaseEntityType(
name = "bat"), Combatant, ItemHolder

object Zombie : BaseEntityType(
name = "zombie"), Combatant, ItemHolder

object BatMeat : BaseEntityType(
name = "Bat meat",
description = "Stringy bat meat. It is edible, but not tasty."), Food
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import org.hexworks.cavesofzircon.attributes.types.Sword
import org.hexworks.cavesofzircon.attributes.types.Wall
import org.hexworks.cavesofzircon.attributes.types.Weapon
import org.hexworks.cavesofzircon.attributes.types.Zircon
import org.hexworks.cavesofzircon.attributes.types.Zombie
import org.hexworks.cavesofzircon.commands.Attack
import org.hexworks.cavesofzircon.commands.Dig
import org.hexworks.cavesofzircon.entities.FogOfWar
Expand All @@ -45,8 +46,8 @@ import org.hexworks.cavesofzircon.systems.Destructible
import org.hexworks.cavesofzircon.systems.DigestiveSystem
import org.hexworks.cavesofzircon.systems.Diggable
import org.hexworks.cavesofzircon.systems.EnergyExpender
import org.hexworks.cavesofzircon.systems.EquipmentHandler
import org.hexworks.cavesofzircon.systems.FungusGrowth
import org.hexworks.cavesofzircon.systems.HunterSeeker
import org.hexworks.cavesofzircon.systems.InputReceiver
import org.hexworks.cavesofzircon.systems.InventoryInspector
import org.hexworks.cavesofzircon.systems.ItemDropper
Expand Down Expand Up @@ -105,7 +106,7 @@ object EntityFactory {
initialWeapon = newClub(),
initialArmor = newJacket()))
behaviors(InputReceiver, EnergyExpender)
facets(EquipmentHandler, Movable, CameraMover, StairClimber, StairDescender, Attackable, Destructible,
facets(Movable, CameraMover, StairClimber, StairDescender, Attackable, Destructible,
ItemPicker, InventoryInspector, ItemDropper, EnergyExpender, DigestiveSystem)
}

Expand Down Expand Up @@ -138,6 +139,24 @@ object EntityFactory {
behaviors(Wanderer)
}

fun newZombie() = newGameEntityOfType(Zombie) {
attributes(BlockOccupier,
EntityPosition(),
EntityTile(GameTileRepository.ZOMBIE),
Vision(10),
CombatStats.create(
maxHp = 25,
attackValue = 8,
defenseValue = 4),
Inventory(2).apply {
addItem(newRandomWeapon())
addItem(newRandomArmor())
},
EntityActions(Attack::class))
facets(Movable, Attackable, ItemDropper, LootDropper, Destructible)
behaviors(HunterSeeker or Wanderer)
}

fun newBatMeat() = newGameEntityOfType(BatMeat) {
attributes(ItemIcon(Tiles.newBuilder()
.withName("Meatball")
Expand Down Expand Up @@ -261,5 +280,7 @@ object EntityFactory {
1 -> newMediumArmor()
else -> newHeavyArmor()
}


}

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ object GameColors {
val ACCENT_COLOR = TileColors.fromString("#FFCD22")
val ZIRCON_COLOR = TileColors.fromString("#dddddd")
val BAT_MEAT_COLOR = TileColors.fromString("#EA4861")
val ZOMBIE_COLOR = TileColors.fromString("#618358")

val UNREVEALED_COLOR = TileColors.fromString("#000000")
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,10 @@ object GameTileRepository {
.withForegroundColor(ANSITileColor.BRIGHT_WHITE)
.withBackgroundColor(GameColors.FLOOR_BACKGROUND)
.buildCharacterTile()

val ZOMBIE = Tiles.newBuilder()
.withCharacter('z')
.withForegroundColor(GameColors.ZOMBIE_COLOR)
.withBackgroundColor(GameColors.FLOOR_BACKGROUND)
.buildCharacterTile()
}
25 changes: 25 additions & 0 deletions src/main/kotlin/org/hexworks/cavesofzircon/systems/HunterSeeker.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.hexworks.cavesofzircon.systems

import org.hexworks.amethyst.api.base.BaseBehavior
import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.commands.MoveTo
import org.hexworks.cavesofzircon.extensions.GameEntity
import org.hexworks.cavesofzircon.extensions.position
import org.hexworks.cavesofzircon.world.GameContext
import org.hexworks.zircon.api.Positions

object HunterSeeker : BaseBehavior<GameContext>() {

override fun update(entity: GameEntity<out EntityType>, context: GameContext): Boolean {
val (world, _, _, player) = context
var hunted = false
world.whenCanSee(entity, player) { path ->
entity.executeCommand(MoveTo(
context = context,
source = entity,
position = Positions.from2DTo3D(path.iterator().next(), player.position.z)))
hunted = true
}
return hunted
}
}
19 changes: 4 additions & 15 deletions src/main/kotlin/org/hexworks/cavesofzircon/world/GameBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package org.hexworks.cavesofzircon.world

import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.cavesofzircon.GameConfig
import org.hexworks.cavesofzircon.GameConfig.ARMOR_PER_LEVEL
import org.hexworks.cavesofzircon.GameConfig.BATS_PER_LEVEL
import org.hexworks.cavesofzircon.GameConfig.WEAPONS_PER_LEVEL
import org.hexworks.cavesofzircon.GameConfig.WORLD_SIZE
import org.hexworks.cavesofzircon.attributes.types.Player
import org.hexworks.cavesofzircon.builders.EntityFactory
Expand Down Expand Up @@ -33,8 +31,7 @@ class GameBuilder(val worldSize: Size3D = WORLD_SIZE) {
addFungi()
addBats()
addZircons()
addWeapons()
addArmor()
addZombies()

val game = Game.create(
player = player,
Expand Down Expand Up @@ -79,18 +76,10 @@ class GameBuilder(val worldSize: Size3D = WORLD_SIZE) {
}
}

private fun addWeapons() = also {
private fun addZombies() = also {
repeat(world.actualSize().zLength) { level ->
repeat(WEAPONS_PER_LEVEL) {
EntityFactory.newRandomWeapon().addToWorld(level)
}
}
}

private fun addArmor() = also {
repeat(world.actualSize().zLength) { level ->
repeat(ARMOR_PER_LEVEL) {
EntityFactory.newRandomArmor().addToWorld(level)
repeat(GameConfig.ZOMBIES_PER_LEVEL) {
EntityFactory.newZombie().addToWorld(level)
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/main/kotlin/org/hexworks/cavesofzircon/world/World.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.hexworks.zircon.api.screen.Screen
import org.hexworks.zircon.api.shape.EllipseFactory
import org.hexworks.zircon.api.shape.LineFactory
import org.hexworks.zircon.api.uievent.UIEvent
import kotlin.math.abs

class World(startingBlocks: Map<Position3D, GameBlock>,
visibleSize: Size3D,
Expand Down Expand Up @@ -150,6 +151,25 @@ class World(startingBlocks: Map<Position3D, GameBlock>,
}.orElse(listOf())
}

fun whenCanSee(looker: GameEntity<EntityType>, target: GameEntity<EntityType>, fn: (path: List<Position>) -> Unit) {
looker.findAttribute(Vision::class).map { (radius) ->
val level = looker.position.z
if (looker.position.isWithinRangeOf(target.position, radius)) {
val path = LineFactory.buildLine(looker.position.to2DPosition(), target.position.to2DPosition())
if (path.none { isVisionBlockedAt(Positions.from2DTo3D(it, level)) }) {
fn(path.positions().toList().drop(1))
}
}
}
}

private fun Position3D.isWithinRangeOf(other: Position3D, radius: Int): Boolean {
return this.isUnknown().not()
&& other.isUnknown().not()
&& this.z == other.z
&& abs(x - other.x) + abs(y - other.y) <= radius
}

companion object {
private val DEFAULT_BLOCK = GameBlockFactory.floor()
}
Expand Down

0 comments on commit 700c6a4

Please sign in to comment.