<?php
/**
* 敵クラス
*
*/
class Enemy implements BattleAble, HasEmotion, Stringable
{
private const EMOTION_DEFAULT = Emotion::COMMON;
private const DEFENCE_RATE = 2;
/** @var string $name 名前 */
private string $name;
/** @var int $hp HP */
private int $hp;
/** @var int $hpMax 最大HP */
private int $hpMax;
/** @var int $atk ATK */
private int $atk;
/** @var int $def DEF */
private int $def;
/** @var int $cri CRI */
private int $cri;
/** @var int $block BLOCK */
private int $block;
/** @var bool $isDefence 防御状態 */
private bool $isDefence = false;
/** @var bool クリティカルヒットしたか */
private bool $isCriticalHit = false;
/** @var bool ブロック成功したか */
private bool $isBlockSuccess = false;
/** @var Personality $personality 性格 */
private Personality $personality;
/** @var Emotion $emotion 感情 */
private Emotion $emotion = self::EMOTION_DEFAULT;
/** @var BehaviorPattern $behaviorPattern 行動パターン */
private BehaviorPattern $behaviorPattern;
/** @var StatusStrategy ステータスストラテジー */
private StatusStrategy $statusStrategy;
/**
* constructor
*
* @param int $hpMax 最大HP
* @param int $atk ATK
* @param int $def DEF
* @param int $cri CRI
* @param int $block BLOCK
* @param Personality $personality 性格
*/
public function __construct(string $name, int $hpMax, int $atk, int $def, int $cri, int $block, Personality $personality)
{
$this->name = $name;
$this->hp = $hpMax;
$this->hpMax = $hpMax;
$this->atk = $atk;
$this->def = $def;
$this->cri = $cri;
$this->block = $block;
$this->personality = $personality;
$this->behaviorPattern = new BehaviorPattern($personality, $this->emotion);
$this->setStatusStrategyFromEmotion($this->emotion);
}
/**
* 文字列変換
*
* @return string
*/
public function __toString(): string
{
return "名前:{$this->getName()} HP: {$this->getHp()}/{$this->getHpMax()} ({$this->getHpRate()}%) 性格: {$this->personality->value}";
}
/**
* @inheritDoc
*/
public function getName(): string
{
return $this->name;
}
/**
* @inheritDoc
*/
public function getHp(): int
{
return $this->statusStrategy->getHp($this->hp);
}
/**
* @inheritDoc
*/
public function subHp(int $value): void
{
$this->hp = max($this->hp - $value, self::HP_MIN);
}
/**
* @inheritDoc
*/
public function getHpMax(): int
{
return $this->statusStrategy->getHpMax($this->hpMax);
}
/**
* @inheritDoc
*/
public function getHpRate(): int
{
return $this->getHp() / $this->getHpMax() * BattleAble::PERCENTAGE;
}
/**
* @inheritDoc
*/
public function getAtk(): int
{
return $this->statusStrategy->getAtk($this->atk);
}
/**
* @inheritDoc
*/
public function getDef(): int
{
$def = $this->statusStrategy->getDef($this->def);
return $this->isDefence ? $def * self::DEFENCE_RATE : $def;
}
/**
* @inheritDoc
*/
public function getCri(): int
{
return $this->statusStrategy->getCri($this->cri);
}
/**
* @inheritDoc
*/
public function getBlock(): int
{
return $this->statusStrategy->getBlock($this->block);
}
/**
* @inheritDoc
*/
public function getTotalStatus(): int
{
return $this->getHpMax() + $this->getAtk() + $this->getDef() + $this->getCri() + $this->getBlock();
}
/**
* 感情を取得
*
* @return Emotion
*/
public function getEmotion(): Emotion
{
return $this->emotion;
}
/**
* 感情を更新
*
* @param Emotion $emotion
* @return void
*/
public function updateEmotion(Emotion $emotion): void
{
$this->emotion = $emotion;
$this->behaviorPattern->setWeightStrategyFromEmotion($emotion);
$this->setStatusStrategyFromEmotion($emotion);
}
/**
* 性格を取得
*
* @return Personality
*/
public function getPersonality(): Personality
{
return $this->personality;
}
/**
* @inheritDoc
*/
public function isDead(): bool
{
return $this->getHp() <= 0;
}
/**
* @inheritDoc
*/
public function action(BattleAble $target): Action
{
return match ($this->behaviorPattern->lotteryBehavior()) {
Behavior::ATTACK => new Attack($this, $target),
Behavior::DEFENCE => new Defence($this, $target),
Behavior::WAIT => new Wait($this, $target),
Behavior::ESCAPE => new Escape($this, $target),
};
}
/**
* @inheritDoc
*/
public function setDefence(bool $isDefence): void
{
$this->isDefence = $isDefence;
}
/**
* @inheritDoc
*/
public function isDefence(): bool
{
return $this->isDefence;
}
/**
* @inheritDoc
*/
public function lotteryCriticalHit(): bool
{
$this->setCriticalHit(RandomUtil::lottery($this->getCri()));
return $this->isCriticalHit();
}
/**
* @inheritDoc
*/
public function setCriticalHit(bool $isCriticalHit): void
{
$this->isCriticalHit = $isCriticalHit;
}
/**
* @inheritDoc
*/
public function isCriticalHit(): bool
{
return $this->isCriticalHit;
}
/**
* @inheritDoc
*/
public function lotteryBlockSuccess(): bool
{
$this->setBlockSuccess(RandomUtil::lottery($this->getBlock()));
return $this->isBlockSuccess();
}
/**
* @inheritDoc
*/
public function setBlockSuccess(bool $isBlockSuccess): void
{
$this->isBlockSuccess = $isBlockSuccess;
}
/**
* @inheritDoc
*/
public function isBlockSuccess(): bool
{
return $this->isBlockSuccess;
}
/**
* 感情からステータスストラテジーを設定
*
* @param Emotion $emotion
* @return void
*/
private function setStatusStrategyFromEmotion(Emotion $emotion): void
{
$this->statusStrategy = match ($emotion) {
Emotion::COMMON => new CommonEmotionStatus(),
Emotion::ARROGANCE => new ArroganceEmotionStatus(),
Emotion::CAUTION => new CautionEmotionStatus(),
Emotion::FEAR => new FearEmotionStatus(),
Emotion::ANGER => new AngerEmotionStatus(),
};
}
}