don't recreate random state for sequential ep3 battles

This commit is contained in:
Martin Michelsen
2023-06-10 09:53:54 -07:00
parent ee837712aa
commit 0386d14638
9 changed files with 30 additions and 35 deletions
+2 -2
View File
@@ -54,7 +54,7 @@ public:
DeckState(
uint8_t client_id,
const parray<CardIDT, 0x1F>& card_ids,
std::shared_ptr<PSOV2Encryption> random_crypt)
std::shared_ptr<PSOLFGEncryption> random_crypt)
: client_id(client_id),
draw_index(1),
card_ref_base(this->client_id << 8),
@@ -107,7 +107,7 @@ private:
parray<CardEntry, 31> entries;
parray<uint16_t, 31> card_refs;
std::shared_ptr<PSOV2Encryption> random_crypt;
std::shared_ptr<PSOLFGEncryption> random_crypt;
};
} // namespace Episode3
+15 -12
View File
@@ -27,12 +27,12 @@ void ServerBase::PresenceEntry::clear() {
ServerBase::ServerBase(
shared_ptr<Lobby> lobby,
shared_ptr<const DataIndex> data_index,
uint32_t random_seed,
shared_ptr<PSOLFGEncryption> random_crypt,
shared_ptr<const DataIndex::MapEntry> map_if_tournament)
: lobby(lobby),
data_index(data_index),
log(lobby->log.prefix + "[Ep3::Server] "),
random_seed(random_seed),
random_crypt(random_crypt),
is_tournament(!!map_if_tournament),
last_chosen_map(map_if_tournament) {}
@@ -75,6 +75,7 @@ Server::Server(shared_ptr<ServerBase> base)
num_pending_attacks(0),
client_done_enqueuing_attacks(false),
player_ready_to_end_phase(false),
random_crypt(base->random_crypt),
unknown_a10(0),
overall_time_expired(false),
battle_start_usecs(0),
@@ -102,9 +103,12 @@ Server::Server(shared_ptr<ServerBase> base)
void Server::init() {
this->card_special.reset(new CardSpecial(this->shared_from_this()));
// The default PSOV2Encryption constructor in the original implementation just
// uses 0 as the seed. We'll replace this object later when the battle starts.
this->random_crypt.reset(new PSOV2Encryption(0));
// 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.reset(new PSOV2Encryption(0));
this->state_flags.reset(new StateFlags());
this->clear_player_flags_after_dice_phase();
@@ -213,8 +217,7 @@ void Server::send_6xB4x46() const {
G_ServerVersionStrings_GC_Ep3_6xB4x46 cmd46;
cmd46.version_signature = VERSION_SIGNATURE;
cmd46.date_str1 = format_time(this->base()->data_index->card_definitions_mtime() * 1000000);
cmd46.date_str2 = string_printf("Lobby/%08" PRIX32 " random %08" PRIX32,
l->lobby_id, l->random_seed);
cmd46.date_str2 = string_printf("Lobby/%08" PRIX32, l->lobby_id);
this->send(cmd46);
}
@@ -1171,8 +1174,8 @@ void Server::set_client_id_ready_to_advance_phase(uint8_t client_id) {
// TODO: It'd be nice to do this in a constant-randomness way, but I'm
// lazy, and this matches Sega's original implementation. The less-lazy
// way to do it would be to roll three dice: one in the range [1, N],
// one in the range [3, N], and on in the range [1, 2] to decide whether
// to swap the first two results.
// one in the range [3, N], and one in the range [1, 2] to decide
// whether to swap the first two results.
for (size_t z = 0; z < 200; z++) {
ps->roll_main_dice();
if ((ps->get_atk_points() >= 3) || (ps->get_def_points() >= 3)) {
@@ -1302,9 +1305,9 @@ void Server::set_player_deck_valid(uint8_t client_id) {
void Server::setup_and_start_battle() {
this->setup_phase = SetupPhase::STARTER_ROLLS;
// Note: The original implementation uses time() as the random seed; we use a
// user-settable value in order to support replays and deterministic testing
this->random_crypt.reset(new PSOV2Encryption(this->base()->random_seed));
// Note: This is where original implementation re-seeds random_crypt (it uses
// time() as the seed value).
for (size_t z = 0; z < 4; z++) {
if (!this->check_presence_entry(z)) {
+3 -3
View File
@@ -58,7 +58,7 @@ public:
ServerBase(
std::shared_ptr<Lobby> lobby,
std::shared_ptr<const DataIndex> data_index,
uint32_t random_seed,
std::shared_ptr<PSOLFGEncryption> random_crypt,
std::shared_ptr<const DataIndex::MapEntry> map_if_tournament);
void init();
void reset();
@@ -75,7 +75,7 @@ public:
std::weak_ptr<Lobby> lobby;
std::shared_ptr<const DataIndex> data_index;
PrefixedLogger log;
uint32_t random_seed;
std::shared_ptr<PSOLFGEncryption> random_crypt;
bool is_tournament;
std::shared_ptr<const DataIndex::MapEntry> last_chosen_map;
@@ -258,7 +258,7 @@ public:
uint32_t num_pending_attacks;
parray<uint8_t, 4> client_done_enqueuing_attacks;
parray<uint8_t, 4> player_ready_to_end_phase;
std::shared_ptr<PSOV2Encryption> random_crypt;
std::shared_ptr<PSOLFGEncryption> random_crypt;
uint32_t unknown_a10;
uint32_t overall_time_expired;
// Note: In the original implementation, this is a uint32_t and is measured in
-1
View File
@@ -22,7 +22,6 @@ Lobby::Lobby(uint32_t id)
mode(GameMode::NORMAL),
difficulty(0),
random_seed(random_object<uint32_t>()),
random(new mt19937(this->random_seed)),
event(0),
block(0),
type(0),
+1 -1
View File
@@ -72,7 +72,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
std::u16string name;
// This seed is also sent to the client for rare enemy generation
uint32_t random_seed;
std::shared_ptr<std::mt19937> random;
std::shared_ptr<PSOLFGEncryption> random_crypt;
std::shared_ptr<ItemCreator> item_creator;
// Ep3 stuff
+4 -3
View File
@@ -4,6 +4,7 @@
#include <phosg/Strings.hh>
#include "Loggers.hh"
#include "PSOEncryption.hh"
#include "StaticGameData.hh"
using namespace std;
@@ -665,7 +666,7 @@ const vector<vector<AreaMapFileIndex>>& map_file_info_for_episode(Episode ep) {
void generate_variations(
parray<le_uint32_t, 0x20>& variations,
shared_ptr<mt19937> random,
shared_ptr<PSOLFGEncryption> random_crypt,
Episode episode,
bool is_solo) {
const auto& ep_index = map_file_info_for_episode(episode);
@@ -681,8 +682,8 @@ void generate_variations(
variations[z * 2 + 0] = 0;
variations[z * 2 + 1] = 0;
} else {
variations[z * 2 + 0] = (a->variation1_values.size() < 2) ? 0 : ((*random)() % a->variation1_values.size());
variations[z * 2 + 1] = (a->variation2_values.size() < 2) ? 0 : ((*random)() % a->variation2_values.size());
variations[z * 2 + 0] = (a->variation1_values.size() < 2) ? 0 : (random_crypt->next() % a->variation1_values.size());
variations[z * 2 + 1] = (a->variation2_values.size() < 2) ? 0 : (random_crypt->next() % a->variation2_values.size());
}
}
}
+2 -1
View File
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
#include "PSOEncryption.hh"
#include "StaticGameData.hh"
#include "Text.hh"
@@ -117,7 +118,7 @@ private:
void generate_variations(
parray<le_uint32_t, 0x20>& variations,
std::shared_ptr<std::mt19937> random,
std::shared_ptr<PSOLFGEncryption> random,
Episode episode,
bool is_solo);
std::vector<std::string> map_filenames_for_variation(
+3 -4
View File
@@ -1322,7 +1322,7 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
}
auto tourn = l->tournament_match ? l->tournament_match->tournament.lock() : nullptr;
l->ep3_server_base = make_shared<Episode3::ServerBase>(
l, s->ep3_data_index, l->random_seed, tourn ? tourn->get_map() : nullptr);
l, s->ep3_data_index, l->random_crypt, tourn ? tourn->get_map() : nullptr);
l->ep3_server_base->init();
if (s->ep3_behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES) {
@@ -1331,7 +1331,6 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
send_text_message_printf(l->clients[z], "Your client ID: $C6%zu", z);
}
}
send_text_message_printf(l, "State seed: $C6%08" PRIX32, l->random_seed);
}
if (s->ep3_behavior_flags & Episode3::BehaviorFlag::ENABLE_RECORDING) {
@@ -3167,8 +3166,8 @@ shared_ptr<Lobby> create_game_generic(
game->difficulty = difficulty;
if (c->options.override_random_seed >= 0) {
game->random_seed = c->options.override_random_seed;
game->random->seed(game->random_seed);
}
game->random_crypt.reset(new PSOV2Encryption(game->random_seed));
if (battle_player) {
game->battle_player = battle_player;
battle_player->set_lobby(game);
@@ -3204,7 +3203,7 @@ shared_ptr<Lobby> create_game_generic(
if (game->is_ep3() || (c->version() == GameVersion::DC && (c->flags & (Client::Flag::IS_TRIAL_EDITION | Client::Flag::IS_DC_V1_PROTOTYPE)))) {
game->variations.clear(0);
} else {
generate_variations(game->variations, game->random, game->episode, is_solo);
generate_variations(game->variations, game->random_crypt, game->episode, is_solo);
}
if (game->version == GameVersion::BB) {
-8
View File
@@ -3372,10 +3372,6 @@ I 48349 2023-05-26 15:59:20 - [Commands] Sending to C-4 (Tali) (version=GC comma
0010 | 20 63 6C 69 65 6E 74 20 49 44 3A 20 09 43 36 30 | client ID: C60
0020 | 00 00 00 00 |
I 48349 2023-05-26 15:59:20 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
0000 | B0 00 28 00 00 00 00 00 00 00 00 00 53 74 61 74 | ( Stat
0010 | 65 20 73 65 65 64 3A 20 09 43 36 34 34 34 34 34 | e seed: C644444
0020 | 34 34 34 00 00 00 00 00 | 444
I 48349 2023-05-26 15:59:20 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
0000 | B0 00 24 00 00 00 00 00 00 00 00 00 09 43 36 52 | $ C6R
0010 | 65 63 6F 72 64 69 6E 67 20 65 6E 61 62 6C 65 64 | ecording enabled
0020 | 00 00 00 00 |
@@ -25143,10 +25139,6 @@ I 48349 2023-05-26 16:04:46 - [Commands] Sending to C-4 (Tali) (version=GC comma
0010 | 20 63 6C 69 65 6E 74 20 49 44 3A 20 09 43 36 30 | client ID: C60
0020 | 00 00 00 00 |
I 48349 2023-05-26 16:04:46 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
0000 | B0 00 28 00 00 00 00 00 00 00 00 00 53 74 61 74 | ( Stat
0010 | 65 20 73 65 65 64 3A 20 09 43 36 34 34 34 34 34 | e seed: C644444
0020 | 34 34 34 00 00 00 00 00 | 444
I 48349 2023-05-26 16:04:46 - [Commands] Sending to C-4 (Tali) (version=GC command=B0 flag=00)
0000 | B0 00 24 00 00 00 00 00 00 00 00 00 09 43 36 52 | $ C6R
0010 | 65 63 6F 72 64 69 6E 67 20 63 6F 6D 70 6C 65 74 | ecording complet
0020 | 65 00 00 00 | e