NPC 행동 코드 재 구현중
This commit is contained in:
@@ -221,7 +221,7 @@ function SetNationFront($nationNo) {
|
|||||||
} else {
|
} else {
|
||||||
//평시이면 공백지
|
//평시이면 공백지
|
||||||
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
|
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
|
||||||
foreach ($db->queryFirstColumn('SELECT city,path from city where nation=0') as $city) {
|
foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) {
|
||||||
foreach(CityConst::byID($city)->path as $adjKey=>$adjVal){
|
foreach(CityConst::byID($city)->path as $adjKey=>$adjVal){
|
||||||
$adj[$adjKey] = $adjVal;
|
$adj[$adjKey] = $adjVal;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-28
@@ -283,32 +283,7 @@ function processAI(General $generalObj, $command, $arg):array{
|
|||||||
// 교전중이면 4상태
|
// 교전중이면 4상태
|
||||||
if($dipCount > 0) { $dipState = 4; }
|
if($dipCount > 0) { $dipState = 4; }
|
||||||
|
|
||||||
//무장
|
|
||||||
if($general['power'] >= $general['intel']) {
|
|
||||||
$genType = 0;
|
|
||||||
if($general['intel'] >= $general['power'] * 0.8) { //무지장
|
|
||||||
switch(rand() % 5) {
|
|
||||||
case 0: case 1: case 2: case 3: $genType = 0; break;
|
|
||||||
case 4: $genType = 1; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//지장
|
|
||||||
} else {
|
|
||||||
$genType = 1;
|
|
||||||
if($general['power'] >= $general['intel'] * 0.8) { //지무장
|
|
||||||
switch(rand() % 5) {
|
|
||||||
case 0: $genType = 0; break;
|
|
||||||
case 1: case 2: case 3: case 4: $genType = 1; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//내정장
|
|
||||||
if($general['leader'] < 40) {
|
|
||||||
$genType += 2;
|
|
||||||
//$genType = 2; // 무내정장
|
|
||||||
//$genType = 3; // 지내정장
|
|
||||||
}
|
|
||||||
|
|
||||||
$tech = getTechCost($nation['tech']);
|
$tech = getTechCost($nation['tech']);
|
||||||
$resrc = $tech * 700;//XXX: 왜 700이지?
|
$resrc = $tech * 700;//XXX: 왜 700이지?
|
||||||
@@ -362,7 +337,8 @@ function processAI(General $generalObj, $command, $arg):array{
|
|||||||
}
|
}
|
||||||
$query = "update general set turn0='$command' where no='{$generalID}'";
|
$query = "update general set turn0='$command' where no='{$generalID}'";
|
||||||
MYDB_query($query, $connect) or Error("processAI07 ".MYDB_error($connect),"");
|
MYDB_query($query, $connect) or Error("processAI07 ".MYDB_error($connect),"");
|
||||||
return;
|
return [];
|
||||||
|
|
||||||
} elseif($general['npc'] != 9 && $general['level'] == 0) {
|
} elseif($general['npc'] != 9 && $general['level'] == 0) {
|
||||||
switch(Util::choiceRandomUsingWeight([11.4, 40, 20, 28.6])) {
|
switch(Util::choiceRandomUsingWeight([11.4, 40, 20, 28.6])) {
|
||||||
//임관 10%
|
//임관 10%
|
||||||
@@ -413,9 +389,11 @@ function processAI(General $generalObj, $command, $arg):array{
|
|||||||
}
|
}
|
||||||
$query = "update general set turn0='$command' where no='{$generalID}'";
|
$query = "update general set turn0='$command' where no='{$generalID}'";
|
||||||
MYDB_query($query, $connect) or Error("processAI07 ".MYDB_error($connect),"");
|
MYDB_query($query, $connect) or Error("processAI07 ".MYDB_error($connect),"");
|
||||||
return;
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO:여기부터 다시 구현
|
||||||
|
|
||||||
$rulerCommand = 0;
|
$rulerCommand = 0;
|
||||||
//군주가 할일
|
//군주가 할일
|
||||||
if($general['level'] == 12) {
|
if($general['level'] == 12) {
|
||||||
|
|||||||
@@ -325,18 +325,26 @@ class GameUnitConstBase{
|
|||||||
return static::$constName[$name]??null;
|
return static::$constName[$name]??null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \sammo\GameUnitDetail[]
|
||||||
|
*/
|
||||||
public static function byCity(int $city): array{
|
public static function byCity(int $city): array{
|
||||||
static::_generate();
|
static::_generate();
|
||||||
return static::$constCity[$city]??[];
|
return static::$constCity[$city]??[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \sammo\GameUnitDetail[]
|
||||||
|
*/
|
||||||
public static function byRegion(int $region): array{
|
public static function byRegion(int $region): array{
|
||||||
static::_generate();
|
static::_generate();
|
||||||
return static::$constRegion[$region]??[];
|
return static::$constRegion[$region]??[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \sammo\GameUnitDetail[]
|
||||||
|
*/
|
||||||
public static function byType(int $type): array{
|
public static function byType(int $type): array{
|
||||||
static::_generate();
|
static::_generate();
|
||||||
if(!key_exists($type, static::$constType)){
|
if(!key_exists($type, static::$constType)){
|
||||||
|
|||||||
@@ -159,6 +159,14 @@ class GameUnitDetail{
|
|||||||
return min(50, $ratio) / 100;
|
return min(50, $ratio) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function pickScore($tech){
|
||||||
|
$defaultWar = GameConst::$armperphase + $this->attack + $this->defence + getTechAbil($tech) * 2;
|
||||||
|
$defaultWar *= 1 + $this->speed / 2;
|
||||||
|
$defaultWar /= Util::valueFit(1 - $this->avoid / 100, 0.1);
|
||||||
|
$defaultWar *= 1 + $this->magicCoef / 2;
|
||||||
|
return sqrt($defaultWar);
|
||||||
|
}
|
||||||
|
|
||||||
public function isValid($ownCities, $ownRegions, $relativeYear, $tech){
|
public function isValid($ownCities, $ownRegions, $relativeYear, $tech){
|
||||||
//음수 없음
|
//음수 없음
|
||||||
$relativeYear = max(0, $relativeYear);
|
$relativeYear = max(0, $relativeYear);
|
||||||
|
|||||||
+481
-9
@@ -2,26 +2,498 @@
|
|||||||
namespace sammo;
|
namespace sammo;
|
||||||
|
|
||||||
class GeneralAI{
|
class GeneralAI{
|
||||||
|
/**
|
||||||
|
* @var General $general
|
||||||
|
*/
|
||||||
protected $general;
|
protected $general;
|
||||||
|
protected $city;
|
||||||
protected $nation;
|
protected $nation;
|
||||||
protected $dipState;
|
protected $dipState;
|
||||||
protected $genType;
|
protected $genType;
|
||||||
protected $env;
|
protected $env;
|
||||||
|
|
||||||
|
protected $leadership;
|
||||||
|
protected $power;
|
||||||
|
protected $intel;
|
||||||
|
|
||||||
|
protected $attackable;
|
||||||
|
|
||||||
|
const t무장 = 1;
|
||||||
|
const t지장 = 2;
|
||||||
|
const t통솔장 = 4;
|
||||||
|
|
||||||
|
const d평화 = 0;
|
||||||
|
const d선포 = 1;
|
||||||
|
const d징병 = 2;
|
||||||
|
const d직전 = 3;
|
||||||
|
const d전쟁 = 4;
|
||||||
|
|
||||||
public function __construct(General $general){
|
public function __construct(General $general){
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
|
$this->env = $gameStor->getValues(['startyear','year','month','turnterm','scenario','gold_rate','rice_rate']);
|
||||||
$this->general = $general;
|
$this->general = $general;
|
||||||
if($general->getRawCity() === null){
|
if($general->getRawCity() === null){
|
||||||
$general->setRawCity($db->queryFirstRow('SELECT * FROM city WHERE city = %i', $general->getCityID()));
|
$city = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $general->getCityID());
|
||||||
|
$general->setRawCity($city);
|
||||||
|
}
|
||||||
|
$this->city = $general->getRawCity();
|
||||||
|
$this->nation = $db->queryFirstRow(
|
||||||
|
'SELECT nation,level,tech,gold,rice,rate,type,color,name,war FROM nation WHERE nation = %i',
|
||||||
|
$generalObj->getNationID()
|
||||||
|
)??[
|
||||||
|
'nation'=>0,
|
||||||
|
'level'=>0,
|
||||||
|
'tech'=>0,
|
||||||
|
'gold'=>0,
|
||||||
|
'rice'=>0,
|
||||||
|
'type'=>GameConst::$neutralNationType,
|
||||||
|
'color'=>'#000000',
|
||||||
|
'name'=>'재야',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->calcGenType();
|
||||||
|
|
||||||
|
$this->leadership = $general->getLeadership(true, true, true, true);
|
||||||
|
$this->power = $general->getPower(true, true, true, true);
|
||||||
|
$this->intel = $general->getIntel(true, true, true, true);
|
||||||
|
|
||||||
|
$this->calcDiplomacyState();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGeneralObj():General{
|
||||||
|
return $this->general;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function calcGenType(){
|
||||||
|
$leadership = $this->leadership;
|
||||||
|
$power = $this->power;
|
||||||
|
$intel = $this->intel;
|
||||||
|
|
||||||
|
//무장
|
||||||
|
if ($power >= $intel) {
|
||||||
|
$genType = self::t무장;
|
||||||
|
if ($intel >= $power * 0.8) { //무지장
|
||||||
|
if(Util::randBool($intel / $power / 2)){
|
||||||
|
$genType |= self::t지장;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//지장
|
||||||
|
} else {
|
||||||
|
$genType = self::t지장;
|
||||||
|
if ($power >= $intel * 0.8 && Util::randBol(0.2)) { //지무장
|
||||||
|
if(Util::randBool($power / $intel / 2)){
|
||||||
|
$genType |= self::t무장;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//통솔
|
||||||
|
if ($leadership >= 40) {
|
||||||
|
$genType |= self::t통솔장;
|
||||||
|
}
|
||||||
|
$this->genType = $genType;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function calcDiplomacyState(){
|
||||||
|
$db = DB::db();
|
||||||
|
$nationID = $this->general->getNationID();
|
||||||
|
|
||||||
|
$cityCount = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i AND supply=1 AND front>0', $nationID);
|
||||||
|
// 공격가능도시 있으면
|
||||||
|
$this->attackable = $cityCount > 0;
|
||||||
|
|
||||||
|
|
||||||
|
$minWarTerm = $db->queryFirstField('SELECT min(term) FROM diplomacy WHERE me = %i AND state=1', $nationID);
|
||||||
|
if($minWarTerm === null){
|
||||||
|
$this->dipState = self::d평화;
|
||||||
|
}
|
||||||
|
else if($minWarTerm > 8){
|
||||||
|
$this->dipState = self::d선포;
|
||||||
|
}
|
||||||
|
else if($minWarTerm > 5){
|
||||||
|
$this->dipState = self::d징병;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$this->dipState = self::d직전;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->attackable){
|
||||||
|
//전쟁으로 인한 attackable인가?
|
||||||
|
$onWar = $db->queryFirstField('SELECT you FROM diplomacy WHERE me = %i AND state=0 LIMIT 1', $nationID) !== null;
|
||||||
|
if($onWar){
|
||||||
|
$this->dipState = self::d전쟁;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function chooseDevelopTurn():?array{
|
||||||
|
$general = $this->general;
|
||||||
|
$city = $this->city;
|
||||||
|
$nation = $this->nation;
|
||||||
|
$env = $this->env;
|
||||||
|
|
||||||
|
$genType = $this->genType;
|
||||||
|
$leadership = $this->leadership;
|
||||||
|
$power = $this->power;
|
||||||
|
$intel = $this->intel;
|
||||||
|
|
||||||
|
$develRate = [
|
||||||
|
'trust'=>$city['trust'],
|
||||||
|
'pop'=>$city['pop']/$city['pop2'],
|
||||||
|
'agri'=>$city['agri']/$city['agri2'],
|
||||||
|
'comm'=>$city['comm']/$city['comm2'],
|
||||||
|
'secu'=>$city['secu']/$city['secu2'],
|
||||||
|
'def'=>$city['def']/$city['def2'],
|
||||||
|
'wall'=>$city['wall']/$city['wall2'],
|
||||||
|
];
|
||||||
|
|
||||||
|
// 우선 선정
|
||||||
|
if($develRate['trust'] < 95 && Util::randBool($leadership / 40)){
|
||||||
|
return ['che_선정', null];
|
||||||
|
}
|
||||||
|
|
||||||
|
$commandList = [];
|
||||||
|
|
||||||
|
if($genType & self::t무장){
|
||||||
|
if($develRate['secu'] < 0.99){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_치안강화', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $power / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($develRate['def'] < 0.99){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_수비강화', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $power / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($develRate['wall'] < 0.99){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_성벽보수', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $power / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($genType & self::t지장){
|
||||||
|
if($develRate['agri'] < 0.99){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_농지개간', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $intel / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($develRate['comm'] < 0.99){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_상업투자', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $intel / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!TechLimit($env['startyear'], $env['year'], $nation['tech'])){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_기술연구', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $intel / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($genType & self::t통솔장){
|
||||||
|
if($develRate['trust'] < 1){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_주민선정', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $leadership / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($develRate['pop'] < 0.99){
|
||||||
|
$commandObj = buildGeneralCommandClass('che_정착장려', $general, $env);
|
||||||
|
if($commandObj->isRunnable()){
|
||||||
|
$commandList[$commandName] = $leadership / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$genCount = $db->queryFirstField('SELECT count(no) FROM general');
|
||||||
|
$commandList['che_인재탐색'] = 500 / $genCount * 10;
|
||||||
|
|
||||||
|
$commandList['che_물자조달'] = (
|
||||||
|
(GameConst::$minNationalGold + GameConst::$minNationalRice + 10000) /
|
||||||
|
Util::valueFit($nation['gold'] + $nation['rice'], 1000)
|
||||||
|
) * 10;
|
||||||
|
|
||||||
|
//NOTE:내정 풀을 인식하는게 더 좋지 않을까?
|
||||||
|
|
||||||
|
return [Util::choiceRandomUsingWeight($commandList), null];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function chooseRecruitCrewType():array{
|
||||||
|
$general = $this->getGeneralObj();
|
||||||
|
$city = $this->city;
|
||||||
|
$nation = $this->nation;
|
||||||
|
$env = $this->env;
|
||||||
|
|
||||||
|
$genType = $this->genType;
|
||||||
|
$leadership = $this->leadership;
|
||||||
|
$power = $this->power;
|
||||||
|
$intel = $this->intel;
|
||||||
|
|
||||||
|
$tech = $nation['tech'];
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
|
$raw = $general->getRaw();
|
||||||
|
|
||||||
|
$dex = [
|
||||||
|
GameUnitConst::T_FOOTMAN=>sqrt($general->getVar('dex0') + 500),
|
||||||
|
GameUnitConst::T_ARCHER=>sqrt($general->getVar('dex10') + 500),
|
||||||
|
GameUnitConst::T_CAVALRY=>sqrt($general->getVar('dex20') + 500),
|
||||||
|
GameUnitConst::T_WIZARD=>sqrt($general->getVar('dex30') + 500),
|
||||||
|
GameUnitConst::T_SIEGE=>sqrt($general->getVar('dex40') + 500),
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
$cities = [];
|
||||||
|
$regions = [];
|
||||||
|
|
||||||
|
foreach($db->queryAllLists('SELECT city, region FROM city WHERE nation = %i', $nationID) as [$cityID, $regionID]){
|
||||||
|
$cities[$cityID] = true;
|
||||||
|
$regions[$regionID] = true;
|
||||||
|
}
|
||||||
|
$relYear = Util::valueFit($env['year'] - $env['startyear'], 0);
|
||||||
|
|
||||||
|
|
||||||
|
$typesAll = [];
|
||||||
|
if($genType & self::t무장){
|
||||||
|
$types = [];
|
||||||
|
foreach(GameUnitConst::byType(GameUnitConst::T_FOOTMAN) as $crewtype){
|
||||||
|
if($crewtype->isValid($cities, $regions, $relYear, $tech)){
|
||||||
|
$score = $dex[GameConst::T_FOOTMAN] * $crewtype->pickScore($tech);
|
||||||
|
$types[] = [$crewtype->id, $score];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach(GameUnitConst::byType(GameUnitConst::T_ARCHER) as $crewtype){
|
||||||
|
if($crewtype->isValid($cities, $regions, $relYear, $tech)){
|
||||||
|
$score = $dex[GameConst::T_ARCHER] * $crewtype->pickScore($tech);
|
||||||
|
$types[] = [$crewtype->id, $score];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach(GameUnitConst::byType(GameUnitConst::T_CAVALRY) as $crewtype){
|
||||||
|
if($crewtype->isValid($cities, $regions, $relYear, $tech)){
|
||||||
|
$score = $dex[GameConst::T_CAVALRY] * $crewtype->pickScore($tech);
|
||||||
|
$types[] = [$crewtype->id, $dex[GameConst::T_CAVALRY] + 500];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach($types as [$crewtype, $score]){
|
||||||
|
$typesAll[] = [$crewtype, $score / count($types)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($genType & self::t지장){
|
||||||
|
$types = [];
|
||||||
|
foreach(GameUnitConst::byType(GameUnitConst::T_WIZARD) as $crewtype){
|
||||||
|
if($crewtype->isValid($cities, $regions, $relYear, $tech)){
|
||||||
|
$score = $dex[GameConst::T_WIZARD] * $crewtype->pickScore($tech);
|
||||||
|
$types[] = [$crewtype->id, $score];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach($types as [$crewtype, $score]){
|
||||||
|
$typesAll[] = [$crewtype, $score / count($types)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($typesAll){
|
||||||
|
$type = Util::choiceRandomUsingWeightPair($types);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$type = GameUnitConst::DEFAULT_CREWTYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$obj훈련 = buildGeneralCommandClass('che_훈련', $general, $env);
|
||||||
|
$obj사기진작 = buildGeneralCommandClass('che_사기진작', $general, $env);
|
||||||
|
|
||||||
|
$gold -= $obj훈련->getCost()[0] * 2;
|
||||||
|
$gold -= $obj사기진작->getCost()[0] * 2;
|
||||||
|
|
||||||
|
$cost = getCost($type) * getTechCost($tech);
|
||||||
|
$cost = $general->onCalcDomestic('징병', 'cost', $cost);
|
||||||
|
|
||||||
|
$crew = intdiv($gold, $cost);
|
||||||
|
if($leader < $crew) { $crew = $leader; }
|
||||||
|
$arg = [
|
||||||
|
'crewType'=>$type,
|
||||||
|
'amountCrew'=>$crew
|
||||||
|
];
|
||||||
|
return ['che_징병', $arg];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function chooseNationTurn($command, $arg):array{
|
||||||
|
$general = $this->getGeneralObj();
|
||||||
|
$city = $this->city;
|
||||||
|
$nation = $this->nation;
|
||||||
|
$env = $this->env;
|
||||||
|
|
||||||
|
$cityID = $general->getCityID();
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$genType = $this->genType;
|
||||||
|
$leadership = $this->leadership;
|
||||||
|
$power = $this->power;
|
||||||
|
$intel = $this->intel;
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
|
if($general->getVar('npc') == 5){
|
||||||
|
return [$command, $arg];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$command, $arg];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function chooseNeutralTurn():array{
|
||||||
|
// 오랑캐는 바로 임관
|
||||||
|
if($general->getVar('npc') == 9) {
|
||||||
|
$rulerNation = $db->queryFirstField(
|
||||||
|
'SELECT nation FROM general WHERE `level`=12 AND npc=9 and nation not in %li ORDER BY RAND() limit 1',
|
||||||
|
Json::decode($general->getVar('nations'))
|
||||||
|
);
|
||||||
|
|
||||||
|
if($rulerNation){
|
||||||
|
return ['che_임관', ['destNationID'=>$rulerNation]];
|
||||||
|
}
|
||||||
|
return ['che_견문', null];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(Util::choiceRandomUsingWeight([11.4, 40, 20, 28.6])) {
|
||||||
|
//임관
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
$available = true;
|
||||||
|
|
||||||
|
if($admin['startyear']+3 > $admin['year']){
|
||||||
|
//초기 임관 기간에서는 국가가 적을수록 임관 시도가 적음
|
||||||
|
$nationCnt = $db->queryFirstField('SELECT count(nation) FROM nation');
|
||||||
|
$notFullNationCnt = $db->queryFirstField('SELECT count(nation) FROM nation WHERE gennum < %i', GameConst::$initialNationGenLimit);
|
||||||
|
if($nationCnt == 0 || $notFullNationCnt == 0){
|
||||||
|
$available = false;
|
||||||
|
}
|
||||||
|
else if(Util::randBool(pow(1 / $nationCnt / pow($notFullNationCnt, 3), 1/4))){
|
||||||
|
//국가가 1개일 경우에는 '임관하지 않음'
|
||||||
|
$available = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($general->getVar('affinity') == 999 || !$available){
|
||||||
|
$command = 'che_견문'; //견문
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//랜임 커맨드 입력.
|
||||||
|
$command = 'che_임관';
|
||||||
|
$arg = ['destNationID'=>99];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: //거병이나 견문
|
||||||
|
// 초반이면서 능력이 좋은놈 위주로 1.4%확률로 거병
|
||||||
|
$prop = Util::randF() * (GameConst::$defaultStatNPCMax + GameConst::$chiefStatMin) / 2;
|
||||||
|
$ratio = ($general->getVar('leader') + $general->getVar('power') + $general->getVar('intel')) / 3;
|
||||||
|
if($admin['startyear']+2 > $admin['year'] && $prop < $ratio && Util::randBool(0.014) && $general->getVar('makelimit') == 0) {
|
||||||
|
//거병
|
||||||
|
$command = 'che_거병';
|
||||||
|
} else {
|
||||||
|
//견문
|
||||||
|
$command = 'che_견문';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: //이동
|
||||||
|
|
||||||
|
$paths = array_keys(CityConst::byID($city['city'])::$path);
|
||||||
|
$command = 'che_이동';
|
||||||
|
$arg = ['destCityID'=>Util::choiceRandom($paths)];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$command = 'che_견문';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return [$command, $arg];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function chooseGeneralTurn($command, $arg):array{
|
||||||
|
$general = $this->getGeneralObj();
|
||||||
|
$city = $this->city;
|
||||||
|
$nation = $this->nation;
|
||||||
|
$env = $this->env;
|
||||||
|
|
||||||
|
$cityID = $general->getCityID();
|
||||||
|
$nationID = $general->getNationID();
|
||||||
|
|
||||||
|
$genType = $this->genType;
|
||||||
|
$leadership = $this->leadership;
|
||||||
|
$power = $this->power;
|
||||||
|
$intel = $this->intel;
|
||||||
|
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
|
if($general->getVar('npc') == 5){
|
||||||
|
if($nationID == 0 && $general->getVar('killturn') > 1){
|
||||||
|
$command = 'che_휴식'; //휴식
|
||||||
|
$arg = null;
|
||||||
|
$generalObj->setVar('killturn', 1);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$command = 'che_집합'; //집합
|
||||||
|
$arg = [];
|
||||||
|
$generalObj->setVar('killturn', rand(70,75));
|
||||||
|
//NOTE: 부대 편성에 보여야 하므로 이것만 DB에 직접 접근함.
|
||||||
|
$db->update('general_turn', [
|
||||||
|
'action'=>'che_집합',
|
||||||
|
'arg'=>'{}'
|
||||||
|
], 'general_ID=%i AND turn_idx < 6', $generalID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$command, $arg];
|
||||||
|
}
|
||||||
|
|
||||||
|
//특별 메세지 있는 경우 출력 하루 4번
|
||||||
|
$term = $env['turnterm'];
|
||||||
|
if($general->getVar('npcmsg') && Util::randBool($term / (6*60))) {
|
||||||
|
$src = new MessageTarget(
|
||||||
|
$generalID,
|
||||||
|
$general->getVar('name'),
|
||||||
|
$general->getVar('nation'),
|
||||||
|
$nation['name'],
|
||||||
|
$nation['color'],
|
||||||
|
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
|
||||||
|
);
|
||||||
|
$msg = new Message(
|
||||||
|
Message::MSGTYPE_PUBLIC,
|
||||||
|
$src,
|
||||||
|
$src,
|
||||||
|
$general->getVar('npcmsg'),
|
||||||
|
new \DateTime(),
|
||||||
|
new \DateTime('9999-12-31'),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
$msg->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($general->getVar('level') == 0){
|
||||||
|
return $this->chooseNeutralTurn();
|
||||||
|
}
|
||||||
|
|
||||||
|
$baseDevelCost = $env['develcost'] * 12;
|
||||||
|
|
||||||
|
$techCost = getTechCost($nation['tech']);
|
||||||
|
$baseArmCost = 10 * GameUnitConst::byID(GameUnitConst::DEFAULT_CREWTYPE)->costWithTect($nation['tech']);//기본 병종 1000기
|
||||||
|
$baseArmCost = $general->onCalcDomestic('징병', 'cost', $baseArmCost);
|
||||||
|
|
||||||
|
if($general->getVar('atmos') >= 90 && $general->getVar('train') >= 90) {
|
||||||
|
if($general->getVar('mode') == 0) {
|
||||||
|
$general->setVar('mode', 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if($general->getVar('mode') == 1) {
|
||||||
|
$general->setVar('mode', 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function chooseNationTurn($nationCommand, $nationArg):array{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function chooseGeneralTurn($generalCommand, $generalArg):array{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user