Skip to content

Commit

Permalink
progress replicating packages
Browse files Browse the repository at this point in the history
  • Loading branch information
ManApart committed Jan 24, 2024
1 parent 167d638 commit 70d6526
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 34 deletions.
22 changes: 12 additions & 10 deletions src/commonMain/kotlin/core/ai/packages/AIPackageTemplateBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ package core.ai.packages

import core.thing.Thing

//Build all the templates, but don't flatten them
//Using the dependency injection, we could have many things producing the templates
//Once all templates generated, validate / transform them into ai packages
//A mind references a single ai package by string
//Ideas _should_ only have a single instance, so can possibly be optimized

// How do we specify additional priority? Do we need to?

class AIPackageTemplateBuilder(val name: String) {
private val templates = mutableListOf<String>()
Expand All @@ -26,20 +23,25 @@ class AIPackageTemplateBuilder(val name: String) {
/**
Override the priority of an idea inherited from a template.
*/
fun priority(ideaName: String, newPriority: Int){
fun priority(ideaName: String, newPriority: Int) {
priorityOverride[ideaName] = newPriority
}

fun drop(vararg ideaName: String){
fun drop(vararg ideaName: String) {
dropped.addAll(ideaName)
}

fun idea(name: String, priority: Int = 20, initializer: IdeaBuilder.() -> Unit = {}) {
ideas.add(IdeaBuilder(name, priority).apply(initializer))
}

fun criteria(criteria: suspend (Thing) -> Boolean, initializer: IdeasBuilder.() -> Unit){
criteriaChildren[criteria] = IdeasBuilder().apply(initializer)
fun tagged(tag: String, initializer: IdeasBuilder.() -> Unit) {
val cond: suspend (Thing) -> Boolean = { it.properties.tags.has(tag) }
criteriaChildren[cond] = IdeasBuilder().apply(initializer)
}

fun cond(condition: suspend (Thing) -> Boolean, initializer: IdeasBuilder.() -> Unit) {
criteriaChildren[condition] = IdeasBuilder().apply(initializer)
}

}
Expand All @@ -51,11 +53,11 @@ fun aiPackage(name: String, initializer: AIPackageTemplateBuilder.() -> Unit): A

class AIPackageTemplatesBuilder {
internal val children = mutableListOf<AIPackageTemplateBuilder>()
fun aiPackage(item: AIPackageTemplateBuilder){
fun aiPackage(item: AIPackageTemplateBuilder) {
children.add(item)
}

fun aiPackage(name: String, initializer: AIPackageTemplateBuilder.() -> Unit){
fun aiPackage(name: String, initializer: AIPackageTemplateBuilder.() -> Unit) {
children.add(AIPackageTemplateBuilder(name).apply(initializer))
}

Expand Down
6 changes: 3 additions & 3 deletions src/commonMain/kotlin/core/ai/packages/IdeaBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ class IdeaBuilder(val name: String, val priority: Int) {

fun build(packageName: String) = Idea("$packageName-$name", priority, criteria, action)

fun criteria(criteria: suspend (Thing) -> Boolean) {
this.criteria = criteria
fun cond(condition: suspend (Thing) -> Boolean) {
this.criteria = condition
}

fun actions(action: suspend (Thing) -> List<Event>) {
this.action = action
}

fun action(action: suspend (Thing) -> Event) {
fun act(action: suspend (Thing) -> Event) {
this.action = { listOf(action(it)) }
}

Expand Down
102 changes: 81 additions & 21 deletions src/commonMain/kotlin/resources/ai/packages/CommonPackages.kt
Original file line number Diff line number Diff line change
@@ -1,36 +1,96 @@
package resources.ai.packages

import combat.DamageType
import combat.attack.AttackEvent
import combat.attack.startAttack
import core.GameState
import core.ai.knowledge.DiscoverFactEvent
import core.ai.knowledge.Fact
import core.ai.knowledge.Subject
import core.ai.packages.AIPackageTemplateResource
import core.ai.packages.aiPackages
import core.events.Event
import core.properties.Properties
import core.properties.Values
import core.thing.Thing
import core.utility.RandomManager
import status.rest.RestEvent
import status.stat.STAMINA
import traveling.move.startMoveEvent
import traveling.position.ThingAim
import use.eat.EatFoodEvent
import use.interaction.nothing.NothingEvent

class CommonPackages: AIPackageTemplateResource {
override val values = aiPackages {
aiPackage("animal") {
criteria({ !it.isSafe() }) {
criteria({ !it.isSafe() }) {
idea("eat", 10) {
criteria { !it.isSafe() }
action { EatFoodEvent(it, it) }
}
idea("wait") {
criteria { !it.isSafe() }
action { EatFoodEvent(it, it) }
}
class CommonPackages : AIPackageTemplateResource {
override val values = aiPackages {
aiPackage("creature") {

idea("Rest") {
cond { s -> s.soul.getCurrent(STAMINA) < s.soul.getTotal(STAMINA) / 10 }
act { RestEvent(it, 2) }
}

idea("Attack", 70) {
cond { it.mind.getAggroTarget() != null }
act {
clawAttack(it.mind.getAggroTarget()!!, it)
}
}

//TODO - need move to location as well
idea("Move to Use Target", 50) {
cond { it.hasUseTarget() && !it.canReach(it.mind.getUseTarget()!!.position) }
act { startMoveEvent(it, destination = it.mind.getUseTarget()!!.position) }
}

idea("Eat Targeted Food", 50) {
//TODO get fact itself, check properties to see if goal is eat
cond {
val useTarget = it.mind.getUseTarget()
useTarget != null && it.canReach(useTarget.position)
}
act { EatFoodEvent(it, it.mind.getUseTarget()!!) }
}
}
aiPackage("predator") {
template("animal")
priority("animal-eat", 15)
drop("animal-wait")

idea("hunt") {
criteria { it.soul.getConditions().isEmpty() }
action { RestEvent(it, 1) }

aiPackage("Commoner") {
template("creature")
idea("Want Food") {
cond { GameState.timeManager.getPercentDayComplete() in listOf(25, 50, 75) }
act { owner ->
val target = (owner.inventory.getItems() + owner.location.getLocation().getItems(perceivedBy = owner)).firstOrNull { it.properties.tags.has("Food") }
target?.let {
owner.setGoal(target, "eat")
} ?: NothingEvent(owner)
}
}
}

}
}

private suspend fun Thing.hasUseTarget() = mind.getUseTarget() != null

private fun Thing.setGoal(target: Thing, howToUse: String): DiscoverFactEvent{
return DiscoverFactEvent(this, Fact(Subject(target), "useTarget", Properties(Values(mutableMapOf("goal" to howToUse)))))
}

//TODO - forget goal
private fun Thing.clearGoal(target: Thing, howToUse: String): List<Event>{
return emptyList()
}

private suspend fun clawAttack(target: Thing, creature: Thing): AttackEvent {
val enemyBody = target.body
val possibleParts = listOf(
enemyBody.getPart("Right Foot"),
enemyBody.getPart("Left Foot")
)
val thingPart = listOf(RandomManager.getRandom(possibleParts))
val partToAttackWith = if (creature.body.hasPart("Small Claws")) {
creature.body.getPart("Small Claws")
} else {
creature.body.getRootPart()
}
return startAttack(creature, partToAttackWith, ThingAim(GameState.player.thing, thingPart), DamageType.SLASH)
}

0 comments on commit 70d6526

Please sign in to comment.