mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-29 08:55:42 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8d7e03afe |
@@ -6,4 +6,3 @@
|
||||
*.bytes filter=lfs diff=lfs merge=lfs -text
|
||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
*.tsv filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
+3
-3
@@ -48,8 +48,9 @@ public class AvailableGameItem : MonoBehaviour {
|
||||
joinButton.interactable = true;
|
||||
buttonText.text = "JOIN";
|
||||
|
||||
List<HeroView> heroOptions =
|
||||
new List<HeroView> { new() { Id = 0, Profession = Profession.NoProfession } };
|
||||
List<HeroView> heroOptions = new List<HeroView> {
|
||||
new() { Name = "Random", Id = 0, Profession = Profession.NoProfession }
|
||||
};
|
||||
for (int i = 0; i < leaders.Count; i++) {
|
||||
var leader = leaders[i];
|
||||
heroOptions.Add(new HeroView {
|
||||
@@ -59,7 +60,6 @@ public class AvailableGameItem : MonoBehaviour {
|
||||
});
|
||||
}
|
||||
|
||||
heroDropdownController.FallbackText = "Random";
|
||||
heroDropdownController.AvailableHeroes = heroOptions;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -60,8 +60,9 @@ public class CreateGameItem : MonoBehaviour {
|
||||
|
||||
buttonText.text = "CREATE";
|
||||
|
||||
List<HeroView> heroOptions =
|
||||
new List<HeroView> { new() { Id = 0, Profession = Profession.NoProfession } };
|
||||
List<HeroView> heroOptions = new List<HeroView> {
|
||||
new HeroView { Name = "Random", Id = 0, Profession = Profession.NoProfession }
|
||||
};
|
||||
for (int i = 0; i < leaders.Count; i++) {
|
||||
var leader = leaders[i];
|
||||
heroOptions.Add(new HeroView {
|
||||
@@ -72,7 +73,6 @@ public class CreateGameItem : MonoBehaviour {
|
||||
});
|
||||
}
|
||||
|
||||
heroDropdownController.FallbackText = "Random";
|
||||
heroDropdownController.AvailableHeroes = heroOptions;
|
||||
heroDropdownController.HeadshotImage.gameObject.SetActive(false);
|
||||
|
||||
|
||||
+32
-22
@@ -26,48 +26,58 @@ namespace eagle {
|
||||
|
||||
private readonly HashSet<IClientTextListener> _listeners = new();
|
||||
|
||||
public void Clear() { _streamingTexts.Clear(); }
|
||||
public void Clear() {
|
||||
lock (this) { _streamingTexts.Clear(); }
|
||||
}
|
||||
|
||||
public Dictionary<String, TextEntry> All() {
|
||||
return new Dictionary<string, TextEntry>(_streamingTexts);
|
||||
lock (this) { return new Dictionary<string, TextEntry>(_streamingTexts); }
|
||||
}
|
||||
|
||||
public String
|
||||
HandleNewStreamingText(String llmId, String newText, Int32 knownByteCount, bool completed) {
|
||||
var currentText = "";
|
||||
if (_streamingTexts.TryGetValue(llmId, out var entry)) { currentText = entry.Text; }
|
||||
lock (this) {
|
||||
var currentText = "";
|
||||
if (_streamingTexts.TryGetValue(llmId, out var entry)) { currentText = entry.Text; }
|
||||
|
||||
var currentTextBytes = Encoding.UTF8.GetBytes(currentText);
|
||||
var truncatedBytes = currentTextBytes.Take(knownByteCount).ToArray();
|
||||
var currentTextBytes = Encoding.UTF8.GetBytes(currentText);
|
||||
var truncatedBytes = currentTextBytes.Take(knownByteCount).ToArray();
|
||||
|
||||
var updatedText = Encoding.UTF8.GetString(truncatedBytes) + newText;
|
||||
_streamingTexts[llmId] = new TextEntry(updatedText, completed);
|
||||
var updatedText = Encoding.UTF8.GetString(truncatedBytes) + newText;
|
||||
_streamingTexts[llmId] = new TextEntry(updatedText, completed);
|
||||
|
||||
_listeners.Where(x => x.TextId() == llmId)
|
||||
.ToList()
|
||||
.ForEach(x => x.OnTextUpdate(updatedText, completed));
|
||||
_listeners.Where(x => x.TextId() == llmId)
|
||||
.ToList()
|
||||
.ForEach(x => x.OnTextUpdate(updatedText, completed));
|
||||
|
||||
return updatedText;
|
||||
return updatedText;
|
||||
}
|
||||
}
|
||||
|
||||
public TextEntry GetTextEntry(string streamId) {
|
||||
if (String.IsNullOrEmpty(streamId)) return new TextEntry("", false);
|
||||
lock (this) {
|
||||
if (String.IsNullOrEmpty(streamId)) return new TextEntry("", false);
|
||||
|
||||
if (ClientPregeneratedText.Provider.TryGetText(streamId, out var text)) {
|
||||
return new TextEntry(text, true);
|
||||
if (ClientPregeneratedText.Provider.TryGetText(streamId, out var text)) {
|
||||
return new TextEntry(text, true);
|
||||
}
|
||||
|
||||
return _streamingTexts.GetValueOrDefault(streamId, null);
|
||||
}
|
||||
|
||||
return _streamingTexts.GetValueOrDefault(streamId, null);
|
||||
}
|
||||
|
||||
public void AddListener(IClientTextListener listener) {
|
||||
_listeners.Add(listener);
|
||||
if (listener.TextId() is {} textId && !String.IsNullOrEmpty(textId)) {
|
||||
var entry = GetTextEntry(textId);
|
||||
if (entry != null) { listener.OnTextUpdate(entry.Text, entry.Completed); }
|
||||
lock (this) {
|
||||
if (listener.TextId() is {} textId && !String.IsNullOrEmpty(textId)) {
|
||||
_listeners.Add(listener);
|
||||
var entry = GetTextEntry(textId);
|
||||
if (entry != null) { listener.OnTextUpdate(entry.Text, entry.Completed); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveListener(IClientTextListener listener) { _listeners.Remove(listener); }
|
||||
public void RemoveListener(IClientTextListener listener) {
|
||||
lock (this) { _listeners.Remove(listener); }
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-11
@@ -39,7 +39,12 @@ namespace eagle {
|
||||
? $" ({GUIUtils.ConditionString(ConditionAccessor(hero), ConditionName)})"
|
||||
: "",
|
||||
i,
|
||||
SetGeneratedText);
|
||||
(index, text) => {
|
||||
if (index < Dropdown.options.Count) {
|
||||
options[index].text = text;
|
||||
AssignOptions();
|
||||
}
|
||||
});
|
||||
|
||||
listeners.Add(listener);
|
||||
ClientTextProvider.Provider.AddListener(listener);
|
||||
@@ -49,14 +54,6 @@ namespace eagle {
|
||||
}
|
||||
}
|
||||
|
||||
public string FallbackText = "";
|
||||
|
||||
private void SetGeneratedText(int index, string text) {
|
||||
if (index >= Dropdown.options.Count) return;
|
||||
options[index].text = text;
|
||||
AssignOptions();
|
||||
}
|
||||
|
||||
private List<TMP_Dropdown.OptionData> options = new();
|
||||
public void AssignOptions() {
|
||||
Dropdown.ClearOptions();
|
||||
@@ -135,7 +132,7 @@ namespace eagle {
|
||||
}
|
||||
|
||||
private TMP_Dropdown.OptionData HeroOption(HeroView hv) {
|
||||
var texture = !Textures ? null : Textures.Profession(hv.Profession);
|
||||
var texture = Textures.Profession(hv.Profession);
|
||||
|
||||
var op = new TMP_Dropdown.OptionData {
|
||||
image = !texture ? null
|
||||
@@ -143,7 +140,7 @@ namespace eagle {
|
||||
texture,
|
||||
new Rect(0, 0, texture.width, texture.height),
|
||||
new Vector2(0.5f, 0.5f)),
|
||||
text = String.IsNullOrEmpty(hv.NameTextId) ? FallbackText : ""
|
||||
text = ""
|
||||
};
|
||||
|
||||
return op;
|
||||
|
||||
@@ -260,7 +260,6 @@ namespace eagle {
|
||||
switch (quest.Details.SealedValueCase) {
|
||||
case SealedValueOneofCase.DefeatFactionQuest: return "Attack Faction";
|
||||
case SealedValueOneofCase.DismissSpecificVassalQuest: return "Dismiss Vassal";
|
||||
case SealedValueOneofCase.AllianceQuest: return "Secure Alliance";
|
||||
case SealedValueOneofCase.AlmsToProvinceQuest: return "Give Alms in Province";
|
||||
case SealedValueOneofCase.AlmsAcrossRealmQuest: return "Give Alms Across Realm";
|
||||
case SealedValueOneofCase.GiveToHeroesInProvinceQuest:
|
||||
|
||||
+2
-6
@@ -15,14 +15,10 @@ namespace eagle {
|
||||
_currentCompleted = false;
|
||||
|
||||
var scrollRect = GetComponentInParent<ScrollRect>(includeInactive: true);
|
||||
if (scrollRect) { scrollRect.normalizedPosition = new Vector2(0, 1); }
|
||||
if (scrollRect != null) { scrollRect.normalizedPosition = new Vector2(0, 1); }
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(_textId)) {
|
||||
// If the text ID is set, we want to update the view immediately
|
||||
// to reflect any existing text.
|
||||
OnTextUpdate(ClientTextProvider.Provider.GetTextEntry(TextId));
|
||||
}
|
||||
OnTextUpdate(ClientTextProvider.Provider.GetTextEntry(TextId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Can't render this file because it contains an unexpected character in line 5 and column 5.
|
Binary file not shown.
|
Binary file not shown.
|
Binary file not shown.
|
Binary file not shown.
|
Binary file not shown.
|
@@ -15,7 +15,7 @@ import java.time.format.DateTimeFormatter
|
||||
import java.util.function.Consumer
|
||||
|
||||
object ClaudeServiceImpl {
|
||||
val model: String = "claude-sonnet-4-20250514"
|
||||
val model: String = "claude-3-5-sonnet-20240620"
|
||||
val maxTokens = 2048
|
||||
|
||||
private val apiKey = ApiKeys.anthropic
|
||||
@@ -43,7 +43,6 @@ object ClaudeServiceImpl {
|
||||
.timeout(Duration.ofSeconds(timeoutSeconds))
|
||||
.header("X-API-Key", s"${ClaudeServiceImpl.apiKey}")
|
||||
.header("anthropic-version", "2023-06-01")
|
||||
.header("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
class ClaudeServiceImpl(
|
||||
|
||||
@@ -77,6 +77,10 @@ final class ExternalTextGenerationCaller(
|
||||
backoffSeconds: Double =
|
||||
ExternalTextGenerationCaller.initialBackoffSeconds
|
||||
): Future[HttpResponse[Unit]] = {
|
||||
if (inputText.contains("Some(")) {
|
||||
println("SOME!")
|
||||
}
|
||||
|
||||
streamCompletion(
|
||||
inputText = inputText,
|
||||
request = serviceImpl.makeRequest(
|
||||
|
||||
@@ -74,7 +74,7 @@ scala_library(
|
||||
srcs = ["package.scala"],
|
||||
visibility = [
|
||||
":__subpackages__",
|
||||
"//src/main/scala/net/eagle0/util:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
"//src/test:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
|
||||
+4
-4
@@ -122,7 +122,7 @@ case class PerformUnaffiliatedHeroesAction(
|
||||
.withActionResults { gs =>
|
||||
EndUnaffiliatedHeroActionsPhaseAction(
|
||||
gameId = gs.gameId,
|
||||
currentDate = currentDate,
|
||||
currentDate = DateConverter.fromProto(gs.currentDate),
|
||||
currentRoundId = gs.currentRoundId,
|
||||
provinces =
|
||||
gs.provinces.values.map(ProvinceConverter.fromProto).toVector,
|
||||
@@ -250,15 +250,15 @@ case class PerformUnaffiliatedHeroesAction(
|
||||
.getHero(
|
||||
random = nextFr,
|
||||
hid = nextHid,
|
||||
date = currentDate
|
||||
date = gs.currentDate
|
||||
)
|
||||
.map {
|
||||
case HeroGenerationResponse(
|
||||
hero,
|
||||
nameInfo
|
||||
) =>
|
||||
innerAcc :+ (toCheck.head, hero
|
||||
.copy(id = nextHid), nameInfo)
|
||||
innerAcc :+ (toCheck.head, HeroConverter
|
||||
.fromProto(hero.withId(nextHid)), nameInfo)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,9 +8,12 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle:__subpackages__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/internal:hero_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:profession_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/internal:hero_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/common/name_generation:string_construction_token_generator",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
@@ -19,8 +22,5 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/hero_generation_response",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/name_info",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/random_hero_generator",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/date",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/backstory_version",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package net.eagle0.eagle.library.util.hero_generator
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.common.date.Date
|
||||
import net.eagle0.eagle.internal.hero.Hero
|
||||
import net.eagle0.eagle.library.EagleInternalException
|
||||
import net.eagle0.eagle.library.util.EagleRequire.internalRequire
|
||||
import net.eagle0.eagle.library.util.hero_generator.hero_generation_response.HeroGenerationResponse
|
||||
import net.eagle0.eagle.library.util.hero_generator.name_info.NoNameRequest
|
||||
import net.eagle0.eagle.library.util.hero_generator.random_hero_generator.RandomHeroGenerator
|
||||
import net.eagle0.eagle.model.state.date.Date
|
||||
import net.eagle0.eagle.model.state.hero.concrete.HeroC
|
||||
import net.eagle0.eagle.{HeroId, RoundId}
|
||||
|
||||
import scala.util.{Failure, Success}
|
||||
@@ -16,7 +16,7 @@ object HeroGenerator {
|
||||
private val randomChance: Double = 0.0
|
||||
|
||||
def apply(
|
||||
pregeneratedHeroes: Vector[HeroC],
|
||||
pregeneratedHeroes: Vector[Hero],
|
||||
excludingNames: Vector[String],
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[HeroGenerator] =
|
||||
@@ -33,7 +33,7 @@ object HeroGenerator {
|
||||
|
||||
class HeroGenerator(
|
||||
functionalRandom: FunctionalRandom,
|
||||
shuffledPregeneratedHeroes: Vector[HeroC],
|
||||
shuffledPregeneratedHeroes: Vector[Hero],
|
||||
excludingNames: Vector[String]
|
||||
) {
|
||||
private val randomHeroGenerator = new RandomHeroGenerator(
|
||||
@@ -41,7 +41,7 @@ class HeroGenerator(
|
||||
excludingNames = excludingNames
|
||||
)
|
||||
|
||||
private var remainingPregeneratedHeroes: Vector[HeroC] =
|
||||
private var remainingPregeneratedHeroes: Vector[Hero] =
|
||||
if (
|
||||
shuffledPregeneratedHeroes == null || shuffledPregeneratedHeroes.isEmpty
|
||||
) Vector()
|
||||
@@ -54,7 +54,7 @@ class HeroGenerator(
|
||||
s"Pregenerated heroes exhausted, no hero with id $hid"
|
||||
)
|
||||
val nextHero = remainingPregeneratedHeroes.head
|
||||
.copy(id = hid)
|
||||
.withId(hid)
|
||||
internalRequire(
|
||||
nextHero.backstoryVersions.nonEmpty,
|
||||
s"Pregenerated hero ${nextHero.name} has no backstory text"
|
||||
@@ -74,7 +74,7 @@ class HeroGenerator(
|
||||
.getHero(hid, date) match {
|
||||
case Success(HeroGenerationResponse(hero, nameInfo)) =>
|
||||
HeroGenerationResponse(
|
||||
hero = hero.copy(backstoryVersions = Vector()),
|
||||
hero = hero.clearBackstoryVersions,
|
||||
nameInfo = nameInfo
|
||||
)
|
||||
case Failure(_) =>
|
||||
|
||||
+1
-2
@@ -7,12 +7,11 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/impl/action:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/hero_generator:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/internal:hero_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/name_info",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
],
|
||||
)
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package net.eagle0.eagle.library.util.hero_generator.hero_generation_response
|
||||
|
||||
import net.eagle0.eagle.internal.hero.Hero
|
||||
import net.eagle0.eagle.library.util.hero_generator.name_info.NameInfo
|
||||
import net.eagle0.eagle.model.state.hero.concrete.HeroC
|
||||
|
||||
case class HeroGenerationResponse(
|
||||
hero: HeroC,
|
||||
hero: Hero,
|
||||
nameInfo: NameInfo
|
||||
)
|
||||
|
||||
@@ -8,7 +8,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/name_generation_request:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/hero_generator:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
|
||||
+3
-4
@@ -12,11 +12,13 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle:__subpackages__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/protobuf/net/eagle0/eagle/internal:hero_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
],
|
||||
deps = [
|
||||
":random_hero_personalities",
|
||||
"//src/main/protobuf/net/eagle0/eagle/common:profession_scala_proto",
|
||||
"//src/main/protobuf/net/eagle0/eagle/internal:hero_scala_proto",
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/common/name_generation:string_construction_token_generator",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
@@ -24,9 +26,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/hero_generation_response",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/name_info",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_name_fetcher",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/date",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/backstory_version",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+62
-57
@@ -2,24 +2,29 @@ package net.eagle0.eagle.library.util.hero_generator.random_hero_generator
|
||||
|
||||
import net.eagle0.common.{FunctionalRandom, RandomState}
|
||||
import net.eagle0.eagle.HeroId
|
||||
import net.eagle0.eagle.common.date.Date
|
||||
import net.eagle0.eagle.common.gender.Gender
|
||||
import net.eagle0.eagle.common.gender.Gender.{
|
||||
GENDER_FEMALE,
|
||||
GENDER_MALE,
|
||||
GENDER_OTHER
|
||||
}
|
||||
import net.eagle0.eagle.common.hero_backstory_version.BackstoryVersion
|
||||
import net.eagle0.eagle.common.profession.Profession
|
||||
import net.eagle0.eagle.common.profession.Profession.{
|
||||
CHAMPION,
|
||||
ENGINEER,
|
||||
MAGE,
|
||||
NECROMANCER,
|
||||
NO_PROFESSION,
|
||||
PALADIN,
|
||||
RANGER
|
||||
}
|
||||
import net.eagle0.eagle.internal.hero.Hero
|
||||
import net.eagle0.eagle.library.EagleInternalException
|
||||
import net.eagle0.eagle.library.util.hero_generator.hero_generation_response.HeroGenerationResponse
|
||||
import net.eagle0.eagle.library.util.hero_generator.name_info.FixedName
|
||||
import net.eagle0.eagle.library.util.hero_name_fetcher.HeroNameFetcher
|
||||
import net.eagle0.eagle.model.state.date.Date
|
||||
import net.eagle0.eagle.model.state.hero.Gender.{Female, Male, Other}
|
||||
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
|
||||
import net.eagle0.eagle.model.state.hero.Profession.{
|
||||
Champion,
|
||||
Engineer,
|
||||
Mage,
|
||||
Necromancer,
|
||||
NoProfession,
|
||||
Paladin,
|
||||
Ranger
|
||||
}
|
||||
import net.eagle0.eagle.model.state.hero.backstory_version.BackstoryVersion
|
||||
import net.eagle0.eagle.model.state.hero.concrete.HeroC
|
||||
|
||||
import javax.naming.InsufficientResourcesException
|
||||
import scala.annotation.tailrec
|
||||
@@ -35,44 +40,44 @@ object RandomHeroGenerator {
|
||||
|
||||
private def genderFromString(genderString: String): Gender =
|
||||
genderString match {
|
||||
case "female" => Gender.Female
|
||||
case "male" => Gender.Male
|
||||
case "other" => Gender.Other
|
||||
case "female" => GENDER_FEMALE
|
||||
case "male" => GENDER_MALE
|
||||
case "other" => GENDER_OTHER
|
||||
case _ => throw new EagleInternalException("unknown gender string")
|
||||
}
|
||||
|
||||
private def genderToString(gender: Gender): String =
|
||||
gender match {
|
||||
case Gender.Female => "female"
|
||||
case Gender.Male => "male"
|
||||
case Gender.Other => "other"
|
||||
case GENDER_FEMALE => "female"
|
||||
case GENDER_MALE => "male"
|
||||
case GENDER_OTHER => "other"
|
||||
case _ => throw new EagleInternalException("unknown gender")
|
||||
}
|
||||
|
||||
private def withProfessionAndPrimeStat(
|
||||
bh: HeroC,
|
||||
bh: Hero,
|
||||
fr: FunctionalRandom
|
||||
): RandomState[HeroC] =
|
||||
): RandomState[Hero] =
|
||||
primeStat(fr)
|
||||
.continue { case (ps, nextRandom) =>
|
||||
nextRandom.nextInt(0, 125).map {
|
||||
case 1 | 2 => bh.withProfession(Mage).copy(wisdom = ps)
|
||||
case 1 | 2 => bh.withProfession(MAGE).withWisdom(ps)
|
||||
case 3 | 4 =>
|
||||
bh.withProfession(Necromancer).copy(charisma = ps)
|
||||
bh.withProfession(NECROMANCER).withCharisma(ps)
|
||||
case 5 | 6 | 7 | 8 | 9 =>
|
||||
bh.withProfession(Engineer).copy(agility = ps)
|
||||
bh.withProfession(ENGINEER).withAgility(ps)
|
||||
case 10 | 11 | 12 | 13 =>
|
||||
bh.withProfession(Paladin).copy(charisma = ps)
|
||||
bh.withProfession(PALADIN).withCharisma(ps)
|
||||
case 14 | 15 | 16 | 17 =>
|
||||
bh.withProfession(Ranger).copy(agility = ps)
|
||||
bh.withProfession(RANGER).withAgility(ps)
|
||||
case 18 | 19 | 20 | 21 =>
|
||||
bh.withProfession(Champion).copy(strength = ps)
|
||||
case _ => bh.withProfession(NoProfession)
|
||||
bh.withProfession(CHAMPION).withStrength(ps)
|
||||
case _ => bh.withProfession(NO_PROFESSION)
|
||||
}
|
||||
}
|
||||
|
||||
def withNoProfession(bh: HeroC, fr: FunctionalRandom): RandomState[HeroC] =
|
||||
RandomState(bh.withProfession(NoProfession), fr)
|
||||
def withNoProfession(bh: Hero, fr: FunctionalRandom): RandomState[Hero] =
|
||||
RandomState(bh.withProfession(NO_PROFESSION), fr)
|
||||
|
||||
private def primeStat(random: FunctionalRandom): RandomState[Int] =
|
||||
random
|
||||
@@ -83,7 +88,7 @@ class RandomHeroGenerator(
|
||||
functionalRandom: FunctionalRandom,
|
||||
var excludingNames: Vector[String] = Vector.empty[String],
|
||||
excludingImagePaths: Vector[String] = Vector.empty[String],
|
||||
professionAdder: (HeroC, FunctionalRandom) => RandomState[HeroC] =
|
||||
professionAdder: (Hero, FunctionalRandom) => RandomState[Hero] =
|
||||
RandomHeroGenerator.withProfessionAndPrimeStat
|
||||
) {
|
||||
import RandomHeroGenerator._
|
||||
@@ -91,7 +96,7 @@ class RandomHeroGenerator(
|
||||
private def createHeroes(
|
||||
count: Int,
|
||||
functionalRandom: FunctionalRandom
|
||||
): Try[RandomState[Vector[HeroC]]] =
|
||||
): Try[RandomState[Vector[Hero]]] =
|
||||
(1 to count)
|
||||
.foldLeft(RandomState(Vector[String](), functionalRandom)) {
|
||||
case (RandomState(acc, fr), _) =>
|
||||
@@ -102,7 +107,7 @@ class RandomHeroGenerator(
|
||||
.names(genderStrings, excludingNames)
|
||||
.map(_.zip(genderStrings))
|
||||
.map {
|
||||
_.foldLeft(RandomState(Vector[HeroC](), fr)) {
|
||||
_.foldLeft(RandomState(Vector[Hero](), fr)) {
|
||||
case (RandomState(heroes, fr), (name, gendString)) =>
|
||||
excludingNames = excludingNames :+ name
|
||||
heroWithBaseStats(0, name, genderFromString(gendString), fr)
|
||||
@@ -115,7 +120,7 @@ class RandomHeroGenerator(
|
||||
hero.profession,
|
||||
genderFromString(gendString)
|
||||
)
|
||||
.map(ip => hero.copy(imagePath = ip))
|
||||
.map(hero.withImagePath)
|
||||
}
|
||||
.map(heroes :+ _)
|
||||
}
|
||||
@@ -159,10 +164,10 @@ class RandomHeroGenerator(
|
||||
|
||||
Success(
|
||||
taken.zip(hids).map { case (hero, hid) =>
|
||||
val adjustedHero = hero.copy(
|
||||
id = hid,
|
||||
nameTextId = s"hn_$hid",
|
||||
backstoryVersions = hero.backstoryVersions :+ BackstoryVersion(
|
||||
val adjustedHero = hero.update(
|
||||
_.id := hid,
|
||||
_.nameTextId := s"hn_$hid",
|
||||
_.backstoryVersions :+= BackstoryVersion(
|
||||
textId = s"hero_${hid}_backstory_0",
|
||||
date = date
|
||||
)
|
||||
@@ -183,13 +188,13 @@ class RandomHeroGenerator(
|
||||
getClass.getResource("/net/eagle0/eagle/headshots.tsv")
|
||||
|
||||
private val professionStringMap = Map(
|
||||
"no_profession" -> NoProfession,
|
||||
"mage" -> Mage,
|
||||
"engineer" -> Engineer,
|
||||
"necromancer" -> Necromancer,
|
||||
"paladin" -> Paladin,
|
||||
"ranger" -> Ranger,
|
||||
"champion" -> Champion
|
||||
"no_profession" -> NO_PROFESSION,
|
||||
"mage" -> MAGE,
|
||||
"engineer" -> ENGINEER,
|
||||
"necromancer" -> NECROMANCER,
|
||||
"paladin" -> PALADIN,
|
||||
"ranger" -> RANGER,
|
||||
"champion" -> CHAMPION
|
||||
)
|
||||
|
||||
private def normalStat(random: FunctionalRandom): RandomState[Int] =
|
||||
@@ -200,10 +205,10 @@ class RandomHeroGenerator(
|
||||
gender: Gender,
|
||||
fr: FunctionalRandom
|
||||
): RandomState[Gender] =
|
||||
if (gender == Gender.Other)
|
||||
if (gender == GENDER_OTHER)
|
||||
fr.nextIntInclusive(0, 1).map {
|
||||
case 0 => Gender.Female
|
||||
case 1 => Gender.Male
|
||||
case 0 => GENDER_FEMALE
|
||||
case 1 => GENDER_MALE
|
||||
}
|
||||
else RandomState(gender, fr)
|
||||
|
||||
@@ -240,9 +245,9 @@ class RandomHeroGenerator(
|
||||
private def gender(random: FunctionalRandom): RandomState[Gender] =
|
||||
random.nextDouble
|
||||
.map { d =>
|
||||
if (d < 0.47) Female
|
||||
else if (d < 0.94) Male
|
||||
else Other
|
||||
if (d < 0.47) GENDER_FEMALE
|
||||
else if (d < 0.94) GENDER_MALE
|
||||
else GENDER_OTHER
|
||||
}
|
||||
|
||||
private def heroWithBaseStats(
|
||||
@@ -250,7 +255,7 @@ class RandomHeroGenerator(
|
||||
name: String,
|
||||
gender: Gender,
|
||||
fr: FunctionalRandom
|
||||
): RandomState[HeroC] =
|
||||
): RandomState[Hero] =
|
||||
fr.nextInt(constitutionMin, 100)
|
||||
.continue { case (constitution, fr) =>
|
||||
fr.nextItems(8, normalStat).continue {
|
||||
@@ -269,7 +274,7 @@ class RandomHeroGenerator(
|
||||
) =>
|
||||
RandomHeroPersonalities.randomPersonalityWords(3, innerFr).map {
|
||||
personalityWords =>
|
||||
HeroC(
|
||||
Hero(
|
||||
id = hid,
|
||||
name = name,
|
||||
strength = strength,
|
||||
@@ -342,13 +347,13 @@ class RandomHeroGenerator(
|
||||
private val minCacheSize = 10
|
||||
private val cacheFetchSize = 50
|
||||
|
||||
private var cache: RandomState[Vector[HeroC]] =
|
||||
if (functionalRandom == null) RandomState(Vector[HeroC](), null)
|
||||
private var cache: RandomState[Vector[Hero]] =
|
||||
if (functionalRandom == null) RandomState(Vector[Hero](), null)
|
||||
else createCache(functionalRandom)
|
||||
|
||||
private def createCache(
|
||||
functionalRandom: FunctionalRandom
|
||||
): RandomState[Vector[HeroC]] =
|
||||
): RandomState[Vector[Hero]] =
|
||||
createHeroes(cacheFetchSize, functionalRandom) match {
|
||||
case Success(rs) => rs
|
||||
case Failure(e) =>
|
||||
|
||||
@@ -9,7 +9,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/quest_fulfillment:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/model:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/actions/impl:__subpackages__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/quest_fulfillment:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/model/proto_converters:__pkg__",
|
||||
|
||||
@@ -35,7 +35,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/impl:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
|
||||
@@ -54,7 +53,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/impl:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
@@ -82,7 +80,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/impl:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:profession",
|
||||
|
||||
@@ -4,7 +4,14 @@ scala_library(
|
||||
name = "date",
|
||||
srcs = ["Date.scala"],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
"//src/main/scala/net/eagle0/eagle/library:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/quest_fulfillment:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/model:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/util/quest_fulfillment:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/model:__subpackages__",
|
||||
],
|
||||
deps = [],
|
||||
)
|
||||
|
||||
@@ -29,7 +29,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/hero:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library:__subpackages__",
|
||||
"//src/test/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
],
|
||||
@@ -65,7 +64,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/hero:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/test/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
],
|
||||
|
||||
@@ -5,13 +5,11 @@ scala_library(
|
||||
srcs = ["BackstoryVersion.scala"],
|
||||
visibility = [
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/generated_text_request:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/hero:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/llm_request:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
|
||||
@@ -5,10 +5,7 @@ scala_library(
|
||||
srcs = ["HeroC.scala"],
|
||||
visibility = [
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator:__subpackages__",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/hero:__pkg__",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/actions:__subpackages__",
|
||||
"//src/test/scala/net/eagle0/eagle/library/util:__subpackages__",
|
||||
],
|
||||
|
||||
@@ -31,7 +31,6 @@ import net.eagle0.eagle.library.settings.loaders.{
|
||||
}
|
||||
import net.eagle0.eagle.library.util.EagleRequire
|
||||
import net.eagle0.eagle.library.util.hero_generator.HeroGenerator
|
||||
import net.eagle0.eagle.model.state.hero.concrete.HeroC
|
||||
import net.eagle0.eagle.service.controller._
|
||||
import net.eagle0.eagle.service.new_game_creation.{
|
||||
ExpandedGameParameters,
|
||||
@@ -170,7 +169,7 @@ object GamesManager {
|
||||
gamePersister: Persister,
|
||||
history: GameHistory,
|
||||
userToFid: Map[String, FactionId],
|
||||
pregeneratedHeroes: Vector[HeroC]
|
||||
pregeneratedHeroes: Vector[Hero]
|
||||
): GameController = {
|
||||
val existingNames = (history.last.gameState.killedHeroes ++
|
||||
history.last.gameState.heroes).values.map(_.name).toVector
|
||||
@@ -224,7 +223,7 @@ object GamesManager {
|
||||
gamePersister = persister,
|
||||
history = gh,
|
||||
userToFid = runningGame.userToPid,
|
||||
pregeneratedHeroes = GameParametersUtils.allPregeneratedHeroes
|
||||
pregeneratedHeroes = GameParametersUtils.allPregeneratedHeroProtos
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -105,11 +105,11 @@ class LlmResolver(updateReceiver: LlmUpdateQueuingProxy, gptModelName: String) {
|
||||
defaultModelName = gptModelName
|
||||
)
|
||||
private def newClaudeServiceImpl = new ClaudeServiceImpl(
|
||||
defaultModelName = "claude-sonnet-4-20250514"
|
||||
defaultModelName = "claude-3-5-sonnet-20240620"
|
||||
)
|
||||
|
||||
private val chatGptCount = 1
|
||||
private val claudeCount = 1
|
||||
private val chatGptCount = 2
|
||||
private val claudeCount = 0
|
||||
|
||||
lazy private val llmCallers = ((1 to claudeCount).map { _ =>
|
||||
new ExternalTextGenerationCaller(
|
||||
|
||||
@@ -15,7 +15,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library:eagle_internal_exception",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:profession",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:loaded_hero",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -24,20 +23,17 @@ scala_library(
|
||||
srcs = ["GreatPerson.scala"],
|
||||
visibility = [
|
||||
"//src/main/scala/net/eagle0/eagle/service:__pkg__",
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/service:__pkg__",
|
||||
"//src/test/scala/net/eagle0/eagle/service/new_game_creation:__pkg__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:profession",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:loaded_hero",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:profession",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:loaded_hero",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -64,8 +60,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library:eagle_internal_exception",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:map_generator",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:price_index_utils",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:loaded_hero",
|
||||
"@maven//:com_thesamet_scalapb_scalapb_json4s_2_13",
|
||||
],
|
||||
)
|
||||
@@ -77,6 +71,7 @@ scala_library(
|
||||
"//src/test/scala/net/eagle0/eagle/service:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":great_person",
|
||||
":start_date",
|
||||
"//src/main/protobuf/net/eagle0/eagle/internal:hero_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
@@ -84,9 +79,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/hero:gender",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/hero:profession",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/date",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/backstory_version",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:loaded_hero",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -131,7 +123,6 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/random_hero_generator",
|
||||
"//src/main/scala/net/eagle0/eagle/model/action_result/generated_text_request",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/date",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/hero",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/date",
|
||||
"//src/main/scala/net/eagle0/eagle/service:persisted_history",
|
||||
],
|
||||
@@ -140,9 +131,6 @@ scala_library(
|
||||
scala_library(
|
||||
name = "start_date",
|
||||
srcs = ["StartDate.scala"],
|
||||
visibility = [
|
||||
"//src/main/scala/net/eagle0/util:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/date",
|
||||
],
|
||||
@@ -158,10 +146,10 @@ scala_library(
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
],
|
||||
deps = [
|
||||
":great_person",
|
||||
":loaded_hero_conversion",
|
||||
"//src/main/protobuf/net/eagle0/eagle/internal:action_result_scala_proto",
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util:idable",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:loaded_hero",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.eagle0.eagle.service.new_game_creation
|
||||
import net.eagle0.common.TsvUtils
|
||||
import net.eagle0.eagle.library.EagleInternalException
|
||||
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@ import net.eagle0.eagle.internal.hero.Hero
|
||||
import net.eagle0.eagle.internal.province.Province
|
||||
import net.eagle0.eagle.library.EagleInternalException
|
||||
import net.eagle0.eagle.library.util.{MapGenerator, PriceIndexUtils}
|
||||
import net.eagle0.eagle.model.state.hero.concrete.HeroC
|
||||
import net.eagle0.eagle.{BattalionId, FactionId, HeroId}
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
import scalapb.json4s.JsonFormat
|
||||
|
||||
import scala.io.Source
|
||||
@@ -46,11 +44,6 @@ object GameParametersUtils {
|
||||
val fixedOthers: Vector[LoadedHero] = fixedHeroes.others
|
||||
val pregeneratedOthers: Vector[LoadedHero] = pregeneratedHeroes.others
|
||||
|
||||
val allPregeneratedHeroes: Vector[HeroC] = (greatPeople.map(
|
||||
_.greatPerson.hero
|
||||
) ++ fixedOthers ++ pregeneratedOthers)
|
||||
.map(LoadedHeroConversion.toHeroC)
|
||||
|
||||
val allPregeneratedHeroProtos: Vector[Hero] = (greatPeople.map(
|
||||
_.greatPerson.hero
|
||||
) ++ fixedOthers ++ pregeneratedOthers)
|
||||
|
||||
@@ -1,6 +1,37 @@
|
||||
package net.eagle0.eagle.service.new_game_creation
|
||||
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
|
||||
import net.eagle0.eagle.{FactionId, HeroId}
|
||||
|
||||
import scala.util.hashing.MurmurHash3
|
||||
|
||||
case class LoadedHero(
|
||||
name: String,
|
||||
factionId: Option[FactionId] = None,
|
||||
id: HeroId,
|
||||
backstory: String = "",
|
||||
strength: Int = 0,
|
||||
agility: Int = 0,
|
||||
constitution: Int = 0,
|
||||
charisma: Int = 0,
|
||||
wisdom: Int = 0,
|
||||
integrity: Int = 0,
|
||||
ambition: Int = 0,
|
||||
gregariousness: Int = 0,
|
||||
bravery: Int = 0,
|
||||
vigor: Int = 0,
|
||||
profession: Profession = Profession.NoProfession,
|
||||
imagePath: String = "",
|
||||
pronounGender: Gender = Gender.Other,
|
||||
personalityWords: Vector[String] = Vector.empty
|
||||
) {
|
||||
def withId(newId: HeroId): LoadedHero = copy(id = newId)
|
||||
def withFactionId(newFactionId: FactionId): LoadedHero =
|
||||
copy(factionId = Some(newFactionId))
|
||||
def nameTextId =
|
||||
s"fhn_${MurmurHash3.stringHash(name).toHexString}"
|
||||
def backstoryTextId = s"${name}_backstory 0"
|
||||
}
|
||||
|
||||
case class GreatPerson(
|
||||
hero: LoadedHero,
|
||||
|
||||
+2
-56
@@ -1,70 +1,16 @@
|
||||
package net.eagle0.eagle.service.new_game_creation
|
||||
|
||||
import net.eagle0.eagle.common.hero_backstory_version.{
|
||||
BackstoryVersion => BackstoryVersionProto
|
||||
}
|
||||
import net.eagle0.eagle.common.hero_backstory_version.BackstoryVersion
|
||||
import net.eagle0.eagle.internal.hero.Hero
|
||||
import net.eagle0.eagle.model.proto_converters.date.DateConverter
|
||||
import net.eagle0.eagle.model.proto_converters.hero.{
|
||||
GenderConverter,
|
||||
ProfessionConverter
|
||||
}
|
||||
import net.eagle0.eagle.model.state.hero.backstory_version.BackstoryVersion
|
||||
import net.eagle0.eagle.model.state.hero.concrete.HeroC
|
||||
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
|
||||
import net.eagle0.eagle.{FactionId, HeroId}
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
|
||||
object LoadedHeroConversion {
|
||||
def toHeroC(loadedHero: LoadedHero): HeroC = loadedHero match {
|
||||
case LoadedHero(
|
||||
name: String,
|
||||
factionId: Option[FactionId],
|
||||
id: HeroId,
|
||||
backstory: String,
|
||||
strength: Int,
|
||||
agility: Int,
|
||||
constitution: Int,
|
||||
charisma: Int,
|
||||
wisdom: Int,
|
||||
integrity: Int,
|
||||
ambition: Int,
|
||||
gregariousness: Int,
|
||||
bravery: Int,
|
||||
vigor: Int,
|
||||
profession: Profession,
|
||||
imagePath: String,
|
||||
pronounGender: Gender,
|
||||
personalityWords: Vector[String]
|
||||
) =>
|
||||
HeroC(
|
||||
name = name,
|
||||
nameTextId = loadedHero.nameTextId,
|
||||
factionId = factionId,
|
||||
id = id,
|
||||
backstoryVersions = Vector(
|
||||
BackstoryVersion(
|
||||
textId = loadedHero.backstoryTextId,
|
||||
date = StartDate.startDate
|
||||
)
|
||||
),
|
||||
strength = strength,
|
||||
agility = agility,
|
||||
constitution = constitution,
|
||||
charisma = charisma,
|
||||
wisdom = wisdom,
|
||||
integrity = integrity,
|
||||
ambition = ambition,
|
||||
gregariousness = gregariousness,
|
||||
bravery = bravery,
|
||||
vigor = vigor,
|
||||
profession = profession,
|
||||
imagePath = imagePath,
|
||||
pronounGender = pronounGender,
|
||||
personalityWords = personalityWords
|
||||
)
|
||||
}
|
||||
|
||||
def toHeroProto(loadedHero: LoadedHero): Hero = loadedHero match {
|
||||
case LoadedHero(
|
||||
name: String,
|
||||
@@ -92,7 +38,7 @@ object LoadedHeroConversion {
|
||||
factionId = factionId,
|
||||
id = id,
|
||||
backstoryVersions = Vector(
|
||||
BackstoryVersionProto(
|
||||
BackstoryVersion(
|
||||
textId = loadedHero.backstoryTextId,
|
||||
date = DateConverter.toProto(StartDate.startDate)
|
||||
)
|
||||
|
||||
@@ -47,11 +47,9 @@ import net.eagle0.eagle.model.action_result.generated_text_request.{
|
||||
GeneratedTextRequestT
|
||||
}
|
||||
import net.eagle0.eagle.model.proto_converters.date.DateConverter
|
||||
import net.eagle0.eagle.model.proto_converters.hero.HeroConverter
|
||||
import net.eagle0.eagle.service.PersistedHistory
|
||||
import net.eagle0.eagle.service.persistence.Persister
|
||||
import net.eagle0.eagle.{FactionId, GameId, HeroId, ProvinceId}
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
@@ -190,15 +188,15 @@ object FixedNewGameCreation extends NewGameCreation {
|
||||
val newHeroes = heroGenerator
|
||||
.getHeroes(
|
||||
hids,
|
||||
StartDate.startDate
|
||||
DateConverter.toProto(StartDate.startDate)
|
||||
)
|
||||
.get
|
||||
.map { case HeroGenerationResponse(hero, nameInfo) =>
|
||||
(
|
||||
hero.copy(
|
||||
factionId = Some(fid),
|
||||
loyalty = 75,
|
||||
roundIdJoined = Some(0)
|
||||
hero.update(
|
||||
_.factionId := fid,
|
||||
_.loyalty := 75,
|
||||
_.roundIdJoined := 0
|
||||
),
|
||||
NameGenerationRequestCreator.nameGenerationRequest(
|
||||
heroId = hero.id,
|
||||
@@ -209,7 +207,7 @@ object FixedNewGameCreation extends NewGameCreation {
|
||||
}
|
||||
|
||||
(
|
||||
ar.withHeroes(newHeroes.map(_._1).map(HeroConverter.toProto))
|
||||
ar.withHeroes(newHeroes.map(_._1))
|
||||
.withGeneratedTextRequests(
|
||||
newHeroes.flatMap(_._2).map(convertNameRequest(_, playerCount))
|
||||
),
|
||||
@@ -557,7 +555,7 @@ object FixedNewGameCreation extends NewGameCreation {
|
||||
.getHero(
|
||||
random = fr,
|
||||
hid = heroId,
|
||||
date = StartDate.startDate
|
||||
date = DateConverter.toProto(StartDate.startDate)
|
||||
)
|
||||
.map { acc :+ _ }
|
||||
}
|
||||
@@ -671,8 +669,9 @@ object FixedNewGameCreation extends NewGameCreation {
|
||||
val fixedHeroesARwithGenerator = withFixedHeroesAR.continue {
|
||||
case (ar, fr) =>
|
||||
HeroGenerator(
|
||||
pregeneratedHeroes =
|
||||
pregeneratedHeroes.map(LoadedHeroConversion.toHeroC),
|
||||
pregeneratedHeroes = pregeneratedHeroes.map(h =>
|
||||
LoadedHeroConversion.toHeroProto(loadedHero = h)
|
||||
),
|
||||
excludingNames = withFixedHeroesAR.newValue.newHeroes.map(_.name),
|
||||
functionalRandom = fr
|
||||
).map((ar, _))
|
||||
@@ -696,7 +695,7 @@ object FixedNewGameCreation extends NewGameCreation {
|
||||
)
|
||||
}
|
||||
}.map(newHeroes =>
|
||||
ar.withHeroes(newHeroes.map(_._1).map(HeroConverter.toProto))
|
||||
ar.withHeroes(newHeroes.map(_._1))
|
||||
.withGeneratedTextRequests(
|
||||
newHeroes.flatMap(_._2).map { convertNameRequest(_, playerCount) }
|
||||
)
|
||||
|
||||
-1
@@ -12,7 +12,6 @@ import net.eagle0.eagle.library.util.IDable.{
|
||||
mapifyProvinces
|
||||
}
|
||||
import net.eagle0.eagle.{BattalionId, FactionId, HeroId, ProvinceId}
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
|
||||
object StartGameActionResultUtils {
|
||||
implicit class _StartGameActionResult(value: ActionResult) {
|
||||
|
||||
@@ -25,31 +25,23 @@ scala_binary(
|
||||
],
|
||||
)
|
||||
|
||||
scala_binary(
|
||||
name = "hero_library_generator",
|
||||
srcs = ["HeroLibraryGenerator.scala"],
|
||||
main_class = "net.eagle0.util.HeroLibraryGenerator",
|
||||
resources = [
|
||||
"//src/main/resources/net/eagle0/eagle:headshots",
|
||||
"//src/main/resources/net/eagle0/eagle:heroes",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//src/main/scala/net/eagle0/common:functional_random",
|
||||
"//src/main/scala/net/eagle0/common/llm_integration:claude_service_impl",
|
||||
"//src/main/scala/net/eagle0/common/llm_integration:external_text_generation_caller",
|
||||
"//src/main/scala/net/eagle0/common/llm_integration:external_text_generation_service_impl",
|
||||
"//src/main/scala/net/eagle0/common/llm_integration:open_ai_chat_completions_service_impl",
|
||||
"//src/main/scala/net/eagle0/common/llm_integration:streaming_text_results",
|
||||
"//src/main/scala/net/eagle0/eagle/library/actions/llm_prompt_generators:generator_utilities",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/hero_generation_response",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator/random_hero_generator",
|
||||
"//src/main/scala/net/eagle0/eagle/model/proto_converters/date",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:fixed_heroes",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:great_person",
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:start_date",
|
||||
],
|
||||
)
|
||||
#scala_binary(
|
||||
# name = "hero_library_generator",
|
||||
# srcs = ["HeroLibraryGenerator.scala"],
|
||||
# main_class = "net.eagle0.util.HeroLibraryGenerator",
|
||||
# resources = [
|
||||
# "//src/main/resources/net/eagle0/eagle:headshots",
|
||||
# "//src/main/resources/net/eagle0/eagle:heroes",
|
||||
# ],
|
||||
# visibility = ["//visibility:public"],
|
||||
# deps = [
|
||||
# "//src/main/scala/net/eagle0/common:functional_random",
|
||||
# "//src/main/scala/net/eagle0/common/llm_integration:chat_gpt_service_impl",
|
||||
# "//src/main/scala/net/eagle0/eagle/library/actions/llm_prompt_generators:generator_utilities",
|
||||
# "//src/main/scala/net/eagle0/eagle/library/util/hero_generator/random_hero_generator",
|
||||
# "//src/main/scala/net/eagle0/eagle/service/new_game_creation:fixed_heroes",
|
||||
# ],
|
||||
#)
|
||||
|
||||
scala_binary(
|
||||
name = "name_list_checker",
|
||||
|
||||
@@ -1,72 +1,59 @@
|
||||
package net.eagle0.util
|
||||
|
||||
import net.eagle0.common.SeededRandom
|
||||
import net.eagle0.common.llm_integration.{
|
||||
ClaudeServiceImpl,
|
||||
ExternalTextGenerationCaller,
|
||||
OpenAIChatCompletionsServiceImpl,
|
||||
StreamingTextResults
|
||||
}
|
||||
import net.eagle0.common.llm_integration.OpenAIChatCompletionsServiceImpl
|
||||
import net.eagle0.common.{RandomState, SeededRandom}
|
||||
import net.eagle0.eagle.common.profession.Profession
|
||||
import net.eagle0.eagle.internal.hero.Hero
|
||||
import net.eagle0.eagle.common.gender.Gender
|
||||
import net.eagle0.eagle.library.actions.llm_prompt_generators.GeneratorUtilities.{
|
||||
academyName,
|
||||
conjunction
|
||||
}
|
||||
import net.eagle0.eagle.library.util.hero_generator.hero_generation_response.HeroGenerationResponse
|
||||
import net.eagle0.eagle.library.util.hero_generator.random_hero_generator.RandomHeroGenerator
|
||||
import net.eagle0.eagle.model.state.hero.concrete.HeroC
|
||||
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
|
||||
import net.eagle0.eagle.service.new_game_creation.{FixedHeroes, StartDate}
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
import net.eagle0.eagle.service.new_game_creation.FixedHeroes
|
||||
|
||||
import java.io.FileOutputStream
|
||||
import java.util.function.Consumer
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutor}
|
||||
import scala.util.{Random, Success, Using}
|
||||
import scala.concurrent.duration.Duration
|
||||
import scala.util.{Random, Success}
|
||||
|
||||
object HeroLibraryGenerator {
|
||||
private val random = new Random()
|
||||
private val heroFilePath: String = "/net/eagle0/eagle/heroes.tsv"
|
||||
val heroFilePath = "/net/eagle0/eagle/heroes.tsv"
|
||||
private val generatedHeroesFilePath = "/net/eagle0/eagle/generated_heroes.tsv"
|
||||
val heroCount = 10
|
||||
|
||||
private val openAICaller = new OpenAIChatCompletionsServiceImpl(
|
||||
timeoutSeconds = 90,
|
||||
defaultModelName = OpenAIChatCompletionsServiceImpl.gpt4
|
||||
)
|
||||
private val claudeCaller = new ClaudeServiceImpl(
|
||||
timeoutSeconds = 90,
|
||||
defaultModelName = ClaudeServiceImpl.model
|
||||
)
|
||||
|
||||
implicit val ec: ExecutionContextExecutor = ExecutionContext.global
|
||||
|
||||
val random = new Random()
|
||||
private def randomElement[T](elts: Seq[T]): T =
|
||||
elts(random.nextInt(elts.length))
|
||||
|
||||
def genderString(gender: Gender): String = gender match {
|
||||
case Gender.Female => "female"
|
||||
case Gender.Male => "male"
|
||||
case Gender.Other => "other"
|
||||
case Gender.GENDER_UNKNOWN => "unknown"
|
||||
case Gender.GENDER_FEMALE => "female"
|
||||
case Gender.GENDER_MALE => "male"
|
||||
case Gender.GENDER_OTHER => "other"
|
||||
case Gender.Unrecognized(_) => ???
|
||||
}
|
||||
|
||||
private def professionString(profession: Profession) = profession match {
|
||||
case Profession.Mage => "mage"
|
||||
case Profession.Necromancer => "necromancer"
|
||||
case Profession.Engineer => "engineer"
|
||||
case Profession.Paladin => "paladin"
|
||||
case Profession.Ranger => "ranger"
|
||||
case Profession.Champion => "champion"
|
||||
case Profession.NoProfession => "noProfession"
|
||||
case Profession.UNKNOWN_PROFESSION => "unknownProfession"
|
||||
case Profession.MAGE => "mage"
|
||||
case Profession.NECROMANCER => "necromancer"
|
||||
case Profession.ENGINEER => "engineer"
|
||||
case Profession.PALADIN => "paladin"
|
||||
case Profession.RANGER => "ranger"
|
||||
case Profession.CHAMPION => "champion"
|
||||
case Profession.NO_PROFESSION => "noProfession"
|
||||
case Profession.Unrecognized(_) => ???
|
||||
}
|
||||
|
||||
private def heroTsvString(hero: LoadedHero): String = {
|
||||
private def heroTsvString(hero: Hero): String = {
|
||||
val sum =
|
||||
hero.strength + hero.agility + hero.constitution + hero.charisma + hero.wisdom
|
||||
|
||||
val personalityWords = hero.personalityWords.mkString(", ")
|
||||
|
||||
s"${hero.name}\t${hero.strength}\t${hero.agility}\t${hero.constitution}\t${hero.charisma}\t${hero.wisdom}\t$sum\t${hero.integrity}\t${hero.ambition}\t${hero.gregariousness}\t${hero.bravery}\t${hero.vigor}\t${professionString(
|
||||
s"${hero.name}\t${hero.strength}\t${hero.agility}\t${hero.constitution}\t${hero.charisma}\t${hero.wisdom}\t$sum\t${hero.integrity}\t${hero.ambition}\t${hero.gregariousness}\t${hero.bravery}\t${hero.vigor.toInt}\t${professionString(
|
||||
hero.profession
|
||||
)}\tFALSE\t${hero.imagePath}\t${genderString(hero.pronounGender)}\t${hero.backstory}\t$personalityWords"
|
||||
}
|
||||
@@ -84,19 +71,19 @@ object HeroLibraryGenerator {
|
||||
else if (value <= 15) Some(negativeWord)
|
||||
else None
|
||||
|
||||
private def extraPersonalityWords(hero: HeroC): Vector[String] = (
|
||||
private def extraPersonalityWords(hero: Hero): Vector[String] = (
|
||||
personalityWord(hero.strength, "strong", "feeble") ++
|
||||
personalityWord(hero.agility, "agile", "clumsy") ++
|
||||
personalityWord(hero.charisma, "charismatic", "dull") ++
|
||||
personalityWord(hero.wisdom, "intelligent", "dumb")
|
||||
).toVector
|
||||
|
||||
private def personalityString(hero: HeroC): String =
|
||||
private def personalityString(hero: Hero): String =
|
||||
conjunction(
|
||||
randomElement(hero.personalityWords) +: extraPersonalityWords(hero)
|
||||
).get
|
||||
|
||||
private def heroLine(hero: HeroC): String =
|
||||
private def heroLine(hero: Hero): String =
|
||||
s"(${genderString(hero.pronounGender)}) (${professionString(
|
||||
hero.profession
|
||||
)}) (${personalityString(hero)}) ${hero.name}"
|
||||
@@ -106,17 +93,12 @@ object HeroLibraryGenerator {
|
||||
val randomHeroes = FixedHeroes.parse(generatedHeroesFilePath).get
|
||||
|
||||
val usedHeroes =
|
||||
heroes.greatPeople.map(
|
||||
_.greatPerson.hero
|
||||
) ++ heroes.others ++ randomHeroes.greatPeople.map(
|
||||
_.greatPerson.hero
|
||||
) ++ randomHeroes.others
|
||||
heroes.greatPeople ++ heroes.others ++ randomHeroes.greatPeople ++ randomHeroes.others
|
||||
|
||||
val usedNames = usedHeroes.map(_.name)
|
||||
val usedImagePaths = usedHeroes.map(_.imagePath)
|
||||
|
||||
val heroGenerator = new RandomHeroGenerator(
|
||||
functionalRandom = SeededRandom(seed = new Random().nextLong()),
|
||||
excludingNames = usedNames,
|
||||
excludingImagePaths = usedImagePaths
|
||||
)
|
||||
@@ -126,113 +108,57 @@ object HeroLibraryGenerator {
|
||||
)
|
||||
randomHeroes.others.foreach { hero => println(heroTsvString(hero)) }
|
||||
|
||||
val factionHeadNames = conjunction(
|
||||
heroes.greatPeople.map(_.greatPerson.hero.name)
|
||||
).get
|
||||
val factionDescriptions =
|
||||
s"Possible leaders of the factions are: $factionHeadNames."
|
||||
val promptString =
|
||||
s"""This is a fantasy setting with a medieval technology level. Multiple factions are engaged in a civil war for
|
||||
|control of the kingdom after a mysterious stranger from afar, a powerful mage called The Eagle, invaded the realm.
|
||||
|King Bregos Fyar's right-hand man, Ikhaan Tarn, betrayed the King to join with The Eagle.
|
||||
|Several other factions arose under powerful heroes, allied with neither the King nor The Eagle.
|
||||
|$factionDescriptions
|
||||
|$academyName, where mages and other practitioners of arcane magics are trained and practice, has remained neutral,
|
||||
|though some of its members take part in the war.
|
||||
|
|
||||
|The following are the names of $heroCount heroes that are not yet affiliated with any faction. Each name
|
||||
|is preceded by their gender, their profession, if any, and a few notes about their personality or traits,
|
||||
|all in parentheses. Make up a one-paragraph backstory, no more than 120 words each, for each hero. Make
|
||||
|the backstory consistent with the background given above. The backstory may refer to the any of the factions
|
||||
|or their leaders or to other heroes listed here, but it does not need to. Put the backstories in the same
|
||||
|order as the names given here, but do not number them. Do not include any other context beyond the in-world
|
||||
|text of the response itself.""".stripMargin
|
||||
.replaceAll("\n", " ")
|
||||
val factionHeadNames = conjunction(heroes.greatPeople.map(_.name)).get
|
||||
|
||||
val _ = Using(
|
||||
new FileOutputStream(
|
||||
"/tmp/new_generated_heroes" + random.nextLong().toHexString + ".tsv"
|
||||
)
|
||||
) { outputStream =>
|
||||
for (_ <- 1 to 500) {
|
||||
val newHeroesState =
|
||||
(1 to heroCount).toVector.foldLeft(Vector[HeroGenerationResponse]()) {
|
||||
case (acc, hid) =>
|
||||
val heroState =
|
||||
heroGenerator
|
||||
.getHero(hid = 0, date = StartDate.startDate)
|
||||
.getOrElse(
|
||||
throw new IllegalStateException(
|
||||
s"Failed to generate hero with id $hid"
|
||||
)
|
||||
)
|
||||
acc :+ heroState
|
||||
}
|
||||
val chatGptCaller = new OpenAIChatCompletionsServiceImpl(
|
||||
timeoutSeconds = 90,
|
||||
defaultModelName = OpenAIChatCompletionsServiceImpl.gpt4
|
||||
)
|
||||
|
||||
val newHeroes = newHeroesState.map(_.hero)
|
||||
// val nameRequests = newHeroesState.map(_.nameInfo)
|
||||
|
||||
val caller = new ExternalTextGenerationCaller(
|
||||
timeoutSeconds = 90,
|
||||
serviceImpl = claudeCaller
|
||||
for (_ <- 1 to 50) {
|
||||
val newHeroesState = (1 to heroCount).toVector.foldLeft(
|
||||
RandomState[Vector[Hero]](
|
||||
newValue = Vector(),
|
||||
SeededRandom(seed = new Random().nextLong())
|
||||
)
|
||||
) { case (RandomState(acc, nextRandom), _) =>
|
||||
val heroState = heroGenerator.getHero(random = nextRandom, hid = 0)
|
||||
heroState.map(h => acc :+ h)
|
||||
}
|
||||
|
||||
var allText = ""
|
||||
val consumer: Consumer[StreamingTextResults] = {
|
||||
case StreamingTextResults(streamId, textValue, completed) =>
|
||||
if (completed) {
|
||||
val backstories = allText.split("\n").filterNot(_.isEmpty)
|
||||
if (backstories.length != newHeroes.length) {
|
||||
println(
|
||||
s"Expected ${newHeroes.length} backstories, but got ${backstories.length}"
|
||||
)
|
||||
} else {
|
||||
val heroesWithBackstories =
|
||||
newHeroes.zip(backstories).map { case (hero, backstory) =>
|
||||
LoadedHero(
|
||||
name = hero.name,
|
||||
id = hero.id,
|
||||
factionId = None,
|
||||
backstory = backstory,
|
||||
strength = hero.strength,
|
||||
agility = hero.agility,
|
||||
constitution = hero.constitution,
|
||||
charisma = hero.charisma,
|
||||
wisdom = hero.wisdom,
|
||||
integrity = hero.integrity,
|
||||
ambition = hero.ambition,
|
||||
gregariousness = hero.gregariousness,
|
||||
bravery = hero.bravery,
|
||||
vigor = hero.vigor.toInt,
|
||||
profession = hero.profession,
|
||||
imagePath = hero.imagePath,
|
||||
pronounGender = hero.pronounGender,
|
||||
personalityWords = hero.personalityWords
|
||||
)
|
||||
}
|
||||
val newHeroes = newHeroesState.newValue
|
||||
|
||||
val tsv =
|
||||
heroesWithBackstories
|
||||
.map(heroTsvString)
|
||||
.mkString("\r\n") + "\r\n"
|
||||
val promptString =
|
||||
"This is a fantasy setting with a medieval technology level. Multiple factions are engaged in a civil war for " +
|
||||
"control of the kingdom after a mysterious stranger from afar, a powerful mage called The Eagle, invaded the " +
|
||||
"realm. King Bregos Fyar's right-hand man, Ikhaan Tarn, betrayed the King to join with The Eagle. Several other " +
|
||||
"factions arose under powerful heroes, allied with neither the King nor The Eagle. " +
|
||||
s"Among the great heroes that might be leading factions are $factionHeadNames. " +
|
||||
s"$academyName, where mages " +
|
||||
"and other practitioners of arcane magics are trained and practice, has remained neutral, though some of its " +
|
||||
"members take part in the war.\n\n" +
|
||||
s"The following are the names of $heroCount heroes that are not yet affiliated with any faction. Each name " +
|
||||
"is preceded by their gender, their profession, if any, and a few notes about their personality or traits, " +
|
||||
"all in parentheses. Make up a one-paragraph backstory, no more than 120 words each, for each hero. Make " +
|
||||
"the backstory consistent with the " +
|
||||
"background given above. Put the backstories in the same order " +
|
||||
"as the names given here, but do not number them. Do not include any other context beyond the in-world text " +
|
||||
"of the response itself.\n\n" +
|
||||
newHeroes.map(heroLine).mkString("\n")
|
||||
val future =
|
||||
chatGptCaller.getCompletion(promptString, 1).map { response =>
|
||||
val backstories = response.value.split("\n").filterNot(_.isEmpty)
|
||||
val heroesWithBackstories =
|
||||
newHeroes.zip(backstories).map { case (hero, backstory) =>
|
||||
hero.withBackstory(backstory)
|
||||
}
|
||||
|
||||
outputStream.write(tsv.getBytes("UTF-8"))
|
||||
outputStream.flush()
|
||||
println(s"Stream completed for $streamId")
|
||||
}
|
||||
} else
|
||||
allText += textValue
|
||||
heroesWithBackstories.map(heroTsvString).mkString("\n")
|
||||
}
|
||||
|
||||
val promptWithNames =
|
||||
promptString ++ newHeroes.map(heroLine).mkString("\n")
|
||||
|
||||
val future = caller.streamCompletion(promptWithNames, None, consumer, 0)
|
||||
|
||||
Await.ready(future, Duration.Inf).value match {
|
||||
case Some(Success(value)) => println(value)
|
||||
case _ => throw new IllegalStateException("Failure!")
|
||||
}
|
||||
Await.ready(future, Duration.Inf).value match {
|
||||
case Some(Success(value)) => println(value)
|
||||
case _ => throw new IllegalStateException("Failure!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
load("@io_bazel_rules_scala//scala:scala.bzl", "scala_library")
|
||||
|
||||
scala_library(
|
||||
name = "loaded_hero",
|
||||
srcs = ["LoadedHero.scala"],
|
||||
visibility = [
|
||||
"//src/main/scala/net/eagle0:__subpackages__",
|
||||
"//src/test/scala/net/eagle0/eagle:__subpackages__",
|
||||
],
|
||||
exports = [
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:gender",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero:profession",
|
||||
],
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
package net.eagle0.util.hero_generation
|
||||
|
||||
import net.eagle0.eagle.{FactionId, HeroId}
|
||||
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
|
||||
|
||||
import scala.util.hashing.MurmurHash3
|
||||
|
||||
case class LoadedHero(
|
||||
name: String,
|
||||
factionId: Option[FactionId] = None,
|
||||
id: HeroId,
|
||||
backstory: String = "",
|
||||
strength: Int = 0,
|
||||
agility: Int = 0,
|
||||
constitution: Int = 0,
|
||||
charisma: Int = 0,
|
||||
wisdom: Int = 0,
|
||||
integrity: Int = 0,
|
||||
ambition: Int = 0,
|
||||
gregariousness: Int = 0,
|
||||
bravery: Int = 0,
|
||||
vigor: Int = 0,
|
||||
profession: Profession = Profession.NoProfession,
|
||||
imagePath: String = "",
|
||||
pronounGender: Gender = Gender.Other,
|
||||
personalityWords: Vector[String] = Vector.empty
|
||||
) {
|
||||
def withId(newId: HeroId): LoadedHero = copy(id = newId)
|
||||
def withFactionId(newFactionId: FactionId): LoadedHero =
|
||||
copy(factionId = Some(newFactionId))
|
||||
def nameTextId =
|
||||
s"fhn_${MurmurHash3.stringHash(name).toHexString}"
|
||||
def backstoryTextId = s"${name}_backstory 0"
|
||||
}
|
||||
@@ -12,7 +12,6 @@ scala_test(
|
||||
"//src/main/scala/net/eagle0/eagle/library:engine_impl",
|
||||
"//src/main/scala/net/eagle0/eagle/library:game_history",
|
||||
"//src/main/scala/net/eagle0/eagle/library/util/hero_generator",
|
||||
"//src/main/scala/net/eagle0/eagle/model/state/hero/concrete",
|
||||
"//src/main/scala/net/eagle0/eagle/service:in_memory_history",
|
||||
"@maven//:org_scalamock_scalamock_2_13",
|
||||
],
|
||||
|
||||
@@ -24,7 +24,6 @@ scala_test(
|
||||
"//src/main/scala/net/eagle0/eagle/service/new_game_creation:loaded_hero_conversion",
|
||||
"//src/main/scala/net/eagle0/eagle/shardok_interface:battle_resolution",
|
||||
"//src/main/scala/net/eagle0/eagle/shardok_interface:battle_update_receiver",
|
||||
"//src/main/scala/net/eagle0/util/hero_generation:loaded_hero",
|
||||
"//src/test/scala/net/eagle0/common:proto_matchers",
|
||||
"@maven//:org_scalamock_scalamock_2_13",
|
||||
],
|
||||
|
||||
@@ -15,11 +15,11 @@ import net.eagle0.eagle.service.new_game_creation.{
|
||||
ExpandedGameParameters,
|
||||
GreatPerson,
|
||||
GreatPersonWithBackstory,
|
||||
LoadedHero,
|
||||
LoadedHeroConversion,
|
||||
NewGameCreation
|
||||
}
|
||||
import net.eagle0.eagle.service.persistence.Persister
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
import org.scalamock.scalatest.MockFactory
|
||||
import org.scalatest.BeforeAndAfterEach
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package net.eagle0.eagle.service.new_game_creation
|
||||
|
||||
import net.eagle0.eagle.model.state.hero.{Gender, Profession}
|
||||
import net.eagle0.util.hero_generation.LoadedHero
|
||||
import org.scalatest.flatspec.AnyFlatSpec
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
|
||||
|
||||
Reference in New Issue
Block a user