AI 구현중

This commit is contained in:
2020-04-08 03:30:40 +09:00
parent 97fdc095a5
commit 8519481f96
5 changed files with 330 additions and 47 deletions
+178 -26
View File
@@ -61,14 +61,14 @@ class GeneralAI
protected $npcWarGenerals;
/** @var General[] */
protected $userGenerals;
/** @var General[] */
/** @var General[] (전쟁 가능한 기간만 따져서) 최근 12턴 내에 전투를 수행한, 또는 전투를 수행할 수 있는 유저장 목록*/
protected $userWarGenerals;
/** @var General[] */
protected $userCivilGenerals;
/** @var General[] */
protected $lostGenerals;
/** @var General[] */
/** @var General[] 이번 턴에 '집합'하는 부대장 목록 */
protected $troopLeaders;
const t무장 = 1;
@@ -237,6 +237,9 @@ class GeneralAI
protected function do부대전방발령(LastTurn $lastTurn): ?NationCommand
{
if(!$this->frontCities){
return null;
}
$this->calcWarRoute();
$troopCandidate = [];
@@ -320,6 +323,10 @@ class GeneralAI
protected function do부대후방발령(LastTurn $lastTurn): ?NationCommand
{
if(!$this->frontCities){
return null;
}
$troopCandidate = [];
foreach($this->troopLeaders as $troopLeader){
$leaderID = $troopLeader->getID();
@@ -392,7 +399,7 @@ class GeneralAI
$generalCadidates = [];
$db = DB::db();
$chiefTurnTime = new \DateTimeImmutable($this->general->getVar('turntime'));
$chiefTurnTime = new \DateTimeImmutable($this->general->getTurnTime());
foreach($this->userWarGenerals as $userGeneral){
$generalID = $userGeneral->getID();
@@ -403,10 +410,18 @@ class GeneralAI
if(!key_exists($generalID, $this->supplyCities)){
continue;
}
if($userGeneral->getVar('troop') === 0){
$troopLeaderID = $userGeneral->getVar('troop');
if(!$troopLeaderID || !key_exists($troopLeaderID, $this->troopLeaders)){
continue;
}
if($userGeneral->getVar('troop') === $userGeneral->getID()){
if($troopLeaderID === $userGeneral->getID()){
continue;
}
$troopLeader = $this->nationGenerals[$troopLeaderID];
if($troopLeader->getCityID() !== $userGeneral->getCityID()){
continue;
}
if(!key_exists($troopLeader->getCityID(), $this->supplyCities)){
continue;
}
if($city['pop'] / $city['pop_max'] >= $this->nationPolicy->safeRecruitCityPopulationRatio){
@@ -416,9 +431,9 @@ class GeneralAI
continue;
}
$generalTurnTime = new \DateTimeImmutable($userGeneral->getVar('turntime'));
$generalTurnTime = new \DateTimeImmutable($userGeneral->getTurnTime());
$troopLeader = $this->nationGenerals[$userGeneral->getVar('troop')];
$troopTurnTime = new \DateTimeImmutable($troopLeader->getVar('turntime'));
$troopTurnTime = new \DateTimeImmutable($troopLeader->getTurnTime());
if($chiefTurnTime < $generalTurnTime && $generalTurnTime < $troopTurnTime){
$generalCadidates[$generalID] = $userGeneral;
@@ -429,16 +444,16 @@ class GeneralAI
return null;
}
$rawTurn = Util::convertArrayToDict($db->query('SELECT * FROM general_turn WHERE general_id IN %li AND turn_idx = 0', array_keys($generalCadidates)), 'no');
$generalCadidates = array_filter($generalCadidates, function(General $general)use($rawTurn){
$turnList = General::getReservedTurnByGeneralList($generalCadidates, 0, $this->env);
$generalCadidates = array_filter($generalCadidates, function(General $general)use($turnList){
$generalID = $general->getID();
if(in_array($rawTurn[$generalID]??null, ['che_징병', 'che_모병'])){
if($turnList[$generalID] instanceof Command\General\che_징병){
return true;
}
else{
return false;
}
}, ARRAY_FILTER_USE_KEY);
});
if(count($this->supplyCities) == 1){
return null;
@@ -548,12 +563,30 @@ class GeneralAI
protected function do유저장구출발령(LastTurn $lastTurn): ?NationCommand
{
if (in_array($this->dipState, [self::d평화, self::d선포])) {
return null;
}
//고립 도시 장수 발령
$args = [];
foreach ($this->lostGenerals as $lostGeneral) {
if ($lostGeneral->getVar('npc') >= 2) {
continue;
}
$troopID = $lostGeneral->getVar('troop');
if($troopID && key_exists($troopID, $this->troopLeaders)){
$troopLeader = $this->troopLeaders[$troopID];
if(
key_exists($troopLeader->getCityID(), $this->supplyCities) &&
$this->troopLeaders[$troopID]->getTurnTime() < $lostGeneral->getTurnTime()
){
//이미 탈출 가능한 부대를 탔다
continue;
}
}
if (in_array($this->dipState, [self::d직전, self::d전쟁]) && count($this->frontCities) > 2) {
$selCity = Util::choiceRandom($this->frontCities);
} else {
@@ -577,6 +610,40 @@ class GeneralAI
protected function do유저장전방발령(LastTurn $lastTurn): ?NationCommand
{
if(!$this->frontCities){
return null;
}
if (in_array($this->dipState, [self::d평화, self::d선포])) {
return null;
}
$generalCandidates = [];
foreach($this->userWarGenerals as $userGeneral){
$generalID = $userGeneral->getID();
$cityID = $userGeneral->getCityID();
if(key_exists($cityID, $this->frontCities)){
continue;
}
if($userGeneral->getVar('crew') < $this->nationPolicy->minWarCrew){
continue;
}
if($userGeneral->getVar('troop')){
continue;
}
$train = $userGeneral->getVar('train');
$atmos = $userGeneral->getVar('atmos');
if(max($train, $atmos) < $this->nationPolicy->properWarTrainAtmos){
continue;
}
$generalCandidates[$generalID] = $userGeneral;
}
return null;
}
@@ -591,6 +658,12 @@ class GeneralAI
protected function doNPC후방발령(LastTurn $lastTurn): ?NationCommand
{
if(!$this->frontCities){
return null;
}
if (in_array($this->dipState, [self::d평화, self::d선포])) {
return null;
}
return null;
}
@@ -622,6 +695,12 @@ class GeneralAI
protected function doNPC전방발령(LastTurn $lastTurn): ?NationCommand
{
if(!$this->frontCities){
return null;
}
if (in_array($this->dipState, [self::d평화, self::d선포])) {
return null;
}
return null;
}
@@ -1101,7 +1180,7 @@ class GeneralAI
if($lastTurn->getCommand() === 'che_천도'){
$cmd = buildNationCommandClass('che_천도', $general, $this->env, $lastTurn, $lastTurn->getArg());
if($cmd->isRunnable()){
$nationStor->last천도Trial = [$general->getVar('level'), $general->getVar('turntime')];
$nationStor->last천도Trial = [$general->getVar('level'), $general->getTurnTime()];
return $cmd;
}
}
@@ -1111,7 +1190,7 @@ class GeneralAI
[$lastTrialLevel, $lastTrialTurnTime] = $lastTrial;
$timeDiffSeconds = TimeUtil::DateIntervalToSeconds(
date_create_immutable($lastTrialTurnTime)->diff(
date_create_immutable($general->getVar('turntime'))
date_create_immutable($general->getTurnTime())
)
);
if($timeDiffSeconds < $turnTerm * 30 && $lastTrialLevel !== $general->getVar('level')){ //0.5Turn
@@ -1222,7 +1301,7 @@ class GeneralAI
}
$nationStor->last천도Trial = [$general->getVar('level'), $general->getVar('turntime')];
$nationStor->last천도Trial = [$general->getVar('level'), $general->getTurnTime()];
return $cmd;
}
@@ -1540,6 +1619,13 @@ class GeneralAI
protected function do징병(GeneralCommand $reservedCommand): ?GeneralCommand
{
if (!$this->attackable){
return null;
}
if (in_array($this->dipState, [self::d평화, self::d선포])) {
return null;
}
$general = $this->getGeneralObj();
$nation = $this->nation;
$env = $this->env;
@@ -1694,6 +1780,13 @@ class GeneralAI
protected function do출병(GeneralCommand $reservedCommand): ?GeneralCommand
{
if (!$this->attackable) {
return null;
}
if($this->dipState !== self::d전쟁){
return null;
}
$general = $this->getGeneralObj();
$city = $this->city;
$nation = $this->nation;
@@ -1745,11 +1838,25 @@ class GeneralAI
protected function do후방워프(GeneralCommand $reservedCommand): ?GeneralCommand
{
if(!$this->attackable){
return null;
}
if (in_array($this->dipState, [self::d평화, self::d선포])) {
return null;
}
return null;
}
protected function do전방워프(GeneralCommand $reservedCommand): ?GeneralCommand
{
if(!$this->attackable){
return null;
}
if (in_array($this->dipState, [self::d평화, self::d선포])) {
return null;
}
return null;
}
@@ -1761,12 +1868,28 @@ class GeneralAI
protected function do귀환(GeneralCommand $reservedCommand): ?GeneralCommand
{
return null;
$cityID = $this->general->getCityID();
if(key_exists($cityID, $this->supplyCities)){
return null;
}
$cmd = buildGeneralCommandClass('che_귀환', $this->general, $this->env);
if(!$cmd->isRunnable()){
return null;
}
return $cmd;
}
protected function do집합(GeneralCommand $reservedCommand): ?GeneralCommand
{
return null;
$cmd = $reservedCommand;
$general = $this->general;
$generalID = $general->getID();
$cmd = buildGeneralCommandClass('che_집합', $general, $this->env);
_setGeneralCommand($generalID, range(0, GameConst::$maxTurn - 1), $cmd->getRawClassName(), $cmd->getArg(), $cmd->getBrief());
return $cmd;
}
protected function do방랑군이동(GeneralCommand $reservedCommand): ?GeneralCommand
@@ -2027,7 +2150,20 @@ class GeneralAI
$db = DB::db();
$generalIDList = $db->queryFirstColumn('SELECT no FROM general WHERE nation = %i AND no != %i', $nationID, $this->general->getID());
foreach(General::createGeneralObjListFromDB($generalIDList, null, 2) as $nationGeneral){
$nationGenerals = General::createGeneralObjListFromDB($generalIDList, null, 2);
$lastWar = \PHP_INT_MAX;
foreach($nationGenerals as $nationGeneral){
$recentWar = $nationGeneral->calcRecentWarTurn($this->env['turnterm']);
if($recentWar >= $nationGeneral->getVar('belong') * 12){
//임관전 전투는 제외
continue;
}
$lastWar = min($lastWar, $recentWar);
}
foreach($nationGenerals as $nationGeneral){
$generalID = $nationGeneral->getID();
$cityID = $nationGeneral->getCityID();
$npcType = $nationGeneral->getVar('npc');
@@ -2045,13 +2181,25 @@ class GeneralAI
//부대장임
$troopLeaders[$generalID] = $nationGeneral;
}
else if($nationGeneral->getVar('troop') === $generalID && $nationGeneral->getReservedTurn(0, $this->env)->getName() === 'che_집합'){
//비 NPC부대장임
$troopLeaders[$generalID] = $nationGeneral;
}
else if($nationGeneral->getVar('killturn') < 5){
//삭턴이 몇 안남은 장수는 '내정장 npc'로 처리
$npcCivilGenerals[$generalID] = $nationGeneral;
}
else if($npcType < 2) {
$userGenerals[$generalID] = $nationGeneral;
if($nationGeneral->calcRecentWarTurn($this->env['turnterm']) <= 12){
if($nationGeneral->calcRecentWarTurn($this->env['turnterm']) <= $lastWar + 12){
$userWarGenerals[$generalID] = $nationGeneral;
}
else if(
$this->dipState !== self::d평화 &&
$nationGeneral->getVar('crew') >= $this->nationPolicy->minWarCrew &&
$nationGeneral->getVar('train') >= $nationGeneral->getVar('defence_train') &&
$nationGeneral->getVar('atmos') >= $nationGeneral->getVar('defence_train')
){
$userWarGenerals[$generalID] = $nationGeneral;
}
else{
@@ -2064,6 +2212,7 @@ class GeneralAI
}
}
$this->nationGenerals = $nationGenerals;
$this->userGenerals = $userGenerals;
$this->userCivilGenerals = $userCivilGenerals;
$this->userWarGenerals = $userWarGenerals;
@@ -2071,7 +2220,6 @@ class GeneralAI
$this->npcCivilGenerals = $npcCivilGenerals;
$this->npcWarGenerals = $npcWarGenerals;
$this->troopLeaders = $troopLeaders;
}
@@ -2134,17 +2282,21 @@ class GeneralAI
}
public function chooseGeneralTurn(GeneralCommand $reservedCommand): GeneralCommand{
$general = $this->general;
$npcType = $general->getVar('npc');
$nationID = $general->getNationID();
if($npcType == 5){
return $this->do집합($reservedCommand);
}
if($reservedCommand->isRunnable()){
return $reservedCommand;
}
$general = $this->general;
$npcType = $general->getVar('npc');
$nationID = $general->getNationID();
if($npcType == 5){
return $this->do집합($reservedCommand);
}
else if($npcType == 2 && $nationID == 0){
if($npcType == 2 && $nationID == 0){
$result = $this->do거병($reservedCommand);
if($result !== null){
return $result;