Skip to content

Commit

Permalink
Fix edge case where units can retreat twice
Browse files Browse the repository at this point in the history
  • Loading branch information
Oliveriver committed Sep 16, 2024
1 parent 1859d7a commit d37f04b
Show file tree
Hide file tree
Showing 16 changed files with 115 additions and 63 deletions.
5 changes: 4 additions & 1 deletion client/src/components/world/orders/OrderPath.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ const OrderPath = ({
[OrderStatus.Success]: successMarkerId,
[OrderStatus.Failure]: failureMarkerId,
[OrderStatus.Invalid]: failureMarkerId,
[OrderStatus.Retreat]: retreatMarkerId,
[OrderStatus.RetreatNew]: newMarkerId,
[OrderStatus.RetreatSuccess]: retreatMarkerId,
[OrderStatus.RetreatFailure]: failureMarkerId,
[OrderStatus.RetreatInvalid]: failureMarkerId,
}[status];

return (
Expand Down
15 changes: 8 additions & 7 deletions client/src/hooks/useOrderEntryReducer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const handleBasicOrderCreation = (
...state,
currentOrder: {
$type: OrderType.Move,
status: OrderStatus.New,
status: unit.mustRetreat ? OrderStatus.RetreatNew : OrderStatus.New,
unit,
location,
destination: null,
Expand All @@ -145,7 +145,7 @@ const handleBasicOrderCreation = (
...filteredOrders,
{
$type: OrderType.Hold,
status: OrderStatus.New,
status: unit.mustRetreat ? OrderStatus.RetreatNew : OrderStatus.New,
unit,
location,
},
Expand Down Expand Up @@ -194,7 +194,7 @@ const handleBasicOrderCreation = (
...state,
currentOrder: {
$type: OrderType.Support,
status: OrderStatus.New,
status: unit.mustRetreat ? OrderStatus.RetreatNew : OrderStatus.New,
unit,
location,
destination: null,
Expand Down Expand Up @@ -247,7 +247,7 @@ const handleBasicOrderCreation = (
...state,
currentOrder: {
$type: OrderType.Convoy,
status: OrderStatus.New,
status: unit.mustRetreat ? OrderStatus.RetreatNew : OrderStatus.New,
unit,
location,
destination: null,
Expand Down Expand Up @@ -302,7 +302,7 @@ const handleBasicOrderCreation = (
...filteredOrders,
{
$type: OrderType.Disband,
status: OrderStatus.New,
status: OrderStatus.RetreatNew,
unit,
location,
},
Expand Down Expand Up @@ -346,7 +346,7 @@ const handleInputModeChange = (
...orders,
{
$type: OrderType.Hold,
status: OrderStatus.New,
status: currentOrder.status,
unit: currentOrder.unit,
location: currentOrder.location,
},
Expand Down Expand Up @@ -431,7 +431,8 @@ const orderEntryReducer = (
highlightedOrder:
state.orders.find(
(order) =>
getOrderKey(order) === `${getLocationKey(action.location)} ${OrderStatus.New}`,
getOrderKey(order) === `${getLocationKey(action.location)} ${OrderStatus.New}` ||
getOrderKey(order) === `${getLocationKey(action.location)} ${OrderStatus.RetreatNew}`,
) ?? null,
};
case OrderEntryActionType.HighlightStop:
Expand Down
1 change: 0 additions & 1 deletion client/src/hooks/useSelectLocation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ const canSelectMajorLocation = (

if (isRetreatTurn(world)) {
const canStartRetreat =
isActiveBoard &&
(currentOrder === null || currentOrder.unit === null) &&
(currentMode === InputMode.None ||
currentMode === InputMode.Move ||
Expand Down
10 changes: 8 additions & 2 deletions client/src/types/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export enum OrderStatus {
Success = 'Success',
Failure = 'Failure',
Invalid = 'Invalid',
Retreat = 'Retreat',
RetreatNew = 'RetreatNew',
RetreatSuccess = 'RetreatSuccess',
RetreatFailure = 'RetreatFailure',
RetreatInvalid = 'RetreatInvalid',
}

type Hold = {
Expand Down Expand Up @@ -78,7 +81,10 @@ export const getOrderColour = (order: Order | OrderStatus, isHighlighted: boolea
[OrderStatus.Success]: colours.orderSuccess,
[OrderStatus.Failure]: colours.orderFailure,
[OrderStatus.Invalid]: colours.orderFailure,
[OrderStatus.Retreat]: colours.orderRetreat,
[OrderStatus.RetreatNew]: colours.orderNew,
[OrderStatus.RetreatSuccess]: colours.orderRetreat,
[OrderStatus.RetreatFailure]: colours.orderFailure,
[OrderStatus.RetreatInvalid]: colours.orderFailure,
}[typeof order === 'object' ? order.status : order];
};

Expand Down
6 changes: 5 additions & 1 deletion server/Adjudication/Evaluation/Evaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void EvaluateOrders()

private List<Order> GetActiveOrders()
{
var newOrders = world.Orders.Where(o => o.Status == OrderStatus.New).ToList();
var newOrders = world.Orders.Where(o => o.Status is OrderStatus.New or OrderStatus.RetreatNew).ToList();

if (world.HasRetreats)
{
Expand Down Expand Up @@ -99,6 +99,10 @@ private void SetSafetyFailures()
{
order.Status = OrderStatus.Failure;
}
else if (order.Status == OrderStatus.RetreatNew)
{
order.Status = OrderStatus.RetreatFailure;
}
}
}
}
15 changes: 14 additions & 1 deletion server/Adjudication/Evaluation/MovementEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ o is Move m
}

var unit = order.Unit;

var existingRetreat = world.Orders.FirstOrDefault(o =>
o.Unit == unit
&& o.Status is OrderStatus.RetreatNew
or OrderStatus.RetreatSuccess
or OrderStatus.RetreatFailure
or OrderStatus.RetreatInvalid);

if (existingRetreat != null)
{
world.Orders.Remove(existingRetreat);
}

var canEscape = CanEscape(unit, stationaryOrders, moves.ToList());

if (canEscape)
Expand All @@ -64,7 +77,7 @@ o is Move m

var disband = new Disband
{
Status = OrderStatus.Retreat,
Status = OrderStatus.RetreatSuccess,
Unit = unit,
UnitId = unit.Id,
Location = unit.Location,
Expand Down
13 changes: 10 additions & 3 deletions server/Adjudication/Evaluation/Resolution/StrengthCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ private void CalculateMoveHoldStrength(Move move)
switch (move.Status)
{
case OrderStatus.Success:
case OrderStatus.Retreat:
{
move.HoldStrength.Max = 0;
move.HoldStrength.Min = 0;
Expand All @@ -68,12 +67,17 @@ private void CalculateMoveHoldStrength(Move move)
break;
}
case OrderStatus.New:
default:
{
move.HoldStrength.Max = 1;
move.HoldStrength.Min = 0;
break;
}
case OrderStatus.RetreatNew:
case OrderStatus.RetreatSuccess:
case OrderStatus.RetreatFailure:
case OrderStatus.RetreatInvalid:
default:
break;
}
}

Expand Down Expand Up @@ -221,7 +225,10 @@ private void AddSupportStrength(OrderStrength strength, List<Support> supports)
}
case OrderStatus.Invalid:
case OrderStatus.Failure:
case OrderStatus.Retreat:
case OrderStatus.RetreatNew:
case OrderStatus.RetreatSuccess:
case OrderStatus.RetreatFailure:
case OrderStatus.RetreatInvalid:
default:
break;
}
Expand Down
20 changes: 10 additions & 10 deletions server/Adjudication/Evaluation/RetreatEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ private void EvaluateDisbands()
var disbands = activeOrders.OfType<Disband>().Where(d => d.Location.Phase != Phase.Winter);
foreach (var disband in disbands)
{
disband.Status = OrderStatus.Retreat;
disband.Status = OrderStatus.RetreatSuccess;
}
}

private void EvaluateRetreatMoves()
{
var retreats = activeOrders.OfType<Move>().Where(m => m.Unit.MustRetreat && m.Status != OrderStatus.Invalid).ToList();
var retreats = activeOrders.OfType<Move>().Where(m => m.Unit.MustRetreat && m.Status != OrderStatus.RetreatInvalid).ToList();
var holds = world.Orders.OfType<Hold>();
var moves = world.Orders.OfType<Move>();
var supports = world.Orders.OfType<Support>();
Expand Down Expand Up @@ -63,11 +63,11 @@ private void EvaluateRetreatMoves()

if (isDestinationOccupied || hadBounceInDestination || hasOpposingMove)
{
retreat.Status = OrderStatus.Failure;
retreat.Status = OrderStatus.RetreatFailure;

var disband = new Disband
{
Status = OrderStatus.Retreat,
Status = OrderStatus.RetreatSuccess,
Unit = retreat.Unit,
UnitId = retreat.UnitId,
Location = retreat.Location,
Expand All @@ -77,18 +77,18 @@ private void EvaluateRetreatMoves()
}
}

var remainingRetreats = retreats.Where(r => r.Status == OrderStatus.New).ToList();
var remainingRetreats = retreats.Where(r => r.Status == OrderStatus.RetreatNew).ToList();

foreach (var retreat in remainingRetreats)
{
var hasOpposingRetreat = remainingRetreats.Any(r => r != retreat && r.Destination == retreat.Destination);
if (hasOpposingRetreat)
{
retreat.Status = OrderStatus.Failure;
retreat.Status = OrderStatus.RetreatFailure;

var disband = new Disband
{
Status = OrderStatus.Retreat,
Status = OrderStatus.RetreatSuccess,
Unit = retreat.Unit,
UnitId = retreat.UnitId,
Location = retreat.Location,
Expand All @@ -98,7 +98,7 @@ private void EvaluateRetreatMoves()
}
else
{
retreat.Status = OrderStatus.Retreat;
retreat.Status = OrderStatus.RetreatSuccess;
}
}
}
Expand All @@ -112,11 +112,11 @@ private void AddMissingDisbands()
foreach (var unit in retreatingUnits)
{
var order = activeOrders.FirstOrDefault(o => o.Unit == unit);
if (order == null || order.Status != OrderStatus.Retreat)
if (order == null || order.Status != OrderStatus.RetreatSuccess)
{
var disband = new Disband
{
Status = OrderStatus.Retreat,
Status = OrderStatus.RetreatSuccess,
Unit = unit,
UnitId = unit.Id,
Location = unit.Location,
Expand Down
10 changes: 10 additions & 0 deletions server/Adjudication/Evaluation/TouchedOrdersFinder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Entities;
using Enums;

namespace Adjudication;

Expand Down Expand Up @@ -29,6 +30,15 @@ private class DepthFirstSearch(World world, List<Order> newOrders, AdjacencyVali

public void AddTouchedOrders(Order order)
{
if (order.Status is OrderStatus.RetreatNew
or OrderStatus.RetreatSuccess
or OrderStatus.RetreatFailure
or OrderStatus.RetreatInvalid)
{
TouchedOrders.Remove(order);
return;
}

if (!TouchedOrders.Contains(order))
{
TouchedOrders.Add(order);
Expand Down
4 changes: 2 additions & 2 deletions server/Adjudication/Execution/Executor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ private Board AdvanceMajorBoard(Board previousBoard)
var year = previousBoard.Year;
var phase = previousBoard.Phase.NextPhase();

var disbands = world.Orders.OfType<Disband>().Where(d => d.Status == OrderStatus.Retreat);
var disbands = world.Orders.OfType<Disband>().Where(d => d.Status == OrderStatus.RetreatSuccess);

var holds = world.Orders.Where(o =>
(o is not Move || o.Status != OrderStatus.Success)
&& !disbands.Any(d => d.Unit == o.Unit)
&& previousBoard.Contains(o.Location)
&& !originalRetreatingUnits.Contains(o.Unit));
var incomingMoves = world.Orders.OfType<Move>().Where(m =>
(m.Status == OrderStatus.Success || m.Status == OrderStatus.Retreat)
(m.Status == OrderStatus.Success || m.Status == OrderStatus.RetreatSuccess)
&& previousBoard.Contains(m.Destination));

var units = new List<Unit>();
Expand Down
8 changes: 4 additions & 4 deletions server/Adjudication/Validation/Validator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ private void ValidateRetreats()
retreat.Status = retreat switch
{
Move move => adjacencyValidator.IsValidDirectMove(move.Unit, move.Location, move.Destination)
? OrderStatus.New
: OrderStatus.Invalid,
Disband => OrderStatus.New,
_ => OrderStatus.Invalid,
? OrderStatus.RetreatNew
: OrderStatus.RetreatInvalid,
Disband => OrderStatus.RetreatNew,
_ => OrderStatus.RetreatInvalid,
};
}
}
Expand Down
5 changes: 4 additions & 1 deletion server/Enums/OrderStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ public enum OrderStatus
Success,
Failure,
Invalid,
Retreat,
RetreatNew,
RetreatSuccess,
RetreatFailure,
RetreatInvalid,
}
2 changes: 1 addition & 1 deletion server/Tests/DATC_F.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ public void DATC_F_7()
new Adjudicator(world, false, MapFactory, DefaultWorldFactory).Adjudicate();

// Assert
englishRetreat.Status.Should().Be(OrderStatus.Retreat);
englishRetreat.Status.Should().Be(OrderStatus.RetreatSuccess);

board.Next().ShouldHaveUnits(
[
Expand Down
Loading

0 comments on commit d37f04b

Please sign in to comment.