private List <Vector2> CalcDestinations( PieceEV pieceEV, List <PieceEV> allPieces, IEntitiesDB entitiesDB, bool excludeCheckViolations = false, bool excludeObstructedDestinations = true) { bool useGoldMovement = IsOpponentPieceDirectlyBelow(pieceEV, allPieces); IPieceData pieceData = CreatePieceData(pieceEV, useGoldMovement); List <Vector2> returnValue = AdjustAndExcludeSingleDestinations( pieceData, pieceEV, allPieces, excludeObstructedDestinations); returnValue.AddRange(AdjustJumpDestinations( pieceData, pieceEV, allPieces )); returnValue.AddRange(AdjustAndExcludeLineDestinations( pieceData, pieceEV, allPieces, excludeObstructedDestinations)); if (excludeCheckViolations) // Should only happen for turn player { ExcludeCheckViolations(pieceEV, returnValue, allPieces, entitiesDB); } return(returnValue); }
private IEnumerable <Vector2> AdjustAndExcludeLineDestinations( IPieceData pieceData, PieceEV pieceEV, List <PieceEV> allPieces, bool excludeObstructedDestinations) { int tier = CalcTierToUse(pieceEV, allPieces); List <Vector2> vectors = pieceData.Tiers[tier - 1].Line; List <Vector2> returnValue = new List <Vector2>(); foreach (Vector2 vector in vectors) { List <Vector2> line = ExpandLineVector(vector); AdjustRawDataWithPieceLocationAndDirection(pieceEV, line); ExcludeOutOfBoard(line); if (excludeObstructedDestinations) // Do NOT allow destinations other pieces in the way { ExcludeDestinationsWithObstructingPieces(pieceEV, line, allPieces); } // Always exclude these scenarios ExcludeDestinationsAtCannotBeStackedPieces(line, allPieces); ExcludeTowerDestinationsWithSameTypeAndTeam(pieceEV, line, allPieces); returnValue.AddRange(line); } return(returnValue); }
public bool ForcedRearrangementCanResolveThreats( PieceEV commander, PieceEV pieceToDrop, List <PieceEV> actualThreats, List <PieceEV> allPieces, IEntitiesDB entitiesDB) { bool returnValue = false; // Test drop each valid location to see if threats resolved for (int rank = turnService.GetMinRankWithinTerritory(commander.PlayerOwner.PlayerColor); rank <= turnService.GetMaxRankWithinTerritory(commander.PlayerOwner.PlayerColor); ++rank) { for (int file = 0; file < BoardConst.NUM_FILES_RANKS; ++file) { Vector2 location = new Vector2(file, rank); List <PieceEV> piecesAtLocation = pieceFindService.FindPiecesByLocation(location, entitiesDB); if (IsValidDrop(piecesAtLocation, entitiesDB) && DoesDropResolveCheck( commander, pieceToDrop, location, piecesAtLocation, actualThreats, allPieces, entitiesDB)) { returnValue = true; break; } } } return(returnValue); }
private bool CheckDropToken(ref HandPieceEV handPiece, ref TileEV destinationTile, PieceSide?sideToCheck) { TurnEV currentTurn = turnService.GetCurrentTurnEV(entitiesDB); PieceEV pieceToDrop = pieceFindService.FindFirstPieceByLocationAndType( BoardConst.HAND_LOCATION, handPiece.HandPiece.PieceType, handPiece.HandPiece.Back, entitiesDB); bool returnValue = !currentTurn.Check.CommanderInCheck; if (!returnValue) // Commander is in check { bool singleSideValid = sideToCheck.HasValue && checkService.DropReleasesCheck( pieceToDrop, destinationTile.Location.Location, currentTurn, sideToCheck.Value, entitiesDB); bool eitherSideValid = !sideToCheck.HasValue && ( checkService.DropReleasesCheck( pieceToDrop, destinationTile.Location.Location, currentTurn, PieceSide.FRONT, entitiesDB) || checkService.DropReleasesCheck( pieceToDrop, destinationTile.Location.Location, currentTurn, PieceSide.BACK, entitiesDB)); returnValue = singleSideValid || eitherSideValid; } return(returnValue); }
private bool IsValidEarthLinkDrop(List <PieceEV> piecesAtLocation, PieceSide?side) { // Since this is called after IsEmptyTile with an OR condition, we know there is at least one piece on the tile PieceEV topPiece = piecesAtLocation[piecesAtLocation.Count - 1]; return(topPiece.Tier.Tier < 3 && AbilityToPiece.HasAbility(GetEarthLinkAbilityType(side), topPiece.Piece.PieceType)); }
private List <PieceEV> FindEnemyThreats(PieceEV commander, PieceEV pieceToMove, List <PieceEV> allPieces, IEntitiesDB entitiesDB) { List <PieceEV> enemyPieces = allPieces.Where(piece => piece.PlayerOwner.PlayerColor != commander.PlayerOwner.PlayerColor).ToList(); List <PieceEV> piecesAtCurrentLocation = allPieces.Where(piece => // Min size one piece.Location.Location == pieceToMove.Location.Location).ToList(); List <PieceEV> returnValue = enemyPieces.Where(piece => piece.Tier.TopOfTower && (piece.Location.Location == commander.Location.Location || CalcUnobstructedDestinationTiles(piece, allPieces, entitiesDB).Contains(commander.Location.Location)) ) .ToList(); // One more scenario: Moving the pieceToMove could expose the underlying enemy piece that could check the Commander // That piece is UNABLE check the commander if other pieces obstruct it if (piecesAtCurrentLocation.Count > 1) { PieceEV pieceToEvaluate = piecesAtCurrentLocation[piecesAtCurrentLocation.Count - 2]; if (pieceToEvaluate.PlayerOwner.PlayerColor != commander.PlayerOwner.PlayerColor && CalcUnobstructedDestinationTiles(pieceToEvaluate, allPieces, entitiesDB).Contains(commander.Location.Location)) { returnValue.Add(pieceToEvaluate); } } return(returnValue); }
private void OnPressed(int entityId, int pieceReferenceId) { PieceEV piece = FindAssociatedPiece(pieceReferenceId); TowerAnswerState nextAction = DecideNextAction(piece); PerformNextAction(nextAction, piece); }
public int CalcNumCommanderThreats(PlayerColor commanderColor, IEntitiesDB entitiesDB) { int returnValue = 0; PieceEV commander = pieceFindService.FindCommander(commanderColor, entitiesDB); List <PieceEV> allPieces = pieceFindService.FindAllBoardPieces(entitiesDB).ToList(); List <PieceEV> commanderTowerPieces = pieceFindService.FindPiecesByLocation(commander.Location.Location, entitiesDB); if (IsCommanderBuried(commander, commanderTowerPieces)) { // Commander cannot be captured this turn return(returnValue); } if (IsCommanderInDangerFromBelow(commander, commanderTowerPieces)) { returnValue++; } if (commander.Tier.TopOfTower) { List <PieceEV> enemyPieces = allPieces.Where(piece => piece.PlayerOwner.PlayerColor != commanderColor && piece.Tier.TopOfTower).ToList(); foreach (PieceEV enemy in enemyPieces) { if (CalcDestinationTileLocations(enemy, entitiesDB, allPieces, false).Contains(commander.Location.Location)) { returnValue++; } } } return(returnValue); }
private bool ShouldRemoveDestination( PieceEV pieceToCalc, Vector2 destination, List <PieceEV> allPieces, bool canIgnoreFriendlyPieces) { bool returnValue = false; Vector2 pieceLocation = pieceToCalc.Location.Location; Vector2 increment = new Vector2( pieceLocation.x == destination.x ? 0 : (pieceLocation.x - destination.x) / Math.Abs(pieceLocation.x - destination.x), pieceLocation.y == destination.y ? 0 : (pieceLocation.y - destination.y) / Math.Abs(pieceLocation.y - destination.y) ); Vector2 evalLocation = pieceLocation - increment; while (evalLocation != destination) { int numPiecesBarringPath = allPieces.Where(piece => evalLocation == piece.Location.Location && (!canIgnoreFriendlyPieces || (piece.PlayerOwner.PlayerColor != pieceToCalc.PlayerOwner.PlayerColor || (piece.Tier.TopOfTower && AbilityToPiece.HasAbility(PreMoveAbility.CANNOT_BE_STACKED, piece.Piece.PieceType))) )).Count(); if (numPiecesBarringPath > 0) { returnValue = true; break; } evalLocation -= increment; } return(returnValue); }
/** * Potentially modify param destinations, by removing locations with piece(s) in the way * * Some destinations are in different rank AND file as pieceToCalc's current location */ private void ExcludeDestinationsWithObstructingPieces( PieceEV pieceToCalc, List <Vector2> destinations, List <PieceEV> allPieces, bool canIgnoreFriendlyPieces = false) { List <Vector2> destinationsToRemove = new List <Vector2>(); /* * Types of destinations * * One tile away, horizontally, vertically, or diagonally * More than one tile away, * * Same rank, different file * * Same file, different rank * * Different rank, different file */ // for loop hopLocations, since that count will often be less than allPiece's count foreach (Vector2 destination in destinations) { if (ShouldRemoveDestination(pieceToCalc, destination, allPieces, canIgnoreFriendlyPieces)) { destinationsToRemove.Add(destination); } } foreach (Vector2 removeDestination in destinationsToRemove) { destinations.Remove(removeDestination); } }
private int CalcTierToUse(PieceEV piece, List <PieceEV> allPieces) { return(CanMobileRangeExpansion(piece) && (IsAffectedByMobileRangeExpansionRadial(piece.PlayerOwner.PlayerColor, piece.Location.Location, allPieces) || IsAffectedByMobileRangeExpansionLine(piece.PlayerOwner.PlayerColor, piece.Location.Location, allPieces)) ? Math.Min(piece.Tier.Tier + 1, 3) : piece.Tier.Tier); }
private void MovePawnToHand(PieceEV piece) { pieceSetService.SetPieceLocationToHandLocation(piece, entitiesDB); piece.Visibility.IsVisible.value = false; handService.AddPieceToHand(piece, entitiesDB); }
public bool IsSubstitutionPossible(PieceEV?clickedPiece, TileEV?clickedTile, IEntitiesDB entitiesDB) { // Remember, Commander cannot run to Samurai during check, b/c that's a violation of a different rule /* Conditions: * piece clicked * not a destination tile (user is clicking this piece to access substitution ability or click-highlight it) * commander in check * samurai (has substitution ability) * piece is topOfTower * piece tier == 1 * piece is adjacent to Commander vertically or horizontally * substitution would resolve check */ TurnEV currentTurn = turnService.GetCurrentTurnEV(entitiesDB); PieceEV commander = pieceFindService.FindCommander(currentTurn.TurnPlayer.PlayerColor, entitiesDB); return(currentTurn.Check.CommanderInCheck && clickedPiece.HasValue && clickedTile.HasValue && (!clickedTile.Value.Tile.PieceRefEntityId.HasValue || clickedTile.Value.Tile.PieceRefEntityId.Value == 0) && AbilityToPiece.HasAbility(OtherMoveAbility.SUBSTITUTION, clickedPiece.Value.Piece.PieceType) && clickedPiece.Value.Tier.Tier == 1 && clickedPiece.Value.Tier.TopOfTower && IsAdjacentLocationToCommander(clickedPiece.Value, commander) && DoesSubstitutionResolveCheck(clickedPiece.Value, commander, entitiesDB)); }
private bool DropPossible( HandPieceEV handPiece, Vector2 location, PlayerColor playerColor, DropCheckmateLevel recursionLevel, IEntitiesDB entitiesDB) { List <PieceEV> piecesAtLocation = pieceFindService.FindPiecesByLocation(location, entitiesDB); bool isFrontValid = preDropService.IsValidFrontDrop(ref handPiece, location, piecesAtLocation, entitiesDB); bool isBackValid = preDropService.IsValidBackDrop(ref handPiece, location, piecesAtLocation, entitiesDB); PieceEV pieceToDrop = pieceFindService.FindFirstPieceByLocationAndType( BoardConst.HAND_LOCATION, handPiece.HandPiece.PieceType, handPiece.HandPiece.Back, entitiesDB); return((isFrontValid && DropReleasesCheck( pieceToDrop, location, playerColor, PieceSide.FRONT, handPiece, recursionLevel, entitiesDB)) || (isBackValid && DropReleasesCheck( pieceToDrop, location, playerColor, PieceSide.BACK, handPiece, recursionLevel, entitiesDB))); }
public void Step(ref CapturePieceStepState token, int condition) { PieceEV pieceToCapture = token.PieceToCapture; pieceSetService.SetPieceLocationToHandLocation(pieceToCapture, entitiesDB); pieceToCapture.Visibility.IsVisible.value = false; }
private void ChangeTileColor(List <TileEV> tilesToChange, ref PressStepState token) { bool isClicked = token.PiecePressState == PiecePressState.CLICKED; PieceEV piece = pieceFindService.FindPieceEV(token.PieceEntityId, entitiesDB); int pieceIdtoken = token.PieceEntityId; HighlightState newHighlightState = HighlightService.CalcClickHighlightState(piece.PlayerOwner.PlayerColor); TurnEV currentTurn = turnService.GetCurrentTurnEV(entitiesDB); bool doesPieceBelongToTurnPlayer = currentTurn.TurnPlayer.PlayerColor == piece.PlayerOwner.PlayerColor; foreach (TileEV tileEV in tilesToChange) { entitiesDB.ExecuteOnEntity( tileEV.ID, (ref TileEV tileToChange) => { tileToChange.Highlight.IsHighlighted = isClicked; if (doesPieceBelongToTurnPlayer) { tileToChange.Tile.PieceRefEntityId = isClicked ? (int?)pieceIdtoken : null; } if (isClicked) { tileToChange.Highlight.CurrentColorStates.Add(newHighlightState); } else { tileToChange.Highlight.CurrentColorStates.Remove(newHighlightState); } }); tileEV.ChangeColorTrigger.PlayChangeColor = true; } }
private bool ImmobileCapturePossible(PieceEV piece, PlayerColor playerColor, IEntitiesDB entitiesDB) { List <PieceEV> towerPieces = pieceFindService.FindPiecesByLocation(piece.Location.Location, entitiesDB); return(immobileCaptureService.ImmobileCapturePossible(towerPieces, playerColor, entitiesDB) && immobileCaptureService.NoCheckViolationsExist(towerPieces, true, entitiesDB)); }
public bool DropReleasesCheck( PieceEV pieceToDrop, Vector2 location, TurnEV turn, PieceSide side, IEntitiesDB entitiesDB) { bool returnValue = false; PieceEV?topPieceAtLocation = pieceFindService.FindTopPieceByLocation(location, entitiesDB); pieceSetService.SetTopOfTowerToFalse(topPieceAtLocation, entitiesDB); int tier = topPieceAtLocation.HasValue ? topPieceAtLocation.Value.Tier.Tier + 1 : 1; pieceSetService.SetPieceLocationAndTier(pieceToDrop, location, tier, entitiesDB); pieceSetService.SetPiecePlayerOwner(pieceToDrop, turn.TurnPlayer.PlayerColor, entitiesDB); pieceSetService.SetPieceSide(pieceToDrop, side, entitiesDB); returnValue = !IsCommanderInCheck(turn.TurnPlayer.PlayerColor, entitiesDB); pieceSetService.SetPieceLocationToHandLocation(pieceToDrop, entitiesDB); if (topPieceAtLocation.HasValue) { pieceSetService.SetTopOfTower(topPieceAtLocation.Value, entitiesDB); } return(returnValue); }
public bool DoesLowerTierThreatenCommander( PieceEV commander, PieceEV enemyPiece, PieceEV secondFromTopEnemyPiece, List <PieceEV> towerPieces, IEntitiesDB entitiesDB) { // If middle piece is lance, Forced Rearrangement could potentially resolve or prevent check // NOTE: Below foreach loop causes invalid tier values, I'm just too lazy too deal with it right now foreach (PieceEV piece in towerPieces) { piece.Tier.Tier--; } bool returnValue = commander.Tier.TopOfTower && destinationTileService.CalcDestinationTileLocations(enemyPiece, entitiesDB, null, false).Contains(commander.Location.Location); if (returnValue && IsForcedRearrangementPossible(secondFromTopEnemyPiece)) { returnValue = DoesForcedRearrangementResolveOrPreventCheck( secondFromTopEnemyPiece, commander, towerPieces, entitiesDB); } foreach (PieceEV piece in towerPieces) { piece.Tier.Tier++; } return(returnValue); }
private void LoadSavedGame() { string fileName = "saved_game.txt"; if (isMobile) { fileName = Path.Combine(persistentDataPath, fileName); } // For simplicity, I'm not error checking this file. string[] lines = File.ReadAllLines(fileName); SetTurnStatus(lines[0]); int index = 1; while (index < lines.Length && IsHandPieceLine(lines[index])) { string[] data = lines[index].Split(','); MovePiecesToHand(data); index++; } List <PieceEV> pieces = pieceFindService.FindAllBoardPieces(entitiesDB).ToList(); for (; index < lines.Length; ++index) { string[] data = lines[index].Split(','); PieceEV pieceToRemoveFromList = PositionPiece(data, pieces); pieces.Remove(pieceToRemoveFromList); // Prevent future line from re-position already-positioned piece } }
private bool IsImmobileCapturePossible(PieceEV piece, List <PieceEV> piecesAtLocation, TurnEV currentTurn) { // TODO Immobile capture issues should only be a potential problem if the pieceToCapture has Mobile Range Expansion (since top piece is friendly) bool immobileCapturePossible = immobileCaptureService.ImmobileCapturePossible(piecesAtLocation, currentTurn.TurnPlayer.PlayerColor, entitiesDB); bool noCheckViolationsExist = immobileCaptureService.NoCheckViolationsExist(piecesAtLocation, immobileCapturePossible, entitiesDB); return(immobileCapturePossible && noCheckViolationsExist); }
private bool HasSameTypeAndTeamInTower( PieceEV pieceToCalc, Vector2 destination, List <PieceEV> allPieces) { return(allPieces.Where(piece => piece.Location.Location == destination && piece.PlayerOwner.PlayerColor == pieceToCalc.PlayerOwner.PlayerColor && piece.Piece.PieceType == pieceToCalc.Piece.PieceType).Count() > 0); }
private PieceSideState CheckDropToken(ref HandPieceEV handPiece, ref TileEV destinationTile, PieceSide?sideToCheck) { TurnEV currentTurn = turnService.GetCurrentTurnEV(entitiesDB); if (currentTurn.InitialArrangement.IsInitialArrangementInEffect) { return(PieceSideState.FRONT); } PieceEV pieceToDrop = pieceFindService.FindFirstPieceByLocationAndType( BoardConst.HAND_LOCATION, handPiece.HandPiece.PieceType, handPiece.HandPiece.Back, entitiesDB); bool singleSideValid = sideToCheck.HasValue && checkmateService.DropReleasesCheck( pieceToDrop, destinationTile.Location.Location, currentTurn.TurnPlayer.PlayerColor, sideToCheck.Value, handPiece, entitiesDB); bool frontSideValid = !sideToCheck.HasValue && checkmateService.DropReleasesCheck( pieceToDrop, destinationTile.Location.Location, currentTurn.TurnPlayer.PlayerColor, PieceSide.FRONT, handPiece, entitiesDB); bool backSideValid = !sideToCheck.HasValue && checkmateService.DropReleasesCheck( pieceToDrop, destinationTile.Location.Location, currentTurn.TurnPlayer.PlayerColor, PieceSide.BACK, handPiece, entitiesDB); if (singleSideValid) { return(sideToCheck.Value == PieceSide.FRONT ? PieceSideState.FRONT : PieceSideState.BACK); } else if (frontSideValid && backSideValid) { return(PieceSideState.BOTH); } else if (frontSideValid) { return(PieceSideState.FRONT); } else if (backSideValid) { return(PieceSideState.BACK); } else { return(PieceSideState.NONE); } }
public void SetTopOfTower(PieceEV pieceEV, IEntitiesDB entitiesDB, bool topOfTower = true) { entitiesDB.ExecuteOnEntity( pieceEV.ID, (ref PieceEV pieceToChange) => { pieceToChange.Tier.TopOfTower = topOfTower; }); }
public void SetPieceSide(PieceEV pieceEV, PieceSide side, IEntitiesDB entitiesDB) { entitiesDB.ExecuteOnEntity( pieceEV.ID, (ref PieceEV pieceToChange) => { pieceToChange.Piece.PieceType = side == PieceSide.FRONT ? pieceToChange.Piece.Front : pieceToChange.Piece.Back; }); }
private void FlipPiece(PieceEV piece, PlayerColor turnPlayerColor) { pieceSetService.SetPiecePlayerOwner(piece, turnPlayerColor, entitiesDB); pieceSetService.SetPieceSide( piece, piece.Piece.PieceType == piece.Piece.Front ? PieceSide.BACK : PieceSide.FRONT, entitiesDB); piece.ChangeColorTrigger.PlayChangeColor = true; }
private bool IsOpponentPieceDirectlyBelow(PieceEV pieceEV, List <PieceEV> allPieces) { return(pieceEV.Tier.Tier != 1 && allPieces.Where(piece => piece.Location.Location == pieceEV.Location.Location && piece.PlayerOwner.PlayerColor != pieceEV.PlayerOwner.PlayerColor && piece.Tier.Tier + 1 == pieceEV.Tier.Tier) .Count() > 0); }
private void NextActionClickHighlightCapture(PieceEV piece) { var clickPieceStepState = new ClickPieceStepState { ClickedPiece = piece }; towerModalConfirmSequence.Next(this, ref clickPieceStepState, (int)TowerAnswerState.DECIDE_CLICK_HIGHLIGHT_CAPTURE); }
private void RestoreSingleState(PreviousPieceState previousState) { PieceEV pieceToRestore = previousState.Piece; pieceToRestore.PlayerOwner.PlayerColor = previousState.PlayerColor; pieceToRestore.Piece.PieceType = previousState.PieceType; pieceToRestore.Location.Location = previousState.Location; pieceToRestore.Tier.Tier = previousState.Tier; pieceToRestore.Tier.TopOfTower = previousState.TopOfTower; }
public void Step(ref SubstitutionStepState token, int condition) { TurnEV currentTurn = turnService.GetCurrentTurnEV(entitiesDB); PieceEV commander = pieceFindService.FindCommander(currentTurn.TurnPlayer.PlayerColor, entitiesDB); PieceEV ninja = token.SubstitutionPiece; SwitchCommanderAndNinjaPiece(commander, ninja); NextActionTurnEnd(); }