Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BlazorRogue.Tests/HeadlessPlayDriverTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace BlazorRogue.Tests;

// HeadlessPlayDriver/IPlayerPolicy/RandomHazardAvoidingPolicy - issue #88's headless play driver.
// HeadlessPlayDriver/IPlayerPolicy/RandomHazardAvoidingPolicy - the headless play driver.
// Map.TakeTurn itself (the thing the driver forwards to) is already exercised directly in
// TurnResultTests/MapTests; these tests are about the driver's own thin delegation and the
// built-in policy's action selection, not about re-proving TakeTurn's turn-resolution rules.
Expand Down
2 changes: 1 addition & 1 deletion BlazorRogue.Tests/MapTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public void IsMovementBlockedAcrossEdgeOnlyBlocksTheDeclaredEdgeAndNeverAnUnseal
// A diagonal move that would otherwise cut straight through a sealed corner - both detours
// around it blocked - must be denied too, or a mover can bypass two blocked edges at once by
// stepping onto/through the corner tile diagonally. Reported live: a monster walked diagonally
// through a fence enclosure corner (dontrolle/BlazorRogue-internal#86).
// through a fence enclosure corner.
[Fact]
public void IsMovementBlockedAcrossEdgeDeniesADiagonalThatCutsASealedCorner()
{
Expand Down
2 changes: 1 addition & 1 deletion BlazorRogue.Tests/TestSupport/HeadlessPlayDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace BlazorRogue.Tests.TestSupport;

/// <summary>
/// Thin wrapper for driving a <see cref="BlazorRogue.Game"/> with no Blazor Server/browser
/// involved (issue #88) - fast automated play tests and, eventually, play-balance sweeps. Every
/// involved - fast automated play tests and, eventually, play-balance sweeps. Every
/// actual turn-taking rule lives in <see cref="Map.TakeTurn"/>; this only owns the
/// <see cref="Game"/> instance and forwards to it, plus optionally driving an
/// <see cref="IPlayerPolicy"/> instead of a caller picking each <see cref="PlayerAction"/> by hand.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace BlazorRogue.Tests.TestSupport;

/// <summary>
/// Supplies the next <see cref="PlayerAction"/> for a <see cref="HeadlessPlayDriver"/> to take,
/// given the current <see cref="Map"/> state - the seam a play-balance sweep (issue #88) would
/// given the current <see cref="Map"/> state - the seam a play-balance sweep would
/// implement its own smarter policy against instead of <see cref="RandomHazardAvoidingPolicy"/>.
/// </summary>
interface IPlayerPolicy
Expand Down
4 changes: 2 additions & 2 deletions BlazorRogue.Tests/TurnResultTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace BlazorRogue.Tests;

// Map.TakeTurn(PlayerAction) - the unified entry point for issue #88's headless play driver, and
// Map.TakeTurn(PlayerAction) - the unified entry point for the headless play driver, and
// (as of Phase 4) GamePage.razor's own turn-taking path too. Exercises the same handlers
// MapTests/ItemInteractionTests/StairTests already cover individually
// (HandlePlayerActionCore/PickUpItemsAtPlayer/UseInventoryItem/DropInventoryItem/stairs), but
Expand Down Expand Up @@ -160,7 +160,7 @@ public void MonsterKilledByThePlayersOwnAttackCannotCounterAttackInTheSameTurn()
var ai = (SimpleAIComponent)
AIComponentFactory.Create(SimpleAIComponent.ComponentId, map, SettingsMap.Empty);
// Adjacent, awake, and one hit from dead - registered via AddMonster (not AddMoveable) so
// it's actually enqueued in the tick scheduler like a real monster (issue #68).
// it's actually enqueued in the tick scheduler like a real monster.
var monster = NewCreature(5, 4, weaponSkill: 1, wounds: 1, ai: ai);
map.AddMonster(monster);
ai.Wake();
Expand Down
14 changes: 7 additions & 7 deletions BlazorRogue.Tests/World/FenceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace BlazorRogue.Tests.World;

/// <summary>
/// Covers the fence decoration types in Data/decorations.json (dontrolle/BlazorRogue-internal#86,
/// Stage 1): each is a plain StaticDecorativeObjectType riding the shared "fence" Edge-blocking
/// primitive (see Edge/GameObject.BlockedEdges) that Statue already proves out - these tests confirm
/// Covers the fence decoration types in Data/decorations.json (Stage 1): each is a plain
/// StaticDecorativeObjectType riding the shared "fence" Edge-blocking primitive (see
/// Edge/GameObject.BlockedEdges) that Statue already proves out - these tests confirm
/// decorations.json parses with the intended image/Blocking/BlockedEdges, and that a full
/// rectangular enclosure built from them contains its interior except at a gate. No map-generation
/// placement exists yet - these types are only reachable by direct placement, as here.
Expand Down Expand Up @@ -94,7 +94,7 @@ bool expectedInfront
}

// Builds the same 3x3 enclosure (north wall with a center gate, west/east side walls, south
// wall) validated via the composite mockups in issue #86: a west-cap/opening/east-cap north row,
// wall) validated via the composite mockups: a west-cap/opening/east-cap north row,
// vertical west/east runs, and a corner/straight/corner south row.
[Fact]
public void RectangularEnclosureContainsItsInteriorExceptThroughTheGate()
Expand Down Expand Up @@ -150,9 +150,9 @@ public void PlacingWithoutAnOverrideUsesTheTypesDefaultLayer()
);
}

// The pillar reads as too slight visually to justify blocking anything (see
// dontrolle/BlazorRogue-internal#86 discussion) - purely a decorative two-tile flourish, with
// no gameplay effect at all. MapGeneratorBase.PlaceFencePillar is the intended way to place it.
// The pillar reads as too slight visually to justify blocking anything - purely a decorative
// two-tile flourish, with no gameplay effect at all. MapGeneratorBase.PlaceFencePillar is the
// intended way to place it.
[Fact]
public void FreestandingPillarIsPurelyDecorativeAndBlocksNothing()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
namespace BlazorRogue.Tests.World.Generation;

/// <summary>
/// Covers MapGeneratorBase.AddFenceEnclosures/PlaceFenceEnclosure (see
/// dontrolle/BlazorRogue-internal#86) - the procedural placement pass that fences off a random
/// rectangle of open floor, structured like AddLiquidPools (opt-in via a common.fence_enclosures
/// settings block, sampled-origin retry loop, skipped entirely when unconfigured).
/// Covers MapGeneratorBase.AddFenceEnclosures/PlaceFenceEnclosure - the procedural
/// placement pass that fences off a random rectangle of open floor, structured like AddLiquidPools
/// (opt-in via a common.fence_enclosures settings block, sampled-origin retry loop, skipped
/// entirely when unconfigured).
/// </summary>
public class FenceEnclosurePlacementTests
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
namespace BlazorRogue.Tests.World.Generation;

/// <summary>
/// A regression guard for the fence gallery debug level (see Game.ToggleDebugLevelView,
/// dontrolle/BlazorRogue-internal#86): as the fence catalog grows, a new type that makes
/// FenceGalleryMapGenerator run off the map edge or throw should fail here rather than only being
/// noticed the next time someone actually looks at the gallery in-browser.
/// A regression guard for the fence gallery debug level (see Game.ToggleDebugLevelView):
/// as the fence catalog grows, a new type that makes FenceGalleryMapGenerator run off the map edge
/// or throw should fail here rather than only being noticed the next time someone actually looks at
/// the gallery in-browser.
/// </summary>
public class FenceGalleryMapGeneratorTests
{
Expand Down
37 changes: 18 additions & 19 deletions World/Generation/FenceGalleryMapGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@
namespace BlazorRogue.World.Generation;

/// <summary>
/// Deterministic dev-only level showing every current fence_* decoration type (see
/// dontrolle/BlazorRogue-internal#86) - a swatch row (one tile per shape, in decorations.json's
/// declaration order) plus the validated 3x3 rectangular enclosure, so a new fence addition can be
/// eyeballed for regressions without hand-splicing test placement code. Reached in a running game
/// via Ctrl+D (debug mode) then Ctrl+G (see Game.ToggleDebugLevelView, GamePage.razor) whenever
/// game-config.json's "debug_level" points at this level's number; never part of normal level
/// progression - see Data/levels.json's "fence_gallery" entry.
/// Deterministic dev-only level showing every current fence_* decoration type - a swatch
/// row (one tile per shape, in decorations.json's declaration order) plus the validated 3x3
/// rectangular enclosure, so a new fence addition can be eyeballed for regressions without
/// hand-splicing test placement code. Reached in a running game via Ctrl+D (debug mode) then Ctrl+G
/// (see Game.ToggleDebugLevelView, GamePage.razor) whenever game-config.json's "debug_level" points
/// at this level's number; never part of normal level progression - see Data/levels.json's
/// "fence_gallery" entry.
/// </summary>
/// <remarks>
/// Unlike <see cref="TestMapGenerator"/>, this overrides <see cref="GenerateMap"/> itself rather
/// than just <see cref="CreateLayout"/>, skipping doors/liquid pools/random decorations/monsters
/// entirely - the gallery should stay quiet so the fence rows are the only thing to look at, with
/// one deliberate exception: a single goblin standing on the enclosure's west wall tile, for
/// manually checking that a blocked edge blocks combat as well as movement (see
/// dontrolle/BlazorRogue-internal#86 follow-up). Uses a fixed (not randomly-weighted) floor/wall
/// entirely - the gallery should stay quiet so the fence rows are the only thing to look at, with one
/// deliberate exception: a single goblin standing on the enclosure's west wall tile, for manually checking
/// that a blocked edge blocks combat as well as movement. Uses a fixed (not randomly-weighted) floor/wall
/// set so repeat visits render identically.
/// </remarks>
class FenceGalleryMapGenerator(
Expand Down Expand Up @@ -140,15 +139,15 @@ protected override Tuple<int, int> CreateLayout()
// through the gate rather than sitting still) standing on the east wall tile itself. That
// tile isn't Blocking for occupancy, only edge-blocked on its *outward* (east) side, so
// this is a legitimate reachable position, not a synthetic one - the same situation a
// wandering monster can end up in during real play. On the east side (close to the
// player's arrival point above) rather than the west, so there's less time for it to path
// out through the gate before you reach it. Walk to the companion tile immediately outside
// it (enclosureX0 + 3, enclosureY0 + 1) and press the move-west key: the goblin should be
// wandering monster can end up in during real play. On the east side (close to the player's
// arrival point above) rather than the west, so there's less time for it to path out
// through the gate before you reach it. Walk to the companion tile immediately outside it
// (enclosureX0 + 3, enclosureY0 + 1) and press the move-west key: the goblin should be
// neither attackable nor able to attack back, even though it's directly adjacent, because
// the fence's blocked edge sits between the two tiles (dontrolle/BlazorRogue-internal#86
// follow-up). If it's already slipped out through the gate by the time you arrive, that's
// the gate working as intended (fully walkable) - leave and re-enter the gallery (Ctrl+G
// twice) for a fresh goblin and try approaching more directly.
// the fence's blocked edge sits between the two tiles. If it's already slipped out through
// the gate by the time you arrive, that's the gate working as intended (fully walkable) -
// leave and re-enter the gallery (Ctrl+G twice) for a fresh goblin and try approaching more
// directly.
_ = AddMonsterAt(enclosureX0 + 2, enclosureY0 + 1, configuration.MonsterTypes["goblin"]);

// Sight radius is only game-config.json's player_sight_radius - may be too small to see the whole gallery from
Expand Down
16 changes: 8 additions & 8 deletions World/Generation/MapGeneratorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ bool IsPoolEligible(int x, int y, Tuple<int, int> playerPos)

/// <summary>
/// Places a few rectangular fence enclosures (see Data/decorations.json's fence_* types and
/// PlaceFenceEnclosure below, dontrolle/BlazorRogue-internal#86) if the level's
/// PlaceFenceEnclosure below) if the level's
/// <c>common.fence_enclosures</c> settings ask for them - absent settings (or a zero
/// <c>count_max</c>) mean none, same "opt in explicitly" default as <see cref="AddLiquidPools"/>.
/// Each enclosure is a rough rectangle sampled over existing floor tiles only, never over
Expand Down Expand Up @@ -638,7 +638,7 @@ bool IsWall(int x, int y) =>
/// fence_opening-repeated/fence_end_east along the top, fence_wall_west/fence_wall_east
/// repeated down both sides, fence_corner_sw/fence_straight-repeated/fence_corner_se along the
/// bottom - the same shape validated by FenceGalleryMapGenerator's fixed 3x3 example and the
/// composite mockups in dontrolle/BlazorRogue-internal#86. Also places a non-blocking companion
/// composite mockups. Also places a non-blocking companion
/// tile one column outside the footprint for every shape along the west/east sides - the side
/// walls (fence_wall_east_companion/fence_wall_west_companion), the top row's end caps
/// (fence_post_east/fence_post_west), and the bottom row's corners (fence_corner_sw_companion/
Expand Down Expand Up @@ -690,10 +690,10 @@ protected void PlaceFenceEnclosure(int x0, int y0, int width, int height, int ga

// fence_wall_west's rail sits at its own west edge and fence_wall_east's at its own
// east edge - each reads as a spindly single line alone, but the two interlock into a
// proper double-rail once adjacent (confirmed by compositing the source art, see
// dontrolle/BlazorRogue-internal#86). These companions are the same images, placed one
// column outside the enclosure's own footprint, but non-blocking - the enclosure's real
// blocking edge is still just the fence_wall_west/east column placed above.
// proper double-rail once adjacent (confirmed by compositing the source art). These
// companions are the same images, placed one column outside the enclosure's own
// footprint, but non-blocking - the enclosure's real blocking edge is still just the
// fence_wall_west/east column placed above.
PlaceFence(x0 - 1, y0 + dy, "fence_wall_east_companion");
PlaceFence(x0 + width, y0 + dy, "fence_wall_west_companion");
}
Expand All @@ -716,7 +716,7 @@ protected void PlaceFenceEnclosure(int x0, int y0, int width, int height, int ga
}

/// <summary>
/// Places one fence_* decoration (see Data/decorations.json, dontrolle/BlazorRogue-internal#86)
/// Places one fence_* decoration (see Data/decorations.json)
/// by id at (<paramref name="x"/>, <paramref name="y"/>).
/// </summary>
protected void PlaceFence(int x, int y, string typeId) =>
Expand Down Expand Up @@ -1271,7 +1271,7 @@ protected void PlaceFloor(int x, int y, TileSet floorSet)
/// <summary>
/// Places a freestanding decorative fence pillar spanning (<paramref name="x"/>,
/// <paramref name="y"/>) and the tile immediately east of it - the "fence_pillar_west"/
/// "fence_pillar_east" pair (see Data/decorations.json, dontrolle/BlazorRogue-internal#86) only
/// "fence_pillar_east" pair (see Data/decorations.json) only
/// reads correctly as two adjacent tiles, and doesn't block movement or light at all (it's too
/// slight visually to justify either) - purely a decorative flourish, unrelated to any actual
/// fence line. Callers must ensure both tiles are free floor themselves.
Expand Down
4 changes: 2 additions & 2 deletions World/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Map
readonly List<Moveable> monsters;
public IEnumerable<Moveable> Monsters => monsters;

// Tick-priority-queue turn scheduler (issue #84) - see PlayerTookTurn. Only awake monsters are
// Tick-priority-queue turn scheduler - see PlayerTookTurn. Only awake monsters are
// ever enqueued (via AIComponent.Wake -> EnqueueMonster); the player is never in this queue,
// since the player is always resolved directly by TakeTurn's dispatch rather than "popped".
// Per-Map-instance like monsters/moveables: Game.TransitionToLevel swaps Game.Map to a
Expand Down Expand Up @@ -652,7 +652,7 @@ void RecomputeVisibilityAndWakeMonstersIfChanged(bool stateChanged)
}

/// <summary>
/// Unified entry point for a single player turn - the one both the headless driver (issue #88)
/// Unified entry point for a single player turn - the one both the headless driver
/// and GamePage.razor drive: dispatches <paramref name="action"/> through the same handlers
/// <see cref="HandlePlayerMoveAction"/>/<see cref="HandlePlayerUseAction"/>/
/// <see cref="PickUpItemsAtPlayer"/>/<see cref="UseInventoryItem"/>/
Expand Down
Loading