eliminate using namespace

This commit is contained in:
Martin Michelsen
2026-05-25 16:38:31 -07:00
parent 4503d09c77
commit e9c2ac34a3
98 changed files with 6022 additions and 6531 deletions
+13 -15
View File
@@ -2,22 +2,20 @@
#include "Server.hh"
using namespace std;
namespace Episode3 {
const vector<uint16_t>& all_assist_card_ids(bool is_nte) {
const std::vector<uint16_t>& all_assist_card_ids(bool is_nte) {
// Note: This order matches the order that the cards are defined in the original
// code. This is relevant for consistency of results when choosing a random card
// (for God Whim).
static const vector<uint16_t> ALL_ASSIST_CARD_IDS_TRIAL = {
static const std::vector<uint16_t> ALL_ASSIST_CARD_IDS_TRIAL = {
0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102,
0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, 0x0121,
0x0125, 0x0126, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, 0x0130, 0x0131, 0x0132,
0x0133, 0x0134, 0x0135, 0x0136, 0x0137, 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x013F, 0x0140,
0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0148, 0x014A, 0x014B, 0x014C, 0x014D, 0x014E, 0x023F, 0x0240,
0x0241, 0x0242};
static const vector<uint16_t> ALL_ASSIST_CARD_IDS_FINAL = {
static const std::vector<uint16_t> ALL_ASSIST_CARD_IDS_FINAL = {
0x0018, 0x0019, 0x001A, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D,
0x010E, 0x010F, 0x0121, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
@@ -28,12 +26,12 @@ const vector<uint16_t>& all_assist_card_ids(bool is_nte) {
}
AssistEffect assist_effect_number_for_card_id(uint16_t card_id, bool is_nte) {
static const unordered_map<uint16_t, AssistEffect> card_id_to_effect_final_only({
static const std::unordered_map<uint16_t, AssistEffect> card_id_to_effect_final_only({
{0x0018, /* 0x0049 */ AssistEffect::DICE_FEVER_PLUS},
{0x0019, /* 0x004A */ AssistEffect::RICH_PLUS},
{0x001A, /* 0x004B */ AssistEffect::CHARITY_PLUS},
});
static const unordered_map<uint16_t, AssistEffect> card_id_to_effect({
static const std::unordered_map<uint16_t, AssistEffect> card_id_to_effect({
{0x00F5, /* 0x0001 */ AssistEffect::DICE_HALF},
{0x00F6, /* 0x0002 */ AssistEffect::DICE_PLUS_1},
{0x00F7, /* 0x0003 */ AssistEffect::DICE_FEVER},
@@ -109,18 +107,18 @@ AssistEffect assist_effect_number_for_card_id(uint16_t card_id, bool is_nte) {
});
try {
return card_id_to_effect.at(card_id);
} catch (const out_of_range&) {
} catch (const std::out_of_range&) {
}
if (!is_nte) {
try {
return card_id_to_effect_final_only.at(card_id);
} catch (const out_of_range&) {
} catch (const std::out_of_range&) {
}
}
return AssistEffect::NONE;
}
AssistServer::AssistServer(shared_ptr<Server> server)
AssistServer::AssistServer(std::shared_ptr<Server> server)
: w_server(server),
assist_effects(AssistEffect::NONE),
num_assist_cards_set(0),
@@ -128,18 +126,18 @@ AssistServer::AssistServer(shared_ptr<Server> server)
active_assist_effects(AssistEffect::NONE),
num_active_assists(0) {}
shared_ptr<Server> AssistServer::server() {
std::shared_ptr<Server> AssistServer::server() {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
shared_ptr<const Server> AssistServer::server() const {
std::shared_ptr<const Server> AssistServer::server() const {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
@@ -148,7 +146,7 @@ uint16_t AssistServer::card_id_for_card_ref(uint16_t card_ref) const {
return this->server()->card_id_for_card_ref(card_ref);
}
shared_ptr<const CardIndex::CardEntry> AssistServer::definition_for_card_id(
std::shared_ptr<const CardIndex::CardEntry> AssistServer::definition_for_card_id(
uint16_t card_id) const {
return this->server()->definition_for_card_id(card_id);
}
+31 -39
View File
@@ -5,8 +5,6 @@
#include "../CommandFormats.hh"
#include "../SendCommands.hh"
using namespace std;
namespace Episode3 {
void BattleRecord::PlayerEntry::print(FILE* stream) const {
@@ -41,7 +39,7 @@ BattleRecord::Event::Event(phosg::StringReader& r) {
this->data = r.read(r.get_u16l());
break;
default:
throw logic_error("unknown event type");
throw std::logic_error("unknown event type");
}
}
@@ -51,7 +49,7 @@ void BattleRecord::Event::serialize(phosg::StringWriter& w) const {
switch (this->type) {
case Event::Type::PLAYER_JOIN:
if (this->players.size() != 1) {
throw logic_error("player join event does not contain 1 player entry");
throw std::logic_error("player join event does not contain 1 player entry");
}
w.put(this->players[0]);
break;
@@ -75,13 +73,12 @@ void BattleRecord::Event::serialize(phosg::StringWriter& w) const {
w.write(this->data);
break;
default:
throw logic_error("unknown event type");
throw std::logic_error("unknown event type");
}
}
void BattleRecord::Event::print(FILE* stream) const {
string time_str = phosg::format_time(this->timestamp);
phosg::fwrite_fmt(stream, "Event @{:016X} ({}) ", this->timestamp, time_str);
phosg::fwrite_fmt(stream, "Event @{:016X} ({}) ", this->timestamp, phosg::format_time(this->timestamp));
switch (this->type) {
case Type::PLAYER_JOIN:
phosg::fwrite_fmt(stream, "PLAYER_JOIN {:02X}\n", this->players[0].lobby_data.client_id);
@@ -121,7 +118,7 @@ void BattleRecord::Event::print(FILE* stream) const {
phosg::print_data(stream, this->data, 0, phosg::FormatDataFlags::PRINT_ASCII | phosg::FormatDataFlags::OFFSET_16_BITS);
break;
default:
throw runtime_error("unknown event type in battle record");
throw std::runtime_error("unknown event type in battle record");
}
}
@@ -131,11 +128,8 @@ BattleRecord::BattleRecord(uint32_t behavior_flags)
battle_start_timestamp(0),
battle_end_timestamp(0) {}
BattleRecord::BattleRecord(const string& data)
: is_writable(false),
behavior_flags(0),
battle_start_timestamp(0),
battle_end_timestamp(0) {
BattleRecord::BattleRecord(const std::string& data)
: is_writable(false), behavior_flags(0), battle_start_timestamp(0), battle_end_timestamp(0) {
phosg::StringReader r(data);
uint64_t signature = r.get_u64l();
@@ -145,7 +139,7 @@ BattleRecord::BattleRecord(const string& data)
} else if (signature == this->SIGNATURE_V2) {
has_random_stream = true;
} else {
throw runtime_error("incorrect battle record signature");
throw std::runtime_error("incorrect battle record signature");
}
this->battle_start_timestamp = r.get_u64l();
@@ -159,7 +153,7 @@ BattleRecord::BattleRecord(const string& data)
}
}
string BattleRecord::serialize() const {
std::string BattleRecord::serialize() const {
phosg::StringWriter w;
w.put_u64l(this->SIGNATURE_V2);
w.put_u64l(this->battle_start_timestamp);
@@ -179,10 +173,10 @@ void BattleRecord::add_player(
const PlayerDispDataDCPCV3& disp,
uint32_t level) {
if (!this->is_writable) {
throw logic_error("cannot write to battle record");
throw std::logic_error("cannot write to battle record");
}
if (this->battle_start_timestamp != 0) {
throw runtime_error("cannot add player during battle");
throw std::runtime_error("cannot add player during battle");
}
Event& ev = this->events.emplace_back();
ev.type = Event::Type::PLAYER_JOIN;
@@ -196,7 +190,7 @@ void BattleRecord::add_player(
void BattleRecord::delete_player(uint8_t client_id) {
if (!this->is_writable) {
throw logic_error("cannot write to battle record");
throw std::logic_error("cannot write to battle record");
}
Event& ev = this->events.emplace_back();
ev.type = Event::Type::PLAYER_LEAVE;
@@ -206,7 +200,7 @@ void BattleRecord::delete_player(uint8_t client_id) {
void BattleRecord::add_command(Event::Type type, const void* data, size_t size) {
if (!this->is_writable) {
throw logic_error("cannot write to battle record");
throw std::logic_error("cannot write to battle record");
}
Event& ev = this->events.emplace_back();
ev.type = type;
@@ -214,9 +208,9 @@ void BattleRecord::add_command(Event::Type type, const void* data, size_t size)
ev.data.assign(reinterpret_cast<const char*>(data), size);
}
void BattleRecord::add_command(Event::Type type, string&& data) {
void BattleRecord::add_command(Event::Type type, std::string&& data) {
if (!this->is_writable) {
throw logic_error("cannot write to battle record");
throw std::logic_error("cannot write to battle record");
}
Event& ev = this->events.emplace_back();
ev.type = type;
@@ -224,10 +218,9 @@ void BattleRecord::add_command(Event::Type type, string&& data) {
ev.data = std::move(data);
}
void BattleRecord::add_chat_message(
uint32_t guild_card_number, string&& data) {
void BattleRecord::add_chat_message(uint32_t guild_card_number, std::string&& data) {
if (!this->is_writable) {
throw logic_error("cannot write to battle record");
throw std::logic_error("cannot write to battle record");
}
Event& ev = this->events.emplace_back();
ev.type = Event::Type::CHAT_MESSAGE;
@@ -240,7 +233,7 @@ void BattleRecord::add_random_data(const void* data, size_t size) {
this->random_stream.append(reinterpret_cast<const char*>(data), size);
}
const string& BattleRecord::get_random_stream() const {
const std::string& BattleRecord::get_random_stream() const {
return this->random_stream;
}
@@ -259,7 +252,7 @@ bool BattleRecord::is_map_definition_event(const Event& ev) {
void BattleRecord::set_battle_start_timestamp() {
if (this->battle_start_timestamp != 0) {
throw logic_error("battle start timestamp is already set");
throw std::logic_error("battle start timestamp is already set");
}
this->battle_start_timestamp = phosg::now();
@@ -271,30 +264,30 @@ void BattleRecord::set_battle_start_timestamp() {
for (auto& ev : this->events) {
if (ev.type == Event::Type::PLAYER_JOIN) {
if (ev.players.size() != 1) {
throw logic_error("player join event does not contain 1 player entry");
throw std::logic_error("player join event does not contain 1 player entry");
}
auto& player = ev.players[0];
if (player.lobby_data.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
players[player.lobby_data.client_id] = player;
players_present[player.lobby_data.client_id] = true;
} else if (ev.type == Event::Type::PLAYER_LEAVE) {
if (ev.leaving_client_id >= 4) {
throw logic_error("invalid client ID");
throw std::logic_error("invalid client ID");
}
players_present[ev.leaving_client_id] = false;
} else if (ev.type == Event::Type::SET_INITIAL_PLAYERS) {
throw logic_error("BattleRecord::set_battle_start_timestamp called twice");
throw std::logic_error("BattleRecord::set_battle_start_timestamp called twice");
} else if (this->is_map_definition_event(ev)) {
num_map_events++;
}
}
deque<Event> new_events;
std::deque<Event> new_events;
// Generate the initial players event
Event initial_ev;
@@ -335,32 +328,31 @@ void BattleRecord::set_battle_end_timestamp() {
}
void BattleRecord::print(FILE* stream) const {
string start_str = phosg::format_time(this->battle_start_timestamp);
string end_str = phosg::format_time(this->battle_end_timestamp);
phosg::fwrite_fmt(stream, "BattleRecord {} behavior_flags={:08X} start={:016X} ({}) end={:016X} ({}); {} events\n",
this->is_writable ? "writable" : "read-only",
this->behavior_flags,
this->battle_start_timestamp,
start_str,
phosg::format_time(this->battle_start_timestamp),
this->battle_end_timestamp,
end_str, this->events.size());
phosg::format_time(this->battle_end_timestamp),
this->events.size());
for (const auto& event : this->events) {
event.print(stream);
}
}
BattleRecordPlayer::BattleRecordPlayer(std::shared_ptr<asio::io_context> io_context, shared_ptr<const BattleRecord> rec)
BattleRecordPlayer::BattleRecordPlayer(std::shared_ptr<asio::io_context> io_context, std::shared_ptr<const BattleRecord> rec)
: io_context(io_context),
record(rec),
event_it(this->record->events.begin()),
play_start_timestamp(0),
next_command_timer(*this->io_context) {}
shared_ptr<const BattleRecord> BattleRecordPlayer::get_record() const {
std::shared_ptr<const BattleRecord> BattleRecordPlayer::get_record() const {
return this->record;
}
void BattleRecordPlayer::set_lobby(shared_ptr<Lobby> l) {
void BattleRecordPlayer::set_lobby(std::shared_ptr<Lobby> l) {
this->lobby = l;
}
@@ -406,7 +398,7 @@ asio::awaitable<void> BattleRecordPlayer::play_task() {
switch (ev.type) {
case BattleRecord::Event::Type::PLAYER_JOIN:
// Technically we can support this, but it should never happen
throw runtime_error("player join event during battle replay");
throw std::runtime_error("player join event during battle replay");
case BattleRecord::Event::Type::PLAYER_LEAVE:
send_player_leave_notification(l, ev.leaving_client_id);
break;
+52 -59
View File
@@ -3,11 +3,9 @@
#include "../CommandFormats.hh"
#include "Server.hh"
using namespace std;
namespace Episode3 {
Card::Card(uint16_t card_id, uint16_t card_ref, uint16_t client_id, shared_ptr<Server> server)
Card::Card(uint16_t card_id, uint16_t card_ref, uint16_t client_id, std::shared_ptr<Server> server)
: w_server(server),
w_player_state(server->get_player_state(client_id)),
client_id(client_id),
@@ -39,7 +37,7 @@ void Card::init() {
// Arkz-side. This could break things later on in the battle, and even if it
// doesn't, it certainly isn't behavior that the player would expect, so we
// prevent it instead.
throw runtime_error("card definition is missing");
throw std::runtime_error("card definition is missing");
}
this->sc_card_ref = ps->get_sc_card_ref();
this->sc_def_entry = s->definition_for_card_id(ps->get_sc_card_id());
@@ -56,7 +54,7 @@ void Card::init() {
} else {
int16_t rules_char_hp = s->map_and_rules->rules.char_hp;
int16_t base_char_hp = (rules_char_hp == 0) ? 15 : rules_char_hp;
int16_t hp = clamp<int16_t>(base_char_hp + this->def_entry->def.hp.stat, 1, 99);
int16_t hp = std::clamp<int16_t>(base_char_hp + this->def_entry->def.hp.stat, 1, 99);
this->max_hp = hp;
this->current_hp = hp;
}
@@ -78,34 +76,34 @@ void Card::init() {
}
}
shared_ptr<Server> Card::server() {
std::shared_ptr<Server> Card::server() {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
shared_ptr<const Server> Card::server() const {
std::shared_ptr<const Server> Card::server() const {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
shared_ptr<PlayerState> Card::player_state() {
std::shared_ptr<PlayerState> Card::player_state() {
auto s = this->w_player_state.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
shared_ptr<const PlayerState> Card::player_state() const {
std::shared_ptr<const PlayerState> Card::player_state() const {
auto s = this->w_player_state.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
@@ -158,7 +156,7 @@ ssize_t Card::apply_abnormal_condition(
int16_t existing_cond_value = 0;
auto& cond = this->action_chain.conditions[cond_index];
if ((eff.type == ConditionType::MV_BONUS) && (cond.type == ConditionType::MV_BONUS)) {
existing_cond_value = clamp<int16_t>(cond.value, -99, 99);
existing_cond_value = std::clamp<int16_t>(cond.value, -99, 99);
log.debug_f("MV_BONUS combines => existing_cond_value = {}", existing_cond_value);
}
@@ -176,7 +174,7 @@ ssize_t Card::apply_abnormal_condition(
switch (eff.arg1.at(0)) {
case 'a': {
string s = eff.arg1.decode();
std::string s = eff.arg1.decode();
cond.a_arg_value = atoi(s.c_str() + 1);
break;
}
@@ -190,13 +188,12 @@ ssize_t Card::apply_abnormal_condition(
cond.remaining_turns = 102;
break;
case 't': {
string s = eff.arg1.decode();
std::string s = eff.arg1.decode();
cond.remaining_turns = atoi(s.c_str() + 1);
}
}
string cond_str = cond.str(s);
log.debug_f("wrote condition {} => {}", cond_index, cond_str);
log.debug_f("wrote condition {} => {}", cond_index, cond.str(s));
if (!is_nte) {
s->card_special->update_condition_orders(this->shared_from_this());
@@ -204,8 +201,7 @@ ssize_t Card::apply_abnormal_condition(
if (this->action_chain.conditions[z].type == ConditionType::NONE) {
continue;
}
string cond_str = cond.str(s);
log.debug_f("sorted conditions: [{}] => {}", z, cond_str);
log.debug_f("sorted conditions: [{}] => {}", z, cond.str(s));
}
}
@@ -213,7 +209,7 @@ ssize_t Card::apply_abnormal_condition(
}
void Card::apply_ap_and_tp_adjust_assists_to_attack(
shared_ptr<const Card> attacker_card,
std::shared_ptr<const Card> attacker_card,
int16_t* inout_attacker_ap,
int16_t* in_defense_power,
int16_t* inout_attacker_tp) const {
@@ -226,12 +222,12 @@ void Card::apply_ap_and_tp_adjust_assists_to_attack(
switch (s->assist_server->get_active_assist_by_index(z)) {
case AssistEffect::POWERLESS_RAIN:
if (is_nte) {
*inout_attacker_ap = max<int16_t>(*inout_attacker_ap - 2, 0);
*inout_attacker_ap = std::max<int16_t>(*inout_attacker_ap - 2, 0);
}
break;
case AssistEffect::BRAVE_WIND:
if (is_nte) {
*inout_attacker_ap = max<int16_t>(*inout_attacker_ap + 2, 0);
*inout_attacker_ap = std::max<int16_t>(*inout_attacker_ap + 2, 0);
}
break;
case AssistEffect::SILENT_COLOSSEUM:
@@ -284,7 +280,7 @@ bool Card::check_card_flag(uint32_t flags) const {
void Card::commit_attack(
int16_t damage,
shared_ptr<Card> attacker_card,
std::shared_ptr<Card> attacker_card,
G_ApplyConditionEffect_Ep3_6xB4x06* cmd,
size_t strike_number,
int16_t* out_effective_damage) {
@@ -302,7 +298,7 @@ void Card::commit_attack(
auto eff = s->assist_server->get_active_assist_by_index(z);
if ((eff == AssistEffect::RANSOM) && (attacker_card->action_chain.chain.attack_medium == AttackMedium::PHYSICAL)) {
uint8_t team_id = this->player_state()->get_team_id();
int16_t exp_amount = clamp<int16_t>(s->team_exp[team_id], 0, effective_damage);
int16_t exp_amount = std::clamp<int16_t>(s->team_exp[team_id], 0, effective_damage);
s->team_exp[team_id] -= exp_amount;
effective_damage -= exp_amount;
if (!is_nte) {
@@ -326,7 +322,7 @@ void Card::commit_attack(
this->player_state()->stats.damage_taken += effective_damage;
log.debug_f("updated stats");
this->current_hp = clamp<int16_t>(this->current_hp - effective_damage, 0, this->max_hp);
this->current_hp = std::clamp<int16_t>(this->current_hp - effective_damage, 0, this->max_hp);
log.debug_f("hp set to {}", this->current_hp);
if ((effective_damage > 0) && (attacker_ps->stats.max_attack_damage < effective_damage)) {
@@ -366,7 +362,7 @@ void Card::commit_attack(
}
}
int16_t Card::compute_defense_power_for_attacker_card(shared_ptr<const Card> attacker_card) {
int16_t Card::compute_defense_power_for_attacker_card(std::shared_ptr<const Card> attacker_card) {
if (!attacker_card) {
return 0;
}
@@ -392,7 +388,7 @@ int16_t Card::compute_defense_power_for_attacker_card(shared_ptr<const Card> att
return this->action_metadata.defense_power + this->action_metadata.defense_bonus;
}
void Card::destroy_set_card(shared_ptr<Card> attacker_card) {
void Card::destroy_set_card(std::shared_ptr<Card> attacker_card) {
auto s = this->server();
auto ps = this->player_state();
@@ -490,7 +486,7 @@ int32_t Card::error_code_for_move_to_location(const Location& loc) const {
return 0;
}
void Card::execute_attack(shared_ptr<Card> attacker_card) {
void Card::execute_attack(std::shared_ptr<Card> attacker_card) {
if (!attacker_card) {
return;
}
@@ -518,7 +514,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
if (attacker_card->action_chain.chain.attack_medium == AttackMedium::UNKNOWN_03) {
// Probably Resta
for (size_t strike_num = 0; strike_num < attacker_card->action_chain.chain.strike_count; strike_num++) {
this->current_hp = min<int16_t>(this->current_hp + attacker_card->action_chain.chain.effective_tp, this->max_hp);
this->current_hp = std::min<int16_t>(this->current_hp + attacker_card->action_chain.chain.effective_tp, this->max_hp);
}
this->propagate_shared_hp_if_needed();
cmd.effect.tp = attacker_card->action_chain.chain.effective_tp;
@@ -545,7 +541,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
log.debug_f("assist adjusts ap={}, defense={}", attack_ap, defense_power);
int16_t raw_damage = attack_ap - defense_power;
int16_t preliminary_damage = max<int16_t>(raw_damage, 0) - attack_tp;
int16_t preliminary_damage = std::max<int16_t>(raw_damage, 0) - attack_tp;
this->last_attack_preliminary_damage = preliminary_damage;
log.debug_f("raw_damage={}, preliminary_damange={}", raw_damage, preliminary_damage);
@@ -571,8 +567,8 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
}
}
cmd.effect.current_hp = is_nte ? attack_ap : min<int16_t>(attack_ap, 99);
cmd.effect.ap = is_nte ? defense_power : min<int16_t>(defense_power, 99);
cmd.effect.current_hp = is_nte ? attack_ap : std::min<int16_t>(attack_ap, 99);
cmd.effect.ap = is_nte ? defense_power : std::min<int16_t>(defense_power, 99);
cmd.effect.tp = attack_tp;
auto ps = this->player_state();
@@ -583,7 +579,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
for (size_t strike_num = 0; strike_num < attacker_card->action_chain.chain.strike_count; strike_num++) {
int16_t final_effective_damage = 0;
target->commit_attack(preliminary_damage, attacker_card, &cmd, strike_num, &final_effective_damage);
ps->stats.action_card_negated_damage += max<int16_t>(0, this->current_defense_power - final_effective_damage);
ps->stats.action_card_negated_damage += std::max<int16_t>(0, this->current_defense_power - final_effective_damage);
}
} else {
log.debug_f("flag 2 set; committing zero-damage attack");
@@ -618,7 +614,7 @@ const Condition* Card::find_condition(ConditionType cond_type) const {
return const_cast<Card*>(this)->find_condition(cond_type);
}
shared_ptr<const CardIndex::CardEntry> Card::get_definition() const {
std::shared_ptr<const CardIndex::CardEntry> Card::get_definition() const {
return this->def_entry;
}
@@ -839,10 +835,10 @@ void Card::set_current_and_max_hp(int16_t hp) {
void Card::set_current_hp(
uint32_t new_hp, bool propagate_shared_hp, bool enforce_max_hp) {
if (!enforce_max_hp) {
new_hp = max<int16_t>(new_hp, 0);
this->max_hp = max<int16_t>(this->max_hp, new_hp);
new_hp = std::max<int16_t>(new_hp, 0);
this->max_hp = std::max<int16_t>(this->max_hp, new_hp);
} else {
new_hp = clamp<int16_t>(new_hp, 0, this->max_hp);
new_hp = std::clamp<int16_t>(new_hp, 0, this->max_hp);
}
this->current_hp = new_hp;
@@ -955,11 +951,11 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
}
if (!this->action_chain.check_flag(0x10)) {
this->action_chain.chain.effective_ap = is_nte ? effective_ap : min<int16_t>(effective_ap, 99);
this->action_chain.chain.effective_ap = is_nte ? effective_ap : std::min<int16_t>(effective_ap, 99);
log.debug_f("set chain effective_ap = {}", this->action_chain.chain.effective_ap);
}
if (!this->action_chain.check_flag(0x20)) {
this->action_chain.chain.effective_tp = is_nte ? effective_tp : min<int16_t>(effective_tp, 99);
this->action_chain.chain.effective_tp = is_nte ? effective_tp : std::min<int16_t>(effective_tp, 99);
log.debug_f("set chain effective_tp = {}", this->action_chain.chain.effective_tp);
}
@@ -1099,7 +1095,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
this->action_chain.chain.damage = is_nte
? (damage * this->action_chain.chain.damage_multiplier)
: min<int16_t>(damage * this->action_chain.chain.damage_multiplier, 99);
: std::min<int16_t>(damage * this->action_chain.chain.damage_multiplier, 99);
log.debug_f("overall chain damage = {} (base) * {} (mult) = {}",
damage, this->action_chain.chain.damage_multiplier, this->action_chain.chain.damage);
@@ -1108,7 +1104,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, this_sh, this_sh, 2, nullptr);
log.debug_f("applied action conditions (2)");
if (!is_nte && this->action_chain.check_flag(0x100)) {
this->action_chain.chain.damage = min<int16_t>(this->action_chain.chain.damage + 5, 99);
this->action_chain.chain.damage = std::min<int16_t>(this->action_chain.chain.damage + 5, 99);
log.debug_f("(has flag 0x100) chain damage = {}", this->action_chain.chain.damage);
}
} else {
@@ -1141,8 +1137,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
}
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string chain_str = this->action_chain.str(s);
log.debug_f("result computed as {}", chain_str);
log.debug_f("result computed as {}", this->action_chain.str(s));
}
}
@@ -1208,20 +1203,19 @@ void Card::move_phase_before() {
this->server()->card_special->move_phase_before_for_card(this->shared_from_this());
}
void Card::unknown_80236374(shared_ptr<Card> other_card, const ActionState* as) {
void Card::unknown_80236374(std::shared_ptr<Card> other_card, const ActionState* as) {
auto s = this->server();
auto log = s->log_stack(std::format("unknown_80236374(@{:04X} #{:04X}, @{:04X} #{:04X}): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id()));
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
if (as) {
string as_str = as->str(s);
log.debug_f("as = {}", as_str);
log.debug_f("as = {}", as->str(s));
} else {
log.debug_f("as = null");
}
}
auto check_card = [&](shared_ptr<Card> card) -> void {
auto check_card = [&](std::shared_ptr<Card> card) -> void {
if (card) {
if (!card->unknown_80236554(other_card, as)) {
log.debug_f("check_card @{:04X} #{:04X} => false", card->get_card_ref(), card->get_card_id());
@@ -1263,7 +1257,7 @@ void Card::unknown_802379DC(const ActionState& pa) {
pa.defense_card_ref, this->shared_from_this(), pa.original_attacker_card_ref);
this->server()->card_special->unknown_8024A9D8(pa, 0xFFFF);
for (size_t z = 0; z < this->action_metadata.target_card_ref_count; z++) {
shared_ptr<Card> card = this->server()->card_for_set_card_ref(this->action_metadata.target_card_refs[z]);
std::shared_ptr<Card> card = this->server()->card_for_set_card_ref(this->action_metadata.target_card_refs[z]);
if (card) {
card->action_chain.set_action_subphase_from_card(this->shared_from_this());
card->send_6xB4x4E_4C_4D_if_needed();
@@ -1302,7 +1296,7 @@ void Card::unknown_80237A90(const ActionState& pa, uint16_t action_card_ref) {
if (this->action_chain.chain.target_card_ref_count == 0) {
for (size_t z = 0; (z < 4 * 9) && (pa.target_card_refs[z] != 0xFFFF); z++) {
this->action_chain.add_target_card_ref(pa.target_card_refs[z]);
shared_ptr<Card> sc_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
std::shared_ptr<Card> sc_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
if (sc_card) {
sc_card->action_metadata.add_target_card_ref(this->card_ref);
sc_card->card_flags |= 8;
@@ -1357,7 +1351,7 @@ bool Card::is_guard_item() const {
return (this->def_entry->def.card_class() == CardClass::GUARD_ITEM);
}
bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as) {
bool Card::unknown_80236554(std::shared_ptr<Card> other_card, const ActionState* as) {
auto s = this->server();
auto log = s->log_stack(other_card
? std::format("unknown_80236554(@{:04X} #{:04X}, @{:04X} #{:04X}): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id())
@@ -1395,7 +1389,7 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
}
}
this->action_metadata.attack_bonus = max<int16_t>(attack_bonus, 0);
this->action_metadata.attack_bonus = std::max<int16_t>(attack_bonus, 0);
log.debug_f("attack_bonus = {}", this->action_metadata.attack_bonus);
this->last_attack_preliminary_damage = 0;
this->last_attack_final_damage = 0;
@@ -1421,17 +1415,17 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
return ret;
}
void Card::execute_attack_on_all_valid_targets(shared_ptr<Card> attacker_card) {
void Card::execute_attack_on_all_valid_targets(std::shared_ptr<Card> attacker_card) {
auto s = this->server();
for (size_t client_id = 0; client_id < 4; client_id++) {
auto ps = s->player_states[client_id];
if (ps) {
shared_ptr<Card> card = ps->get_sc_card();
std::shared_ptr<Card> card = ps->get_sc_card();
if (card) {
card->execute_attack(attacker_card);
}
for (size_t set_index = 0; set_index < 8; set_index++) {
shared_ptr<Card> card = ps->get_set_card(set_index);
std::shared_ptr<Card> card = ps->get_set_card(set_index);
if (card) {
card->execute_attack(attacker_card);
}
@@ -1476,7 +1470,7 @@ void Card::apply_attack_result() {
temp_chain.chain.target_card_ref_count++;
} else if ((target_card->get_definition()->def.type == CardType::ITEM) && !this->action_chain.check_flag(0x02)) {
auto target_ps = target_card->player_state();
shared_ptr<Card> candidate_card;
std::shared_ptr<Card> candidate_card;
for (size_t set_index = 0; set_index < 8; set_index++) {
auto set_card = target_ps->get_set_card(set_index);
if (set_card && (set_card != target_card) && !(set_card->card_flags & 2) && set_card->is_guard_item()) {
@@ -1555,12 +1549,11 @@ void Card::apply_attack_result() {
}
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string as_str = as.str(s);
log.debug_f("as constructed as {}", as_str);
log.debug_f("as constructed as {}", as.str(s));
}
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
shared_ptr<Card> card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
std::shared_ptr<Card> card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
if (card) {
card->current_defense_power = card->action_metadata.attack_bonus;
if (!this->action_chain.check_flag(0x40)) {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6 -8
View File
@@ -2,8 +2,6 @@
#include "Server.hh"
using namespace std;
namespace Episode3 {
NameEntry::NameEntry() {
@@ -198,7 +196,7 @@ void DeckState::redraw_initial_hand(bool is_nte) {
auto s = this->server.lock();
if (!s) {
throw runtime_error("server is missing");
throw std::runtime_error("server is missing");
}
// Shuffle the deck, except the first 5 cards (which are about to be drawn).
@@ -260,7 +258,7 @@ void DeckState::shuffle() {
if (this->shuffle_enabled) {
auto s = this->server.lock();
if (!s) {
throw runtime_error("server is missing");
throw std::runtime_error("server is missing");
}
size_t max = this->num_drawable_cards();
@@ -305,17 +303,17 @@ void DeckState::print(FILE* stream, std::shared_ptr<const CardIndex> card_index)
this->loop_enabled ? "true" : "false");
for (size_t z = 0; z < 31; z++) {
const auto& e = this->entries[z];
shared_ptr<const CardIndex::CardEntry> ce;
std::shared_ptr<const CardIndex::CardEntry> ce;
if (card_index) {
try {
ce = card_index->definition_for_id(e.card_id);
} catch (const out_of_range&) {
} catch (const std::out_of_range&) {
}
}
if (ce) {
string name = ce->def.en_name.decode(Language::ENGLISH);
phosg::fwrite_fmt(stream, " ({:02}) index={:02X} ref=@{:04X} card_id=#{:04X} \"{}\" {}\n",
z, e.deck_index, this->card_refs[z], e.card_id, name, name_for_card_state(e.state));
z, e.deck_index, this->card_refs[z], e.card_id, ce->def.en_name.decode(Language::ENGLISH),
name_for_card_state(e.state));
} else {
phosg::fwrite_fmt(stream, " ({:02}) index={:02X} ref=@{:04X} card_id=#{:04X} {}\n",
z, e.deck_index, this->card_refs[z], e.card_id, name_for_card_state(e.state));
-2
View File
@@ -1,7 +1,5 @@
#include "MapState.hh"
using namespace std;
namespace Episode3 {
MapState::MapState() {
+47 -53
View File
@@ -2,11 +2,9 @@
#include "Server.hh"
using namespace std;
namespace Episode3 {
PlayerState::PlayerState(uint8_t client_id, shared_ptr<Server> server)
PlayerState::PlayerState(uint8_t client_id, std::shared_ptr<Server> server)
: w_server(server),
client_id(client_id),
num_hand_redraws_allowed(1),
@@ -46,10 +44,10 @@ void PlayerState::init() {
if (s->player_states.at(this->client_id).get() != this) {
// Note: The original code handles this, but we don't. This appears not to
// ever happen, so we didn't bother implementing it.
throw logic_error("replacing a player state object is not permitted");
throw std::logic_error("replacing a player state object is not permitted");
}
this->deck_state = make_shared<DeckState>(this->client_id, s->deck_entries[client_id]->card_ids, s);
this->deck_state = std::make_shared<DeckState>(this->client_id, s->deck_entries[client_id]->card_ids, s);
if (s->map_and_rules->rules.disable_deck_shuffle) {
this->deck_state->disable_shuffle();
}
@@ -62,7 +60,7 @@ void PlayerState::init() {
this->team_id = s->deck_entries[this->client_id]->team_id;
auto sc_ce = s->definition_for_card_ref(this->sc_card_ref);
if (!sc_ce) {
throw runtime_error("SC card definition is missing");
throw std::runtime_error("SC card definition is missing");
}
if (sc_ce->def.type == CardType::HUNTERS_SC) {
this->sc_card_type = CardType::HUNTERS_SC;
@@ -72,13 +70,13 @@ void PlayerState::init() {
// In the original code, sc_card_type gets left as 0xFFFFFFFF (yes, it's a
// uint32_t). This probably breaks some things later on, so we instead
// prevent it upfront.
throw runtime_error("SC card is not a Hunters or Arkz SC");
throw std::runtime_error("SC card is not a Hunters or Arkz SC");
}
this->hand_and_equip = make_shared<HandAndEquipState>();
this->card_short_statuses = make_shared<parray<CardShortStatus, 0x10>>();
this->set_card_action_chains = make_shared<parray<ActionChainWithConds, 9>>();
this->set_card_action_metadatas = make_shared<parray<ActionMetadata, 9>>();
this->hand_and_equip = std::make_shared<HandAndEquipState>();
this->card_short_statuses = std::make_shared<parray<CardShortStatus, 0x10>>();
this->set_card_action_chains = std::make_shared<parray<ActionChainWithConds, 9>>();
this->set_card_action_metadatas = std::make_shared<parray<ActionMetadata, 9>>();
this->hand_and_equip->clear_FF();
for (size_t z = 0; z < 0x10; z++) {
@@ -89,7 +87,7 @@ void PlayerState::init() {
this->set_card_action_metadatas->at(z).clear_FF();
}
this->sc_card = make_shared<Card>(this->deck_state->sc_card_id(), this->sc_card_ref, this->client_id, s);
this->sc_card = std::make_shared<Card>(this->deck_state->sc_card_id(), this->sc_card_ref, this->client_id, s);
this->sc_card->init();
this->draw_initial_hand();
if (s->options.is_nte()) {
@@ -114,18 +112,18 @@ void PlayerState::init() {
this->god_whim_can_use_hidden_cards = (s->deck_entries[this->client_id]->god_whim_flag != 3);
}
shared_ptr<Server> PlayerState::server() {
std::shared_ptr<Server> PlayerState::server() {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
shared_ptr<const Server> PlayerState::server() const {
std::shared_ptr<const Server> PlayerState::server() const {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
@@ -151,7 +149,7 @@ bool PlayerState::draw_cards_allowed() const {
return true;
}
void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter_ps) {
void PlayerState::apply_assist_card_effect_on_set(std::shared_ptr<PlayerState> setter_ps) {
auto s = this->server();
uint16_t assist_card_id = this->set_assist_card_id;
@@ -244,7 +242,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
case AssistEffect::LEGACY: {
uint16_t total_cost = 0;
for (ssize_t z = 7; z >= 0; z--) {
shared_ptr<const Card> card = this->set_cards[z];
std::shared_ptr<const Card> card = this->set_cards[z];
if (card) {
auto ce = card->get_definition();
uint8_t card_cost = ce->def.self_cost;
@@ -258,7 +256,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
if (!is_nte) {
this->on_cards_destroyed();
}
this->atk_points = min<uint8_t>(9, this->atk_points + (total_cost >> 1));
this->atk_points = std::min<uint8_t>(9, this->atk_points + (total_cost >> 1));
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
if (!is_nte) {
s->send_6xB4x05();
@@ -353,7 +351,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
if (is_nte
? (other_ps->assist_remaining_turns != 90 && other_ps->assist_remaining_turns != 99)
: (other_ps->assist_remaining_turns < 10)) {
other_ps->assist_remaining_turns = min<uint8_t>(9, other_ps->assist_remaining_turns << 1);
other_ps->assist_remaining_turns = std::min<uint8_t>(9, other_ps->assist_remaining_turns << 1);
}
for (ssize_t set_index = is_nte ? 0 : -1; set_index < 8; set_index++) {
@@ -369,7 +367,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
cond.remaining_turns <<= 1;
}
} else if (cond.remaining_turns < 10) {
cond.remaining_turns = min<uint8_t>(9, cond.remaining_turns << 1);
cond.remaining_turns = std::min<uint8_t>(9, cond.remaining_turns << 1);
}
}
}
@@ -480,7 +478,7 @@ void PlayerState::apply_dice_effects() {
}
for (size_t die_index = 0; die_index < 2; die_index++) {
this->dice_results[die_index] = min<uint8_t>(this->dice_results[die_index], 9);
this->dice_results[die_index] = std::min<uint8_t>(this->dice_results[die_index], 9);
}
}
@@ -818,15 +816,14 @@ int32_t PlayerState::error_code_for_client_setting_card(
}
}
vector<uint16_t> PlayerState::get_all_cards_within_range(
std::vector<uint16_t> PlayerState::get_all_cards_within_range(
const parray<uint8_t, 9 * 9>& range, const Location& loc, uint8_t target_team_id) const {
auto s = this->server();
auto log = s->log_stack("get_all_cards_within_range: ");
string loc_str = loc.str();
log.debug_f("loc={}, target_team_id={:02X}", loc_str, target_team_id);
log.debug_f("loc={}, target_team_id={:02X}", loc.str(), target_team_id);
vector<uint16_t> ret;
std::vector<uint16_t> ret;
for (size_t client_id = 0; client_id < 4; client_id++) {
auto other_ps = s->player_states[client_id];
if (other_ps && ((target_team_id == 0xFF) || (target_team_id == other_ps->get_team_id()))) {
@@ -845,7 +842,7 @@ void PlayerState::get_short_status_for_card_index_in_hand(size_t hand_index, Car
stat->card_ref = this->card_refs[hand_index - 1];
}
shared_ptr<DeckState> PlayerState::get_deck() {
std::shared_ptr<DeckState> PlayerState::get_deck() {
return this->deck_state;
}
@@ -871,11 +868,11 @@ uint16_t PlayerState::get_sc_card_id() const {
return this->sc_card_id;
}
shared_ptr<Card> PlayerState::get_sc_card() {
std::shared_ptr<Card> PlayerState::get_sc_card() {
return this->sc_card;
}
shared_ptr<const Card> PlayerState::get_sc_card() const {
std::shared_ptr<const Card> PlayerState::get_sc_card() const {
return this->sc_card;
}
@@ -887,11 +884,11 @@ CardType PlayerState::get_sc_card_type() const {
return this->sc_card_type;
}
shared_ptr<Card> PlayerState::get_set_card(size_t set_index) {
std::shared_ptr<Card> PlayerState::get_set_card(size_t set_index) {
return (set_index < 8) ? this->set_cards[set_index] : nullptr;
}
shared_ptr<const Card> PlayerState::get_set_card(size_t set_index) const {
std::shared_ptr<const Card> PlayerState::get_set_card(size_t set_index) const {
return (set_index < 8) ? this->set_cards[set_index] : nullptr;
}
@@ -964,7 +961,7 @@ uint16_t PlayerState::pop_from_discard_log(uint16_t) {
bool PlayerState::move_card_to_location_by_card_index(size_t card_index, const Location& new_loc) {
auto s = this->server();
shared_ptr<Card> card;
std::shared_ptr<Card> card;
if (card_index == 0) {
card = this->sc_card;
} else {
@@ -1010,7 +1007,7 @@ void PlayerState::move_null_hand_refs_to_end() {
void PlayerState::on_cards_destroyed() {
auto s = this->server();
unordered_multimap<uint16_t, bool> card_refs_map; // {card_ref: should_return_to_hand}
std::unordered_multimap<uint16_t, bool> card_refs_map; // {card_ref: should_return_to_hand}
for (size_t z = 0; z < 8; z++) {
auto card = this->set_cards[z];
if (!card || !(card->card_flags & 2)) {
@@ -1333,7 +1330,7 @@ bool PlayerState::set_card_from_hand(
}
this->card_refs[card_index + 1] = card_ref;
// Note: NTE doesn't call the destructor on the existing card, if there is one. Is that a bug?
this->set_cards[card_index - 7] = make_shared<Card>(s->card_id_for_card_ref(card_ref), card_ref, this->client_id, s);
this->set_cards[card_index - 7] = std::make_shared<Card>(s->card_id_for_card_ref(card_ref), card_ref, this->client_id, s);
auto new_card = this->set_cards[card_index - 7];
new_card->init();
@@ -1433,7 +1430,7 @@ void PlayerState::set_initial_location() {
static const uint8_t start_tile_defs_offset_for_team_size[4] = {0, 0, 1, 3};
if (num_team_players >= 4) {
throw logic_error("too many players on team");
throw std::logic_error("too many players on team");
}
size_t start_tile_def_index = start_tile_defs_offset_for_team_size[num_team_players] + player_index_within_team;
uint8_t player_start_tile = mr->map.start_tile_definitions[this->team_id][start_tile_def_index];
@@ -1455,11 +1452,11 @@ void PlayerState::set_initial_location() {
}
}
if (!start_tile_found) {
throw runtime_error("player start location not set");
throw std::runtime_error("player start location not set");
}
}
void PlayerState::set_map_occupied_bit_for_card_on_warp_tile(shared_ptr<const Card> card) {
void PlayerState::set_map_occupied_bit_for_card_on_warp_tile(std::shared_ptr<const Card> card) {
if (!card) {
return;
}
@@ -1524,7 +1521,7 @@ bool PlayerState::subtract_or_check_atk_or_def_points_for_action(const ActionSta
void PlayerState::subtract_atk_points(uint8_t cost) {
this->atk_points -= cost;
this->atk_points2 = min<uint8_t>(this->atk_points, this->atk_points2_max);
this->atk_points2 = std::min<uint8_t>(this->atk_points, this->atk_points2_max);
}
G_UpdateHand_Ep3_6xB4x02 PlayerState::prepare_6xB4x02() const {
@@ -1571,7 +1568,7 @@ void PlayerState::set_random_assist_card_from_hand_for_free() {
auto s = this->server();
bool is_nte = s->options.is_nte();
vector<uint16_t> candidate_card_refs;
std::vector<uint16_t> candidate_card_refs;
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
uint16_t card_ref = this->card_refs[hand_index];
auto ce = s->definition_for_card_ref(card_ref);
@@ -1636,11 +1633,11 @@ void PlayerState::send_6xB4x04_if_needed(bool always_send) {
}
}
vector<uint16_t> PlayerState::get_card_refs_within_range_from_all_players(
std::vector<uint16_t> PlayerState::get_card_refs_within_range_from_all_players(
const parray<uint8_t, 9 * 9>& range, const Location& loc, CardType type) const {
auto s = this->server();
vector<uint16_t> ret;
std::vector<uint16_t> ret;
for (size_t client_id = 0; client_id < 4; client_id++) {
auto other_ps = s->player_states[client_id];
if (other_ps && ((other_ps->get_sc_card_type() == type) || (type == CardType::ITEM))) {
@@ -1697,7 +1694,7 @@ void PlayerState::handle_before_turn_assist_effects() {
break;
case AssistEffect::ATK_DICE_2:
// Note: This behavior doesn't match the card description. Is it supposed to add 2 or multiply by 2?
this->atk_points = min<int16_t>(this->atk_points + 2, 9);
this->atk_points = std::min<int16_t>(this->atk_points + 2, 9);
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
break;
case AssistEffect::SKIP_TURN:
@@ -1756,8 +1753,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
size_t z = 0;
do {
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
log.debug_f("on action card ref {}", ref_str);
log.debug_f("on action card ref {}", s->debug_str_for_card_ref(pa.action_card_refs[z]));
}
card->unknown_80237A90(pa, pa.action_card_refs[z]);
card->unknown_802379BC(pa.action_card_refs[z]);
@@ -1793,8 +1789,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
auto target_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
if (target_card) {
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string ref_str = s->debug_str_for_card_ref(pa.target_card_refs[z]);
log.debug_f("on target card ref {}", ref_str);
log.debug_f("on target card ref {}", s->debug_str_for_card_ref(pa.target_card_refs[z]));
}
target_card->unknown_802379DC(pa);
if (!is_nte) {
@@ -1823,8 +1818,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
}
for (size_t z = 0; (z < pa.action_card_refs.size()) && (pa.action_card_refs[z] != 0xFFFF); z++) {
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
log.debug_f("discarding {} from hand", ref_str);
log.debug_f("discarding {} from hand", s->debug_str_for_card_ref(pa.action_card_refs[z]));
}
this->discard_ref_from_hand(pa.action_card_refs[z]);
}
@@ -1866,7 +1860,7 @@ void PlayerState::dice_phase_before() {
this->send_set_card_updates();
}
void PlayerState::handle_homesick_assist_effect_from_bomb(shared_ptr<Card> card) {
void PlayerState::handle_homesick_assist_effect_from_bomb(std::shared_ptr<Card> card) {
if (!card) {
return;
}
@@ -1998,13 +1992,13 @@ void PlayerState::roll_main_dice_or_apply_after_effects() {
}
this->atk_points += s->team_dice_bonus[this->team_id];
this->def_points += s->team_dice_bonus[this->team_id];
this->atk_points = clamp<uint8_t>(this->atk_points, 1, 9);
this->def_points = clamp<uint8_t>(this->def_points, 1, 9);
this->atk_points = std::clamp<uint8_t>(this->atk_points, 1, 9);
this->def_points = std::clamp<uint8_t>(this->def_points, 1, 9);
if (!s->options.is_nte()) {
this->atk_bonuses = this->atk_points - atk_before_bonuses;
this->def_bonuses = this->def_points - def_before_bonuses;
}
this->atk_points2 = min<uint8_t>(this->atk_points2_max, this->atk_points);
this->atk_points2 = std::min<uint8_t>(this->atk_points2_max, this->atk_points);
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
}
@@ -2036,7 +2030,7 @@ void PlayerState::compute_team_dice_bonus_after_draw_phase() {
uint8_t current_team_turn = s->get_current_team_turn();
uint8_t dice_boost = s->get_team_exp(current_team_turn) / (s->team_client_count[current_team_turn] * 12);
s->card_special->adjust_dice_boost_if_team_has_condition_52(current_team_turn, &dice_boost, 0);
s->team_dice_bonus[current_team_turn] = clamp<int16_t>(dice_boost, 0, 8);
s->team_dice_bonus[current_team_turn] = std::clamp<int16_t>(dice_boost, 0, 8);
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
}
+16 -18
View File
@@ -2,8 +2,6 @@
#include "Server.hh"
using namespace std;
namespace Episode3 {
Condition::Condition() {
@@ -61,7 +59,7 @@ void Condition::clear_FF() {
this->unknown_a8 = 0xFF;
}
std::string Condition::str(shared_ptr<const Server> s) const {
std::string Condition::str(std::shared_ptr<const Server> s) const {
return std::format(
"Condition[type={}, turns={}, a_arg={}, dice={}, flags={:02X}, "
"def_eff_index={}, ref={}, value={}, giver_ref={} "
@@ -98,7 +96,7 @@ void EffectResult::clear() {
this->dice_roll_value = 0;
}
std::string EffectResult::str(shared_ptr<const Server> s) const {
std::string EffectResult::str(std::shared_ptr<const Server> s) const {
return std::format(
"EffectResult[att_ref={}, target_ref={}, value={}, cur_hp={}, ap={}, tp={}, flags={:02X}, op={}, cond_index={}, dice={}]",
s->debug_str_for_card_ref(this->attacker_card_ref),
@@ -130,7 +128,7 @@ bool CardShortStatus::operator!=(const CardShortStatus& other) const {
return !this->operator==(other);
}
std::string CardShortStatus::str(shared_ptr<const Server> s) const {
std::string CardShortStatus::str(std::shared_ptr<const Server> s) const {
return std::format(
"CardShortStatus[ref={}, cur_hp={}, flags={:08X}, loc={}, u1={:04X}, max_hp={}, u2={}]",
s->debug_str_for_card_ref(this->card_ref),
@@ -178,7 +176,7 @@ void ActionState::clear() {
this->unused2 = 0xFFFF;
}
std::string ActionState::str(shared_ptr<const Server> s) const {
std::string ActionState::str(std::shared_ptr<const Server> s) const {
return std::format(
"ActionState[client={:X}, u={}, facing={}, attacker_ref={}, def_ref={}, target_refs={}, action_refs={}, orig_attacker_ref={}]",
this->client_id,
@@ -222,7 +220,7 @@ bool ActionChain::operator!=(const ActionChain& other) const {
return !this->operator==(other);
}
std::string ActionChain::str(shared_ptr<const Server> s) const {
std::string ActionChain::str(std::shared_ptr<const Server> s) const {
return std::format(
"ActionChain[eff_ap={}, eff_tp={}, ap_bonus={}, damage={}, acting_ref={}, unknown_ref_a3={}, attack_action_refs={}, "
"attack_action_ref_count={}, medium={}, target_ref_count={}, subphase={}, strikes={}, damage_mult={}, attack_num={}, "
@@ -309,8 +307,8 @@ bool ActionChainWithConds::operator!=(const ActionChainWithConds& other) const {
return !this->operator==(other);
}
std::string ActionChainWithConds::str(shared_ptr<const Server> s) const {
string ret = "ActionChainWithConds[chain=";
std::string ActionChainWithConds::str(std::shared_ptr<const Server> s) const {
std::string ret = "ActionChainWithConds[chain=";
ret += this->chain.str(s);
ret += ", conds=[";
for (size_t z = 0; z < this->conditions.size(); z++) {
@@ -383,7 +381,7 @@ void ActionChainWithConds::set_flags(uint32_t flags) {
this->chain.flags |= flags;
}
void ActionChainWithConds::add_attack_action_card_ref(uint16_t card_ref, shared_ptr<Server> server) {
void ActionChainWithConds::add_attack_action_card_ref(uint16_t card_ref, std::shared_ptr<Server> server) {
if (card_ref != 0xFFFF) {
this->chain.attack_action_card_refs[this->chain.attack_action_card_ref_count++] = card_ref;
}
@@ -397,7 +395,7 @@ void ActionChainWithConds::add_target_card_ref(uint16_t card_ref) {
}
}
void ActionChainWithConds::compute_attack_medium(shared_ptr<Server> server) {
void ActionChainWithConds::compute_attack_medium(std::shared_ptr<Server> server) {
this->chain.attack_medium = AttackMedium::PHYSICAL;
for (size_t z = 0; z < this->chain.attack_action_card_ref_count; z++) {
uint16_t card_ref = this->chain.attack_action_card_refs[z];
@@ -437,7 +435,7 @@ bool ActionChainWithConds::get_condition_value(
return any_found;
}
void ActionChainWithConds::set_action_subphase_from_card(shared_ptr<const Card> card) {
void ActionChainWithConds::set_action_subphase_from_card(std::shared_ptr<const Card> card) {
this->chain.action_subphase = card->server()->get_current_action_subphase();
}
@@ -545,7 +543,7 @@ bool ActionMetadata::operator!=(const ActionMetadata& other) const {
return !this->operator==(other);
}
std::string ActionMetadata::str(shared_ptr<const Server> s) const {
std::string ActionMetadata::str(std::shared_ptr<const Server> s) const {
return std::format(
"ActionMetadata[ref={}, target_ref_count={}, def_ref_count={}, subphase={}, def_power={}, def_bonus={}, "
"att_bonus={}, flags={:08X}, target_refs={}, defense_refs={}, original_attacker_refs={}]",
@@ -621,7 +619,7 @@ void ActionMetadata::add_target_card_ref(uint16_t card_ref) {
}
void ActionMetadata::add_defense_card_ref(
uint16_t defense_card_ref, shared_ptr<Card> card, uint16_t original_attacker_card_ref) {
uint16_t defense_card_ref, std::shared_ptr<Card> card, uint16_t original_attacker_card_ref) {
if ((defense_card_ref != 0xFFFF) && (this->defense_card_ref_count < 8)) {
this->defense_card_refs[this->defense_card_ref_count] = defense_card_ref;
this->original_attacker_card_refs[this->defense_card_ref_count] = original_attacker_card_ref;
@@ -634,7 +632,7 @@ HandAndEquipState::HandAndEquipState() {
this->clear();
}
std::string HandAndEquipState::str(shared_ptr<const Server> s) const {
std::string HandAndEquipState::str(std::shared_ptr<const Server> s) const {
return std::format(
"HandAndEquipState[dice=[{}, {}], atk={}, def={}, atk2={}, a1={}, total_set_cost={}, is_cpu={}, assist_flags={:08X}, "
"hand_refs={}, assist_ref={}, set_refs={}, sc_ref={}, hand_refs2={}, set_refs2={}, assist_ref2={}, assist_set_num={}, assist_card_id={}, "
@@ -777,7 +775,7 @@ uint8_t PlayerBattleStats::rank_for_score(float score) {
const char* PlayerBattleStats::name_for_rank(uint8_t rank) {
if (rank >= RANK_THRESHOLD_COUNT + 1) {
throw invalid_argument("invalid rank");
throw std::invalid_argument("invalid rank");
}
return RANK_NAMES[rank];
}
@@ -842,12 +840,12 @@ static bool is_card_within_range(
return ret;
}
vector<uint16_t> get_card_refs_within_range(
std::vector<uint16_t> get_card_refs_within_range(
const parray<uint8_t, 9 * 9>& range,
const Location& loc,
const parray<CardShortStatus, 0x10>& short_statuses,
phosg::PrefixedLogger* log) {
vector<uint16_t> ret;
std::vector<uint16_t> ret;
if (is_card_within_range(range, loc, short_statuses[0], log)) {
if (log) {
log->debug_f("get_card_refs_within_range: sc card @{:04X} within range", short_statuses[0].card_ref);
+57 -64
View File
@@ -5,20 +5,17 @@
#include "DataIndexes.hh"
#include "Server.hh"
using namespace std;
namespace Episode3 {
void compute_effective_range(
parray<uint8_t, 9 * 9>& ret,
shared_ptr<const CardIndex> card_index,
std::shared_ptr<const CardIndex> card_index,
uint16_t card_id,
const Location& loc,
shared_ptr<const MapAndRulesState> map_and_rules,
std::shared_ptr<const MapAndRulesState> map_and_rules,
phosg::PrefixedLogger* log) {
if (log && log->should_log(phosg::LogLevel::L_DEBUG)) {
string loc_str = loc.str();
log->debug_f("compute_effective_range: card_id=#{:04X}, loc={}", card_id, loc_str);
log->debug_f("compute_effective_range: card_id=#{:04X}, loc={}", card_id, loc.str());
log->debug_f("compute_effective_range: map_and_rules->map:");
map_and_rules->map.print(stderr);
}
@@ -28,10 +25,10 @@ void compute_effective_range(
if (card_id == 0xFFFE) { // Heavy Fog: one tile directly in front
range_def[3] = 0x00000100;
} else {
shared_ptr<const CardIndex::CardEntry> ce;
std::shared_ptr<const CardIndex::CardEntry> ce;
try {
ce = card_index->definition_for_id(card_id);
} catch (const out_of_range&) {
} catch (const std::out_of_range&) {
return;
}
for (size_t z = 0; z < 6; z++) {
@@ -95,7 +92,7 @@ void compute_effective_range(
up_y = 9 - y - 1;
break;
default:
throw logic_error("invalid direction");
throw std::logic_error("invalid direction");
}
ret[y * 9 + x] = decoded_range[up_y * 9 + up_x];
if (log) {
@@ -117,9 +114,9 @@ void compute_effective_range(
}
bool card_linkage_is_valid(
shared_ptr<const CardIndex::CardEntry> right_ce,
shared_ptr<const CardIndex::CardEntry> left_ce,
shared_ptr<const CardIndex::CardEntry> sc_ce,
std::shared_ptr<const CardIndex::CardEntry> right_ce,
std::shared_ptr<const CardIndex::CardEntry> left_ce,
std::shared_ptr<const CardIndex::CardEntry> sc_ce,
bool has_permission_effect) {
if (!right_ce) {
return false;
@@ -173,31 +170,27 @@ bool card_linkage_is_valid(
return false;
}
RulerServer::RulerServer(shared_ptr<Server> server)
: w_server(server),
team_id_for_client_id(0xFF),
error_code1(0),
error_code2(0),
error_code3(0) {}
RulerServer::RulerServer(std::shared_ptr<Server> server)
: w_server(server), team_id_for_client_id(0xFF), error_code1(0), error_code2(0), error_code3(0) {}
shared_ptr<Server> RulerServer::server() {
std::shared_ptr<Server> RulerServer::server() {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
shared_ptr<const Server> RulerServer::server() const {
std::shared_ptr<const Server> RulerServer::server() const {
auto s = this->w_server.lock();
if (!s) {
throw runtime_error("server is deleted");
throw std::runtime_error("server is deleted");
}
return s;
}
ActionChainWithConds* RulerServer::action_chain_with_conds_for_card_ref(uint16_t card_ref) {
return const_cast<ActionChainWithConds*>(as_const(*this).action_chain_with_conds_for_card_ref(card_ref));
return const_cast<ActionChainWithConds*>(std::as_const(*this).action_chain_with_conds_for_card_ref(card_ref));
}
const ActionChainWithConds* RulerServer::action_chain_with_conds_for_card_ref(uint16_t card_ref) const {
@@ -398,7 +391,7 @@ bool RulerServer::attack_action_has_pierce_and_not_rampage(const ActionState& pa
last_action_card_index = z;
}
auto check_chain = [&]() -> optional<bool> {
auto check_chain = [&]() -> std::optional<bool> {
const auto* chain = this->action_chain_with_conds_for_card_ref(pa.attacker_card_ref);
if (chain) {
for (ssize_t cond_index = 8; cond_index >= 0; cond_index--) {
@@ -415,7 +408,7 @@ bool RulerServer::attack_action_has_pierce_and_not_rampage(const ActionState& pa
}
}
}
return nullopt;
return std::nullopt;
};
if (is_nte) {
@@ -767,7 +760,7 @@ bool RulerServer::check_move_path_and_get_cost(
if (max_dist < 1) {
return false;
}
max_dist = min<uint8_t>(max_dist, 9);
max_dist = std::min<uint8_t>(max_dist, 9);
const auto* short_status = this->short_status_for_card_ref(card_ref);
if (!short_status) {
@@ -1030,7 +1023,7 @@ bool RulerServer::check_usability_or_condition_apply(
}
break;
case CriterionCode::HUNTER_NON_ANDROID_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0001, // Orland
0x0002, // Kranz
0x0003, // Ino'lis
@@ -1059,7 +1052,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_HU_CLASS_MALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0001, // Orland
0x0113, // Teifu
0x02AA, // H-HUmar
@@ -1070,7 +1063,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_FEMALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0003, // Ino'lis
0x0004, // Sil'fer
0x0006, // Kylria
@@ -1094,7 +1087,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_NON_RA_CLASS_HUMAN_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0001, // Orland
0x0003, // Ino'lis
0x0004, // Sil'fer
@@ -1117,7 +1110,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_HU_CLASS_ANDROID_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0110, // Saligun
0x0113, // Teifu
0x02AC, // H-HUcast
@@ -1128,7 +1121,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_NON_RA_CLASS_NON_NEWMAN_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0001, // Orland
0x0003, // Ino'lis
0x0110, // Saligun
@@ -1148,7 +1141,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_NON_NEWMAN_NON_FORCE_MALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0001, // Orland
0x0002, // Kranz
0x0005, // Guykild
@@ -1166,7 +1159,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_HUNEWEARL_CLASS_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0004, // Sil'fer
0x02AB, // H-HUnewearl
0x02CF, // H-HUnewearl
@@ -1174,7 +1167,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_RA_CLASS_MALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0002, // Kranz
0x0005, // Guykild
0x02AE, // H-RAmar
@@ -1185,7 +1178,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_RA_CLASS_FEMALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0006, // Kylria
0x0114, // Stella
0x02AF, // H-RAmarl
@@ -1196,7 +1189,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_RA_OR_FO_CLASS_FEMALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0003, // Ino'lis
0x0006, // Kylria
0x0112, // Viviana
@@ -1213,7 +1206,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_HU_OR_RA_CLASS_HUMAN_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0001, // Orland
0x0002, // Kranz
0x0004, // Sil'fer
@@ -1230,7 +1223,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_RA_CLASS_ANDROID_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0005, // Guykild
0x0114, // Stella
0x02B0, // H-RAcast
@@ -1241,7 +1234,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_FO_CLASS_FEMALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0003, // Ino'lis
0x0112, // Viviana
0x02B3, // H-FOmarl
@@ -1252,7 +1245,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_HUMAN_FEMALE_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0003, // Ino'lis
0x0004, // Sil'fer
0x0006, // Kylria
@@ -1269,7 +1262,7 @@ bool RulerServer::check_usability_or_condition_apply(
return ret && card_ids.count(card_id2);
}
case CriterionCode::HUNTER_ANDROID_SC: {
static const unordered_set<uint16_t> card_ids = {
static const std::unordered_set<uint16_t> card_ids = {
0x0005, // Guykild
0x0110, // Saligun
0x0113, // Teifu
@@ -1433,14 +1426,14 @@ uint16_t RulerServer::compute_attack_or_defense_costs(
final_cost = 0;
}
} else {
final_cost = max<int16_t>(final_cost, this->hand_and_equip_states[pa.client_id]->atk_points);
final_cost = std::max<int16_t>(final_cost, this->hand_and_equip_states[pa.client_id]->atk_points);
}
}
if (out_ally_cost) {
*out_ally_cost = total_ally_cost;
}
return max<int16_t>(final_cost, total_cost + assist_cost_bias);
return std::max<int16_t>(final_cost, total_cost + assist_cost_bias);
}
bool RulerServer::compute_effective_range_and_target_mode_for_attack(
@@ -1627,7 +1620,7 @@ bool RulerServer::defense_card_can_apply_to_attack(
bool RulerServer::defense_card_matches_any_attack_card_top_color(const ActionState& pa) const {
auto ce = this->definition_for_card_ref(pa.action_card_refs[0]);
if (!ce) {
throw runtime_error("defense card definition is missing");
throw std::runtime_error("defense card definition is missing");
}
const auto* chain = this->action_chain_with_conds_for_card_ref(pa.original_attacker_card_ref);
if (chain->chain.attack_action_card_ref_count < 1) {
@@ -1646,7 +1639,7 @@ bool RulerServer::defense_card_matches_any_attack_card_top_color(const ActionSta
return false;
}
shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_ref(uint16_t card_ref) const {
std::shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_ref(uint16_t card_ref) const {
uint16_t card_id = this->card_id_for_card_ref(card_ref);
if (card_id == 0xFFFF) {
return nullptr;
@@ -1841,7 +1834,7 @@ int32_t RulerServer::error_code_for_client_setting_card(
return -0x7E;
}
} else {
int16_t diff = max<int16_t>(summon_area_size - summon_cost, 0);
int16_t diff = std::max<int16_t>(summon_area_size - summon_cost, 0);
if (x_offset > 0) {
if (loc->x < summon_area_loc.x) {
return -0x7E;
@@ -1860,7 +1853,7 @@ int32_t RulerServer::error_code_for_client_setting_card(
return -0x7E;
}
} else {
int16_t diff = max<int16_t>(summon_area_size - summon_cost, 0);
int16_t diff = std::max<int16_t>(summon_area_size - summon_cost, 0);
if (y_offset > 0) {
if (loc->y < summon_area_loc.y) {
return -0x7E;
@@ -1974,7 +1967,7 @@ bool RulerServer::flood_fill_move_path(
Direction dirs[3] = {direction, turn_left(direction), turn_right(direction)};
for (size_t dir_index = 0; dir_index < 3; dir_index++) {
if (static_cast<uint8_t>(dirs[dir_index]) > 3) {
throw logic_error("invalid direction");
throw std::logic_error("invalid direction");
}
ret |= this->flood_fill_move_path(
chain,
@@ -2017,7 +2010,7 @@ uint16_t RulerServer::get_ally_sc_card_ref(uint16_t card_ref) const {
return 0xFFFF;
}
shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_id(uint32_t card_id) const {
std::shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_id(uint32_t card_id) const {
return this->server()->definition_for_card_id(card_id);
}
@@ -2130,11 +2123,11 @@ bool RulerServer::get_creature_summon_area(uint8_t client_id, Location* out_loc,
return true;
}
shared_ptr<HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) {
std::shared_ptr<HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) {
return (client_id < 4) ? this->hand_and_equip_states[client_id] : nullptr;
}
shared_ptr<const HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) const {
std::shared_ptr<const HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) const {
return (client_id < 4) ? this->hand_and_equip_states[client_id] : nullptr;
}
@@ -2171,7 +2164,7 @@ ssize_t RulerServer::get_path_cost(
path_length *= cond.value;
}
}
return clamp<ssize_t>(path_length + cost_penalty, 0, 99);
return std::clamp<ssize_t>(path_length + cost_penalty, 0, 99);
}
ActionType RulerServer::get_pending_action_type(const ActionState& pa) const {
@@ -2440,9 +2433,9 @@ bool RulerServer::is_defense_valid(const ActionState& pa) {
}
void RulerServer::link_objects(
shared_ptr<MapAndRulesState> map_and_rules,
shared_ptr<StateFlags> state_flags,
shared_ptr<AssistServer> assist_server) {
std::shared_ptr<MapAndRulesState> map_and_rules,
std::shared_ptr<StateFlags> state_flags,
std::shared_ptr<AssistServer> assist_server) {
this->map_and_rules = map_and_rules;
this->state_flags = state_flags;
this->assist_server = assist_server;
@@ -2491,7 +2484,7 @@ size_t RulerServer::max_move_distance_for_card_ref(uint32_t card_ref) const {
if (this->find_condition_on_card_ref(card_ref, ConditionType::SET_MV, &cond, nullptr, true)) {
ret = cond.value;
}
ret = max<ssize_t>(0, ret);
ret = std::max<ssize_t>(0, ret);
size_t num_assists = this->assist_server->compute_num_assist_effects_for_client(client_id);
bool has_stamina_effect = false;
@@ -2505,7 +2498,7 @@ size_t RulerServer::max_move_distance_for_card_ref(uint32_t card_ref) const {
}
}
return has_stamina_effect ? 9 : min<ssize_t>(9, ret);
return has_stamina_effect ? 9 : std::min<ssize_t>(9, ret);
}
}
@@ -2566,11 +2559,11 @@ void RulerServer::offsets_for_direction(
void RulerServer::register_player(
uint8_t client_id,
shared_ptr<HandAndEquipState> hes,
shared_ptr<parray<CardShortStatus, 0x10>> short_statuses,
shared_ptr<DeckEntry> deck_entry,
shared_ptr<parray<ActionChainWithConds, 9>> set_card_action_chains,
shared_ptr<parray<ActionMetadata, 9>> set_card_action_metadatas) {
std::shared_ptr<HandAndEquipState> hes,
std::shared_ptr<parray<CardShortStatus, 0x10>> short_statuses,
std::shared_ptr<DeckEntry> deck_entry,
std::shared_ptr<parray<ActionChainWithConds, 9>> set_card_action_chains,
std::shared_ptr<parray<ActionMetadata, 9>> set_card_action_metadatas) {
this->hand_and_equip_states[client_id] = hes;
this->short_statuses[client_id] = short_statuses;
this->deck_entries[client_id] = deck_entry;
@@ -2656,7 +2649,7 @@ int32_t RulerServer::set_cost_for_card(uint8_t client_id, uint16_t card_ref) con
// In NTE, Land Price is apparently 2x rather than 1.5x
ret = is_nte ? (ret << 1) : (ret + (ret >> 1));
} else if (eff == AssistEffect::DEFLATION) {
ret = max<int32_t>(0, ret - 1);
ret = std::max<int32_t>(0, ret - 1);
} else if (eff == AssistEffect::INFLATION) {
ret++;
}
+117 -119
View File
@@ -7,11 +7,9 @@
#include "../Revision.hh"
#include "../SendCommands.hh"
using namespace std;
namespace Episode3 {
// This is (obviously) not the original string. The original string is:
// This is (obviously) not the original std::string. The original std::string is:
// NTE: "03/05/29 18:00 by K.Toya"
// Final: "[V1][FINAL2.0] 03/09/13 15:30 by K.Toya"
static const char* VERSION_SIGNATURE = "newserv Ep3 based on [V1][FINAL2.0] 03/09/13 15:30 by K.Toya";
@@ -27,7 +25,7 @@ void Server::PresenceEntry::clear() {
this->is_cpu_player = 0;
}
Server::Server(shared_ptr<Lobby> lobby, Options&& options)
Server::Server(std::shared_ptr<Lobby> lobby, Options&& options)
: lobby(lobby),
battle_record(lobby ? lobby->battle_record : nullptr),
has_lobby(lobby != nullptr),
@@ -81,7 +79,7 @@ Server::Server(shared_ptr<Lobby> lobby, Options&& options)
Server::~Server() noexcept(false) {
if (this->logger_stack.size() != 1) {
throw logic_error(std::format("incorrect logger stack size: expected 1, received {}", this->logger_stack.size()));
throw std::logic_error(std::format("incorrect logger stack size: expected 1, received {}", this->logger_stack.size()));
}
delete this->logger_stack.back();
}
@@ -89,31 +87,31 @@ Server::~Server() noexcept(false) {
void Server::init() {
this->log().info_f("Creating server with random seed {:08X}", this->options.rand_crypt->seed());
this->map_and_rules = make_shared<MapAndRulesState>();
this->map_and_rules = std::make_shared<MapAndRulesState>();
this->num_clients_present = 0;
this->overlay_state.clear();
for (size_t z = 0; z < 4; z++) {
this->presence_entries[z].clear();
this->deck_entries[z] = make_shared<DeckEntry>();
this->deck_entries[z] = std::make_shared<DeckEntry>();
this->name_entries[z].clear();
this->name_entries_valid[z] = false;
}
this->card_special = make_shared<CardSpecial>(this->shared_from_this());
this->card_special = std::make_shared<CardSpecial>(this->shared_from_this());
// Note: The original implementation calls the default PSOV2Encryption constructor for random_crypt, which just uses
// 0 as the seed. It then re-seeds the generator later. We instead expect the caller to provide a seeded generator,
// and we don't re-seed it at all.
// this->random_crypt = make_shared<PSOV2Encryption>(0);
// this->random_crypt = std::make_shared<PSOV2Encryption>(0);
this->state_flags = make_shared<StateFlags>();
this->state_flags = std::make_shared<StateFlags>();
this->clear_player_flags_after_dice_phase();
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
this->assist_server = make_shared<AssistServer>(this->shared_from_this());
this->ruler_server = make_shared<RulerServer>(this->shared_from_this());
this->assist_server = std::make_shared<AssistServer>(this->shared_from_this());
this->ruler_server = std::make_shared<RulerServer>(this->shared_from_this());
this->ruler_server->link_objects(this->map_and_rules, this->state_flags, this->assist_server);
this->send_6xB4x46();
@@ -135,7 +133,7 @@ Server::StackLogger::StackLogger(StackLogger&& other)
: PrefixedLogger(std::move(other)),
server(other.server) {
if (this->server->logger_stack.back() != &other) {
throw logic_error("cannot move StackLogger unless it is the last one");
throw std::logic_error("cannot move StackLogger unless it is the last one");
}
this->server->logger_stack.back() = this;
}
@@ -144,7 +142,7 @@ Server::StackLogger& Server::StackLogger::operator=(StackLogger&& other) {
this->PrefixedLogger::operator=(std::move(other));
this->server = other.server;
if (this->server->logger_stack.back() != &other) {
throw logic_error("cannot move StackLogger unless it is the last one");
throw std::logic_error("cannot move StackLogger unless it is the last one");
}
this->server->logger_stack.back() = this;
return *this;
@@ -152,7 +150,7 @@ Server::StackLogger& Server::StackLogger::operator=(StackLogger&& other) {
Server::StackLogger::~StackLogger() noexcept(false) {
if (this->server->logger_stack.back() != this) {
throw logic_error("incorrect logger stack unwind order");
throw std::logic_error("incorrect logger stack unwind order");
}
this->server->logger_stack.pop_back();
}
@@ -171,8 +169,7 @@ std::string Server::debug_str_for_card_ref(uint16_t card_ref) const {
}
auto ce = this->definition_for_card_ref(card_ref);
if (ce) {
string name = ce->def.en_name.decode();
return std::format("@{:04X} (#{:04X} {})", card_ref, ce->def.card_id, name);
return std::format("@{:04X} (#{:04X} {})", card_ref, ce->def.card_id, ce->def.en_name.decode());
} else {
return std::format("@{:04X} (missing)", card_ref);
}
@@ -184,8 +181,7 @@ std::string Server::debug_str_for_card_id(uint16_t card_id) const {
}
auto ce = this->definition_for_card_id(card_id);
if (ce) {
string name = ce->def.en_name.decode();
return std::format("#{:04X} ({})", card_id, name);
return std::format("#{:04X} ({})", card_id, ce->def.en_name.decode());
} else {
return std::format("#{:04X} (missing)", card_id);
}
@@ -209,17 +205,17 @@ int8_t Server::get_winner_team_id() const {
}
if (!team_player_counts[0] || !team_player_counts[1]) {
throw logic_error("at least one team has no players");
throw std::logic_error("at least one team has no players");
}
if (team_win_flag_counts[0] && team_win_flag_counts[1]) {
throw logic_error("both teams have winning players");
throw std::logic_error("both teams have winning players");
}
for (int8_t z = 0; z < 2; z++) {
if (!team_win_flag_counts[z]) {
continue;
}
if (team_win_flag_counts[z] != team_player_counts[z]) {
throw logic_error("only some players on team have won");
throw std::logic_error("only some players on team have won");
}
return z;
}
@@ -236,10 +232,10 @@ void Server::send(const void* data, size_t size, uint8_t command, bool enable_ma
if (this->has_lobby) {
auto l = this->lobby.lock();
if (!l) {
throw runtime_error("lobby is deleted");
throw std::runtime_error("lobby is deleted");
}
string masked_data;
std::string masked_data;
if (enable_masking &&
!this->options.is_nte() &&
!(this->options.behavior_flags & BehaviorFlag::DISABLE_MASKING) &&
@@ -267,7 +263,7 @@ void Server::send(const void* data, size_t size, uint8_t command, bool enable_ma
void Server::send_6xB4x46() const {
// Note: This function is not part of the original implementation; it was factored out from its callsites in this
// file and the strings were changed.
// file and the std::strings were changed.
// NTE doesn't have the date_str2 field, but we send it anyway to make debugging easier.
G_ServerVersionStrings_Ep3_6xB4x46 cmd;
@@ -275,12 +271,13 @@ void Server::send_6xB4x46() const {
cmd.date_str1.encode(
std::format("Card definitions: {:016X}", this->options.card_index->definitions_hash()),
Language::ENGLISH);
string build_date = phosg::format_time(BUILD_TIMESTAMP);
std::string build_date = phosg::format_time(BUILD_TIMESTAMP);
cmd.date_str2.encode(std::format("newserv {} compiled at {}", GIT_REVISION_HASH, build_date), Language::ENGLISH);
this->send(cmd);
}
string Server::prepare_6xB6x41_map_definition(shared_ptr<const MapIndex::Map> map, Language language, bool is_nte) {
std::string Server::prepare_6xB6x41_map_definition(
std::shared_ptr<const MapIndex::Map> map, Language language, bool is_nte) {
auto vm = map->version(language);
const auto& compressed = vm->compressed(is_nte);
@@ -295,7 +292,8 @@ string Server::prepare_6xB6x41_map_definition(shared_ptr<const MapIndex::Map> ma
void Server::send_commands_for_joining_spectator(std::shared_ptr<Channel> ch) const {
if (this->last_chosen_map) {
string data = this->prepare_6xB6x41_map_definition(this->last_chosen_map, ch->language, this->options.is_nte());
std::string data = this->prepare_6xB6x41_map_definition(
this->last_chosen_map, ch->language, this->options.is_nte());
this->log().info_f(
"Sending {} version of map {:08X}", name_for_language(ch->language), this->last_chosen_map->map_number);
ch->send(0x6C, 0x00, data);
@@ -366,11 +364,12 @@ void Server::add_team_exp(uint8_t team_id, int32_t exp) {
}
}
this->team_exp[team_id] = clamp<int16_t>(this->team_exp[team_id] + exp, 0, this->team_client_count[team_id] * 96);
this->team_exp[team_id] = std::clamp<int16_t>(
this->team_exp[team_id] + exp, 0, this->team_client_count[team_id] * 96);
uint8_t dice_boost = this->team_exp[team_id] / (this->team_client_count[team_id] * 12);
this->card_special->adjust_dice_boost_if_team_has_condition_52(team_id, &dice_boost, 0);
this->team_dice_bonus[team_id] = min<uint8_t>(dice_boost, 8);
this->team_dice_bonus[team_id] = std::min<uint8_t>(dice_boost, 8);
}
bool Server::advance_battle_phase() {
@@ -396,7 +395,7 @@ bool Server::advance_battle_phase() {
this->dice_phase_before();
break;
default:
throw logic_error("invalid battle phase");
throw std::logic_error("invalid battle phase");
}
return this->check_for_battle_end();
}
@@ -414,15 +413,15 @@ void Server::draw_phase_before() {
}
}
shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_ref(uint16_t card_ref) const {
std::shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_ref(uint16_t card_ref) const {
try {
return this->options.card_index->definition_for_id(this->card_id_for_card_ref(card_ref));
} catch (const out_of_range&) {
} catch (const std::out_of_range&) {
return nullptr;
}
}
shared_ptr<Card> Server::card_for_set_card_ref(uint16_t card_ref) {
std::shared_ptr<Card> Server::card_for_set_card_ref(uint16_t card_ref) {
if (card_ref == 0xFFFF) {
return nullptr;
}
@@ -447,7 +446,7 @@ shared_ptr<Card> Server::card_for_set_card_ref(uint16_t card_ref) {
return nullptr;
}
shared_ptr<const Card> Server::card_for_set_card_ref(uint16_t card_ref) const {
std::shared_ptr<const Card> Server::card_for_set_card_ref(uint16_t card_ref) const {
return const_cast<Server*>(this)->card_for_set_card_ref(card_ref);
}
@@ -584,7 +583,7 @@ bool Server::check_for_battle_end() {
void Server::force_replace_assist_card(uint8_t client_id, uint16_t card_id) {
auto ps = this->player_states.at(client_id);
if (!ps) {
throw runtime_error("player does not exist");
throw std::runtime_error("player does not exist");
}
if (card_id == 0xFFFF) {
ps->discard_set_assist_card();
@@ -599,12 +598,12 @@ void Server::force_replace_assist_card(uint8_t client_id, uint16_t card_id) {
void Server::force_destroy_field_character(uint8_t client_id, size_t visible_index) {
auto ps = this->player_states.at(client_id);
if (!ps) {
throw runtime_error("player does not exist");
throw std::runtime_error("player does not exist");
}
// TODO: Is it possible for there to be gaps in the set cards array? If not, we could just do a direct array lookup
// here instead of this loop
shared_ptr<Card> set_card = nullptr;
std::shared_ptr<Card> set_card = nullptr;
for (size_t set_index = 0; set_index < 8; set_index++) {
if (!ps->set_cards[set_index]) {
continue;
@@ -681,7 +680,7 @@ void Server::compute_all_map_occupied_bits() {
}
void Server::compute_team_dice_bonus(uint8_t team_id) {
this->team_dice_bonus[team_id] = clamp<int16_t>(
this->team_dice_bonus[team_id] = std::clamp<int16_t>(
this->team_exp[team_id] / (this->team_client_count[team_id] * 12), 0, 8);
}
@@ -700,10 +699,10 @@ void Server::copy_player_states_to_prev_states() {
}
}
shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_id(uint16_t card_id) const {
std::shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_id(uint16_t card_id) const {
try {
return this->options.card_index->definition_for_id(card_id);
} catch (const out_of_range&) {
} catch (const std::out_of_range&) {
return nullptr;
}
}
@@ -731,7 +730,7 @@ void Server::determine_first_team_turn() {
this->team_client_count[0] = this->map_and_rules->num_team0_players;
this->team_client_count[1] = this->map_and_rules->num_players - this->team_client_count[0];
if (this->team_client_count[0] == 0 || this->team_client_count[1] == 0) {
throw runtime_error("one or both teams have no players");
throw std::runtime_error("one or both teams have no players");
}
this->first_team_turn = 0xFF;
while (this->first_team_turn == 0xFF) {
@@ -927,7 +926,7 @@ void Server::end_action_phase() {
bool Server::enqueue_attack_or_defense(uint8_t client_id, ActionState* pa) {
auto log = this->log_stack("enqueue_attack_or_defense: ");
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string s = pa->str(this->shared_from_this());
std::string s = pa->str(this->shared_from_this());
log.debug_f("input: {}", s);
}
@@ -977,8 +976,8 @@ bool Server::enqueue_attack_or_defense(uint8_t client_id, ActionState* pa) {
size_t attack_index = this->num_pending_attacks++;
this->pending_attacks[attack_index] = *pa;
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string pa_str = this->pending_attacks[attack_index].str(this->shared_from_this());
log.debug_f("set pending attack {}: {}", attack_index, pa_str);
log.debug_f("set pending attack {}: {}",
attack_index, this->pending_attacks[attack_index].str(this->shared_from_this()));
}
ps->set_action_cards_for_action_state(*pa);
log.debug_f("set action cards");
@@ -1013,14 +1012,14 @@ uint8_t Server::get_current_team_turn() const {
return this->current_team_turn1;
}
shared_ptr<PlayerState> Server::get_player_state(uint8_t client_id) {
std::shared_ptr<PlayerState> Server::get_player_state(uint8_t client_id) {
if (client_id >= 4) {
return nullptr;
}
return this->player_states[client_id];
}
shared_ptr<const PlayerState> Server::get_player_state(uint8_t client_id) const {
std::shared_ptr<const PlayerState> Server::get_player_state(uint8_t client_id) const {
if (client_id >= 4) {
return nullptr;
}
@@ -1094,19 +1093,19 @@ void Server::move_phase_after() {
continue;
}
static const array<vector<uint16_t>, 5> DEFAULT_TRAP_CARD_IDS = {
static const std::array<std::vector<uint16_t>, 5> DEFAULT_TRAP_CARD_IDS = {
// Red: Dice Fever, Heavy Fog, Muscular, Immortality, Snail Pace
vector<uint16_t>{0x00F7, 0x010F, 0x012E, 0x013B, 0x013C},
std::vector<uint16_t>{0x00F7, 0x010F, 0x012E, 0x013B, 0x013C},
// Blue: Gold Rush, Charity, Requiem
vector<uint16_t>{0x0131, 0x012B, 0x0133},
std::vector<uint16_t>{0x0131, 0x012B, 0x0133},
// Purple: Powerless Rain, Trash 1, Empty Hand, Skip Draw
vector<uint16_t>{0x00FA, 0x0125, 0x0126, 0x0137},
std::vector<uint16_t>{0x00FA, 0x0125, 0x0126, 0x0137},
// Green: Brave Wind, Homesick, Fly
vector<uint16_t>{0x00FB, 0x014E, 0x0107},
std::vector<uint16_t>{0x00FB, 0x014E, 0x0107},
// Yellow: Dice+1, Battle Royale, Reverse Card, Giant Garden, Fix
vector<uint16_t>{0x00F6, 0x0242, 0x014B, 0x0145, 0x012D}};
std::vector<uint16_t>{0x00F6, 0x0242, 0x014B, 0x0145, 0x012D}};
const vector<uint16_t>* trap_card_ids = &this->options.trap_card_ids.at(trap_type);
const std::vector<uint16_t>* trap_card_ids = &this->options.trap_card_ids.at(trap_type);
if (trap_card_ids->empty()) {
trap_card_ids = &DEFAULT_TRAP_CARD_IDS.at(trap_type);
}
@@ -1201,7 +1200,7 @@ int8_t Server::send_6xB4x33_remove_ally_atk_if_needed(const ActionState& pa) {
bool has_ally_cost = false;
uint8_t ally_cost = 0;
uint8_t setter_client_id = 0xFF;
shared_ptr<PlayerState> setter_ps = nullptr;
std::shared_ptr<PlayerState> setter_ps = nullptr;
cmd.card_ref = 0xFFFF;
for (size_t z = 0; (z < 8) && (pa.action_card_refs[z] != 0xFFFF); z++) {
auto ce = this->definition_for_card_ref(pa.action_card_refs[z]);
@@ -1509,7 +1508,7 @@ void Server::setup_and_start_battle() {
this->name_entries[z].clear();
}
} else {
this->player_states[z] = make_shared<PlayerState>(z, this->shared_from_this());
this->player_states[z] = std::make_shared<PlayerState>(z, this->shared_from_this());
this->player_states[z]->init();
}
}
@@ -1523,7 +1522,7 @@ void Server::setup_and_start_battle() {
}
auto card = ps->get_sc_card();
if (card) {
team_hp[ps->get_team_id()] = min<int16_t>(team_hp[ps->get_team_id()], card->get_current_hp());
team_hp[ps->get_team_id()] = std::min<int16_t>(team_hp[ps->get_team_id()], card->get_current_hp());
}
}
@@ -1739,7 +1738,7 @@ bool Server::update_registration_phase() {
return true;
}
const unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
const std::unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
{0x0B, &Server::handle_CAx0B_redraw_initial_hand},
{0x0C, &Server::handle_CAx0C_end_redraw_initial_hand_phase},
{0x0D, &Server::handle_CAx0D_end_non_action_phase},
@@ -1765,23 +1764,23 @@ const unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
{0x49, &Server::handle_CAx49_card_counts},
});
void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& data) {
void Server::on_server_data_input(std::shared_ptr<Client> sender_c, const std::string& data) {
auto header = check_size_t<G_CardBattleCommandHeader>(data, 0xFFFF);
size_t expected_size = header.size * 4;
if (expected_size < data.size()) {
phosg::print_data(stderr, data);
throw runtime_error(std::format(
throw std::runtime_error(std::format(
"command is incomplete: expected {:X} bytes, received {:X} bytes", expected_size, data.size()));
}
if (header.subcommand != 0xB3) {
throw runtime_error("server data command is not 6xB3");
throw std::runtime_error("server data command is not 6xB3");
}
handler_t handler = nullptr;
try {
handler = this->subcommand_handlers.at(header.subsubcommand);
} catch (const out_of_range&) {
throw runtime_error("unknown CAx subsubcommand");
} catch (const std::out_of_range&) {
throw std::runtime_error("unknown CAx subsubcommand");
}
if (this->battle_record && this->battle_record->writable()) {
@@ -1791,17 +1790,17 @@ void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& dat
if ((sender_c && (sender_c->version() == Version::GC_EP3_NTE)) || !header.mask_key) {
(this->*handler)(sender_c, data);
} else {
string unmasked_data = data;
std::string unmasked_data = data;
set_mask_for_ep3_game_command(unmasked_data.data(), unmasked_data.size(), 0);
(this->*handler)(sender_c, unmasked_data);
}
}
void Server::handle_CAx0B_redraw_initial_hand(shared_ptr<Client>, const string& data) {
void Server::handle_CAx0B_redraw_initial_hand(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_RedrawInitialHand_Ep3_CAx0B>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "REDRAW");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
int32_t error_code = 0;
@@ -1829,11 +1828,11 @@ void Server::handle_CAx0B_redraw_initial_hand(shared_ptr<Client>, const string&
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
}
void Server::handle_CAx0C_end_redraw_initial_hand_phase(shared_ptr<Client>, const string& data) {
void Server::handle_CAx0C_end_redraw_initial_hand_phase(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_EndInitialRedrawPhase_Ep3_CAx0C>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "HAND READY");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
int32_t error_code = 0;
@@ -1887,11 +1886,11 @@ void Server::handle_CAx0C_end_redraw_initial_hand_phase(shared_ptr<Client>, cons
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
}
void Server::handle_CAx0D_end_non_action_phase(shared_ptr<Client>, const string& data) {
void Server::handle_CAx0D_end_non_action_phase(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_EndNonAttackPhase_Ep3_CAx0D>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END PHASE");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
if (!this->options.is_nte()) {
@@ -1909,11 +1908,11 @@ void Server::handle_CAx0D_end_non_action_phase(shared_ptr<Client>, const string&
this->send(out_cmd_fin);
}
void Server::handle_CAx0E_discard_card_from_hand(shared_ptr<Client>, const string& data) {
void Server::handle_CAx0E_discard_card_from_hand(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_DiscardCardFromHand_Ep3_CAx0E>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "DISCARD");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
int32_t error_code = 0;
@@ -1948,11 +1947,11 @@ void Server::handle_CAx0E_discard_card_from_hand(shared_ptr<Client>, const strin
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
}
void Server::handle_CAx0F_set_card_from_hand(shared_ptr<Client>, const string& data) {
void Server::handle_CAx0F_set_card_from_hand(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_SetCardFromHand_Ep3_CAx0F>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "SET FC");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
int32_t error_code = 0;
@@ -1994,11 +1993,11 @@ void Server::handle_CAx0F_set_card_from_hand(shared_ptr<Client>, const string& d
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, this->ruler_server->error_code1);
}
void Server::handle_CAx10_move_fc_to_location(shared_ptr<Client>, const string& data) {
void Server::handle_CAx10_move_fc_to_location(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_MoveFieldCharacter_Ep3_CAx10>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "MOVE");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
int32_t error_code = 0;
@@ -2034,11 +2033,11 @@ void Server::handle_CAx10_move_fc_to_location(shared_ptr<Client>, const string&
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, this->ruler_server->error_code2);
}
void Server::handle_CAx11_enqueue_attack_or_defense(shared_ptr<Client>, const string& data) {
void Server::handle_CAx11_enqueue_attack_or_defense(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_EnqueueAttackOrDefense_Ep3_CAx11>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "ENQUEUE ACT");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
int32_t error_code = 0;
@@ -2072,11 +2071,11 @@ void Server::handle_CAx11_enqueue_attack_or_defense(shared_ptr<Client>, const st
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, this->ruler_server->error_code3);
}
void Server::handle_CAx12_end_attack_list(shared_ptr<Client>, const string& data) {
void Server::handle_CAx12_end_attack_list(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_EndAttackList_Ep3_CAx12>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END ATK LIST");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
int32_t error_code = 0;
@@ -2097,7 +2096,7 @@ void Server::handle_CAx12_end_attack_list(shared_ptr<Client>, const string& data
}
template <typename CmdT>
void Server::handle_CAx13_update_map_during_setup_t(shared_ptr<Client> c, const string& data) {
void Server::handle_CAx13_update_map_during_setup_t(std::shared_ptr<Client> c, const std::string& data) {
const auto& in_cmd = check_size_t<CmdT>(data);
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "UPDATE MAP");
@@ -2157,7 +2156,7 @@ void Server::handle_CAx13_update_map_during_setup_t(shared_ptr<Client> c, const
}
}
void Server::handle_CAx13_update_map_during_setup(shared_ptr<Client> c, const string& data) {
void Server::handle_CAx13_update_map_during_setup(std::shared_ptr<Client> c, const std::string& data) {
if (this->options.is_nte()) {
this->handle_CAx13_update_map_during_setup_t<G_SetMapState_Ep3NTE_CAx13>(c, data);
} else {
@@ -2165,7 +2164,7 @@ void Server::handle_CAx13_update_map_during_setup(shared_ptr<Client> c, const st
}
}
void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const string& data) {
void Server::handle_CAx14_update_deck_during_setup(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_SetPlayerDeck_Ep3_CAx14>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "UPDATE DECK");
@@ -2188,7 +2187,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
}
}
if (verify_error) {
throw runtime_error(std::format("invalid deck: -0x{:X}", verify_error));
throw std::runtime_error(std::format("invalid deck: -0x{:X}", verify_error));
}
if (!this->options.is_nte() && !(this->options.behavior_flags & BehaviorFlag::SKIP_D1_D2_REPLACE)) {
this->ruler_server->replace_D1_D2_rank_cards_with_Attack(entry.card_ids);
@@ -2211,7 +2210,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
}
}
void Server::handle_CAx15_unused_hard_reset_server_state(shared_ptr<Client>, const string& data) {
void Server::handle_CAx15_unused_hard_reset_server_state(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_HardResetServerState_Ep3_CAx15>(data);
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "HARD RESET");
@@ -2224,10 +2223,10 @@ void Server::handle_CAx15_unused_hard_reset_server_state(shared_ptr<Client>, con
// this->send_all_state_updates();
// this->update_registration_phase();
// this->setup_and_start_battle();
throw runtime_error("hard reset command received");
throw std::runtime_error("hard reset command received");
}
void Server::handle_CAx1B_update_player_name(shared_ptr<Client>, const string& data) {
void Server::handle_CAx1B_update_player_name(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_SetPlayerName_Ep3_CAx1B>(data);
this->send_debug_command_received_message(in_cmd.entry.client_id, in_cmd.header.subsubcommand, "UPDATE NAME");
@@ -2258,7 +2257,7 @@ void Server::handle_CAx1B_update_player_name(shared_ptr<Client>, const string& d
this->send(out_cmd);
}
void Server::handle_CAx1D_start_battle(shared_ptr<Client>, const string& data) {
void Server::handle_CAx1D_start_battle(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_StartBattle_Ep3_CAx1D>(data);
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "START BATTLE");
@@ -2304,7 +2303,7 @@ void Server::handle_CAx1D_start_battle(shared_ptr<Client>, const string& data) {
}
}
void Server::handle_CAx21_end_battle(shared_ptr<Client>, const string& data) {
void Server::handle_CAx21_end_battle(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_EndBattle_Ep3_CAx21>(data);
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "END BATTLE");
if (this->setup_phase == SetupPhase::BATTLE_ENDED) {
@@ -2318,11 +2317,11 @@ void Server::handle_CAx21_end_battle(shared_ptr<Client>, const string& data) {
}
}
void Server::handle_CAx28_end_defense_list(shared_ptr<Client>, const string& data) {
void Server::handle_CAx28_end_defense_list(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_EndDefenseList_Ep3_CAx28>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END DEF LIST");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
G_ActionResult_Ep3_6xB4x1E out_cmd_ack;
@@ -2369,13 +2368,13 @@ void Server::handle_CAx28_end_defense_list(shared_ptr<Client>, const string& dat
this->send(out_cmd_fin);
}
void Server::handle_CAx2B_legacy_set_card(shared_ptr<Client>, const string& data) {
void Server::handle_CAx2B_legacy_set_card(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_ExecLegacyCard_Ep3_CAx2B>(data);
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "EXEC LEGACY");
// Sega's original implementation does nothing here, so we do nothing as well.
}
void Server::handle_CAx34_subtract_ally_atk_points(shared_ptr<Client>, const string& data) {
void Server::handle_CAx34_subtract_ally_atk_points(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_PhotonBlastRequest_Ep3_CAx34>(data);
uint8_t card_ref_client_id = client_id_for_card_ref(in_cmd.card_ref);
@@ -2450,11 +2449,11 @@ void Server::handle_CAx34_subtract_ally_atk_points(shared_ptr<Client>, const str
}
}
void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(shared_ptr<Client>, const string& data) {
void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_AdvanceFromStartingRollsPhase_Ep3_CAx37>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "CHOOSE ORDER");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
auto ps = this->player_states[in_cmd.client_id];
@@ -2479,19 +2478,19 @@ void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(shared
}
}
void Server::handle_CAx3A_time_limit_expired(shared_ptr<Client>, const string& data) {
void Server::handle_CAx3A_time_limit_expired(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_OverallTimeLimitExpired_Ep3_CAx3A>(data);
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "TIME EXPIRED");
// We don't need to do anything here because the overall time limit is tracked server-side instead.
}
void Server::handle_CAx40_map_list_request(shared_ptr<Client> sender_c, const string& data) {
void Server::handle_CAx40_map_list_request(std::shared_ptr<Client> sender_c, const std::string& data) {
const auto& in_cmd = check_size_t<G_MapListRequest_Ep3_CAx40>(data);
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "MAP LIST");
auto l = this->lobby.lock();
if (!l) {
throw runtime_error("lobby is deleted");
throw std::runtime_error("lobby is deleted");
}
size_t num_players = l ? l->count_clients() : 1;
@@ -2512,13 +2511,13 @@ void Server::handle_CAx40_map_list_request(shared_ptr<Client> sender_c, const st
void Server::send_6xB6x41_to_all_clients() const {
if (!this->last_chosen_map) {
throw logic_error("cannot send 6xB4x41 without a map chosen");
throw std::logic_error("cannot send 6xB4x41 without a map chosen");
}
auto l = this->lobby.lock();
if (l) {
vector<string> map_commands_by_language;
auto send_to_client = [&](shared_ptr<Client> c) -> void {
std::vector<std::string> map_commands_by_language;
auto send_to_client = [&](std::shared_ptr<Client> c) -> void {
if (!c) {
return;
}
@@ -2545,7 +2544,7 @@ void Server::send_6xB6x41_to_all_clients() const {
if (this->battle_record && this->battle_record->writable()) {
// TODO: It's not great that we just pick the first one; ideally we'd put all of them in the recording and send
// the appropriate one to the client in the playback lobby
for (string& data : map_commands_by_language) {
for (std::string& data : map_commands_by_language) {
if (!data.empty()) {
this->battle_record->add_command(BattleRecord::Event::Type::BATTLE_COMMAND, std::move(data));
break;
@@ -2559,7 +2558,7 @@ void Server::send_6xB6x41_to_all_clients() const {
}
}
void Server::handle_CAx41_map_request(shared_ptr<Client>, const string& data) {
void Server::handle_CAx41_map_request(std::shared_ptr<Client>, const std::string& data) {
const auto& cmd = check_size_t<G_MapDataRequest_Ep3_CAx41>(data);
this->send_debug_command_received_message(cmd.header.subsubcommand, "MAP DATA");
if (!this->options.tournament || (this->options.tournament->get_map()->map_number == cmd.map_number)) {
@@ -2568,11 +2567,11 @@ void Server::handle_CAx41_map_request(shared_ptr<Client>, const string& data) {
}
}
void Server::handle_CAx48_end_turn(shared_ptr<Client>, const string& data) {
void Server::handle_CAx48_end_turn(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_EndTurn_Ep3_CAx48>(data);
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END TURN");
if (in_cmd.client_id >= 4) {
throw runtime_error("invalid client ID");
throw std::runtime_error("invalid client ID");
}
auto ps = this->get_player_state(in_cmd.client_id);
@@ -2585,7 +2584,7 @@ void Server::handle_CAx48_end_turn(shared_ptr<Client>, const string& data) {
this->send(out_cmd);
}
void Server::handle_CAx49_card_counts(shared_ptr<Client>, const string& data) {
void Server::handle_CAx49_card_counts(std::shared_ptr<Client>, const std::string& data) {
const auto& in_cmd = check_size_t<G_CardCounts_Ep3_CAx49>(data);
this->send_debug_command_received_message(in_cmd.header.sender_client_id, in_cmd.header.subsubcommand, "CARD COUNTS");
@@ -2612,7 +2611,7 @@ void Server::compute_losing_team_id_and_add_winner_flags(uint32_t flags) {
uint32_t winner_flags = flags | AssistFlag::HAS_WON_BATTLE | AssistFlag::WINNER_DECIDED_BY_DEFEAT;
int8_t losing_team_id = -1;
array<uint32_t, 2> team_counts = {0, 0};
std::array<uint32_t, 2> team_counts{0, 0};
if (!is_nte) {
// First, check which team has more dead SCs
@@ -2747,8 +2746,7 @@ void Server::unknown_8023EEF4() {
ActionState as = this->pending_attacks_with_cards[this->unknown_a14];
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
log.debug_f("card @{:04X} #{:04X} can attack", card->get_card_ref(), card->get_card_id());
string as_str = as.str(this->shared_from_this());
log.debug_f("as: {}", as_str);
log.debug_f("as: {}", as.str(this->shared_from_this()));
}
if (is_nte) {
this->replace_targets_due_to_destruction_nte(&as);
@@ -2756,8 +2754,7 @@ void Server::unknown_8023EEF4() {
this->replace_targets_due_to_destruction_or_conditions(&as);
}
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
string as_str = as.str(this->shared_from_this());
log.debug_f("as after target replacement: {}", as_str);
log.debug_f("as after target replacement: {}", as.str(this->shared_from_this()));
}
if (this->any_target_exists_for_attack(as)) {
log.debug_f("as is valid");
@@ -2837,8 +2834,8 @@ void Server::execute_bomb_assist_effect() {
for (size_t set_index = 0; set_index < 8; set_index++) {
auto card = ps->get_set_card(set_index);
if (card && !(card->card_flags & 2)) {
max_hp = max<int16_t>(max_hp, card->get_current_hp());
min_hp = min<int16_t>(min_hp, card->get_current_hp());
max_hp = std::max<int16_t>(max_hp, card->get_current_hp());
min_hp = std::min<int16_t>(min_hp, card->get_current_hp());
}
}
}
@@ -2875,7 +2872,7 @@ void Server::replace_targets_due_to_destruction_nte(ActionState* as) {
continue;
}
auto ps = target_card->player_state();
shared_ptr<Card> found_guard_item;
std::shared_ptr<Card> found_guard_item;
for (size_t z = 0; z < 8; z++) {
auto set_card = ps->get_set_card(z);
if (set_card && (set_card != target_card) && !(set_card->card_flags & 2) && set_card->is_guard_item()) {
@@ -2915,7 +2912,7 @@ void Server::replace_targets_due_to_destruction_or_conditions(ActionState* as) {
return;
}
vector<uint16_t> phase1_replaced_card_refs;
std::vector<uint16_t> phase1_replaced_card_refs;
for (size_t client_id = 0; client_id < 4; client_id++) {
auto ps = this->get_player_state(client_id);
if (!attacker_card->action_chain.check_flag(0x200 << client_id)) {
@@ -3005,7 +3002,7 @@ void Server::replace_targets_due_to_destruction_or_conditions(ActionState* as) {
}
// as->target_card_refs[phase1_replaced_card_refs.size()] = 0xFFFF;
vector<uint16_t> phase2_replaced_card_refs;
std::vector<uint16_t> phase2_replaced_card_refs;
for (size_t z = 0; (z < 4 * 9) && (as->target_card_refs[z] != 0xFFFF); z++) {
uint16_t target_card_ref = this->send_6xB4x06_if_card_ref_invalid(as->target_card_refs[z], 7);
auto target_card = this->card_for_set_card_ref(target_card_ref);
@@ -3105,13 +3102,14 @@ void Server::unknown_802402F4() {
}
}
vector<shared_ptr<Card>> Server::const_cast_set_cards_v(const vector<shared_ptr<const Card>>& cards) {
std::vector<std::shared_ptr<Card>> Server::const_cast_set_cards_v(
const std::vector<std::shared_ptr<const Card>>& cards) {
// TODO: This is dumb. Figure out a not-dumb way to do this.
vector<shared_ptr<Card>> ret;
std::vector<std::shared_ptr<Card>> ret;
for (auto const_card : cards) {
auto mutable_card = this->card_for_set_card_ref(const_card->get_card_ref());
if (mutable_card.get() != const_card.get()) {
throw logic_error("inconsistent set cards index");
throw std::logic_error("inconsistent set cards index");
}
ret.emplace_back(mutable_card);
}
+1 -1
View File
@@ -37,7 +37,7 @@ namespace Episode3 {
// RulerServer.hh/cc
// Server.hh/cc
// Class ownership levels (classes may contain weak_ptrs but not shared_ptrs to classes at the same or higher level):
// Class ownership levels (classes may contain weak_ptrs but not std::shared_ptrs to classes at the same or higher level):
// - Server
// - - RulerServer
// - - - AssistServer
+99 -115
View File
@@ -7,23 +7,18 @@
#include "../SendCommands.hh"
#include "../ServerState.hh"
using namespace std;
namespace Episode3 {
Tournament::PlayerEntry::PlayerEntry(uint32_t account_id, const string& player_name)
: account_id(account_id),
player_name(player_name) {}
Tournament::PlayerEntry::PlayerEntry(uint32_t account_id, const std::string& player_name)
: account_id(account_id), player_name(player_name) {}
Tournament::PlayerEntry::PlayerEntry(shared_ptr<Client> c)
Tournament::PlayerEntry::PlayerEntry(std::shared_ptr<Client> c)
: account_id(c->login->account->account_id),
client(c),
player_name(c->character_file()->disp.name.decode(c->language())) {}
Tournament::PlayerEntry::PlayerEntry(
shared_ptr<const COMDeckDefinition> com_deck)
: account_id(0),
com_deck(com_deck) {}
Tournament::PlayerEntry::PlayerEntry(std::shared_ptr<const COMDeckDefinition> com_deck)
: account_id(0), com_deck(com_deck) {}
bool Tournament::PlayerEntry::is_com() const {
return (this->com_deck != nullptr);
@@ -33,8 +28,7 @@ bool Tournament::PlayerEntry::is_human() const {
return (this->account_id != 0);
}
Tournament::Team::Team(
shared_ptr<Tournament> tournament, size_t index, size_t max_players)
Tournament::Team::Team(std::shared_ptr<Tournament> tournament, size_t index, size_t max_players)
: tournament(tournament),
index(index),
max_players(max_players),
@@ -43,7 +37,7 @@ Tournament::Team::Team(
num_rounds_cleared(0),
is_active(true) {}
string Tournament::Team::str() const {
std::string Tournament::Team::str() const {
size_t num_human_players = 0;
size_t num_com_players = 0;
for (const auto& player : this->players) {
@@ -51,7 +45,7 @@ string Tournament::Team::str() const {
num_com_players += player.is_com();
}
string ret = std::format("[Team/{} {} {}H/{}C/{}P name={} pass={} rounds={}",
std::string ret = std::format("[Team/{} {} {}H/{}C/{}P name={} pass={} rounds={}",
this->index, this->is_active ? "active" : "inactive",
num_human_players, num_com_players, this->max_players, this->name,
this->password, this->num_rounds_cleared);
@@ -67,26 +61,27 @@ string Tournament::Team::str() const {
return ret + "]";
}
void Tournament::Team::register_player(shared_ptr<Client> c, const string& team_name, const string& password) {
void Tournament::Team::register_player(
std::shared_ptr<Client> c, const std::string& team_name, const std::string& password) {
if (this->players.size() >= this->max_players) {
throw runtime_error("team is full");
throw std::runtime_error("team is full");
}
if (!this->name.empty() && (password != this->password)) {
throw runtime_error("incorrect password");
throw std::runtime_error("incorrect password");
}
auto tournament = this->tournament.lock();
if (!tournament) {
throw runtime_error("tournament has been deleted");
throw std::runtime_error("tournament has been deleted");
}
if (!tournament->all_player_account_ids.emplace(c->login->account->account_id).second) {
throw runtime_error("player already registered in same tournament");
throw std::runtime_error("player already registered in same tournament");
}
for (const auto& player : this->players) {
if (player.is_human() && (player.account_id == c->login->account->account_id)) {
throw logic_error("player already registered in team but not in tournament");
throw std::logic_error("player already registered in team but not in tournament");
}
}
@@ -125,7 +120,7 @@ bool Tournament::Team::unregister_player(uint32_t account_id) {
// Look through the pending matches to see if this team is involved in any of them
for (auto match : tournament->pending_matches) {
if (!match->preceding_a || !match->preceding_b) {
throw logic_error("zero-round match is pending after tournament registration phase");
throw std::logic_error("zero-round match is pending after tournament registration phase");
}
if (match->preceding_a->winner_team.get() == this) {
match->set_winner_team(match->preceding_b->winner_team);
@@ -139,7 +134,7 @@ bool Tournament::Team::unregister_player(uint32_t account_id) {
} else {
// If the tournament has not started yet, just remove the player from the team
if (!tournament->all_player_account_ids.erase(account_id)) {
throw logic_error("player removed from team but not from tournament");
throw std::logic_error("player removed from team but not from tournament");
}
}
@@ -176,27 +171,19 @@ size_t Tournament::Team::num_com_players() const {
}
Tournament::Match::Match(
shared_ptr<Tournament> tournament, shared_ptr<Match> preceding_a, shared_ptr<Match> preceding_b)
: tournament(tournament),
preceding_a(preceding_a),
preceding_b(preceding_b),
winner_team(nullptr),
round_num(0) {
std::shared_ptr<Tournament> tournament, std::shared_ptr<Match> preceding_a, std::shared_ptr<Match> preceding_b)
: tournament(tournament), preceding_a(preceding_a), preceding_b(preceding_b), winner_team(nullptr), round_num(0) {
if (this->preceding_a->round_num != this->preceding_b->round_num) {
throw logic_error("preceding matches have different round numbers");
throw std::logic_error("preceding matches have different round numbers");
}
this->round_num = this->preceding_a->round_num + 1;
}
Tournament::Match::Match(shared_ptr<Tournament> tournament, shared_ptr<Team> winner_team)
: tournament(tournament),
preceding_a(nullptr),
preceding_b(nullptr),
winner_team(winner_team),
round_num(0) {}
Tournament::Match::Match(std::shared_ptr<Tournament> tournament, std::shared_ptr<Team> winner_team)
: tournament(tournament), preceding_a(nullptr), preceding_b(nullptr), winner_team(winner_team), round_num(0) {}
string Tournament::Match::str() const {
string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
std::string Tournament::Match::str() const {
std::string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
return std::format("[Match round={} winner={}]", this->round_num, winner_str);
}
@@ -262,12 +249,12 @@ void Tournament::Match::on_winner_team_set() {
}
}
void Tournament::Match::set_winner_team_without_triggers(shared_ptr<Team> team) {
void Tournament::Match::set_winner_team_without_triggers(std::shared_ptr<Team> team) {
if (!this->preceding_a || !this->preceding_b) {
throw logic_error("set_winner_team called on zero-round match");
throw std::logic_error("set_winner_team called on zero-round match");
}
if ((team != this->preceding_a->winner_team) && (team != this->preceding_b->winner_team)) {
throw logic_error("winner team did not participate in match");
throw std::logic_error("winner team did not participate in match");
}
this->winner_team = team;
@@ -280,29 +267,29 @@ void Tournament::Match::set_winner_team_without_triggers(shared_ptr<Team> team)
}
}
void Tournament::Match::set_winner_team(shared_ptr<Team> team) {
void Tournament::Match::set_winner_team(std::shared_ptr<Team> team) {
this->set_winner_team_without_triggers(team);
this->on_winner_team_set();
}
shared_ptr<Tournament::Team> Tournament::Match::opponent_team_for_team(shared_ptr<Team> team) const {
std::shared_ptr<Tournament::Team> Tournament::Match::opponent_team_for_team(std::shared_ptr<Team> team) const {
if (!this->preceding_a || !this->preceding_b) {
throw logic_error("zero-round matches do not have opponents");
throw std::logic_error("zero-round matches do not have opponents");
}
if (team == this->preceding_a->winner_team) {
return this->preceding_b->winner_team;
} else if (team == this->preceding_b->winner_team) {
return this->preceding_a->winner_team;
} else {
throw logic_error("team is not registered for this match");
throw std::logic_error("team is not registered for this match");
}
}
Tournament::Tournament(
shared_ptr<const MapIndex> map_index,
shared_ptr<const COMDeckIndex> com_deck_index,
const string& name,
shared_ptr<const MapIndex::Map> map,
std::shared_ptr<const MapIndex> map_index,
std::shared_ptr<const COMDeckIndex> com_deck_index,
const std::string& name,
std::shared_ptr<const MapIndex::Map> map,
const Rules& rules,
size_t num_teams,
uint8_t flags)
@@ -317,18 +304,20 @@ Tournament::Tournament(
current_state(State::REGISTRATION),
menu_item_id(0xFFFFFFFF) {
if (this->num_teams < 4) {
throw invalid_argument("team count must be 4 or more");
throw std::invalid_argument("team count must be 4 or more");
}
if (this->num_teams > 32) {
throw invalid_argument("team count must be 32 or fewer");
throw std::invalid_argument("team count must be 32 or fewer");
}
if (this->num_teams & (this->num_teams - 1)) {
throw invalid_argument("team count must be a power of 2");
throw std::invalid_argument("team count must be a power of 2");
}
}
Tournament::Tournament(
shared_ptr<const MapIndex> map_index, shared_ptr<const COMDeckIndex> com_deck_index, const phosg::JSON& json)
std::shared_ptr<const MapIndex> map_index,
std::shared_ptr<const COMDeckIndex> com_deck_index,
const phosg::JSON& json)
: log(std::format("[Tournament:{}] ", json.get_string("name"))),
map_index(map_index),
com_deck_index(com_deck_index),
@@ -336,7 +325,7 @@ Tournament::Tournament(
current_state(State::REGISTRATION) {}
void Tournament::init() {
vector<size_t> team_index_to_rounds_cleared;
std::vector<size_t> team_index_to_rounds_cleared;
bool is_registration_complete;
if (!this->source_json.is_null()) {
@@ -350,7 +339,7 @@ void Tournament::init() {
is_registration_complete = this->source_json.get_bool("is_registration_complete");
for (const auto& team_json : this->source_json.get_list("teams")) {
auto& team = this->teams.emplace_back(make_shared<Team>(
auto& team = this->teams.emplace_back(std::make_shared<Team>(
this->shared_from_this(), this->teams.size(), team_json->get_int("max_players")));
team->name = team_json->get_string("name");
team->password = team_json->get_string("password");
@@ -367,7 +356,7 @@ void Tournament::init() {
} else if (player_json->is_string()) {
team->players.emplace_back(this->com_deck_index->deck_for_name(player_json->as_string()));
} else {
throw runtime_error("invalid player spec");
throw std::runtime_error("invalid player spec");
}
}
}
@@ -378,7 +367,7 @@ void Tournament::init() {
} else {
// Create empty teams
while (this->teams.size() < this->num_teams) {
auto t = make_shared<Team>(this->shared_from_this(), this->teams.size(), (this->flags & Flag::IS_2V2) ? 2 : 1);
auto t = std::make_shared<Team>(this->shared_from_this(), this->teams.size(), (this->flags & Flag::IS_2V2) ? 2 : 1);
this->teams.emplace_back(t);
}
is_registration_complete = false;
@@ -390,12 +379,12 @@ void Tournament::init() {
this->create_bracket_matches();
// Start with all zero-round matches in the match queue
unordered_set<shared_ptr<Match>> match_queue;
std::unordered_set<std::shared_ptr<Match>> match_queue;
for (auto match : this->zero_round_matches) {
match_queue.emplace(match->following.lock());
}
if (match_queue.count(nullptr)) {
throw logic_error("null match in match queue");
throw std::logic_error("null match in match queue");
}
// For each match in the queue, either resolve it from the previous state or
@@ -406,12 +395,12 @@ void Tournament::init() {
match_queue.erase(match_it);
if (!match->preceding_a->winner_team || !match->preceding_b->winner_team) {
throw logic_error("preceding matches are not resolved");
throw std::logic_error("preceding matches are not resolved");
}
size_t& a_rounds_cleared = team_index_to_rounds_cleared[match->preceding_a->winner_team->index];
size_t& b_rounds_cleared = team_index_to_rounds_cleared[match->preceding_b->winner_team->index];
if (a_rounds_cleared && b_rounds_cleared) {
throw runtime_error("both teams won the same match");
throw std::runtime_error("both teams won the same match");
}
if (!a_rounds_cleared && !b_rounds_cleared) {
this->pending_matches.emplace(match); // Neither team has won yet
@@ -434,7 +423,7 @@ void Tournament::init() {
}
if (!this->final_match->winner_team == this->pending_matches.empty()) {
throw logic_error("there must be pending matches if and only if the final match is not resolved");
throw std::logic_error("there must be pending matches if and only if the final match is not resolved");
}
// If all matches are resolved, then the tournament is complete
@@ -449,19 +438,19 @@ void Tournament::init() {
void Tournament::create_bracket_matches() {
if (this->teams.size() < 4) {
throw logic_error("tournaments must have at least 4 teams");
throw std::logic_error("tournaments must have at least 4 teams");
}
if (this->teams.size() > 32) {
throw logic_error("tournaments must have at most 32 teams");
throw std::logic_error("tournaments must have at most 32 teams");
}
if (this->teams.size() & (this->teams.size() - 1)) {
throw logic_error("tournaments team count is not a power of 2");
throw std::logic_error("tournaments team count is not a power of 2");
}
// Create the zero-round matches, and make them all pending if registration is still open
this->zero_round_matches.clear();
for (const auto& team : this->teams) {
auto m = make_shared<Match>(this->shared_from_this(), team);
auto m = std::make_shared<Match>(this->shared_from_this(), team);
this->zero_round_matches.emplace_back(m);
if (this->current_state == State::REGISTRATION) {
this->pending_matches.emplace(m);
@@ -469,11 +458,11 @@ void Tournament::create_bracket_matches() {
}
// Create the bracket matches
vector<shared_ptr<Match>> current_round_matches = this->zero_round_matches;
std::vector<std::shared_ptr<Match>> current_round_matches = this->zero_round_matches;
while (current_round_matches.size() > 1) {
vector<shared_ptr<Match>> next_round_matches;
std::vector<std::shared_ptr<Match>> next_round_matches;
for (size_t z = 0; z < current_round_matches.size(); z += 2) {
auto m = make_shared<Match>(this->shared_from_this(), current_round_matches[z], current_round_matches[z + 1]);
auto m = std::make_shared<Match>(this->shared_from_this(), current_round_matches[z], current_round_matches[z + 1]);
current_round_matches[z]->following = m;
current_round_matches[z + 1]->following = m;
next_round_matches.emplace_back(std::move(m));
@@ -516,26 +505,26 @@ phosg::JSON Tournament::json() const {
});
}
shared_ptr<Tournament::Team> Tournament::get_winner_team() const {
std::shared_ptr<Tournament::Team> Tournament::get_winner_team() const {
if (this->current_state != State::COMPLETE) {
return nullptr;
}
if (!this->final_match) {
throw logic_error("tournament is complete but final match is missing");
throw std::logic_error("tournament is complete but final match is missing");
}
if (!this->final_match->winner_team) {
throw logic_error("tournament is complete but winner is not set");
throw std::logic_error("tournament is complete but winner is not set");
}
return this->final_match->winner_team;
}
shared_ptr<Tournament::Match> Tournament::next_match_for_team(shared_ptr<Team> team) const {
std::shared_ptr<Tournament::Match> Tournament::next_match_for_team(std::shared_ptr<Team> team) const {
if (this->current_state == Tournament::State::REGISTRATION) {
return nullptr;
}
for (auto match : this->pending_matches) {
if (!match->preceding_a || !match->preceding_b) {
throw logic_error("zero-round match is pending after tournament registration phase");
throw std::logic_error("zero-round match is pending after tournament registration phase");
}
if ((team == match->preceding_a->winner_team) || (team == match->preceding_b->winner_team)) {
return match;
@@ -544,11 +533,11 @@ shared_ptr<Tournament::Match> Tournament::next_match_for_team(shared_ptr<Team> t
return nullptr;
}
shared_ptr<Tournament::Match> Tournament::get_final_match() const {
std::shared_ptr<Tournament::Match> Tournament::get_final_match() const {
return this->final_match;
}
shared_ptr<Tournament::Team> Tournament::team_for_account_id(uint32_t account_id) const {
std::shared_ptr<Tournament::Team> Tournament::team_for_account_id(uint32_t account_id) const {
if (!this->all_player_account_ids.count(account_id)) {
return nullptr;
}
@@ -561,16 +550,16 @@ shared_ptr<Tournament::Team> Tournament::team_for_account_id(uint32_t account_id
}
}
throw logic_error("account ID registered in tournament but not in any team");
throw std::logic_error("account ID registered in tournament but not in any team");
}
const set<uint32_t>& Tournament::get_all_player_account_ids() const {
const std::set<uint32_t>& Tournament::get_all_player_account_ids() const {
return this->all_player_account_ids;
}
void Tournament::start() {
if (this->current_state != State::REGISTRATION) {
throw runtime_error("tournament has already started");
throw std::runtime_error("tournament has already started");
}
bool has_com_teams = (this->flags & Flag::HAS_COM_TEAMS);
@@ -584,7 +573,7 @@ void Tournament::start() {
}
}
if (num_human_teams < (has_com_teams ? 1 : 2)) {
throw runtime_error("not enough registrants to start tournament");
throw std::runtime_error("not enough registrants to start tournament");
}
if ((this->flags & Flag::SHUFFLE_ENTRIES) && (this->flags & Flag::RESIZE_ON_START)) {
@@ -642,11 +631,11 @@ void Tournament::start() {
}
for (const auto& player : t->players) {
if (player.is_com()) {
throw logic_error("non-human player on team before tournament start");
throw std::logic_error("non-human player on team before tournament start");
}
}
if (this->com_deck_index->num_decks() < t->max_players - t->players.size()) {
throw runtime_error("not enough COM decks to complete team");
throw std::runtime_error("not enough COM decks to complete team");
}
// If we allow all-COM teams, or this is a 2v2 tournament and the team has only one human on it, add a COM
if (has_com_teams || !t->players.empty()) {
@@ -687,10 +676,10 @@ void Tournament::send_all_state_updates_on_deletion() const {
}
}
string Tournament::bracket_str() const {
string ret = std::format("Tournament \"{}\"\n", this->name);
std::string Tournament::bracket_str() const {
std::string ret = std::format("Tournament \"{}\"\n", this->name);
function<void(shared_ptr<Match>, size_t)> add_match = [&](shared_ptr<Match> m, size_t indent_level) -> void {
std::function<void(std::shared_ptr<Match>, size_t)> add_match = [&](std::shared_ptr<Match> m, size_t indent_level) -> void {
ret.append(2 * indent_level, ' ');
ret += m->str();
if (this->pending_matches.count(m)) {
@@ -707,13 +696,12 @@ string Tournament::bracket_str() const {
auto en_vm = this->map->version(Language::ENGLISH);
if (en_vm) {
string map_name = en_vm->map->name.decode(en_vm->language);
std::string map_name = en_vm->map->name.decode(en_vm->language);
ret += std::format(" Map: {:08X} ({})\n", this->map->map_number, map_name);
} else {
ret += std::format(" Map: {:08X}\n", this->map->map_number);
}
string rules_str = this->rules.str();
ret += std::format(" Rules: {}\n", rules_str);
ret += std::format(" Rules: {}\n", this->rules.str());
ret += std::format(" Structure: {}, {} entries\n", (this->flags & Flag::IS_2V2) ? "2v2" : "1v1", this->num_teams);
ret += std::format(" COM teams: {}\n", (this->flags & Flag::HAS_COM_TEAMS) ? "allowed" : "forbidden");
ret += std::format(" Shuffle entries: {}\n", (this->flags & Flag::SHUFFLE_ENTRIES) ? "yes" : "no");
@@ -739,14 +727,12 @@ string Tournament::bracket_str() const {
if (this->current_state == State::REGISTRATION) {
ret += " Teams:\n";
for (const auto& team : this->teams) {
string team_str = team->str();
ret += std::format(" {}\n", team_str);
ret += std::format(" {}\n", team->str());
}
} else {
ret += " Pending matches:\n";
for (const auto& match : this->pending_matches) {
string match_str = match->str();
ret += std::format(" {}\n", match_str);
ret += std::format(" {}\n", match->str());
}
}
@@ -755,13 +741,11 @@ string Tournament::bracket_str() const {
}
TournamentIndex::TournamentIndex(
shared_ptr<const MapIndex> map_index,
shared_ptr<const COMDeckIndex> com_deck_index,
const string& state_filename,
std::shared_ptr<const MapIndex> map_index,
std::shared_ptr<const COMDeckIndex> com_deck_index,
const std::string& state_filename,
bool skip_load_state)
: map_index(map_index),
com_deck_index(com_deck_index),
state_filename(state_filename) {
: map_index(map_index), com_deck_index(com_deck_index), state_filename(state_filename) {
if (this->state_filename.empty() || skip_load_state) {
return;
}
@@ -775,14 +759,14 @@ TournamentIndex::TournamentIndex(
if (json.is_list()) {
if (json.size() > 0x20) {
throw runtime_error("tournament phosg::JSON list length is incorrect");
throw std::runtime_error("tournament phosg::JSON list length is incorrect");
}
for (size_t z = 0; z < min<size_t>(json.size(), 0x20); z++) {
for (size_t z = 0; z < std::min<size_t>(json.size(), 0x20); z++) {
if (!json.at(z).is_null()) {
auto tourn = make_shared<Tournament>(this->map_index, this->com_deck_index, json.at(z));
auto tourn = std::make_shared<Tournament>(this->map_index, this->com_deck_index, json.at(z));
tourn->init();
if (!this->name_to_tournament.emplace(tourn->get_name(), tourn).second) {
throw runtime_error("multiple tournaments have the same name: " + tourn->get_name());
throw std::runtime_error("multiple tournaments have the same name: " + tourn->get_name());
}
tourn->set_menu_item_id(this->menu_item_id_to_tournament.size());
this->menu_item_id_to_tournament.emplace_back(tourn);
@@ -790,20 +774,20 @@ TournamentIndex::TournamentIndex(
}
} else if (json.is_dict()) {
if (json.size() > 0x20) {
throw runtime_error("tournament phosg::JSON dict length is incorrect");
throw std::runtime_error("tournament phosg::JSON dict length is incorrect");
}
for (const auto& it : json.as_dict()) {
auto tourn = make_shared<Tournament>(this->map_index, this->com_deck_index, *it.second);
auto tourn = std::make_shared<Tournament>(this->map_index, this->com_deck_index, *it.second);
tourn->init();
if (!this->name_to_tournament.emplace(tourn->get_name(), tourn).second) {
// This is logic_error instead of runtime_error because phosg::JSON dicts already have unique keys
throw logic_error("multiple tournaments have the same name: " + tourn->get_name());
throw std::logic_error("multiple tournaments have the same name: " + tourn->get_name());
}
tourn->set_menu_item_id(this->menu_item_id_to_tournament.size());
this->menu_item_id_to_tournament.emplace_back(tourn);
}
} else {
throw runtime_error("tournament state root phosg::JSON is not a list or dict");
throw std::runtime_error("tournament state root phosg::JSON is not a list or dict");
}
}
@@ -819,20 +803,20 @@ void TournamentIndex::save() const {
phosg::save_file(this->state_filename, json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::HEX_INTEGERS | phosg::JSON::SerializeOption::ESCAPE_CONTROLS_ONLY));
}
shared_ptr<Tournament> TournamentIndex::create_tournament(
const string& name,
shared_ptr<const MapIndex::Map> map,
std::shared_ptr<Tournament> TournamentIndex::create_tournament(
const std::string& name,
std::shared_ptr<const MapIndex::Map> map,
const Rules& rules,
size_t num_teams,
uint8_t flags) {
if (this->name_to_tournament.size() >= 0x20) {
throw runtime_error("there can be at most 32 tournaments at a time");
throw std::runtime_error("there can be at most 32 tournaments at a time");
}
auto t = make_shared<Tournament>(this->map_index, this->com_deck_index, name, map, rules, num_teams, flags);
auto t = std::make_shared<Tournament>(this->map_index, this->com_deck_index, name, map, rules, num_teams, flags);
t->init();
if (!this->name_to_tournament.emplace(t->get_name(), t).second) {
throw runtime_error("a tournament with the same name already exists");
throw std::runtime_error("a tournament with the same name already exists");
}
size_t z;
@@ -852,7 +836,7 @@ shared_ptr<Tournament> TournamentIndex::create_tournament(
return t;
}
bool TournamentIndex::delete_tournament(const string& name) {
bool TournamentIndex::delete_tournament(const std::string& name) {
auto it = this->name_to_tournament.find(name);
if (it == this->name_to_tournament.end()) {
return false;
@@ -869,7 +853,7 @@ bool TournamentIndex::delete_tournament(const string& name) {
return true;
}
shared_ptr<Tournament::Team> TournamentIndex::team_for_account_id(uint32_t account_id) const {
std::shared_ptr<Tournament::Team> TournamentIndex::team_for_account_id(uint32_t account_id) const {
for (const auto& it : this->name_to_tournament) {
const auto& tourn = it.second;
auto team = tourn->team_for_account_id(account_id);
@@ -880,7 +864,7 @@ shared_ptr<Tournament::Team> TournamentIndex::team_for_account_id(uint32_t accou
return nullptr;
}
void TournamentIndex::link_client(shared_ptr<Client> c) {
void TournamentIndex::link_client(std::shared_ptr<Client> c) {
if (!is_ep3(c->version())) {
return;
}
@@ -898,7 +882,7 @@ void TournamentIndex::link_client(shared_ptr<Client> c) {
return;
}
}
throw logic_error("tournament team found for player, but player not found on team");
throw std::logic_error("tournament team found for player, but player not found on team");
} else {
c->ep3_tournament_team.reset();
if (c->version() == Version::GC_EP3) {