Skip to content

Instantly share code, notes, and snippets.

@sdebaun

sdebaun/one-level-up.cs

Last active Aug 18, 2020
Embed
What would you like to do?
/*
# GetRunMovesForReserveUnit(playerId, Unit, isVanguard)
What is using it:
- GetHexesForVanguard(Unit)
-- GetRunMovesForReserveUnit(unit.owningPlayerId, unit, true)
- GetActionableHexesForReserveUnit(PTD, Unit, HS<HT> x3)
-- GetRunMovesForReserveUnit(unit.owningPlayerId, unit, false)
What it is doing:
- playerId is irrelevant, both callers are just passing unit.owningPlayerId
- it actually contains logic to check vanguard and use 2 instead of actual walks
- its pulling in a set of start hexes from gm.ReservesForPlayer(playerId)
- so its effectively: (Unit, List<Hex>) => List<Hex>
- delegating actual generation of list to GetHexesInRange(playerId, ht, min, max, allTerrain, vanguard, vanguard)
# GetJumpMovesForReserveUnit(Unit)
What is using it:
- GetActionableHexesForReserveUnit(PTD, Unit, HS<HT> x3)
-- GetJumpMovesForReserveUnit(unit)
- MoveAction:DetermineMovementPathForReserveUnit(isVanguard, PTD) ???
-- GetJumpMovesForReserveUnit(unit)
What it is doing:
- also pulling in gm.ReservesForPlayer
- effectively making it (Unit, List<Hex>) => List<Hex>
- and delegating to GetHexesInRangeForJump(unit.owningPlayerId, ht, unit)
# GetInsertMovesForReserveUnit(playerId, PTD)
What is using it:
- GetActionableHexesForReserveUnit(PTD, Unit, HS<HT> x3)
-- GetInsertMovesForReserveUnit(unit.owningPlayerId, turnData)
- MoveAction:DetermineMovementPathForReserveUnit(isVanguard, PTD)
-- GetInsertMovesForReserveUnit(baseData.playerId, turnData)
What it is doing:
- getting a list of potential source hexes from PlayersUnitsOnMap(playerId), similar to gm.ReservesForPlayer
- effectively List<Hex> => List<Hex> (no Unit bc dont need walks or runs or nuttin)
- uses HexMap.GetNeighbors(ht) and filters out hts with units or in reserves, nice
# GetHexesForVanguard(Unit)
What is using it:
- ONLY GetActionableHexesForReserveUnit (covered above)
What it is doing:
- does checking of whether or not a vanguard move can be made with that unit
- and then passes through to GetRunMovesForReserveUnit with a vanguard=true flag
# Next steps
## GetHexesForVanguard [ValidVanguardTargets]
playerId => List<Hex>
dont need to use move logic, its just the first two rows
returns map.hexes
.Where(playerId == 1 ? Hex.InRows(1, 2) : Hex.InRows(8, 9))
// prolly better to cache the result of the above, it doesnt change
.Where(Hex.IsEmpty)
# GetRunMovesForReserveUnit(playerId, Unit, isVanguard)
# GetJumpMovesForReserveUnit(Unit)
# GetInsertMovesForReserveUnit(playerId, PTD)
All of these are special in the same way bc a unit coming from reserve
effectively starts their move from multiple hexes
so at one level the signature is:
(List<Hex> starts) => List<Hex> dests
so we can think of it as eg:
var reserveStarts = map.ReserveHexesFor(playerId)
var insertStarts = map.ValidBeaconsFor(unit.owningPlayerId)
var walkTargets = reserveStarts.SelectMany(start => GetHexesInRange(...)).Unique()
var runTargets = reserveStarts.SelectMany(start => GetHexesInRange(...)).Unique()
var jumpTargets = reserveStarts.SelectMany(start => GetHexesInRangeForJump(...)).Unique()
var insertTargets = insertStarts.SelectMany(start => GetHexesInRangeForInsertion(...))
new function to mirror abstractionso of InRange, InRangeForJump
public List<Hex> GetHexesInRangeForInsertion(playerId, ht) =>
GetNeighbors(ht).Where(Hex.IsEmpty)
And then see the commonalities:
List<Hex> (List<Hex> starts) => starts.SelectMany(Func<Hex, List<Hex> selector).Unique()
lets make those selectors into rules
public Func<Hex, List<Hex>> WalkRules(Unit unit) =>
(Hex hex) =>
GetHexesInRange(unit.owningPlayerId, hex, 1, (unit.jumpMoves > 0) ? 1 : unit.walkMoves, unit.allTerrain, false, false)
// logic wont work for units with jump+walk eg AH
public Func<Hex, List<Hex>> RunRules(Unit unit) =>
(Hex hex) =>
GetHexesInRange(unit.owningPlayerId, hex, 1 + unit.walkMoves, 1 + unit.walkMoves + unit.runMoves, unit.allTerrain, false, false)
public Func<Hex, List<Hex>> JumpRules(Unit unit) =>
(Hex hex) =>
GetHexesInRangeForJump(unit.owningPlayerId, hex, unit)
public Func<Hex, List<Hex>> InsertionRules() =>
(Hex hex) =>
GetNeighbors(hex).Where(Hex.IsEmpty)
oh but wait, we dont have the hoof it rule
public Func<Hex, List<Hex>> HoofItRules() =>
(Hex hex) =>
GetHexesInRange(unit.owningPlayerId, hex, 0, 1, unit.allTerrain, false, false)
and now:
var reserveStarts = map.ReserveHexesFor(unit.owningPlayerId)
var insertStarts = map.ValidBeaconsFor(unit.owningPlayerId, turnData?)
var walkTargets = reserveStarts.SelectMany(WalkRules(unit)).Unique()
var runTargets = reserveStarts.SelectMany(RunRules(unit)).Unique()
var jumpTargets = reserveStarts.SelectMany(JumpRules(unit)).Unique()
var insertTargets = insertStarts.SelectMany(start => GetHexesInRangeForInsertion(...))
also note how we've unified reserve vs onboard moves
var walkTargets = WalkRules(unit)(unit.hex)
etc.
and why i prefer terser every-other-language syntax:
var walks = reserves.Map(WalkRules(unit)).Flatten().Uniq()
and getting crazy with functional
var flatMapUnique = selector => pipe(map(selector), flatten, uniq)
var starts = unit.onMap ? new List<Hex> { unit.hex } : map.ReservesForPlayer(unit.owningPlayerId)
var walkDestsFromStarts = flatMapUnique(WalkRules(unit))
var walks = walkDestsFromStarts(starts)
lets make those selectors into rules V2
public Func<Hex, List<Hex>> WalkFinderFor(Unit unit) =>
(Hex hex) =>
GetHexesInRange(unit.owningPlayerId, hex, 1, (unit.jumpMoves > 0) ? 1 : unit.walkMoves, unit.allTerrain, false, false)
// logic wont work for units with jump+walk eg AH
public Func<Hex, List<Hex>> RunFinderFor(Unit unit) =>
(Hex hex) =>
GetHexesInRange(unit.owningPlayerId, hex, 1 + unit.walkMoves, 1 + unit.walkMoves + unit.runMoves, unit.allTerrain, false, false)
public Func<Hex, List<Hex>> JumpFinderFor(Unit unit) =>
(Hex hex) =>
GetHexesInRangeForJump(unit.owningPlayerId, hex, unit)
public Func<Hex, List<Hex>> InsertionFinderFor() =>
(Hex hex) =>
GetNeighbors(hex).Where(Hex.IsEmpty)
var starts = unit.isInReserves ?
map.ReserveStartsFor(unit.owningPlayerId) :
new List<Hex> { unit.hex };
private List<Hex> FindMoveTargets(Func<Hex, List<Hex>> selector, List<Hex> source) =>
source.SelectMany(selector).Unique();
var walks = FindMoveTargets(WalkFinderFor(unit), starts);
var runs = FindMoveTargets(RunFinderFor(unit), starts);
var jumps = FindMoveTargets(JumpFinderFor(unit), starts);
var insertions = FindMoveTargets(InsertionFinder(), map.ValidBeaconsFor(turnData, unit.owningPlayerId));
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment