Skip to content

Commit

Permalink
Character examples
Browse files Browse the repository at this point in the history
  • Loading branch information
RowDaBoat committed Jun 22, 2024
1 parent e7a442c commit 524b5c1
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Then create a main character, it requires a key (`"player"`) to identify it, and
val mainCharacter = mainCharacter("player", "you")
```

Then create a scene, it requires a key (`"hello-keep""`) to identify it, and a title name to display (`"Hello Keep""`), scenes usually also have a `narration` as third argument to provide context to the player. The last argument is very important, but we won't use it for now so we just use an empty action list using `actions()`.
Then create a scene, it requires a key (`"hello-keep"`) to identify it, and a title name to display (`"Hello Keep""`), scenes usually also have a `narration` as third argument to provide context to the player. The last argument is very important, but we won't use it for now so we just use an empty action list using `actions()`.

```kotlin
val scene = Scene("hello-keep", "Hello Keep", "Keep is a text game engine.", actions())
Expand Down
53 changes: 50 additions & 3 deletions doc/characters.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
# Keep Engine
# Keep Engine - Characters

## Characters
## Simple characters

##
Simple characters are declared using the `npc` function with a `key` to identify them, a display `name`, and a `description`. Typically, a callback is registered using `onTalk`, it will be called when the `Talk` action is used on the character.

The following example shows Bob, who can be talked to by the player and will answer back.

```kotlin
val bob =
npc(
"bob",
"Bob",
"Bob, an NPC."
) onTalk {
io.paragraph("${target.name}: Hello ${game.mainCharacter.name}!.")
io.promptContinue()
}
```

## Stateful Characters

Characters can also hold state, allowing them to react to the world and the player's actions. Use an overload of the `npc` function, and declare `key`, `initialState` and `states` parameters.

Each state has its own `key`, also the state has `name` and `description` properties that replace the character's ones. Each state can have its own subscriptions to `onTalk` or any other actions, allowing the character to change its dialogues and behavior. Name and description are set on each state to make it easy to reflect changes on each character.

The following example shows Alice, who greets the player by his name only once.

```kotlin
val alice =
npc(
"alice",
"first-time",
characterState(
"first-time",
"Alice",
"Alice, another NPC.",
) onTalk {
io.paragraph("${target.name}: Oh, hi ${game.mainCharacter.name}!.")
target.change("regular")
io.promptContinue()
},
characterState(
"regular",
"Alice",
"Alice, another NPC.",
) onTalk {
io.paragraph("${target.name}: Hello.")
io.promptContinue()
}
)
```
2 changes: 1 addition & 1 deletion doc/items.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ val potion =

Items can hold state, allowing the world to react and be modified by the player's actions. Use an overload of the `item` function, and declare `key`, `initialState` and `states` parameters.

Each state has its own `key`, also the state have `name` and `description` properties that replace the item ones. Each state can have its own subscriptions to `onUse` and other actions, allowing the item to change its behavior.
Each state has its own `key`, also the state has `name` and `description` properties that replace the item's ones. Each state can have its own subscriptions to `onUse` or any other actions, allowing the item to change its behavior.

The following example shows a switch that can be turned on or off by the player.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
package tech.alephia.keep.samples.advanced.characters

import tech.alephia.keep.core.entities.characters.characterState
import tech.alephia.keep.core.entities.characters.npc
import tech.alephia.keep.core.events.onTalk

val alice =
npc(
"alice",
"Alice",
"Alice, another NPC."
) onTalk {
io.paragraph("${target.name}: Hi, how have you been?")
io.promptContinue()
}
"first-time",
characterState(
"first-time",
"Alice",
"Alice, another NPC.",
) onTalk {
io.paragraph("${target.name}: Oh, hi ${game.mainCharacter.name}!.")
target.change("regular")
io.promptContinue()
},
characterState(
"regular",
"Alice",
"Alice, another NPC.",
) onTalk {
io.paragraph("${target.name}: Hello.")
io.promptContinue()
}
)
35 changes: 29 additions & 6 deletions src/main/kotlin/tech/alephia/keep/core/entities/characters/dsl.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package tech.alephia.keep.core.entities.characters

import tech.alephia.keep.core.entities.items.IndefiniteArticle
import tech.alephia.keep.core.entities.items.ItemState
import tech.alephia.keep.core.entities.items.defaultItemSubscriptions
import tech.alephia.keep.core.events.Subscriptions
import tech.alephia.keep.core.storages.ItemStorage

Expand All @@ -10,27 +13,47 @@ fun mainCharacter(
inventory: ItemStorage = mainCharacterInventory()
) =
singleState(name, description)
.let { mainCharacter(key, inventory, it.key, it) }
.let { mainCharacter(key, it.key, inventory, it) }

fun mainCharacter(
key: String,
inventory: ItemStorage = mainCharacterInventory(),
initialState: String,
inventory: ItemStorage = mainCharacterInventory(),
vararg states: CharacterState
): Character =
SimpleCharacter(key, inventory, initialState, states.toList(), Subscriptions())

fun npc(key: String, name: String, description: String = "", inventory: ItemStorage = ItemStorage()) =
singleState(name, description).let { npc(key, inventory, it.key, it) }
fun npc(
key: String,
name: String,
description: String = "",
inventory: ItemStorage = ItemStorage()
) =
singleState(name, description)
.let { npc(key, it.key, inventory, it) }


fun npc(
key: String,
inventory: ItemStorage = ItemStorage(),
initialState: String,
vararg states: CharacterState
): Character =
SimpleCharacter(key, ItemStorage(), initialState, states.toList(), Subscriptions())

fun npc(
key: String,
initialState: String,
inventory: ItemStorage = ItemStorage(),
vararg states: CharacterState
): Character =
SimpleCharacter(key, inventory, initialState, states.toList(), Subscriptions())

fun characterState(
key: String,
name: String,
description: String = "",
) = CharacterState(key, name, description, Subscriptions())

private fun mainCharacterInventory() =
ItemStorage(
listOf(),
Expand All @@ -40,4 +63,4 @@ private fun mainCharacterInventory() =
)

private fun singleState(name: String, description: String) =
CharacterState("single-state", name, description, Subscriptions())
characterState("single-state", name, description)

0 comments on commit 524b5c1

Please sign in to comment.