feat,refac: 게임 로직 내 '랜덤'을 RandUtil을 활용하여 재설정

- 기존의 랜덤 코드는 deprecated 처리
- 서버 시작 시 랜덤하게 정해진 hiddenSeed를 활용
- 랜덤 생성 단위
  - 월 실행
  - 사령턴 실행 결과
  - 커맨드 실행 결과
  - 작위 보상
  - 부대장 생성
  - 유니크 획득 시도
  - 설문 조사
  - 장수 생성
  - NPC국 생성, NPC 생성, NPC의 토너먼트 베팅
  - 전투
  - 도시 점령
  - 자율 행동 선택
  - 랜덤 턴 변경
- 거래장, 토너먼트 등 구 랜덤 코드를 이용하는 잔여 코드 있음
This commit is contained in:
2022-05-17 03:46:59 +09:00
parent 3c078e7f4a
commit 9fbe270bba
136 changed files with 1000 additions and 784 deletions
-8
View File
@@ -109,10 +109,6 @@ $db = DB::db();
<td align=center>강제 사망</td>
<td><input type=submit name=btn value='강제 사망'></td>
</tr>
<tr>
<td align=center>이벤트</td>
<td><input type=submit name=btn value='특기 부여'><input type=submit name=btn value='공헌치1000'><input type=submit name=btn value='경험치1000'></td>
</tr>
<tr>
<td align=center>이벤트2</td>
<td><input type=submit name=btn value='보숙10000'><input type=submit name=btn value='궁숙10000'><input type=submit name=btn value='기숙10000'><input type=submit name=btn value='귀숙10000'><input type=submit name=btn value='차숙10000'></td>
@@ -121,10 +117,6 @@ $db = DB::db();
<td align=center>접속제한</td>
<td><input type=submit name=btn value='접속 허용'><input type=submit name=btn value='접속 제한'></td>
</tr>
<tr>
<td align=center>턴 시각 설정</td>
<td><input type=submit name=btn value='00턴'><input type=submit name=btn value='랜덤턴'></td>
</tr>
<tr>
<td align=center>명령 설정</td>
<td><input type=submit name=btn value='하야입력'><input type=submit name=btn value='방랑해산'></td>
-42
View File
@@ -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("특기 【<b><C>{$specialWarName}</></b>】{$josaUl} 습득");
$logger->pushGeneralActionLog("특기 【<b><L>{$specialWarName}</></b>】{$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');
+27 -27
View File
@@ -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');
}
+2 -2
View File
@@ -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{
+76 -22
View File
@@ -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[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6:
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
break;
case 5:
case 4:
case 3:
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
break;
case 2:
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>로 나서다"]);
$history[] = "<C>●</>{$year}{$month}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$year}{$month}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . 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 = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
$hiddenSeed = UniqueConst::$hiddenSeed;
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다. <span class='hidden_but_copyable'>(서버시드: $hiddenSeed})</span>"];
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);
}
+6 -7
View File
@@ -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;
}
+10 -9
View File
@@ -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;
}
+8 -8
View File
@@ -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{
+7 -1
View File
@@ -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];
}
+8 -1
View File
@@ -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];
}
+5 -1
View File
@@ -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);
+6 -4
View File
@@ -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),
+1 -1
View File
@@ -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([
+9 -3
View File
@@ -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 = [];
+25 -12
View File
@@ -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("<D><b>{$attacker->getNationVar('name')}</b></>의 <Y>{$attacker->getName()}</>{$josaYi} <G><b>{$city->getName()}</b></>{$josaRo} 진격합니다.");
$logger->pushGeneralActionLog("<G><b>{$city->getName()}</b></>{$josaRo} <M>진격</>합니다. <1>$date</>");
$logger->pushGlobalActionLog("<D><b>{$attacker->getNationVar('name')}</b></>의 <Y>{$attacker->getName()}</>{$josaYi} <G><b>{$city->getName()}</b></>{$josaRo} 진격합니다.<span class='hidden_but_copyable'>(전투시드: {$warSeed})</span>");
$logger->pushGeneralActionLog("<G><b>{$city->getName()}</b></>{$josaRo} <M>진격</>합니다.<span class='hidden_but_copyable'>(전투시드: {$warSeed})</span> <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)));
}
+24 -11
View File
@@ -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;
+11 -1
View File
@@ -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){
+11 -1
View File
@@ -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);
+3 -3
View File
@@ -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);
+10 -9
View File
@@ -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);
+3 -2
View File
@@ -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']
]);
@@ -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;
}
+2 -1
View File
@@ -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;
+2 -2
View File
@@ -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();
+3 -2
View File
@@ -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 [];
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -111,7 +111,7 @@ class che_강행 extends Command\GeneralCommand
return "{$failReason} <G><b>{$destCityName}</b></>{$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);
+2 -2
View File
@@ -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);
+3 -2
View File
@@ -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;
+4 -4
View File
@@ -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);
@@ -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);
+2 -2
View File
@@ -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);
+13 -13
View File
@@ -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;
}
}
+9 -9
View File
@@ -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;
}
}
+2 -2
View File
@@ -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);
@@ -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('불가능한 커맨드를 강제로 실행 시도');
}
@@ -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("<D>{$destNationName}</>에 랜덤 임관했습니다. <1>$date</>");
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>에 랜덤 임관");
@@ -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;
@@ -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);
@@ -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);
+2 -2
View File
@@ -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;
@@ -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;
}
}
+19 -18
View File
@@ -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;
+7 -6
View File
@@ -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
);
}
}
+2 -2
View File
@@ -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);
@@ -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;
@@ -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;
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -119,7 +119,7 @@ class che_이동 extends Command\GeneralCommand
return "{$failReason} <G><b>{$destCityName}</b></>{$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);
@@ -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("<Y>{$generalName}</>{$josaYi} <Y>$npcName</>{$josaRa}는 <C>인재</>를 {$scoutType}하였습니다!");
$logger->pushGeneralHistoryLog("<Y>$npcName</>{$josaRa}는 <C>인재</>를 {$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;
}
+2 -2
View File
@@ -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;
@@ -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("<C>{$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("<C>{$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;
@@ -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;
@@ -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;
}
}
@@ -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;
}
}
+18 -17
View File
@@ -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;
+19 -18
View File
@@ -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;
}
}
+2 -2
View File
@@ -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);
+7 -7
View File
@@ -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;
}
}
+2 -2
View File
@@ -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;
+4 -4
View File
@@ -120,7 +120,7 @@ class che_첩보 extends Command\GeneralCommand
return "{$failReason} <G><b>{$destCityName}</b></>에 {$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;
+19 -4
View File
@@ -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} <G><b>{$destCityName}</b></>{$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;
+5 -4
View File
@@ -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);
+7 -6
View File
@@ -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
);
}
}
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -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);
// 이벤트 핸들러 동작
+2 -2
View File
@@ -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;
+14 -13
View File
@@ -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} <G><b>{$destCityName}</b></>에 {$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("<G><b>{$destCityName}</b></>에 {$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;
+8 -8
View File
@@ -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;
}
}
+2 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
}
@@ -91,7 +91,7 @@ class che_국기변경 extends Command\NationCommand
return "【<span style='color:{$color};'>국기</span>】를 변경";
}
public function run(): bool
public function run(\Sammo\RandUtil $rng): bool
{
if (!$this->hasFullConditionMet()) {
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
+3 -3
View File
@@ -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(),
@@ -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('불가능한 커맨드를 강제로 실행 시도');
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
}
@@ -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('불가능한 커맨드를 강제로 실행 시도');
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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();
}
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
}
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
}
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
}
+1 -1
View File
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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('불가능한 커맨드를 강제로 실행 시도');
@@ -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);
}
+3 -3
View File
@@ -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);
+2 -2
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
}
+3 -3
View File
@@ -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, ''];
+33 -19
View File
@@ -1,37 +1,51 @@
<?php
namespace sammo\Event\Action;
use \sammo\GameConst;
use \sammo\Util;
use \sammo\DB;
use sammo\LiteHashDRBG;
use sammo\RandUtil;
use sammo\UniqueConst;
use function sammo\pickGeneralFromPool;
//기존 event_3.php
class CreateManyNPC extends \sammo\Event\Action{
class CreateManyNPC extends \sammo\Event\Action
{
protected $npcCount;
protected $fillCnt;
protected $avgGen;
public function __construct($npcCount = 10, $fillCnt = 0){
public function __construct($npcCount = 10, $fillCnt = 0)
{
$this->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("<Y>$npcName</>{$josaRa}는 장수가 <S>등장</>하였습니다.");
}
else{
} else {
$logger->pushGlobalActionLog("장수 <C>{$genCnt}</>명이 <S>등장</>하였습니다.");
}
$logger->pushGlobalHistoryLog("장수 <C>{$genCnt}</>명이 <S>등장</>했습니다.", \sammo\ActionLogger::NOTICE_YEAR_MONTH);
@@ -76,4 +90,4 @@ class CreateManyNPC extends \sammo\Event\Action{
return [__CLASS__, $result];
}
}
}
+16 -6
View File
@@ -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);

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