tests/Health/HealthTest.php
<?php declare(strict_types=1);
namespace DrdPlus\Tests\Health;
use DrdPlus\Codes\Body\OrdinaryWoundOriginCode;
use DrdPlus\Codes\Body\SeriousWoundOriginCode;
use DrdPlus\Health\Afflictions\AfflictionByWound;
use DrdPlus\Health\Afflictions\AfflictionName;
use DrdPlus\Health\Afflictions\SpecificAfflictions\Pain;
use DrdPlus\Health\HealingPower;
use DrdPlus\Health\Health;
use DrdPlus\Health\Inflictions\Glared;
use DrdPlus\Health\ReasonToRollAgainstMalusFromWounds;
use DrdPlus\Health\SeriousWound;
use DrdPlus\Health\Wound;
use DrdPlus\Health\WoundSize;
use DrdPlus\Lighting\Glare;
use DrdPlus\BaseProperties\Will;
use DrdPlus\Properties\Derived\Toughness;
use DrdPlus\Properties\Derived\WoundBoundary;
use DrdPlus\Tables\Measurements\Wounds\Wounds;
use DrdPlus\Tables\Measurements\Wounds\WoundsBonus;
use DrdPlus\Tables\Measurements\Wounds\WoundsTable;
use DrdPlus\Tables\Tables;
use Granam\DiceRolls\Templates\Rolls\Roll2d6DrdPlus;
use Granam\TestWithMockery\TestWithMockery;
class HealthTest extends TestWithMockery
{
/**
* @test
*/
public function I_can_use_it(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
self::assertSame(369, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(369, $health->getHealthMaximum($woundBoundary));
}
/**
* @param WoundBoundary $woundBoundary
* @return Health
*/
private function createHealthToTest(WoundBoundary $woundBoundary): Health
{
$health = new Health();
$this->assertUnwounded($health, $woundBoundary);
return $health;
}
/**
* @param int $value
* @return \Mockery\MockInterface|WoundBoundary
*/
private function createWoundBoundary(int $value)
{
$woundBoundary = $this->mockery(WoundBoundary::class);
$woundBoundary->shouldReceive('getValue')
->andReturn($value);
return $woundBoundary;
}
private function assertUnwounded(Health $health, WoundBoundary $woundBoundary): void
{
self::assertSame($health->getGridOfWounds()->getWoundsPerRowMaximum($woundBoundary), $woundBoundary->getValue());
self::assertSame($health->getGridOfWounds()->getWoundsPerRowMaximum($woundBoundary) * 3, $health->getHealthMaximum($woundBoundary));
self::assertSame($health->getGridOfWounds()->getWoundsPerRowMaximum($woundBoundary) * 3, $health->getRemainingHealthAmount($woundBoundary));
self::assertCount(0, $health->getUnhealedWounds());
self::assertSame(0, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame(0, $health->getUnhealedSeriousWoundsSum());
self::assertSame(0, $health->getNumberOfSeriousInjuries());
self::assertCount(0, $health->getAfflictions());
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary));
self::assertCount(0, $health->getPains());
self::assertTrue($health->isAlive($woundBoundary));
self::assertTrue($health->isConscious($woundBoundary));
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
self::assertSame(0, $health->getTreatmentBoundary()->getValue());
}
/**
* @test
* @dataProvider provideConsciousAndAlive
* @param int $woundBoundaryValue
* @param int $wound
* @param bool $isConscious
* @param bool $isAlive
*/
public function I_can_easily_find_out_if_creature_is_conscious_and_alive(
int $woundBoundaryValue,
int $wound,
bool $isConscious,
bool $isAlive
): void
{
$woundBoundary = $this->createWoundBoundary($woundBoundaryValue);
$health = $this->createHealthToTest($woundBoundary);
$health->addWound(
$this->createWoundSize($wound),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
self::assertSame($isConscious, $health->isConscious($woundBoundary));
self::assertSame($isAlive, $health->isAlive($woundBoundary));
}
public function provideConsciousAndAlive(): array
{
return [
[1, 0, true, true], // healthy
[1, 1, true, true], // wounded
[1, 2, false, true], // knocked down
[1, 3, false, false], // dead
];
}
// TREATMENT BOUNDARY
/**
* @test
*/
public function I_get_treatment_boundary_moved_to_reaming_wounds_on_ordinary_heal(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
self::assertSame(0, $health->getTreatmentBoundary()->getValue());
$health->addWound($this->createWoundSize(4), SeriousWoundOriginCode::getMechanicalCutWoundOrigin(), $woundBoundary);
self::assertSame(0, $health->getTreatmentBoundary()->getValue());
$health->healFreshOrdinaryWounds($this->createHealingPower(1, 1), $woundBoundary);
self::assertSame(3, $health->getTreatmentBoundary()->getValue());
self::assertSame($health->getUnhealedWoundsSum(), $health->getTreatmentBoundary()->getValue());
}
/**
* @param $value
* @return \Mockery\MockInterface|Toughness
*/
private function createToughness(int $value)
{
$toughness = $this->mockery(Toughness::class);
$toughness->shouldReceive('getValue')
->andReturn($value);
return $toughness;
}
/**
* @param int $woundsValue
* @return \Mockery\MockInterface|Tables
*/
private function createTablesWithWoundsTable(int $woundsValue)
{
$tables = $this->mockery(Tables::class);
$tables->shouldReceive('getWoundsTable')
->andReturn($woundsTable = $this->mockery(WoundsTable::class));
$woundsTable->shouldReceive('toWounds')
->andReturn($wounds = $this->mockery(Wounds::class));
$wounds->shouldReceive('getValue')
->andReturn($woundsValue);
$woundsTable->shouldReceive('toBonus')
->andReturn($woundsBonus = $this->mockery(WoundsBonus::class));
/** just for @see \DrdPlus\Properties\Partials\WithHistoryTrait::extractArgumentsDescription */
$woundsBonus->shouldReceive('getValue')
->andReturn(789);
return $tables;
}
/**
* @test
*/
public function I_get_treatment_boundary_increased_by_serious_wound_immediately(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
self::assertSame(0, $health->getTreatmentBoundary()->getValue());
$health->addWound($this->createWoundSize(7), SeriousWoundOriginCode::getMechanicalCutWoundOrigin(), $woundBoundary);
self::assertSame(7, $health->getTreatmentBoundary()->getValue());
self::assertSame($health->getUnhealedWoundsSum(), $health->getTreatmentBoundary()->getValue());
}
/**
* @test
*/
public function I_get_treatment_boundary_lowered_by_healed_serious_wound(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
self::assertSame(0, $health->getTreatmentBoundary()->getValue());
$seriousWound = $health->addWound($this->createWoundSize(7), SeriousWoundOriginCode::getMechanicalCutWoundOrigin(), $woundBoundary);
$health->healFreshSeriousWound(
$seriousWound,
$this->createHealingPower(5),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
self::assertSame(2, $health->getTreatmentBoundary()->getValue());
}
/**
* @test
*/
public function I_do_not_have_lowered_treatment_boundary_by_healed_ordinary_wound(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$health->addWound($this->createWoundSize(3), SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(), $woundBoundary);
$health->addWound($this->createWoundSize(6), SeriousWoundOriginCode::getMechanicalCutWoundOrigin(), $woundBoundary);
self::assertSame(6, $health->getTreatmentBoundary()->getValue());
self::assertSame(9, $health->getUnhealedWoundsSum());
$health->healFreshOrdinaryWounds($this->createHealingPower(999, 3), $woundBoundary);
self::assertSame(6, $health->getTreatmentBoundary()->getValue());
self::assertSame(6, $health->getUnhealedWoundsSum());
}
/**
* @test
*/
public function I_get_treatment_boundary_lowered_by_regenerated_amount(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$health->addWound($this->createWoundSize(3), SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(), $woundBoundary);
$health->addWound($this->createWoundSize(6), SeriousWoundOriginCode::getMechanicalCutWoundOrigin(), $woundBoundary);
self::assertSame(6, $health->getTreatmentBoundary()->getValue());
$health->regenerate(HealingPower::createForTreatment(9, $this->createToughness(-1), Tables::getIt()), $woundBoundary);
self::assertSame(
1,
$health->getTreatmentBoundary()->getValue(),
'Both ordinary and serious wound should be regenerated, therefore treatment boundary should be moved by regenerating power'
);
self::assertSame(1, $health->getUnhealedWoundsSum());
}
// ROLL ON MALUS RESULT
/**
* @test
* @dataProvider provideDecreasingRollAgainstMalusData
* @param $willValue
* @param $rollValue
* @param $expectedMalus
*/
public function I_should_roll_against_malus_from_wounds_because_of_new_wound($willValue, $rollValue, $expectedMalus): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$health->addWound($this->createWoundSize(10), SeriousWoundOriginCode::getElementalWoundOrigin(), $woundBoundary);
self::assertTrue($health->needsToRollAgainstMalusFromWounds());
self::assertSame(ReasonToRollAgainstMalusFromWounds::getWoundReason(), $health->getReasonToRollAgainstMalusFromWounds());
self::assertSame(
$expectedMalus,
$health->rollAgainstMalusFromWounds(
$this->createWill($willValue),
$this->createRoll2d6Plus($rollValue),
$woundBoundary
)
);
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
}
public function provideDecreasingRollAgainstMalusData(): array
{
return [
[7, 8, 0],
[99, 99, 0],
[6, 4, -1],
[6, 8, -1],
[3, 2, -2],
[2, 3, -2],
[1, 1, -3],
];
}
/**
* @param int $value
* @return \Mockery\MockInterface|Will
*/
private function createWill($value = null)
{
$will = $this->mockery(Will::class);
if ($value !== null) {
$will->shouldReceive('getValue')
->andReturn($value);
}
return $will;
}
/**
* @param $value
* @return \Mockery\MockInterface|Roll2d6DrdPlus
*/
private function createRoll2d6Plus($value = null): Roll2d6DrdPlus
{
$roll = $this->mockery(Roll2d6DrdPlus::class);
if ($value !== null) {
$roll->shouldReceive('getValue')
->andReturn($value);
$roll->shouldReceive('getRolledNumbers')
->andReturn([$value]);
}
return $roll;
}
/**
* @test
* @dataProvider provideIncreasingRollAgainstMalusData
* @param $willValue
* @param $rollValue
* @param $expectedMalus
*/
public function I_should_roll_against_malus_from_wounds_because_of_heal_of_ordinary_wound($willValue, $rollValue, $expectedMalus): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$health->addWound($this->createWoundSize(4),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->addWound($this->createWoundSize(4),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->addWound($this->createWoundSize(4),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(-1),
$this->createRoll2d6Plus(3),
$woundBoundary
); // -3 malus as a result
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
$health->healFreshOrdinaryWounds($this->createHealingPower(1, 1), $woundBoundary);
self::assertSame(ReasonToRollAgainstMalusFromWounds::getHealReason(), $health->getReasonToRollAgainstMalusFromWounds());
self::assertSame(
$expectedMalus,
$health->rollAgainstMalusFromWounds(
$this->createWill($willValue),
$this->createRoll2d6Plus($rollValue),
$woundBoundary
)
);
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
}
public function provideIncreasingRollAgainstMalusData(): array
{
return [
[1, 1, -3],
[3, 2, -2],
[2, 3, -2],
[6, 4, -1],
[6, 8, -1],
[7, 8, 0],
[99, 99, 0],
];
}
/**
* @test
* @dataProvider provideIncreasingRollAgainstMalusData
* @param $willValue
* @param $rollValue
* @param $expectedMalus
*/
public function I_should_roll_against_malus_from_wounds_because_of_heal_of_serious_wound($willValue, $rollValue, $expectedMalus): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$seriousWound = $health->addWound($this->createWoundSize(15),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(-1),
$this->createRoll2d6Plus(3),
$woundBoundary
); // -3 malus as a result
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(1),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
self::assertSame(ReasonToRollAgainstMalusFromWounds::getHealReason(), $health->getReasonToRollAgainstMalusFromWounds());
self::assertSame(
$expectedMalus,
$health->rollAgainstMalusFromWounds(
$this->createWill($willValue),
$this->createRoll2d6Plus($rollValue),
$woundBoundary
)
);
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
}
/**
* @test
* @dataProvider provideIncreasingRollAgainstMalusData
* @param $willValue
* @param $rollValue
* @param $expectedMalus
*/
public function I_should_roll_against_malus_from_wounds_because_of_regeneration($willValue, $rollValue, $expectedMalus): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$health->addWound($this->createWoundSize(15),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(-1),
$this->createRoll2d6Plus(3),
$woundBoundary
); // -3 malus as a result
$health->regenerate($this->createHealingPower(5, 5), $woundBoundary);
self::assertSame(ReasonToRollAgainstMalusFromWounds::getHealReason(), $health->getReasonToRollAgainstMalusFromWounds());
self::assertSame(
$expectedMalus,
$health->rollAgainstMalusFromWounds(
$this->createWill($willValue),
$this->createRoll2d6Plus($rollValue),
$woundBoundary
)
);
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
}
/**
* @test
*/
public function I_can_not_roll_on_malus_from_wounds_if_not_needed(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\UselessRollAgainstMalus::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$health->rollAgainstMalusFromWounds($this->createWill(),
$this->createRoll2d6Plus(),
$woundBoundary
);
}
// ROLL ON MALUS EXPECTED
/**
* @test
*/
public function I_can_not_add_new_wound_if_roll_on_malus_expected(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\NeedsToRollAgainstMalusFromWoundsFirst::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
try {
$health->addWound($this->createWoundSize(10),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getTraceAsString());
}
$health->addWound($this->createWoundSize(10),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
}
/**
* @test
*/
public function I_can_not_heal_fresh_ordinary_wounds_if_roll_on_malus_expected(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\NeedsToRollAgainstMalusFromWoundsFirst::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
try {
$health->addWound(
$this->createWoundSize(4),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->addWound(
$this->createWoundSize(4),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->addWound(
$this->createWoundSize(4),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getTraceAsString());
}
$health->healFreshOrdinaryWounds($this->createHealingPower(5), $woundBoundary);
}
/**
* @test
*/
public function I_can_not_heal_serious_wound_if_roll_on_malus_expected(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\NeedsToRollAgainstMalusFromWoundsFirst::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
try {
$seriousWound = $health->addWound($this->createWoundSize(14),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getTraceAsString());
}
/** @noinspection PhpUndefinedVariableInspection */
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(5),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
}
/**
* @test
*/
public function I_can_not_regenerate_if_roll_on_malus_expected(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\NeedsToRollAgainstMalusFromWoundsFirst::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
try {
$health->addWound($this->createWoundSize(14),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getTraceAsString());
}
$health->regenerate($this->createHealingPower(5), $woundBoundary);
}
/**
* @test
*/
public function I_can_not_get_malus_from_wounds_if_roll_on_it_expected(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\NeedsToRollAgainstMalusFromWoundsFirst::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
try {
$health->addWound(
$this->createWoundSize(14),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getTraceAsString());
}
$health->getSignificantMalusFromPains($woundBoundary);
}
// MALUS CONDITIONAL CHANGES
/**
* @test
* @dataProvider provideRollForMalus
* @param int $willValue
* @param int $rollValue
* @param int $expectedMalus
*/
public function Malus_can_increase_on_fresh_wound(int $willValue, int $rollValue, int $expectedMalus): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$health->addWound(
$this->createWoundSize(5),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
self::assertSame($expectedMalus, $health->rollAgainstMalusFromWounds($this->createWill($willValue),
$this->createRoll2d6Plus($rollValue),
$woundBoundary
));
self::assertSame($expectedMalus, $health->getSignificantMalusFromPains($woundBoundary));
for ($currentWillValue = $willValue, $currentRollValue = $rollValue;
$currentRollValue > -2 && $currentWillValue > -2;
$currentRollValue--, $currentWillValue--
) {
$seriousWound = $health->addWound($this->createWoundSize(3),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$currentlyExpectedMalus = max(0, min(3, (int)floor(($currentWillValue + $currentRollValue) / 5))) - 3; // 0; -1; -2; -3
self::assertSame(
$currentlyExpectedMalus, // malus can increase (be more negative)
$health->rollAgainstMalusFromWounds(
$this->createWill($currentWillValue),
$this->createRoll2d6Plus($currentRollValue),
$woundBoundary
),
"For will $currentWillValue and roll $currentRollValue has been expected malus $currentlyExpectedMalus"
);
self::assertSame($currentlyExpectedMalus, $health->getSignificantMalusFromPains($woundBoundary));
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(5, 3),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
); // "resetting" currently given wound
// low values to ensure untouched malus (should not be increased, therefore changed here at all, on heal)
$health->rollAgainstMalusFromWounds($this->createWill(-1),
$this->createRoll2d6Plus(-1),
$woundBoundary
);
}
}
public function provideRollForMalus(): array
{
return [
[1, 1, -3],
[-5, -5, -3],
[10, 5, 0],
[15, 0, 0],
[13, 1, -1],
[2, 7, -2],
[3, 7, -1],
[3, 1, -3],
[3, 2, -2],
];
}
/**
* @test
* @dataProvider provideRollForMalus
* @param int $willValue
* @param int $rollValue
* @param int $expectedMalus
*/
public function Malus_can_not_decrease_on_fresh_wound(int $willValue, int $rollValue, int $expectedMalus): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$health->addWound($this->createWoundSize(5),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
self::assertSame($expectedMalus, $health->rollAgainstMalusFromWounds($this->createWill($willValue),
$this->createRoll2d6Plus($rollValue),
$woundBoundary
));
self::assertSame($expectedMalus, $health->getSignificantMalusFromPains($woundBoundary));
for ($currentWillValue = $willValue, $currentRollValue = $rollValue;
$currentRollValue < 16 && $currentWillValue < 10;
$currentRollValue++, $currentWillValue++
) {
$seriousWound = $health->addWound($this->createWoundSize(3),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
self::assertSame(
$expectedMalus, // malus should not be decreased (be closer to zero)
$health->rollAgainstMalusFromWounds(
$this->createWill($currentWillValue),
$this->createRoll2d6Plus($currentRollValue),
$woundBoundary
),
"Even for will $currentWillValue and roll $currentRollValue has been expected previous malus $expectedMalus"
);
self::assertSame($expectedMalus, $health->getSignificantMalusFromPains($woundBoundary));
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(5, 3),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
); // "resetting" currently given wound
// low values to ensure untouched malus (should not be increased, therefore changed here at all, on heal)
$health->rollAgainstMalusFromWounds($this->createWill(-1),
$this->createRoll2d6Plus(-1),
$woundBoundary
);
}
}
/**
* @test
*/
public function Malus_is_not_increased_on_new_heal_by_worse_roll(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary));
// 3 ordinary wounds to reach some malus
$health->addWound($this->createWoundSize(2),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->addWound($this->createWoundSize(2),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->addWound($this->createWoundSize(2),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(0),
$this->createRoll2d6Plus(11),
$woundBoundary
);
self::assertSame(-1, $health->getSignificantMalusFromPains($woundBoundary));
self::assertSame(
1,
$health->healFreshOrdinaryWounds($this->createHealingPower(1, 1), $woundBoundary)
);
$health->rollAgainstMalusFromWounds($this->createWill(0),
$this->createRoll2d6Plus(-2),
$woundBoundary
); // much worse roll
self::assertSame(-1, $health->getSignificantMalusFromPains($woundBoundary), 'Malus should not be increased');
}
// AFFLICTION
/**
* @test
*/
public function I_can_add_affliction(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$wound = $health->addWound($this->createWoundSize(5),
SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(),
$woundBoundary
);
$affliction = $this->createAffliction($wound);
$health->addAffliction($affliction);
self::assertCount(1, $health->getAfflictions());
$afflictions = $health->getAfflictions();
self::assertSame($affliction, \current($afflictions));
}
/**
* @param SeriousWound $seriousWound
* @param array $values
* @return \Mockery\MockInterface|AfflictionByWound
*/
private function createAffliction(SeriousWound $seriousWound, array $values = [])
{
$afflictionByWound = $this->mockery(AfflictionByWound::class);
$afflictionByWound->shouldReceive('getSeriousWound')
->andReturn($seriousWound);
$afflictionByWound->shouldReceive('getName')
->andReturn($this->mockery(AfflictionName::class));
foreach ($values as $valueName => $value) {
$afflictionByWound->shouldReceive('get' . ucfirst($valueName))
->andReturn($value);
}
return $afflictionByWound;
}
/**
* @test
*/
public function I_can_not_add_affliction_of_unknown_wound(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\UnknownAfflictionOriginatingWound::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$affliction = $this->createAffliction($this->createSeriousWound());
$health->addAffliction($affliction);
}
/**
* @return \Mockery\MockInterface|SeriousWound
*/
private function createSeriousWound()
{
$wound = $this->mockery(SeriousWound::class);
$wound->shouldReceive('getHealth')
->andReturn($this->mockery(Health::class));
$wound->shouldReceive('getWoundOriginCode')
->andReturn(SeriousWoundOriginCode::getMechanicalCrushWoundOrigin());
$wound->shouldReceive('__toString')
->andReturn('123');
return $wound;
}
/**
* @test
*/
public function I_can_not_add_same_affliction_twice(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\AfflictionIsAlreadyRegistered::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$wound = $health->addWound(
$this->createWoundSize(6),
SeriousWoundOriginCode::getElementalWoundOrigin()
,
$woundBoundary
);
$affliction = $this->createAffliction($wound);
try {
$health->addAffliction($affliction);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getTraceAsString());
}
$health->addAffliction($affliction);
}
/**
* @test
*/
public function I_can_not_add_affliction_with_to_health_unknown_wound(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\UnknownAfflictionOriginatingWound::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$seriousWound = $health->addWound(
$this->createWoundSize(6),
SeriousWoundOriginCode::getElementalWoundOrigin()
,
$woundBoundary
);
$anotherHealth = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$anotherHealth->addAffliction($this->createAffliction($seriousWound));
}
// NEW WOUND
/**
* @test
*/
public function I_can_be_ordinary_wounded(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$ordinaryWound = $health->addWound(
$this->createWoundSize(2),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
self::assertInstanceOf(Wound::class, $ordinaryWound);
self::assertSame(2, $ordinaryWound->getValue());
self::assertSame(
OrdinaryWoundOriginCode::getIt(),
$ordinaryWound->getWoundOriginCode(),
'The ordinary wound origin should be used on such small wound'
);
self::assertCount(1, $health->getUnhealedWounds());
$unhealedWounds = $health->getUnhealedWounds();
self::assertSame($ordinaryWound, \end($unhealedWounds));
self::assertSame(13, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(2, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary));
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
$anotherOrdinaryWound = $health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
self::assertInstanceOf(Wound::class, $anotherOrdinaryWound);
self::assertSame(1, $anotherOrdinaryWound->getValue());
self::assertSame(
OrdinaryWoundOriginCode::getIt(),
$anotherOrdinaryWound->getWoundOriginCode(),
'The ordinary wound origin should be used on such small wound'
);
self::assertCount(2, $health->getUnhealedWounds());
$unhealedWounds = $health->getUnhealedWounds();
self::assertSame($anotherOrdinaryWound, \end($unhealedWounds));
self::assertSame([$ordinaryWound, $anotherOrdinaryWound], $health->getUnhealedWounds());
self::assertSame(3, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame(12, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary));
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
}
/**
* @test
*/
public function I_can_be_ordinary_healed(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(7));
$health->addWound($this->createWoundSize(1),
SeriousWoundOriginCode::getElementalWoundOrigin(),
$woundBoundary
);
$health->addWound($this->createWoundSize(3),
SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(),
$woundBoundary
);
$health->addWound($this->createWoundSize(2),
SeriousWoundOriginCode::getMechanicalStabWoundOrigin(),
$woundBoundary
);
self::assertSame(15, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(
4/** power of 4 - 3 (toughness) = 1 heals up to 4 wounds, @see WoundsTable and related bonus-to-value conversion */,
$health->healFreshOrdinaryWounds(
HealingPower::createForTreatment(4, $this->createToughness(-3), Tables::getIt()),
$woundBoundary
)
);
self::assertSame(19, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(2, $health->getUnhealedWoundsSum());
self::assertSame(0, $health->getUnhealedFreshOrdinaryWoundsSum(), 'All ordinary wounds should become "old" after heal');
self::assertSame(0, $health->getUnhealedSeriousWoundsSum());
self::assertSame(0, $health->getNumberOfSeriousInjuries());
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary));
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
self::assertSame(
0,
$health->healFreshOrdinaryWounds($this->createHealingPower(10, 0), $woundBoundary),
'Nothing should be healed as a "new ordinary wound: because of treatment boundary'
);
self::assertSame(19, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(2, $health->getUnhealedWoundsSum());
}
/**
* @param $healUpTo
* @param $expectedHealedAmount
* @return \Mockery\MockInterface|HealingPower
*/
private function createHealingPower($healUpTo = null, $expectedHealedAmount = null)
{
$healingPower = $this->mockery(HealingPower::class);
if ($healUpTo !== null) {
$healingPower->shouldReceive('getHealUpToWounds')
->andReturn($healUpTo);
}
if ($expectedHealedAmount !== null) {
$decreasedHealingPower = $this->mockery(HealingPower::class);
$decreasedHealingPower->shouldReceive('getHealUpToWounds')
->andReturn(0);
}
return $healingPower;
}
/**
* @test
*/
public function I_can_be_seriously_wounded(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(6));
$seriousWoundByStab = $health->addWound(
$this->createWoundSize(3),
$seriousWoundOrigin = SeriousWoundOriginCode::getMechanicalStabWoundOrigin(),
$woundBoundary
);
self::assertInstanceOf(Wound::class, $seriousWoundByStab);
self::assertSame(3, $seriousWoundByStab->getValue());
self::assertSame($seriousWoundOrigin, $seriousWoundByStab->getWoundOriginCode());
self::assertCount(1, $health->getUnhealedWounds());
self::assertCount(1, $health->getUnhealedFreshWounds());
self::assertCount(0, $health->getUnhealedOldWounds());
$unhealedWounds = $health->getUnhealedWounds();
self::assertSame($seriousWoundByStab, \end($unhealedWounds));
$unhealedFreshWounds = $health->getUnhealedFreshWounds();
self::assertSame($seriousWoundByStab, \end($unhealedFreshWounds));
self::assertSame(15, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(0, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame(3, $health->getUnhealedFreshSeriousWoundsSum());
self::assertSame(3, $health->getUnhealedSeriousWoundsSum());
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary), 'There are not enough wounds to suffer from them yet.');
self::assertFalse($health->needsToRollAgainstMalusFromWounds());
self::assertNull($health->getReasonToRollAgainstMalusFromWounds());
$seriousWoundByPsyche = $health->addWound(
$this->createWoundSize(5),
$seriousWoundOrigin = SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
self::assertInstanceOf(Wound::class, $seriousWoundByPsyche);
self::assertSame(5, $seriousWoundByPsyche->getValue());
self::assertTrue($seriousWoundByPsyche->isSerious());
self::assertSame($seriousWoundOrigin, $seriousWoundByPsyche->getWoundOriginCode());
self::assertCount(2, $health->getUnhealedWounds());
self::assertSame(0, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame(8, $health->getUnhealedSeriousWoundsSum());
self::assertSame(8, $health->getUnhealedFreshSeriousWoundsSum());
self::assertSame(8, $health->getUnhealedWoundsSum());
self::assertSame(10, $health->getRemainingHealthAmount($woundBoundary));
self::assertTrue($health->needsToRollAgainstMalusFromWounds());
self::assertSame(ReasonToRollAgainstMalusFromWounds::getWoundReason(), $health->getReasonToRollAgainstMalusFromWounds());
$woundSum = 0;
$collectedWounds = [];
foreach ($health->getUnhealedWounds() as $unhealedWound) {
self::assertInstanceOf(Wound::class, $unhealedWound);
self::assertLessThanOrEqual(5, $unhealedWound->getValue());
$woundSum += $unhealedWound->getValue();
$collectedWounds[] = $unhealedWound;
}
$collectedWounds = $this->sortObjects($collectedWounds);
$unhealedWounds = $this->sortObjects($health->getUnhealedWounds());
self::assertSame($unhealedWounds, $collectedWounds);
self::assertCount(2, $health->getUnhealedWounds());
self::assertSame(8, $woundSum);
}
/**
* @param int $value
* @return \Mockery\MockInterface|WoundSize
*/
private function createWoundSize($value)
{
$woundSize = $this->mockery(WoundSize::class);
$woundSize->shouldReceive('getValue')
->andReturn($value);
return $woundSize;
}
private function sortObjects(array $objects): array
{
\usort($objects, function ($object1, $object2) {
return \strcasecmp(\spl_object_hash($object1), \spl_object_hash($object2));
});
return $objects;
}
/**
* @test
*/
public function I_can_get_healed_serious_wounds(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(6));
$seriousWoundByStab = $health->addWound(
$this->createWoundSize(3),
$seriousWoundOrigin = SeriousWoundOriginCode::getMechanicalStabWoundOrigin(),
$woundBoundary
);
$seriousWoundByPsyche = $health->addWound(
$this->createWoundSize(5),
$seriousWoundOrigin = SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
self::assertSame(
-3,
$health->rollAgainstMalusFromWounds($this->createWill(-1), $this->createRoll2d6Plus(1), $woundBoundary)
);
self::assertSame(
0,
$health->healFreshOrdinaryWounds($this->createHealingPower(1, 0), $woundBoundary),
'Nothing should be healed because there is no ordinary wound'
);
self::assertSame(8, $health->getUnhealedWoundsSum());
self::assertCount(2, $health->getUnhealedWounds());
self::assertSame(10, $health->getRemainingHealthAmount($woundBoundary));
self::assertSame(8, $health->getUnhealedSeriousWoundsSum());
self::assertSame(8, $health->getUnhealedFreshSeriousWoundsSum());
self::assertSame(0, $health->getUnhealedOldWoundsSum());
self::assertSame(3, $health->healFreshSeriousWound($seriousWoundByPsyche,
$this->createHealingPower(3, 3),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
));
self::assertSame(13, $health->getRemainingHealthAmount($woundBoundary));
self::assertCount(2, $health->getUnhealedWounds());
self::assertSame(5, $health->getUnhealedWoundsSum());
self::assertSame(0, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame(5, $health->getUnhealedSeriousWoundsSum());
self::assertSame(3, $health->getUnhealedFreshSeriousWoundsSum());
self::assertSame(2, $health->getUnhealedOldSeriousWoundsSum());
self::assertSame(2, $health->getNumberOfSeriousInjuries(), 'Both serious wounds are still unhealed');
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary), 'Malus should be gone because of low damage after heal');
self::assertSame(3, $health->healFreshSeriousWound($seriousWoundByStab,
$this->createHealingPower(10, 3),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
));
self::assertSame(16, $health->getRemainingHealthAmount($woundBoundary));
self::assertCount(1, $health->getUnhealedWounds());
self::assertSame(2, $health->getUnhealedWoundsSum());
self::assertSame(0, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame(0, $health->getUnhealedFreshSeriousWoundsSum());
self::assertSame(2, $health->getUnhealedOldSeriousWoundsSum());
self::assertSame(2, $health->getUnhealedSeriousWoundsSum());
self::assertSame(1, $health->getNumberOfSeriousInjuries(), 'Single serious wound is unhealed');
}
/**
* @test
*/
public function I_can_not_heal_serious_wound_from_different_health(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\UnknownSeriousWoundToHeal::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$seriousWound = $health->addWound($this->createWoundSize(5),
SeriousWoundOriginCode::getMechanicalCutWoundOrigin(),
$woundBoundary
);
$anotherHealth = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(3));
$anotherHealth->healFreshSeriousWound($seriousWound,
$this->createHealingPower(),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
}
/**
* @test
* @throws \ReflectionException
*/
public function I_can_not_heal_serious_wound_not_created_by_current_health(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\UnknownSeriousWoundToHeal::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$healthReflection = new \ReflectionClass($health);
$openForNewWound = $healthReflection->getProperty('openForNewWound');
$openForNewWound->setAccessible(true);
$openForNewWound->setValue($health, true);
$seriousWound = new SeriousWound($health, $this->createWoundSize(5), SeriousWoundOriginCode::getMechanicalCutWoundOrigin());
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
}
/**
* @test
*/
public function I_can_not_heal_old_serious_wound(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\ExpectedFreshWoundToHeal::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$seriousWound = $health->addWound(
$this->createWoundSize(5),
SeriousWoundOriginCode::getMechanicalCutWoundOrigin(),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(0),
$this->createRoll2d6Plus(10),
$woundBoundary
);
self::assertTrue($seriousWound->isSerious());
$seriousWound->setOld();
self::assertTrue($seriousWound->isOld());
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
}
/**
* @test
*/
public function I_can_not_heal_already_treated_serious_wound(): void
{
$this->expectException(\DrdPlus\Health\Exceptions\ExpectedFreshWoundToHeal::class);
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(5));
$seriousWound = $health->addWound(
$this->createWoundSize(5),
SeriousWoundOriginCode::getMechanicalCutWoundOrigin()
,
$woundBoundary
);
self::assertTrue($seriousWound->isSerious());
$health->rollAgainstMalusFromWounds($this->createWill(123),
$this->createRoll2d6Plus(321),
$woundBoundary
);
try {
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(3, 3),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
} catch (\Exception $exception) {
self::fail('No exception expected so far: ' . $exception->getMessage() . "\n" . $exception->getTraceAsString());
}
self::assertTrue($seriousWound->isOld());
$health->healFreshSeriousWound($seriousWound,
$this->createHealingPower(),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
);
}
/**
* @test
*/
public function I_can_ask_it_if_has_fresh_wounds(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
self::assertFalse($health->hasFreshWounds());
$health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(),
$woundBoundary
);
self::assertTrue($health->hasFreshWounds(), 'There should be a fresh wound');
}
/**
* @test
*/
public function I_can_be_wounded_both_ordinary_and_seriously(): void
{
$ordinaryWoundsSize = 0;
$seriousWoundsSize = 0;
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(10));
$firstOrdinaryWound = $health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(),
$woundBoundary
);
self::assertTrue($firstOrdinaryWound->isOrdinary(), 'That wounds expected to be ordinary for testing purposes');
$ordinaryWoundsSize += $firstOrdinaryWound->getValue();
$secondOrdinaryWound = $health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(),
$woundBoundary
);
self::assertTrue($secondOrdinaryWound->isOrdinary(), 'That wounds expected to be ordinary for testing purposes');
$ordinaryWoundsSize += $secondOrdinaryWound->getValue();
$firstSeriousWound = $health->addWound(
$this->createWoundSize(5),
SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(),
$woundBoundary
);
$seriousWoundsSize += $firstSeriousWound->getValue();
self::assertTrue($firstSeriousWound->isSerious(), 'That wounds expected to be serious for testing purposes');
$secondSeriousWound = $health->addWound(
$this->createWoundSize(6),
SeriousWoundOriginCode::getMechanicalCrushWoundOrigin(),
$woundBoundary
);
$seriousWoundsSize += $secondSeriousWound->getValue();
self::assertTrue($secondSeriousWound->isSerious(), 'That wounds expected to be serious for testing purposes');
// total
self::assertSame($seriousWoundsSize, $health->getTreatmentBoundary()->getValue(), 'Treatment boundary should be moved on sum of serious wounds');
self::assertSame($ordinaryWoundsSize + $seriousWoundsSize, $health->getUnhealedWoundsSum());
// fresh
self::assertSame($ordinaryWoundsSize + $seriousWoundsSize, $health->getUnhealedFreshWoundsSum());
self::assertSame($ordinaryWoundsSize, $health->getUnhealedFreshOrdinaryWoundsSum());
self::assertSame($seriousWoundsSize, $health->getUnhealedFreshSeriousWoundsSum());
// old
self::assertSame(0, $health->getUnhealedOldWoundsSum());
self::assertSame(0, $health->getUnhealedOldOrdinaryWoundsSum());
self::assertSame(0, $health->getUnhealedOldSeriousWoundsSum());
// ordinary vs serious
self::assertSame($ordinaryWoundsSize, $health->getUnhealedOrdinaryWoundsSum());
self::assertSame($seriousWoundsSize, $health->getUnhealedSeriousWoundsSum());
$health->rollAgainstMalusFromWounds($this->createWill(1), $this->createRoll2d6Plus(5), $woundBoundary);
self::assertSame(
0, // nothing healed because of too low healing power
$health->healFreshOrdinaryWounds($this->createHealingPower(-21, 0), $woundBoundary)
);
// all ordinary wounds should become old as we tried to heal them (even if unsuccessfully)
self::assertSame(0, $health->getUnhealedFreshOrdinaryWoundsSum(), 'All ordinary wounds should be marked as old');
self::assertSame(
$health->getUnhealedFreshOrdinaryWoundsSum(),
$health->getUnhealedWoundsSum() - $health->getTreatmentBoundary()->getValue()
);
self::assertSame($ordinaryWoundsSize, $health->getUnhealedOldWoundsSum(), 'All ordinary wounds should be marked as old');
self::assertSame($ordinaryWoundsSize, $health->getUnhealedOldOrdinaryWoundsSum(), 'All ordinary wounds should be marked as old');
// nothing should change on serious wounds so far
self::assertSame($seriousWoundsSize, $health->getUnhealedSeriousWoundsSum());
self::assertSame($seriousWoundsSize, $health->getUnhealedFreshSeriousWoundsSum());
self::assertSame(0, $health->getUnhealedOldSeriousWoundsSum());
self::assertSame(
0, // nothing healed because of too low healing power
$health->healFreshSeriousWound(
$firstSeriousWound,
$this->createHealingPower(-21, 0),
$this->createToughness(123),
$this->createTablesWithWoundsTable($woundBoundary->getValue())
)
);
// first serious wound should be marked as old
self::assertSame($seriousWoundsSize, $health->getUnhealedSeriousWoundsSum());
self::assertSame(
$secondSeriousWound->getValue(), // this one is unhealed
$health->getUnhealedFreshSeriousWoundsSum()
);
self::assertSame(
$firstSeriousWound->getValue(), // this one was attempted to be healed, so is old
$health->getUnhealedOldSeriousWoundsSum()
);
}
/**
* @test
*/
public function I_get_highest_malus_from_wound_and_pains(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(12));
$damnSeriousWound = $health->addWound($this->createWoundSize(15),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(1),
$this->createRoll2d6Plus(7),
$woundBoundary
);
self::assertSame(-2, $health->getSignificantMalusFromPains($woundBoundary));
$health->addAffliction($this->createAffliction($damnSeriousWound));
self::assertSame(-2, $health->getSignificantMalusFromPains($woundBoundary));
$health->addAffliction($this->createPain($damnSeriousWound, ['malusToActivities' => -5]));
self::assertSame(-5, $health->getSignificantMalusFromPains($woundBoundary));
}
/**
* @param SeriousWound $seriousWound
* @param array $maluses
* @return \Mockery\MockInterface|Pain
*/
private function createPain(SeriousWound $seriousWound, array $maluses = [])
{
$pain = $this->mockery(Pain::class);
$pain->shouldReceive('getSeriousWound')
->andReturn($seriousWound);
foreach ($maluses as $nameOfValue => $otherValue) {
$pain->shouldReceive('get' . ucfirst($nameOfValue))
->andReturn($otherValue);
}
return $pain;
}
/**
* @test
*/
public function I_can_get_all_pains_and_afflictions(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
$seriousWound = $health->addWound($this->createWoundSize(70),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->addAffliction($firstPain = $this->createPain($seriousWound, ['malusToActivities' => -10]));
$health->addAffliction($someAffliction = $this->createAffliction($seriousWound));
$health->addAffliction($secondPain = $this->createPain($seriousWound, ['malusToActivities' => -20]));
$health->addAffliction($thirdPain = $this->createPain($seriousWound, ['malusToActivities' => -30]));
self::assertSame($this->sortObjects([$firstPain, $secondPain, $thirdPain]), $this->sortObjects($health->getPains()));
self::assertSame($this->sortObjects([$firstPain, $secondPain, $someAffliction, $thirdPain]), $this->sortObjects($health->getAfflictions()));
}
/**
* @test
*/
public function I_can_get_strength_malus_from_afflictions(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
$seriousWound = $health->addWound($this->createWoundSize(70),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->addAffliction($this->createPain($seriousWound, ['strengthMalus' => -4]));
$health->addAffliction($this->createAffliction($seriousWound, ['strengthMalus' => -1]));
$health->addAffliction($this->createPain($seriousWound, ['strengthMalus' => 123]));
self::assertSame(118, $health->getStrengthMalusFromAfflictions());
}
/**
* @test
*/
public function I_can_get_agility_malus_from_afflictions(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
$seriousWound = $health->addWound($this->createWoundSize(70),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->addAffliction($this->createPain($seriousWound, ['agilityMalus' => -1]));
$health->addAffliction($this->createAffliction($seriousWound, ['agilityMalus' => -2]));
$health->addAffliction($this->createPain($seriousWound, ['agilityMalus' => -3]));
self::assertSame(-6, $health->getAgilityMalusFromAfflictions());
}
/**
* @test
*/
public function I_can_get_knack_malus_from_afflictions(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
$seriousWound = $health->addWound($this->createWoundSize(70),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->addAffliction($this->createPain($seriousWound, ['knackMalus' => -8]));
$health->addAffliction($this->createAffliction($seriousWound, ['knackMalus' => -15]));
$health->addAffliction($this->createPain($seriousWound, ['knackMalus' => -1]));
self::assertSame(-24, $health->getKnackMalusFromAfflictions());
}
/**
* @test
*/
public function I_can_get_will_malus_from_afflictions(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
$seriousWound = $health->addWound($this->createWoundSize(70),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->addAffliction($this->createPain($seriousWound, ['willMalus' => -3]));
$health->addAffliction($this->createAffliction($seriousWound, ['willMalus' => -2]));
$health->addAffliction($this->createPain($seriousWound, ['willMalus' => -5]));
self::assertSame(-10, $health->getWillMalusFromAfflictions());
}
/**
* @test
*/
public function I_can_get_intelligence_malus_from_afflictions(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
$seriousWound = $health->addWound($this->createWoundSize(70),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->addAffliction($this->createPain($seriousWound, ['intelligenceMalus' => 0]));
$health->addAffliction($this->createAffliction($seriousWound, ['intelligenceMalus' => 1]));
$health->addAffliction($this->createPain($seriousWound, ['intelligenceMalus' => 0]));
$health->addAffliction($this->createPain($seriousWound, ['intelligenceMalus' => -6]));
self::assertSame(-5, $health->getIntelligenceMalusFromAfflictions());
}
/**
* @test
*/
public function I_can_get_charisma_malus_from_afflictions(): void
{
$health = $this->createHealthToTest($woundBoundary = $this->createWoundBoundary(123));
$seriousWound = $health->addWound($this->createWoundSize(70),
SeriousWoundOriginCode::getPsychicalWoundOrigin(),
$woundBoundary
);
$health->addAffliction($this->createPain($seriousWound, ['charismaMalus' => -5]));
$health->addAffliction($this->createAffliction($seriousWound, ['charismaMalus' => -2]));
self::assertSame(-7, $health->getCharismaMalusFromAfflictions());
}
/**
* @test
*/
public function I_can_be_glared(): void
{
$health = new Health();
self::assertEquals(Glared::createWithoutGlare($health), $health->getGlared());
$health->inflictByGlare($glare = $this->createGlare());
self::assertEquals(Glared::createFromGlare($glare, $health), $health->getGlared());
$previousGlared = $health->getGlared();
$health->inflictByGlare($this->createGlare());
self::assertNotSame($previousGlared, $health->getGlared());
}
/**
* @param int $malus
* @param bool $isShined
* @return \Mockery\MockInterface|Glare
*/
private function createGlare($malus = -123, $isShined = true)
{
$glare = $this->mockery(Glare::class);
$glare->shouldReceive('getMalus')
->andReturn($malus);
$glare->shouldReceive('isShined')
->andReturn($isShined);
return $glare;
}
/**
* @test
*/
public function I_can_easily_find_out_if_may_have_malus_from_wounds(): void
{
$health = new Health();
self::assertFalse($health->mayHaveMalusFromWounds($woundBoundary = $this->createWoundBoundary(10)));
$health->addWound(
$this->createWoundSize($woundBoundary->getValue() - 1),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
self::assertFalse($health->mayHaveMalusFromWounds($woundBoundary));
self::assertTrue($health->mayHaveMalusFromWounds($this->createWoundBoundary($woundBoundary->getValue() - 1)));
self::assertFalse($health->mayHaveMalusFromWounds($woundBoundary));
$health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
self::assertTrue($health->mayHaveMalusFromWounds($woundBoundary));
}
/**
* @test
*/
public function I_can_ask_it_if_may_suffer_from_wounds(): void
{
$woundBoundary = $this->createWoundBoundary(5);
$health = $this->createHealthToTest($woundBoundary);
self::assertFalse($health->maySufferFromWounds($woundBoundary));
$health->addWound(
$this->createWoundSize(4),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
self::assertFalse($health->maySufferFromWounds($woundBoundary));
$health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(999), $this->createRoll2d6Plus(999), $woundBoundary);
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary), 'No malus expected due to a really high roll and will');
self::assertTrue(
$health->maySufferFromWounds($woundBoundary),
'There should be already a chance to suffer from wounds as the fatigue boundary is same as fatigue (first row is filled)'
);
$health->addWound(
$this->createWoundSize(4),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(999), $this->createRoll2d6Plus(999), $woundBoundary);
self::assertTrue(
$health->maySufferFromWounds($woundBoundary),
'There should be a chance to suffer from wounds as two rows are filled'
);
self::assertTrue($health->isConscious($woundBoundary));
$health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
self::assertFalse($health->isConscious($woundBoundary));
self::assertFalse(
$health->maySufferFromWounds($woundBoundary),
'I should not suffer from wounds as I am unconscious'
);
}
/**
* @test
*/
public function I_can_ask_it_if_I_am_suffering_from_wounds(): void
{
$woundBoundary = $this->createWoundBoundary(5);
$health = $this->createHealthToTest($woundBoundary);
self::assertFalse($health->mayHaveMalusFromWounds($woundBoundary));
$health->addWound(
$this->createWoundSize(4),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
self::assertFalse($health->mayHaveMalusFromWounds($woundBoundary));
$health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(999), $this->createRoll2d6Plus(999), $woundBoundary);
self::assertSame(0, $health->getSignificantMalusFromPains($woundBoundary), 'No malus expected due to a really high roll and will');
self::assertTrue(
$health->mayHaveMalusFromWounds($woundBoundary),
'There should be already a chance to suffer from wounds as the fatigue boundary is same as fatigue (first row is filled)'
);
$health->addWound(
$this->createWoundSize(4),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
$health->rollAgainstMalusFromWounds($this->createWill(999), $this->createRoll2d6Plus(999), $woundBoundary);
self::assertTrue(
$health->mayHaveMalusFromWounds($woundBoundary),
'There should be a chance to suffer from wounds as two rows are filled'
);
self::assertTrue($health->isConscious($woundBoundary));
$health->addWound(
$this->createWoundSize(1),
SeriousWoundOriginCode::getIt(SeriousWoundOriginCode::PSYCHICAL),
$woundBoundary
);
self::assertFalse($health->isConscious($woundBoundary));
self::assertTrue(
$health->mayHaveMalusFromWounds($woundBoundary),
'I should still have (non-applicable) malus fatigue even as unconscious'
);
}
}