Skip to content

Commit 700c6a4

Browse files
author
adam-arold
committed
Add aggressive monsters
1 parent 31d36b5 commit 700c6a4

9 files changed

Lines changed: 85 additions & 21 deletions

File tree

src/main/kotlin/org/hexworks/cavesofzircon/GameConfig.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ object GameConfig {
2727
const val BATS_PER_LEVEL = 10
2828
const val ZIRCONS_PER_LEVEL = 20
2929
const val MAXIMUM_FUNGUS_SPREAD = 20
30-
const val WEAPONS_PER_LEVEL = 3
31-
const val ARMOR_PER_LEVEL = 3
30+
const val ZOMBIES_PER_LEVEL = 3
3231

3332
fun buildAppConfig() = AppConfigs.newConfig()
3433
.enableBetaFeatures()

src/main/kotlin/org/hexworks/cavesofzircon/attributes/Equipment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ class Equipment(initialWeapon: GameEntity<Weapon>,
3131
val weaponName: String
3232
get() = weaponProperty.value.name
3333

34-
private val weapon: GameEntity<Weapon> by weaponProperty.asDelegate()
35-
private val armor: GameEntity<Armor> by armorProperty.asDelegate()
34+
val weapon: GameEntity<Weapon> by weaponProperty.asDelegate()
35+
val armor: GameEntity<Armor> by armorProperty.asDelegate()
3636

3737
private val weaponStats: String
3838
get() = " A: ${weapon.attackValue} D: ${weapon.defenseValue}"

src/main/kotlin/org/hexworks/cavesofzircon/attributes/types/EntityTypes.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ object Fungus : BaseEntityType(
1414
object Bat : BaseEntityType(
1515
name = "bat"), Combatant, ItemHolder
1616

17+
object Zombie : BaseEntityType(
18+
name = "zombie"), Combatant, ItemHolder
19+
1720
object BatMeat : BaseEntityType(
1821
name = "Bat meat",
1922
description = "Stringy bat meat. It is edible, but not tasty."), Food

src/main/kotlin/org/hexworks/cavesofzircon/builders/EntityFactory.kt

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import org.hexworks.cavesofzircon.attributes.types.Sword
3535
import org.hexworks.cavesofzircon.attributes.types.Wall
3636
import org.hexworks.cavesofzircon.attributes.types.Weapon
3737
import org.hexworks.cavesofzircon.attributes.types.Zircon
38+
import org.hexworks.cavesofzircon.attributes.types.Zombie
3839
import org.hexworks.cavesofzircon.commands.Attack
3940
import org.hexworks.cavesofzircon.commands.Dig
4041
import org.hexworks.cavesofzircon.entities.FogOfWar
@@ -45,8 +46,8 @@ import org.hexworks.cavesofzircon.systems.Destructible
4546
import org.hexworks.cavesofzircon.systems.DigestiveSystem
4647
import org.hexworks.cavesofzircon.systems.Diggable
4748
import org.hexworks.cavesofzircon.systems.EnergyExpender
48-
import org.hexworks.cavesofzircon.systems.EquipmentHandler
4949
import org.hexworks.cavesofzircon.systems.FungusGrowth
50+
import org.hexworks.cavesofzircon.systems.HunterSeeker
5051
import org.hexworks.cavesofzircon.systems.InputReceiver
5152
import org.hexworks.cavesofzircon.systems.InventoryInspector
5253
import org.hexworks.cavesofzircon.systems.ItemDropper
@@ -105,7 +106,7 @@ object EntityFactory {
105106
initialWeapon = newClub(),
106107
initialArmor = newJacket()))
107108
behaviors(InputReceiver, EnergyExpender)
108-
facets(EquipmentHandler, Movable, CameraMover, StairClimber, StairDescender, Attackable, Destructible,
109+
facets(Movable, CameraMover, StairClimber, StairDescender, Attackable, Destructible,
109110
ItemPicker, InventoryInspector, ItemDropper, EnergyExpender, DigestiveSystem)
110111
}
111112

@@ -138,6 +139,24 @@ object EntityFactory {
138139
behaviors(Wanderer)
139140
}
140141

142+
fun newZombie() = newGameEntityOfType(Zombie) {
143+
attributes(BlockOccupier,
144+
EntityPosition(),
145+
EntityTile(GameTileRepository.ZOMBIE),
146+
Vision(10),
147+
CombatStats.create(
148+
maxHp = 25,
149+
attackValue = 8,
150+
defenseValue = 4),
151+
Inventory(2).apply {
152+
addItem(newRandomWeapon())
153+
addItem(newRandomArmor())
154+
},
155+
EntityActions(Attack::class))
156+
facets(Movable, Attackable, ItemDropper, LootDropper, Destructible)
157+
behaviors(HunterSeeker or Wanderer)
158+
}
159+
141160
fun newBatMeat() = newGameEntityOfType(BatMeat) {
142161
attributes(ItemIcon(Tiles.newBuilder()
143162
.withName("Meatball")
@@ -261,5 +280,7 @@ object EntityFactory {
261280
1 -> newMediumArmor()
262281
else -> newHeavyArmor()
263282
}
283+
284+
264285
}
265286

src/main/kotlin/org/hexworks/cavesofzircon/builders/GameColors.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ object GameColors {
1515
val ACCENT_COLOR = TileColors.fromString("#FFCD22")
1616
val ZIRCON_COLOR = TileColors.fromString("#dddddd")
1717
val BAT_MEAT_COLOR = TileColors.fromString("#EA4861")
18+
val ZOMBIE_COLOR = TileColors.fromString("#618358")
1819

1920
val UNREVEALED_COLOR = TileColors.fromString("#000000")
2021
}

src/main/kotlin/org/hexworks/cavesofzircon/builders/GameTileRepository.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,10 @@ object GameTileRepository {
115115
.withForegroundColor(ANSITileColor.BRIGHT_WHITE)
116116
.withBackgroundColor(GameColors.FLOOR_BACKGROUND)
117117
.buildCharacterTile()
118+
119+
val ZOMBIE = Tiles.newBuilder()
120+
.withCharacter('z')
121+
.withForegroundColor(GameColors.ZOMBIE_COLOR)
122+
.withBackgroundColor(GameColors.FLOOR_BACKGROUND)
123+
.buildCharacterTile()
118124
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.hexworks.cavesofzircon.systems
2+
3+
import org.hexworks.amethyst.api.base.BaseBehavior
4+
import org.hexworks.amethyst.api.entity.EntityType
5+
import org.hexworks.cavesofzircon.commands.MoveTo
6+
import org.hexworks.cavesofzircon.extensions.GameEntity
7+
import org.hexworks.cavesofzircon.extensions.position
8+
import org.hexworks.cavesofzircon.world.GameContext
9+
import org.hexworks.zircon.api.Positions
10+
11+
object HunterSeeker : BaseBehavior<GameContext>() {
12+
13+
override fun update(entity: GameEntity<out EntityType>, context: GameContext): Boolean {
14+
val (world, _, _, player) = context
15+
var hunted = false
16+
world.whenCanSee(entity, player) { path ->
17+
entity.executeCommand(MoveTo(
18+
context = context,
19+
source = entity,
20+
position = Positions.from2DTo3D(path.iterator().next(), player.position.z)))
21+
hunted = true
22+
}
23+
return hunted
24+
}
25+
}

src/main/kotlin/org/hexworks/cavesofzircon/world/GameBuilder.kt

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ package org.hexworks.cavesofzircon.world
22

33
import org.hexworks.amethyst.api.entity.EntityType
44
import org.hexworks.cavesofzircon.GameConfig
5-
import org.hexworks.cavesofzircon.GameConfig.ARMOR_PER_LEVEL
65
import org.hexworks.cavesofzircon.GameConfig.BATS_PER_LEVEL
7-
import org.hexworks.cavesofzircon.GameConfig.WEAPONS_PER_LEVEL
86
import org.hexworks.cavesofzircon.GameConfig.WORLD_SIZE
97
import org.hexworks.cavesofzircon.attributes.types.Player
108
import org.hexworks.cavesofzircon.builders.EntityFactory
@@ -33,8 +31,7 @@ class GameBuilder(val worldSize: Size3D = WORLD_SIZE) {
3331
addFungi()
3432
addBats()
3533
addZircons()
36-
addWeapons()
37-
addArmor()
34+
addZombies()
3835

3936
val game = Game.create(
4037
player = player,
@@ -79,18 +76,10 @@ class GameBuilder(val worldSize: Size3D = WORLD_SIZE) {
7976
}
8077
}
8178

82-
private fun addWeapons() = also {
79+
private fun addZombies() = also {
8380
repeat(world.actualSize().zLength) { level ->
84-
repeat(WEAPONS_PER_LEVEL) {
85-
EntityFactory.newRandomWeapon().addToWorld(level)
86-
}
87-
}
88-
}
89-
90-
private fun addArmor() = also {
91-
repeat(world.actualSize().zLength) { level ->
92-
repeat(ARMOR_PER_LEVEL) {
93-
EntityFactory.newRandomArmor().addToWorld(level)
81+
repeat(GameConfig.ZOMBIES_PER_LEVEL) {
82+
EntityFactory.newZombie().addToWorld(level)
9483
}
9584
}
9685
}

src/main/kotlin/org/hexworks/cavesofzircon/world/World.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.hexworks.zircon.api.screen.Screen
2424
import org.hexworks.zircon.api.shape.EllipseFactory
2525
import org.hexworks.zircon.api.shape.LineFactory
2626
import org.hexworks.zircon.api.uievent.UIEvent
27+
import kotlin.math.abs
2728

2829
class World(startingBlocks: Map<Position3D, GameBlock>,
2930
visibleSize: Size3D,
@@ -150,6 +151,25 @@ class World(startingBlocks: Map<Position3D, GameBlock>,
150151
}.orElse(listOf())
151152
}
152153

154+
fun whenCanSee(looker: GameEntity<EntityType>, target: GameEntity<EntityType>, fn: (path: List<Position>) -> Unit) {
155+
looker.findAttribute(Vision::class).map { (radius) ->
156+
val level = looker.position.z
157+
if (looker.position.isWithinRangeOf(target.position, radius)) {
158+
val path = LineFactory.buildLine(looker.position.to2DPosition(), target.position.to2DPosition())
159+
if (path.none { isVisionBlockedAt(Positions.from2DTo3D(it, level)) }) {
160+
fn(path.positions().toList().drop(1))
161+
}
162+
}
163+
}
164+
}
165+
166+
private fun Position3D.isWithinRangeOf(other: Position3D, radius: Int): Boolean {
167+
return this.isUnknown().not()
168+
&& other.isUnknown().not()
169+
&& this.z == other.z
170+
&& abs(x - other.x) + abs(y - other.y) <= radius
171+
}
172+
153173
companion object {
154174
private val DEFAULT_BLOCK = GameBlockFactory.floor()
155175
}

0 commit comments

Comments
 (0)