diff --git a/hwe/_admin2.php b/hwe/_admin2.php
index 2ccb1358..4281e2eb 100644
--- a/hwe/_admin2.php
+++ b/hwe/_admin2.php
@@ -109,10 +109,6 @@ $db = DB::db();
강제 사망 |
|
-
- | 이벤트 |
- |
-
| 이벤트2 |
|
@@ -121,10 +117,6 @@ $db = DB::db();
접속제한 |
|
-
- | 턴 시각 설정 |
- |
-
| 명령 설정 |
|
diff --git a/hwe/_admin2_submit.php b/hwe/_admin2_submit.php
index 8c9476e8..fb0b717f 100644
--- a/hwe/_admin2_submit.php
+++ b/hwe/_admin2_submit.php
@@ -107,28 +107,6 @@ switch ($btn) {
'arg' => '{}',
'brief' => '휴식',
], 'general_id IN %li AND turn_idx = 0', $genlist);
- break;
- case "특기 부여":
- [$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
- $text = "특기 부여!";
-
- foreach ($db->query("SELECT `no`,leadership,strength,intel,dex1,dex2,dex3,dex4,dex5 FROM general WHERE `no` IN %li", $genlist) as $general) {
- $msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($general['no']), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
- $msg->send(true);
-
- $specialWar = SpecialityHelper::pickSpecialWar($general);
- $db->update('general', [
- 'specage2' => $db->sqleval('age'),
- 'special2' => $specialWar
- ], 'no=%i', $general['no']);
- $specialWarName = buildGeneralSpecialWarClass($specialWar)->getName();
- $josaUl = JosaUtil::pick($specialWarName, '을');
- $logger = new ActionLogger($general['no'], 0, $year, $month);
- $logger->pushGeneralHistoryLog("특기 【{$specialWarName}>】{$josaUl} 습득");
- $logger->pushGeneralActionLog("특기 【{$specialWarName}>】{$josaUl} 익혔습니다!",ActionLogger::PLAIN);
- $logger->flush();
- }
-
break;
case "경험치1000":
$text = $btn . " 지급!";
@@ -330,26 +308,6 @@ switch ($btn) {
'brief' => '해산',
], 'general_id IN %li AND turn_idx = 1', $genlist);
break;
- case "00턴":
- $turnterm = $gameStor->turnterm;
-
- foreach ($genlist as $generalID) {
- $turntime = getRandTurn($turnterm);
- $cutTurn = cutTurn($turntime, $turnterm);
- $db->update('general', [
- 'turntime' => $cutTurn
- ], '`no` IN %li', $genlist);
- }
- break;
- case "랜덤턴":
- $turnterm = $gameStor->turnterm;
- foreach ($genlist as $generalID) {
- $turntime = getRandTurn($turnterm);
- $db->update('general', [
- 'turntime' => $turntime
- ], '`no` IN %li', $genlist);
- }
- break;
}
header('location:_admin2.php');
diff --git a/hwe/func.php b/hwe/func.php
index bde7ffc5..8680cf94 100644
--- a/hwe/func.php
+++ b/hwe/func.php
@@ -135,11 +135,11 @@ function getBlockLevel()
return DB::db()->queryFirstField('select block from general where no = %i', Session::getInstance()->generalID);
}
-function getRandGenName()
+function getRandGenName(RandUtil $rng)
{
- $firstname = Util::choiceRandom(GameConst::$randGenFirstName);
- $middlename = Util::choiceRandom(GameConst::$randGenMiddleName);
- $lastname = Util::choiceRandom(GameConst::$randGenLastName);
+ $firstname = $rng->choice(GameConst::$randGenFirstName);
+ $middlename = $rng->choice(GameConst::$randGenMiddleName);
+ $lastname = $rng->choice(GameConst::$randGenLastName);
return "{$firstname}{$middlename}{$lastname}";
}
@@ -1343,7 +1343,7 @@ function turnDate($curtime)
}
-function triggerTournament()
+function triggerTournament(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -1357,7 +1357,7 @@ function triggerTournament()
if ($tnmt_trig == 0) {
return;
}
- if (!Util::randBool(0.4)) {
+ if (!$rng->nextBool(0.4)) {
return;
}
@@ -1552,7 +1552,7 @@ function CheckHall($no)
}
}
-function giveRandomUniqueItem(General $general, string $acquireType): bool
+function giveRandomUniqueItem(RandUtil $rng, General $general, string $acquireType): bool
{
$db = DB::db();
//아이템 습득 상황
@@ -1643,7 +1643,7 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
}
}
- [$itemType, $itemCode] = Util::choiceRandomUsingWeightPair($availableUnique);
+ [$itemType, $itemCode] = $rng->choiceUsingWeightPair($availableUnique);
$nationName = $general->getStaticNation()['name'];
$generalName = $general->getName();
@@ -1722,12 +1722,12 @@ function rollbackInheritUniqueTrial(General $general, string $itemKey, string $r
$msg->send(true);
}
-function tryRollbackInheritUniqueItem(General $general): void
+function tryRollbackInheritUniqueItem(RandUtil $rng, General $general): void
{
- tryInheritUniqueItem($general, 'Rollback', true);
+ tryInheritUniqueItem($rng, $general, 'Rollback', true);
}
-function tryInheritUniqueItem(General $general, string $acquireType = '아이템', bool $justRollback = false): bool
+function tryInheritUniqueItem(RandUtil $rng, General $general, string $acquireType = '아이템', bool $justRollback = false): bool
{
$ownerID = $general->getVar('owner');
if (!$ownerID) {
@@ -1779,7 +1779,7 @@ function tryInheritUniqueItem(General $general, string $acquireType = '아이템
}
$reasons = [];
- $itemType = Util::choiceRandom($availableItemTypes);
+ $itemType = $rng->choice($availableItemTypes);
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}"); //혹시 itemKey의 크기가 37이 넘을 수 있을까?
$anyTrials = $trialStor->getAll();
@@ -1865,12 +1865,12 @@ function tryInheritUniqueItem(General $general, string $acquireType = '아이템
$general->applyDB($db);
//같은 종류의 유니크를 입찰했을 수 있으니 한번 더 검사한다.
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
return true;
}
-function tryUniqueItemLottery(General $general, string $acquireType = '아이템'): bool
+function tryUniqueItemLottery(RandUtil $rng, General $general, string $acquireType = '아이템'): bool
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -1915,13 +1915,13 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
$userLogger = new UserLogger($general->getVar('owner'));
$userLogger->push(sprintf("유니크를 얻을 공간이 없어 %d 포인트 반환", GameConst::$inheritItemRandomPoint), "inheritPoint");
}
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
return false;
}
$inheritUnique = $general->getAuxVar('inheritUniqueTrial');
if ($acquireType != '설문조사' && $inheritUnique && count($inheritUnique) && $availableBuyUnique) {
- $trialResult = tryInheritUniqueItem($general, $acquireType);
+ $trialResult = tryInheritUniqueItem($rng, $general, $acquireType);
if ($trialResult) {
return true;
}
@@ -1956,7 +1956,7 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
}
foreach (Util::range($maxCnt) as $_idx) {
- if (Util::randBool($prob)) {
+ if ($rng->nextBool($prob)) {
$result = true;
break;
}
@@ -1968,7 +1968,7 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
}
LogText("{$general->getName()}, {$general->getID()} 유니크 성공 {$maxCnt}", $prob);
- return giveRandomUniqueItem($general, $acquireType);
+ return giveRandomUniqueItem($rng, $general, $acquireType);
}
function getAdmin()
@@ -2415,7 +2415,7 @@ function isNeighbor(int $nation1, int $nation2, bool $includeNoSupply = true)
return false;
}
-function SabotageInjury(array $cityGeneralList, string $reason): int
+function SabotageInjury(RandUtil $rng, array $cityGeneralList, string $reason): int
{
$injuryCount = 0;
$josaRo = JosaUtil::pick($reason, '로');
@@ -2427,12 +2427,12 @@ function SabotageInjury(array $cityGeneralList, string $reason): int
/** @var General $general */
$injuryProb = 0.3;
$injuryProb = $general->onCalcStat($general, 'injuryProb', $injuryProb);
- if (!Util::randBool($injuryProb)) {
+ if (!$rng->nextBool($injuryProb)) {
continue;
}
$general->getLogger()->pushGeneralActionLog($text);
- $general->increaseVarWithLimit('injury', Util::randRangeInt(1, 16), 0, 80);
+ $general->increaseVarWithLimit('injury', $rng->nextRangeInt(1, 16), 0, 80);
$general->multiplyVar('crew', 0.98);
$general->multiplyVar('atmos', 0.98);
$general->multiplyVar('train', 0.98);
@@ -2445,7 +2445,7 @@ function SabotageInjury(array $cityGeneralList, string $reason): int
return $injuryCount;
}
-function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null)
+function getRandTurn(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
{
if ($baseDateTime === null) {
$baseDateTime = new \DateTimeImmutable();
@@ -2457,13 +2457,13 @@ function getRandTurn($term, ?\DateTimeInterface $baseDateTime = null)
throw new MustNotBeReachedException();
}
- $randSecond = Util::randRangeInt(0, 60 * $term - 1);
- $randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
+ $randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
+ $randFraction = $rng->nextRangeInt(0, 999999) / 1000000; //6자리 소수
return TimeUtil::format($baseDateTime->add(TimeUtil::secondsToDateInterval($randSecond + $randFraction)), true);
}
-function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
+function getRandTurn2(RandUtil $rng, $term, ?\DateTimeInterface $baseDateTime = null)
{
if ($baseDateTime === null) {
$baseDateTime = new \DateTimeImmutable();
@@ -2472,8 +2472,8 @@ function getRandTurn2($term, ?\DateTimeInterface $baseDateTime = null)
} else {
throw new MustNotBeReachedException();
}
- $randSecond = Util::randRangeInt(0, 60 * $term - 1);
- $randFraction = Util::randRangeInt(0, 999999) / 1000000; //6자리 소수
+ $randSecond = $rng->nextRangeInt(0, 60 * $term - 1);
+ $randFraction = $rng->nextRangeInt(0, 999999) / 1000000; //6자리 소수
return $baseDateTime->sub(TimeUtil::secondsToDateInterval($randSecond + $randFraction))->format('Y-m-d H:i:s.u');
}
diff --git a/hwe/func_converter.php b/hwe/func_converter.php
index 8969efab..bc603fc9 100644
--- a/hwe/func_converter.php
+++ b/hwe/func_converter.php
@@ -405,10 +405,10 @@ function getGeneralPoolClass(string $type){
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
-function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array{
+function pickGeneralFromPool(\MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix=null):array{
/** @var AbsGeneralPool */
$class = getGeneralPoolClass(GameConst::$targetGeneralPool);
- return $class::pickGeneralFromPool($db, $owner, $pickCnt, $prefix);
+ return $class::pickGeneralFromPool($db, $rng, $owner, $pickCnt, $prefix);
}
function countPureGeneralFromRawList(?array $rawGeneralList=null):int{
diff --git a/hwe/func_gamerule.php b/hwe/func_gamerule.php
index 06abca85..da488e7c 100644
--- a/hwe/func_gamerule.php
+++ b/hwe/func_gamerule.php
@@ -333,7 +333,7 @@ EOD),
}
// 외교 로그처리, 외교 상태 처리
-function postUpdateMonthly()
+function postUpdateMonthly(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -485,12 +485,12 @@ function postUpdateMonthly()
$availableWarSettingCnt = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'available_war_setting_cnt');
foreach ($nations as $nation) {
$nationID = $nation['nation'];
- if(!key_exists($nationID, $availableWarSettingCnt)){
+ if (!key_exists($nationID, $availableWarSettingCnt)) {
$availableWarSettingCnt[$nationID] = 0;
}
}
- foreach($availableWarSettingCnt as $nationID=>$cnt){
- if($cnt >= GameConst::$maxAvailableWarSettingCnt){
+ foreach ($availableWarSettingCnt as $nationID => $cnt) {
+ if ($cnt >= GameConst::$maxAvailableWarSettingCnt) {
continue;
}
$cnt = Util::valueFit($cnt + GameConst::$incAvailableWarSettingCnt, 0, GameConst::$maxAvailableWarSettingCnt);
@@ -499,7 +499,7 @@ function postUpdateMonthly()
//초반이후 방랑군 자동 해체
if ($admin['year'] >= $admin['startyear'] + 2) {
- checkWander();
+ checkWander($rng);
}
// 작위 업데이트
updateNationState();
@@ -508,7 +508,7 @@ function postUpdateMonthly()
// 천통여부 검사
checkEmperior();
//토너먼트 개시
- triggerTournament();
+ triggerTournament($rng);
// 시스템 거래건 등록
registerAuction();
//전방설정
@@ -521,7 +521,7 @@ function postUpdateMonthly()
}
-function checkWander()
+function checkWander(RandUtil $rng)
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -535,7 +535,7 @@ function checkWander()
if ($wanderCmd->hasFullConditionMet()) {
$logger = $wanderer->getLogger();
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
- $wanderCmd->run();
+ $wanderCmd->run($rng);
$wanderCmd->setNextAvailable();
}
}
@@ -552,6 +552,9 @@ function updateNationState()
$history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']);
+ $year = $admin['year'];
+ $month = $admin['month'];
+ $startYear = $admin['startyear'];
$assemblerCnts = [];
foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) {
@@ -560,7 +563,9 @@ function updateNationState()
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
- $citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
+ $nationID = $nation['nation'];
+ $citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nationID);
+
if ($citycount == 0) {
$nationlevel = 0; // 방랑군
@@ -594,26 +599,26 @@ function updateNationState()
switch ($nationlevel) {
case 7:
$josaUl = JosaUtil::pick(getNationLevel($nationlevel), '을');
- $history[] = "●>{$admin['year']}년 {$admin['month']}월:【작위】>{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">{$josaUl} 자칭하였습니다.";
- pushNationHistoryLog($nation['nation'], ["●>{$admin['year']}년 {$admin['month']}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">{$josaUl} 자칭"]);
+ $history[] = "●>{$year}년 {$month}월:【작위】>{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">{$josaUl} 자칭하였습니다.";
+ pushNationHistoryLog($nation['nation'], ["●>{$year}년 {$month}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">{$josaUl} 자칭"]);
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6:
- $history[] = "●>{$admin['year']}년 {$admin['month']}월:【작위】>{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 등극하였습니다.";
- pushNationHistoryLog($nation['nation'], ["●>{$admin['year']}년 {$admin['month']}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 등극"]);
+ $history[] = "●>{$year}년 {$month}월:【작위】>{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 등극하였습니다.";
+ pushNationHistoryLog($nation['nation'], ["●>{$year}년 {$month}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 등극"]);
break;
case 5:
case 4:
case 3:
- $history[] = "●>{$admin['year']}년 {$admin['month']}월:【작위】>{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 임명되었습니다.";
- pushNationHistoryLog($nation['nation'], ["●>{$admin['year']}년 {$admin['month']}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 임명됨"]);
+ $history[] = "●>{$year}년 {$month}월:【작위】>{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 임명되었습니다.";
+ pushNationHistoryLog($nation['nation'], ["●>{$year}년 {$month}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">에 임명됨"]);
break;
case 2:
- $history[] = "●>{$admin['year']}년 {$admin['month']}월:【작위】>{$nation['name']}>의 군주가 독립하여 " . getNationLevel($nationlevel) . ">로 나섰습니다.";
- pushNationHistoryLog($nation['nation'], ["●>{$admin['year']}년 {$admin['month']}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">로 나서다"]);
+ $history[] = "●>{$year}년 {$month}월:【작위】>{$nation['name']}>의 군주가 독립하여 " . getNationLevel($nationlevel) . ">로 나섰습니다.";
+ pushNationHistoryLog($nation['nation'], ["●>{$year}년 {$month}월:{$nation['name']}>의 군주가 " . getNationLevel($nationlevel) . ">로 나서다"]);
break;
}
@@ -648,7 +653,6 @@ function updateNationState()
$uniqueLotteryWeightList = [];
- [$startYear, $year] = $gameStor->getValuesAsArray(['startyear', 'year']);
$relYear = $year - $startYear;
$maxTrialCountByYear = 1;
foreach (GameConst::$maxUniqueItemLimit as $tmpVals) {
@@ -684,20 +688,37 @@ function updateNationState()
$score += 15;
}
- $score *= 2**$trialCnt;
+ $score *= 2 ** $trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
+ $nationLevelUpRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'nationLevelUp',
+ $year,
+ $month,
+ $nationID
+ )));
+
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
- $winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
+ $winnerObj = $nationLevelUpRNG->choiceUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
- giveRandomUniqueItem($winnerObj, '작위보상');
+
+ $givenUniqueRNG = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'givenUnique',
+ $year,
+ $month,
+ $nationID,
+ $winnerObj->getID(),
+ )));
+ giveRandomUniqueItem($givenUniqueRNG, $winnerObj, '작위보상');
$winnerObj->applyDB($db);
}
@@ -723,9 +744,18 @@ function updateNationState()
if ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID = $gameStor->assembler_id ?? 0;
+ $troopLeaderRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'troopLeader',
+ $year,
+ $month,
+ $nationID
+ )));
+
while ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1;
$npcObj = new Scenario\GeneralBuilder(
+ $troopLeaderRng,
sprintf('부대장%4d', $lastAssemblerID),
false,
null,
@@ -1183,7 +1213,8 @@ function checkEmperior()
'aux' => $statGeneral['aux']
]);
- $history = ["●>{$admin['year']}년 {$admin['month']}월:【통일】>{$nation['name']}>{$josaYi} 전토를 통일하였습니다."];
+ $hiddenSeed = UniqueConst::$hiddenSeed;
+ $history = ["●>{$admin['year']}년 {$admin['month']}월:【통일】>{$nation['name']}>{$josaYi} 전토를 통일하였습니다. (서버시드: $hiddenSeed})"];
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
//연감 월결산
@@ -1201,3 +1232,26 @@ function updateMaxDomesticCritical(General $general, $score)
$general->setInheritancePoint(InheritanceKey::max_domestic_critical, $maxDomesticCritical);
}
}
+
+function genGenericUniqueRNG(int $year, int $month, int $generalID): RandUtil
+{
+ return new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'unique',
+ $year,
+ $month,
+ $generalID
+ )));
+}
+
+function genGenericUniqueRNGFromGeneral(General $general): RandUtil
+{
+ $logger = $general->getLogger();
+ if (!$logger) {
+ throw new \Exception('정식 초기화된 객체가 아닙니다.');
+ }
+ $year = $logger->getYear();
+ $month = $logger->getMonth();
+ $generalID = $general->getID();
+ return genGenericUniqueRNG($year, $month, $generalID);
+}
diff --git a/hwe/func_process.php b/hwe/func_process.php
index fd4ab027..41c8a4b8 100644
--- a/hwe/func_process.php
+++ b/hwe/func_process.php
@@ -3,10 +3,10 @@ namespace sammo;
/**
* 내정 커맨드 사용시 성공 확률 계산
- *
+ *
* @param General $general 장수 정보
* @param string $type 내정 커맨드 타입, 'leadership' = 통솔 기반, 'strength' = 무력 기반, 'intel' = 지력 기반
- *
+ *
* @return array 계산된 실패, 성공 확률 ('success' => 성공 확률, 'fail' => 실패 확률)
*/
function CriticalRatioDomestic(General $general, string $type) {
@@ -24,7 +24,7 @@ function CriticalRatioDomestic(General $general, string $type) {
506040(33%/30%), 505050(43%/40%), 504060(50%/50%)
* 통솔 내정 기준
- 756510(25%/22%), 707010(31%/28%), 657510(38%,35%),
+ 756510(25%/22%), 707010(31%/28%), 657510(38%,35%),
505050(50%,50%), 107070(50%,50%)
*/
switch($type) {
@@ -60,13 +60,12 @@ function calcLeadershipBonus($officerLevel, $nationLevel):int{
return $lbonus;
}
-function CriticalScoreEx(string $type):float {
+function CriticalScoreEx(RandUtil $rng, string $type):float {
if ($type == 'success') {
- return Util::randRange(2.2, 3.0);
+ return $rng->nextRange(2.2, 3.0);
}
if ($type == 'fail') {
- return Util::randRange(0.2, 0.4);
+ return $rng->nextRange(0.2, 0.4);
}
return 1;
}
-
diff --git a/hwe/func_template.php b/hwe/func_template.php
index 26e5c7a7..f44e18e9 100644
--- a/hwe/func_template.php
+++ b/hwe/func_template.php
@@ -60,7 +60,8 @@ function chiefTurnTable()
";
}
-function templateLimitMsg(string $turntime): string{
+function templateLimitMsg(string $turntime): string
+{
return "이미 너무 많은 접속을 하셨습니다. 다음 턴에 다시 시도해주세요. (턴시간: {$turntime})";
}
@@ -165,7 +166,7 @@ function commandButton(array $opts = [])
'color' => '#000000'
];
- $bgColor = Util::array_get($nation['color']) ?: '#000000';
+ $bgColor = $nation['color'] ?? '#000000';
$fgColor = newColor($bgColor);
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
@@ -173,16 +174,16 @@ function commandButton(array $opts = [])
$permission = checkSecretPermission($me);
$btnClassForTournament = $opts['btnClass'];
if ($opts['isTournamentApplicationOpen']) {
- if ($btnClassForTournament != 'dropdown-item') {
- $btnClassForTournament = 'toolbarButton2';
- }
+ if ($btnClassForTournament != 'dropdown-item') {
+ $btnClassForTournament = 'toolbarButton2';
+ }
}
$btnClassForBetting = $opts['btnClass'];
if ($opts['isBettingActive']) {
- if ($btnClassForTournament != 'dropdown-item') {
- $btnClassForBetting = 'toolbarButton2';
- }
+ if ($btnClassForTournament != 'dropdown-item') {
+ $btnClassForBetting = 'toolbarButton2';
+ }
}
if ($permission >= 1) {
@@ -246,7 +247,7 @@ function getMapHtml(?string $mapName = null)
{
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
- if($mapName === null){
+ if ($mapName === null) {
$mapName = GameConst::$mapName;
}
diff --git a/hwe/func_time_event.php b/hwe/func_time_event.php
index 5ed7e025..f0d6912a 100644
--- a/hwe/func_time_event.php
+++ b/hwe/func_time_event.php
@@ -513,7 +513,7 @@ function getOutcome(float $billRate, array $generalList) {
return $outcome;
}
-function tradeRate() {
+function tradeRate(RandUtil $rng) {
$db = DB::db();
foreach($db->query('SELECT city,level FROM city') as $city){
@@ -528,8 +528,8 @@ function tradeRate() {
7=>0.8,
8=>1
][$city['level']];
- if($prob > 0 && Util::randBool($prob)) {
- $trade = Util::randRangeInt(95, 105);
+ if($prob > 0 && $rng->nextBool($prob)) {
+ $trade = $rng->nextRangeInt(95, 105);
} else {
$trade = null;
}
@@ -539,7 +539,7 @@ function tradeRate() {
}
}
-function disaster() {
+function disaster(RandUtil $rng) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
@@ -560,7 +560,7 @@ function disaster() {
10=>0
];
- $isGood = Util::randBool($boomingRate[$month]);
+ $isGood = $rng->nextBool($boomingRate[$month]);
$targetCityList = [];
@@ -575,7 +575,7 @@ function disaster() {
$raiseProp = 0.06 - ($city['secu'] / $city['secu_max']) * 0.05; // 1 ~ 6%
}
- if(Util::randBool($raiseProp)) {
+ if($rng->nextBool($raiseProp)) {
$targetCityList[] = $city;
}
}
@@ -621,7 +621,7 @@ function disaster() {
10 => null
];
- [$logTitle, $stateCode, $logBody] = Util::choiceRandom(($isGood?$boomingTextList:$disasterTextList)[$month]);
+ [$logTitle, $stateCode, $logBody] = $rng->choice(($isGood?$boomingTextList:$disasterTextList)[$month]);
$logger = new ActionLogger(0, 0, $year, $month, false);
@@ -653,7 +653,7 @@ function disaster() {
$generalListByCity[$city['city']]??[]
);
- SabotageInjury($generalList, '재난');
+ SabotageInjury($rng, $generalList, '재난');
}
}
else{
diff --git a/hwe/func_tournament.php b/hwe/func_tournament.php
index 5c4d9ecb..ffdaef12 100644
--- a/hwe/func_tournament.php
+++ b/hwe/func_tournament.php
@@ -448,12 +448,18 @@ function startBetting($type, $unit)
$betGold = Util::valueFit(floor((3 + $year - $startyear) * 0.334) * 10, 10);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'OpenBettingTournament',
+ $bettingID,
+ )));
+
$npcList = $db->queryFirstColumn('SELECT no FROM general WHERE npc >= 2 AND gold >= (500 + %i)', $betGold);
$npcBet = [];
$targetList = array_keys($candidates);
foreach ($npcList as $npcID) {
- $target = Util::choiceRandom($targetList);
+ $target = $rng->choice($targetList);
$npcBet[] = [$npcID, $target];
}
diff --git a/hwe/j_get_select_npc_token.php b/hwe/j_get_select_npc_token.php
index 03c6398c..ec6d0344 100644
--- a/hwe/j_get_select_npc_token.php
+++ b/hwe/j_get_select_npc_token.php
@@ -110,10 +110,17 @@ foreach($db->queryFirstColumn('SELECT pick_result FROM select_npc_token WHERE `o
}
}
+$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'SelectNPCToken',
+ $userID,
+ $now,
+)));
+
$pickLimit = min(count($candidates), 5);
while(count($pickResult) < $pickLimit){
- $generalID = Util::choiceRandomUsingWeight($weight);
+ $generalID = $rng->choiceUsingWeight($weight);
if(!key_exists($generalID, $pickResult)){
$pickResult[$generalID] = $candidates[$generalID];
}
diff --git a/hwe/j_get_select_pool.php b/hwe/j_get_select_pool.php
index 5c2d838d..3696f142 100644
--- a/hwe/j_get_select_pool.php
+++ b/hwe/j_get_select_pool.php
@@ -74,9 +74,13 @@ if($tokens){
]);
}
+$rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed, 'selectPool', $userID, $now
+)));
+
$pick = [];
$valid_until = null;
-foreach(pickGeneralFromPool($db, $userID, 14) as $pickObj){
+foreach(pickGeneralFromPool($db, $rng, $userID, 14) as $pickObj){
$valid_until = $pickObj->getValidUntil();
$info = $pickObj->getInfo();
putInfoText($info);
diff --git a/hwe/j_install.php b/hwe/j_install.php
index c5f3547d..43301a3d 100644
--- a/hwe/j_install.php
+++ b/hwe/j_install.php
@@ -144,7 +144,7 @@ $autorun_user = $autorun_user_minutes?[
if($reserve_open){
$reserve_open = new \DateTime($reserve_open);
$db = DB::db();
-
+
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
$clearResult = ResetHelper::clearDB();
if(!$clearResult['result']){
@@ -159,7 +159,9 @@ if($reserve_open){
]);
}
- $scenarioObj = new Scenario($scenario, true);
+ $rng = new RandUtil(new LiteHashDRBG(random_bytes(16)));
+
+ $scenarioObj = new Scenario($rng, $scenario, true);
$open_date = $reserve_open->format('Y-m-d H:i:s');
$reserveInfo = [
@@ -179,14 +181,14 @@ if($reserve_open){
'autorun_user'=>$autorun_user
];
-
+
if($pre_reserve_open){
$pre_reserve_open = new \DateTime($pre_reserve_open);
$open_date = $pre_reserve_open->format('Y-m-d H:i:s');
}
-
+
$db->delete('reserved_open', true);
$db->insert('reserved_open', [
'options'=>Json::encode($reserveInfo),
diff --git a/hwe/j_select_picked_general.php b/hwe/j_select_picked_general.php
index af50d30a..d5f99e96 100644
--- a/hwe/j_select_picked_general.php
+++ b/hwe/j_select_picked_general.php
@@ -103,7 +103,7 @@ foreach(GameConst::$generalPoolAllowOption as $allowOption){
}
else if($allowOption == 'ego'){
if(!$personal || $personal == 'Random'){
- $personal = Util::choiceRandom(GameConst::$availablePersonality);
+ $personal = Util::choiceRandom(GameConst::$availablePersonality);
}
if(!array_search($personal, GameConst::$availablePersonality)){
Json::die([
diff --git a/hwe/j_simulate_battle.php b/hwe/j_simulate_battle.php
index ac89c241..ab9ffccf 100644
--- a/hwe/j_simulate_battle.php
+++ b/hwe/j_simulate_battle.php
@@ -300,12 +300,17 @@ function simulateBattle(
$rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
){
+
+ $warSeed = bin2hex(random_bytes(16));
+ $warRng = new RandUtil(new LiteHashDRBG($warSeed));
+
$attacker = new WarUnitGeneral(
+ $warRng,
new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
$rawAttackerNation,
true
);
- $city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
+ $city = new WarUnitCity($warRng, $rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
$iterDefender = new \ArrayIterator($rawDefenderList);
$iterDefender->rewind();
@@ -316,7 +321,7 @@ function simulateBattle(
$defenderRice = 0;
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
- use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
+ use ($warRng, $iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
if($prevDefender !== null){
$prevDefender->getLogger()->rollback();
$battleResult[] = $prevDefender;
@@ -341,6 +346,7 @@ function simulateBattle(
$defenderRice += $defenderObj->getVar('rice');
$retVal = new WarUnitGeneral(
+ $warRng,
$defenderObj,
$rawDefenderNation,
false
@@ -349,7 +355,7 @@ function simulateBattle(
return $retVal;
};
- $conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
+ $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
$rawDefenderCity = $city->getRaw();
$updateAttackerNation = [];
diff --git a/hwe/process_war.php b/hwe/process_war.php
index 4c600456..d910ade6 100644
--- a/hwe/process_war.php
+++ b/hwe/process_war.php
@@ -3,9 +3,10 @@
namespace sammo;
-function processWar(General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
+function processWar(string $warSeed, General $attackerGeneral, array $rawAttackerNation, array $rawDefenderCity)
{
+ $rng = new RandUtil(new LiteHashDRBG($warSeed));
$db = DB::db();
$attackerNationID = $attackerGeneral->getNationID();
@@ -30,9 +31,9 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$gameStor = KVStorage::getStorage($db, 'game_env');
[$startYear, $year, $month, $cityRate, $joinMode] = $gameStor->getValuesAsArray(['startyear', 'year', 'month', 'city_rate', 'join_mode']);
- $attacker = new WarUnitGeneral($attackerGeneral, $rawAttackerNation, true);
+ $attacker = new WarUnitGeneral($rng, $attackerGeneral,$rawAttackerNation, true);
- $city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
+ $city = new WarUnitCity($rng, $rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
$defenderIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and train>=defence_train and atmos>=defence_train', $city->getVar('nation'), $city->getVar('city'));
$defenderList = General::createGeneralObjListFromDB($defenderIDList, null, 2);
@@ -44,7 +45,7 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind();
- $getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
+ $getNextDefender = function (?WarUnit $prevDefender, bool $reqNext) use ($rng, $iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
if ($prevDefender !== null) {
$prevDefender->applyDB($db);
}
@@ -65,6 +66,7 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$retVal = new WarUnitGeneral(
+ $rng,
$nextDefender,
$rawDefenderNation,
false
@@ -73,7 +75,7 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
return $retVal;
};
- $conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
+ $conquerCity = processWar_NG($warSeed, $attacker, $getNextDefender, $city, $year - $startYear);
$attacker->applyDB($db);
@@ -206,6 +208,7 @@ function extractBattleOrder(General $general)
}
function processWar_NG(
+ string $warSeed,
WarUnitGeneral $attacker,
callable $getNextDefender,
WarUnitCity $city,
@@ -228,8 +231,8 @@ function processWar_NG(
$josaRo = JosaUtil::pick($city->getName(), '로');
$josaYi = JosaUtil::pick($attacker->getName(), '이');
- $logger->pushGlobalActionLog("{$attacker->getNationVar('name')}>의 {$attacker->getName()}>{$josaYi} {$city->getName()}>{$josaRo} 진격합니다.");
- $logger->pushGeneralActionLog("{$city->getName()}>{$josaRo} 진격>합니다. <1>$date>");
+ $logger->pushGlobalActionLog("{$attacker->getNationVar('name')}>의 {$attacker->getName()}>{$josaYi} {$city->getName()}>{$josaRo} 진격합니다.(전투시드: {$warSeed})");
+ $logger->pushGeneralActionLog("{$city->getName()}>{$josaRo} 진격>합니다.(전투시드: {$warSeed}) <1>$date>");
$logWritten = false;
@@ -309,7 +312,7 @@ function processWar_NG(
$initCaller = $attacker->getGeneral()->getBattleInitSkillTriggerList($attacker);
$initCaller->merge($defender->getGeneral()->getBattleInitSkillTriggerList($defender));
- $initCaller->fire([], [$attacker, $defender]);
+ $initCaller->fire($attacker->rng, [], [$attacker, $defender]);
}
$attacker->beginPhase();
@@ -318,7 +321,7 @@ function processWar_NG(
$battleCaller = $attacker->getGeneral()->getBattlePhaseSkillTriggerList($attacker);
$battleCaller->merge($defender->getGeneral()->getBattlePhaseSkillTriggerList($defender));
- $battleCaller->fire([], [$attacker, $defender]);
+ $battleCaller->fire($attacker->rng, [], [$attacker, $defender]);
$deadDefender = $attacker->calcDamage();
$deadAttacker = $defender->calcDamage();
@@ -510,6 +513,16 @@ function ConquerCity(array $admin, General $general, array $city)
$cityID = $city['city'];
$cityName = $city['name'];
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'ConquerCity',
+ $year,
+ $month,
+ $attackerNationID,
+ $attackerID,
+ $cityID
+ )));
+
$defenderNationID = $city['nation'];
$defenderStaticNation = getNationStaticInfo($defenderNationID);
$defenderNationName = $defenderStaticNation['name'];
@@ -594,7 +607,7 @@ function ConquerCity(array $admin, General $general, array $city)
$oldGeneral->applyDB($db);
//모두 등용장 발부
- if ($admin['join_mode'] != 'onlyRandom' && Util::randBool(0.5)) {
+ if ($admin['join_mode'] != 'onlyRandom' && $rng->nextBool(0.5)) {
$msg = ScoutMessage::buildScoutMessage($attackerID, $oldGeneral->getID());
if ($msg) {
$msg->send(true);
@@ -603,11 +616,11 @@ function ConquerCity(array $admin, General $general, array $city)
//NPC인 경우 일정 확률로 임관(엔장, 인재, 의병)
$npcType = $oldGeneral->getNPCType();
- if ($admin['join_mode'] != 'onlyRandom' && 2 <= $npcType && $npcType <= 8 && $npcType != 5 && Util::randBool(GameConst::$joinRuinedNPCProp)) {
+ if ($admin['join_mode'] != 'onlyRandom' && 2 <= $npcType && $npcType <= 8 && $npcType != 5 && $rng->nextBool(GameConst::$joinRuinedNPCProp)) {
$cmd = buildGeneralCommandClass('che_임관', $oldGeneral, $admin, [
'destNationID' => $attackerNationID
]);
- $joinTurn = Util::randRangeInt(0, 12);
+ $joinTurn = $rng->nextRangeInt(0, 12);
if ($joinTurn) {
_setGeneralCommand(buildGeneralCommandClass('che_견문', $oldGeneral, $admin), iterator_to_array(Util::range($joinTurn)));
}
diff --git a/hwe/sammo/API/General/Join.php b/hwe/sammo/API/General/Join.php
index 8c8563b3..b54cafab 100644
--- a/hwe/sammo/API/General/Join.php
+++ b/hwe/sammo/API/General/Join.php
@@ -13,11 +13,14 @@ use sammo\InheritancePointManager;
use sammo\JosaUtil;
use sammo\Json;
use sammo\KVStorage;
+use sammo\LiteHashDRBG;
+use sammo\RandUtil;
use sammo\RootDB;
use sammo\Session;
use sammo\SpecialityHelper;
use sammo\StringUtil;
use sammo\TimeUtil;
+use sammo\UniqueConst;
use sammo\UserLogger;
use sammo\Util;
use sammo\Validator;
@@ -162,6 +165,14 @@ class Join extends \sammo\BaseAPI
$userLogger = new UserLogger($userID, $admin['year'], $admin['month'], false);
+ $now = TimeUtil::now(false);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'MakeGeneral',
+ $userID,
+ $now
+ )));
+
if ($inheritCity !== null) {
$inheritRequiredPoint += GameConst::$inheritBornCityPoint;
}
@@ -193,7 +204,7 @@ class Join extends \sammo\BaseAPI
$genius = true;
} else {
// 현재 1%
- $genius = Util::randBool(0.01);
+ $genius = $rng->nextBool(0.01);
}
if ($genius && $gameStor->genius > 0) {
@@ -208,10 +219,12 @@ class Join extends \sammo\BaseAPI
$city = $inheritCity;
} else {
// 공백지에서만 태어나게
- $city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1");
- if (!$city) {
- $city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1");
+ $cities = $db->queryFirstColumn('SELECT city FROM city where `level`>=5 and `level`<=6 and nation=0');
+ if (!$cities) {
+ $db->queryFirstColumn('SELECT city FROM city where `level`>=5 and `level`<=6');
+ $cities = $db->queryFirstField("SELECT city from city where `level`>=5 and `level`<=6");
}
+ $city = $rng->choice($cities);
}
if ($inheritBonusStat) {
@@ -221,8 +234,8 @@ class Join extends \sammo\BaseAPI
$pleadership = 0;
$pstrength = 0;
$pintel = 0;
- foreach (Util::range(Util::randRangeInt(3, 5)) as $statIdx) {
- switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) {
+ foreach (Util::range($rng->nextRangeInt(3, 5)) as $statIdx) {
+ switch ($rng->choiceUsingWeight([$leadership, $strength, $intel])) {
case 0:
$pleadership++;
break;
@@ -242,14 +255,14 @@ class Join extends \sammo\BaseAPI
$relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0);
- $age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1));
+ $age = 20 + ($pleadership + $pstrength + $pintel) * 2 - $rng->nextRangeInt(0, 1);
// 아직 남았고 천재등록상태이면 특기 부여
if ($genius) {
$specage2 = $age;
if ($inheritSpecial) {
$special2 = $inheritSpecial;
} else {
- $special2 = SpecialityHelper::pickSpecialWar([
+ $special2 = SpecialityHelper::pickSpecialWar($rng, [
'leadership' => $leadership,
'strength' => $strength,
'intel' => $intel,
@@ -290,12 +303,12 @@ class Join extends \sammo\BaseAPI
$userLogger->push(sprintf("턴 시간 %02d:%02d 로 지정", intdiv($inheritTurntime, 60), $inheritTurntime%60), "inheritPoint");
- $inheritTurntime += Util::randRangeInt(0, 999999) / 1000000;
+ $inheritTurntime += $rng->nextRangeInt(0, 999999) / 1000000;
$turntime = new \DateTimeImmutable(cutTurn($admin['turntime'], $admin['turnterm']));
$turntime = $turntime->add(TimeUtil::secondsToDateInterval($inheritTurntime));
$turntime = TimeUtil::format($turntime, true);
} else {
- $turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime']));
+ $turntime = getRandTurn($rng, $admin['turnterm'], new \DateTimeImmutable($admin['turntime']));
}
@@ -315,7 +328,7 @@ class Join extends \sammo\BaseAPI
//성격 랜덤시
if (!in_array($character, GameConst::$availablePersonality)) {
- $character = Util::choiceRandom(GameConst::$availablePersonality);
+ $character = $rng->choice(GameConst::$availablePersonality);
}
//상성 랜덤
$affinity = rand() % 150 + 1;
diff --git a/hwe/sammo/API/InheritAction/ResetTurnTime.php b/hwe/sammo/API/InheritAction/ResetTurnTime.php
index 89a44e0f..479608a6 100644
--- a/hwe/sammo/API/InheritAction/ResetTurnTime.php
+++ b/hwe/sammo/API/InheritAction/ResetTurnTime.php
@@ -10,7 +10,10 @@ use sammo\Enums\RankColumn;
use sammo\GameConst;
use sammo\General;
use sammo\KVStorage;
+use sammo\LiteHashDRBG;
+use sammo\RandUtil;
use sammo\TimeUtil;
+use sammo\UniqueConst;
use sammo\UserLogger;
use sammo\Util;
@@ -59,7 +62,14 @@ class ResetTurnTime extends \sammo\BaseAPI
$currTurnTime = new DateTimeImmutable($general->getTurnTime());
$serverTurnTimeObj = new DateTimeImmutable($serverTurnTime);
- $afterTurn = Util::randRange($turnTerm * -60 / 2, $turnTerm * 60 / 2);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'ResetTurnTime',
+ $userID,
+ $general->getTurnTime()
+ )));
+
+ $afterTurn = $rng->nextRange($turnTerm * -60 / 2, $turnTerm * 60 / 2);
$userLogger = new UserLogger($userID);
if($afterTurn >= 0){
diff --git a/hwe/sammo/API/Vote/Vote.php b/hwe/sammo/API/Vote/Vote.php
index d70c4334..7ecc5220 100644
--- a/hwe/sammo/API/Vote/Vote.php
+++ b/hwe/sammo/API/Vote/Vote.php
@@ -8,7 +8,11 @@ use sammo\DTO\VoteInfo;
use sammo\General;
use sammo\Json;
use sammo\KVStorage;
+use sammo\LiteHashDRBG;
+use sammo\RandUtil;
use sammo\Session;
+use sammo\UniqueConst;
+use sammo\Util;
use sammo\Validator;
use Symfony\Component\Lock\LockFactory;
use Symfony\Component\Lock\Store\SemaphoreStore;
@@ -102,7 +106,13 @@ class Vote extends \sammo\BaseAPI
$general = General::createGeneralObjFromDB($generalID, ['gold', 'horse', 'weapon', 'book', 'item', 'npc', 'imgsvr', 'picture', 'aux'], 2);
$general->increaseVar('gold', $voteReward);
- $wonLottery = tryUniqueItemLottery($general, '설문조사');
+ $uniqueRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'voteUnique',
+ $voteID,
+ $generalID
+ )));
+ $wonLottery = tryUniqueItemLottery($uniqueRng, $general, '설문조사');
$general->applyDB($db);
diff --git a/hwe/sammo/AbsFromUserPool.php b/hwe/sammo/AbsFromUserPool.php
index 344f6957..4fca0fac 100644
--- a/hwe/sammo/AbsFromUserPool.php
+++ b/hwe/sammo/AbsFromUserPool.php
@@ -24,7 +24,7 @@ abstract class AbsFromUserPool extends AbsGeneralPool{
return $db->affectedRows()!=0;
}
- static public function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array{
+ static public function pickGeneralFromPool(\MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix=null):array{
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
@@ -48,7 +48,7 @@ abstract class AbsFromUserPool extends AbsGeneralPool{
$result = [];
$validUntil = TimeUtil::nowAddMinutes(2 * $gameStor->turnterm);
while(count($result) < $pickCnt){
- $cand = Util::choiceRandomUsingWeightPair($pool);
+ $cand = $rng->choiceUsingWeightPair($pool);
$poolID = $cand['id'];
if(key_exists($poolID, $result)){
continue;
@@ -64,7 +64,7 @@ abstract class AbsFromUserPool extends AbsGeneralPool{
if($db->affectedRows()==0){
continue;
}
- $result[$poolID] = new static($db, $candInfo, $validUntil);
+ $result[$poolID] = new static($db, $rng, $candInfo, $validUntil);
}
return array_values($result);
diff --git a/hwe/sammo/AbsGeneralPool.php b/hwe/sammo/AbsGeneralPool.php
index 805f16f4..64252ed3 100644
--- a/hwe/sammo/AbsGeneralPool.php
+++ b/hwe/sammo/AbsGeneralPool.php
@@ -20,27 +20,28 @@ abstract class AbsGeneralPool{
* generalName
* imgsvr
* picture
- *
+ *
* leadership
* strength
* intel
- *
+ *
* experience
* dedication
- *
+ *
* dex[5]
- *
+ *
* specialDomestic
* specialWar
*/
- public function __construct(\MeekroDB $db, array $info, string $validUntil)
+ public function __construct(\MeekroDB $db, RandUtil $rng, array $info, string $validUntil)
{
$this->db = $db;
$this->info = $info;
$this->uniqueName = $info['uniqueName'];
$this->generalName = $info['generalName'];
$this->builder = new GeneralBuilder(
+ $rng,
$info['generalName'],
$info['imgsvr'],
$info['picture'],
@@ -97,14 +98,14 @@ abstract class AbsGeneralPool{
/**
* @param \MeekroDB $db
- * @param int $owner
- * @param int $pickCnt
+ * @param int $owner
+ * @param int $pickCnt
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
- static abstract public function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array;
+ static abstract public function pickGeneralFromPool(\MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix=null):array;
abstract public function occupyGeneralName():bool;
-
+
abstract public static function getPoolName():string;
abstract public static function initPool(\MeekroDB $db);
diff --git a/hwe/sammo/ActionItem/che_보물_도기.php b/hwe/sammo/ActionItem/che_보물_도기.php
index d85da20d..ee1d67c4 100644
--- a/hwe/sammo/ActionItem/che_보물_도기.php
+++ b/hwe/sammo/ActionItem/che_보물_도기.php
@@ -6,6 +6,7 @@ use sammo\DB;
use \sammo\iAction;
use \sammo\General;
use sammo\KVStorage;
+use sammo\RandUtil;
use sammo\Util;
class che_보물_도기 extends \sammo\BaseItem
@@ -17,7 +18,7 @@ class che_보물_도기 extends \sammo\BaseItem
protected $cost = 200;
protected $consumable = false;
- public function onArbitraryAction(General $general, string $actionType, ?string $phase = null, $aux = null): ?array
+ public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase = null, $aux = null): ?array
{
if ($aux === null){
return $aux;
@@ -39,7 +40,7 @@ class che_보물_도기 extends \sammo\BaseItem
$score = 10000 + 5000 * Util::valueFit(intdiv($relYear, 2), 0);
- [$resName, $resKey] = Util::choiceRandom([
+ [$resName, $resKey] = $rng->choice([
['금', 'gold'],
['쌀', 'rice']
]);
diff --git a/hwe/sammo/ActionItem/che_저지_삼황내문.php b/hwe/sammo/ActionItem/che_저지_삼황내문.php
index 19576c22..f444c0bd 100644
--- a/hwe/sammo/ActionItem/che_저지_삼황내문.php
+++ b/hwe/sammo/ActionItem/che_저지_삼황내문.php
@@ -22,7 +22,7 @@ class che_저지_삼황내문 extends \sammo\BaseItem{
if($unit->getPhase() >= 2){
return null;
}
- if($unit->getPhase() == 1 && Util::randBool(0.5)){
+ if($unit->getPhase() == 1 && $unit->rng->nextBool(0.5)){
return null;
}
diff --git a/hwe/sammo/ActionItem/che_치료_환약.php b/hwe/sammo/ActionItem/che_치료_환약.php
index 59b4b704..719728af 100644
--- a/hwe/sammo/ActionItem/che_치료_환약.php
+++ b/hwe/sammo/ActionItem/che_치료_환약.php
@@ -4,6 +4,7 @@ use \sammo\iAction;
use \sammo\General;
use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller;
+use sammo\RandUtil;
class che_치료_환약 extends \sammo\BaseItem{
@@ -23,7 +24,7 @@ class che_치료_환약 extends \sammo\BaseItem{
);
}
- function onArbitraryAction(General $general, string $actionType, ?string $phase = null, $aux = null): ?array
+ function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase = null, $aux = null): ?array
{
if($actionType != '장비매매'){
return $aux;
diff --git a/hwe/sammo/BaseWarUnitTrigger.php b/hwe/sammo/BaseWarUnitTrigger.php
index eeb80f44..504683f3 100644
--- a/hwe/sammo/BaseWarUnitTrigger.php
+++ b/hwe/sammo/BaseWarUnitTrigger.php
@@ -28,7 +28,7 @@ abstract class BaseWarUnitTrigger extends ObjectTrigger{
return "{$priority}_{$fqn}_{$objID}_{$this->raiseType}";
}
- public function action(?array $env=null, $arg=null):?array{
+ public function action(\sammo\RandUtil $rng, ?array $env=null, $arg=null):?array{
if($env === null){
$env = [];
}
@@ -46,7 +46,7 @@ abstract class BaseWarUnitTrigger extends ObjectTrigger{
/** @var WarUnitGeneral $attacker */
/** @var WarUnit $defender */
[$attacker, $defender] = $arg;
-
+
/** @var WarUnit $self */
$self = $this->object;
$isAttacker = $self->isAttacker();
diff --git a/hwe/sammo/Command/BaseCommand.php b/hwe/sammo/Command/BaseCommand.php
index 469d07be..ba49666e 100644
--- a/hwe/sammo/Command/BaseCommand.php
+++ b/hwe/sammo/Command/BaseCommand.php
@@ -6,7 +6,8 @@ use \sammo\{
General, GameConst,
ActionLogger,
LastTurn,
- NotInheritedMethodException
+ NotInheritedMethodException,
+ RandUtil
};
use function \sammo\getNationStaticInfo;
@@ -473,7 +474,7 @@ abstract class BaseCommand{
abstract public function getPreReqTurn():int;
abstract public function getPostReqTurn():int;
- abstract public function run():bool;
+ abstract public function run(RandUtil $rng):bool;
public function exportJSVars():array {
return [];
diff --git a/hwe/sammo/Command/General/che_NPC능동.php b/hwe/sammo/Command/General/che_NPC능동.php
index 1b3d8de9..70815485 100644
--- a/hwe/sammo/Command/General/che_NPC능동.php
+++ b/hwe/sammo/Command/General/che_NPC능동.php
@@ -75,7 +75,7 @@ class che_NPC능동 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -98,7 +98,7 @@ class che_NPC능동 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
}
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_강행.php b/hwe/sammo/Command/General/che_강행.php
index 23b79c05..ff2ec0b5 100644
--- a/hwe/sammo/Command/General/che_강행.php
+++ b/hwe/sammo/Command/General/che_강행.php
@@ -111,7 +111,7 @@ class che_강행 extends Command\GeneralCommand
return "{$failReason} {$destCityName}>{$josaRo} {$commandName} 실패.";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -156,7 +156,7 @@ class che_강행 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_거병.php b/hwe/sammo/Command/General/che_거병.php
index 2fd6a285..2914f430 100644
--- a/hwe/sammo/Command/General/che_거병.php
+++ b/hwe/sammo/Command/General/che_거병.php
@@ -59,7 +59,7 @@ class che_거병 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -174,7 +174,7 @@ class che_거병 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_건국.php b/hwe/sammo/Command/General/che_건국.php
index 5495d397..7fc17f98 100644
--- a/hwe/sammo/Command/General/che_건국.php
+++ b/hwe/sammo/Command/General/che_건국.php
@@ -20,6 +20,7 @@ use \sammo\Constraint\ConstraintHelper;
use sammo\Enums\InheritanceKey;
use function sammo\buildNationTypeClass;
+use function sammo\genGenericUniqueRNGFromGeneral;
use function sammo\refreshNationStaticInfo;
use function sammo\GetNationColors;
@@ -126,7 +127,7 @@ class che_건국 extends Command\GeneralCommand
return 0;
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -190,7 +191,7 @@ class che_건국 extends Command\GeneralCommand
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general, '건국');
+ tryUniqueItemLottery(genGenericUniqueRNGFromGeneral($general), $general, '건국');
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_견문.php b/hwe/sammo/Command/General/che_견문.php
index c7903fd5..1af237da 100644
--- a/hwe/sammo/Command/General/che_견문.php
+++ b/hwe/sammo/Command/General/che_견문.php
@@ -51,7 +51,7 @@ class che_견문 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -99,10 +99,10 @@ class che_견문 extends Command\GeneralCommand{
$text = str_replace(':riceAmount:', '200', $text);
}
if($type & SightseeingMessage::Wounded){
- $general->increaseVarWithLimit('injury', Util::randRangeInt(10, 20), null, 80);
+ $general->increaseVarWithLimit('injury', $rng->nextRangeInt(10, 20), null, 80);
}
if($type & SightseeingMessage::HeavyWounded){
- $general->increaseVarWithLimit('injury', Util::randRangeInt(20, 50), null, 80);
+ $general->increaseVarWithLimit('injury', $rng->nextRangeInt(20, 50), null, 80);
}
$logger = $general->getLogger();
@@ -112,7 +112,7 @@ class che_견문 extends Command\GeneralCommand{
$general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_군량매매.php b/hwe/sammo/Command/General/che_군량매매.php
index f0af7ca8..1bdad1a1 100644
--- a/hwe/sammo/Command/General/che_군량매매.php
+++ b/hwe/sammo/Command/General/che_군량매매.php
@@ -98,7 +98,7 @@ class che_군량매매 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -166,7 +166,7 @@ class che_군량매매 extends Command\GeneralCommand{
$exp = 30;
$ded = 50;
- $incStat = Util::choiceRandomUsingWeight([
+ $incStat = $rng->choiceUsingWeight([
'leadership_exp'=>$general->getLeadership(false, false, false, false),
'strength_exp'=>$general->getStrength(false, false, false, false),
'intel_exp'=>$general->getIntel(false, false, false, false)
@@ -178,7 +178,7 @@ class che_군량매매 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_귀환.php b/hwe/sammo/Command/General/che_귀환.php
index 7ca7c1f4..30096673 100644
--- a/hwe/sammo/Command/General/che_귀환.php
+++ b/hwe/sammo/Command/General/che_귀환.php
@@ -58,7 +58,7 @@ class che_귀환 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -95,7 +95,7 @@ class che_귀환 extends Command\GeneralCommand{
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_기술연구.php b/hwe/sammo/Command/General/che_기술연구.php
index 2ed2c351..6bb824b3 100644
--- a/hwe/sammo/Command/General/che_기술연구.php
+++ b/hwe/sammo/Command/General/che_기술연구.php
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
LastTurn,
Command, GameConst
@@ -11,7 +11,7 @@ use \sammo\{
use function sammo\{
TechLimit,
- CriticalRatioDomestic,
+ CriticalRatioDomestic,
CriticalScoreEx,
tryUniqueItemLottery,
updateMaxDomesticCritical
@@ -38,11 +38,11 @@ class che_기술연구 extends che_상업투자{
$this->setCity();
$this->setNation(['tech']);
-
+
[$reqGold, $reqRice] = $this->getCost();
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity(),
@@ -53,7 +53,7 @@ class che_기술연구 extends che_상업투자{
$this->reqGold = $reqGold;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -64,7 +64,7 @@ class che_기술연구 extends che_상업투자{
$trust = Util::valueFit($this->city['trust'], 50);
- $score = Util::valueFit($this->calcBaseScore(), 1);
+ $score = Util::valueFit($this->calcBaseScore($rng), 1);
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
if($trust < 80){
@@ -77,9 +77,9 @@ class che_기술연구 extends che_상업투자{
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
$normalRatio = 1 - $failRatio - $successRatio;
- $pick = Util::choiceRandomUsingWeight([
- 'fail'=>$failRatio,
- 'success'=>$successRatio,
+ $pick = $rng->choiceUsingWeight([
+ 'fail'=>$failRatio,
+ 'success'=>$successRatio,
'normal'=>$normalRatio
]);
@@ -87,14 +87,14 @@ class che_기술연구 extends che_상업투자{
$date = $general->getTurnTime($general::TURNTIME_HM);
- $score *= CriticalScoreEx($pick);
+ $score *= CriticalScoreEx($rng, $pick);
$score = Util::round($score);
$exp = $score * 0.7;
$ded = $score * 1.0;
if($pick == 'success'){
- updateMaxDomesticCritical($general, $score);
+ updateMaxDomesticCritical($general, $score);
}
else{
$general->setAuxVar('max_domestic_critical', 0);
@@ -134,11 +134,11 @@ class che_기술연구 extends che_상업투자{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_단련.php b/hwe/sammo/Command/General/che_단련.php
index c5fa2d63..b4d18345 100644
--- a/hwe/sammo/Command/General/che_단련.php
+++ b/hwe/sammo/Command/General/che_단련.php
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -35,9 +35,9 @@ class che_단련 extends Command\GeneralCommand{
$this->setNation();
[$reqGold, $reqRice] = $this->getCost();
-
+
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::ReqGeneralCrew(),
ConstraintHelper::ReqGeneralValue('train', '훈련', '>=', GameConst::$defaultTrainLow),
ConstraintHelper::ReqGeneralValue('atmos', '사기', '>=', GameConst::$defaultAtmosLow),
@@ -66,7 +66,7 @@ class che_단련 extends Command\GeneralCommand{
$env = $this->env;
return [$env['develcost'], $env['develcost']];
}
-
+
public function getPreReqTurn():int{
return 0;
}
@@ -75,7 +75,7 @@ class che_단련 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -85,7 +85,7 @@ class che_단련 extends Command\GeneralCommand{
$general = $this->generalObj;
$date = $general->getTurnTime($general::TURNTIME_HM);
- [$pick, $multiplier] = Util::choiceRandomUsingWeightPair([
+ [$pick, $multiplier] = $rng->choiceUsingWeightPair([
[['success', 3], 0.34],
[['normal', 2], 0.33],
[['fail', 1], 0.33]
@@ -113,7 +113,7 @@ class che_단련 extends Command\GeneralCommand{
$general->addDex($general->getCrewTypeObj(), $score, false);
- $incStat = Util::choiceRandomUsingWeight([
+ $incStat = $rng->choiceUsingWeight([
'leadership_exp'=>$general->getLeadership(false, false, false, false),
'strength_exp'=>$general->getStrength(false, false, false, false),
'intel_exp'=>$general->getIntel(false, false, false, false)
@@ -126,11 +126,11 @@ class che_단련 extends Command\GeneralCommand{
$general->increaseVar($incStat, 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_등용.php b/hwe/sammo/Command/General/che_등용.php
index 8c0d5c70..196f6c6a 100644
--- a/hwe/sammo/Command/General/che_등용.php
+++ b/hwe/sammo/Command/General/che_등용.php
@@ -136,7 +136,7 @@ class che_등용 extends Command\GeneralCommand
return "【{$destGeneralName}】{$josaUl} {$name}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -173,7 +173,7 @@ class che_등용 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_등용수락.php b/hwe/sammo/Command/General/che_등용수락.php
index d50b8b35..223eab6f 100644
--- a/hwe/sammo/Command/General/che_등용수락.php
+++ b/hwe/sammo/Command/General/che_등용수락.php
@@ -100,7 +100,7 @@ class che_등용수락 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
diff --git a/hwe/sammo/Command/General/che_랜덤임관.php b/hwe/sammo/Command/General/che_랜덤임관.php
index 6e6ca261..ad9a6624 100644
--- a/hwe/sammo/Command/General/che_랜덤임관.php
+++ b/hwe/sammo/Command/General/che_랜덤임관.php
@@ -14,6 +14,7 @@ use \sammo\GameUnitConst;
use \sammo\LastTurn;
use \sammo\Command;
+use function sammo\genGenericUniqueRNGFromGeneral;
use function \sammo\tryUniqueItemLottery;
use \sammo\Constraint\Constraint;
@@ -110,7 +111,7 @@ class che_랜덤임관 extends Command\GeneralCommand
return 0;
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -162,7 +163,7 @@ class che_랜덤임관 extends Command\GeneralCommand
$score = log($affinity + 1, 2); //0~
//쉐킷쉐킷
- $score += Util::randF();
+ $score += $rng->nextFloat1();
$score += sqrt($testNation['gennum'] / $allGen);
@@ -219,7 +220,7 @@ class che_랜덤임관 extends Command\GeneralCommand
}
if ($generalsCnt) {
- $destNation = Util::choiceRandomUsingWeightPair($generalsCnt);
+ $destNation = $rng->choiceUsingWeightPair($generalsCnt);
}
}
@@ -251,7 +252,7 @@ class che_랜덤임관 extends Command\GeneralCommand
'천하의 균형을 맞추기 위해',
'오랜 은거를 마치고',
];
- $randomTalk = Util::choiceRandom($talkList);
+ $randomTalk = $rng->choice($talkList);
$logger->pushGeneralActionLog("{$destNationName}>에 랜덤 임관했습니다. <1>$date>");
$logger->pushGeneralHistoryLog("{$destNationName}>에 랜덤 임관");
@@ -290,7 +291,7 @@ class che_랜덤임관 extends Command\GeneralCommand
$general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general, '랜덤 임관');
+ tryUniqueItemLottery(genGenericUniqueRNGFromGeneral($general), $general, '랜덤 임관');
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_모반시도.php b/hwe/sammo/Command/General/che_모반시도.php
index 2e11afda..0be42d50 100644
--- a/hwe/sammo/Command/General/che_모반시도.php
+++ b/hwe/sammo/Command/General/che_모반시도.php
@@ -55,7 +55,7 @@ class che_모반시도 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -99,7 +99,7 @@ class che_모반시도 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
$lordGeneral->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_물자조달.php b/hwe/sammo/Command/General/che_물자조달.php
index 6ef41490..182bb300 100644
--- a/hwe/sammo/Command/General/che_물자조달.php
+++ b/hwe/sammo/Command/General/che_물자조달.php
@@ -60,7 +60,7 @@ class che_물자조달 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -70,14 +70,14 @@ class che_물자조달 extends Command\GeneralCommand{
$general = $this->generalObj;
$date = $general->getTurnTime($general::TURNTIME_HM);
- [$resName, $resKey] = Util::choiceRandom([
+ [$resName, $resKey] = $rng->choice([
['금', 'gold'],
['쌀', 'rice']
]);
$score = $general->getLeadership() + $general->getStrength() + $general->getIntel();
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
- $score *= Util::randRange(0.8, 1.2);
+ $score *= $rng->nextRange(0.8, 1.2);
$successRatio = 0.1;
$failRatio = 0.3;
@@ -86,12 +86,12 @@ class che_물자조달 extends Command\GeneralCommand{
$failRatio = $general->onCalcDomestic('조달', 'fail', $failRatio);
$normalRatio = 1 - $failRatio - $successRatio;
- $pick = Util::choiceRandomUsingWeight([
+ $pick = $rng->choiceUsingWeight([
'fail'=>$failRatio,
'success'=>$successRatio,
'normal'=>$normalRatio
]);
- $score *= CriticalScoreEx($pick);
+ $score *= CriticalScoreEx($rng, $pick);
$score = $general->onCalcDomestic('조달', 'score', $score);
$score = Util::round($score);
@@ -112,7 +112,7 @@ class che_물자조달 extends Command\GeneralCommand{
$exp = $score * 0.7 / 3;
$ded = $score * 1.0 / 3;
- $incStat = Util::choiceRandomUsingWeight([
+ $incStat = $rng->choiceUsingWeight([
'leadership_exp'=>$general->getLeadership(false, false, false, false),
'strength_exp'=>$general->getStrength(false, false, false, false),
'intel_exp'=>$general->getIntel(false, false, false, false)
@@ -128,7 +128,7 @@ class che_물자조달 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_방랑.php b/hwe/sammo/Command/General/che_방랑.php
index 0daf2e2a..74a559be 100644
--- a/hwe/sammo/Command/General/che_방랑.php
+++ b/hwe/sammo/Command/General/che_방랑.php
@@ -59,7 +59,7 @@ class che_방랑 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -125,7 +125,7 @@ class che_방랑 extends Command\GeneralCommand{
refreshNationStaticInfo();
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_사기진작.php b/hwe/sammo/Command/General/che_사기진작.php
index f44a58de..f4dc8829 100644
--- a/hwe/sammo/Command/General/che_사기진작.php
+++ b/hwe/sammo/Command/General/che_사기진작.php
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -34,13 +34,13 @@ class che_사기진작 extends Command\GeneralCommand{
[$reqGold, $reqRice] = $this->getCost();
$this->minConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
];
-
+
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::ReqGeneralCrew(),
@@ -62,7 +62,7 @@ class che_사기진작 extends Command\GeneralCommand{
$general = $this->generalObj;
return [Util::round($general->getVar('crew')/100), 0];
}
-
+
public function getPreReqTurn():int{
return 0;
}
@@ -71,7 +71,7 @@ class che_사기진작 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -103,11 +103,11 @@ class che_사기진작 extends Command\GeneralCommand{
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_상업투자.php b/hwe/sammo/Command/General/che_상업투자.php
index 0a986e07..3838ca9a 100644
--- a/hwe/sammo/Command/General/che_상업투자.php
+++ b/hwe/sammo/Command/General/che_상업투자.php
@@ -3,12 +3,13 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst,
LastTurn,
GameUnitConst,
- Command
+ Command,
+ RandUtil
};
use function \sammo\getDomesticExpLevelBonus;
@@ -41,11 +42,11 @@ class che_상업투자 extends Command\GeneralCommand{
$this->setCity();
$this->setNation();
-
+
[$reqGold, $reqRice] = $this->getCost();
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity(),
@@ -82,15 +83,15 @@ class che_상업투자 extends Command\GeneralCommand{
$develCost = $this->env['develcost'];
$reqGold = Util::round($this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost));
$reqRice = 0;
-
+
return [$reqGold, $reqRice];
}
-
+
public function getCompensationStyle():?int{
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
}
-
+
public function getPreReqTurn():int{
return 0;
}
@@ -99,7 +100,7 @@ class che_상업투자 extends Command\GeneralCommand{
return 0;
}
- protected function calcBaseScore():float{
+ protected function calcBaseScore(RandUtil $rng):float{
$trust = Util::valueFit($this->city['trust'], 50);
$general = $this->generalObj;
@@ -115,16 +116,16 @@ class che_상업투자 extends Command\GeneralCommand{
else{
throw new \sammo\MustNotBeReachedException();
}
-
+
$score *= $trust / 100;
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
- $score *= Util::randRange(0.8, 1.2);
+ $score *= $rng->nextRange(0.8, 1.2);
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
return $score;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -135,7 +136,7 @@ class che_상업투자 extends Command\GeneralCommand{
$trust = Util::valueFit($this->city['trust'], 50);
- $score = Util::valueFit($this->calcBaseScore(), 1);
+ $score = Util::valueFit($this->calcBaseScore($rng), 1);
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
if($trust < 80){
@@ -148,9 +149,9 @@ class che_상업투자 extends Command\GeneralCommand{
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
$normalRatio = 1 - $failRatio - $successRatio;
- $pick = Util::choiceRandomUsingWeight([
- 'fail'=>$failRatio,
- 'success'=>$successRatio,
+ $pick = $rng->choiceUsingWeight([
+ 'fail'=>$failRatio,
+ 'success'=>$successRatio,
'normal'=>$normalRatio
]);
@@ -158,14 +159,14 @@ class che_상업투자 extends Command\GeneralCommand{
$date = $general->getTurnTime($general::TURNTIME_HM);
- $score *= CriticalScoreEx($pick);
+ $score *= CriticalScoreEx($rng, $pick);
$score = Util::round($score);
$exp = $score * 0.7;
$ded = $score * 1.0;
if($pick == 'success'){
- updateMaxDomesticCritical($general, $score);
+ updateMaxDomesticCritical($general, $score);
}
else{
$general->setAuxVar('max_domestic_critical', 0);
@@ -204,7 +205,7 @@ class che_상업투자 extends Command\GeneralCommand{
$general->increaseVar(static::$statKey.'_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_선동.php b/hwe/sammo/Command/General/che_선동.php
index de193a7b..a8195716 100644
--- a/hwe/sammo/Command/General/che_선동.php
+++ b/hwe/sammo/Command/General/che_선동.php
@@ -9,6 +9,7 @@ use \sammo\ActionLogger;
use \sammo\GameConst;
use \sammo\GameUnitConst;
use \sammo\Command;
+use sammo\RandUtil;
class che_선동 extends che_화계{
static protected $actionName = '선동';
@@ -16,7 +17,7 @@ class che_선동 extends che_화계{
static protected $statType = 'leadership';
static protected $injuryGeneral = true;
- protected function affectDestCity(int $injuryCount){
+ protected function affectDestCity(RandUtil $rng, int $injuryCount){
$general = $this->generalObj;
$date = $general->getTurnTime($general::TURNTIME_HM);
@@ -30,15 +31,15 @@ class che_선동 extends che_화계{
$commandName = $this->getName();
// 선동 최대 10
- $secuAmount = Util::valueFit(Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['secu']);
+ $secuAmount = Util::valueFit($rng->nextRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['secu']);
$trustAmount = Util::valueFit(
- Util::randRange(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) / 50,
- null,
+ $rng->nextRange(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) / 50,
+ null,
$destCity['trust']
);
$destCity['secu'] -= $secuAmount;
$destCity['trust'] -= $trustAmount;
-
+
DB::db()->update('city', [
'state'=>32,
'secu'=>$destCity['secu'],
@@ -57,5 +58,5 @@ class che_선동 extends che_화계{
ActionLogger::PLAIN
);
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_선양.php b/hwe/sammo/Command/General/che_선양.php
index 7c4d8239..922dcc48 100644
--- a/hwe/sammo/Command/General/che_선양.php
+++ b/hwe/sammo/Command/General/che_선양.php
@@ -99,7 +99,7 @@ class che_선양 extends Command\GeneralCommand
return "【{$destGeneralName}】에게 {$name}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -139,7 +139,7 @@ class che_선양 extends Command\GeneralCommand
$general->increaseInheritancePoint(InheritanceKey::active_action, 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
$destGeneral->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_소집해제.php b/hwe/sammo/Command/General/che_소집해제.php
index 3a8d57e3..6d474a4b 100644
--- a/hwe/sammo/Command/General/che_소집해제.php
+++ b/hwe/sammo/Command/General/che_소집해제.php
@@ -54,7 +54,7 @@ class che_소집해제 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -82,7 +82,7 @@ class che_소집해제 extends Command\GeneralCommand{
$general->addDedication($ded);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_숙련전환.php b/hwe/sammo/Command/General/che_숙련전환.php
index 1b4d0e0f..b5a5a2fa 100644
--- a/hwe/sammo/Command/General/che_숙련전환.php
+++ b/hwe/sammo/Command/General/che_숙련전환.php
@@ -144,7 +144,7 @@ class che_숙련전환 extends Command\GeneralCommand
return 0;
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -179,7 +179,7 @@ class che_숙련전환 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 2);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_요양.php b/hwe/sammo/Command/General/che_요양.php
index 48d31bfc..b316240e 100644
--- a/hwe/sammo/Command/General/che_요양.php
+++ b/hwe/sammo/Command/General/che_요양.php
@@ -46,7 +46,7 @@ class che_요양 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -71,7 +71,7 @@ class che_요양 extends Command\GeneralCommand{
$general->addDedication($ded);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_은퇴.php b/hwe/sammo/Command/General/che_은퇴.php
index 570a73f7..4abc5648 100644
--- a/hwe/sammo/Command/General/che_은퇴.php
+++ b/hwe/sammo/Command/General/che_은퇴.php
@@ -53,7 +53,7 @@ class che_은퇴 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -69,7 +69,7 @@ class che_은퇴 extends Command\GeneralCommand{
$logger->pushGeneralActionLog("은퇴하였습니다. <1>$date>");
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_이동.php b/hwe/sammo/Command/General/che_이동.php
index b3ff7583..edbd88eb 100644
--- a/hwe/sammo/Command/General/che_이동.php
+++ b/hwe/sammo/Command/General/che_이동.php
@@ -119,7 +119,7 @@ class che_이동 extends Command\GeneralCommand
return "{$failReason} {$destCityName}>{$josaRo} {$commandName} 실패.";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -164,7 +164,7 @@ class che_이동 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_인재탐색.php b/hwe/sammo/Command/General/che_인재탐색.php
index a1507c19..6d1a33c1 100644
--- a/hwe/sammo/Command/General/che_인재탐색.php
+++ b/hwe/sammo/Command/General/che_인재탐색.php
@@ -109,7 +109,7 @@ class che_인재탐색 extends Command\GeneralCommand
return $foundProp;
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -128,14 +128,14 @@ class che_인재탐색 extends Command\GeneralCommand
$totalNpcCnt = $db->queryFirstField('SELECT count(`no`) FROM general WHERE 3 <= npc AND npc <= 4');
$foundProp = $this->calcFoundProp($env['maxgeneral'], $totalGenCnt, $totalNpcCnt);
- $foundNpc = Util::randBool($foundProp);
+ $foundNpc = $rng->nextBool($foundProp);
$logger = $general->getLogger();
if (!$foundNpc) {
$logger->pushGeneralActionLog("인재를 찾을 수 없었습니다. <1>$date>");
- $incStat = Util::choiceRandomUsingWeight([
+ $incStat = $rng->choiceUsingWeight([
'leadership_exp' => $general->getLeadership(false, false, false, false),
'strength_exp' => $general->getStrength(false, false, false, false),
'intel_exp' => $general->getIntel(false, false, false, false)
@@ -152,7 +152,7 @@ class che_인재탐색 extends Command\GeneralCommand
$general->increaseVar($incStat, 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
@@ -163,9 +163,9 @@ class che_인재탐색 extends Command\GeneralCommand
$scoutType = "발견";
- $age = Util::randRangeInt(20, 25);
+ $age = $rng->nextRangeInt(20, 25);
$birthYear = $env['year'] - $age;
- $deathYear = $env['year'] + Util::randRangeInt(10, 50);
+ $deathYear = $env['year'] + $rng->nextRangeInt(10, 50);
$avgGen = $db->queryFirstRow(
'SELECT avg(dedication) as ded,avg(experience) as exp,
@@ -175,7 +175,7 @@ class che_인재탐색 extends Command\GeneralCommand
$pickTypeList = ['무' => 6, '지' => 6, '무지' => 3];
- $pickedNPC = pickGeneralFromPool($db, 0, 1)[0];
+ $pickedNPC = pickGeneralFromPool($db, $rng, 0, 1)[0];
$newNPC = $pickedNPC->getGeneralBuilder();
$newNPC->setSpecial('None', 'None');
@@ -200,7 +200,7 @@ class che_인재탐색 extends Command\GeneralCommand
$logger->pushGlobalActionLog("{$generalName}>{$josaYi} $npcName>{$josaRa}는 인재>를 {$scoutType}하였습니다!");
$logger->pushGeneralHistoryLog("$npcName>{$josaRa}는 인재>를 {$scoutType}");
- $incStat = Util::choiceRandomUsingWeight([
+ $incStat = $rng->choiceUsingWeight([
'leadership_exp' => $general->getLeadership(false, false, false, false),
'strength_exp' => $general->getStrength(false, false, false, false),
'intel_exp' => $general->getIntel(false, false, false, false)
@@ -218,7 +218,7 @@ class che_인재탐색 extends Command\GeneralCommand
$general->increaseVar($incStat, 3);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
diff --git a/hwe/sammo/Command/General/che_임관.php b/hwe/sammo/Command/General/che_임관.php
index c4333c0a..2a7e4e20 100644
--- a/hwe/sammo/Command/General/che_임관.php
+++ b/hwe/sammo/Command/General/che_임관.php
@@ -119,7 +119,7 @@ class che_임관 extends Command\GeneralCommand
return "【{$destNationName}】{$josaRo} {$commandName}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -179,7 +179,7 @@ class che_임관 extends Command\GeneralCommand
$general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_장비매매.php b/hwe/sammo/Command/General/che_장비매매.php
index ae7f1e7b..2204dae9 100644
--- a/hwe/sammo/Command/General/che_장비매매.php
+++ b/hwe/sammo/Command/General/che_장비매매.php
@@ -141,7 +141,7 @@ class che_장비매매 extends Command\GeneralCommand
return "【{$itemName}】{$josaUl} 구입";
}
- public function run(): bool
+ public function run(\sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -174,11 +174,11 @@ class che_장비매매 extends Command\GeneralCommand
$logger->pushGeneralActionLog("{$itemName}>{$josaUl} 구입했습니다. <1>$date>");
$general->increaseVarWithLimit('gold', -$cost, 0);
$general->setItem($itemType, $itemCode);
- $general->onArbitraryAction($general, '장비매매', '구매', ['itemCode' => $itemCode]);
+ $general->onArbitraryAction($general, $rng, '장비매매', '구매', ['itemCode' => $itemCode]);
} else {
$logger->pushGeneralActionLog("{$itemName}>{$josaUl} 판매했습니다. <1>$date>");
$general->increaseVarWithLimit('gold', $cost / 2);
- $general->onArbitraryAction($general, '장비매매', '판매', ['itemCode' => $itemCode]);
+ $general->onArbitraryAction($general, $rng, '장비매매', '판매', ['itemCode' => $itemCode]);
$general->setItem($itemType, null);
if(!$itemObj->isBuyable()){
@@ -195,7 +195,7 @@ class che_장비매매 extends Command\GeneralCommand
$general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_장수대상임관.php b/hwe/sammo/Command/General/che_장수대상임관.php
index e2c299aa..480be561 100644
--- a/hwe/sammo/Command/General/che_장수대상임관.php
+++ b/hwe/sammo/Command/General/che_장수대상임관.php
@@ -116,7 +116,7 @@ class che_장수대상임관 extends Command\GeneralCommand{
return "【{$destGeneralName}】{$josaUl} 따라 임관";
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -176,7 +176,7 @@ class che_장수대상임관 extends Command\GeneralCommand{
$general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_전투태세.php b/hwe/sammo/Command/General/che_전투태세.php
index 331e35a0..bd96e9ba 100644
--- a/hwe/sammo/Command/General/che_전투태세.php
+++ b/hwe/sammo/Command/General/che_전투태세.php
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -34,9 +34,9 @@ class che_전투태세 extends Command\GeneralCommand{
$this->setNation();
[$reqGold, $reqRice] = $this->getCost();
-
+
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::ReqGeneralCrew(),
@@ -53,7 +53,7 @@ class che_전투태세 extends Command\GeneralCommand{
$techCost = getTechCost($this->nation['tech']);
return [Util::round($crew / 100 * 3 * $techCost), 0];
}
-
+
public function getPreReqTurn():int{
return 3;
}
@@ -62,7 +62,7 @@ class che_전투태세 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -102,7 +102,7 @@ class che_전투태세 extends Command\GeneralCommand{
return true;
}
-
+
$logger->pushGeneralActionLog("전투태세 완료! ({$term}/3) <1>$date>");
$general->increaseVarWithLimit('train', 0, GameConst::$maxTrainByCommand - 5); //95보다 높으면 '깎이지는 않음'
@@ -117,15 +117,15 @@ class che_전투태세 extends Command\GeneralCommand{
$crew = $general->getVar('crew');
$general->addDex($general->getCrewTypeObj(), $crew / 100 * 3, false);
-
+
$general->increaseVar('leadership_exp', 3);
$this->setResultTurn($turnResult);
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_전투특기초기화.php b/hwe/sammo/Command/General/che_전투특기초기화.php
index 72a431d3..cf5bfa5f 100644
--- a/hwe/sammo/Command/General/che_전투특기초기화.php
+++ b/hwe/sammo/Command/General/che_전투특기초기화.php
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -32,7 +32,7 @@ class che_전투특기초기화 extends Command\GeneralCommand{
$this->minConditionConstraints=[
ConstraintHelper::ReqGeneralValue(static::$specialType, static::$specialText, '!=', 'None', '특기가 없습니다.'),
];
-
+
$this->fullConditionConstraints=[
ConstraintHelper::ReqGeneralValue(static::$specialType, static::$specialText, '!=', 'None', '특기가 없습니다.')
];
@@ -54,7 +54,7 @@ class che_전투특기초기화 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
-
+
public function getPreReqTurn():int{
return 1;
}
@@ -69,7 +69,7 @@ class che_전투특기초기화 extends Command\GeneralCommand{
return "새로운 적성을 찾는 중... ({$term}/{$termMax})";
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -83,7 +83,7 @@ class che_전투특기초기화 extends Command\GeneralCommand{
$specialName = static::$specialText;
$env = $this->env;
-
+
$yearMonth = Util::joinYearMonth($env['year'], $env['month']);
$oldSpecialList = $general->getAuxVar($oldTypeKey)??[];
$oldSpecialList[] = $general->getVar(static::$specialType);
@@ -97,11 +97,11 @@ class che_전투특기초기화 extends Command\GeneralCommand{
$logger->pushGeneralActionLog("새로운 {$specialName}를 가질 준비가 되었습니다. <1>$date>");
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_정착장려.php b/hwe/sammo/Command/General/che_정착장려.php
index dc9c6009..6df6de64 100644
--- a/hwe/sammo/Command/General/che_정착장려.php
+++ b/hwe/sammo/Command/General/che_정착장려.php
@@ -3,12 +3,13 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst,
LastTurn,
GameUnitConst,
- Command
+ Command,
+ RandUtil
};
use function \sammo\getDomesticExpLevelBonus;
@@ -40,11 +41,11 @@ class che_정착장려 extends Command\GeneralCommand{
$this->setCity();
$this->setNation();
-
+
[$reqGold, $reqRice] = $this->getCost();
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity(),
@@ -81,14 +82,14 @@ class che_정착장려 extends Command\GeneralCommand{
$develCost = $this->env['develcost'] * 2;
$reqGold = 0;
$reqRice = Util::round($this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost));
-
+
return [$reqGold, $reqRice];
}
public function getCompensationStyle():?int{
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
}
-
+
public function getPreReqTurn():int{
return 0;
}
@@ -97,7 +98,7 @@ class che_정착장려 extends Command\GeneralCommand{
return 0;
}
- protected function calcBaseScore():float{
+ protected function calcBaseScore(RandUtil $rng):float{
$general = $this->generalObj;
if(static::$statKey == 'leadership'){
@@ -106,15 +107,15 @@ class che_정착장려 extends Command\GeneralCommand{
else{
throw new \sammo\MustNotBeReachedException();
}
-
+
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
- $score *= Util::randRange(0.8, 1.2);
+ $score *= $rng->nextRange(0.8, 1.2);
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
return $score;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -123,7 +124,7 @@ class che_정착장려 extends Command\GeneralCommand{
$general = $this->generalObj;
- $score = Util::valueFit($this->calcBaseScore(), 1);
+ $score = Util::valueFit($this->calcBaseScore($rng), 1);
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
$successRatio = $general->onCalcDomestic(static::$actionKey, 'success', $successRatio);
@@ -133,9 +134,9 @@ class che_정착장려 extends Command\GeneralCommand{
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
$normalRatio = 1 - $failRatio - $successRatio;
- $pick = Util::choiceRandomUsingWeight([
- 'fail'=>$failRatio,
- 'success'=>$successRatio,
+ $pick = $rng->choiceUsingWeight([
+ 'fail'=>$failRatio,
+ 'success'=>$successRatio,
'normal'=>$normalRatio
]);
@@ -143,14 +144,14 @@ class che_정착장려 extends Command\GeneralCommand{
$date = $general->getTurnTime($general::TURNTIME_HM);
- $score *= CriticalScoreEx($pick);
+ $score *= CriticalScoreEx($rng, $pick);
$score = Util::round($score);
$exp = $score * 0.7;
$ded = $score * 1.0;
if($pick == 'success'){
- updateMaxDomesticCritical($general, $score);
+ updateMaxDomesticCritical($general, $score);
}
else{
$general->setAuxVar('max_domestic_critical', 0);
@@ -187,7 +188,7 @@ class che_정착장려 extends Command\GeneralCommand{
$general->increaseVar(static::$statKey.'_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_주민선정.php b/hwe/sammo/Command/General/che_주민선정.php
index 1b70b6ea..af8f7009 100644
--- a/hwe/sammo/Command/General/che_주민선정.php
+++ b/hwe/sammo/Command/General/che_주민선정.php
@@ -3,12 +3,13 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst,
LastTurn,
GameUnitConst,
- Command
+ Command,
+ RandUtil
};
use function \sammo\getDomesticExpLevelBonus;
@@ -40,11 +41,11 @@ class che_주민선정 extends Command\GeneralCommand{
$this->setCity();
$this->setNation();
-
+
[$reqGold, $reqRice] = $this->getCost();
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity(),
@@ -81,14 +82,14 @@ class che_주민선정 extends Command\GeneralCommand{
$develCost = $this->env['develcost'] * 2;
$reqGold = 0;
$reqRice = $this->generalObj->onCalcDomestic(static::$actionKey, 'cost', $develCost);
-
+
return [$reqGold, Util::round($reqRice)];
}
public function getCompensationStyle():?int{
return $this->generalObj->onCalcDomestic(static::$actionKey, 'score', 100)<=>100;
}
-
+
public function getPreReqTurn():int{
return 0;
}
@@ -97,7 +98,7 @@ class che_주민선정 extends Command\GeneralCommand{
return 0;
}
- protected function calcBaseScore():float{
+ protected function calcBaseScore(RandUtil $rng):float{
$general = $this->generalObj;
if(static::$statKey == 'leadership'){
@@ -106,16 +107,16 @@ class che_주민선정 extends Command\GeneralCommand{
else{
throw new \sammo\MustNotBeReachedException();
}
-
+
$score *= getDomesticExpLevelBonus($general->getVar('explevel'));
- $score *= Util::randRange(0.8, 1.2);
+ $score *= $rng->nextRange(0.8, 1.2);
$score = $general->onCalcDomestic(static::$actionKey, 'score', $score);
$score = Util::valueFit($score, 1);
return $score;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -124,7 +125,7 @@ class che_주민선정 extends Command\GeneralCommand{
$general = $this->generalObj;
- $score = Util::valueFit($this->calcBaseScore(), 1);
+ $score = Util::valueFit($this->calcBaseScore($rng), 1);
['success'=>$successRatio, 'fail'=>$failRatio] = CriticalRatioDomestic($general, static::$statKey);
$successRatio = $general->onCalcDomestic(static::$actionKey, 'success', $successRatio);
@@ -134,9 +135,9 @@ class che_주민선정 extends Command\GeneralCommand{
$failRatio = Util::valueFit($failRatio, 0, 1 - $successRatio);
$normalRatio = 1 - $failRatio - $successRatio;
- $pick = Util::choiceRandomUsingWeight([
- 'fail'=>$failRatio,
- 'success'=>$successRatio,
+ $pick = $rng->choiceUsingWeight([
+ 'fail'=>$failRatio,
+ 'success'=>$successRatio,
'normal'=>$normalRatio
]);
@@ -144,13 +145,13 @@ class che_주민선정 extends Command\GeneralCommand{
$date = $general->getTurnTime($general::TURNTIME_HM);
- $score *= CriticalScoreEx($pick);
+ $score *= CriticalScoreEx($rng, $pick);
$exp = $score * 0.7;
$ded = $score * 1.0;
if($pick == 'success'){
- updateMaxDomesticCritical($general, $score);
+ updateMaxDomesticCritical($general, $score);
}
else{
$general->setAuxVar('max_domestic_critical', 0);
@@ -187,11 +188,11 @@ class che_주민선정 extends Command\GeneralCommand{
$general->increaseVar(static::$statKey.'_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_증여.php b/hwe/sammo/Command/General/che_증여.php
index 81521971..a1f1426a 100644
--- a/hwe/sammo/Command/General/che_증여.php
+++ b/hwe/sammo/Command/General/che_증여.php
@@ -132,7 +132,7 @@ class che_증여 extends Command\GeneralCommand
return "【{$destGeneralName}】에게 {$resText} {$this->arg['amount']}을 {$name}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -169,7 +169,7 @@ class che_증여 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
$destGeneral->applyDB($db);
diff --git a/hwe/sammo/Command/General/che_집합.php b/hwe/sammo/Command/General/che_집합.php
index 3afccf61..f7497099 100644
--- a/hwe/sammo/Command/General/che_집합.php
+++ b/hwe/sammo/Command/General/che_집합.php
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -34,9 +34,9 @@ class che_집합 extends Command\GeneralCommand{
$this->setNation();
[$reqGold, $reqRice] = $this->getCost();
-
+
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::SuppliedCity(),
ConstraintHelper::MustBeTroopLeader(),
@@ -52,7 +52,7 @@ class che_집합 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
-
+
public function getPreReqTurn():int{
return 0;
}
@@ -61,7 +61,7 @@ class che_집합 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -103,11 +103,11 @@ class che_집합 extends Command\GeneralCommand{
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_징병.php b/hwe/sammo/Command/General/che_징병.php
index b2d56703..3e538c9c 100644
--- a/hwe/sammo/Command/General/che_징병.php
+++ b/hwe/sammo/Command/General/che_징병.php
@@ -162,7 +162,7 @@ class che_징병 extends Command\GeneralCommand
return 0;
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -222,7 +222,7 @@ class che_징병 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
$general->setAuxVar('armType', $reqCrewType->armType);
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_첩보.php b/hwe/sammo/Command/General/che_첩보.php
index 276441a3..5102d1aa 100644
--- a/hwe/sammo/Command/General/che_첩보.php
+++ b/hwe/sammo/Command/General/che_첩보.php
@@ -120,7 +120,7 @@ class che_첩보 extends Command\GeneralCommand
return "{$failReason} {$destCityName}>에 {$commandName} 실패.";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -202,8 +202,8 @@ class che_첩보 extends Command\GeneralCommand
'spy'=>Json::encode($spyInfo)
], 'nation=%i',$nationID);
- $exp = Util::randRangeInt(1, 100);
- $ded = Util::randRangeInt(1, 70);
+ $exp = $rng->nextRangeInt(1, 100);
+ $ded = $rng->nextRangeInt(1, 70);
[$reqGold, $reqRice] = $this->getCost();
$general->increaseInheritancePoint(InheritanceKey::active_action, 0.5);//NOTE: 첩보만 예외!
@@ -214,7 +214,7 @@ class che_첩보 extends Command\GeneralCommand
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_출병.php b/hwe/sammo/Command/General/che_출병.php
index ccfa306b..7cfcacf7 100644
--- a/hwe/sammo/Command/General/che_출병.php
+++ b/hwe/sammo/Command/General/che_출병.php
@@ -20,6 +20,9 @@ use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst;
use sammo\Enums\InheritanceKey;
+use sammo\LiteHashDRBG;
+use sammo\RandUtil;
+use sammo\UniqueConst;
class che_출병 extends Command\GeneralCommand
{
@@ -127,7 +130,7 @@ class che_출병 extends Command\GeneralCommand
return "{$failReason} {$destCityName}>{$josaRo} {$commandName} 실패.";
}
- public function run(): bool
+ public function run(RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -188,7 +191,7 @@ class che_출병 extends Command\GeneralCommand
}
} while (false);
- $defenderCityID = (int) Util::choiceRandom($candidateCities);
+ $defenderCityID = (int) $rng->choice($candidateCities);
$this->setDestCity($defenderCityID);
$defenderCityName = $this->destCity['name'];
$josaRo = JosaUtil::pick($defenderCityName, '로');
@@ -236,9 +239,21 @@ class che_출병 extends Command\GeneralCommand
$general->applyDB($db);
- processWar($general, $this->nation, $this->destCity);
- tryUniqueItemLottery($general);
+ //어디로 출병하느냐에 따라 사실 결과가 다르다
+ $warRngPre = new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'war',
+ $logger->getYear(),
+ $logger->getMonth(),
+ $general->getID(),
+ $defenderCityID,
+ ));
+ $warRngSeed = bin2hex($warRngPre->nextBytes(16));
+
+ processWar($warRngSeed, $general, $this->nation, $this->destCity);
+
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_탈취.php b/hwe/sammo/Command/General/che_탈취.php
index 57440220..2c1f9668 100644
--- a/hwe/sammo/Command/General/che_탈취.php
+++ b/hwe/sammo/Command/General/che_탈취.php
@@ -6,7 +6,8 @@ use \sammo\{
General,
ActionLogger,
GameConst, GameUnitConst,
- Command
+ Command,
+ RandUtil
};
class che_탈취 extends che_화계{
@@ -15,7 +16,7 @@ class che_탈취 extends che_화계{
static protected $statType = 'strength';
static protected $injuryGeneral = false;
- protected function affectDestCity(int $injuryCount){
+ protected function affectDestCity(RandUtil $rng, int $injuryCount){
$general = $this->generalObj;
$nationID = $general->getNationID();
$date = $general->getTurnTime($general::TURNTIME_HM);
@@ -35,8 +36,8 @@ class che_탈취 extends che_화계{
$yearCoef = sqrt(1 + ($this->env['year'] - $this->env['startyear']) / 4) / 2;
$commRatio = $destCity['comm'] / $destCity['comm_max'];
$agriRatio = $destCity['agri'] / $destCity['agri_max'];
- $gold = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef * (0.25 + $commRatio / 4);
- $rice = Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef * (0.25 + $agriRatio / 4);
+ $gold = $rng->nextRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef * (0.25 + $commRatio / 4);
+ $rice = $rng->nextRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax) * $destCity['level'] * $yearCoef * (0.25 + $agriRatio / 4);
if($destCity['supply']){
[$destNationGold, $destNationRice] = $db->queryFirstList('SELECT gold,rice FROM nation WHERE nation=%i', $destNationID);
diff --git a/hwe/sammo/Command/General/che_파괴.php b/hwe/sammo/Command/General/che_파괴.php
index 54ffd3ed..98b60473 100644
--- a/hwe/sammo/Command/General/che_파괴.php
+++ b/hwe/sammo/Command/General/che_파괴.php
@@ -3,10 +3,11 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst, GameUnitConst,
- Command
+ Command,
+ RandUtil
};
class che_파괴 extends che_화계{
@@ -15,7 +16,7 @@ class che_파괴 extends che_화계{
static protected $statType = 'strength';
static protected $injuryGeneral = true;
- protected function affectDestCity(int $injuryCount){
+ protected function affectDestCity(RandUtil $rng, int $injuryCount){
$general = $this->generalObj;
$date = $general->getTurnTime($general::TURNTIME_HM);
@@ -29,8 +30,8 @@ class che_파괴 extends che_화계{
$commandName = $this->getName();
// 파괴
- $defAmount = Util::valueFit(Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['def']);
- $wallAmount = Util::valueFit(Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['wall']);
+ $defAmount = Util::valueFit($rng->nextRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['def']);
+ $wallAmount = Util::valueFit($rng->nextRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['wall']);
if($defAmount < 0){ $defAmount = 0; }
if($wallAmount < 0){ $wallAmount = 0; }
@@ -56,5 +57,5 @@ class che_파괴 extends che_화계{
ActionLogger::PLAIN
);
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/che_하야.php b/hwe/sammo/Command/General/che_하야.php
index 8658dc19..5cbcbd69 100644
--- a/hwe/sammo/Command/General/che_하야.php
+++ b/hwe/sammo/Command/General/che_하야.php
@@ -53,7 +53,7 @@ class che_하야 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -118,7 +118,7 @@ class che_하야 extends Command\GeneralCommand{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_해산.php b/hwe/sammo/Command/General/che_해산.php
index a848e160..48389b07 100644
--- a/hwe/sammo/Command/General/che_해산.php
+++ b/hwe/sammo/Command/General/che_해산.php
@@ -57,7 +57,7 @@ class che_해산 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -99,7 +99,7 @@ class che_해산 extends Command\GeneralCommand{
$oldGeneral->setVar('makelimit', 12);
$oldGeneral->applyDB($db);
}
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
// 이벤트 핸들러 동작
diff --git a/hwe/sammo/Command/General/che_헌납.php b/hwe/sammo/Command/General/che_헌납.php
index 424e3807..c95f6912 100644
--- a/hwe/sammo/Command/General/che_헌납.php
+++ b/hwe/sammo/Command/General/che_헌납.php
@@ -107,7 +107,7 @@ class che_헌납 extends Command\GeneralCommand
return 0;
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -146,7 +146,7 @@ class che_헌납 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_화계.php b/hwe/sammo/Command/General/che_화계.php
index 5b33bd5f..0b2cd114 100644
--- a/hwe/sammo/Command/General/che_화계.php
+++ b/hwe/sammo/Command/General/che_화계.php
@@ -17,6 +17,7 @@ use function sammo\tryRollbackInheritUniqueItem;
use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst;
use sammo\Enums\RankColumn;
+use sammo\RandUtil;
class che_화계 extends Command\GeneralCommand
{
@@ -200,7 +201,7 @@ class che_화계 extends Command\GeneralCommand
return "{$failReason} {$destCityName}>에 {$commandName} 실패.";
}
- protected function affectDestCity(int $injuryCount)
+ protected function affectDestCity(RandUtil $rng, int $injuryCount)
{
$general = $this->generalObj;
$date = $general->getTurnTime($general::TURNTIME_HM);
@@ -214,8 +215,8 @@ class che_화계 extends Command\GeneralCommand
$commandName = $this->getName();
- $agriAmount = Util::valueFit(Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['agri']);
- $commAmount = Util::valueFit(Util::randRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['comm']);
+ $agriAmount = Util::valueFit($rng->nextRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['agri']);
+ $commAmount = Util::valueFit($rng->nextRangeInt(GameConst::$sabotageDamageMin, GameConst::$sabotageDamageMax), null, $destCity['comm']);
$destCity['agri'] -= $agriAmount;
$destCity['comm'] -= $commAmount;
@@ -239,7 +240,7 @@ class che_화계 extends Command\GeneralCommand
);
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -279,12 +280,12 @@ class che_화계 extends Command\GeneralCommand
$prob /= $dist;
$prob = Util::valueFit($prob, 0, 0.5);
- if (!Util::randBool($prob)) {
+ if (!$rng->nextBool($prob)) {
$josaYi = JosaUtil::pick($commandName, '이');
$logger->pushGeneralActionLog("{$destCityName}>에 {$commandName}{$josaYi} 실패했습니다. <1>$date>");
- $exp = Util::randRangeInt(1, 100);
- $ded = Util::randRangeInt(1, 70);
+ $exp = $rng->nextRangeInt(1, 100);
+ $ded = $rng->nextRangeInt(1, 70);
[$reqGold, $reqRice] = $this->getCost();
$general->increaseVarWithLimit('gold', -$reqGold, 0);
@@ -295,18 +296,18 @@ class che_화계 extends Command\GeneralCommand
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return false;
}
if (static::$injuryGeneral) {
- $injuryCount = \sammo\SabotageInjury($destCityGeneralList, '계략');
+ $injuryCount = \sammo\SabotageInjury($rng, $destCityGeneralList, '계략');
} else {
$injuryCount = 0;
}
- $this->affectDestCity($injuryCount);
+ $this->affectDestCity($rng, $injuryCount);
$itemObj = $general->getItem();
if ($itemObj->tryConsumeNow($general, 'GeneralCommand', '계략')) {
@@ -317,8 +318,8 @@ class che_화계 extends Command\GeneralCommand
$general->deleteItem();
}
- $exp = Util::randRangeInt(201, 300);
- $ded = Util::randRangeInt(141, 210);
+ $exp = $rng->nextRangeInt(201, 300);
+ $ded = $rng->nextRangeInt(141, 210);
[$reqGold, $reqRice] = $this->getCost();
$general->increaseVarWithLimit('gold', -$reqGold, 0);
@@ -329,7 +330,7 @@ class che_화계 extends Command\GeneralCommand
$general->increaseRankVar(RankColumn::firenum, 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB($db);
return true;
diff --git a/hwe/sammo/Command/General/che_훈련.php b/hwe/sammo/Command/General/che_훈련.php
index 52292f88..528f23e9 100644
--- a/hwe/sammo/Command/General/che_훈련.php
+++ b/hwe/sammo/Command/General/che_훈련.php
@@ -3,7 +3,7 @@ namespace sammo\Command\General;
use \sammo\{
DB, Util, JosaUtil,
- General,
+ General,
ActionLogger,
GameConst, GameUnitConst,
LastTurn,
@@ -33,13 +33,13 @@ class che_훈련 extends Command\GeneralCommand{
$this->setNation();
$this->minConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
];
-
+
$this->fullConditionConstraints=[
- ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotBeNeutral(),
ConstraintHelper::NotWanderingNation(),
ConstraintHelper::OccupiedCity(),
ConstraintHelper::ReqGeneralCrew(),
@@ -66,7 +66,7 @@ class che_훈련 extends Command\GeneralCommand{
public function getCost():array{
return [0, 0];
}
-
+
public function getPreReqTurn():int{
return 0;
}
@@ -75,7 +75,7 @@ class che_훈련 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -107,11 +107,11 @@ class che_훈련 extends Command\GeneralCommand{
$general->increaseVar('leadership_exp', 1);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange();
- tryUniqueItemLottery($general);
+ tryUniqueItemLottery(\sammo\genGenericUniqueRNGFromGeneral($general), $general);
$general->applyDB($db);
return true;
}
-
+
}
\ No newline at end of file
diff --git a/hwe/sammo/Command/General/휴식.php b/hwe/sammo/Command/General/휴식.php
index 5b02f96c..ecdb0b83 100644
--- a/hwe/sammo/Command/General/휴식.php
+++ b/hwe/sammo/Command/General/휴식.php
@@ -34,14 +34,14 @@ class 휴식 extends Command\GeneralCommand{
return 0;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
$general = $this->generalObj;
$logger = $general->getLogger();
$date = $general->getTurnTime($general::TURNTIME_HM);
$logger->pushGeneralActionLog("아무것도 실행하지 않았습니다. <1>$date>");
$this->setResultTurn(new LastTurn());
- tryRollbackInheritUniqueItem($general);
+ tryRollbackInheritUniqueItem($rng, $general);
$general->applyDB(DB::db());
return true;
}
diff --git a/hwe/sammo/Command/Nation/che_감축.php b/hwe/sammo/Command/Nation/che_감축.php
index 575f7d4e..a54af37b 100644
--- a/hwe/sammo/Command/Nation/che_감축.php
+++ b/hwe/sammo/Command/Nation/che_감축.php
@@ -136,7 +136,7 @@ class che_감축 extends Command\NationCommand{
return "수도를 {$commandName}";
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
diff --git a/hwe/sammo/Command/Nation/che_국기변경.php b/hwe/sammo/Command/Nation/che_국기변경.php
index 9250a228..5bea215e 100644
--- a/hwe/sammo/Command/Nation/che_국기변경.php
+++ b/hwe/sammo/Command/Nation/che_국기변경.php
@@ -91,7 +91,7 @@ class che_국기변경 extends Command\NationCommand
return "【국기】를 변경";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_국호변경.php b/hwe/sammo/Command/Nation/che_국호변경.php
index 68e53db8..10bd40fa 100644
--- a/hwe/sammo/Command/Nation/che_국호변경.php
+++ b/hwe/sammo/Command/Nation/che_국호변경.php
@@ -103,7 +103,7 @@ class che_국호변경 extends Command\NationCommand
return "국호를 【{$newNationName}】{$josaRo} 변경";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_급습.php b/hwe/sammo/Command/Nation/che_급습.php
index 8ef601f3..7a178e9c 100644
--- a/hwe/sammo/Command/Nation/che_급습.php
+++ b/hwe/sammo/Command/Nation/che_급습.php
@@ -121,7 +121,7 @@ class che_급습 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_몰수.php b/hwe/sammo/Command/Nation/che_몰수.php
index 6f90ea69..2d563afb 100644
--- a/hwe/sammo/Command/Nation/che_몰수.php
+++ b/hwe/sammo/Command/Nation/che_몰수.php
@@ -141,7 +141,7 @@ class che_몰수 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -168,7 +168,7 @@ class che_몰수 extends Command\NationCommand
);
$amountText = number_format($amount, 0);
- if ($destGeneral->getNPCType() >= 2 && Util::randBool(GameConst::$npcSeizureMessageProb)) {
+ if ($destGeneral->getNPCType() >= 2 && $rng->nextBool(GameConst::$npcSeizureMessageProb)) {
$npcTexts = [
'몰수를 하다니... 이것이 윗사람이 할 짓이란 말입니까...',
'사유재산까지 몰수해가면서 이 나라가 잘 될거라 믿습니까? 정말 이해할 수가 없군요...',
@@ -176,7 +176,7 @@ class che_몰수 extends Command\NationCommand
'몰수해간 내 자금... 언젠가 몰래 다시 빼내올 것이다...',
'몰수로 인한 사기 저하는 몰수로 얻은 물자보다 더 손해란걸 모른단 말인가!'
];
- $text = Util::choiceRandom($npcTexts);
+ $text = $rng->choice($npcTexts);
$src = new MessageTarget(
$destGeneral->getID(),
$destGeneral->getName(),
diff --git a/hwe/sammo/Command/Nation/che_물자원조.php b/hwe/sammo/Command/Nation/che_물자원조.php
index 2dcdba61..bfaad9d1 100644
--- a/hwe/sammo/Command/Nation/che_물자원조.php
+++ b/hwe/sammo/Command/Nation/che_물자원조.php
@@ -155,7 +155,7 @@ class che_물자원조 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_발령.php b/hwe/sammo/Command/Nation/che_발령.php
index 26ad01a3..7acf90dd 100644
--- a/hwe/sammo/Command/Nation/che_발령.php
+++ b/hwe/sammo/Command/Nation/che_발령.php
@@ -129,7 +129,7 @@ class che_발령 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_백성동원.php b/hwe/sammo/Command/Nation/che_백성동원.php
index de54dc2f..64d8dffd 100644
--- a/hwe/sammo/Command/Nation/che_백성동원.php
+++ b/hwe/sammo/Command/Nation/che_백성동원.php
@@ -111,7 +111,7 @@ class che_백성동원 extends Command\NationCommand
return "【{$destCityName}】에 {$commandName}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_불가침수락.php b/hwe/sammo/Command/Nation/che_불가침수락.php
index 89ee1965..dbf923a4 100644
--- a/hwe/sammo/Command/Nation/che_불가침수락.php
+++ b/hwe/sammo/Command/Nation/che_불가침수락.php
@@ -22,6 +22,7 @@ use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
use sammo\Json;
use sammo\KVStorage;
+use sammo\RandUtil;
class che_불가침수락 extends Command\NationCommand
{
@@ -165,7 +166,7 @@ class che_불가침수락 extends Command\NationCommand
return "{$year}년 {$month}월까지 불가침 합의";
}
- public function run(): bool
+ public function run(RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_불가침제의.php b/hwe/sammo/Command/Nation/che_불가침제의.php
index e8ea5359..ba8fe753 100644
--- a/hwe/sammo/Command/Nation/che_불가침제의.php
+++ b/hwe/sammo/Command/Nation/che_불가침제의.php
@@ -148,7 +148,7 @@ class che_불가침제의 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_불가침파기수락.php b/hwe/sammo/Command/Nation/che_불가침파기수락.php
index 0e4ecc56..3ca9f794 100644
--- a/hwe/sammo/Command/Nation/che_불가침파기수락.php
+++ b/hwe/sammo/Command/Nation/che_불가침파기수락.php
@@ -20,6 +20,7 @@ use function \sammo\getNationStaticInfo;
use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper;
+use sammo\RandUtil;
class che_불가침파기수락 extends Command\NationCommand
{
@@ -71,7 +72,7 @@ class che_불가침파기수락 extends Command\NationCommand
$this->permissionConstraints = [
ConstraintHelper::AlwaysFail('예약 불가능 커맨드')
- ];
+ ];
}
protected function initWithArg()
@@ -120,7 +121,7 @@ class che_불가침파기수락 extends Command\NationCommand
return "{$destNationName}국과 불가침 파기 합의";
}
- public function run(): bool
+ public function run(RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_불가침파기제의.php b/hwe/sammo/Command/Nation/che_불가침파기제의.php
index 4d500534..9a22b215 100644
--- a/hwe/sammo/Command/Nation/che_불가침파기제의.php
+++ b/hwe/sammo/Command/Nation/che_불가침파기제의.php
@@ -102,7 +102,7 @@ class che_불가침파기제의 extends Command\NationCommand{
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
diff --git a/hwe/sammo/Command/Nation/che_선전포고.php b/hwe/sammo/Command/Nation/che_선전포고.php
index 6df46ec8..69d90988 100644
--- a/hwe/sammo/Command/Nation/che_선전포고.php
+++ b/hwe/sammo/Command/Nation/che_선전포고.php
@@ -116,7 +116,7 @@ class che_선전포고 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_수몰.php b/hwe/sammo/Command/Nation/che_수몰.php
index 6305d33e..62ca5cbd 100644
--- a/hwe/sammo/Command/Nation/che_수몰.php
+++ b/hwe/sammo/Command/Nation/che_수몰.php
@@ -116,7 +116,7 @@ class che_수몰 extends Command\NationCommand
return "【{$destCityName}】{$josaUl} {$commandName}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_의병모집.php b/hwe/sammo/Command/Nation/che_의병모집.php
index 5bfc12c6..2453c6e7 100644
--- a/hwe/sammo/Command/Nation/che_의병모집.php
+++ b/hwe/sammo/Command/Nation/che_의병모집.php
@@ -74,7 +74,7 @@ class che_의병모집 extends Command\NationCommand
return $nextTerm;
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -143,8 +143,8 @@ class che_의병모집 extends Command\NationCommand
from general where nation=%i',
$nationID
);
- foreach(\sammo\pickGeneralFromPool($db, 0, $createGenCnt) as $pickedNPC){
-
+ foreach(\sammo\pickGeneralFromPool($db, $rng, 0, $createGenCnt) as $pickedNPC){
+
$newNPC = $pickedNPC->getGeneralBuilder();
$newNPC->setCityID($general->getCityID());
@@ -152,12 +152,12 @@ class che_의병모집 extends Command\NationCommand
$newNPC->setSpecial('None', 'None');
$newNPC->setLifeSpan($env['year']-20, $env['year']+10);
- $newNPC->setKillturn(Util::randRangeInt(64, 70));
+ $newNPC->setKillturn($rng->nextRangeInt(64, 70));
$newNPC->setNPCType(4);
$newNPC->setMoney(1000, 1000);
$newNPC->setSpecYear(19, 19);
$newNPC->fillRemainSpecAsRandom($pickTypeList, $avgGen, $env);
-
+
$newNPC->build($this->env);
$pickedNPC->occupyGeneralName();
}
diff --git a/hwe/sammo/Command/Nation/che_이호경식.php b/hwe/sammo/Command/Nation/che_이호경식.php
index 5ffc6094..afb61b10 100644
--- a/hwe/sammo/Command/Nation/che_이호경식.php
+++ b/hwe/sammo/Command/Nation/che_이호경식.php
@@ -118,7 +118,7 @@ class che_이호경식 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_종전수락.php b/hwe/sammo/Command/Nation/che_종전수락.php
index 017a0f2d..dfbee08c 100644
--- a/hwe/sammo/Command/Nation/che_종전수락.php
+++ b/hwe/sammo/Command/Nation/che_종전수락.php
@@ -76,7 +76,7 @@ class che_종전수락 extends Command\NationCommand
$this->setCity();
$this->setNation();
-
+
$nationID = $this->nation['nation'];
$this->permissionConstraints = [
@@ -129,7 +129,7 @@ class che_종전수락 extends Command\NationCommand
return "{$destNationName}국과 종전 합의";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_종전제의.php b/hwe/sammo/Command/Nation/che_종전제의.php
index a738957a..63370d8b 100644
--- a/hwe/sammo/Command/Nation/che_종전제의.php
+++ b/hwe/sammo/Command/Nation/che_종전제의.php
@@ -100,7 +100,7 @@ class che_종전제의 extends Command\NationCommand{
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
diff --git a/hwe/sammo/Command/Nation/che_증축.php b/hwe/sammo/Command/Nation/che_증축.php
index b1ce0487..84cfbee5 100644
--- a/hwe/sammo/Command/Nation/che_증축.php
+++ b/hwe/sammo/Command/Nation/che_증축.php
@@ -134,7 +134,7 @@ class che_증축 extends Command\NationCommand{
return "수도를 {$commandName}";
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
diff --git a/hwe/sammo/Command/Nation/che_천도.php b/hwe/sammo/Command/Nation/che_천도.php
index ec6738bd..f9a85165 100644
--- a/hwe/sammo/Command/Nation/che_천도.php
+++ b/hwe/sammo/Command/Nation/che_천도.php
@@ -180,7 +180,7 @@ class che_천도 extends Command\NationCommand
return "【{$destCityName}】{$josaRo} {$commandName}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_초토화.php b/hwe/sammo/Command/Nation/che_초토화.php
index 5cb63e07..805ef47b 100644
--- a/hwe/sammo/Command/Nation/che_초토화.php
+++ b/hwe/sammo/Command/Nation/che_초토화.php
@@ -124,7 +124,7 @@ class che_초토화 extends Command\NationCommand{
return Util::toInt($amount);
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
diff --git a/hwe/sammo/Command/Nation/che_포상.php b/hwe/sammo/Command/Nation/che_포상.php
index 6d57c02c..f69a4f55 100644
--- a/hwe/sammo/Command/Nation/che_포상.php
+++ b/hwe/sammo/Command/Nation/che_포상.php
@@ -133,7 +133,7 @@ class che_포상 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_피장파장.php b/hwe/sammo/Command/Nation/che_피장파장.php
index c2a3421e..2507e2d3 100644
--- a/hwe/sammo/Command/Nation/che_피장파장.php
+++ b/hwe/sammo/Command/Nation/che_피장파장.php
@@ -159,7 +159,7 @@ class che_피장파장 extends Command\NationCommand
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
diff --git a/hwe/sammo/Command/Nation/che_필사즉생.php b/hwe/sammo/Command/Nation/che_필사즉생.php
index 61b93fb6..431b0c63 100644
--- a/hwe/sammo/Command/Nation/che_필사즉생.php
+++ b/hwe/sammo/Command/Nation/che_필사즉생.php
@@ -33,7 +33,7 @@ class che_필사즉생 extends Command\NationCommand{
$this->setCity();
$this->setNation(['strategic_cmd_limit']);
-
+
$this->fullConditionConstraints=[
ConstraintHelper::OccupiedCity(),
ConstraintHelper::BeChief(),
@@ -43,7 +43,7 @@ class che_필사즉생 extends Command\NationCommand{
ConstraintHelper::AvailableStrategicCommand()
];
}
-
+
public function getCommandDetailTitle():string{
$name = $this->getName();
$reqTurn = $this->getPreReqTurn()+1;
@@ -51,24 +51,24 @@ class che_필사즉생 extends Command\NationCommand{
return "{$name}/{$reqTurn}턴(재사용 대기 $postReqTurn)";
}
-
+
public function getCost():array{
return [0, 0];
}
-
+
public function getPreReqTurn():int{
return 2;
}
public function getPostReqTurn():int{
$genCount = Util::valueFit($this->nation['gennum'], GameConst::$initialNationGenLimit);
- $nextTerm = Util::round(sqrt($genCount*8)*10);
+ $nextTerm = Util::round(sqrt($genCount*8)*10);
$nextTerm = $this->generalObj->onCalcStrategic($this->getName(), 'delay', $nextTerm);
return $nextTerm;
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
}
@@ -79,7 +79,7 @@ class che_필사즉생 extends Command\NationCommand{
$generalID = $general->getID();
$generalName = $general->getName();
$date = $general->getTurnTime($general::TURNTIME_HM);
-
+
$nationID = $general->getNationID();
$nationName = $this->nation['name'];
@@ -101,8 +101,8 @@ class che_필사즉생 extends Command\NationCommand{
}
if($targetGeneral->getVar('atmos') < 100){
$targetGeneral->setVar('atmos', 100);
- }
-
+ }
+
$targetGeneral->applyDB($db);
}
diff --git a/hwe/sammo/Command/Nation/che_허보.php b/hwe/sammo/Command/Nation/che_허보.php
index 5cfbf580..b3c201b7 100644
--- a/hwe/sammo/Command/Nation/che_허보.php
+++ b/hwe/sammo/Command/Nation/che_허보.php
@@ -116,7 +116,7 @@ class che_허보 extends Command\NationCommand
return "【{$destCityName}】에 {$commandName}";
}
- public function run(): bool
+ public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -167,10 +167,10 @@ class che_허보 extends Command\NationCommand
$targetLogger = $targetGeneral->getLogger();
$targetLogger->pushGeneralActionLog($destBroadcastMessage, ActionLogger::PLAIN);
- $moveCityID = Util::choiceRandom($destNationCityList);
+ $moveCityID = $rng->choice($destNationCityList);
if ($moveCityID == $destCityID) {
//현재도시면 다시 랜덤 추첨
- $moveCityID = Util::choiceRandom($destNationCityList);
+ $moveCityID = $rng->choice($destNationCityList);
}
$targetGeneral->setVar('city', $moveCityID);
diff --git a/hwe/sammo/Command/Nation/휴식.php b/hwe/sammo/Command/Nation/휴식.php
index 952e68d6..4f5af13c 100644
--- a/hwe/sammo/Command/Nation/휴식.php
+++ b/hwe/sammo/Command/Nation/휴식.php
@@ -16,7 +16,7 @@ class 휴식 extends Command\NationCommand{
protected function init(){
//아무것도 하지 않음
$this->fullConditionConstraints=[];
-
+
}
public function getPreReqTurn():int{
@@ -31,7 +31,7 @@ class 휴식 extends Command\NationCommand{
return [0, 0];
}
- public function run():bool{
+ public function run(\Sammo\RandUtil $rng):bool{
$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
return true;
}
diff --git a/hwe/sammo/DefaultAction.php b/hwe/sammo/DefaultAction.php
index a50f5927..612e7832 100644
--- a/hwe/sammo/DefaultAction.php
+++ b/hwe/sammo/DefaultAction.php
@@ -50,7 +50,7 @@ trait DefaultAction{
return null;
}
- public function onArbitraryAction(General $general, string $actionType, ?string $phase=null, $aux=null): null|array{
+ public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase=null, $aux=null): null|array{
return $aux;
}
}
\ No newline at end of file
diff --git a/hwe/sammo/DiplomaticMessage.php b/hwe/sammo/DiplomaticMessage.php
index 199d2e91..dc53bbe5 100644
--- a/hwe/sammo/DiplomaticMessage.php
+++ b/hwe/sammo/DiplomaticMessage.php
@@ -88,7 +88,7 @@ class DiplomaticMessage extends Message{
return [self::INVALID, $commandObj->getFailString()];
}
- $commandObj->run();
+ $commandObj->run(NoRNG::rngInstance());
$commandObj->setNextAvailable();
return [self::ACCEPTED, ''];
@@ -110,7 +110,7 @@ class DiplomaticMessage extends Message{
return [self::INVALID, $commandObj->getFailString()];
}
- $commandObj->run();
+ $commandObj->run(NoRNG::rngInstance());
$commandObj->setNextAvailable();
return [self::ACCEPTED, ''];
@@ -132,7 +132,7 @@ class DiplomaticMessage extends Message{
return [self::INVALID, $commandObj->getFailString()];
}
- $commandObj->run();
+ $commandObj->run(NoRNG::rngInstance());
$commandObj->setNextAvailable();
return [self::ACCEPTED, ''];
diff --git a/hwe/sammo/Event/Action/CreateManyNPC.php b/hwe/sammo/Event/Action/CreateManyNPC.php
index 3c50b046..c7292165 100644
--- a/hwe/sammo/Event/Action/CreateManyNPC.php
+++ b/hwe/sammo/Event/Action/CreateManyNPC.php
@@ -1,37 +1,51 @@
npcCount = $npcCount;
$this->fillCnt = $fillCnt;
}
- protected function generateNPC($env, int $cnt){
- $pickTypeList = ['무'=>1, '지'=>1];
+ protected function generateNPC($env, int $cnt)
+ {
+ $pickTypeList = ['무' => 1, '지' => 1];
- $age = Util::randRangeInt(20, 25);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'CreateManyNPC',
+ $env['year'],
+ $env['month']
+ )));
+ $age = $rng->nextRangeInt(20, 25);
$birthYear = $env['year'] - $age;
- $deathYear = $env['year'] + Util::randRangeInt(10, 50);
+ $deathYear = $env['year'] + $rng->nextRangeInt(10, 50);
$result = [];
- foreach(pickGeneralFromPool(DB::db(), 0, $cnt) as $pickedNPC){
+ foreach (pickGeneralFromPool(DB::db(), $rng, 0, $cnt) as $pickedNPC) {
$newNPC = $pickedNPC->getGeneralBuilder();
$newNPC->setNationID(0)
- ->setNPCType(3)
- ->setMoney(1000, 1000)
- ->setExpDed(0, 0)
- ->setLifeSpan($birthYear, $deathYear);
- if($newNPC->getStat()[0]===null){
+ ->setNPCType(3)
+ ->setMoney(1000, 1000)
+ ->setExpDed(0, 0)
+ ->setLifeSpan($birthYear, $deathYear);
+ if ($newNPC->getStat()[0] === null) {
$newNPC->fillRandomStat($pickTypeList);
}
$newNPC->fillRemainSpecAsZero($env);
@@ -45,14 +59,15 @@ class CreateManyNPC extends \sammo\Event\Action{
}
- public function run(array $env){
- if($this->npcCount <= 0 && $this->fillCnt <= 0){
+ public function run(array $env)
+ {
+ if ($this->npcCount <= 0 && $this->fillCnt <= 0) {
return [__CLASS__, []];
}
$moreGenCnt = 0;
- if($this->fillCnt){
+ if ($this->fillCnt) {
$db = DB::db();
$nations = $db->queryFirstColumn('SELECT nation FROM general WHERE npc < 3 AND officer_level = 12');
$regGens = $db->queryFirstField('SELECT count(*) FROM general WHERE nation IN %li AND npc < 4', $nations);
@@ -63,12 +78,11 @@ class CreateManyNPC extends \sammo\Event\Action{
$logger = new \sammo\ActionLogger(0, 0, $env['year'], $env['month']);
$genCnt = count($result);
- if($genCnt == 1){
+ if ($genCnt == 1) {
$npcName = $result[0][0];
$josaRa = \sammo\JosaUtil::pick($npcName, '라');
$logger->pushGlobalActionLog("$npcName>{$josaRa}는 장수가 등장>하였습니다.");
- }
- else{
+ } else {
$logger->pushGlobalActionLog("장수 {$genCnt}>명이 등장>하였습니다.");
}
$logger->pushGlobalHistoryLog("장수 {$genCnt}>명이 등장>했습니다.", \sammo\ActionLogger::NOTICE_YEAR_MONTH);
@@ -76,4 +90,4 @@ class CreateManyNPC extends \sammo\Event\Action{
return [__CLASS__, $result];
}
-}
\ No newline at end of file
+}
diff --git a/hwe/sammo/Event/Action/RaiseInvader.php b/hwe/sammo/Event/Action/RaiseInvader.php
index a4849868..880bfc72 100644
--- a/hwe/sammo/Event/Action/RaiseInvader.php
+++ b/hwe/sammo/Event/Action/RaiseInvader.php
@@ -7,6 +7,8 @@ use sammo\CityConst;
use sammo\DB;
use sammo\Json;
use sammo\KVStorage;
+use sammo\LiteHashDRBG;
+use sammo\RandUtil;
use sammo\Scenario\GeneralBuilder;
use sammo\Scenario\Nation;
use sammo\UniqueConst;
@@ -140,6 +142,14 @@ class RaiseInvader extends \sammo\Event\Action
], true);
$year = $env['year'];
+ $month = $env['month'];
+
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'RaiseInvader',
+ $year,
+ $month,
+ )));
$invaderNationIDList = [];
refreshNationStaticInfo();
@@ -154,10 +164,10 @@ class RaiseInvader extends \sammo\Event\Action
$invaderName = $cityObj->name;
$nationName = "ⓞ{$invaderName}족";
- $nationObj = new Nation($invaderNationID, $nationName, '#800080', 9999999, 9999999, "중원의 부패를 물리쳐라! 이민족 침범!", $tech, "che_병가", 2, [$cityObj->name]);
+ $nationObj = new Nation($rng, $invaderNationID, $nationName, '#800080', 9999999, 9999999, "중원의 부패를 물리쳐라! 이민족 침범!", $tech, "che_병가", 2, [$cityObj->name]);
$nationObj->build($env);
- $ruler = (new GeneralBuilder("{$invaderName}대왕", false, null, $lastNationID))
+ $ruler = (new GeneralBuilder($rng, "{$invaderName}대왕", false, null, $lastNationID))
->setEgo('che_패권')
->setSpecial('che_인덕', 'che_척사')
->setLifeSpan($year - 20, $year + 20)
@@ -172,7 +182,7 @@ class RaiseInvader extends \sammo\Event\Action
$nationObj->addGeneral($ruler);
foreach (Util::range(1, $npcEachCount) as $invaderGenIdx) {
- $gen = (new GeneralBuilder("{$invaderName}장수{$invaderGenIdx}", false, null, $invaderNationID))
+ $gen = (new GeneralBuilder($rng, "{$invaderName}장수{$invaderGenIdx}", false, null, $invaderNationID))
->setEgo('che_패권')
->setSpecial('che_인덕', 'che_척사')
->setLifeSpan($year - 20, $year + 20)
@@ -182,11 +192,11 @@ class RaiseInvader extends \sammo\Event\Action
->setExpDed($exp, null)
->setGoldRice(99999, 99999);
- $leadership = Util::randRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4));
- $mainStat = Util::randRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4));
+ $leadership = $rng->nextRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4));
+ $mainStat = $rng->nextRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4));
$subStat = $specAvg * 3 - $leadership - $mainStat;
- if (Util::randBool()) {
+ if ($rng->nextBit()) {
//무장
$dexTable = [$dex * 2, $dex, $dex];
shuffle($dexTable);
diff --git a/hwe/sammo/Event/Action/RaiseNPCNation.php b/hwe/sammo/Event/Action/RaiseNPCNation.php
index 74605c5b..b090cb50 100644
--- a/hwe/sammo/Event/Action/RaiseNPCNation.php
+++ b/hwe/sammo/Event/Action/RaiseNPCNation.php
@@ -9,6 +9,8 @@ use sammo\DB;
use sammo\GameConst;
use sammo\Json;
use sammo\KVStorage;
+use sammo\LiteHashDRBG;
+use sammo\RandUtil;
use sammo\Scenario\GeneralBuilder;
use sammo\Scenario\Nation;
use sammo\UniqueConst;
@@ -28,7 +30,7 @@ class RaiseNPCNation extends \sammo\Event\Action
const MIN_DIST_USERNATION = 3;
const MIN_DIST_NPCNATION = 2;
- private function calcAvgNationCity(array $cities)
+ private function calcAvgNationCity(RandUtil $rng, array $cities)
{
if (count($cities) == 0) {
throw new InvalidArgumentException();
@@ -55,7 +57,7 @@ class RaiseNPCNation extends \sammo\Event\Action
$cityCnt = count($targetCities);
if ($cityCnt == 0) {
- $target = Util::choiceRandom($cities);
+ $target = $rng->choice($cities);
$randCity = [];
foreach (static::CITY_KEYS as $key) {
$randCity[$key] = $target["{$key}_max"];
@@ -136,7 +138,7 @@ class RaiseNPCNation extends \sammo\Event\Action
return Util::toInt($techSum / $nationCnt);
}
- private function buildNation(int $nationID, int $tech, array $baseCity, array $avgCity, int $genCnt, $env)
+ private function buildNation(RandUtil $rng, int $nationID, int $tech, array $baseCity, array $avgCity, int $genCnt, $env)
{
$db = DB::db();
@@ -153,11 +155,11 @@ class RaiseNPCNation extends \sammo\Event\Action
$cityName = $baseCity['name'];
$nationName = "ⓤ{$cityName}";
- $color = Util::choiceRandom(GetNationColors());
- $nationObj = new Nation($nationID, $nationName, $color, 0, 2000, "우리도 할 수 있다! {$cityName}군", $tech, null, 2, [$cityName]);
+ $color = $rng->choice(GetNationColors());
+ $nationObj = new Nation($rng, $nationID, $nationName, $color, 0, 2000, "우리도 할 수 있다! {$cityName}군", $tech, null, 2, [$cityName]);
$nationObj->build($env);
- $ruler = (new GeneralBuilder("{$cityName}태수", false, null, $nationID))
+ $ruler = (new GeneralBuilder($rng, "{$cityName}태수", false, null, $nationID))
->setOfficerLevel(12)
->setCityID($cityID)
->setNPCType(6)
@@ -172,9 +174,9 @@ class RaiseNPCNation extends \sammo\Event\Action
$birthYear = $env['year'] - 20;
$deadYearMin = $env['year'] + 10;
- foreach (pickGeneralFromPool(DB::db(), 0, $genCnt - 1) as $pickedNPC) {
+ foreach (pickGeneralFromPool(DB::db(), $rng, 0, $genCnt - 1) as $pickedNPC) {
//대충 10년후부터 6년마다 절반?
- $deadYear = $deadYearMin + Util::toInt(60 * (1 - log(Util::randRange(1, 1024), 2) / 10));
+ $deadYear = $deadYearMin + Util::toInt(60 * (1 - log($rng->nextRange(1, 1024), 2) / 10));
$newNPC = $pickedNPC->getGeneralBuilder();
$newNPC->setNationID($nationID)
->setCityID($cityID)
@@ -204,7 +206,11 @@ class RaiseNPCNation extends \sammo\Event\Action
$occupiedCities = [];
$npcCities = [];
- $avgCity = $this->calcAvgNationCity($allCities);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed, 'RaiseNPCNation', $env['year'], $env['month']
+ )));
+
+ $avgCity = $this->calcAvgNationCity($rng, $allCities);
foreach ($allCities as $city) {
if ($city['nation'] == 0) {
@@ -257,7 +263,7 @@ class RaiseNPCNation extends \sammo\Event\Action
//TODO: 거리 측정
$lastNationID += 1;
- $this->buildNation($lastNationID, $avgTech, $emptyCity, $avgCity, $avgGenCnt, $env);
+ $this->buildNation($rng, $lastNationID, $avgTech, $emptyCity, $avgCity, $avgGenCnt, $env);
$npcCities[$cityID] = $emptyCity;
$npcCitiesID[] = $cityID;
}
diff --git a/hwe/sammo/Event/Action/RegNPC.php b/hwe/sammo/Event/Action/RegNPC.php
index 10ef70c7..8d3bc4a1 100644
--- a/hwe/sammo/Event/Action/RegNPC.php
+++ b/hwe/sammo/Event/Action/RegNPC.php
@@ -1,33 +1,38 @@
npc=(new \sammo\Scenario\GeneralBuilder(
- $name,
+ $rng,
+ $name,
false,
- $picturePath,
- $nationID
+ $picturePath,
+ $nationID
))
->setCity($locatedCity)
->setStat($leadership, $strength, $intel)
diff --git a/hwe/sammo/Event/Action/RegNeutralNPC.php b/hwe/sammo/Event/Action/RegNeutralNPC.php
index 46e857dc..1c4d51ac 100644
--- a/hwe/sammo/Event/Action/RegNeutralNPC.php
+++ b/hwe/sammo/Event/Action/RegNeutralNPC.php
@@ -1,31 +1,39 @@
npc=(new \sammo\Scenario\GeneralBuilder(
- $name,
+ $rng,
+ $name,
false,
- $picturePath,
- $nationID
+ $picturePath,
+ $nationID
))
->setCity($locatedCity)
->setStat($leadership, $strength, $intel)
diff --git a/hwe/sammo/General.php b/hwe/sammo/General.php
index 22021dfe..cb9bab77 100644
--- a/hwe/sammo/General.php
+++ b/hwe/sammo/General.php
@@ -987,7 +987,7 @@ class General implements iAction
return $amount;
}
- public function onArbitraryAction(General $general, string $actionType, ?string $phase = null, $aux = null): null|array
+ public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase = null, $aux = null): null|array
{
foreach (array_merge([
$this->nationType,
@@ -1002,7 +1002,7 @@ class General implements iAction
continue;
}
/** @var iAction $iObj */
- $aux = $iObj->onArbitraryAction($general, $actionType, $phase, $aux);
+ $aux = $iObj->onArbitraryAction($general, $rng, $actionType, $phase, $aux);
}
return $aux;
}
diff --git a/hwe/sammo/GeneralAI.php b/hwe/sammo/GeneralAI.php
index e666b61b..35415fe0 100644
--- a/hwe/sammo/GeneralAI.php
+++ b/hwe/sammo/GeneralAI.php
@@ -9,6 +9,8 @@ use sammo\Scenario\NPC;
class GeneralAI
{
+ protected RandUtil $rng;
+
/** @var General */
protected $general;
protected array $city;
@@ -94,6 +96,14 @@ class GeneralAI
}
$this->city = $city;
+ $this->rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'GeneralAI',
+ $this->env['year'],
+ $this->env['month'],
+ $general->getID(),
+ )));
+
$this->nation = $db->queryFirstRow(
'SELECT nation,name,color,capital,capset,gennum,gold,rice,bill,rate,rate_tmp,scout,war,strategic_cmd_limit,surlimit,tech,power,level,chief_set,type,aux FROM nation WHERE nation = %i',
$general->getNationID()
@@ -161,7 +171,7 @@ class GeneralAI
if ($strength >= $intel) {
$genType = self::t무장;
if ($intel >= $strength * 0.8) { //무지장
- if (Util::randBool($intel / $strength / 2)) {
+ if ($this->rng->nextBool($intel / $strength / 2)) {
$genType |= self::t지장;
}
}
@@ -169,7 +179,7 @@ class GeneralAI
} else {
$genType = self::t지장;
if ($strength >= $intel * 0.8) { //지무장
- if (Util::randBool($strength / $intel / 2)) {
+ if ($this->rng->nextBool($strength / $intel / 2)) {
$genType |= self::t무장;
}
}
@@ -310,19 +320,19 @@ class GeneralAI
if (!key_exists($fromCityID, $this->warRoute) && !key_exists($toCityID, $this->warRoute)) {
//공격 루트 상실, 전방 아무데나
- $troopCandidate[] = [$leaderID, Util::choiceRandom($this->frontCities)['city']];
+ $troopCandidate[] = [$leaderID, $this->rng->choice($this->frontCities)['city']];
continue;
}
if (!key_exists($toCityID, $this->warRoute[$fromCityID])) {
//공격 루트 상실, 전방 아무데나
- $troopCandidate[] = [$leaderID, Util::choiceRandom($this->frontCities)['city']];
+ $troopCandidate[] = [$leaderID, $this->rng->choice($this->frontCities)['city']];
continue;
}
if (key_exists($fromCityID, $this->supplyCities) && key_exists($toCityID, $this->supplyCities)) {
//점령 완료, 전방 아무데나
- $troopCandidate[] = [$leaderID, Util::choiceRandom($this->frontCities)['city']];
+ $troopCandidate[] = [$leaderID, $this->rng->choice($this->frontCities)['city']];
continue;
}
@@ -354,7 +364,7 @@ class GeneralAI
$targetCityID = $nextCityCandidate[0];
continue;
}
- $targetCityID = Util::choiceRandom($nextCityCandidate);
+ $targetCityID = $this->rng->choice($nextCityCandidate);
}
$troopCandidate[] = ['destGenaralID' => $leaderID, 'destCityID' => $targetCityID];
@@ -364,7 +374,7 @@ class GeneralAI
return null;
}
- $cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, Util::choiceRandom($troopCandidate));
+ $cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, $this->rng->choice($troopCandidate));
if (!$cmd->hasFullConditionMet()) {
return null;
}
@@ -450,8 +460,8 @@ class GeneralAI
}
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
- 'destGeneralID' => Util::choiceRandom($troopCandidate)->getID(),
- 'destCityID' => Util::choiceRandom($cityCandidates)['city']
+ 'destGeneralID' => $this->rng->choice($troopCandidate)->getID(),
+ 'destCityID' => $this->rng->choice($cityCandidates)['city']
]);
if (!$cmd->hasFullConditionMet()) {
@@ -503,8 +513,8 @@ class GeneralAI
}
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
- 'destGeneralID' => Util::choiceRandom($troopCandidate)->getID(),
- 'destCityID' => Util::choiceRandom($cityCandidates)['city']
+ 'destGeneralID' => $this->rng->choice($troopCandidate)->getID(),
+ 'destCityID' => $this->rng->choice($cityCandidates)['city']
]);
if (!$cmd->hasFullConditionMet()) {
@@ -612,8 +622,8 @@ class GeneralAI
}
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
- 'destGeneralID' => Util::choiceRandom($generalCadidates)->getID(),
- 'destCityID' => Util::choiceRandom($cityCandidates)['city']
+ 'destGeneralID' => $this->rng->choice($generalCadidates)->getID(),
+ 'destCityID' => $this->rng->choice($cityCandidates)['city']
]);
if (!$cmd->hasFullConditionMet()) {
@@ -663,7 +673,7 @@ class GeneralAI
}
/** @var General */
- $pickedGeneral = Util::choiceRandom($generalCadidates);
+ $pickedGeneral = $this->rng->choice($generalCadidates);
$minRecruitPop = $this->fullLeadership * 100 + GameConst::$minAvailableRecruitPop;
if (!$this->generalPolicy->can한계징병) {
$minRecruitPop = max($minRecruitPop, $this->fullLeadership * 100 + $this->nationPolicy->minNPCRecruitCityPopulation);
@@ -717,7 +727,7 @@ class GeneralAI
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
'destGeneralID' => $pickedGeneral->getID(),
- 'destCityID' => Util::choiceRandomUsingWeight($recruitableCityList)
+ 'destCityID' => $this->rng->choiceUsingWeight($recruitableCityList)
]);
if (!$cmd->hasFullConditionMet()) {
@@ -762,9 +772,9 @@ class GeneralAI
}
if (in_array($this->dipState, [self::d직전, self::d전쟁]) && count($this->frontCities) > 2) {
- $selCity = Util::choiceRandom($this->frontCities);
+ $selCity = $this->rng->choice($this->frontCities);
} else {
- $selCity = Util::choiceRandom($this->supplyCities);
+ $selCity = $this->rng->choice($this->supplyCities);
}
//고립된 장수가 많을 수록 발령 확률 증가
$args[] = [
@@ -776,7 +786,7 @@ class GeneralAI
return null;
}
- $arg = Util::choiceRandom($args);
+ $arg = $this->rng->choice($args);
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, $arg);
if (!$cmd->hasFullConditionMet()) {
@@ -835,8 +845,8 @@ class GeneralAI
}
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
- 'destGeneralID' => Util::choiceRandom($generalCandidates)->getID(),
- 'destCityID' => Util::choiceRandomUsingWeight($cityCandidates)
+ 'destGeneralID' => $this->rng->choice($generalCandidates)->getID(),
+ 'destCityID' => $this->rng->choiceUsingWeight($cityCandidates)
]);
if (!$cmd->hasFullConditionMet()) {
@@ -898,9 +908,9 @@ class GeneralAI
}
/** @var General */
- $destGeneral = Util::choiceRandom($generalCandidates);
+ $destGeneral = $this->rng->choice($generalCandidates);
$srcCity = $this->supplyCities[$destGeneral->getCityID()];
- $destCity = $this->supplyCities[Util::choiceRandomUsingWeight($cityCandidiates)];
+ $destCity = $this->supplyCities[$this->rng->choiceUsingWeight($cityCandidiates)];
if ($srcCity['dev'] <= $destCity['dev']) {
return null;
@@ -962,7 +972,7 @@ class GeneralAI
}
/** @var General */
- $pickedGeneral = Util::choiceRandom($generalCadidates);
+ $pickedGeneral = $this->rng->choice($generalCadidates);
$minRecruitPop = $this->fullLeadership * 100 + GameConst::$minAvailableRecruitPop;
if (!$this->generalPolicy->can한계징병) {
$minRecruitPop = max($minRecruitPop, $this->fullLeadership * 100 + $this->nationPolicy->minNPCRecruitCityPopulation);
@@ -1020,7 +1030,7 @@ class GeneralAI
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
'destGeneralID' => $pickedGeneral->getID(),
- 'destCityID' => Util::choiceRandomUsingWeight($recruitableCityList)
+ 'destCityID' => $this->rng->choiceUsingWeight($recruitableCityList)
]);
if (!$cmd->hasFullConditionMet()) {
@@ -1042,7 +1052,7 @@ class GeneralAI
if ($lostGeneral->getNPCType() < 2 || $lostGeneral->getNPCType() == 5) {
continue;
}
- $selCity = Util::choiceRandom($this->supplyCities);
+ $selCity = $this->rng->choice($this->supplyCities);
//고립된 장수가 많을 수록 발령 확률 증가
$args[] = [
'destGeneralID' => $lostGeneral->getID(),
@@ -1052,7 +1062,7 @@ class GeneralAI
if (!$args) {
return null;
}
- $cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, Util::choiceRandom($args));
+ $cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, $this->rng->choice($args));
if (!$cmd->hasFullConditionMet()) {
return null;
}
@@ -1111,8 +1121,8 @@ class GeneralAI
}
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
- 'destGeneralID' => Util::choiceRandom($generalCandidates)->getID(),
- 'destCityID' => Util::choiceRandomUsingWeight($cityCandidates)
+ 'destGeneralID' => $this->rng->choice($generalCandidates)->getID(),
+ 'destCityID' => $this->rng->choiceUsingWeight($cityCandidates)
]);
if (!$cmd->hasFullConditionMet()) {
@@ -1170,9 +1180,9 @@ class GeneralAI
}
/** @var General */
- $destGeneral = Util::choiceRandom($generalCandidates);
+ $destGeneral = $this->rng->choice($generalCandidates);
$srcCity = $this->supplyCities[$destGeneral->getCityID()];
- $destCity = $this->supplyCities[Util::choiceRandomUsingWeight($cityCandidiates)];
+ $destCity = $this->supplyCities[$this->rng->choiceUsingWeight($cityCandidiates)];
if ($srcCity['dev'] <= $destCity['dev']) {
return null;
@@ -1269,7 +1279,7 @@ class GeneralAI
$this->general,
$this->env,
$lastTurn,
- Util::choiceRandomUsingWeightPair($candidateArgs)
+ $this->rng->choiceUsingWeightPair($candidateArgs)
);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -1376,7 +1386,7 @@ class GeneralAI
$this->general,
$this->env,
$lastTurn,
- Util::choiceRandomUsingWeightPair($candidateArgs)
+ $this->rng->choiceUsingWeightPair($candidateArgs)
);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -1469,7 +1479,7 @@ class GeneralAI
$this->general,
$this->env,
$lastTurn,
- Util::choiceRandomUsingWeightPair($candidateArgs)
+ $this->rng->choiceUsingWeightPair($candidateArgs)
);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -1590,7 +1600,7 @@ class GeneralAI
$this->general,
$this->env,
$lastTurn,
- Util::choiceRandomUsingWeightPair($candidateArgs)
+ $this->rng->choiceUsingWeightPair($candidateArgs)
);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -1720,7 +1730,7 @@ class GeneralAI
$this->general,
$this->env,
$lastTurn,
- Util::choiceRandomUsingWeightPair($candidateArgs)
+ $this->rng->choiceUsingWeightPair($candidateArgs)
);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -1888,7 +1898,7 @@ class GeneralAI
$trialProp /= 4;
$trialProp = $trialProp ** 6;
- if (!Util::randBool($trialProp)) {
+ if (!$this->rng->nextBool($trialProp)) {
return null;
}
@@ -1924,14 +1934,14 @@ class GeneralAI
if (!$lowTargetNations) {
return null;
}
- if (Util::randBool(1 / count($lowTargetNations))) {
+ if ($this->rng->nextBool(1 / count($lowTargetNations))) {
return null;
}
$nations = $warNations;
}
$cmd = buildNationCommandClass('che_선전포고', $this->general, $this->env, $lastTurn, [
- 'destNationID' => Util::choiceRandomUsingWeight($nations)
+ 'destNationID' => $this->rng->choiceUsingWeight($nations)
]);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -2063,7 +2073,7 @@ class GeneralAI
$candidates[] = $stopID;
}
}
- $targetCityID = Util::choiceRandom($candidates);
+ $targetCityID = $this->rng->choice($candidates);
}
$cmd = buildNationCommandClass('che_천도', $this->general, $this->env, $lastTurn, [
@@ -2098,7 +2108,7 @@ class GeneralAI
$cmdList = [];
- if (($nation['rice'] < GameConst::$baserice) && Util::randBool(0.3)) {
+ if (($nation['rice'] < GameConst::$baserice) && $this->rng->nextBool(0.3)) {
return null;
}
@@ -2179,7 +2189,7 @@ class GeneralAI
return null;
}
- return Util::choiceRandomUsingWeightPair($cmdList);
+ return $this->rng->choiceUsingWeightPair($cmdList);
}
protected function do긴급내정(): ?GeneralCommand
@@ -2198,14 +2208,14 @@ class GeneralAI
$city = $this->city;
- if ($city['trust'] < 70 && Util::randBool($leadership / GameConst::$chiefStatMin)) {
+ if ($city['trust'] < 70 && $this->rng->nextBool($leadership / GameConst::$chiefStatMin)) {
$cmd = buildGeneralCommandClass('che_주민선정', $general, $env);
if ($cmd->hasFullConditionMet()) {
return $cmd;
}
}
- if ($city['pop'] < $this->nationPolicy->minNPCRecruitCityPopulation && Util::randBool($leadership / GameConst::$chiefStatMin / 2)) {
+ if ($city['pop'] < $this->nationPolicy->minNPCRecruitCityPopulation && $this->rng->nextBool($leadership / GameConst::$chiefStatMin / 2)) {
$cmd = buildGeneralCommandClass('che_정착장려', $general, $env);
if ($cmd->hasFullConditionMet()) {
return $cmd;
@@ -2233,7 +2243,7 @@ class GeneralAI
$city = $this->city;
$nation = $this->nation;
- if (($nation['rice'] < GameConst::$baserice) && Util::randBool(0.3)) {
+ if (($nation['rice'] < GameConst::$baserice) && $this->rng->nextBool(0.3)) {
return null;
}
@@ -2241,7 +2251,7 @@ class GeneralAI
$isSpringSummer = $this->env['month'] <= 6;
$cmdList = [];
- if (Util::randBool(0.3)) {
+ if ($this->rng->nextBool(0.3)) {
return null;
}
@@ -2324,7 +2334,7 @@ class GeneralAI
return null;
}
- $cmd = Util::choiceRandomUsingWeightPair($cmdList);
+ $cmd = $this->rng->choiceUsingWeightPair($cmdList);
return $cmd;
}
@@ -2474,7 +2484,7 @@ class GeneralAI
$maxPop = $city['pop_max'] - $this->nationPolicy->minNPCRecruitCityPopulation;
if (($city['pop'] / $city['pop_max'] < $this->nationPolicy->safeRecruitCityPopulationRatio) &&
- (Util::randF($remainPop / $maxPop))
+ ($this->rng->nextFloat1($remainPop / $maxPop))
) {
return null;
}
@@ -2516,7 +2526,7 @@ class GeneralAI
$availableArmType[GameUnitConst::T_WIZARD] = $dex[GameUnitConst::T_WIZARD] * $this->fullIntel * 3;
}
- $armType = Util::choiceRandomUsingWeight($availableArmType);
+ $armType = $this->rng->choiceUsingWeight($availableArmType);
}
@@ -2539,7 +2549,7 @@ class GeneralAI
}
if ($types) {
- $type = Util::choiceRandomUsingWeight($types);
+ $type = $this->rng->choiceUsingWeight($types);
} else {
throw new MustNotBeReachedException('에러:' . print_r([$general->getName(), $general->getAuxVar('armType'), $armType, $cities, $regions, $relYear, $tech], true));
}
@@ -2636,7 +2646,7 @@ class GeneralAI
if (!$cmdList) {
return null;
}
- return Util::choiceRandomUsingWeightPair($cmdList);
+ return $this->rng->choiceUsingWeightPair($cmdList);
}
public function do소집해제(): ?GeneralCommand
@@ -2650,7 +2660,7 @@ class GeneralAI
if ($this->general->getVar('crew') == 0) {
return null;
}
- if (Util::randBool(0.75)) {
+ if ($this->rng->nextBool(0.75)) {
return null;
}
$cmd = buildGeneralCommandClass('che_소집해제', $this->general, $this->env);
@@ -2675,7 +2685,7 @@ class GeneralAI
$city = $this->city;
$nation = $this->nation;
- if (($nation['rice'] < GameConst::$baserice) && Util::randBool(0.7)) {
+ if (($nation['rice'] < GameConst::$baserice) && $this->rng->nextBool(0.7)) {
return null;
}
@@ -2724,7 +2734,7 @@ class GeneralAI
throw new \RuntimeException('출병 불가' . $cityID . var_export($attackableNations, true) . var_export($nearCities, true));
}
- $cmd = buildGeneralCommandClass('che_출병', $general, $this->env, ['destCityID' => Util::choiceRandom($attackableCities)]);
+ $cmd = buildGeneralCommandClass('che_출병', $general, $this->env, ['destCityID' => $this->rng->choice($attackableCities)]);
if (!$cmd->hasFullConditionMet()) {
return null;
}
@@ -2796,7 +2806,7 @@ class GeneralAI
if ($genRes < $reqRes * 1.5) {
continue;
}
- if ($reqRes > 0 && !Util::randBool(($genRes / $reqRes) - 0.5)) {
+ if ($reqRes > 0 && !$this->rng->nextBool(($genRes / $reqRes) - 0.5)) {
continue;
}
$amount = $genRes - $reqRes;
@@ -2813,7 +2823,7 @@ class GeneralAI
return null;
}
- $cmd = buildGeneralCommandClass('che_헌납', $general, $this->env, Util::choiceRandomUsingWeightPair($args));
+ $cmd = buildGeneralCommandClass('che_헌납', $general, $this->env, $this->rng->choiceUsingWeightPair($args));
if (!$cmd->hasFullConditionMet()) {
return null;
}
@@ -2915,7 +2925,7 @@ class GeneralAI
$cmd = buildGeneralCommandClass('che_NPC능동', $this->general, $this->env, [
'optionText' => '순간이동',
- 'destCityID' => Util::choiceRandomUsingWeight($recruitableCityList),
+ 'destCityID' => $this->rng->choiceUsingWeight($recruitableCityList),
]);
@@ -2963,7 +2973,7 @@ class GeneralAI
$cmd = buildGeneralCommandClass('che_NPC능동', $this->general, $this->env, [
'optionText' => '순간이동',
- 'destCityID' => Util::choiceRandomUsingWeight($candidateCities),
+ 'destCityID' => $this->rng->choiceUsingWeight($candidateCities),
]);
@@ -2981,7 +2991,7 @@ class GeneralAI
}
$city = $this->city;
- if (Util::randBool(0.6)) {
+ if ($this->rng->nextBool(0.6)) {
return null;
}
@@ -3002,7 +3012,7 @@ class GeneralAI
return null;
}
- if (!Util::randBool($warpProp)) {
+ if (!$this->rng->nextBool($warpProp)) {
return null;
}
@@ -3037,7 +3047,7 @@ class GeneralAI
$cmd = buildGeneralCommandClass('che_NPC능동', $this->general, $this->env, [
'optionText' => '순간이동',
- 'destCityID' => Util::choiceRandomUsingWeight($candidateCities),
+ 'destCityID' => $this->rng->choiceUsingWeight($candidateCities),
]);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -3068,7 +3078,7 @@ class GeneralAI
$general = $this->general;
if ($general->getNPCType() == 5) {
- $newKillTurn = ($general->getVar('killturn') + Util::randRangeInt(2, 4)) % 5;
+ $newKillTurn = ($general->getVar('killturn') + $this->rng->nextRangeInt(2, 4)) % 5;
$newKillTurn += 70;
$general->setVar('killturn', $newKillTurn);
}
@@ -3121,7 +3131,7 @@ class GeneralAI
if (!$candidateCities) {
return null;
}
- $movingTargetCityID = Util::choiceRandomUsingWeightPair($candidateCities);
+ $movingTargetCityID = $this->rng->choiceUsingWeightPair($candidateCities);
$general->setAuxVar('movingTargetCityID', $movingTargetCityID);
}
@@ -3149,7 +3159,7 @@ class GeneralAI
}
$cmd = buildGeneralCommandClass('che_이동', $general, $this->env, [
- 'destCityID' => Util::choiceRandomUsingWeightPair($candidateCities)
+ 'destCityID' => $this->rng->choiceUsingWeightPair($candidateCities)
]);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -3173,7 +3183,7 @@ class GeneralAI
}
$currentCityLevel = CityConst::byID($general->getCityID())->level;
- if (($currentCityLevel < 5 || 6 < $currentCityLevel) && Util::randBool(0.5)) {
+ if (($currentCityLevel < 5 || 6 < $currentCityLevel) && $this->rng->nextBool(0.5)) {
return null;
}
@@ -3199,7 +3209,7 @@ class GeneralAI
if ($cityLevel < 5 || 6 < $cityLevel) {
continue;
}
- if ($dist == 3 && Util::randBool()) {
+ if ($dist == 3 && $this->rng->nextBool()) {
continue;
}
$availableNearCity = true;
@@ -3209,7 +3219,7 @@ class GeneralAI
return null;
}
- $prop = Util::randF() * (GameConst::$defaultStatNPCMax + GameConst::$chiefStatMin) / 2;
+ $prop = $this->rng->nextFloat1() * (GameConst::$defaultStatNPCMax + GameConst::$chiefStatMin) / 2;
$ratio = ($this->fullLeadership + $this->fullStrength + $this->fullIntel) / 3;
@@ -3219,7 +3229,7 @@ class GeneralAI
//XXX: 건국기한 2년
$more = Util::valueFit(3 - $this->env['year'] + $this->env['init_year'], 1, 3);
- if (!Util::randBool(0.0075 * $more)) {
+ if (!$this->rng->nextBool(0.0075 * $more)) {
return null;
}
@@ -3245,8 +3255,8 @@ class GeneralAI
protected function do건국(): ?GeneralCommand
{
- $nationType = Util::choiceRandom(GameConst::$availableNationType);
- $nationColor = Util::choiceRandom(array_keys(GetNationColors()));
+ $nationType = $this->rng->choice(GameConst::$availableNationType);
+ $nationColor = $this->rng->choice(array_keys(GetNationColors()));
$cmd = buildGeneralCommandClass('che_건국', $this->general, $this->env, [
'nationName' => "㉿" . mb_substr($this->general->getName(), 1),
'nationType' => $nationType,
@@ -3300,7 +3310,7 @@ class GeneralAI
}
}
- if (Util::randBool(0.3)) {
+ if ($this->rng->nextBool(0.3)) {
if ($env['startyear'] + 3 > $env['year']) {
//초기 임관 기간에서는 국가가 적을수록 임관 시도가 적음
$nationCnt = $db->queryFirstField('SELECT count(nation) FROM nation');
@@ -3309,7 +3319,7 @@ class GeneralAI
return null;
}
- if (Util::randBool(pow(1 / ($nationCnt + 1) / pow($notFullNationCnt, 3), 1 / 4))) {
+ if ($this->rng->nextBool(pow(1 / ($nationCnt + 1) / pow($notFullNationCnt, 3), 1 / 4))) {
return null;
}
}
@@ -3327,10 +3337,10 @@ class GeneralAI
return $cmd;
}
- if (Util::randBool(0.2)) {
+ if ($this->rng->nextBool(0.2)) {
$paths = array_keys(CityConst::byID($city['city'])->path);
- $cmd = buildGeneralCommandClass('che_이동', $general, $env, ['destCityID' => Util::choiceRandom($paths)]);
+ $cmd = buildGeneralCommandClass('che_이동', $general, $env, ['destCityID' => $this->rng->choice($paths)]);
if (!$cmd->hasFullConditionMet()) {
return null;
}
@@ -3350,7 +3360,7 @@ class GeneralAI
if ($general->getNationID() == 0) {
$cmd = buildGeneralCommandClass('che_인재탐색', $general, $this->env);
- if (!$cmd->hasFullConditionMet() || Util::randBool()) {
+ if (!$cmd->hasFullConditionMet() || $this->rng->nextBool()) {
$cmd = buildGeneralCommandClass('che_견문', $general, $this->env);
}
return $cmd;
@@ -3378,7 +3388,7 @@ class GeneralAI
$general = $this->general;
if ($general->getNationID() == 0) {
$cmd = buildGeneralCommandClass('che_인재탐색', $general, $this->env);
- if (!$cmd->hasFullConditionMet() || Util::randBool(0.8)) {
+ if (!$cmd->hasFullConditionMet() || $this->rng->nextBool(0.8)) {
$cmd = buildGeneralCommandClass('che_견문', $general, $this->env);
}
return $cmd;
@@ -3395,7 +3405,7 @@ class GeneralAI
}
- $cmd = buildGeneralCommandClass(Util::choiceRandom($candidate), $this->general, $this->env);
+ $cmd = buildGeneralCommandClass($this->rng->choice($candidate), $this->general, $this->env);
if (!$cmd->hasFullConditionMet()) {
return buildGeneralCommandClass('che_물자조달', $this->general, $this->env);
}
@@ -3646,7 +3656,7 @@ class GeneralAI
//특별 메세지 있는 경우 출력
$term = $this->env['turnterm'];
- if ($general->getVar('npcmsg') && Util::randBool(GameConst::$npcMessageFreqByDay * $term / (60 * 24))) {
+ if ($general->getVar('npcmsg') && $this->rng->nextBool(GameConst::$npcMessageFreqByDay * $term / (60 * 24))) {
$src = new MessageTarget(
$general->getID(),
$general->getVar('name'),
@@ -3830,16 +3840,16 @@ class GeneralAI
/** @var General */
if ($this->npcWarGenerals) {
/** @var General */
- $randGeneral = Util::choiceRandom($this->npcWarGenerals);
+ $randGeneral = $this->rng->choice($this->npcWarGenerals);
} else if ($this->npcCivilGenerals) {
/** @var General */
- $randGeneral = Util::choiceRandom($this->npcCivilGenerals);
+ $randGeneral = $this->rng->choice($this->npcCivilGenerals);
} else if ($this->userWarGenerals) {
/** @var General */
- $randGeneral = Util::choiceRandom($this->userWarGenerals);
+ $randGeneral = $this->rng->choice($this->userWarGenerals);
} else if ($this->userCivilGenerals) {
/** @var General */
- $randGeneral = Util::choiceRandom($this->userCivilGenerals);
+ $randGeneral = $this->rng->choice($this->userCivilGenerals);
} else {
break;
}
@@ -3987,10 +3997,10 @@ class GeneralAI
if (!key_exists($chiefLevel, $this->chiefGenerals) && !key_exists($chiefLevel, $nextChiefs)) {
$newChiefProb = 1;
} else {
- $newChiefProb = Util::randF(0.1);
+ $newChiefProb = $this->rng->nextFloat1(0.1);
}
- if ($newChiefProb < 1 && !Util::randF($newChiefProb)) {
+ if ($newChiefProb < 1 && !$this->rng->nextFloat1($newChiefProb)) {
continue;
}
diff --git a/hwe/sammo/GeneralPool/RandomNameGeneral.php b/hwe/sammo/GeneralPool/RandomNameGeneral.php
index fcd15979..ffdd7012 100644
--- a/hwe/sammo/GeneralPool/RandomNameGeneral.php
+++ b/hwe/sammo/GeneralPool/RandomNameGeneral.php
@@ -4,6 +4,7 @@ namespace sammo\GeneralPool;
use MeekroDB;
use sammo\AbsGeneralPool;
use sammo\GameConst;
+use sammo\RandUtil;
use sammo\Util;
@@ -26,67 +27,14 @@ class RandomNameGeneral extends AbsGeneralPool{
return $db->affectedRows()!=0;
}
- public function giveGeneralSpec(array $pickTypeList, array $avgGen, array $env){
- //do Nothing
- $dexTotal = $avgGen['dex_t'];
-
- $pickType = Util::choiceRandomUsingWeight($pickTypeList);
-
- $totalStat = GameConst::$defaultStatNPCTotal;
- $minStat = GameConst::$defaultStatNPCMin;
- $mainStat = GameConst::$defaultStatNPCMax - Util::randRangeInt(0, GameConst::$defaultStatNPCMin);
- $otherStat = $minStat + Util::randRangeInt(0, Util::toInt(GameConst::$defaultStatNPCMin/2));
- $subStat = $totalStat - $mainStat - $otherStat;
- if ($subStat < $minStat) {
- $subStat = $otherStat;
- $otherStat = $minStat;
- $mainStat = $totalStat - $subStat - $otherStat;
- if ($mainStat) {
- throw new \LogicException('기본 스탯 설정값이 잘못되어 있음');
- }
- }
-
- if ($pickType == '무') {
- $leadership = $subStat;
- $strength = $mainStat;
- $intel = $otherStat;
- $dexVal = Util::choiceRandom([
- [$dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8, $dexTotal / 8],
- [$dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8],
- [$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8],
- ]);
- } else if ($pickType == '지') {
- $leadership = $subStat;
- $strength = $otherStat;
- $intel = $mainStat;
- $dexVal = [$dexTotal / 8, $dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8];
- } else {
- $leadership = $otherStat;
- $strength = $subStat;
- $intel = $mainStat;
- $dexVal = [$dexTotal / 4, $dexTotal / 4, $dexTotal / 4, $dexTotal / 4];
- }
-
- $leadership = Util::round($leadership);
- $strength = Util::round($strength);
- $intel = Util::round($intel);
-
- $builder = $this->getGeneralBuilder();
- $builder->setStat($leadership, $strength, $intel);
- $builder->setDex($dexVal[0], $dexVal[1], $dexVal[2], $dexVal[3], $avgGen['dex5']);
- $builder->setCityID(Util::choiceRandom(array_keys(\sammo\CityConst::all())));
-
- $builder->setExpDed($avgGen['exp'], $avgGen['ded']);
- }
-
- static protected function pickGeneral1FromPool(\MeekroDB $db, int $owner, ?string $prefix=null):self{
+ static protected function pickGeneral1FromPool(\MeekroDB $db, RandUtil $rng, int $owner, ?string $prefix=null):self{
$loopCnt = 0;
while(true){
- $firstname = Util::choiceRandom(GameConst::$randGenFirstName);
- $middlename = Util::choiceRandom(GameConst::$randGenMiddleName);
- $lastname = Util::choiceRandom(GameConst::$randGenLastName);
+ $firstname = $rng->choice(GameConst::$randGenFirstName);
+ $middlename = $rng->choice(GameConst::$randGenMiddleName);
+ $lastname = $rng->choice(GameConst::$randGenLastName);
$generalName = "{$firstname}{$middlename}{$lastname}";
if($prefix){
@@ -106,7 +54,7 @@ class RandomNameGeneral extends AbsGeneralPool{
$uniqueName = $generalName;
- return new static($db, [
+ return new static($db, $rng, [
'uniqueName'=>$uniqueName,
'generalName'=>$generalName,
'imgsvr'=>0,
@@ -114,17 +62,17 @@ class RandomNameGeneral extends AbsGeneralPool{
], '9999-12-31 12:00:00');
}
- static public function pickGeneralFromPool(MeekroDB $db, int $owner, int $pickCnt, ?string $prefix = null): array
+ static public function pickGeneralFromPool(MeekroDB $db, RandUtil $rng, int $owner, int $pickCnt, ?string $prefix = null): array
{
/** @var RandomNameGeneral[] */
$result = [];
$dbInsert = [];
$oNow = new \DateTimeImmutable();
-
-
+
+
for($i=0;$i<$pickCnt;$i++){
- $result[] = static::pickGeneral1FromPool($db, $owner, $prefix);
+ $result[] = static::pickGeneral1FromPool($db, $rng, $owner, $prefix);
}
if($owner){
diff --git a/hwe/sammo/GeneralTrigger/che_도시치료.php b/hwe/sammo/GeneralTrigger/che_도시치료.php
index 025b5352..865cda44 100644
--- a/hwe/sammo/GeneralTrigger/che_도시치료.php
+++ b/hwe/sammo/GeneralTrigger/che_도시치료.php
@@ -10,7 +10,7 @@ use sammo\JosaUtil;
class che_도시치료 extends BaseGeneralTrigger{
protected $priority = 10010;
- public function action(?array $env=null, $arg=null):?array{
+ public function action(\sammo\RandUtil $rng, ?array $env=null, $arg=null):?array{
/** @var \sammo\General $general */
$general = $this->object;
@@ -43,7 +43,7 @@ class che_도시치료 extends BaseGeneralTrigger{
/** @var string|null */
$curedPatientName = null;
foreach($patients as [$patientID, $patientName, $patientNationID]){
- if (!Util::randBool(0.5)) {
+ if (!$rng->nextBool(0.5)) {
continue;
}
diff --git a/hwe/sammo/GeneralTrigger/che_병력군량소모.php b/hwe/sammo/GeneralTrigger/che_병력군량소모.php
index 31c0c433..5dc948cd 100644
--- a/hwe/sammo/GeneralTrigger/che_병력군량소모.php
+++ b/hwe/sammo/GeneralTrigger/che_병력군량소모.php
@@ -10,7 +10,7 @@ use sammo\JosaUtil;
class che_병력군량소모 extends BaseGeneralTrigger{
protected $priority = 50000;
- public function action(?array $env=null, $arg=null):?array{
+ public function action(\sammo\RandUtil $rng, ?array $env=null, $arg=null):?array{
/** @var \sammo\General $general */
$general = $this->object;
@@ -26,13 +26,13 @@ class che_병력군량소모 extends BaseGeneralTrigger{
$db->update('city', [
'pop'=>$db->sqleval('pop + %i', $general->getVar('crew'))
], 'city=%i', $general->getCityID());
-
+
$general->setVar('crew', 0);
$general->setVar('rice', 0);
$general->getLogger()->pushGeneralActionLog(
'군량이 모자라 병사들이 소집해제>되었습니다!', ActionLogger::PLAIN
);
-
+
$general->activateSkill('pre.소집해제');
}
$general->activateSkill('pre.병력군량소모');
diff --git a/hwe/sammo/GeneralTrigger/che_부상경감.php b/hwe/sammo/GeneralTrigger/che_부상경감.php
index 74a019dd..2c1e6121 100644
--- a/hwe/sammo/GeneralTrigger/che_부상경감.php
+++ b/hwe/sammo/GeneralTrigger/che_부상경감.php
@@ -10,7 +10,7 @@ use sammo\JosaUtil;
class che_부상경감 extends BaseGeneralTrigger{
protected $priority = 10000;
- public function action(?array $env=null, $arg=null):?array{
+ public function action(\sammo\RandUtil $rng, ?array $env=null, $arg=null):?array{
/** @var \sammo\General $general */
$general = $this->object;
diff --git a/hwe/sammo/GeneralTrigger/che_아이템치료.php b/hwe/sammo/GeneralTrigger/che_아이템치료.php
index f236af1a..daad2606 100644
--- a/hwe/sammo/GeneralTrigger/che_아이템치료.php
+++ b/hwe/sammo/GeneralTrigger/che_아이템치료.php
@@ -16,7 +16,7 @@ class che_아이템치료 extends BaseGeneralTrigger{
$this->injuryTarget = $injuryTarget;
}
- public function action(?array $env=null, $arg=null):?array{
+ public function action(\sammo\RandUtil $rng, ?array $env=null, $arg=null):?array{
/** @var \sammo\General $general */
$general = $this->object;
diff --git a/hwe/sammo/ObjectTrigger.php b/hwe/sammo/ObjectTrigger.php
index ad3754f7..82648ee9 100644
--- a/hwe/sammo/ObjectTrigger.php
+++ b/hwe/sammo/ObjectTrigger.php
@@ -22,7 +22,7 @@ abstract class ObjectTrigger{
return $this;
}
- abstract public function action(?array $env=null, $arg=null):?array;
+ abstract public function action(RandUtil $rng, ?array $env=null, $arg=null):?array;
public function getUniqueID():string{
$priority = $this->priority;
$fqn = static::class;
diff --git a/hwe/sammo/ResetHelper.php b/hwe/sammo/ResetHelper.php
index 9358a2a3..a23ed087 100644
--- a/hwe/sammo/ResetHelper.php
+++ b/hwe/sammo/ResetHelper.php
@@ -147,7 +147,8 @@ class ResetHelper{
return [
'result'=>true,
'serverID'=>$serverID,
- 'seasonIdx'=>$seasonIdx
+ 'seasonIdx'=>$seasonIdx,
+ 'hiddenSeed'=>$hiddenSeed,
];
}
@@ -187,8 +188,14 @@ class ResetHelper{
$serverID = $clearResult['serverID'];
$seasonIdx = $clearResult['seasonIdx'];
+ $hiddenSeed = $clearResult['hiddenSeed'];
- $scenarioObj = new Scenario($scenario, true);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ $hiddenSeed,
+ 'InitScenario'
+ )));
+
+ $scenarioObj = new Scenario($rng, $scenario, true);
if(class_exists('\\sammo\GameConst', false)){
trigger_error("이미 GameConst가 호출되어있습니다", E_USER_NOTICE);
diff --git a/hwe/sammo/Scenario.php b/hwe/sammo/Scenario.php
index 05615037..9123b6a6 100644
--- a/hwe/sammo/Scenario.php
+++ b/hwe/sammo/Scenario.php
@@ -6,6 +6,8 @@ use sammo\Scenario\GeneralBuilder;
class Scenario{
const SCENARIO_PATH = __DIR__.'/../scenario';
+ private readonly RandUtil $rng;
+
private $scenarioIdx;
private $scenarioPath;
@@ -70,6 +72,7 @@ class Scenario{
$this->tmpGeneralQueue[$name] = $rawGeneral;
$obj = (new Scenario\GeneralBuilder(
+ $this->rng,
$name,
false,
$picturePath,
@@ -106,7 +109,7 @@ class Scenario{
'month'=>0 //포인트
];
- $neutralNation = new Scenario\Nation(0, '재야', '#000000', 0, 0);
+ $neutralNation = new Scenario\Nation($this->rng, 0, '재야', '#000000', 0, 0);
$this->nations = [];
$this->nations[0] = $neutralNation;
$this->nationsInv = [$neutralNation->getName() => $neutralNation];
@@ -117,6 +120,7 @@ class Scenario{
$nation = new Scenario\Nation(
+ $this->rng,
$nationID,
$name,
$color,
@@ -162,7 +166,7 @@ class Scenario{
'month'=>0 //포인트
];
- $neutralNation = new Scenario\Nation(0, '재야', '#000000', 0, 0);
+ $neutralNation = new Scenario\Nation($this->rng, 0, '재야', '#000000', 0, 0);
$this->nations = [];
$this->nations[0] = $neutralNation;
$this->nationsInv = [$neutralNation->getName() => $neutralNation];
@@ -173,6 +177,7 @@ class Scenario{
$nation = new Scenario\Nation(
+ $this->rng,
$nationID,
$name,
$color,
@@ -263,7 +268,8 @@ class Scenario{
return $this->gameConf;
}
- public function __construct(int $scenarioIdx, bool $lazyInit = true){
+ public function __construct(RandUtil $rng, int $scenarioIdx, bool $lazyInit = true){
+ $this->rng = $rng;
$scenarioPath = self::SCENARIO_PATH."/scenario_{$scenarioIdx}.json";
$this->scenarioIdx = $scenarioIdx;
@@ -577,6 +583,8 @@ class Scenario{
public static function getAllScenarios(){
$result = [];
+ $rng = new RandUtil(new LiteHashDRBG(random_bytes(16)));
+
foreach(glob(self::SCENARIO_PATH.'/scenario_*.json') as $scenarioPath){
$scenarioName = pathinfo(basename($scenarioPath), PATHINFO_FILENAME);
$scenarioIdx = Util::array_last(explode('_', $scenarioName));
@@ -590,7 +598,7 @@ class Scenario{
continue;
}
- $result[$scenarioIdx] = new Scenario($scenarioIdx);
+ $result[$scenarioIdx] = new Scenario($rng, $scenarioIdx);
}
return $result;
}
diff --git a/hwe/sammo/Scenario/GeneralBuilder.php b/hwe/sammo/Scenario/GeneralBuilder.php
index 769eb354..190bc666 100644
--- a/hwe/sammo/Scenario/GeneralBuilder.php
+++ b/hwe/sammo/Scenario/GeneralBuilder.php
@@ -8,6 +8,7 @@ use \sammo\GameUnitConst;
use \sammo\CityConst;
use sammo\Enums\RankColumn;
use \sammo\GameConst;
+use sammo\RandUtil;
use \sammo\SpecialityHelper;
use sammo\TimeUtil;
class GeneralBuilder{
@@ -67,6 +68,7 @@ class GeneralBuilder{
protected $aux = [];
public function __construct(
+ public readonly RandUtil $rng,
string $name,
bool $isDynamicImageSvr,
$picturePath,
@@ -109,17 +111,17 @@ class GeneralBuilder{
'intel'=>$this->intel
];
if($option === '랜덤전특'){
- $this->specialWar = SpecialityHelper::pickSpecialWar($general);
+ $this->specialWar = SpecialityHelper::pickSpecialWar($this->rng, $general);
}
else if($option === '랜덤내특'){
- $this->specialDomestic = SpecialityHelper::pickSpecialDomestic($general);
+ $this->specialDomestic = SpecialityHelper::pickSpecialDomestic($this->rng, $general);
}
else if($option === '랜덤'){
- if(Util::randBool(2/3)){
- $this->specialWar = SpecialityHelper::pickSpecialWar($general);
+ if($this->rng->nextBool(2/3)){
+ $this->specialWar = SpecialityHelper::pickSpecialWar($this->rng, $general);
}
else{
- $this->specialDomestic = SpecialityHelper::pickSpecialDomestic($general);
+ $this->specialDomestic = SpecialityHelper::pickSpecialDomestic($this->rng, $general);
}
}
return $this;
@@ -165,7 +167,7 @@ class GeneralBuilder{
public function setAffinity(int $affinity):self{
if($affinity < 1){
- $this->affinity = Util::randRangeInt(1, 150);
+ $this->affinity = $this->rng->nextRangeInt(1, 150);
}
else if($affinity >= 900){
$this->affinity = 999;
@@ -302,11 +304,11 @@ class GeneralBuilder{
}
public function fillRandomStat(array $pickTypeList, &$pickedType=null):self{
- $pickType = Util::choiceRandomUsingWeight($pickTypeList);
+ $pickType = $this->rng->choiceUsingWeight($pickTypeList);
$totalStat = GameConst::$defaultStatNPCTotal;
$minStat = GameConst::$defaultStatNPCMin;
- $mainStat = GameConst::$defaultStatNPCMax - Util::randRangeInt(0, GameConst::$defaultStatNPCMin);
- $otherStat = $minStat + Util::randRangeInt(0, Util::toInt(GameConst::$defaultStatNPCMin/2));
+ $mainStat = GameConst::$defaultStatNPCMax - $this->rng->nextRangeInt(0, GameConst::$defaultStatNPCMin);
+ $otherStat = $minStat + $this->rng->nextRangeInt(0, Util::toInt(GameConst::$defaultStatNPCMin/2));
$subStat = $totalStat - $mainStat - $otherStat;
if ($subStat < $minStat) {
$subStat = $otherStat;
@@ -341,7 +343,7 @@ class GeneralBuilder{
}
if($this->affinity === null || $this->affinity === 0){
- $this->affinity = Util::randRangeInt(1, 150);
+ $this->affinity = $this->rng->nextRangeInt(1, 150);
}
if($this->birth === null){
@@ -371,7 +373,7 @@ class GeneralBuilder{
}
if($this->ego === null){
- $this->ego = Util::choiceRandom(GameConst::$availablePersonality);
+ $this->ego = $this->rng->choice(GameConst::$availablePersonality);
}
if($this->specialDomestic === null){
@@ -401,12 +403,12 @@ class GeneralBuilder{
}
if($this->affinity === null || $this->affinity === 0 || $isFictionMode){
- $this->affinity = Util::randRangeInt(1, 150);
+ $this->affinity = $this->rng->nextRangeInt(1, 150);
}
if($this->birth === null){
- $this->birth = $env['year']+Util::randRange(-5, 5);
- $this->death = $this->birth+Util::randRangeInt(60, 80);
+ $this->birth = $env['year']+$this->rng->nextRange(-5, 5);
+ $this->death = $this->birth+$this->rng->nextRangeInt(60, 80);
}
@@ -443,7 +445,7 @@ class GeneralBuilder{
$pickType = '무';
break;
}
- $pickType = Util::choiceRandomUsingWeight([
+ $pickType = $this->rng->choiceUsingWeight([
'무'=>$strength,
'지'=>$intel
]);
@@ -463,7 +465,7 @@ class GeneralBuilder{
if(!$this->dex1 && key_exists('dex_t', $avgGen)){
$dexTotal = $avgGen['dex_t'];
if ($pickType == '무') {
- $dexVal = Util::choiceRandom([
+ $dexVal = $this->rng->choice([
[$dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8, $dexTotal / 8],
[$dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8, $dexTotal / 8],
[$dexTotal / 8, $dexTotal / 8, $dexTotal * 5 / 8, $dexTotal / 8],
@@ -477,7 +479,7 @@ class GeneralBuilder{
}
if($this->ego === null || $isFictionMode){
- $this->ego = Util::choiceRandom(GameConst::$availablePersonality);
+ $this->ego = $this->rng->choice(GameConst::$availablePersonality);
}
if($this->experience === null){
@@ -628,10 +630,10 @@ class GeneralBuilder{
if($this->cityID === null){
if($nationID == 0 || !CityHelper::getAllNationCities($nationID)){
- $cityObj = Util::choiceRandom(CityHelper::getAllCities());
+ $cityObj = $this->rng->choice(CityHelper::getAllCities());
}
else{
- $cityObj = Util::choiceRandom(CityHelper::getAllNationCities($nationID));
+ $cityObj = $this->rng->choice(CityHelper::getAllNationCities($nationID));
}
'@phan-var array $cityObj';
$this->cityID = $cityObj['id'];
@@ -644,7 +646,7 @@ class GeneralBuilder{
$officerLevel = $nationID?1:0;
}
- $turntime = \sammo\getRandTurn($env['turnterm'], new \DateTimeImmutable($env['turntime']));
+ $turntime = \sammo\getRandTurn($this->rng, $env['turnterm'], new \DateTimeImmutable($env['turntime']));
if($this->killturn){
$killturn = $this->killturn;
diff --git a/hwe/sammo/Scenario/Nation.php b/hwe/sammo/Scenario/Nation.php
index b6f74c76..fbf2267a 100644
--- a/hwe/sammo/Scenario/Nation.php
+++ b/hwe/sammo/Scenario/Nation.php
@@ -5,6 +5,8 @@ use \sammo\GameConst;
use \sammo\Util;
use \sammo\KVStorage;
use \sammo\Json;
+use sammo\RandUtil;
+
use function \sammo\getNationChiefLevel;
class Nation{
@@ -25,6 +27,7 @@ class Nation{
private $generals = [];
public function __construct(
+ private readonly RandUtil $rng,
int $id = null,
string $name = '국가',
string $color = '#000000',
@@ -77,7 +80,7 @@ class Nation{
}
if($this->type === null){
- $type = Util::choiceRandom(GameConst::$availableNationType);
+ $type = $this->rng->choice(GameConst::$availableNationType);
}
else if(strpos($this->type, '_') === FALSE){
$type = 'che_'.$this->type;
diff --git a/hwe/sammo/ScoutMessage.php b/hwe/sammo/ScoutMessage.php
index a99033e7..b3ffe536 100644
--- a/hwe/sammo/ScoutMessage.php
+++ b/hwe/sammo/ScoutMessage.php
@@ -27,7 +27,7 @@ class ScoutMessage extends Message{
}
parent::__construct(...func_get_args());
-
+
if(Util::array_get($msgOption['used'])){
$this->validScout = false;
}
@@ -66,7 +66,7 @@ class ScoutMessage extends Message{
$general = \sammo\General::createGeneralObjFromDB($receiverID, null, 2);
$logger = $general->getLogger();
-
+
list($result, $reason) = $this->checkScoutMessageValidation($receiverID);
if($result !== self::ACCEPTED){
@@ -88,7 +88,7 @@ class ScoutMessage extends Message{
return self::DECLINED;
}
- $commandObj->run();
+ $commandObj->run(NoRNG::rngInstance());
$commandObj->setNextAvailable();
//메시지 비 활성화
@@ -98,9 +98,9 @@ class ScoutMessage extends Message{
$josaRo = JosaUtil::pick($this->src->nationName, '로');
$newMsg = new Message(
- self::MSGTYPE_PRIVATE,
- $this->src,
- $this->dest,
+ self::MSGTYPE_PRIVATE,
+ $this->src,
+ $this->dest,
"{$this->src->nationName}{$josaRo} 등용 제의 수락",
new \DateTime(),
new \DateTime('9999-12-31'),
@@ -120,9 +120,9 @@ class ScoutMessage extends Message{
$josaRo = JosaUtil::pick($this->src->nationName, '로');
$newMsg = new Message(
- self::MSGTYPE_PRIVATE,
- $this->src,
- $this->dest,
+ self::MSGTYPE_PRIVATE,
+ $this->src,
+ $this->dest,
"{$this->src->nationName}{$josaRo} 등용 제의 거부",
new \DateTime(),
new \DateTime('9999-12-31'),
@@ -155,7 +155,7 @@ class ScoutMessage extends Message{
$josaYi = JosaUtil::pick($this->dest->generalName, '이');
(new ActionLogger($receiverID, 0, $year, $month))->pushGeneralActionLog("{$this->src->nationName}>{$josaRo} 망명을 거부했습니다.", ActionLogger::PLAIN);
(new ActionLogger($this->src->generalID, 0, $year, $month))->pushGeneralActionLog("{$this->dest->generalName}>{$josaYi} 등용을 거부했습니다.", ActionLogger::PLAIN);
- $this->_declineMessage();
+ $this->_declineMessage();
return self::DECLINED;
}
@@ -200,18 +200,18 @@ class ScoutMessage extends Message{
$destNationInfo = getNationStaticInfo($destGeneral['nation']);
$src = new MessageTarget(
- $srcGeneralID,
+ $srcGeneralID,
$srcGeneral['name'],
- $srcGeneral['nation'],
- $srcNationInfo['name'],
+ $srcGeneral['nation'],
+ $srcNationInfo['name'],
$srcNationInfo['color']
);
$dest = new MessageTarget(
- $destGeneralID,
+ $destGeneralID,
$destGeneral['name'],
$destGeneral['nation'],
- $destNationInfo['name'],
+ $destNationInfo['name'],
$destNationInfo['color']
);
diff --git a/hwe/sammo/SpecialityHelper.php b/hwe/sammo/SpecialityHelper.php
index eaa21cc0..94105626 100644
--- a/hwe/sammo/SpecialityHelper.php
+++ b/hwe/sammo/SpecialityHelper.php
@@ -122,7 +122,7 @@ class SpecialityHelper{
return $myCond;
}
- private static function calcCondDexterity(array $general) : int {
+ private static function calcCondDexterity(RandUtil $rng, array $general) : int {
$dex = [
static::ARMY_FOOTMAN => $general['dex1']??0,
static::ARMY_ARCHER => $general['dex2']??0,
@@ -134,19 +134,19 @@ class SpecialityHelper{
$dexSum = array_sum($dex);
$dexBase = Util::round(sqrt($dexSum) / 4);
- if(Util::randBool(0.8)){
+ if($rng->nextBool(0.8)){
return 0;
}
- if(mt_rand(0, 99) < $dexBase){
+ if($rng->nextRangeInt(0, 99) < $dexBase){
return 0;
}
if(!$dexSum){
- return array_rand($dex);
+ return $rng->choice($dex);
}
- return Util::choiceRandom(array_keys($dex, max($dex)));
+ return $rng->choice(array_keys($dex, max($dex)));
}
/** @return BaseSpecial[] */
@@ -195,7 +195,7 @@ class SpecialityHelper{
return $result;
}
- public static function pickSpecialDomestic(array $general, array $prevSpecials=[]) : string{
+ public static function pickSpecialDomestic(RandUtil $rng, array $general, array $prevSpecials=[]) : string{
$pAbs = [];
$pRel = [];
@@ -234,31 +234,31 @@ class SpecialityHelper{
if($pRel){
$pAbs[0] = max(0, 100 - array_sum($pAbs));
}
- $id = Util::choiceRandomUsingWeight($pAbs);
+ $id = $rng->choiceUsingWeight($pAbs);
if($id){
return $id;
}
}
- $id = Util::choiceRandomUsingWeight($pRel);
+ $id = $rng->choiceUsingWeight($pRel);
if($id){
return $id;
}
if($prevSpecials){
- return static::pickSpecialDomestic($general, []);
+ return static::pickSpecialDomestic($rng, $general, []);
}
throw new MustNotBeReachedException("{$general['name']}, {$myCond}");
}
- public static function pickSpecialWar(array $general, array $prevSpecials=[]) : string{
+ public static function pickSpecialWar(RandUtil $rng, array $general, array $prevSpecials=[]) : string{
$reqDex = [];
$pAbs = [];
$pRel = [];
$myCond = static::calcCondGeneric($general);
- $myCond |= static::calcCondDexterity($general);
+ $myCond |= static::calcCondDexterity($rng, $general);
$myCond |= static::REQ_DEXTERITY;
foreach(static::getSpecialWarList() as $specialID=>$specialObj){
@@ -294,26 +294,26 @@ class SpecialityHelper{
}
if($reqDex){
- return Util::choiceRandomUsingWeight($reqDex);
+ return $rng->choiceUsingWeight($reqDex);
}
if($pAbs){
if($pRel){
$pAbs[0] = max(0, 100 - array_sum($pAbs));
}
- $id = Util::choiceRandomUsingWeight($pAbs);
+ $id = $rng->choiceUsingWeight($pAbs);
if($id){
return $id;
}
}
- $id = Util::choiceRandomUsingWeight($pRel);
+ $id = $rng->choiceUsingWeight($pRel);
if($id){
return $id;
}
if($prevSpecials){
- return static::pickSpecialWar($general, []);
+ return static::pickSpecialWar($rng, $general, []);
}
throw new MustNotBeReachedException();
diff --git a/hwe/sammo/TriggerCaller.php b/hwe/sammo/TriggerCaller.php
index 08137577..0f3d36b3 100644
--- a/hwe/sammo/TriggerCaller.php
+++ b/hwe/sammo/TriggerCaller.php
@@ -47,7 +47,7 @@ abstract class TriggerCaller{
if(!$sorted){
ksort($this->triggerListByPriority);
}
-
+
}
function append(ObjectTrigger $trigger):self{
@@ -118,11 +118,11 @@ abstract class TriggerCaller{
return $this;
}
- function fire(array $env, $arg = null):?array{
+ function fire(RandUtil $rng, array $env, $arg = null):?array{
foreach($this->triggerListByPriority as $priority=>$subTriggerList){
/** @var ObjectTrigger[] $subTriggerList */
foreach($subTriggerList as $trigger){
- $env = $trigger->action($env, $arg);
+ $env = $trigger->action($rng, $env, $arg);
}
}
return $env;
diff --git a/hwe/sammo/TurnExecutionHelper.php b/hwe/sammo/TurnExecutionHelper.php
index 0c9cb2ec..112783a3 100644
--- a/hwe/sammo/TurnExecutionHelper.php
+++ b/hwe/sammo/TurnExecutionHelper.php
@@ -31,7 +31,7 @@ class TurnExecutionHelper
return $this->generalObj;
}
- public function preprocessCommand(array $env)
+ public function preprocessCommand(RandUtil $rng, array $env)
{
$general = $this->getGeneral();
$caller = $general->getPreTurnExecuteTriggerList($general);
@@ -40,7 +40,7 @@ class TurnExecutionHelper
new GeneralTrigger\che_병력군량소모($general)
));
- $caller->fire($env);
+ $caller->fire($rng, $env);
}
public function processBlocked(): bool
@@ -68,7 +68,7 @@ class TurnExecutionHelper
return true;
}
- public function processNationCommand(Command\NationCommand $commandObj): LastTurn
+ public function processNationCommand(RandUtil $rng, Command\NationCommand $commandObj): LastTurn
{
$general = $this->getGeneral();
@@ -89,7 +89,7 @@ class TurnExecutionHelper
break;
}
- $result = $commandObj->run();
+ $result = $commandObj->run($rng);
if ($result) {
$commandObj->setNextAvailable();
break;
@@ -107,7 +107,7 @@ class TurnExecutionHelper
return $commandObj->getResultTurn();
}
- public function processCommand(Command\GeneralCommand $commandObj, bool $autorunMode)
+ public function processCommand(RandUtil $rng, Command\GeneralCommand $commandObj, bool $autorunMode)
{
$general = $this->getGeneral();
@@ -133,7 +133,7 @@ class TurnExecutionHelper
break;
}
- $result = $commandObj->run();
+ $result = $commandObj->run($rng);
if ($result) {
$commandObj->setNextAvailable();
break;
@@ -263,7 +263,14 @@ class TurnExecutionHelper
$general->increaseInheritancePoint(InheritanceKey::lived_month, 1);
- $turnObj->preprocessCommand($env);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'preprocess',
+ $year,
+ $month,
+ $general->getID(),
+ )));
+ $turnObj->preprocessCommand($rng, $env);
if ($general->getNPCType() >= 2) {
$ai = new GeneralAI($turnObj->getGeneral());
@@ -286,7 +293,16 @@ class TurnExecutionHelper
$cityName = CityConst::byID($general->getCityID())->name;
LogText("NationTurn", "General, {$general->getName()}, {$general->getID()}, {$cityName}, {$general->getStaticNation()['name']}, {$nationCommandObj->getBrief()}, {$nationCommandObj->reason}, ");
}
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'nationCommand',
+ $year,
+ $month,
+ $general->getID(),
+ $nationCommandObj->getRawClassName()
+ )));
$resultNationTurn = $turnObj->processNationCommand(
+ $rng,
$nationCommandObj
);
$nationStor->setValue($lastNationTurnKey, $resultNationTurn->toRaw());
@@ -307,8 +323,15 @@ class TurnExecutionHelper
$cityName = CityConst::byID($general->getCityID())->name;
LogText("turn", "General, {$general->getName()}, {$general->getID()}, {$cityName}, {$general->getStaticNation()['name']}, {$generalCommandObj->getBrief()}, {$generalCommandObj->reason}, ");
}
-
- $turnObj->processCommand($generalCommandObj, $autorunMode);
+ $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'generalCommand',
+ $year,
+ $month,
+ $general->getID(),
+ $generalCommandObj->getRawClassName()
+ )));
+ $turnObj->processCommand($rng, $generalCommandObj, $autorunMode);
}
pullNationCommand($general->getVar('nation'), $general->getVar('officer_level'));
pullGeneralCommand($general->getID());
@@ -397,6 +420,12 @@ class TurnExecutionHelper
return $currentTurn !== null && $lastExecuted !== $currentTurn;
}
+ $monthlyRng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'monthly',
+ $gameStor->year,
+ $gameStor->month
+ )));
// 1달마다 처리하는 것들, 벌점 감소 및 건국,전턴,합병 -1, 군량 소모
if (!preUpdateMonthly()) {
@@ -416,25 +445,25 @@ class TurnExecutionHelper
processGoldIncome();
updateYearly();
updateQuaterly();
- disaster();
- tradeRate();
+ disaster($monthlyRng);
+ tradeRate($monthlyRng);
addAge();
// 새해 알림
$logger->pushGlobalActionLog("{$gameStor->year}>년이 되었습니다.");
$logger->flush(); //TODO: globalAction류는 전역에서 관리하는것이 좋을 듯.
} elseif ($gameStor->month == 4) {
updateQuaterly();
- disaster();
+ disaster($monthlyRng);
} elseif ($gameStor->month == 7) {
processSumInheritPointRank();
processFall();
processRiceIncome();
updateQuaterly();
- disaster();
- tradeRate();
+ disaster($monthlyRng);
+ tradeRate($monthlyRng);
} elseif ($gameStor->month == 10) {
updateQuaterly();
- disaster();
+ disaster($monthlyRng);
}
// 이벤트 핸들러 동작
@@ -456,7 +485,7 @@ class TurnExecutionHelper
$gameStor->resetCache();
}
- postUpdateMonthly();
+ postUpdateMonthly($monthlyRng);
// 다음달로 넘김
$prevTurn = $nextTurn;
diff --git a/hwe/sammo/WarUnit.php b/hwe/sammo/WarUnit.php
index 42fe682b..7ad3c665 100644
--- a/hwe/sammo/WarUnit.php
+++ b/hwe/sammo/WarUnit.php
@@ -4,6 +4,7 @@ namespace sammo;
class WarUnit
{
+ public readonly RandUtil $rng;
protected $general;
protected $rawNation;
@@ -33,8 +34,9 @@ class WarUnit
protected $logActivatedSkill = [];
protected $isFinished = false;
- private function __construct(General $general)
+ private function __construct(RandUtil $rng, General $general)
{
+ $this->rng = $rng;
$this->general = $general;
}
@@ -413,7 +415,7 @@ class WarUnit
function calcDamage(): int
{
$warPower = $this->getWarPower();
- $warPower *= Util::randRange(0.9, 1.1);
+ $warPower *= $this->rng->nextRange(0.9, 1.1);
return Util::round($warPower);
}
@@ -443,7 +445,7 @@ class WarUnit
$range = $general->onCalcStat($general, 'criticalDamageRange', $range);
}
//전특, 병종에 따라 필살 데미지가 달라질지도 모르므로 static 함수는 아닌 것으로
- return Util::randRange(...$range);
+ return $this->rng->nextRange(...$range);
}
function applyDB(\MeekroDB $db): bool
diff --git a/hwe/sammo/WarUnitCity.php b/hwe/sammo/WarUnitCity.php
index 6744ae80..994d9b4f 100644
--- a/hwe/sammo/WarUnitCity.php
+++ b/hwe/sammo/WarUnitCity.php
@@ -8,7 +8,8 @@ class WarUnitCity extends WarUnit{
protected $cityRate;
- function __construct($raw, $rawNation, int $year, int $month, $cityRate){
+ function __construct(RandUtil $rng, $raw, $rawNation, int $year, int $month, $cityRate){
+ $this->rng = $rng;
$general = new DummyGeneral(false);
$general->setVar('city', $raw['city']);
$general->setVar('nation', $raw['nation']);
@@ -23,7 +24,7 @@ class WarUnitCity extends WarUnit{
$this->logger = $general->getLogger();
$this->crewType = GameUnitConst::byID(GameUnitConst::CREWTYPE_CASTLE);
- $this->hp = $this->getCityVar('def') * 10;
+ $this->hp = $this->getCityVar('def') * 10;
//수비자 보정
if($this->getCityVar('level') == 1){
@@ -78,7 +79,7 @@ class WarUnitCity extends WarUnit{
$this->deadCurr += $damage;
$this->hp -= $damage;
$this->increaseVarWithLimit('wall', -$damage/20, 0);
-
+
return $this->hp;
}
@@ -123,7 +124,7 @@ class WarUnitCity extends WarUnit{
$nationID = $oppose->getNationVar('nation');
$newConflict = false;
-
+
$dead = max(1, $this->dead);
if(!$conflict || $this->getHP() == 0){ // 선타, 막타 보너스
@@ -147,7 +148,7 @@ class WarUnitCity extends WarUnit{
return $newConflict;
}
-
+
function applyDB(\MeekroDB $db):bool{
$updateVals = $this->getUpdatedValues();
@@ -156,7 +157,7 @@ class WarUnitCity extends WarUnit{
if(!$updateVals){
return false;
}
-
+
$db->update('city', $updateVals, 'city=%i', $this->raw['city']);
$this->flushUpdateValues();
return $db->affectedRows() > 0;
diff --git a/hwe/sammo/WarUnitGeneral.php b/hwe/sammo/WarUnitGeneral.php
index d2417728..43824ae0 100644
--- a/hwe/sammo/WarUnitGeneral.php
+++ b/hwe/sammo/WarUnitGeneral.php
@@ -10,8 +10,9 @@ class WarUnitGeneral extends WarUnit
protected $killedPerson = 0;
protected $deadPerson = 0;
- function __construct(General $general, array $rawNation, bool $isAttacker)
+ function __construct(RandUtil $rng, General $general, array $rawNation, bool $isAttacker)
{
+ $this->rng = $rng;
$this->general = $general;
$this->raw = $general->getRaw();
$this->rawNation = $rawNation; //read-only
@@ -302,13 +303,13 @@ class WarUnitGeneral extends WarUnit
if ($this->hasActivatedSkillOnLog('퇴각부상무효')) {
return false;
}
- if (!Util::randBool(0.05)) {
+ if (!$this->rng->nextBool(0.05)) {
return false;
}
$this->activateSkill('부상');
- $general->increaseVarWithLimit('injury', Util::randRangeInt(10, 80), null, 80);
+ $general->increaseVarWithLimit('injury', $this->rng->nextRangeInt(10, 80), null, 80);
$this->getLogger()->pushGeneralActionLog("전투중 부상>당했다!", ActionLogger::PLAIN);
return true;
diff --git a/hwe/sammo/WarUnitTrigger/che_격노시도.php b/hwe/sammo/WarUnitTrigger/che_격노시도.php
index 546bc516..6f48958f 100644
--- a/hwe/sammo/WarUnitTrigger/che_격노시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_격노시도.php
@@ -22,14 +22,14 @@ class che_격노시도 extends BaseWarUnitTrigger{
if($oppose->hasActivatedSkill('필살')){
$self->activateSkill('격노');
$oppose->deactivateSkill('회피');
- if($self->isAttacker() && Util::randBool(1/2)){
+ if($self->isAttacker() && $self->rng->nextBool(1/2)){
$self->activateSkill('진노');
}
}
- else if(Util::randBool(1/4)){
+ else if($self->rng->nextBool(1/4)){
$self->activateSkill('격노');
$oppose->deactivateSkill('회피');
- if($self->isAttacker() && Util::randBool(1/2)){
+ if($self->isAttacker() && $self->rng->nextBool(1/2)){
$self->activateSkill('진노');
}
}
diff --git a/hwe/sammo/WarUnitTrigger/che_계략시도.php b/hwe/sammo/WarUnitTrigger/che_계략시도.php
index a348804d..a6bfb93f 100644
--- a/hwe/sammo/WarUnitTrigger/che_계략시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_계략시도.php
@@ -48,7 +48,7 @@ class che_계략시도 extends BaseWarUnitTrigger{
$magicTrialProb *= 3;
}
- if(!Util::randBool($magicTrialProb)){
+ if(!$self->rng->nextBool($magicTrialProb)){
return true;
}
@@ -57,11 +57,11 @@ class che_계략시도 extends BaseWarUnitTrigger{
$magicSuccessProb = $oppose->getGeneral()->onCalcOpposeStat($general, 'warMagicSuccessProb', $magicSuccessProb);
if($oppose instanceof WarUnitCity){
- $magic = Util::choiceRandom(array_keys(static::$tableToCity));
+ $magic = $self->rng->choice(array_keys(static::$tableToCity));
[$successDamage, $failDamage] = static::$tableToCity[$magic];
}
else{
- $magic = Util::choiceRandom(array_keys(static::$tableToGeneral));
+ $magic = $self->rng->choice(array_keys(static::$tableToGeneral));
[$successDamage, $failDamage] = static::$tableToGeneral[$magic];
}
@@ -70,7 +70,7 @@ class che_계략시도 extends BaseWarUnitTrigger{
$self->activateSkill('계략시도', $magic);
- if(Util::randBool($magicSuccessProb)){
+ if($self->rng->nextBool($magicSuccessProb)){
$self->activateSkill('계략');
$selfEnv['magic'] = [$magic, $successDamage];
}
diff --git a/hwe/sammo/WarUnitTrigger/che_반계시도.php b/hwe/sammo/WarUnitTrigger/che_반계시도.php
index 8ed41609..f70daedd 100644
--- a/hwe/sammo/WarUnitTrigger/che_반계시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_반계시도.php
@@ -26,7 +26,7 @@ class che_반계시도 extends BaseWarUnitTrigger{
return true;
}
- if(!Util::randBool($this->prob)){
+ if(!$self->rng->nextBool($this->prob)){
return true;
}
diff --git a/hwe/sammo/WarUnitTrigger/che_약탈시도.php b/hwe/sammo/WarUnitTrigger/che_약탈시도.php
index e22c6477..dc5a7705 100644
--- a/hwe/sammo/WarUnitTrigger/che_약탈시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_약탈시도.php
@@ -35,7 +35,7 @@ class che_약탈시도 extends BaseWarUnitTrigger{
if($self->hasActivatedSkill('약탈불가')){
return true;
}
- if(!Util::randBool($this->ratio)){
+ if(!$self->rng->nextBool($this->ratio)){
return true;
}
diff --git a/hwe/sammo/WarUnitTrigger/che_저격발동.php b/hwe/sammo/WarUnitTrigger/che_저격발동.php
index f6b801e9..609abbb4 100644
--- a/hwe/sammo/WarUnitTrigger/che_저격발동.php
+++ b/hwe/sammo/WarUnitTrigger/che_저격발동.php
@@ -43,7 +43,7 @@ class che_저격발동 extends BaseWarUnitTrigger
$general->increaseVarWithLimit('atmos', $selfEnv['addAtmos'], 0, GameConst::$maxAtmosByWar);
if (!$oppose->hasActivatedSkill('부상무효') && $oppose instanceof WarUnitGeneral) {
- $oppose->getGeneral()->increaseVarWithLimit('injury', Util::randRangeInt($selfEnv['woundMin'], $selfEnv['woundMax']), null, 80);
+ $oppose->getGeneral()->increaseVarWithLimit('injury', $self->rng->nextRangeInt($selfEnv['woundMin'], $selfEnv['woundMax']), null, 80);
}
$this->processConsumableItem();
diff --git a/hwe/sammo/WarUnitTrigger/che_저격시도.php b/hwe/sammo/WarUnitTrigger/che_저격시도.php
index 332e49b7..d5cd9eb8 100644
--- a/hwe/sammo/WarUnitTrigger/che_저격시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_저격시도.php
@@ -36,7 +36,7 @@ class che_저격시도 extends BaseWarUnitTrigger{
if($self->hasActivatedSkill('저격불가')){
return true;
}
- if(!Util::randBool($this->ratio)){
+ if(!$self->rng->nextBool($this->ratio)){
return true;
}
diff --git a/hwe/sammo/WarUnitTrigger/che_저지시도.php b/hwe/sammo/WarUnitTrigger/che_저지시도.php
index 2196b87e..ac1fbd2b 100644
--- a/hwe/sammo/WarUnitTrigger/che_저지시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_저지시도.php
@@ -22,12 +22,12 @@ class che_저지시도 extends BaseWarUnitTrigger{
if($self->hasActivatedSkill('저지불가')){
return true;
}
-
+
$ratio = $self->getComputedAtmos() + $self->getComputedTrain();
- if(Util::randBool($ratio / 400)){
+ if($self->rng->nextBool($ratio / 400)){
$self->activateSkill('특수', '저지');
}
-
+
return true;
}
}
\ No newline at end of file
diff --git a/hwe/sammo/WarUnitTrigger/che_전투치료시도.php b/hwe/sammo/WarUnitTrigger/che_전투치료시도.php
index 199b533e..fb255b0a 100644
--- a/hwe/sammo/WarUnitTrigger/che_전투치료시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_전투치료시도.php
@@ -19,13 +19,13 @@ class che_전투치료시도 extends BaseWarUnitTrigger{
if($self->hasActivatedSkill('치료불가')){
return true;
}
- if(!Util::randBool(0.4)){
+ if(!$self->rng->nextBool(0.4)){
return true;
}
$self->activateSkill('치료');
-
+
return true;
}
}
\ No newline at end of file
diff --git a/hwe/sammo/WarUnitTrigger/che_필살시도.php b/hwe/sammo/WarUnitTrigger/che_필살시도.php
index 01b1801e..ab84a410 100644
--- a/hwe/sammo/WarUnitTrigger/che_필살시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_필살시도.php
@@ -22,13 +22,13 @@ class che_필살시도 extends BaseWarUnitTrigger{
return true;
}
- if(!Util::randBool($self->getComputedCriticalRatio())){
+ if(!$self->rng->nextBool($self->getComputedCriticalRatio())){
return true;
}
$self->activateSkill('필살시도', '필살');
-
+
return true;
}
}
\ No newline at end of file
diff --git a/hwe/sammo/WarUnitTrigger/che_회피시도.php b/hwe/sammo/WarUnitTrigger/che_회피시도.php
index 8ce506ac..70476884 100644
--- a/hwe/sammo/WarUnitTrigger/che_회피시도.php
+++ b/hwe/sammo/WarUnitTrigger/che_회피시도.php
@@ -22,13 +22,13 @@ class che_회피시도 extends BaseWarUnitTrigger{
return true;
}
- if(!Util::randBool($self->getComputedAvoidRatio())){
+ if(!$self->rng->nextBool($self->getComputedAvoidRatio())){
return true;
}
$self->activateSkill('회피시도', '회피');
-
+
return true;
}
}
\ No newline at end of file
diff --git a/hwe/sammo/iAction.php b/hwe/sammo/iAction.php
index 54b5588e..4e37c835 100644
--- a/hwe/sammo/iAction.php
+++ b/hwe/sammo/iAction.php
@@ -19,5 +19,5 @@ interface iAction{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller;
//NOTE: getBattleEndSkillTriggerList도 필요한가?
- public function onArbitraryAction(General $general, string $actionType, ?string $phase=null, ?array $aux=null): null|array;
+ public function onArbitraryAction(General $general, RandUtil $rng, string $actionType, ?string $phase=null, ?array $aux=null): null|array;
}
\ No newline at end of file
diff --git a/src/sammo/NoRNG.php b/src/sammo/NoRNG.php
new file mode 100644
index 00000000..122fef26
--- /dev/null
+++ b/src/sammo/NoRNG.php
@@ -0,0 +1,50 @@
+ $items 각 수치와 비중. [값, weight] 으로 보관
* @return array|object 선택된 랜덤 값의 첫번째 값
+ * @deprecated
*/
public static function choiceRandomUsingWeightPair(array $items)
{
@@ -629,6 +635,7 @@ class Util extends \utilphp\util
* @param array $items 선택하고자 하는 배열
*
* @return int|float|string|array|object 선택된 value값.
+ * @deprecated
*/
public static function choiceRandom(array $items)
{