Rename Travel command to Visit Town (#8641)

This commit is contained in:
2026-07-16 08:47:06 -07:00
committed by GitHub
parent 4abdefd40d
commit 74b816d3f4
102 changed files with 458 additions and 433 deletions
+1 -1
View File
@@ -156,7 +156,7 @@ CREATE TABLE action_changed_provinces (
support_delta REAL,
-- round properties
set_has_acted INTEGER, -- 0/1/NULL
set_ruler_is_traveling INTEGER,
set_ruler_is_visiting_town INTEGER,
-- ruling faction changes
clear_ruling_faction_id INTEGER NOT NULL DEFAULT 0,
new_ruling_faction_id INTEGER,
+1 -1
View File
@@ -72,7 +72,7 @@ Only post a selected command that is currently listed as available. A successful
Some actions enter a temporary subcommand state. For example, trading is operated as:
```text
post-json <province-id> TravelSelectedCommand {}
post-json <province-id> VisitTownSelectedCommand {}
post-json <province-id> TradeSelectedCommand {"tradeType":"BUY_FOOD","amount":<amount>}
post-return <province-id>
```
+2 -2
View File
@@ -287,8 +287,8 @@ You play **Sadar Rakon**, formerly Ikhaan Tarn's most trusted lieutenant. Tarn's
| 5 | `tutorial_support_deadline` | December nag if support < 40: have Elena give alms now |
| 6 | `guidance_expand` (script `tutorial_expansion`) | Once support is stable: keep developing, taxes coming in January |
| 7 | `tutorial_taxes_collected` | January: gold/food collected. Now expand — March your warlord + most heroes to a neighbor, leave 12 behind |
| 8 | `tutorial_ready_to_join` | A free hero in `{provinceName}` is ready to recruit → Travel + Recruit |
| 9 | `tutorial_in_town` | When you Travel: explains Trade / Arm Troops / Divine / Recruit / Manage Prisoners; *Return* ends the turn |
| 8 | `tutorial_ready_to_join` | A free hero in `{provinceName}` is ready to recruit → Visit Town + Recruit |
| 9 | `tutorial_in_town` | When you Visit Town: explains Trade / Arm Troops / Divine / Recruit / Manage Prisoners; *Return* ends the turn |
| 10 | `tutorial_faction_appears` | **The twist**: Fracture Covenant lands at Ingia and Soria. *The Eagle* commands them. Tarn may be with them |
| 11 | `tutorial_hero_departed` | First King's hero abandons service — "something deeper is at work" |
| 12 | `tutorial_hero_departed_again` | Second one in a different month — "something is wrong, I can feel it" (foreshadowing) |
+1 -1
View File
@@ -78,7 +78,7 @@ This section lists quests with direct `QuestCommandChooser` handlers in `Fulfill
|-------|---------|-------|
| `GrandArmyQuest` | `GrandArmyQuestCommandChooser` | Uses OrganizeTroops to top off existing battalions and hire Light Infantry. Only executes if resources are sufficient to fully meet the troop target. |
| `BattalionDiversityQuest` | `BattalionDiversityQuestCommandChooser` | Hires one battalion of a missing type to reach 3+ distinct types. Only attempts if the province already has 2+ existing types, has sufficient development (`meetsRequirements`), and gold/food surplus. |
| `UpgradeBattalionQuest` | `UpgradeBattalionQuestCommandChooser` | Walks a priority tree per turn: arm-completes (with optional travel and/or food sale setup) → train-completes → march in a pre-qualified neighbor battalion → organize/top-off of the target type → march in an unqualified neighbor battalion → develop Economy/Agriculture → train progress → develop Infrastructure → arm progress. Only toggles Travel when it directly enables an arm-completes finisher. |
| `UpgradeBattalionQuest` | `UpgradeBattalionQuestCommandChooser` | Walks a priority tree per turn: arm-completes (with optional Visit Town and/or food sale setup) → train-completes → march in a pre-qualified neighbor battalion → organize/top-off of the target type → march in an unqualified neighbor battalion → develop Economy/Agriculture → train progress → develop Infrastructure → arm progress. Only chooses Visit Town when it directly enables an arm-completes finisher. |
### Reconnaissance Quests
@@ -63,7 +63,7 @@ The two parts remain one tactical unit. If the battalion reaches zero troops, it
[**Organize Troops**](/commands/#organize-troops) creates, resizes, merges, transfers, or dismisses battalions. New troops cost gold and begin without training or armament. Transfers preserve weighted training and armament. Empty battalions are removed.
Use [**Train**](/commands/#train) to improve eligible battalions in the province and [**Arm Troops**](/commands/#arm-troops) while traveling to buy higher armament. Province economy and agriculture affect which types can be raised; effective infrastructure limits equipment.
Use [**Train**](/commands/#train) to improve eligible battalions in the province and [**Arm Troops**](/commands/#arm-troops) while visiting town to buy higher armament. Province economy and agriculture affect which types can be raised; effective infrastructure limits equipment.
## Movement, food, and battle
@@ -164,7 +164,7 @@ Look for growth or attack opportunities. The vassal first tries to march into ne
<b>Available when:</b> the acting province has movable heroes, battalions, gold, or food and at least one valid destination.
<b>Effect:</b> Move heroes, battalions, gold, and food from one province to another. March is inter-province movement and always has a destination; [Travel](#travel) is only a local visit within the current province. The selected units and supplies leave the origin province immediately, each marching hero spends vigor and gains wisdom XP, and the destination receives an [incoming army](/provinces/#incoming-armies) scheduled for the next round.
<b>Effect:</b> Move heroes, battalions, gold, and food from one province to another. March is inter-province movement and always has a destination; [Visit Town](#visit-town) is only a local visit within the current province. The selected units and supplies leave the origin province immediately, each marching hero spends vigor and gains wisdom XP, and the destination receives an [incoming army](/provinces/#incoming-armies) scheduled for the next round.
If the destination is already ruled by your faction when the army arrives, the heroes, battalions, gold, and food enter the province during the next round's Province Move Resolution phase, before riots, vassal commands, and player commands.
@@ -279,23 +279,23 @@ Shipments arrive during the next round's Province Move Resolution phase, before
<b>Selection:</b> choose the acting hero.
### Travel
### Visit Town
<b>Hero requirements:</b> None. The acting province's ruling hero makes the visit.
<b>Vigor cost:</b> 15.
<b>Available when:</b> the acting province's ruling hero has at least 40 vigor, the province is not already in the traveling command state, and there is no blizzard.
<b>Available when:</b> the acting province's ruling hero has at least 40 vigor, the hero is not already visiting town, and there is no blizzard.
<b>Effect:</b> Have the ruling hero leave camp to visit the town inside the acting province. Travel does not move any hero, battalion, or supplies to another province, so it has no destination; use [March](#march) for inter-province movement.
<b>Effect:</b> Have the ruling hero leave camp to visit the town inside the acting province. Visit Town does not move any hero, battalion, or supplies to another province, so it has no destination; use [March](#march) for inter-province movement.
Travel spends the ruling hero's vigor and switches the province into its local traveling command state, unlocking whichever town commands below are currently eligible. You can use as many eligible traveling commands as you want in the same round before using Return to go back to camp. If no town activity currently qualifies, Return may be the only command available.
Visit Town spends the ruling hero's vigor and unlocks whichever town commands below are currently eligible. You can use as many eligible town commands as you want in the same round before using Return to go back to camp. If no town activity currently qualifies, Return may be the only command available.
<b>Selection:</b> no additional choices. Travel always visits the current province's town and never asks you to select a destination.
<b>Selection:</b> no additional choices. Visit Town always uses the current province and never asks you to select a destination.
## Traveling Commands
## Town Commands
You must use Travel before these local town commands appear. Travel keeps the ruling hero in the current province; it only changes the available command set from camp duties to town activities. Once traveling, you can use as many eligible traveling commands as you want in one round before using Return to come back to camp.
You must use Visit Town before these local commands appear. The ruling hero remains in the current province; only the available command set changes from camp duties to town activities. While visiting town, you can use as many eligible town commands as you want in one round before using Return to come back to camp.
### Arm Troops
@@ -303,7 +303,7 @@ You must use Travel before these local town commands appear. Travel keeps the ru
<b>Vigor cost:</b> None.
<b>Available when:</b> you are traveling, the province has gold, and at least one battalion can raise ARM without exceeding effective infrastructure.
<b>Available when:</b> the ruling hero is visiting town, the province has gold, and at least one battalion can raise ARM without exceeding effective infrastructure.
<b>Effect:</b> Spend gold to raise armament on existing battalions. New armament must be higher than the battalion's current armament and cannot exceed the province's effective infrastructure. The province spends gold, the price index may change, and each armed battalion records a backstory event.
@@ -315,7 +315,7 @@ You must use Travel before these local town commands appear. Travel keeps the ru
<b>Vigor cost:</b> None.
<b>Available when:</b> you are traveling and an [unaffiliated hero](/heroes/#unaffiliated-heroes) quest is available in the province.
<b>Available when:</b> the ruling hero is visiting town and an [unaffiliated hero](/heroes/#unaffiliated-heroes) quest is available in the province.
<b>Effect:</b> Decline one of the unaffiliated hero quests available in the acting province.
@@ -329,7 +329,7 @@ You must use Travel before these local town commands appear. Travel keeps the ru
<b>Gold cost:</b> 100 gold per selected hero, multiplied by the province [price index](/provinces/#price-index) and rounded to the nearest whole gold for each hero. The total cost is that per-hero cost multiplied by the number of selected heroes. For example, divining 3 heroes at a 1.25 price index costs 375 gold.
<b>Available when:</b> you are traveling, the province can pay the cost for at least one hero, and there are free heroes who are not yet ready to join your faction but might be won over.
<b>Available when:</b> the ruling hero is visiting town, the province can pay the cost for at least one hero, and there are free heroes who are not yet ready to join your faction but might be won over.
<b>Effect:</b> Spend gold to divine one or more [free heroes](/factions/#free-heroes). For each divined hero, you receive details about what could impress them enough to become recruitable. Fulfill that ask, and the hero can later appear under Recruit Heroes. The province spends gold, and the price index may change.
@@ -341,7 +341,7 @@ You must use Travel before these local town commands appear. Travel keeps the ru
<b>Vigor cost:</b> None.
<b>Available when:</b> you are traveling and the province has prisoner heroes with available management options.
<b>Available when:</b> the ruling hero is visiting town and the province has prisoner heroes with available management options.
<b>Effect:</b> Choose what happens to ordinary prisoners in the province. These are heroes who are already in the prisoner state, not newly captured heroes still waiting for a battle aftermath decision.
@@ -385,7 +385,7 @@ Ordinary prisoners cannot be returned this way. Faction leader prisoners cannot
<b>Vigor cost:</b> None.
<b>Available when:</b> you are traveling and unaffiliated heroes in the province are willing to join.
<b>Available when:</b> the ruling hero is visiting town and unaffiliated heroes in the province are willing to join.
<b>Effect:</b> Recruit available unaffiliated heroes in the acting province. Recruited heroes join the faction at starting loyalty, move from the province's unaffiliated hero list into its ruling faction heroes, and receive a recruitment backstory event.
@@ -397,9 +397,9 @@ Ordinary prisoners cannot be returned this way. Faction leader prisoners cannot
<b>Vigor cost:</b> None.
<b>Available when:</b> you are traveling.
<b>Available when:</b> the ruling hero is visiting town.
<b>Effect:</b> Return the ruling hero from the current province's town to camp, leave the traveling command state, and end that province's turn.
<b>Effect:</b> Return the ruling hero from the current province's town to camp and end that province's turn.
<b>Selection:</b> no additional choices.
@@ -409,7 +409,7 @@ Ordinary prisoners cannot be returned this way. Faction leader prisoners cannot
<b>Vigor cost:</b> None.
<b>Available when:</b> you are traveling and the province has enough gold or food for at least one trade.
<b>Available when:</b> the ruling hero is visiting town and the province has enough gold or food for at least one trade.
<b>Effect:</b> Buy or sell food using the acting province's gold and food stores. Food buy and sell prices are based on the province price index. Buying spends gold and adds food; selling removes food and adds gold. The price index may change after the trade.
@@ -5314,7 +5314,7 @@ PrefabInstance:
- target: {fileID: 1555308994113599573, guid: 911c5413c29434fa8a462a0442ce7a75,
type: 3}
propertyPath: m_Name
value: Travel Panel
value: Visit Town Panel
objectReference: {fileID: 0}
- target: {fileID: 7194983473711936932, guid: 911c5413c29434fa8a462a0442ce7a75,
type: 3}
@@ -63,7 +63,7 @@ namespace eagle {
{ AvailableCommand.SealedValueOneofCase.SwearBrotherhoodCommand, "swear-kinship" },
{ AvailableCommand.SealedValueOneofCase.TradeCommand, "trade" },
{ AvailableCommand.SealedValueOneofCase.TrainCommand, "train" },
{ AvailableCommand.SealedValueOneofCase.TravelCommand, "travel" },
{ AvailableCommand.SealedValueOneofCase.VisitTownCommand, "visit-town" },
};
private readonly struct CommandInfo {
@@ -219,9 +219,9 @@ namespace eagle {
"Exchange food and gold using the province's buy and sell prices.") },
{ AvailableCommand.SealedValueOneofCase.TrainCommand,
new CommandInfo("Train", "Have a hero train to improve their abilities.") },
{ AvailableCommand.SealedValueOneofCase.TravelCommand,
{ AvailableCommand.SealedValueOneofCase.VisitTownCommand,
new CommandInfo(
"Travel",
"Visit Town",
"Have the ruling hero visit the current province's town to unlock local commands.") },
};
@@ -13,7 +13,7 @@ GameObject:
- component: {fileID: 6289363470016652304}
- component: {fileID: 1398189250911451454}
m_Layer: 0
m_Name: Travel Panel
m_Name: Visit Town Panel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -102,7 +102,7 @@ GameObject:
- component: {fileID: 7408366842504297803}
- component: {fileID: 2299640137554880340}
m_Layer: 0
m_Name: Travel command description
m_Name: Visit Town command description
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -1,21 +0,0 @@
using System;
using Net.Eagle0.Eagle.Api;
namespace eagle {
using ProvinceId = Int32;
public class TravelCommandSelector : CommandSelector {
public override AvailableCommand.SealedValueOneofCase CommandType =>
AvailableCommand.SealedValueOneofCase.TravelCommand;
public override string HeaderString => "Travel";
public override string CommitButtonString => "Commit Travel";
private TravelAvailableCommand TravelAvailableCommand => _availableCommand.TravelCommand;
private ProvinceId ActingProvinceId => TravelAvailableCommand.ActingProvinceId;
protected override void SetUpUI() {}
public override SelectedCommand Command =>
new SelectedCommand { TravelCommand = new TravelSelectedCommand() };
}
}
@@ -0,0 +1,22 @@
using System;
using Net.Eagle0.Eagle.Api;
namespace eagle {
using ProvinceId = Int32;
public class VisitTownCommandSelector : CommandSelector {
public override AvailableCommand.SealedValueOneofCase CommandType =>
AvailableCommand.SealedValueOneofCase.VisitTownCommand;
public override string HeaderString => "Visit Town";
public override string CommitButtonString => "Commit Visit Town";
private VisitTownAvailableCommand VisitTownAvailableCommand =>
_availableCommand.VisitTownCommand;
private ProvinceId ActingProvinceId => VisitTownAvailableCommand.ActingProvinceId;
protected override void SetUpUI() {}
public override SelectedCommand Command =>
new SelectedCommand { VisitTownCommand = new VisitTownSelectedCommand() };
}
}
@@ -494,8 +494,8 @@ namespace eagle {
if (SelectedProvince is ProvinceId pid) {
var province = Model.Provinces[pid];
if (province.RulingFactionId is FactionId fid && fid == Model.PlayerId &&
province.FullInfo.RulerIsTraveling) {
soundManager.CurrentMusicType = SoundManager.MusicType.MusicTraveling;
province.FullInfo.RulerIsVisitingTown) {
soundManager.CurrentMusicType = SoundManager.MusicType.MusicVisitTown;
return;
}
if (Model.AvailableCommandsForProvince(pid).Exists(
@@ -1026,8 +1026,8 @@ namespace eagle {
if (nfi.Support != null) province.FullInfo.Support = nfi.Support;
if (nfi.SetRulerIsTraveling is {} newRulerIsTraveling)
province.FullInfo.RulerIsTraveling = newRulerIsTraveling;
if (nfi.SetRulerIsVisitingTown is {} newRulerIsVisitingTown)
province.FullInfo.RulerIsVisitingTown = newRulerIsVisitingTown;
if (nfi.NewProvinceOrders != null)
province.FullInfo.ProvinceOrders = nfi.NewProvinceOrders.Orders;
@@ -152,7 +152,7 @@ namespace eagle0.Tests {
true);
textProvider.HandleNewStreamingText(
"ready-instruction",
"Travel to {provinceName}.",
"Visit Town in {provinceName}.",
0,
true);
@@ -184,7 +184,7 @@ namespace eagle0.Tests {
Assert.IsTrue(converted);
Assert.AreEqual("A hero in Onmaa is ready to join.", script.steps[0].dialogueText);
Assert.AreEqual("Travel to Onmaa.", script.steps[0].instructionText);
Assert.AreEqual("Visit Town in Onmaa.", script.steps[0].instructionText);
textProvider.Clear();
}
@@ -26,7 +26,7 @@ public class SoundManager : MonoBehaviour {
private readonly MusicTypeInfo _summerMusic = new MusicTypeInfo("music-summer");
private readonly MusicTypeInfo _autumnMusic = new MusicTypeInfo("music-autumn");
private readonly MusicTypeInfo _winterMusic = new MusicTypeInfo("music-winter");
private readonly MusicTypeInfo _travelingMusic = new MusicTypeInfo("music-travel");
private readonly MusicTypeInfo _visitTownMusic = new MusicTypeInfo("music-travel");
private readonly MusicTypeInfo _battleMusic = new MusicTypeInfo("music-battle");
private readonly MusicTypeInfo _victoryMusic = new MusicTypeInfo("music-victory");
@@ -299,7 +299,7 @@ public class SoundManager : MonoBehaviour {
{ MusicType.MusicSummer, _summerMusic },
{ MusicType.MusicAutumn, _autumnMusic },
{ MusicType.MusicWinter, _winterMusic },
{ MusicType.MusicTraveling, _travelingMusic },
{ MusicType.MusicVisitTown, _visitTownMusic },
{ MusicType.MusicBattle, _battleMusic },
{ MusicType.MusicVictory, _victoryMusic }
};
@@ -398,7 +398,7 @@ public class SoundManager : MonoBehaviour {
MusicSummer,
MusicAutumn,
MusicWinter,
MusicTraveling,
MusicVisitTown,
MusicBattle,
MusicVictory
}
@@ -75,7 +75,7 @@ message AvailableCommand {
SwearBrotherhoodAvailableCommand swear_brotherhood_command = 33;
TradeAvailableCommand trade_command = 34;
TrainAvailableCommand train_command = 35;
TravelAvailableCommand travel_command = 36;
VisitTownAvailableCommand visit_town_command = 36;
BattleAftermathDecisionAvailableCommand battle_aftermath_decision_command = 41;
}
}
@@ -408,7 +408,7 @@ message TrainAvailableCommand {
int32 recommended_hero_id = 3;
}
message TravelAvailableCommand {
message VisitTownAvailableCommand {
int32 acting_province_id = 1;
}
@@ -69,7 +69,7 @@ message SelectedCommand {
SwearBrotherhoodSelectedCommand swear_brotherhood_command = 33;
TradeSelectedCommand trade_command = 34;
TrainSelectedCommand train_command = 35;
TravelSelectedCommand travel_command = 36;
VisitTownSelectedCommand visit_town_command = 36;
BattleAftermathDecisionSelectedCommand battle_aftermath_decision_command = 41;
}
}
@@ -288,7 +288,7 @@ message TrainSelectedCommand {
int32 acting_hero_id = 1;
}
message TravelSelectedCommand {}
message VisitTownSelectedCommand {}
message BattleAftermathDecisionSelectedCommand {
enum BattleAftermathDecision {
@@ -34,7 +34,7 @@ enum ActionResultType {
NEW_ROUND_ACTION = 15;
NEW_YEAR_ACTION = 16;
IMPROVE = 17;
TRAVEL = 18;
VISIT_TOWN = 18;
RETURN = 19;
ARM_TROOPS = 20;
RECRUIT_HEROES = 21;
@@ -49,6 +49,6 @@ enum CommandType {
COMMAND_TYPE_SWEAR_BROTHERHOOD = 37;
COMMAND_TYPE_TRADE = 38;
COMMAND_TYPE_TRAIN = 39;
COMMAND_TYPE_TRAVEL = 40;
COMMAND_TYPE_VISIT_TOWN = 40;
COMMAND_TYPE_BATTLE_AFTERMATH_DECISION = 41;
}
@@ -75,7 +75,7 @@ message ChangedProvince {
.google.protobuf.BoolValue set_has_acted = 20;
.google.protobuf.BoolValue set_ruler_is_traveling = 21;
.google.protobuf.BoolValue set_ruler_is_visiting_town = 21;
repeated .net.eagle0.eagle.internal.UnaffiliatedHero new_unaffiliated_heroes = 22;
repeated .net.eagle0.eagle.internal.UnaffiliatedHero changed_unaffiliated_heroes = 30;
@@ -91,7 +91,7 @@ message Province {
bool has_acted = 18;
bool ruler_is_traveling = 19;
bool ruler_is_visiting_town = 19;
repeated .net.eagle0.eagle.internal.UnaffiliatedHero unaffiliated_heroes = 20;
repeated .net.eagle0.eagle.internal.CapturedHero captured_heroes = 23;
@@ -71,7 +71,7 @@ message FullProvinceInfo {
StatWithCondition support = 13;
bool ruler_is_traveling = 15;
bool ruler_is_visiting_town = 15;
int32 food_consumption = 16;
@@ -136,7 +136,7 @@ message FullProvinceInfoDiff {
StatWithCondition support = 19;
.google.protobuf.BoolValue set_ruler_is_traveling = 20;
.google.protobuf.BoolValue set_ruler_is_visiting_town = 20;
message ProvinceOrdersOption {
.net.eagle0.eagle.common.ProvinceOrderType orders = 1;
@@ -31,7 +31,7 @@ minVigorForFlee 20 Double
minVigorForImprove 40 Double
minVigorForSendSupplies 50 Double
minVigorForTrain 40 Double
minVigorForTravel 40 Double
minVigorForVisitTown 40 Double
minVigorForRecon 50 Double
newHeroChance 0.001 Double
newRoundVigorGain 5 Double
1 actionVigorCost 15 Int
31 minVigorForImprove 40 Double
32 minVigorForSendSupplies 50 Double
33 minVigorForTrain 40 Double
34 minVigorForTravel minVigorForVisitTown 40 Double
35 minVigorForRecon 50 Double
36 newHeroChance 0.001 Double
37 newRoundVigorGain 5 Double
@@ -90,10 +90,10 @@ tutorial_support_deadline_dialogue Sadar — it's December and the people here s
tutorial_expansion_dialogue_1 Good news, Sadar — the people of Onmaa are behind us. Support is now high enough, so we will collect taxes here in the coming January — gold and food for our cause.
tutorial_expansion_dialogue_2 Until then, keep developing the province. Train the troops, improve the land, and keep our heroes' loyalty high. Every month of preparation now will pay dividends when the real fighting begins.
tutorial_expansion_instruction_2 Keep using <b>Improve</b> and <b>Train</b> to develop Onmaa. Taxes will be collected in <b>January</b>.
tutorial_ready_to_join_dialogue Sadar — there's a hero in {provinceName} who's ready to join our cause. We need every capable sword and mind we can get. By travel, I mean leave our camp and visit the town here in this province. Travel never moves you to another province; that is what March is for.
tutorial_ready_to_join_instruction <b>Travel</b> is a local visit within the current province, so it has no destination. Use it to enter town, then use <b>Recruit</b> to bring the hero into your service. Use <b>March</b> when you want to move between provinces.
tutorial_in_town_dialogue Good — we're in town, still within the same province. Travel has switched us from camp duties to local town business; it has not moved anyone on the strategic map. You can trade food for gold or gold for food, arm your troops with better equipment, divine what free heroes desire, or recruit those willing to join. Take your time — you can do as many of these as you like while you're here.
tutorial_in_town_instruction Travel unlocks the eligible local town commands: <b>Trade</b>, <b>Arm Troops</b>, <b>Divine</b>, <b>Recruit</b>, and <b>Manage Prisoners</b>. If none currently apply, <b>Return</b> may be the only command shown. Use Return to go back to camp — this ends your turn and advances the month.
tutorial_ready_to_join_dialogue Sadar — there's a hero in {provinceName} who's ready to join our cause. We need every capable sword and mind we can get. Use Visit Town to leave camp and meet them in the town here in this province. Visit Town never moves you to another province; that is what March is for.
tutorial_ready_to_join_instruction <b>Visit Town</b> is a local visit within the current province, so it has no destination. Use it to enter town, then use <b>Recruit</b> to bring the hero into your service. Use <b>March</b> when you want to move between provinces.
tutorial_in_town_dialogue Good — we're in town, still within the same province. Visit Town has switched us from camp duties to local town business; it has not moved anyone on the strategic map. You can trade food for gold or gold for food, arm your troops with better equipment, divine what free heroes desire, or recruit those willing to join. Take your time — you can do as many of these as you like while you're here.
tutorial_in_town_instruction Visit Town unlocks the eligible local town commands: <b>Trade</b>, <b>Arm Troops</b>, <b>Divine</b>, <b>Recruit</b>, and <b>Manage Prisoners</b>. If none currently apply, <b>Return</b> may be the only command shown. Use Return to go back to camp — this ends your turn and advances the month.
tutorial_taxes_collected_dialogue_1 January — the tax collectors have made their rounds, and the people came through for us. We have gold and food in the coffers. Gold pays for gifts, feasts, and bribes. Food keeps our soldiers fed and can be given as alms to win more hearts.
tutorial_taxes_collected_dialogue_2 But one province won't win a war. Now that we have resources, it's time to grow. Take most of your heroes with you — especially those with professions — and bring most of the gold and food as well.
tutorial_taxes_collected_dialogue_3 One warning before we march, Sadar: a province must always have one of our heroes ruling it. If every hero leaves Onmaa, we abandon the province immediately — it becomes neutral, and all our work here is lost. Leave at least one loyal hero behind.
@@ -104,8 +104,8 @@ tutorial_attack_prepare_organize_dialogue We've reached the border of another fa
tutorial_attack_prepare_organize_instruction Use <b>Organize Troops</b> to hire soldiers and raise at least <b>two or three full battalions</b> from the troop types currently available.
tutorial_attack_prepare_train_dialogue Good. The ranks are formed; now make certain they know how to fight together. Have a <b>Champion</b> lead their drills if possible — someone like you, Sadar! A full battalion is only as useful as its training.
tutorial_attack_prepare_train_instruction Use <b>Train</b> to improve your battalions' training before attacking.
tutorial_attack_prepare_arm_dialogue They can hold a formation now. The last step is to give them weapons and armor worthy of it. Travel into town and arm the troops before we cross anyone's border. Remember: a province can only provide equipment as good as its infrastructure, so continue improving it if you want better arms.
tutorial_attack_prepare_arm_instruction Use <b>Travel</b> to enter town, then choose <b>Arm Troops</b>. The maximum armament available is limited by the province's <b>Infrastructure</b>.
tutorial_attack_prepare_arm_dialogue They can hold a formation now. The last step is to give them weapons and armor worthy of it. Visit Town and arm the troops before we cross anyone's border. Remember: a province can only provide equipment as good as its infrastructure, so continue improving it if you want better arms.
tutorial_attack_prepare_arm_instruction Use <b>Visit Town</b>, then choose <b>Arm Troops</b>. The maximum armament available is limited by the province's <b>Infrastructure</b>.
tutorial_attack_ready_dialogue We're ready to take the initiative, Sadar. We have a strong body of trained, properly armed troops on the frontier. Take at least two heroes — preferably three — with a battalion under each of them, and march into the hostile province. Just remember to leave someone behind to hold our own land.
tutorial_attack_ready_instruction You have at least <b>1,500 troops</b> with <b>50+ training</b> and <b>30+ armament</b>. Use <b>March</b> to send at least <b>two heroes</b> — preferably three — each leading a battalion, into a neighboring hostile province. Leave at least one faction hero behind.
tutorial_game_over_dialogue Sadar, if you can hear me, either the prison walls are thinner than advertised or death has excellent acoustics. You have most likely been killed or captured, which is a remarkably inconvenient condition for the leader of a rebellion. With nobody left free to command the Reclamation, this campaign is over.
Can't render this file because it contains an unexpected character in line 9 and column 47.
@@ -2,7 +2,7 @@ package net.eagle0.eagle.ai
import net.eagle0.common.{FunctionalRandom, RandomState}
import net.eagle0.eagle.library.util.command_choice_helpers.CommandChoiceHelpers.{
chosenCommandWhileTraveling,
chosenCommandWhileVisitingTown,
chosenDevelopCommand,
chosenUnderAttackCommand
}
@@ -33,7 +33,7 @@ object EarlyGameAIClient {
availableCommands = acs,
rankedChoosers = Vector[CommandChooser](
(fid: FactionId, gs: GameState, acs: Vector[AvailableCommand], fr: FunctionalRandom) =>
chosenCommandWhileTraveling(fid, gs, acs, fr),
chosenCommandWhileVisitingTown(fid, gs, acs, fr),
(fid: FactionId, gs: GameState, acs: Vector[AvailableCommand], fr: FunctionalRandom) =>
RandomState(chosenUnderAttackCommand(fid, gs, acs), fr),
(fid: FactionId, gs: GameState, acs: Vector[AvailableCommand], fr: FunctionalRandom) =>
@@ -100,7 +100,7 @@ object MidGameAIClient {
),
(actingFactionId, gameState, availableCommands, functionalRandom) =>
RandomState(
maybeChosenTravelToRecruitCommand(
maybeChosenVisitTownToRecruitCommand(
actingFactionId,
gameState,
availableCommands
@@ -283,7 +283,7 @@ object MidGameAIClient {
"offer truce with hostile neighbor to buy development time"
),
(prepareAttackCommand, "prepare attack with hostile neighbors"),
(maybeMoveToRecruitCommand, "travel to recruit"),
(maybeMoveToRecruitCommand, "march to recruit"),
(
(actingFactionId, gameState, availableCommands, functionalRandom) =>
RandomState(
@@ -311,7 +311,7 @@ object MidGameAIClient {
),
(
maybeMoveToRecruitCommand,
"chosen hostile neighbors WITH: travel to recruit"
"chosen hostile neighbors WITH: march to recruit"
),
(
(actingFactionId, gameState, availableCommands, functionalRandom) =>
@@ -581,7 +581,7 @@ object MidGameAIClient {
availableCommands,
functionalRandom
).map(_.map(withNeutralNeighborBorderContext(actingFactionId, gameState, availableCommands))),
"chosen neutral neighbors: travel to recruit"
"chosen neutral neighbors: march to recruit"
),
(
(
@@ -669,7 +669,7 @@ object MidGameAIClient {
choosersAndReasons = Vector[(CommandChooser, String)](
(
maybeMoveToRecruitCommand,
"chosen no neutral neighbors, travel to recruit"
"chosen no neutral neighbors, march to recruit"
),
(
(
@@ -687,7 +687,7 @@ object MidGameAIClient {
),
functionalRandom
),
"chosen no neutral neighbors, travel to front"
"chosen no neutral neighbors, march to front"
),
(
(
@@ -1079,14 +1079,14 @@ object MidGameAIClient {
(
(actingFactionId, gameState, availableCommands, functionalRandom) =>
RandomState(
maybeChosenTravelToArmTroopsCommand(
maybeChosenVisitTownToArmTroopsCommand(
actingFactionId,
gameState,
availableCommands
),
functionalRandom
),
"travel to arm troops in preparation for attack"
"visit town to arm troops in preparation for attack"
),
(
(actingFactionId, gameState, availableCommands, functionalRandom) =>
@@ -137,7 +137,7 @@ object StrategicTutorialDialogueSelector {
private def isInTown(state: GameState): Boolean =
state.provinces.values.exists(province =>
province.rulingFactionId.contains(PlayerFactionId) && province.rulerIsTraveling
province.rulingFactionId.contains(PlayerFactionId) && province.rulerIsVisitingTown
)
private def collectedTaxes(before: GameState, after: GameState): Boolean =
@@ -41,7 +41,7 @@ object ProvinceUpdateHelpers2 {
p.copy(
hasActed = cp.setHasActed.getOrElse(p.hasActed),
rulerIsTraveling = cp.setRulerIsTraveling.getOrElse(p.rulerIsTraveling),
rulerIsVisitingTown = cp.setRulerIsVisitingTown.getOrElse(p.rulerIsVisitingTown),
unaffiliatedHeroes = unaffiliatedHeroes,
capturedHeroes = capturedHeroes,
provinceOrders = cp.newProvinceOrders.getOrElse(p.provinceOrders),
@@ -16,7 +16,7 @@ object AvailableArmTroopsCommandFactory extends ScalaAvailableCommandsFactory {
val province = gameState.provinces(provinceId)
Option
.when(province.rulerIsTraveling && province.gold > 0) {
.when(province.rulerIsVisitingTown && province.gold > 0) {
val battalions = province.battalionIds
.map(gameState.battalions)
.filter(
@@ -70,7 +70,7 @@ object AvailableCommandsFactory {
}
class AvailableCommandsFactory(
private val travelingFactories: Vector[ScalaAvailableCommandsFactory] = Vector(
private val townCommandFactories: Vector[ScalaAvailableCommandsFactory] = Vector(
AvailableRecruitHeroesCommandFactory,
AvailableDeclineQuestCommandsFactory,
AvailableDivineCommandsFactory,
@@ -110,7 +110,7 @@ class AvailableCommandsFactory(
AvailableSuppressBeastsCommandFactory,
AvailableSwearBrotherhoodCommandFactory,
AvailableTrainCommandsFactory,
AvailableTravelCommandsFactory
AvailableVisitTownCommandsFactory
)
) {
private def allCommands(
@@ -120,7 +120,7 @@ class AvailableCommandsFactory(
pid: ProvinceId
): Vector[AvailableCommand] =
factories.flatMap(_.availableCommand(gameState, fid, pid)).sortBy {
// Travel commands
// Town commands
case _: RecruitHeroesAvailable => 1
case _: DivineAvailable => 2
case _: ArmTroopsAvailable => 4
@@ -133,7 +133,7 @@ class AvailableCommandsFactory(
case _: ImproveAvailable => 1
case _: TrainAvailable => 2
case _: RestAvailable => 3
case _: TravelAvailable => 4
case _: VisitTownAvailable => 4
case _: MarchAvailable => 5
case _: OrganizeTroopsAvailable => 6
case _: FeastAvailable => 14
@@ -211,7 +211,7 @@ class AvailableCommandsFactory(
optionalOneProvinceAvailableCommands(
province = province,
commands =
if province.rulerIsTraveling then allCommands(travelingFactories, gs, fid, pid)
if province.rulerIsVisitingTown then allCommands(townCommandFactories, gs, fid, pid)
else allCommands(commandPhaseFactories, gs, fid, pid)
)
}
@@ -222,7 +222,7 @@ class AvailableCommandsFactory(
): Boolean = {
val province = gameState.provinces(pid)
val fid = province.getRulingFactionId
if province.rulerIsTraveling then hasCommand(travelingFactories, gameState, fid, pid)
if province.rulerIsVisitingTown then hasCommand(townCommandFactories, gameState, fid, pid)
else hasCommand(commandPhaseFactories, gameState, fid, pid)
}
@@ -17,7 +17,7 @@ object AvailableDeclineQuestCommandsFactory extends ScalaAvailableCommandsFactor
val province = gameState.provinces(provinceId)
MoreOption.flatWhen(
province.rulerIsTraveling
province.rulerIsVisitingTown
&& ProvinceUtils.ruledByFactionLeader(province, gameState.factions.values.toVector)
) {
val withQuests = province.unaffiliatedHeroes
@@ -22,7 +22,7 @@ object AvailableDivineCommandsFactory extends ScalaAvailableCommandsFactory {
val province = gameState.provinces(provinceId)
MoreOption.flatWhen(
province.rulerIsTraveling
province.rulerIsVisitingTown
&& ProvinceUtils.ruledByFactionLeader(province, gameState.factions.values.toVector)
&& province.gold >= effectiveCost(province)
) {
@@ -66,7 +66,7 @@ object AvailableManagePrisonersCommandFactory extends ScalaAvailableCommandsFact
provinceId: ProvinceId
): Option[AvailableCommand] =
MoreOption.flatWhen(
gameState.provinces(provinceId).rulerIsTraveling
gameState.provinces(provinceId).rulerIsVisitingTown
) {
val prisoners = gameState
.provinces(provinceId)
@@ -23,7 +23,7 @@ object AvailableRecruitHeroesCommandFactory extends ScalaAvailableCommandsFactor
Option
.when(
province.rulerIsTraveling &&
province.rulerIsVisitingTown &&
ProvinceUtils.ruledByFactionLeader(province, gameState.factions.values.toVector)
) {
val faction = gameState.factions(factionId)
@@ -18,7 +18,7 @@ object AvailableReturnCommandsFactory extends ScalaAvailableCommandsFactory {
s"Player $factionId does not rule province $provinceId"
)
Option.when(province.rulerIsTraveling)(
Option.when(province.rulerIsVisitingTown)(
ReturnAvailable(actingProvinceId = provinceId)
)
}
@@ -16,7 +16,7 @@ object AvailableTradeCommandFactory extends ScalaAvailableCommandsFactory {
val province = gameState.provinces(provinceId)
Option.when(
province.rulerIsTraveling && (province.gold > 0 || province.food > 0)
province.rulerIsVisitingTown && (province.gold > 0 || province.food > 0)
) {
TradeAvailable(
foodAvailable = province.food,
@@ -1,13 +1,13 @@
package net.eagle0.eagle.library.actions.availability
import net.eagle0.eagle.{FactionId, ProvinceId}
import net.eagle0.eagle.library.settings.MinVigorForTravel
import net.eagle0.eagle.library.settings.MinVigorForVisitTown
import net.eagle0.eagle.library.util.province.ProvinceUtils
import net.eagle0.eagle.model.state.command.available.AvailableCommand
import net.eagle0.eagle.model.state.command.available.AvailableCommand.TravelAvailable
import net.eagle0.eagle.model.state.command.available.AvailableCommand.VisitTownAvailable
import net.eagle0.eagle.model.state.game_state.GameState
object AvailableTravelCommandsFactory extends ScalaAvailableCommandsFactory {
object AvailableVisitTownCommandsFactory extends ScalaAvailableCommandsFactory {
override def availableCommand(
gameState: GameState,
@@ -22,12 +22,12 @@ object AvailableTravelCommandsFactory extends ScalaAvailableCommandsFactory {
)
Option.when(
!province.rulerIsTraveling && !ProvinceUtils.hasBlizzard(province) && province.rulingHeroId
!province.rulerIsVisitingTown && !ProvinceUtils.hasBlizzard(province) && province.rulingHeroId
.flatMap(gameState.heroes.get)
.map(_.vigor)
.exists(_ >= MinVigorForTravel.doubleValue)
.exists(_ >= MinVigorForVisitTown.doubleValue)
) {
TravelAvailable(actingProvinceId = provinceId)
VisitTownAvailable(actingProvinceId = provinceId)
}
}
}
@@ -65,7 +65,7 @@ scala_library(
":available_swear_brotherhood_command_factory",
":available_trade_command_factory",
":available_train_command_factory",
":available_travel_commands_factory",
":available_visit_town_commands_factory",
":scala_available_commands_factory",
"//src/main/scala/net/eagle0/common:more_option",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
@@ -881,8 +881,8 @@ scala_library(
)
scala_library(
name = "available_travel_commands_factory",
srcs = ["AvailableTravelCommandsFactory.scala"],
name = "available_visit_town_commands_factory",
srcs = ["AvailableVisitTownCommandsFactory.scala"],
visibility = [
"//src/test/scala/net/eagle0/eagle/library/actions/availability:__pkg__",
],
@@ -892,7 +892,7 @@ scala_library(
deps = [
":scala_available_commands_factory",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_travel",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_visit_town",
"//src/main/scala/net/eagle0/eagle/library/util/province",
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
"//src/main/scala/net/eagle0/eagle/model/state/game_state",
@@ -248,8 +248,8 @@ case class EndPlayerCommandsPhaseAction(
): RandomState[Vector[ActionResultT]] = {
gameState.provinces.values.foreach { p =>
internalRequire(
!p.rulerIsTraveling,
s"Leader is traveling at the end of the PlayerCommandsPhase in province ${p.id}"
!p.rulerIsVisitingTown,
s"Leader is visiting town at the end of the PlayerCommandsPhase in province ${p.id}"
)
}
@@ -20,8 +20,8 @@ case class EndVassalCommandsPhaseAction(
): RandomState[Vector[ActionResultT]] = {
gameState.provinces.values.foreach { p =>
internalRequire(
!p.rulerIsTraveling,
s"Leader is traveling at the end of the VassalCommandPhase in province ${p.id}"
!p.rulerIsVisitingTown,
s"Leader is visiting town at the end of the VassalCommandPhase in province ${p.id}"
)
}
@@ -302,7 +302,7 @@ case class PerformUnaffiliatedHeroesAction(
val movedHero = gameState.heroes(uh.heroId)
// Extend backstory text visibility to the destination province's ruler so a
// free hero arriving in their territory is legible to them mirrors
// ProvinceConqueredAction (conqueror) and TravelCommand (own ruler).
// ProvinceConqueredAction (conqueror) and VisitTownCommand (own ruler).
// Guarded by backstoryVersions.nonEmpty since backstoryTextId throws when empty.
val backstoryExtensions = Option
.when(movedHero.backstoryVersions.nonEmpty) {
@@ -47,8 +47,8 @@ object ArmTroopsCommand {
)
commandRequire(
actingProvince.rulerIsTraveling,
s"Province ${actingProvince.id} is not in travel state"
actingProvince.rulerIsVisitingTown,
s"Province ${actingProvince.id} is not in town-visit state"
)
ArmTroopsCommand(
@@ -72,7 +72,7 @@ scala_library(
":t_command_factory",
":trade_command",
":train_command",
":travel_command",
":visit_town_command",
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library:eagle_client_exception",
"//src/main/scala/net/eagle0/eagle/library:eagle_internal_exception",
@@ -1389,8 +1389,8 @@ scala_library(
)
scala_library(
name = "travel_command",
srcs = ["TravelCommand.scala"],
name = "visit_town_command",
srcs = ["VisitTownCommand.scala"],
visibility = [
"//src/main/scala/net/eagle0/eagle/library/actions:__subpackages__",
"//src/test/scala/net/eagle0/eagle/library/actions:__subpackages__",
@@ -649,7 +649,7 @@ class CommandFactory extends TCommandFactory {
ReturnCommand.make(
actingFactionId = actingFactionId,
provinceId = ac.actingProvinceId,
rulerIsTraveling = gameState.provinces(ac.actingProvinceId).rulerIsTraveling
rulerIsVisitingTown = gameState.provinces(ac.actingProvinceId).rulerIsVisitingTown
)
case (ac: SendSuppliesAvailable, sc: SendSuppliesSelected) =>
SendSuppliesCommand.make(
@@ -734,12 +734,12 @@ class CommandFactory extends TCommandFactory {
battalionTypes = gameState.battalionTypes.toVector,
currentDate = currentDate(gameState)
)
case (ac: TravelAvailable, _: TravelSelected.type) =>
case (ac: VisitTownAvailable, _: VisitTownSelected.type) =>
val province = gameState.provinces(ac.actingProvinceId)
val rulingHeroId = province.rulingHeroId.getOrElse(
throw new IllegalArgumentException(s"Province ${province.id} has no ruling hero")
)
TravelCommand.make(
VisitTownCommand.make(
province = province,
rulingHero = gameState.heroes(rulingHeroId),
unaffiliatedHeroes = province.unaffiliatedHeroes
@@ -12,12 +12,12 @@ object ReturnCommand {
private case class ReturnCommand(
factionId: FactionId,
provinceId: ProvinceId,
rulerIsTraveling: Boolean
rulerIsVisitingTown: Boolean
) extends ProtolessSimpleAction {
override def immediateExecute: ActionResultT = {
commandRequire(
rulerIsTraveling,
s"Province $provinceId is not in travel state"
rulerIsVisitingTown,
s"Province $provinceId is not in town-visit state"
)
ActionResultC(
@@ -28,7 +28,7 @@ object ReturnCommand {
changedProvinces = Vector(
ChangedProvinceC(
provinceId = provinceId,
setRulerIsTraveling = Some(false)
setRulerIsVisitingTown = Some(false)
)
)
)
@@ -38,11 +38,11 @@ object ReturnCommand {
def make(
actingFactionId: FactionId,
provinceId: ProvinceId,
rulerIsTraveling: Boolean
rulerIsVisitingTown: Boolean
): ProtolessSimpleAction =
ReturnCommand(
factionId = actingFactionId,
provinceId = provinceId,
rulerIsTraveling = rulerIsTraveling
rulerIsVisitingTown = rulerIsVisitingTown
)
}
@@ -41,8 +41,8 @@ object TradeCommand {
) extends ProtolessSimpleAction {
override def immediateExecute: ActionResultT = {
commandRequire(
actingProvince.rulerIsTraveling,
s"province ${actingProvince.id} is not in travel state"
actingProvince.rulerIsVisitingTown,
s"province ${actingProvince.id} is not in town-visit state"
)
commandRequire(
@@ -10,42 +10,42 @@ import net.eagle0.eagle.model.action_result.concrete.{
ClientTextVisibilityExtensionC,
StatDelta
}
import net.eagle0.eagle.model.action_result.types.ActionResultType.Travel
import net.eagle0.eagle.model.action_result.types.ActionResultType.VisitTown
import net.eagle0.eagle.model.action_result.ActionResultT
import net.eagle0.eagle.model.state.hero.HeroT
import net.eagle0.eagle.model.state.province.ProvinceT
object TravelCommand {
object VisitTownCommand {
def make(
province: ProvinceT,
rulingHero: HeroT,
unaffiliatedHeroes: Vector[HeroT]
): ProtolessSimpleAction = {
commandRequire(
!province.rulerIsTraveling,
s"Province ${province.id} is already in travel state"
!province.rulerIsVisitingTown,
s"Province ${province.id} is already in town-visit state"
)
TravelCommand(
VisitTownCommand(
province = province,
rulingHero = rulingHero,
unaffiliatedHeroes = unaffiliatedHeroes
)
}
private case class TravelCommand(
private case class VisitTownCommand(
province: ProvinceT,
rulingHero: HeroT,
unaffiliatedHeroes: Vector[HeroT]
) extends ProtolessSimpleAction {
override def immediateExecute: ActionResultT =
ActionResultC(
actionResultType = Travel,
actionResultType = VisitTown,
provinceId = Some(province.id),
actingFactionId = Some(province.getRulingFactionId),
changedProvinces = Vector(
ChangedProvinceC(
provinceId = province.id,
setRulerIsTraveling = Some(true)
setRulerIsVisitingTown = Some(true)
)
),
changedHeroes = Vector(
@@ -432,8 +432,8 @@ scala_setting_library(
)
scala_setting_library(
name = "min_vigor_for_travel",
setting_name = "MinVigorForTravel",
name = "min_vigor_for_visit_town",
setting_name = "MinVigorForVisitTown",
setting_type = "Double",
setting_value = "40",
visibility = [
@@ -214,7 +214,7 @@ scala_library(
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_start_epidemic",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_suppress_beasts",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_train",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_travel",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_visit_town",
"//src/main/scala/net/eagle0/eagle/library/settings:min_wisdom_for_mage_profession",
"//src/main/scala/net/eagle0/eagle/library/settings:minimum_agility_for_archery",
"//src/main/scala/net/eagle0/eagle/library/settings:minimum_agility_for_start_fire",
@@ -110,7 +110,7 @@ object GameStateViewDiffer {
val beforeById = before.unaffiliatedHeroes.map(uh => uh.heroId -> uh).toMap
after.unaffiliatedHeroes.filterNot(uh => beforeById.get(uh.heroId).contains(uh))
},
setRulerIsTraveling = optionalDiff(before.rulerIsTraveling, after.rulerIsTraveling)
setRulerIsVisitingTown = optionalDiff(before.rulerIsVisitingTown, after.rulerIsVisitingTown)
)
private def emptyFullProvinceInfo = FullProvinceInfo(
@@ -136,7 +136,7 @@ object GameStateViewDiffer {
castleCount = 0,
heroCap = 0,
unaffiliatedHeroes = Vector.empty,
rulerIsTraveling = false
rulerIsVisitingTown = false
)
private def fullProvinceInfoDiff(
@@ -175,7 +175,7 @@ object CommandChoiceHelpers {
gameState = gameState,
availableCommands = availableCommands,
rankedChoosers = Vector[CommandChooser](
chosenCommandWhileTraveling,
chosenCommandWhileVisitingTown,
AttackDecisionCommandChooser.attackDecisionSelectedCommand,
(actingFactionId, gameState, availableCommands, functionalRandom) =>
RandomState(
@@ -190,7 +190,7 @@ object CommandChoiceHelpers {
chosenRescueLeaderIfAllPrisonersCommand,
(actingFactionId, gameState, availableCommands, functionalRandom) =>
RandomState(
maybeChosenTravelToBuyFoodCommand(
maybeChosenVisitTownToBuyFoodCommand(
actingFactionId,
gameState,
availableCommands
@@ -306,7 +306,7 @@ object CommandChoiceHelpers {
),
(actingFactionId, gameState, availableCommands, functionalRandom) =>
RandomState(
maybeChosenTravelToArmTroopsCommand(
maybeChosenVisitTownToArmTroopsCommand(
actingFactionId,
gameState,
availableCommands
@@ -960,12 +960,12 @@ object CommandChoiceHelpers {
.filter(_ > 0)
}
def maybeChosenTravelToBuyFoodCommand(
def maybeChosenVisitTownToBuyFoodCommand(
actingFactionId: FactionId,
gameState: GameState,
availableCommands: Vector[AvailableCommand]
): Option[CommandSelection] =
flatSelectionForType[TravelAvailable](availableCommands) { availableCommand =>
flatSelectionForType[VisitTownAvailable](availableCommands) { availableCommand =>
val province = gameState.provinces(availableCommand.actingProvinceId)
foodAmountToBuy(
province = province,
@@ -973,8 +973,8 @@ object CommandChoiceHelpers {
goldAvailable = province.gold,
foodBuyPrice = BaseFoodBuyPrice.doubleValue * province.priceIndex
).map { _ =>
chosenTravelCommand(actingFactionId, availableCommand).withReason(
"travel to buy food"
chosenVisitTownCommand(actingFactionId, availableCommand).withReason(
"visit town to buy food"
)
}
}
@@ -1671,7 +1671,7 @@ object CommandChoiceHelpers {
)
}
def chosenCommandWhileTraveling(
def chosenCommandWhileVisitingTown(
actingFactionId: FactionId,
gameState: GameState,
availableCommands: Vector[AvailableCommand],
@@ -1716,7 +1716,7 @@ object CommandChoiceHelpers {
actingFactionId,
gameState,
availableCommands,
"chosen command while traveling"
"chosen command while visiting town"
),
functionalRandom
),
@@ -1732,7 +1732,7 @@ object CommandChoiceHelpers {
),
functionalRandom
)
.map(_.map(_.withReason("traveling")))
.map(_.map(_.withReason("visiting town")))
private def maybeChosenRecruitCommand(
actingFactionId: FactionId,
@@ -1808,16 +1808,16 @@ object CommandChoiceHelpers {
)
}
def maybeChosenTravelToArmTroopsCommand(
def maybeChosenVisitTownToArmTroopsCommand(
actingFactionId: FactionId,
gameState: GameState,
availableCommands: Vector[AvailableCommand]
): Option[CommandSelection] =
flatSelectionForType[TravelAvailable](availableCommands) { availableCommand =>
flatSelectionForType[VisitTownAvailable](availableCommands) { availableCommand =>
val actingProvinceId = availableCommand.actingProvinceId
val province = gameState.provinces(actingProvinceId)
// Don't travel if you don't have much extra gold to spend anyway
// Don't visit town if you don't have much extra gold to spend anyway
if provinceGoldSurplus(province) < MinGoldSurplusForArm.intValue
then None
else {
@@ -1829,7 +1829,7 @@ object CommandChoiceHelpers {
Option.when(
battalions.exists(_.armament < highestArmamentWeShouldUpgrade)
)(chosenTravelCommand(actingFactionId, availableCommand))
)(chosenVisitTownCommand(actingFactionId, availableCommand))
}
}
@@ -1932,12 +1932,12 @@ object CommandChoiceHelpers {
.unaffiliatedHeroes
.exists(isInterestingUH)
def maybeChosenTravelToRecruitCommand(
def maybeChosenVisitTownToRecruitCommand(
actingFactionId: FactionId,
gameState: GameState,
availableCommands: Vector[AvailableCommand]
): Option[CommandSelection] =
flatSelectionForType[TravelAvailable](availableCommands) { availableCommand =>
flatSelectionForType[VisitTownAvailable](availableCommands) { availableCommand =>
val actingProvinceId = availableCommand.actingProvinceId
Option.when(
@@ -1949,21 +1949,21 @@ object CommandChoiceHelpers {
gameState
)
) {
chosenTravelCommand(actingFactionId, availableCommand)
chosenVisitTownCommand(actingFactionId, availableCommand)
}
}
.map(_.withReason("travel to recruit"))
.map(_.withReason("visit town to recruit"))
private def chosenTravelCommand(
private def chosenVisitTownCommand(
actingFactionId: FactionId,
ac: TravelAvailable
ac: VisitTownAvailable
): CommandSelection =
CommandSelection(
actingFactionId = actingFactionId,
actingProvinceId = ac.actingProvinceId,
available = ac,
selected = TravelSelected,
reason = "chosenTravelCommand"
selected = VisitTownSelected,
reason = "chosenVisitTownCommand"
)
def chosenTrainCommand(
@@ -20,7 +20,7 @@ import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
OrganizeTroopsAvailable,
TradeAvailable,
TrainAvailable,
TravelAvailable
VisitTownAvailable
}
import net.eagle0.eagle.model.state.command.common.ImprovementType
import net.eagle0.eagle.model.state.command.selected.{ArmedBattalion, CombatUnit, TradeType}
@@ -30,7 +30,7 @@ import net.eagle0.eagle.model.state.command.selected.SelectedCommand.{
OrganizeTroopsSelected,
TradeSelected,
TrainSelected,
TravelSelected
VisitTownSelected
}
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.province.ProvinceT
@@ -69,10 +69,17 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
val best = matching.maxByOption(_.size)
armCompletes(actingFactionId, availableCommands, province, quest, full)
.orElse(travelToEnableArmCompletes(actingFactionId, availableCommands, province, quest, full))
.orElse(visitTownToEnableArmCompletes(actingFactionId, availableCommands, province, quest, full))
.orElse(sellFoodToEnableArmCompletes(actingFactionId, gameState, availableCommands, province, quest, full))
.orElse(
travelToEnableSellFoodThenArmCompletes(actingFactionId, gameState, availableCommands, province, quest, full)
visitTownToEnableSellFoodThenArmCompletes(
actingFactionId,
gameState,
availableCommands,
province,
quest,
full
)
)
.orElse(trainCompletes(actingFactionId, availableCommands, province, quest, full))
.orElse(marchPrequalified(actingFactionId, gameState, availableCommands, questPid, quest, bt, full))
@@ -101,12 +108,12 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
case ata: ArmTroopsAvailable if ata.actingProvinceId == provinceId => ata
}
private def findTravelAvailable(
private def findVisitTownAvailable(
availableCommands: Vector[AvailableCommand],
provinceId: ProvinceId
): Option[TravelAvailable] =
): Option[VisitTownAvailable] =
availableCommands.collectFirst {
case ta: TravelAvailable if ta.actingProvinceId == provinceId => ta
case ta: VisitTownAvailable if ta.actingProvinceId == provinceId => ta
}
private def findTradeAvailable(
@@ -153,7 +160,7 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
b.training >= quest.minimumTraining &&
b.armament < quest.minimumArmament
)
if province.rulerIsTraveling
if province.rulerIsVisitingTown
if province.gold > 0
if quest.minimumArmament <= ProvinceUtils.effectiveInfrastructure(province)
ata <- findArmTroopsAvailable(availableCommands, province.id)
@@ -173,8 +180,8 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
)
}
/** Step A.1: Travel to enable arm-completes next turn. */
private def travelToEnableArmCompletes(
/** Step A.1: Visit Town to enable arm-completes next turn. */
private def visitTownToEnableArmCompletes(
actingFactionId: FactionId,
availableCommands: Vector[AvailableCommand],
province: ProvinceT,
@@ -187,7 +194,7 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
b.training >= quest.minimumTraining &&
b.armament < quest.minimumArmament
)
if !province.rulerIsTraveling
if !province.rulerIsVisitingTown
if province.gold > 0
if quest.minimumArmament <= ProvinceUtils.effectiveInfrastructure(province)
ata <- findArmTroopsAvailable(availableCommands, province.id)
@@ -196,13 +203,13 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
costPerTroop <- armCostPerTroop(ata, quest.battalionTypeId)
goldNeeded = armCostFor(costPerTroop, candidate.armament, minArmInt, candidate.size)
if goldNeeded <= province.gold
travel <- findTravelAvailable(availableCommands, province.id)
visitTown <- findVisitTownAvailable(availableCommands, province.id)
} yield CommandSelection(
actingFactionId = actingFactionId,
actingProvinceId = province.id,
available = travel,
selected = TravelSelected,
reason = "fulfill UpgradeBattalionQuest (travel to enable arm-completes)"
available = visitTown,
selected = VisitTownSelected,
reason = "fulfill UpgradeBattalionQuest (visit town to enable arm-completes)"
)
}
@@ -221,7 +228,7 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
b.training >= quest.minimumTraining &&
b.armament < quest.minimumArmament
)
if province.rulerIsTraveling
if province.rulerIsVisitingTown
if quest.minimumArmament <= ProvinceUtils.effectiveInfrastructure(province)
ata <- findArmTroopsAvailable(availableCommands, province.id)
if ata.availableBattalions.contains(candidate.id)
@@ -252,8 +259,8 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
): Boolean =
ProvinceUtils.monthlyFoodSurplus(province, gameState) - foodToSell >= 0
/** Step A.3: Travel so that next turn we can sell food, then arm-complete. */
private def travelToEnableSellFoodThenArmCompletes(
/** Step A.3: Visit town so that next turn we can sell food, then arm-complete. */
private def visitTownToEnableSellFoodThenArmCompletes(
actingFactionId: FactionId,
gameState: GameState,
availableCommands: Vector[AvailableCommand],
@@ -267,7 +274,7 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
b.training >= quest.minimumTraining &&
b.armament < quest.minimumArmament
)
if !province.rulerIsTraveling
if !province.rulerIsVisitingTown
if quest.minimumArmament <= ProvinceUtils.effectiveInfrastructure(province)
ata <- findArmTroopsAvailable(availableCommands, province.id)
if ata.availableBattalions.contains(candidate.id)
@@ -282,13 +289,13 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
foodToSell = math.ceil(goldDeficit.toDouble / trade.foodSellPrice).toInt
if foodToSell <= trade.foodAvailable
if saleLeavesNonNegativeSurplus(province, gameState, foodToSell)
travel <- findTravelAvailable(availableCommands, province.id)
visitTown <- findVisitTownAvailable(availableCommands, province.id)
} yield CommandSelection(
actingFactionId = actingFactionId,
actingProvinceId = province.id,
available = travel,
selected = TravelSelected,
reason = "fulfill UpgradeBattalionQuest (travel to enable sell-food then arm-completes)"
available = visitTown,
selected = VisitTownSelected,
reason = "fulfill UpgradeBattalionQuest (visit town to enable sell-food then arm-completes)"
)
}
@@ -594,7 +601,7 @@ object UpgradeBattalionQuestCommandChooser extends DeterministicQuestCommandChoo
b <- best
if b.size >= threshold
if b.armament < quest.minimumArmament
if province.rulerIsTraveling
if province.rulerIsVisitingTown
if province.gold > 0
if quest.minimumArmament <= infra
if target > b.armament
@@ -60,7 +60,7 @@ object ProvinceViewFilter {
recruitmentInfo = uh.recruitmentInfo
)
},
rulerIsTraveling = province.rulerIsTraveling
rulerIsVisitingTown = province.rulerIsVisitingTown
)
ProvinceView(
@@ -123,7 +123,7 @@ object ProvinceViewFilter {
recruitmentInfo = uh.recruitmentInfo
)
},
rulerIsTraveling = province.rulerIsTraveling
rulerIsVisitingTown = province.rulerIsVisitingTown
)
ProvinceView(
@@ -188,7 +188,7 @@ object ProvinceViewFilter {
castleCount = province.castleCount,
heroCap = province.heroCap,
unaffiliatedHeroes = Vector.empty,
rulerIsTraveling = province.rulerIsTraveling
rulerIsVisitingTown = province.rulerIsVisitingTown
)
)
.copy(
@@ -330,7 +330,7 @@ object ProvinceViewFilter {
castleCount = province.castleCount,
heroCap = province.heroCap,
unaffiliatedHeroes = province.unaffiliatedHeroes.map(unaffiliatedHeroInfoWithContext(_, gs, ctx, factionId)),
rulerIsTraveling = province.rulerIsTraveling
rulerIsVisitingTown = province.rulerIsVisitingTown
)
}
@@ -43,7 +43,7 @@ case class ChangedProvinceC(
supportDelta: Option[Double] = None,
/* round properties */
setHasActed: Option[Boolean] = None,
setRulerIsTraveling: Option[Boolean] = None,
setRulerIsVisitingTown: Option[Boolean] = None,
/* unaffiliated hero changes */
newUnaffiliatedHeroes: Vector[UnaffiliatedHeroT] = Vector.empty,
changedUnaffiliatedHeroes: Vector[UnaffiliatedHeroT] = Vector.empty,
@@ -23,7 +23,7 @@ enum ActionResultType(val value: Int):
case NewRoundAction extends ActionResultType(15)
case NewYearAction extends ActionResultType(16)
case Improve extends ActionResultType(17)
case Travel extends ActionResultType(18)
case VisitTown extends ActionResultType(18)
case Return extends ActionResultType(19)
case ArmTroops extends ActionResultType(20)
case RecruitHeroes extends ActionResultType(21)
@@ -47,7 +47,7 @@ object ChangedProvinceConverter {
infrastructureDevastationDelta = proto.infrastructureDevastationDelta,
supportDelta = proto.supportDelta,
setHasActed = proto.setHasActed,
setRulerIsTraveling = proto.setRulerIsTraveling,
setRulerIsVisitingTown = proto.setRulerIsVisitingTown,
newUnaffiliatedHeroes = proto.newUnaffiliatedHeroes.map(UnaffiliatedHeroConverter.fromProto).toVector,
changedUnaffiliatedHeroes = proto.changedUnaffiliatedHeroes.map(UnaffiliatedHeroConverter.fromProto).toVector,
removedUnaffiliatedHeroIds = proto.removedUnaffiliatedHeroIds.toVector,
@@ -120,7 +120,7 @@ object ChangedProvinceConverter {
infrastructureDevastationDelta: Option[Double],
supportDelta: Option[Double],
setHasActed: Option[Boolean],
setRulerIsTraveling: Option[Boolean],
setRulerIsVisitingTown: Option[Boolean],
newUnaffiliatedHeroes: Vector[UnaffiliatedHeroT],
changedUnaffiliatedHeroes: Vector[UnaffiliatedHeroT],
removedUnaffiliatedHeroIds: Vector[ProvinceId],
@@ -169,7 +169,7 @@ object ChangedProvinceConverter {
infrastructureDevastationDelta = infrastructureDevastationDelta,
supportDelta = supportDelta,
setHasActed = setHasActed,
setRulerIsTraveling = setRulerIsTraveling,
setRulerIsVisitingTown = setRulerIsVisitingTown,
newUnaffiliatedHeroes = newUnaffiliatedHeroes.map(
UnaffiliatedHeroConverter.toProto
),
@@ -54,7 +54,7 @@ object CommandTypeConverter:
case CommandType.SwearBrotherhood => CommandTypeProto.COMMAND_TYPE_SWEAR_BROTHERHOOD
case CommandType.Trade => CommandTypeProto.COMMAND_TYPE_TRADE
case CommandType.Train => CommandTypeProto.COMMAND_TYPE_TRAIN
case CommandType.Travel => CommandTypeProto.COMMAND_TYPE_TRAVEL
case CommandType.VisitTown => CommandTypeProto.COMMAND_TYPE_VISIT_TOWN
case CommandType.BattleAftermathDecision => CommandTypeProto.COMMAND_TYPE_BATTLE_AFTERMATH_DECISION
/**
@@ -101,7 +101,7 @@ object CommandTypeConverter:
case CommandTypeProto.COMMAND_TYPE_SWEAR_BROTHERHOOD => Some(CommandType.SwearBrotherhood)
case CommandTypeProto.COMMAND_TYPE_TRADE => Some(CommandType.Trade)
case CommandTypeProto.COMMAND_TYPE_TRAIN => Some(CommandType.Train)
case CommandTypeProto.COMMAND_TYPE_TRAVEL => Some(CommandType.Travel)
case CommandTypeProto.COMMAND_TYPE_VISIT_TOWN => Some(CommandType.VisitTown)
case CommandTypeProto.COMMAND_TYPE_BATTLE_AFTERMATH_DECISION => Some(CommandType.BattleAftermathDecision)
case CommandTypeProto.COMMAND_TYPE_UNKNOWN => None
case CommandTypeProto.Unrecognized(12) => None // Removed FFA command type
@@ -455,8 +455,8 @@ object AvailableCommandConverter {
recommendedHeroId = recommendedHeroId
)
case TravelAvailable(actingProvinceId: ProvinceId) =>
proto.TravelAvailableCommand(
case VisitTownAvailable(actingProvinceId: ProvinceId) =>
proto.VisitTownAvailableCommand(
actingProvinceId = actingProvinceId
)
@@ -257,8 +257,8 @@ object SelectedCommandConverter {
case cmd: proto.TrainSelectedCommand =>
TrainSelected(actingHeroId = cmd.actingHeroId)
case _: proto.TravelSelectedCommand =>
TravelSelected
case _: proto.VisitTownSelectedCommand =>
VisitTownSelected
case cmd: proto.BattleAftermathDecisionSelectedCommand =>
BattleAftermathDecisionSelected(
@@ -76,7 +76,7 @@ object ProvinceConverter {
food: Int,
priceIndex: Double,
hasActed: Boolean,
rulerIsTraveling: Boolean,
rulerIsVisitingTown: Boolean,
economy: Double,
agriculture: Double,
infrastructure: Double,
@@ -120,7 +120,7 @@ object ProvinceConverter {
food = food,
priceIndex = priceIndex,
hasActed = hasActed,
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
economy = economy,
agriculture = agriculture,
infrastructure = infrastructure,
@@ -179,7 +179,7 @@ object ProvinceConverter {
priceIndex: Double,
support: Double,
hasActed: Boolean,
rulerIsTraveling: Boolean,
rulerIsVisitingTown: Boolean,
unaffiliatedHeroes: Seq[UnaffiliatedHeroProto],
capturedHeroes: Seq[CapturedHeroProto],
provinceOrders: ProvinceOrderTypeProto,
@@ -213,7 +213,7 @@ object ProvinceConverter {
food = food,
priceIndex = priceIndex,
hasActed = hasActed,
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
economy = economy,
agriculture = agriculture,
infrastructure = infrastructure,
@@ -32,7 +32,7 @@ object FullProvinceInfoConverter {
castleCount = info.castleCount,
heroCap = info.heroCap,
unaffiliatedHeroes = info.unaffiliatedHeroes.map(UnaffiliatedHeroBasicsConverter.toProto),
rulerIsTraveling = info.rulerIsTraveling
rulerIsVisitingTown = info.rulerIsVisitingTown
)
def fromProto(proto: FullProvinceInfoProto): FullProvinceInfo =
@@ -59,6 +59,6 @@ object FullProvinceInfoConverter {
castleCount = proto.castleCount,
heroCap = proto.heroCap,
unaffiliatedHeroes = proto.unaffiliatedHeroes.map(UnaffiliatedHeroBasicsConverter.fromProto).toVector,
rulerIsTraveling = proto.rulerIsTraveling
rulerIsVisitingTown = proto.rulerIsVisitingTown
)
}
@@ -50,7 +50,7 @@ object FullProvinceInfoDiffConverter {
agricultureDevastation = diff.agricultureDevastation,
infrastructureDevastation = diff.infrastructureDevastation,
support = diff.support.map(StatWithConditionConverter.toProto),
setRulerIsTraveling = diff.setRulerIsTraveling,
setRulerIsVisitingTown = diff.setRulerIsVisitingTown,
newProvinceOrders = diff.newProvinceOrders.map(orders =>
FullProvinceInfoDiffProto.ProvinceOrdersOption(ProvinceOrderTypeConverter.toProto(orders))
),
@@ -49,6 +49,6 @@ enum CommandType:
case SwearBrotherhood
case Trade
case Train
case Travel
case VisitTown
case BattleAftermathDecision
end CommandType
@@ -188,7 +188,7 @@ enum AvailableCommand(val commandType: CommandType):
availableHeroIds: Vector[HeroId],
recommendedHeroId: HeroId
) extends AvailableCommand(CommandType.Train)
case TravelAvailable(actingProvinceId: ProvinceId) extends AvailableCommand(CommandType.Travel)
case VisitTownAvailable(actingProvinceId: ProvinceId) extends AvailableCommand(CommandType.VisitTown)
case BattleAftermathDecisionAvailable(
actingProvinceId: ProvinceId,
canKeep: Boolean,
@@ -99,7 +99,7 @@ enum SelectedCommand(val commandType: CommandType):
case SwearBrotherhoodSelected(newBrotherHeroId: HeroId) extends SelectedCommand(CommandType.SwearBrotherhood)
case TradeSelected(tradeType: TradeType, amount: Int) extends SelectedCommand(CommandType.Trade)
case TrainSelected(actingHeroId: HeroId) extends SelectedCommand(CommandType.Train)
case TravelSelected extends SelectedCommand(CommandType.Travel)
case VisitTownSelected extends SelectedCommand(CommandType.VisitTown)
case BattleAftermathDecisionSelected(
decision: BattleAftermathDecisionType,
destinationProvinceId: ProvinceId,
@@ -51,7 +51,7 @@ trait ProvinceT {
def priceIndex: Double
def hasActed: Boolean
def rulerIsTraveling: Boolean
def rulerIsVisitingTown: Boolean
def economy: Double
def agriculture: Double
@@ -105,7 +105,7 @@ trait ProvinceT {
food: Int = food,
priceIndex: Double = priceIndex,
hasActed: Boolean = hasActed,
rulerIsTraveling: Boolean = rulerIsTraveling,
rulerIsVisitingTown: Boolean = rulerIsVisitingTown,
economy: Double = economy,
agriculture: Double = agriculture,
infrastructure: Double = infrastructure,
@@ -144,8 +144,8 @@ trait ProvinceT {
def clearIncomingArmies: ProvinceT = updateWith(incomingArmies = Vector.empty)
def clearHostileArmies: ProvinceT = updateWith(hostileArmies = Vector.empty)
def withRulerIsTraveling(rulerIsTraveling: Boolean): ProvinceT =
updateWith(rulerIsTraveling = rulerIsTraveling)
def withRulerIsVisitingTown(rulerIsVisitingTown: Boolean): ProvinceT =
updateWith(rulerIsVisitingTown = rulerIsVisitingTown)
def withEconomy(economy: Double): ProvinceT =
updateWith(economy = economy)
@@ -38,7 +38,7 @@ case class ProvinceC(
food: Int = 0,
priceIndex: Double = 0.0,
hasActed: Boolean = false,
rulerIsTraveling: Boolean = false,
rulerIsVisitingTown: Boolean = false,
economy: Double = 0.0,
agriculture: Double = 0.0,
infrastructure: Double = 0.0,
@@ -78,7 +78,7 @@ case class ProvinceC(
food: Int = food,
priceIndex: Double = priceIndex,
hasActed: Boolean = hasActed,
rulerIsTraveling: Boolean = rulerIsTraveling,
rulerIsVisitingTown: Boolean = rulerIsVisitingTown,
economy: Double = economy,
agriculture: Double = agriculture,
infrastructure: Double = infrastructure,
@@ -119,7 +119,7 @@ case class ProvinceC(
food = food,
priceIndex = priceIndex,
hasActed = hasActed,
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
economy = economy,
agriculture = agriculture,
infrastructure = infrastructure,
@@ -290,7 +290,7 @@ object TutorialDialogueContent {
marekId,
"tutorial_attack_prepare_arm_dialogue",
instructionTextId = Some("tutorial_attack_prepare_arm_instruction"),
focus = Some(TutorialFocus.Button("TravelButton"))
focus = Some(TutorialFocus.Button("VisitTownButton"))
)
)
)
@@ -29,5 +29,5 @@ case class FullProvinceInfo(
castleCount: Int,
heroCap: Int,
unaffiliatedHeroes: Vector[UnaffiliatedHeroBasics],
rulerIsTraveling: Boolean
rulerIsVisitingTown: Boolean
)
@@ -38,7 +38,7 @@ case class FullProvinceInfoDiff(
agricultureDevastation: Option[Float] = None,
infrastructureDevastation: Option[Float] = None,
support: Option[StatWithCondition] = None,
setRulerIsTraveling: Option[Boolean] = None,
setRulerIsVisitingTown: Option[Boolean] = None,
newProvinceOrders: Option[ProvinceOrderType] = None,
foodConsumption: Option[Int] = None,
goldCap: Option[Int] = None,
@@ -60,7 +60,7 @@ private[service] object ChangedProvinceTableWriter {
| infrastructure_devastation_delta REAL,
| support_delta REAL,
| set_has_acted INTEGER,
| set_ruler_is_traveling INTEGER,
| set_ruler_is_visiting_town INTEGER,
| clear_ruling_faction_id INTEGER NOT NULL DEFAULT 0,
| new_ruling_faction_id INTEGER,
| new_locked_improvement_kind TEXT,
@@ -76,6 +76,9 @@ private[service] object ChangedProvinceTableWriter {
"CREATE INDEX idx_action_changed_provinces_province_id ON action_changed_provinces(province_id)"
)
val renameVisitTownColumnStatement: String =
"ALTER TABLE action_changed_provinces RENAME COLUMN set_ruler_is_traveling TO set_ruler_is_visiting_town"
/**
* Write one `ChangedProvince` for `(actionSeq, n, cp.id)`: the v2 scalar columns (denormalized for querying) plus the
* full proto in `changed_province_proto`. `n` is the position within the source `ActionResult`'s `changedProvinces`
@@ -102,7 +105,7 @@ private[service] object ChangedProvinceTableWriter {
"""INSERT INTO action_changed_provinces
|(action_seq, n, province_id, gold_delta, food_delta, new_price_index, economy_delta, agriculture_delta,
| infrastructure_delta, economy_devastation_delta, agriculture_devastation_delta,
| infrastructure_devastation_delta, support_delta, set_has_acted, set_ruler_is_traveling,
| infrastructure_devastation_delta, support_delta, set_has_acted, set_ruler_is_visiting_town,
| clear_ruling_faction_id, new_ruling_faction_id, new_locked_improvement_kind, new_locked_improvement_value,
| new_province_orders, clear_defending_army, cleared_pending_conquest_info, removed_deferred_change_index,
| changed_province_proto)
@@ -123,7 +126,7 @@ private[service] object ChangedProvinceTableWriter {
setDoubleOpt(ps, 12, cp.infrastructureDevastationDelta)
setDoubleOpt(ps, 13, cp.supportDelta)
setBoolOpt(ps, 14, cp.setHasActed)
setBoolOpt(ps, 15, cp.setRulerIsTraveling)
setBoolOpt(ps, 15, cp.setRulerIsVisitingTown)
ps.setInt(16, if cp.clearRulingFactionId then 1 else 0)
setIntOpt(ps, 17, cp.newRulingFactionId)
setStrOpt(ps, 18, lockedKind)
@@ -1741,7 +1741,8 @@ object SqliteHistory {
Migration(20, applyV20ActionResultVectorTables),
Migration(21, applyV21DropActionResultsPayload),
Migration(22, applyV22ShardokAppliedDeltas),
Migration(23, applyV23DecisionRecords)
Migration(23, applyV23DecisionRecords),
Migration(24, applyV24RenameVisitTownColumn)
)
val latestVersion: Int = all.lastOption.map(_.version).getOrElse(0)
@@ -1813,6 +1814,14 @@ object SqliteHistory {
} finally stmt.close()
}
private def columnExists(connection: Connection, tableName: String, columnName: String): Boolean = {
val stmt = connection.createStatement()
try {
val rs = stmt.executeQuery(s"PRAGMA table_info($tableName)")
Iterator.continually(rs.next()).takeWhile(identity).exists(_ => rs.getString("name") == columnName)
} finally stmt.close()
}
private def actionResultCount(connection: Connection): Int = {
val stmt = connection.createStatement()
try {
@@ -2065,6 +2074,11 @@ object SqliteHistory {
private def applyV23DecisionRecords(connection: Connection): Unit =
execEach(connection, DecisionRecordTableWriter.schemaStatements)
private def applyV24RenameVisitTownColumn(connection: Connection): Unit =
if tableExists(connection, "action_changed_provinces") &&
columnExists(connection, "action_changed_provinces", "set_ruler_is_traveling")
then execEach(connection, Vector(ChangedProvinceTableWriter.renameVisitTownColumnStatement))
}
/**
@@ -664,7 +664,7 @@ private[service] object AIDecisionRecordLogger {
Vector("tradeType" -> jsonString(enumString(tradeType)), "amount" -> jsonNumber(amount))
case TrainSelected(actingHeroId) =>
Vector("actingHeroId" -> jsonNumber(actingHeroId))
case TravelSelected =>
case VisitTownSelected =>
Vector.empty
case BattleAftermathDecisionSelected(decision, destinationProvinceId, gold, food) =>
Vector(
@@ -569,7 +569,7 @@ final class EagleTextClient(config: Config) {
case "SwearBrotherhoodSelectedCommand" => parseJson[sc.SwearBrotherhoodSelectedCommand](json)
case "TradeSelectedCommand" => parseJson[sc.TradeSelectedCommand](json)
case "TrainSelectedCommand" => parseJson[sc.TrainSelectedCommand](json)
case "TravelSelectedCommand" => parseJson[sc.TravelSelectedCommand](json)
case "VisitTownSelectedCommand" => parseJson[sc.VisitTownSelectedCommand](json)
case "BattleAftermathDecisionSelectedCommand" => parseJson[sc.BattleAftermathDecisionSelectedCommand](json)
case other => Failure(new IllegalArgumentException(s"Unknown SelectedCommand type: $other"))
}
@@ -897,7 +897,7 @@ final class ClientState {
agricultureDevastation = diff.agricultureDevastation.getOrElse(withRuler.agricultureDevastation),
infrastructureDevastation = diff.infrastructureDevastation.getOrElse(withRuler.infrastructureDevastation),
support = diff.support.orElse(withRuler.support),
rulerIsTraveling = diff.setRulerIsTraveling.getOrElse(withRuler.rulerIsTraveling),
rulerIsVisitingTown = diff.setRulerIsVisitingTown.getOrElse(withRuler.rulerIsVisitingTown),
provinceOrders = diff.newProvinceOrders.map(_.orders).getOrElse(withRuler.provinceOrders),
foodConsumption = diff.foodConsumption.getOrElse(withRuler.foodConsumption),
goldCap = diff.goldCap.getOrElse(withRuler.goldCap),
@@ -244,7 +244,7 @@ class StrategicTutorialDialogueSelectorTest extends AnyFlatSpec with Matchers {
Vector(TutorialTextReplacement("{provinceName}", TutorialTextReplacementValue.ProvinceName(OnmaaId)))
)
val inTown = state(onmaa = readyOnmaa.copy(rulerIsTraveling = true))
val inTown = state(onmaa = readyOnmaa.copy(rulerIsVisitingTown = true))
selectedIds(ready, inTown, ActionResultType.HeroStatGained) should contain("tutorial_in_town")
}
@@ -57,7 +57,7 @@ class AvailableArmTroopsCommandFactoryTest extends AnyFlatSpec with Matchers wit
private def makeGameState(
battalionIds: Vector[Int] = Vector(lowArmamentBattalion.id, highArmamentBattalion.id),
rulerIsTraveling: Boolean = true,
rulerIsVisitingTown: Boolean = true,
gold: Int = 1200,
priceIndex: Double = 1.0,
infrastructure: Double = 55.0
@@ -75,7 +75,7 @@ class AvailableArmTroopsCommandFactoryTest extends AnyFlatSpec with Matchers wit
rulingFactionId = Some(rulingFactionId),
infrastructure = infrastructure,
battalionIds = battalionIds,
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
gold = gold,
priceIndex = priceIndex
)
@@ -145,9 +145,9 @@ class AvailableArmTroopsCommandFactoryTest extends AnyFlatSpec with Matchers wit
command shouldBe empty
}
it should "return nothing if you are not traveling" in {
it should "return nothing if you are not visiting town" in {
val command = AvailableArmTroopsCommandFactory.availableCommand(
gameState = makeGameState(rulerIsTraveling = false),
gameState = makeGameState(rulerIsVisitingTown = false),
factionId = rulingFactionId,
provinceId = 122
)
@@ -20,8 +20,8 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.BeforeAndAfterEach
class AvailableCommandsFactoryTest extends AnyFlatSpec with Matchers with MockFactory with BeforeAndAfterEach {
private val mockTraveling1 = mock[ScalaAvailableCommandsFactory]
private val mockTraveling2 = mock[ScalaAvailableCommandsFactory]
private val mockTownCommand1 = mock[ScalaAvailableCommandsFactory]
private val mockTownCommand2 = mock[ScalaAvailableCommandsFactory]
private val mockAttackDecisionTier = mock[ScalaAvailableCommandsFactory]
private val mockDefenseTier = mock[ScalaAvailableCommandsFactory]
private val mockCommandsTier1 = mock[ScalaAvailableCommandsFactory]
@@ -136,9 +136,9 @@ class AvailableCommandsFactoryTest extends AnyFlatSpec with Matchers with MockFa
)
private val factory = new AvailableCommandsFactory(
travelingFactories = Vector(
mockTraveling1,
mockTraveling2
townCommandFactories = Vector(
mockTownCommand1,
mockTownCommand2
),
attackDecisionPhaseFactories = Vector(mockAttackDecisionTier),
defensePhaseFactories = Vector(mockDefenseTier),
@@ -456,21 +456,21 @@ class AvailableCommandsFactoryTest extends AnyFlatSpec with Matchers with MockFa
)
}
it should "return only the traveling commands if the province is in travel state" in {
val travelingProvince = baseProvince.copy(rulerIsTraveling = true)
val provinceTravelScalaState = gameStateScala.copy(
provinces = Map(provinceId -> travelingProvince)
it should "return only the town commands if the province is in town-visit state" in {
val visitingTownProvince = baseProvince.copy(rulerIsVisitingTown = true)
val provinceVisitTownScalaState = gameStateScala.copy(
provinces = Map(provinceId -> visitingTownProvince)
)
mockTraveling1.availableCommand
.expects(provinceTravelScalaState, factionId, provinceId)
mockTownCommand1.availableCommand
.expects(provinceVisitTownScalaState, factionId, provinceId)
.returns(Some(returnCommand)): Unit
mockTraveling2.availableCommand
.expects(provinceTravelScalaState, factionId, provinceId)
mockTownCommand2.availableCommand
.expects(provinceVisitTownScalaState, factionId, provinceId)
.returns(Some(armCommand)): Unit
factory
.availablePlayerCommands(provinceTravelScalaState, factionId)
.availablePlayerCommands(provinceVisitTownScalaState, factionId)
.head
._2
.commands should contain theSameElementsAs Vector(
@@ -20,7 +20,7 @@ class AvailableDeclineQuestCommandsFactoryTest extends AnyFlatSpec with Matchers
private val provinceId: ProvinceId = 7
private def makeGameState(
rulerIsTraveling: Boolean = true,
rulerIsVisitingTown: Boolean = true,
rulingHeroId: Option[Int] = Some(10),
rulingFactionHeroIds: Vector[Int] = Vector(10, 11),
unaffiliatedHeroes: Vector[UnaffiliatedHeroC] = Vector(
@@ -59,7 +59,7 @@ class AvailableDeclineQuestCommandsFactoryTest extends AnyFlatSpec with Matchers
provinceId -> ProvinceC(
id = provinceId,
rulingFactionId = Some(actingFactionId),
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
rulingHeroId = rulingHeroId,
rulingFactionHeroIds = rulingFactionHeroIds,
unaffiliatedHeroes = unaffiliatedHeroes
@@ -100,8 +100,8 @@ class AvailableDeclineQuestCommandsFactoryTest extends AnyFlatSpec with Matchers
) shouldBe None
}
it should "return None when the province ruler is not traveling" in {
val gs = makeGameState(rulerIsTraveling = false)
it should "return None when the province ruler is not visiting town" in {
val gs = makeGameState(rulerIsVisitingTown = false)
AvailableDeclineQuestCommandsFactory.availableCommand(
gameState = gs,
@@ -25,7 +25,7 @@ class AvailableDivineCommandsFactoryTest extends AnyFlatSpec with Matchers with
private val actingPid: ProvinceId = 27
private def makeGameState(
rulerIsTraveling: Boolean = true,
rulerIsVisitingTown: Boolean = true,
rulingHeroId: Option[Int] = Some(10),
rulingFactionHeroIds: Vector[Int] = Vector(10, 11),
gold: Int = 1200,
@@ -66,7 +66,7 @@ class AvailableDivineCommandsFactoryTest extends AnyFlatSpec with Matchers with
actingPid -> ProvinceC(
id = actingPid,
rulingFactionId = Some(actingFid),
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
rulingHeroId = rulingHeroId,
rulingFactionHeroIds = rulingFactionHeroIds,
unaffiliatedHeroes = unaffiliatedHeroes,
@@ -109,8 +109,8 @@ class AvailableDivineCommandsFactoryTest extends AnyFlatSpec with Matchers with
) shouldBe None
}
it should "return None when the province ruler is not traveling" in {
val gs = makeGameState(rulerIsTraveling = false)
it should "return None when the province ruler is not visiting town" in {
val gs = makeGameState(rulerIsVisitingTown = false)
AvailableDivineCommandsFactory.availableCommand(
gameState = gs,
@@ -67,7 +67,7 @@ class AvailableManagePrisonerCommandsFactoryTest extends AnyFlatSpec with Before
recruitmentInfo = RecruitmentInfo.Prisoner
)
),
rulerIsTraveling = true,
rulerIsVisitingTown = true,
neighbors = Vector(
Neighbor(provinceId = neighbor1ProvinceId, startingPositionIndex = 5),
Neighbor(provinceId = neighbor2ProvinceId, startingPositionIndex = 6)
@@ -272,21 +272,21 @@ class AvailableManagePrisonerCommandsFactoryTest extends AnyFlatSpec with Before
.availableCommand(gsWithNoPrisoners, actingFactionId, actingProvinceId) shouldBe None
}
it should "return None if the province is not traveling" in {
it should "return None if the province is not visiting town" in {
val actingProvince = inside(baseGameState.provinces(actingProvinceId)) {
case province: ProvinceC =>
province
}
val gsNotTraveling = baseGameState.copy(
val gsNotVisitingTown = baseGameState.copy(
provinces = baseGameState.provinces.updated(
actingProvinceId,
actingProvince.copy(
rulerIsTraveling = false
rulerIsVisitingTown = false
)
)
)
AvailableManagePrisonersCommandFactory
.availableCommand(gsNotTraveling, actingFactionId, actingProvinceId) shouldBe None
.availableCommand(gsNotVisitingTown, actingFactionId, actingProvinceId) shouldBe None
}
}
@@ -39,7 +39,7 @@ class AvailableRecruitHeroesCommandFactoryTest extends AnyFlatSpec with Matchers
private val factionId: FactionId = 3
private def makeGameState(
rulerIsTraveling: Boolean = true,
rulerIsVisitingTown: Boolean = true,
rulingHeroId: Option[Int] = Some(9),
rulingFactionHeroIds: Vector[Int] = Vector(9),
unaffiliatedHeroes: Vector[UnaffiliatedHeroC] = Vector(
@@ -71,7 +71,7 @@ class AvailableRecruitHeroesCommandFactoryTest extends AnyFlatSpec with Matchers
provinceId -> ProvinceC(
id = provinceId,
rulingFactionId = Some(factionId),
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
rulingHeroId = rulingHeroId,
rulingFactionHeroIds = rulingFactionHeroIds,
unaffiliatedHeroes = unaffiliatedHeroes
@@ -118,8 +118,8 @@ class AvailableRecruitHeroesCommandFactoryTest extends AnyFlatSpec with Matchers
MinimumWisdomForStartFire.setDoubleValue(60)
}
"availableCommands" should "return nothing if you are not traveling" in {
val gs = makeGameState(rulerIsTraveling = false)
"availableCommands" should "return nothing if you are not visiting town" in {
val gs = makeGameState(rulerIsVisitingTown = false)
AvailableRecruitHeroesCommandFactory.availableCommand(
gameState = gs,
@@ -72,7 +72,7 @@ class AvailableReturnCommandsFactoryTest extends AnyFlatSpec with Matchers {
ex.getMessage shouldBe "requirement failed: Player 2 does not rule province 24"
}
it should "return nothing if the province is not in traveling state" in {
it should "return nothing if the province is not in town-visit state" in {
val command = AvailableReturnCommandsFactory.availableCommand(
gameState = gameState,
factionId = 1,
@@ -82,14 +82,14 @@ class AvailableReturnCommandsFactoryTest extends AnyFlatSpec with Matchers {
command shouldBe empty
}
it should "return a return command if the province is in a traveling state" in {
val travelingProvince = province.copy(rulerIsTraveling = true)
val gameStateWithTravelingProvince = makeGameState(
provinces = Map(travelingProvince.id -> travelingProvince)
it should "return a return command if the province is in a town-visit state" in {
val visitingTownProvince = province.copy(rulerIsVisitingTown = true)
val gameStateWithVisitingTownProvince = makeGameState(
provinces = Map(visitingTownProvince.id -> visitingTownProvince)
)
val command = AvailableReturnCommandsFactory.availableCommand(
gameState = gameStateWithTravelingProvince,
gameState = gameStateWithVisitingTownProvince,
factionId = 1,
provinceId = province.id
)
@@ -16,7 +16,7 @@ class AvailableTradeCommandFactoryTest extends AnyFlatSpec with Matchers with Be
private def makeGameState(
provinceGold: Int = 2000,
provinceFood: Int = 2500,
rulerIsTraveling: Boolean = true,
rulerIsVisitingTown: Boolean = true,
priceIndex: Double = 1.0
): GameState = GameState(
gameId = 0,
@@ -34,7 +34,7 @@ class AvailableTradeCommandFactoryTest extends AnyFlatSpec with Matchers with Be
rulingFactionHeroIds = Vector(7),
gold = provinceGold,
food = provinceFood,
rulerIsTraveling = rulerIsTraveling,
rulerIsVisitingTown = rulerIsVisitingTown,
priceIndex = priceIndex
)
),
@@ -93,8 +93,8 @@ class AvailableTradeCommandFactoryTest extends AnyFlatSpec with Matchers with Be
}
}
it should "return nothing if the province is not in travel state" in {
val gameState = makeGameState(rulerIsTraveling = false)
it should "return nothing if the province is not in town-visit state" in {
val gameState = makeGameState(rulerIsVisitingTown = false)
val command = AvailableTradeCommandFactory.availableCommand(
gameState = gameState,
@@ -1,8 +1,8 @@
package net.eagle0.eagle.library.actions.availability
import net.eagle0.eagle.library.settings.MinVigorForTravel
import net.eagle0.eagle.library.settings.MinVigorForVisitTown
import net.eagle0.eagle.model.state.{GameType, RoundPhase}
import net.eagle0.eagle.model.state.command.available.AvailableCommand.TravelAvailable
import net.eagle0.eagle.model.state.command.available.AvailableCommand.VisitTownAvailable
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.game_state.GameState
import net.eagle0.eagle.model.state.hero.concrete.HeroC
@@ -14,7 +14,7 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.BeforeAndAfterEach
import org.scalatest.Inside.inside
class AvailableTravelCommandsFactoryTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach {
class AvailableVisitTownCommandsFactoryTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach {
private val rulingHero = HeroC(
id = 17,
@@ -68,14 +68,14 @@ class AvailableTravelCommandsFactoryTest extends AnyFlatSpec with Matchers with
private val gameState = makeGameState()
override def beforeEach(): Unit =
MinVigorForTravel.setDoubleValue(42.0)
MinVigorForVisitTown.setDoubleValue(42.0)
it should "return nothing if the ruling hero has low vigor" in {
val gameStateWithLowVigorHero = makeGameState(
heroes = Map(rulingHero.id -> rulingHero.copy(vigor = 41.5))
)
val command = AvailableTravelCommandsFactory.availableCommand(
val command = AvailableVisitTownCommandsFactory.availableCommand(
gameState = gameStateWithLowVigorHero,
factionId = 1,
provinceId = province.id
@@ -84,13 +84,13 @@ class AvailableTravelCommandsFactoryTest extends AnyFlatSpec with Matchers with
command shouldBe empty
}
it should "return nothing if the province is already in traveling state" in {
val gameStateWithProvinceTraveling = makeGameState(
provinces = Map(province.id -> province.copy(rulerIsTraveling = true))
it should "return nothing if the province is already in town-visit state" in {
val gameStateWithProvinceVisitingTown = makeGameState(
provinces = Map(province.id -> province.copy(rulerIsVisitingTown = true))
)
val command = AvailableTravelCommandsFactory.availableCommand(
gameState = gameStateWithProvinceTraveling,
val command = AvailableVisitTownCommandsFactory.availableCommand(
gameState = gameStateWithProvinceVisitingTown,
factionId = 1,
provinceId = province.id
)
@@ -108,7 +108,7 @@ class AvailableTravelCommandsFactoryTest extends AnyFlatSpec with Matchers with
)
)
val command = AvailableTravelCommandsFactory.availableCommand(
val command = AvailableVisitTownCommandsFactory.availableCommand(
gameState = gsWithBlizzard,
factionId = 1,
provinceId = province.id
@@ -118,21 +118,21 @@ class AvailableTravelCommandsFactoryTest extends AnyFlatSpec with Matchers with
}
it should "return an available command of the appropriate type if the hero has enough vigor" in {
val command = AvailableTravelCommandsFactory.availableCommand(
val command = AvailableVisitTownCommandsFactory.availableCommand(
gameState = gameState,
factionId = 1,
provinceId = province.id
)
inside(command) {
case Some(cmd: TravelAvailable) =>
case Some(cmd: VisitTownAvailable) =>
cmd.actingProvinceId shouldBe province.id
}
}
it should "throw if the given player does not rule the province" in {
val ex = the[IllegalArgumentException] thrownBy
AvailableTravelCommandsFactory.availableCommand(
AvailableVisitTownCommandsFactory.availableCommand(
gameState = gameState,
factionId = 2,
provinceId = province.id
@@ -719,12 +719,12 @@ scala_test(
)
scala_test(
name = "available_travel_commands_factory_test",
srcs = ["AvailableTravelCommandsFactoryTest.scala"],
name = "available_visit_town_commands_factory_test",
srcs = ["AvailableVisitTownCommandsFactoryTest.scala"],
deps = [
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library/actions/availability:available_travel_commands_factory",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_travel",
"//src/main/scala/net/eagle0/eagle/library/actions/availability:available_visit_town_commands_factory",
"//src/main/scala/net/eagle0/eagle/library/settings:min_vigor_for_visit_town",
"//src/main/scala/net/eagle0/eagle/model/state:round_phase",
"//src/main/scala/net/eagle0/eagle/model/state/command/available",
"//src/main/scala/net/eagle0/eagle/model/state/date",
@@ -33,7 +33,7 @@ class ArmTroopsCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfter
private val province = ProvinceC(
id = provinceId,
battalionIds = battalions.map(_.id),
rulerIsTraveling = true,
rulerIsVisitingTown = true,
gold = 9999,
infrastructure = 100,
priceIndex = 1.0
@@ -117,20 +117,20 @@ class ArmTroopsCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfter
ex.getMessage shouldBe s"requirement failed: Selected battalions Vector(7) is not a subset of Vector(23, 99, 221)"
}
it should "throw if the province is not in travel state" in {
val notTravelingProvince = province.withRulerIsTraveling(false)
it should "throw if the province is not in town-visit state" in {
val notVisitingTownProvince = province.withRulerIsVisitingTown(false)
val ex = the[EagleCommandException] thrownBy
ArmTroopsCommand.make(
actingFactionId = factionId,
availableBattalionIds = availableBattalions,
armedBattalions = armedBattalionsForUpgradeAll,
actingProvince = notTravelingProvince,
actingProvince = notVisitingTownProvince,
existingBattalions = battalions,
battalionTypes = battalionTypes,
armamentCosts = armamentCosts
)
ex.getMessage shouldBe s"requirement failed: Province $provinceId is not in travel state"
ex.getMessage shouldBe s"requirement failed: Province $provinceId is not in town-visit state"
}
it should "throw if the same battalion is specified twice" in {
@@ -307,7 +307,7 @@ class ArmTroopsCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfter
result.provinceIdActed shouldBe empty
}
it should "keep the travel state" in {
it should "keep the town-visit state" in {
val command = ArmTroopsCommand.make(
actingFactionId = factionId,
availableBattalionIds = availableBattalions,
@@ -321,7 +321,7 @@ class ArmTroopsCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfter
val result = command.immediateExecute
inside(result.changedProvinces.head) {
case cp: ChangedProvinceC =>
cp.setRulerIsTraveling shouldBe empty
cp.setRulerIsVisitingTown shouldBe empty
}
}
@@ -1098,12 +1098,12 @@ scala_test(
)
scala_test(
name = "travel_command_test",
srcs = ["TravelCommandTest.scala"],
name = "visit_town_command_test",
srcs = ["VisitTownCommandTest.scala"],
deps = [
"//src/main/scala/net/eagle0/eagle:eagle_pkg",
"//src/main/scala/net/eagle0/eagle/library:eagle_client_exception",
"//src/main/scala/net/eagle0/eagle/library/actions/impl/command:travel_command",
"//src/main/scala/net/eagle0/eagle/library/actions/impl/command:visit_town_command",
"//src/main/scala/net/eagle0/eagle/library/actions/impl/common:protoless_simple_action",
"//src/main/scala/net/eagle0/eagle/library/settings:action_vigor_cost",
"//src/main/scala/net/eagle0/eagle/library/settings:vigor_to_constitution_xp_multiplier",
@@ -13,25 +13,25 @@ class ReturnCommandTest extends AnyFlatSpec with Matchers with Inside {
private val actingFactionId: FactionId = 19
private val provinceId: ProvinceId = 7
"execute" should "throw if the province is not in travel state" in {
"execute" should "throw if the province is not in town-visit state" in {
val ex = the[EagleCommandException] thrownBy {
val command = ReturnCommand.make(
actingFactionId = actingFactionId,
provinceId = provinceId,
rulerIsTraveling = false
rulerIsVisitingTown = false
)
command.immediateExecute
}
ex.getMessage shouldBe s"requirement failed: Province $provinceId is not in travel state"
ex.getMessage shouldBe s"requirement failed: Province $provinceId is not in town-visit state"
}
it should "return the appropriate type and basic info" in {
val command = ReturnCommand.make(
actingFactionId = actingFactionId,
provinceId = provinceId,
rulerIsTraveling = true
rulerIsVisitingTown = true
)
val result = command.immediateExecute
@@ -45,11 +45,11 @@ class ReturnCommandTest extends AnyFlatSpec with Matchers with Inside {
}
}
it should "change the province state to not traveling" in {
it should "change the province state to not visiting town" in {
val command = ReturnCommand.make(
actingFactionId = actingFactionId,
provinceId = provinceId,
rulerIsTraveling = true
rulerIsVisitingTown = true
)
val result = command.immediateExecute
@@ -59,7 +59,7 @@ class ReturnCommandTest extends AnyFlatSpec with Matchers with Inside {
ar.changedProvinces shouldBe Vector(
ChangedProvinceC(
provinceId = provinceId,
setRulerIsTraveling = Some(false)
setRulerIsVisitingTown = Some(false)
)
)
}
@@ -30,7 +30,7 @@ class TradeCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
rulingFactionHeroIds = Vector(rulingHeroId),
gold = startingGold,
food = startingFood,
rulerIsTraveling = true,
rulerIsVisitingTown = true,
priceIndex = 1.0
)
@@ -81,12 +81,12 @@ class TradeCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
ex.getMessage shouldBe "Unknown trade type"
}
it should "throw if not in travel state" in {
val notTravelingProvince = province.withRulerIsTraveling(false)
it should "throw if not in town-visit state" in {
val notVisitingTownProvince = province.withRulerIsVisitingTown(false)
val command = TradeCommand.make(
actingFactionId = actingFactionId,
actingProvince = notTravelingProvince,
actingProvince = notVisitingTownProvince,
tradeType = BuyFood,
amount = 500
)
@@ -94,7 +94,7 @@ class TradeCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach
val ex = the[EagleCommandException] thrownBy
command.immediateExecute
ex.getMessage shouldBe s"requirement failed: province $provinceId is not in travel state"
ex.getMessage shouldBe s"requirement failed: province $provinceId is not in town-visit state"
}
it should "throw if amount is zero" in {
@@ -4,7 +4,7 @@ import net.eagle0.eagle.library.settings.{ActionVigorCost, VigorToConstitutionXp
import net.eagle0.eagle.library.EagleCommandException
import net.eagle0.eagle.model.action_result.changed_province.concrete.ChangedProvinceC
import net.eagle0.eagle.model.action_result.concrete.{ChangedHeroC, ClientTextVisibilityExtensionC, StatDelta}
import net.eagle0.eagle.model.action_result.types.ActionResultType.Travel
import net.eagle0.eagle.model.action_result.types.ActionResultType.VisitTown
import net.eagle0.eagle.model.state.date.Date
import net.eagle0.eagle.model.state.hero.backstory_version.BackstoryVersion
import net.eagle0.eagle.model.state.hero.concrete.HeroC
@@ -18,7 +18,7 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.BeforeAndAfterEach
import org.scalatest.LoneElement.convertToCollectionLoneElementWrapper
class TravelCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach {
class VisitTownCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEach {
val actingFactionId = 19
private val date = Date(year = 5, month = Date.Month.October)
@@ -68,24 +68,24 @@ class TravelCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
XpForStatBump.setIntValue(100)
}
"execute" should "throw if the province is already in travel state" in {
val startingStateWithProvinceInTravelState =
province.withRulerIsTraveling(true)
"execute" should "throw if the province is already in town-visit state" in {
val startingStateWithProvinceVisitingTown =
province.withRulerIsVisitingTown(true)
val ex = the[EagleCommandException] thrownBy
TravelCommand
VisitTownCommand
.make(
province = startingStateWithProvinceInTravelState,
province = startingStateWithProvinceVisitingTown,
rulingHero = rulingHero,
unaffiliatedHeroes = unaffiliatedHeroes
)
.immediateExecute
ex.getMessage shouldBe s"requirement failed: Province ${province.id} is already in travel state"
ex.getMessage shouldBe s"requirement failed: Province ${province.id} is already in town-visit state"
}
"the execute result" should "have type TRAVEL" in {
val command = TravelCommand.make(
"the execute result" should "have type VISIT_TOWN" in {
val command = VisitTownCommand.make(
province = province,
rulingHero = rulingHero,
unaffiliatedHeroes = unaffiliatedHeroes
@@ -93,11 +93,11 @@ class TravelCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
val result = command.immediateExecute
result.actionResultType shouldBe Travel
result.actionResultType shouldBe VisitTown
}
it should "change the province state to traveling" in {
val command = TravelCommand.make(
it should "change the province state to visiting town" in {
val command = VisitTownCommand.make(
province = province,
rulingHero = rulingHero,
unaffiliatedHeroes = unaffiliatedHeroes
@@ -109,13 +109,13 @@ class TravelCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
result.changedProvinces shouldBe Vector(
ChangedProvinceC(
provinceId = province.id,
setRulerIsTraveling = Some(true)
setRulerIsVisitingTown = Some(true)
)
)
}
it should "not mark the province as having acted" in {
val command = TravelCommand.make(
val command = VisitTownCommand.make(
province = province,
rulingHero = rulingHero,
unaffiliatedHeroes = unaffiliatedHeroes
@@ -127,7 +127,7 @@ class TravelCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
}
it should "spend vigor on the ruling hero" in {
val command = TravelCommand.make(
val command = VisitTownCommand.make(
province = province,
rulingHero = rulingHero,
unaffiliatedHeroes = unaffiliatedHeroes
@@ -142,7 +142,7 @@ class TravelCommandTest extends AnyFlatSpec with Matchers with BeforeAndAfterEac
}
it should "extend the visibility for unaffiliated heroes in the province" in {
val command = TravelCommand.make(
val command = VisitTownCommand.make(
province = province,
rulingHero = rulingHero,
unaffiliatedHeroes = unaffiliatedHeroes
@@ -8,7 +8,7 @@ import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
DiplomacyAvailable,
DiplomacyOption,
RestAvailable,
TravelAvailable
VisitTownAvailable
}
import net.eagle0.eagle.model.state.command.common.DiplomacyOptionType
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.DiplomacySelected
@@ -91,7 +91,7 @@ class AllianceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Be
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommand,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected =
@@ -122,7 +122,7 @@ class AllianceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Be
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommand,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected =
@@ -159,7 +159,7 @@ class AllianceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Be
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommand,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected =
@@ -196,7 +196,7 @@ class AllianceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Be
it should "return None if there are no diplomacy options available" in {
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected =
@@ -229,7 +229,7 @@ class AllianceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Be
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommandWithoutRightFaction,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected =
@@ -263,7 +263,7 @@ class AllianceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Be
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommandWithOnlyInvite,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected =
@@ -279,7 +279,7 @@ class CommandChoiceHelpersTest extends AnyFlatSpec with Matchers with BeforeAndA
}
}
"maybeChosenTravelToArmTroopsCommand" should "return none if there is no travel command" in {}
"maybeChosenVisitTownToArmTroopsCommand" should "return none if there is no Visit Town command" in {}
it should "return none if there is no extra gold" in {}
@@ -388,7 +388,7 @@ class CommandChoiceHelpersTest extends AnyFlatSpec with Matchers with BeforeAndA
)
}
"maybeChosenTravelToBuyFoodCommand" should "do a travel command if food is needed" in {
"maybeChosenVisitTownToBuyFoodCommand" should "choose Visit Town if food is needed" in {
val gameState = makeGameState(
provinces = mapifyProvincesT(
ProvinceC(
@@ -411,9 +411,9 @@ class CommandChoiceHelpersTest extends AnyFlatSpec with Matchers with BeforeAndA
currentPhase = RoundPhase.PlayerCommands
)
val ac = TravelAvailable(actingProvinceId = 7)
val ac = VisitTownAvailable(actingProvinceId = 7)
CommandChoiceHelpers.maybeChosenTravelToBuyFoodCommand(
CommandChoiceHelpers.maybeChosenVisitTownToBuyFoodCommand(
3,
gameState,
Vector(ac)
@@ -422,13 +422,13 @@ class CommandChoiceHelpersTest extends AnyFlatSpec with Matchers with BeforeAndA
actingFactionId = 3,
actingProvinceId = 7,
available = ac,
selected = TravelSelected,
reason = "travel to buy food"
selected = VisitTownSelected,
reason = "visit town to buy food"
)
)
}
it should "not travel if you don't have any gold anyway" in {
it should "not visit town if you don't have any gold anyway" in {
val gameState = makeGameState(
provinces = mapifyProvincesT(
ProvinceC(
@@ -451,9 +451,9 @@ class CommandChoiceHelpersTest extends AnyFlatSpec with Matchers with BeforeAndA
currentPhase = RoundPhase.PlayerCommands
)
val ac = TravelAvailable(actingProvinceId = 7)
val ac = VisitTownAvailable(actingProvinceId = 7)
CommandChoiceHelpers.maybeChosenTravelToBuyFoodCommand(
CommandChoiceHelpers.maybeChosenVisitTownToBuyFoodCommand(
3,
gameState,
Vector(ac)
@@ -144,11 +144,11 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
recommendedHeroId = 19
)
private val travelCommand = TravelAvailable(actingProvinceId = 18)
private val visitTownCommand = VisitTownAvailable(actingProvinceId = 18)
"chosenFulfillQuestsCommand" should "return a truce command for a specific faction if there is a UH with a truce with faction quest" in {
val availableCommands =
Vector[AvailableCommand](restCommand, truceCommand, travelCommand)
Vector[AvailableCommand](restCommand, truceCommand, visitTownCommand)
FulfillQuestsCommandSelector
.chosenFulfillEasyQuestsCommand(
@@ -174,7 +174,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
it should "return None if the unaffiliated hero is not divined" in {
val availableCommands =
Vector[AvailableCommand](restCommand, truceCommand, travelCommand)
Vector[AvailableCommand](restCommand, truceCommand, visitTownCommand)
val updatedUhs = uhs.updated(0, uhs(0).copy(recruitmentInfo = RecruitmentInfo.LowPrestige))
val gsWithLowPrestige = gameState.copy(
@@ -310,7 +310,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
it should "return None for local quests if there is no faction leader in the province" in {
val availableCommands =
Vector[AvailableCommand](restCommand, truceCommand, travelCommand)
Vector[AvailableCommand](restCommand, truceCommand, visitTownCommand)
val gameStateWithoutFactionLeaderInProvince = gameState.copy(
provinces = gameState.provinces.updated(
@@ -359,7 +359,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
)
val availableCommands =
Vector[AvailableCommand](restCommand, truceCommand, travelCommand)
Vector[AvailableCommand](restCommand, truceCommand, visitTownCommand)
FulfillQuestsCommandSelector
.chosenFulfillEasyQuestsCommand(
@@ -380,7 +380,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
)
val availableCommands =
Vector[AvailableCommand](restCommand, truceCommand, travelCommand)
Vector[AvailableCommand](restCommand, truceCommand, visitTownCommand)
FulfillQuestsCommandSelector
.chosenFulfillEasyQuestsCommand(
@@ -394,7 +394,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
it should "return None if there is no truce command available" in {
val availableCommands =
Vector[AvailableCommand](restCommand, travelCommand)
Vector[AvailableCommand](restCommand, visitTownCommand)
FulfillQuestsCommandSelector
.chosenFulfillEasyQuestsCommand(
@@ -408,7 +408,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
it should "return None if there is low trust in the target faction" in {
val availableCommands =
Vector[AvailableCommand](restCommand, truceCommand, travelCommand)
Vector[AvailableCommand](restCommand, truceCommand, visitTownCommand)
val actingFaction = inside(gameState.factions(actingFactionId)) {
case faction: FactionC =>
@@ -441,7 +441,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
"chosenFulfillQuestsCommand" should "return a truce command if there is a UH with a truce count quest" in {
val availableCommands =
Vector[AvailableCommand](restCommand, truceCommand, travelCommand)
Vector[AvailableCommand](restCommand, truceCommand, visitTownCommand)
val updatedUhs = uhs.updated(
1,
@@ -493,7 +493,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
Vector[AvailableCommand](
restCommand,
moreOptionsTruceCommand,
travelCommand
visitTownCommand
)
val updatedUhs = uhs.updated(
@@ -572,7 +572,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
Vector[AvailableCommand](
restCommand,
moreOptionsTruceCommand,
travelCommand
visitTownCommand
)
val updatedUhs = uhs.updated(
@@ -639,7 +639,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
Vector[AvailableCommand](
restCommand,
moreOptionsTruceCommand,
travelCommand
visitTownCommand
)
val updatedUhs = uhs.updated(
@@ -740,7 +740,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
Vector[AvailableCommand](
restCommand,
improveCommand,
travelCommand
visitTownCommand
)
val updatedUhs = uhs.updated(
@@ -798,7 +798,7 @@ class FulfillQuestsCommandSelectorTest extends AnyFlatSpec with Matchers with Be
Vector[AvailableCommand](
restCommand,
improveCommand,
travelCommand
visitTownCommand
)
val updatedUhs = uhs.updated(
@@ -7,7 +7,7 @@ import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
DiplomacyAvailable,
DiplomacyOption,
RestAvailable,
TravelAvailable
VisitTownAvailable
}
import net.eagle0.eagle.model.state.command.common.DiplomacyOptionType
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.DiplomacySelected
@@ -91,7 +91,7 @@ class TruceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommand,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected = TruceOfferCommandSelector.chosenTruceWithFactionCommand(
@@ -121,7 +121,7 @@ class TruceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommand,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected = TruceOfferCommandSelector.chosenTruceWithFactionCommand(
@@ -157,7 +157,7 @@ class TruceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommand,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected = TruceOfferCommandSelector.chosenTruceWithFactionCommand(
@@ -193,7 +193,7 @@ class TruceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
it should "return None if there are no diplomacy options available" in {
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected = TruceOfferCommandSelector.chosenTruceWithFactionCommand(
@@ -225,7 +225,7 @@ class TruceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommandWithoutRightFaction,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected = TruceOfferCommandSelector.chosenTruceWithFactionCommand(
@@ -258,7 +258,7 @@ class TruceOfferCommandSelectorTest extends AnyFlatSpec with Matchers with Befor
val availableCommands = Vector[AvailableCommand](
RestAvailable(actingProvinceId = 17),
diplomacyCommandWithOnlyInvite,
TravelAvailable(actingProvinceId = 17)
VisitTownAvailable(actingProvinceId = 17)
)
val selected = TruceOfferCommandSelector.chosenTruceWithFactionCommand(
@@ -17,8 +17,8 @@ import net.eagle0.eagle.model.state.command.available.AvailableCommand.{
SuitableBattalions,
TradeAvailable,
TrainAvailable,
TravelAvailable,
TroopCost
TroopCost,
VisitTownAvailable
}
import net.eagle0.eagle.model.state.command.common.ImprovementType
import net.eagle0.eagle.model.state.command.selected.SelectedCommand.{
@@ -28,7 +28,7 @@ import net.eagle0.eagle.model.state.command.selected.SelectedCommand.{
OrganizeTroopsSelected,
TradeSelected,
TrainSelected,
TravelSelected
VisitTownSelected
}
import net.eagle0.eagle.model.state.command.selected.TradeType
import net.eagle0.eagle.model.state.date.Date
@@ -168,7 +168,7 @@ class UpgradeBattalionQuestCommandChooserTest extends AnyFlatSpec with Matchers
economy = 100.0,
infrastructure = 1.0,
support = 100.0,
rulerIsTraveling = true
rulerIsVisitingTown = true
)
private val organizeAvailable: OrganizeTroopsAvailable = OrganizeTroopsAvailable(
@@ -212,7 +212,7 @@ class UpgradeBattalionQuestCommandChooserTest extends AnyFlatSpec with Matchers
recommendedHeroId = factionLeaderId
)
private val travelAvailable: TravelAvailable = TravelAvailable(actingProvinceId = provinceId)
private val visitTownAvailable: VisitTownAvailable = VisitTownAvailable(actingProvinceId = provinceId)
private val improveAvailable: ImproveAvailable = ImproveAvailable(
availableTypes = Vector(
@@ -294,9 +294,9 @@ class UpgradeBattalionQuestCommandChooserTest extends AnyFlatSpec with Matchers
}
}
it should "travel to enable arm-completes next turn (Step A.1)" in {
it should "visit town to enable arm-completes next turn (Step A.1)" in {
val province = baseProvince.copy(
rulerIsTraveling = false,
rulerIsVisitingTown = false,
battalionIds = Vector(battalionId1)
)
val battalions = Map(
@@ -312,13 +312,13 @@ class UpgradeBattalionQuestCommandChooserTest extends AnyFlatSpec with Matchers
val result = UpgradeBattalionQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gs,
availableCommands = Vector(armTroopsAvailable, travelAvailable),
availableCommands = Vector(armTroopsAvailable, visitTownAvailable),
uhsWithQuests = questUhs
)
inside(result) {
case Some(command) =>
command.selected shouldBe TravelSelected
command.selected shouldBe VisitTownSelected
}
}
@@ -362,10 +362,10 @@ class UpgradeBattalionQuestCommandChooserTest extends AnyFlatSpec with Matchers
}
}
it should "travel to enable sell-food then arm-completes (Step A.3)" in {
it should "visit town to enable sell-food then arm-completes (Step A.3)" in {
val province = baseProvince.copy(
gold = 5,
rulerIsTraveling = false,
rulerIsVisitingTown = false,
battalionIds = Vector(battalionId1)
)
val battalions = Map(
@@ -388,13 +388,13 @@ class UpgradeBattalionQuestCommandChooserTest extends AnyFlatSpec with Matchers
val result = UpgradeBattalionQuestCommandChooser.chosenDeterministicCommand(
actingFactionId = actingFactionId,
gameState = gs,
availableCommands = Vector(armTroopsAvailable, trade, travelAvailable),
availableCommands = Vector(armTroopsAvailable, trade, visitTownAvailable),
uhsWithQuests = questUhs
)
inside(result) {
case Some(command) =>
command.selected shouldBe TravelSelected
command.selected shouldBe VisitTownSelected
}
}
@@ -700,9 +700,9 @@ class UpgradeBattalionQuestCommandChooserTest extends AnyFlatSpec with Matchers
}
}
it should "return None when full-size and under-armed but the ruler is not traveling and travel is not available" in {
it should "return None when full-size and under-armed but the ruler is not visiting town and Visit Town is unavailable" in {
val province = baseProvince.copy(
rulerIsTraveling = false,
rulerIsVisitingTown = false,
battalionIds = Vector(battalionId1)
)
val battalions = Map(
@@ -128,7 +128,7 @@ class ProvinceViewFilterTest extends AnyFlatSpec with BeforeAndAfterEach with Ma
castleCount = 0,
heroCap = 5,
unaffiliatedHeroes = unaffiliatedHeroes,
rulerIsTraveling = false
rulerIsVisitingTown = false
)
// Helper to call filteredProvinceView with FilterContext
@@ -170,22 +170,22 @@ class ProvinceViewFilterTest extends AnyFlatSpec with BeforeAndAfterEach with Ma
provinceView.fullInfo.get.economy shouldBe 0.1f
}
it should "show ruler is traveling if they are" in {
val province = ProvinceC(id = 5, rulingFactionId = Some(3), rulerIsTraveling = true)
it should "show ruler is visiting town if they are" in {
val province = ProvinceC(id = 5, rulingFactionId = Some(3), rulerIsVisitingTown = true)
val gs = minimalGameState(provinces = Map(5 -> province))
val provinceView = filteredProvinceView(province, gs, 3)
provinceView.fullInfo.get.rulerIsTraveling shouldBe true
provinceView.fullInfo.get.rulerIsVisitingTown shouldBe true
}
it should "not show ruler is traveling if they are not" in {
val province = ProvinceC(id = 5, rulingFactionId = Some(3), rulerIsTraveling = false)
it should "not show ruler is visiting town if they are not" in {
val province = ProvinceC(id = 5, rulingFactionId = Some(3), rulerIsVisitingTown = false)
val gs = minimalGameState(provinces = Map(5 -> province))
val provinceView = filteredProvinceView(province, gs, 3)
provinceView.fullInfo.get.rulerIsTraveling shouldBe false
provinceView.fullInfo.get.rulerIsVisitingTown shouldBe false
}
it should "show your own incoming armies into your own province" in {
@@ -141,13 +141,13 @@ class AvailableCommandConverterTest extends AnyFlatSpec with Matchers with Befor
}
}
it should "convert TravelAvailable correctly" in {
val cmd = TravelAvailable(actingProvinceId = provinceId)
it should "convert VisitTownAvailable correctly" in {
val cmd = VisitTownAvailable(actingProvinceId = provinceId)
val result = AvailableCommandConverter.toProto(cmd, gameState, factionId)
inside(result) {
case protoCmd: proto.TravelAvailableCommand =>
case protoCmd: proto.VisitTownAvailableCommand =>
protoCmd.actingProvinceId shouldBe provinceId
}
}
@@ -877,12 +877,12 @@ class SelectedCommandConverterTest extends AnyFlatSpec with Matchers {
}
}
it should "convert TravelSelectedCommand correctly" in {
val protoCmd = proto.TravelSelectedCommand()
it should "convert VisitTownSelectedCommand correctly" in {
val protoCmd = proto.VisitTownSelectedCommand()
val result = SelectedCommandConverter.fromProto(protoCmd)
result shouldBe TravelSelected
result shouldBe VisitTownSelected
}
it should "throw exception for empty SelectedCommand" in {

Some files were not shown because too many files have changed in this diff Show More