Skip to content

Commit

Permalink
Cleanup event/error to be more json-like. This changes them
Browse files Browse the repository at this point in the history
to take some additional parameters, and outputs some information
such as an event category and unit or region information for some
events in the json.   This information is already in the text
for the events, so this is just making it nicer for json-based
clients in the future.
  • Loading branch information
jt-traub committed Jan 8, 2024
1 parent f06bbd1 commit cc78421
Show file tree
Hide file tree
Showing 37 changed files with 1,080 additions and 1,305 deletions.
33 changes: 16 additions & 17 deletions aregion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,9 @@ void ARegion::RunDecayEvent(Object *o, ARegionList *pRegs)
pFactions = PresentFactions();
forlist (pFactions) {
Faction *f = ((FactionPtr *) elem)->ptr;
stringstream tmp;
tmp << GetDecayFlavor() << o->name << " " << ObjectDefs[o->type].name << " in " << ShortPrint(pRegs);
f->event(tmp.str());
string tmp = string(GetDecayFlavor().const_str()) + " " + ObjectDefs[o->type].name +
" in " + ShortPrint(pRegs).const_str() + ".";
f->event(tmp, "decay");
}
}

Expand Down Expand Up @@ -1210,12 +1210,11 @@ int ARegion::HasItem(Faction *fac, int item)
return 0;
}

json ARegion::basic_json_data(ARegionList *regions) {
json ARegion::basic_region_data() {
json j;
j["terrain"] = TerrainDefs[type].name;

ARegionArray *level = regions->pRegionArrays[zloc];
string label = (level->strName ? level->strName->const_str() : "surface");
string label = (this->level->strName ? this->level->strName->const_str() : "surface");
j["coordinates"] = { { "x", xloc }, { "y", yloc }, { "z", zloc }, { "label", label } };

// in order to support games with different UW settings, we need to put a bit more information in the JSON to
Expand Down Expand Up @@ -1253,7 +1252,7 @@ void ARegion::build_json_report(json& j, Faction *fac, int month, ARegionList *r
// this faction cannot see this region, why are we even here?
if (!farsight && !passer && !present) return;

j = basic_json_data(regions);
j = basic_region_data();
j["present"] = present && !fac->is_npc;

if (Population() && (present || farsight || (Globals->TRANSIT_REPORT & GameDefs::REPORT_SHOW_PEASANTS))) {
Expand Down Expand Up @@ -1356,7 +1355,7 @@ void ARegion::build_json_report(json& j, Faction *fac, int month, ARegionList *r
for (int i=0; i<NDIRS; i++) {
if (!exits_seen[i] || !neighbors[i]) continue;
j["exits"].push_back(
{ { "direction", DirectionStrs[i] }, { "region", neighbors[i]->basic_json_data(regions) } }
{ { "direction", DirectionStrs[i] }, { "region", neighbors[i]->basic_region_data() } }
);
}

Expand Down Expand Up @@ -1565,7 +1564,7 @@ int ARegion::IsCoastalOrLakeside()
return seacount;
}

int ARegion::MoveCost(int movetype, ARegion *fromRegion, int dir, AString *road)
int ARegion::MoveCost(int movetype, ARegion *fromRegion, int dir, string *road)
{
int cost = 1;
if (Globals->WEATHER_EXISTS) {
Expand Down Expand Up @@ -1666,9 +1665,9 @@ int ARegion::NotifySpell(Unit *caster, char const *spell, ARegionList *pRegs)

forlist_reuse (&flist) {
FactionPtr *fp = (FactionPtr *) elem;
stringstream tmp;
tmp << caster->name << " uses " << SkillStrs(sp) << " in " << Print(pRegs) << ".";
fp->ptr->event(tmp.str());
string tmp = string(caster->name->const_str()) + " uses " + SkillStrs(sp).const_str() +
" in " + Print(pRegs).const_str() + ".";
fp->ptr->event(tmp, "cast");
}
return 1;
}
Expand All @@ -1693,9 +1692,9 @@ void ARegion::NotifyCity(Unit *caster, AString& oldname, AString& newname)
{
forlist(&flist) {
FactionPtr *fp = (FactionPtr *) elem;
stringstream tmp;
tmp << caster->name << " renames " << oldname << " to " << newname << ".";
fp->ptr->event(tmp.str());
string tmp = string(caster->name->const_str()) + " renames " + oldname.const_str() +
" to " + newname.const_str() + ".";
fp->ptr->event(tmp, "rename");
}
}
}
Expand Down Expand Up @@ -1898,8 +1897,8 @@ int ARegionList::ReadRegions(istream &f, AList *factions)
fa.SetRegion(temp->num, temp);
Add(temp);

pRegionArrays[temp->zloc]->SetRegion(temp->xloc, temp->yloc,
temp);
pRegionArrays[temp->zloc]->SetRegion(temp->xloc, temp->yloc, temp);
temp->level = pRegionArrays[temp->zloc];
}

Awrite("Setting up the neighbors...");
Expand Down
10 changes: 6 additions & 4 deletions aregion.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class ARegion : public AListElem

public:
ARegion();
ARegion(int, int);
//ARegion(int, int);
~ARegion();

void Setup();
Expand All @@ -197,6 +197,7 @@ class ARegion : public AListElem

int CanMakeAdv(Faction *, int);
int HasItem(Faction *, int);
json basic_region_data();
void build_json_report(json& j, Faction *fac, int month, ARegionList *pRegions);

AString ShortPrint(ARegionList *pRegs);
Expand All @@ -221,7 +222,7 @@ class ARegion : public AListElem
Object *GetDummy();
void CheckFleets();

int MoveCost(int, ARegion *, int, AString *road);
int MoveCost(int, ARegion *, int, std::string *road);
Unit *Forbidden(Unit *); /* Returns unit that is forbidding */
Unit *ForbiddenByAlly(Unit *); /* Returns unit that is forbidding */
int CanTax(Unit *);
Expand Down Expand Up @@ -353,6 +354,9 @@ class ARegion : public AListElem
int distance;
ARegion *next;

// A link to the region's level to make some things easier.
ARegionArray *level;

// find a production for a certain skill.
Production *get_production_for_skill(int item, int skill);
// Editing functions
Expand All @@ -375,8 +379,6 @@ class ARegion : public AListElem
std::vector<int> GetPossibleLairs();
void SetupHabitat(TerrainType* terrain);
void SetupEconomy();

json basic_json_data(ARegionList *pRegions);
};

class ARegionArray
Expand Down
3 changes: 2 additions & 1 deletion basic/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ void ARegionList::MakeRegions(int level, int xSize, int ySize)
reg->type = -1;
reg->race = -1;
reg->wages = -1;


reg->level = arr;
Add(reg);
arr->SetRegion(x, y, reg);
}
Expand Down
11 changes: 6 additions & 5 deletions battle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,15 @@ void Battle::NormalRound(int round,Army * a,Army * b)
void Battle::GetSpoils(AList *losers, ItemList *spoils, int ass)
{
ItemList *ships = new ItemList;
AString quest_rewards;
string quest_rewards;

forlist(losers) {
Unit * u = ((Location *) elem)->unit;
int numalive = u->GetSoldiers();
int numdead = u->losses;
if (!numalive) {
if (quests.CheckQuestKillTarget(u, spoils, &quest_rewards)) {
// TODO why doesn't the unit get an event here?
AddLine(AString("Quest completed! ") + quest_rewards);
}
}
Expand Down Expand Up @@ -1093,7 +1094,7 @@ int Game::RunBattle(ARegion * r,Unit * attacker,Unit * target,int ass,

if (ass) {
if (attacker->GetAttitude(r,target) == A_ALLY) {
attacker->Error("ASSASSINATE: Can't assassinate an ally.");
attacker->error("ASSASSINATE: Can't assassinate an ally.");
return BATTLE_IMPOSSIBLE;
}
/* Assassination attempt */
Expand All @@ -1105,11 +1106,11 @@ int Game::RunBattle(ARegion * r,Unit * attacker,Unit * target,int ass,
dfacs.Add(p);
} else {
if ( r->IsSafeRegion() ) {
attacker->Error("ATTACK: No battles allowed in safe regions.");
attacker->error("ATTACK: No battles allowed in safe regions.");
return BATTLE_IMPOSSIBLE;
}
if (attacker->GetAttitude(r,target) == A_ALLY) {
attacker->Error("ATTACK: Can't attack an ally.");
attacker->error("ATTACK: Can't attack an ally.");
if (adv) {
attacker->canattack = 0;
if (attacker->advancefrom) {
Expand All @@ -1120,7 +1121,7 @@ int Game::RunBattle(ARegion * r,Unit * attacker,Unit * target,int ass,
}
GetDFacs(r,target,dfacs);
if (GetFaction2(&dfacs,attacker->faction->num)) {
attacker->Error("ATTACK: Can't attack an ally.");
attacker->error("ATTACK: Can't attack an ally.");
if (adv) {
attacker->canattack = 0;
if (attacker->advancefrom) {
Expand Down
4 changes: 2 additions & 2 deletions edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ void Game::EditGameRegionMarkets( ARegion *pReg )
Awrite("Wanted: ");
for (const auto &m : pReg->markets) {
if (m->type == M_SELL) {
AString temp = ItemString(m->item, m->amount) + " at $" + m->price + "(" + m->baseprice + ").";
AString temp = AString(ItemString(m->item, m->amount)) + " at $" + m->price + "(" + m->baseprice + ").";
temp += AString(" Pop: ") + m->minpop + "/" + m->maxpop + ".";
temp += AString(" Amount: ") + m->minamt + "/" + m->maxamt + ".";
Awrite(temp);
Expand All @@ -757,7 +757,7 @@ void Game::EditGameRegionMarkets( ARegion *pReg )
Awrite("For Sale: ");
for (const auto &m : pReg->markets) {
if (m->type == M_BUY) {
AString temp = ItemString(m->item, m->amount) + " at $" + m->price + "(" + m->baseprice + ").";
AString temp = AString(ItemString(m->item, m->amount)) + " at $" + m->price + "(" + m->baseprice + ").";
temp += AString(" Pop: ") + m->minpop + "/" + m->maxpop + ".";
temp += AString(" Amount: ") + m->minamt + "/" + m->maxamt + ".";
Awrite(temp);
Expand Down
31 changes: 24 additions & 7 deletions faction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,23 @@ const string qs[] = {
};
const string *QuitStrs = qs;

void to_json(json &j, const FactionEvent &e) {
j = json{{"message", e.message}, {"category", e.category}};
if (e.unit != nullptr) {
j["unit"] = e.unit->build_json_descriptor();
}
if (e.region != nullptr) {
j["region"] = e.region->basic_region_data();
}
};

void to_json(json &j, const FactionError &e) {
j = json{{"message", e.message}};
if (e.unit != nullptr) {
j["unit"] = e.unit->build_json_descriptor();
}
};

int ParseTemplate(AString *token)
{
for (int i = 0; i < NTEMPLATES; i++)
Expand Down Expand Up @@ -271,7 +288,7 @@ vector<FactionStatistic> Faction::compute_faction_statistics(Game *game, size_t
total += citems[pl][i];
}

string name = ItemString(i, citems[myfaction][i]).const_str();
string name = ItemString(i, citems[myfaction][i]);
if (ItemDefs[i].type & IT_MONSTER && ItemDefs[i].type == IT_ILLUSION) {
name += " (illusion)";
}
Expand Down Expand Up @@ -550,17 +567,17 @@ void Faction::CheckExist(ARegionList* regs)
}
}

void Faction::error(const string& s) {
void Faction::error(const string& s, Unit* u) {
if (is_npc) return;
auto count = errors.size();
if (count == 1000) errors.push_back("Too many errors!");
if (count < 1000) errors.push_back(s);
if (count == 1000) errors.push_back({.message = "Too many errors!", .unit = u});
if (count < 1000) errors.push_back({.message = s, .unit = u});
}

void Faction::event(const string& s)
void Faction::event(const string& message, const string& category, ARegion* r, Unit *u)
{
if (is_npc) return;
events.push_back(s);
events.push_back({.message = message, .category = category, .unit = u, .region = r});
}

void Faction::remove_attitude(int f) {
Expand Down Expand Up @@ -674,7 +691,7 @@ void Faction::DefaultOrders()
void Faction::TimesReward()
{
if (Globals->TIMES_REWARD) {
event("Times reward of " + to_string(Globals->TIMES_REWARD) + " silver.");
event("Times reward of " + to_string(Globals->TIMES_REWARD) + " silver.", "reward");
unclaimed += Globals->TIMES_REWARD;
}
}
Expand Down
58 changes: 32 additions & 26 deletions faction.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ using json = nlohmann::json;
#include <iostream>
#include <sstream>

using namespace std;

enum
{
A_HOSTILE,
Expand Down Expand Up @@ -119,9 +117,8 @@ class FactionPtr : public AListElem
};

// Collect the faction statistics for display in the report
struct FactionStatistic
{
string item_name;
struct FactionStatistic {
std::string item_name;
size_t rank;
size_t max;
size_t total;
Expand All @@ -130,16 +127,25 @@ struct FactionStatistic
// objects/structs that require no additional parameters to be passed in. On the other hand, for simple
// structures this is nice, and works with things like STL containers of structs to make the entire container
// serializable to json.
friend void to_json(json &j, const FactionStatistic &s)
{
friend void to_json(json &j, const FactionStatistic &s) {
j = json{{"item_name", s.item_name}, {"rank", s.rank}, {"max", s.max}, {"total", s.total}};
};
};

friend ostream &operator<<(ostream &os, const FactionStatistic &s)
{
os << left << setw(42) << s.item_name << setw(6) << s.rank << setw(11) << s.max << s.total << right;
return os;
};
struct FactionError {
std::string message;
Unit *unit;

friend void to_json(json &j, const FactionError &e);
};

struct FactionEvent {
std::string message;
std::string category;
Unit *unit;
ARegion *region;

friend void to_json(json &j, const FactionEvent &e);
};

class Faction : public AListElem
Expand All @@ -149,21 +155,21 @@ class Faction : public AListElem
Faction(int);
~Faction();

void Readin(istream &f);
void Writeout(ostream &f);
void Readin(std::istream &f);
void Writeout(std::ostream &f);
void View();

void SetName(AString *);
void SetNameNoChange(AString *str);
void SetAddress(AString &strNewAddress);

void CheckExist(ARegionList *);
void error(const string &s);
void event(const string &s);
void error(const std::string& s, Unit *u = nullptr);
void event(const std::string& message, const std::string& category, ARegion *r = nullptr, Unit *u = nullptr);

void build_json_report(json& j, Game *pGame, size_t **citems);

void WriteFacInfo(ostream &f);
void WriteFacInfo(std::ostream &f);

void set_attitude(int faction_id, int attitude); // attitude -1 clears it
int get_attitude(int faction_id);
Expand Down Expand Up @@ -219,28 +225,28 @@ class Faction : public AListElem
bool gets_gm_report(Game *game);

/* Used when writing reports */
vector<ARegion *> present_regions;
std::vector<ARegion *> present_regions;

int defaultattitude;
// TODO: Convert this to a hashmap of <attitude, vector<factionid>>
// For now, just making it a vector of attitudes. More will come later.
vector<Attitude> attitudes;
std::vector<Attitude> attitudes;

// These need to not be ALists wrapped with extra behavior at some point.
SkillList skills;
ItemList items;

// Extra lines/data from the players.in file for this faction. Stored and dumped, not used.
vector<string> extra_player_data;
std::vector<std::string> extra_player_data;

// Errors and events during turn processing
vector<string> errors;
vector<string> events;
std::vector<FactionError> errors;
std::vector<FactionEvent> events;

vector<Battle *> battles;
vector<ShowSkill> shows;
vector<string> itemshows;
vector<string> objectshows;
std::vector<Battle *> battles;
std::vector<ShowSkill> shows;
std::vector<std::string> itemshows;
std::vector<std::string> objectshows;

// These are used for 'granting' units to a faction via the players.in
// file
Expand Down
Loading

0 comments on commit cc78421

Please sign in to comment.