2026-01-22 20:50:41 +05:30
using System ;
2026-01-21 20:27:45 +05:30
using System.Collections.Generic ;
using System.Linq ;
2026-01-26 19:48:55 +05:30
using TMPro ;
2026-01-21 20:27:45 +05:30
using UnityEngine ;
2026-01-26 19:48:55 +05:30
public enum PlayerType
2026-01-21 20:27:45 +05:30
{
Player1 = 0 ,
Player2 = 1 ,
Player3 = 2 ,
2026-01-27 20:55:55 +05:30
Player4 = 3
2026-01-21 20:27:45 +05:30
}
[System.Serializable]
public class PlayerGameData
{
2026-01-26 19:48:55 +05:30
public PlayerType playerType ;
2026-01-21 20:27:45 +05:30
public int startIndex ;
public int endIndex ;
public Transform playersParent ;
2026-01-27 20:55:55 +05:30
public Dictionary < int , PlayerPawn > playerPawnsDict ;
2026-01-22 20:50:41 +05:30
public int totalPawnsFinished = 0 ;
2026-01-21 20:27:45 +05:30
}
2026-01-26 19:48:55 +05:30
[System.Serializable]
public enum MatchType
{
2026-01-27 20:55:55 +05:30
PVP ,
2026-01-26 19:48:55 +05:30
Bot
}
2026-01-27 20:55:55 +05:30
public enum BotMove
{
FinishingPathMove = 0 ,
SafeMove = 1 ,
AttackMove = 2 ,
NormalMove = 3 ,
NoMoves = 4
}
2026-01-21 20:27:45 +05:30
public class GameplayManager : MonoBehaviour , IBase , IBootLoader , IDataLoader
{
2026-01-26 19:48:55 +05:30
[SerializeField] private TextMeshProUGUI diceText ;
2026-01-21 20:27:45 +05:30
[SerializeField] private Transform pointerDebug ;
[SerializeField] private MeshRenderer pointerMeshRend ;
[SerializeField] private Material turnMat ;
[SerializeField] private Material selectMat ;
[SerializeField] private PlayerGameData [ ] playerGameDatas ;
2026-01-23 15:32:48 +05:30
[SerializeField] private PlayerBaseHandler playerBaseHandler ;
2026-01-21 20:27:45 +05:30
2026-01-26 19:48:55 +05:30
private PlayerType currentPlayerTypeTurn ;
2026-01-21 20:27:45 +05:30
private int currentPlayerTurnIndex = 0 ;
2026-01-27 20:55:55 +05:30
private List < PlayerType > allPlayerTypes = new List < PlayerType > ( ) ;
private List < PlayerType > botTypesInGame = new List < PlayerType > ( ) ;
2026-01-21 20:27:45 +05:30
2026-01-27 20:55:55 +05:30
public List < PlayerType > PlayerTypesCollection = > allPlayerTypes ;
2026-01-21 20:27:45 +05:30
// private Dictionary<PlayerTypes, > playerPawnsDict = new Dictionary<PlayerTypes, List<PlayerPawn>>();
2026-01-26 19:48:55 +05:30
private Dictionary < PlayerType , PlayerGameData > playerGameDatasDict = new Dictionary < PlayerType , PlayerGameData > ( ) ;
2026-01-21 20:27:45 +05:30
2026-01-27 20:55:55 +05:30
// botRuntimeMovementData: where can the bot move if a particular dice value is thrown, and based on the value set the bot move for each using a predictive approach and select based on the the priority
private Dictionary < PlayerType , Dictionary < int , BotMove > > botRuntimeMovementData = new Dictionary < PlayerType , Dictionary < int , BotMove > > ( ) ;
2026-01-21 20:27:45 +05:30
private TilesManager tilesManager ;
private int diceRolledValue ;
public bool CanRollDice
{
get ; private set ;
}
2026-01-22 20:50:41 +05:30
private bool CanRollDiceAgain = false ; // used for when you get a 6 or when you reach the finish point
2026-01-21 20:27:45 +05:30
public void Initialize ( )
{
InterfaceManager . Instance ? . RegisterInterface < GameplayManager > ( this ) ;
}
public void InitializeData ( )
{
tilesManager = InterfaceManager . Instance . GetInterfaceInstance < TilesManager > ( ) ;
CanRollDice = true ;
2026-01-26 19:48:55 +05:30
// initialize the player list from UI.
2026-01-27 20:55:55 +05:30
// InitPlayerTypesForLAN(null);
InitPlayerTypesForBotMatch ( PlayerType . Player1 , 1 ) ;
2026-01-26 19:48:55 +05:30
}
// TODO :: Call when the UI selection is made and game starts
public void InitPlayerTypesForLAN ( List < PlayerType > types )
{
// TODO :: 2P, 3P, 4P
2026-01-27 20:55:55 +05:30
allPlayerTypes = new List < PlayerType > { PlayerType . Player1 , PlayerType . Player2 , PlayerType . Player3 , PlayerType . Player4 } ;
2026-01-23 15:32:48 +05:30
2026-01-27 20:55:55 +05:30
playerBaseHandler . InitPlayerTypes ( allPlayerTypes ) ;
2026-01-23 15:32:48 +05:30
InitCurrentGamePlayerInfo ( ) ;
2026-01-21 20:27:45 +05:30
}
2026-01-26 19:48:55 +05:30
public void InitPlayerTypesForBotMatch ( PlayerType selectedPlayerType , int botCount )
{
2026-01-27 20:55:55 +05:30
botTypesInGame . Clear ( ) ;
allPlayerTypes . Clear ( ) ;
AssignBotTypes ( selectedPlayerType , botCount ) ;
allPlayerTypes . Add ( selectedPlayerType ) ;
allPlayerTypes . AddRange ( botTypesInGame ) ;
playerBaseHandler . InitPlayerTypes ( allPlayerTypes ) ;
InitCurrentGamePlayerInfo ( ) ;
2026-01-28 16:57:27 +05:30
InitBotRuntimeData ( ) ;
2026-01-27 20:55:55 +05:30
AssignPlayerAndBotStates ( selectedPlayerType ) ;
}
private void InitBotRuntimeData ( )
{
botRuntimeMovementData . Clear ( ) ;
foreach ( var botType in botTypesInGame )
{
PlayerGameData playerGameData = playerGameDatasDict [ botType ] ;
if ( ! botRuntimeMovementData . ContainsKey ( botType ) )
{
botRuntimeMovementData . Add ( botType , new Dictionary < int , BotMove > ( ) ) ;
}
foreach ( var pawn in playerGameData . playerPawnsDict )
{
2026-01-28 16:57:27 +05:30
botRuntimeMovementData [ botType ] . Add ( pawn . Value . PlayerId , BotMove . NoMoves ) ;
2026-01-27 20:55:55 +05:30
}
}
}
private void AssignPlayerAndBotStates ( PlayerType selectedPlayerType )
{
PlayerBase playerBase = playerBaseHandler . GetPlayerBase ( selectedPlayerType ) ;
playerBase . AssignBotState ( PawnType . User ) ;
foreach ( PlayerType playerType in botTypesInGame )
{
playerBase = playerBaseHandler . GetPlayerBase ( playerType ) ;
playerBase . AssignBotState ( PawnType . Bot ) ;
}
}
private void AssignBotTypes ( PlayerType selectedPlayerType , int botCount )
{
int addedBots = 0 ;
2026-01-26 19:48:55 +05:30
if ( botCount = = 1 )
{
2026-01-27 20:55:55 +05:30
var playerType = ( PlayerType ) ( ( int ) selectedPlayerType + 2 < Enum . GetValues ( typeof ( PlayerType ) ) . Length ?
2026-01-26 19:48:55 +05:30
( int ) selectedPlayerType + 2 : ( int ) selectedPlayerType - 2 ) ;
2026-01-27 20:55:55 +05:30
botTypesInGame . Add ( playerType ) ;
}
else if ( botCount = = 2 )
{
foreach ( PlayerType enumType in Enum . GetValues ( typeof ( PlayerType ) ) )
{
if ( enumType = = selectedPlayerType ) continue ;
botTypesInGame . Add ( enumType ) ;
addedBots + + ;
if ( addedBots = = botCount ) break ;
}
2026-01-26 19:48:55 +05:30
}
else
{
2026-01-27 20:55:55 +05:30
foreach ( PlayerType enumType in Enum . GetValues ( typeof ( PlayerType ) ) )
{
if ( enumType = = selectedPlayerType ) continue ;
botTypesInGame . Add ( enumType ) ;
}
2026-01-26 19:48:55 +05:30
}
}
2026-01-21 20:27:45 +05:30
// TODO :: Call based on 2P/3P/4P
2026-01-23 15:32:48 +05:30
public void InitCurrentGamePlayerInfo ( )
2026-01-21 20:27:45 +05:30
{
2026-01-27 20:55:55 +05:30
currentPlayerTypeTurn = allPlayerTypes [ currentPlayerTurnIndex ] ;
2026-01-21 20:27:45 +05:30
// initialize the board based on the player types
foreach ( PlayerGameData playerGameData in playerGameDatas )
{
2026-01-27 20:55:55 +05:30
if ( ! allPlayerTypes . Contains ( playerGameData . playerType ) )
2026-01-23 15:32:48 +05:30
continue ;
2026-01-21 20:27:45 +05:30
2026-01-27 20:55:55 +05:30
Debug . Log ( $"playerGameData.playerType: {playerGameData.playerType}" ) ;
2026-01-23 15:32:48 +05:30
playerGameDatasDict . Add ( playerGameData . playerType , playerGameData ) ;
2026-01-27 20:55:55 +05:30
playerGameDatasDict [ playerGameData . playerType ] . playerPawnsDict = new Dictionary < int , PlayerPawn > ( ) ;
2026-01-23 15:32:48 +05:30
foreach ( Transform playerPawnChild in playerGameData . playersParent )
{
if ( ! playerPawnChild . gameObject . activeInHierarchy ) continue ;
2026-01-27 20:55:55 +05:30
var pawn = playerPawnChild . GetComponent < PlayerPawn > ( ) ;
playerGameDatasDict [ playerGameData . playerType ] . playerPawnsDict . Add ( pawn . PlayerId , pawn ) ;
2026-01-21 20:27:45 +05:30
}
}
}
public void EnablePlayerSelectionStates ( bool state )
{
2026-01-23 12:46:59 +05:30
foreach ( var playerPawn in playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict )
2026-01-21 20:27:45 +05:30
{
2026-01-27 20:55:55 +05:30
if ( playerPawn . Value . GetPlayerState ( ) = = PlayerState . InFinishingPath ) continue ;
2026-01-21 20:27:45 +05:30
2026-01-27 20:55:55 +05:30
playerPawn . Value . SetPlayerSelectionState ( state ) ;
2026-01-21 20:27:45 +05:30
}
}
2026-01-28 16:57:27 +05:30
public void RollDiceForPlayer ( int rolledVal )
{
OnDiceRolled ( rolledVal ) ;
CheckForPlayerSwitching ( ) ;
}
private void CheckForPlayerSwitching ( )
{
if ( canSwitchPlayer & & ! CanRollDiceAgain )
{
Debug . Log ( $"Switching player" ) ;
SwitchPlayer ( ) ;
CanRollDice = true ;
}
else if ( botTypesInGame . Contains ( currentPlayerTypeTurn ) & & CanRollDiceAgain )
{
Debug . Log ( $"RollDiceForBot" ) ;
Invoke ( nameof ( RollDiceForBot ) , 1f ) ;
}
}
private void RollDiceForBot ( )
{
Debug . Log ( $"CallTest: RollDiceForBot" ) ;
OnDiceRolled ( UnityEngine . Random . Range ( 1 , Ludo_3D_Constants . Max_Dice_Rolls + 1 ) ) ;
SelectPawnFromBotBase ( ) ;
CheckForPlayerSwitching ( ) ;
}
// TODO :: Call right after the dice is rolled with the animation
// What happens when you get a 6
private void SelectPawnFromBotBase ( )
{
if ( availPlayers . Count ( ) < 1 & & ! CanRollDiceAgain | | ! botTypesInGame . Contains ( currentPlayerTypeTurn ) ) return ;
Debug . Log ( $"CallTest: SelectPawnFromBotBase: {currentPlayerTypeTurn}" ) ;
var botPawnsDictForCurrentPlayer = botRuntimeMovementData [ currentPlayerTypeTurn ] ; // set the data inside this dict
// check the data from the playerGameDataDict
// change playerPawnsDict to list
// only select the pawns that are active
// if no pawns have left the home select the first pawn inside the base should be selected
int savedPlayerId = - 1 ;
PlayerPawn pawn = null ;
if ( availPlayers . Count ( ) < 1 & & CanRollDiceAgain ) // got a 6 roll value
{
pawn = playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict . Values . FirstOrDefault ( pawn = > pawn . GetPlayerState ( ) = = PlayerState . InHome ) ;
OnPawnSelected ( pawn ) ;
return ;
}
// TODO :: Double check
// foreach (var key in botPawnsDictForCurrentPlayer.Keys)
// botPawnsDictForCurrentPlayer[key] = BotMove.NoMoves;
foreach ( var playerPawn in availPlayers )
{
var possibleLandingIndex = playerPawn . CurrentTileIndex + diceRolledValue ;
if ( playerPawn . GetPlayerState ( ) = = PlayerState . HasFinished )
{
botPawnsDictForCurrentPlayer . Remove ( playerPawn . PlayerId ) ; // TODO :: Double check logic
continue ;
}
int lastIndex = tilesManager . GetGeneralTilesLength ( ) - 1 ;
int index = possibleLandingIndex > lastIndex ? ( possibleLandingIndex - lastIndex ) - 1 : possibleLandingIndex ;
Tile possibleTileData = tilesManager . RetrieveTileBasedOnIndex ( index ) ;
if ( playerPawn . GetPlayerState ( ) = = PlayerState . InFinishingPath | | possibleLandingIndex > playerGameDatasDict [ currentPlayerTypeTurn ] . endIndex )
{
botPawnsDictForCurrentPlayer [ playerPawn . PlayerId ] = BotMove . FinishingPathMove ;
savedPlayerId = playerPawn . PlayerId ;
break ;
}
else if ( possibleTileData . IsSafeZone | | playerPawn . GetPlayerState ( ) = = PlayerState . InHome )
{
botPawnsDictForCurrentPlayer [ playerPawn . PlayerId ] = BotMove . SafeMove ;
}
else if ( possibleTileData . PlayerPawn ! = null )
{
botPawnsDictForCurrentPlayer [ playerPawn . PlayerId ] = BotMove . AttackMove ;
}
else
{
botPawnsDictForCurrentPlayer [ playerPawn . PlayerId ] = BotMove . NormalMove ;
}
}
List < int > playerIds = new List < int > ( ) ;
if ( savedPlayerId ! = - 1 )
{
pawn = playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict [ savedPlayerId ] ; // chances are when one of the character reaches towards the finishing point
}
else
{
if ( botPawnsDictForCurrentPlayer . ContainsValue ( BotMove . SafeMove ) & & botPawnsDictForCurrentPlayer . ContainsValue ( BotMove . AttackMove ) )
{
InitPlayerIdsBasedOnState ( ( val ) = > val = = BotMove . AttackMove | | val = = BotMove . SafeMove ) ;
savedPlayerId = playerIds [ UnityEngine . Random . Range ( 0 , playerIds . Count ) ] ;
pawn = playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict [ savedPlayerId ] ;
Debug . Log ( $"Getting savedplayer id" ) ;
}
else if ( botPawnsDictForCurrentPlayer . ContainsValue ( BotMove . SafeMove ) )
{
InitPawnBasedOnState ( BotMove . SafeMove ) ;
Debug . Log ( $"Getting savedplayer id" ) ;
}
else if ( botPawnsDictForCurrentPlayer . ContainsValue ( BotMove . AttackMove ) )
{
InitPawnBasedOnState ( BotMove . AttackMove ) ;
Debug . Log ( $"Getting savedplayer id" ) ;
}
else if ( botPawnsDictForCurrentPlayer . ContainsValue ( BotMove . NormalMove ) )
{
InitPawnBasedOnState ( BotMove . NormalMove ) ;
Debug . Log ( $"Getting savedplayer id" ) ;
}
}
OnPawnSelected ( pawn ) ;
void InitPawnBasedOnState ( BotMove botMove )
{
InitPlayerIdsBasedOnState ( ( val ) = > val = = botMove ) ;
ReturnPlayerWithMaxSteps ( ref savedPlayerId ) ;
pawn = playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict [ savedPlayerId ] ;
}
void InitPlayerIdsBasedOnState ( Predicate < BotMove > state )
{
foreach ( var botPair in botPawnsDictForCurrentPlayer )
if ( state . Invoke ( botPair . Value ) )
playerIds . Add ( botPair . Key ) ;
}
void ReturnPlayerWithMaxSteps ( ref int savedPlayerId )
{
int maxStepsTaken = - 999 ;
foreach ( var id in playerIds )
{
if ( playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict [ id ] . StepsTaken > maxStepsTaken )
{
maxStepsTaken = playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict [ id ] . StepsTaken ;
savedPlayerId = id ;
}
}
}
}
private List < PlayerPawn > availPlayers = new List < PlayerPawn > ( ) ;
private bool canSwitchPlayer = false ;
2026-01-21 20:27:45 +05:30
public void OnDiceRolled ( int rolledVal )
{
CanRollDice = false ;
// add core dice logic here
2026-01-22 20:50:41 +05:30
Debug . Log ( $"Tile Index :: LUDO :: rolledVal: {rolledVal} :: {currentPlayerTypeTurn}" ) ;
2026-01-21 20:27:45 +05:30
diceRolledValue = rolledVal ;
2026-01-26 19:48:55 +05:30
diceText . text = $"{diceRolledValue}" ;
2026-01-21 20:27:45 +05:30
if ( rolledVal = = Ludo_3D_Constants . Max_Dice_Rolls )
{
2026-01-28 16:57:27 +05:30
canSwitchPlayer = false ;
2026-01-21 20:27:45 +05:30
// provide option to select a pawn from the list
// also play a simple animation before selecting
EnablePlayerSelectionStates ( true ) ;
2026-01-22 20:50:41 +05:30
CanRollDiceAgain = true ;
2026-01-27 20:55:55 +05:30
if ( AreAllPawnsInFinishingPath ( ) )
2026-01-22 20:50:41 +05:30
CanRollDice = true ;
2026-01-21 20:27:45 +05:30
pointerMeshRend . material = selectMat ;
// pointerMeshRend.materials[0] = selectMat;
}
else // if there are any other pawns that are in safe or moving state
{
// for player's logic
2026-01-28 16:57:27 +05:30
availPlayers . Clear ( ) ;
availPlayers = playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict . Values . Select ( pawn = > pawn )
2026-01-21 20:27:45 +05:30
. Where ( pawn = > pawn . GetPlayerState ( ) = = PlayerState . InSafeZone | |
pawn . GetPlayerState ( ) = = PlayerState . Moving | |
2026-01-28 16:57:27 +05:30
pawn . GetPlayerState ( ) = = PlayerState . InFinishingPath ) . ToList ( ) ;
Debug . Log ( $"availPlayers: {playerGameDatasDict[currentPlayerTypeTurn].playerPawnsDict.Values.Select(pawn => pawn).Where(pawn => pawn.GetPlayerState() == PlayerState.InHome).ToList().Count}" ) ;
2026-01-22 20:50:41 +05:30
int customAvailPlayers = availPlayers . Count ( ) ;
2026-01-28 16:57:27 +05:30
Debug . Log ( $"before CustomAvailablePlayers: {customAvailPlayers}" ) ;
2026-01-22 20:50:41 +05:30
2026-01-21 20:27:45 +05:30
foreach ( PlayerPawn playerPawn in availPlayers )
{
Debug . Log ( $"## playerPawn.GetPlayerState(): {playerPawn.GetPlayerState()}" ) ;
if ( playerPawn . GetPlayerState ( ) = = PlayerState . InFinishingPath )
{
2026-01-22 20:50:41 +05:30
if ( diceRolledValue < = tilesManager . GetFinishingTileDataLength ( currentPlayerTypeTurn ) - ( playerPawn . CurrentTileIndex + 1 ) )
{
playerPawn . SetPlayerSelectionState ( true ) ;
}
else
{
customAvailPlayers - - ;
}
continue ;
2026-01-21 20:27:45 +05:30
}
2026-01-22 20:50:41 +05:30
playerPawn . SetPlayerSelectionState ( true ) ;
2026-01-21 20:27:45 +05:30
}
2026-01-22 20:50:41 +05:30
// if (availPlayers.Count() < 1)
Debug . Log ( $"CustomAvailablePlayers: {customAvailPlayers}" ) ;
2026-01-28 16:57:27 +05:30
canSwitchPlayer = customAvailPlayers < 1 ;
2026-01-22 20:50:41 +05:30
CanRollDiceAgain = false ;
2026-01-21 20:27:45 +05:30
}
2026-01-28 16:57:27 +05:30
Debug . Log ( $"CanRollDiceAgain: {CanRollDiceAgain}, canSwitchPlayer: {canSwitchPlayer}" ) ;
2026-01-21 20:27:45 +05:30
}
2026-01-27 20:55:55 +05:30
private bool AreAllPawnsInFinishingPath ( )
{
bool areAllPawnsInFinishingPath = false ;
foreach ( var pawn in playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict )
{
if ( pawn . Value . GetPlayerState ( ) = = PlayerState . InFinishingPath & & pawn . Value . GetPlayerState ( ) ! = PlayerState . HasFinished )
{
areAllPawnsInFinishingPath = true ;
continue ;
}
areAllPawnsInFinishingPath = false ;
break ;
}
return areAllPawnsInFinishingPath ;
}
2026-01-28 16:57:27 +05:30
private void UpdatePlayerState ( PlayerPawn playerPawn , PlayerState playerState )
{
playerGameDatasDict [ playerPawn . PlayerType ] . playerPawnsDict [ playerPawn . PlayerId ] = playerPawn ;
playerGameDatasDict [ playerPawn . PlayerType ] . playerPawnsDict [ playerPawn . PlayerId ] . SetPlayerState ( playerState ) ;
playerPawn . SetPlayerState ( playerState ) ;
}
2026-01-21 20:27:45 +05:30
public void OnPawnSelected ( PlayerPawn playerPawn )
{
EnablePlayerSelectionStates ( false ) ;
2026-01-22 20:50:41 +05:30
PlayerGameData playerGameData = playerGameDatasDict [ currentPlayerTypeTurn ] ;
2026-01-26 13:03:50 +05:30
Debug . Log ( $"playerPawn.GetPlayerState(): {playerPawn.GetPlayerState()}" ) ;
2026-01-21 20:27:45 +05:30
if ( playerPawn . GetPlayerState ( ) = = PlayerState . InHome )
{
2026-01-23 12:46:59 +05:30
Tile targetTile = tilesManager . RetrieveTileBasedOnIndex ( playerGameData . startIndex ) ;
2026-01-21 20:27:45 +05:30
playerPawn . MoveToTile (
2026-01-23 13:33:16 +05:30
GetAndInitPositionInsideSafeZone ( playerPawn , targetTile ) ,
2026-01-21 20:27:45 +05:30
onComplete : ( ) = >
{
CanRollDice = true ;
2026-01-28 16:57:27 +05:30
UpdatePlayerState ( playerPawn , PlayerState . InSafeZone ) ;
2026-01-21 20:27:45 +05:30
} , playerGameData . startIndex ) ;
return ;
}
2026-01-22 20:50:41 +05:30
else if ( playerPawn . GetPlayerState ( ) = = PlayerState . InFinishingPath
| | playerPawn . CurrentTileIndex = = playerGameDatasDict [ currentPlayerTypeTurn ] . endIndex )
{
int finishingPathIndex = GetNextFinishingTileIndex ( playerPawn ) ;
int targetIdx = finishingPathIndex + diceRolledValue > tilesManager . GetFinishingTileDataLength ( currentPlayerTypeTurn ) - 1 ?
tilesManager . GetFinishingTileDataLength ( currentPlayerTypeTurn ) - 1 : finishingPathIndex + diceRolledValue ;
Debug . Log ( $"TargetIdx: {targetIdx}" ) ;
MoveThroughFinishingPath ( playerPawn , finishingPathIndex , targetIdx ) ;
}
else if ( playerPawn . GetPlayerState ( ) = = PlayerState . InSafeZone | | playerPawn . GetPlayerState ( ) = = PlayerState . Moving )
2026-01-21 20:27:45 +05:30
{
// move based on the dice value
2026-01-22 20:50:41 +05:30
Debug . Log ( $"Tile Index :: currentTileIndex: {playerPawn.CurrentTileIndex}" ) ;
int nextTileIdx = GetNextGeneralTileIndex ( playerPawn ) ;
int targetIdx = playerPawn . CurrentTileIndex + diceRolledValue ;
2026-01-21 20:27:45 +05:30
2026-01-22 20:50:41 +05:30
if ( nextTileIdx = = 0 )
targetIdx = targetIdx - playerPawn . CurrentTileIndex ;
Tile currentSittingTile = tilesManager . RetrieveTileBasedOnIndex ( playerPawn . CurrentTileIndex ) ;
if ( currentSittingTile . IsSafeZone )
{
2026-01-23 13:33:16 +05:30
SafeTile safeTile = ( SafeTile ) currentSittingTile ;
safeTile . UpdateSafeZonePlayerData ( currentPlayerTypeTurn , playerPawn ) ;
if ( safeTile . PlayerTypesCount = = 1 )
{
2026-01-26 19:48:55 +05:30
PlayerType playerType = safeTile . GetFirstPlayerType ( ) ;
2026-01-23 15:32:48 +05:30
2026-01-23 13:33:16 +05:30
var playerPawns = safeTile . GetPlayerPawns ( playerType ) ;
foreach ( var pawn in playerPawns )
pawn . MoveToCustomTilePosition ( safeTile . CenterPlacementPosition ) ;
}
2026-01-22 20:50:41 +05:30
}
2026-01-26 13:03:50 +05:30
else
{
currentSittingTile . ResetPlayerPawn ( ) ;
}
2026-01-22 20:50:41 +05:30
MoveThroughTiles ( playerPawn , nextTileIdx , targetIndex : targetIdx ) ;
2026-01-21 20:27:45 +05:30
}
}
2026-01-22 20:50:41 +05:30
private int GetNextGeneralTileIndex ( PlayerPawn playerPawn )
{
return playerPawn . CurrentTileIndex = = tilesManager . GetGeneralTilesLength ( ) - 1 ? 0 : playerPawn . CurrentTileIndex + 1 ;
}
private int GetNextFinishingTileIndex ( PlayerPawn playerPawn )
{
return playerPawn . CurrentTileIndex > tilesManager . GetFinishingTileDataLength ( currentPlayerTypeTurn ) - 1 ? 0 : playerPawn . CurrentTileIndex + 1 ;
}
private void SwitchPlayer ( PlayerPawn playerPawn = null )
2026-01-21 20:27:45 +05:30
{
2026-01-28 16:57:27 +05:30
Debug . Log ( $"CallTest: SwitchPlayer" ) ;
2026-01-22 20:50:41 +05:30
if ( ! CanRollDiceAgain )
2026-01-21 20:27:45 +05:30
{
2026-01-22 20:50:41 +05:30
Debug . Log ( $"currentPlayerTurn: {currentPlayerTypeTurn}" ) ;
Debug . Log ( $"currentPlayerTurnIndex: {currentPlayerTurnIndex}" ) ;
2026-01-27 20:55:55 +05:30
if ( allPlayerTypes . Count = = 1 )
2026-01-22 20:50:41 +05:30
{
Debug . LogError ( $"GAME IS OVER" ) ;
return ;
}
2026-01-27 20:55:55 +05:30
if ( currentPlayerTypeTurn = = allPlayerTypes [ allPlayerTypes . Count - 1 ] )
2026-01-21 20:27:45 +05:30
{
currentPlayerTurnIndex = 0 ;
2026-01-27 20:55:55 +05:30
currentPlayerTypeTurn = allPlayerTypes [ currentPlayerTurnIndex ] ;
2026-01-21 20:27:45 +05:30
}
else
{
currentPlayerTurnIndex + + ;
2026-01-27 20:55:55 +05:30
currentPlayerTypeTurn = allPlayerTypes [ currentPlayerTurnIndex ] ;
2026-01-21 20:27:45 +05:30
}
2026-01-26 19:48:55 +05:30
diceText . text = $"{0}" ;
2026-01-21 20:27:45 +05:30
}
2026-01-26 13:03:50 +05:30
Debug . Log ( $"CurrentPlayerTurn: {currentPlayerTypeTurn}" ) ;
var tempPos = playerBaseHandler . GetPlayerBase ( currentPlayerTypeTurn ) . transform . position ;
pointerDebug . position = new Vector3 ( tempPos . x , 3f , tempPos . z ) ;
2026-01-21 20:27:45 +05:30
pointerMeshRend . material = turnMat ;
// pointerMeshRend.materials[0] = turnMat;
2026-01-22 20:50:41 +05:30
if ( playerPawn )
2026-01-28 16:57:27 +05:30
UpdatePlayerState ( playerPawn , tilesManager . RetrieveTileBasedOnIndex ( playerPawn . CurrentTileIndex ) . IsSafeZone ? PlayerState . InSafeZone : PlayerState . Moving ) ;
2026-01-27 20:55:55 +05:30
Debug . Log ( $"botTypesInGame.Contains(currentPlayerTypeTurn): {botTypesInGame.Contains(currentPlayerTypeTurn)}" ) ;
2026-01-28 16:57:27 +05:30
if ( botTypesInGame . Contains ( currentPlayerTypeTurn ) ) // TODO :: Double check calling of the function
2026-01-27 20:55:55 +05:30
{
2026-01-28 16:57:27 +05:30
Debug . Log ( $"Invoking RollDiceForBot" ) ;
2026-01-27 20:55:55 +05:30
Invoke ( nameof ( RollDiceForBot ) , 1f ) ;
}
}
2026-01-21 20:27:45 +05:30
private void MoveThroughTiles ( PlayerPawn playerPawn , int index , int targetIndex )
{
2026-01-22 20:50:41 +05:30
Tile nextTile = tilesManager . RetrieveTileBasedOnIndex ( index ) ;
2026-01-23 12:46:59 +05:30
Vector3 targetPosition = nextTile . CenterPlacementPosition ;
2026-01-22 20:50:41 +05:30
2026-01-23 12:46:59 +05:30
Debug . Log ( $"Tile Index :: nextIndex: {index}, targetIndex: {targetIndex}, nextTileName: {nextTile.name}" ) ;
if ( index = = targetIndex ) // if the target index is the safe zone only then apply the logic for rearranging pawns
2026-01-22 20:50:41 +05:30
{
Tile targetTile = tilesManager . RetrieveTileBasedOnIndex ( targetIndex ) ;
if ( targetTile . IsSafeZone )
2026-01-21 20:27:45 +05:30
{
2026-01-23 13:33:16 +05:30
targetPosition = GetAndInitPositionInsideSafeZone ( playerPawn , targetTile ) ;
2026-01-22 20:50:41 +05:30
}
}
2026-01-23 12:46:59 +05:30
Debug . Log ( $"tile targetPosition: {targetPosition}" ) ;
2026-01-22 20:50:41 +05:30
playerPawn . MoveToTile (
targetPosition ,
onComplete : ( ) = >
{
diceRolledValue - - ;
2026-01-23 12:46:59 +05:30
Debug . Log ( $"DiceRolledValue: {diceRolledValue}" ) ;
2026-01-22 20:50:41 +05:30
if ( diceRolledValue > 0 )
{
int nextTileIndex = GetNextGeneralTileIndex ( playerPawn ) ;
2026-01-23 12:46:59 +05:30
Debug . Log ( $"currentTileIndex: {playerPawn.CurrentTileIndex}, nextTileIndex: {nextTileIndex}, targetIndex: {targetIndex}" ) ;
2026-01-22 20:50:41 +05:30
if ( playerPawn . GetPlayerState ( ) = = PlayerState . InFinishingPath | | index = = playerGameDatasDict [ currentPlayerTypeTurn ] . endIndex )
2026-01-21 20:27:45 +05:30
{
2026-01-22 20:50:41 +05:30
// MoveThroughTiles(playerPawn, index, targetIndex);
Debug . Log ( $"TargetIdx: {targetIndex - index}" ) ;
MoveThroughFinishingPath ( playerPawn , 0 , targetIndex - index ) ;
2026-01-21 20:27:45 +05:30
}
2026-01-22 20:50:41 +05:30
else if ( nextTileIndex < = targetIndex )
{
if ( nextTileIndex = = 0 )
2026-01-23 12:46:59 +05:30
targetIndex = ( targetIndex - playerPawn . CurrentTileIndex ) - 1 ;
2026-01-21 20:27:45 +05:30
2026-01-22 20:50:41 +05:30
MoveThroughTiles ( playerPawn , nextTileIndex , targetIndex ) ;
}
}
else
{
2026-01-23 12:46:59 +05:30
// TODO :: Improve this logic, use a collection
2026-01-26 13:03:50 +05:30
Debug . Log ( $"nextTile.IsSafeZone: {nextTile.IsSafeZone}" ) ;
2026-01-23 12:46:59 +05:30
if ( ! nextTile . IsSafeZone )
{
2026-01-26 13:03:50 +05:30
Debug . Log ( $"nextTile.PlayerPawn: {nextTile.PlayerPawn}, {nextTile.transform.name}" ) ;
2026-01-23 12:46:59 +05:30
if ( nextTile . PlayerPawn ! = null )
{
2026-01-26 13:03:50 +05:30
// play animation for moving back to base.
2026-01-23 12:46:59 +05:30
// TODO :: Send existing pawn back to base.
// means there's already a pawn there, move him back to the base.
2026-01-26 13:03:50 +05:30
var playerBasePos = playerBaseHandler . GetPlayerBase ( nextTile . PlayerPawn . PlayerType )
. GetBasePlacementDataPosition ( nextTile . PlayerPawn . PlayerId - 1 ) . position ;
Debug . Log ( $"playerBasePos: {playerBasePos}" ) ;
2026-01-28 16:57:27 +05:30
nextTile . PlayerPawn . MoveBackToHome ( playerBasePos ) ;
2026-01-23 12:46:59 +05:30
}
nextTile . InitPlayerPawn ( playerPawn , currentPlayerTypeTurn ) ;
}
2026-01-22 20:50:41 +05:30
SwitchPlayer ( playerPawn ) ;
CanRollDice = true ;
2026-01-21 20:27:45 +05:30
}
} ,
index ) ;
}
2026-01-23 13:33:16 +05:30
private Vector3 GetAndInitPositionInsideSafeZone ( PlayerPawn playerPawn , Tile targetTile )
2026-01-23 12:46:59 +05:30
{
Vector3 targetPosition ;
SafeTile targetSafeTile = ( SafeTile ) targetTile ;
Debug . Log ( $"targetSafeTile.PlayerTypesCount: {targetSafeTile.PlayerTypesCount}" ) ;
if ( targetSafeTile . PlayerTypesCount = = 1 )
{
Debug . Log ( $"targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn): {targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn)}" ) ;
if ( ! targetSafeTile . ContainsPlayerType ( currentPlayerTypeTurn ) ) // means it is a new player type, the second one
{
2026-01-26 19:48:55 +05:30
PlayerType initialPlayerType = targetSafeTile . GetFirstPlayerType ( ) ;
2026-01-23 12:46:59 +05:30
// rearrange already existing player from center position to it's saved transform
var playerPawns = targetSafeTile . GetPlayerPawns ( initialPlayerType ) ;
foreach ( var pawn in playerPawns )
{
var placementPoint = targetSafeTile . GetPlacementPoint ( initialPlayerType ) ;
2026-01-23 13:33:16 +05:30
pawn . MoveToCustomTilePosition ( placementPoint . position ) ;
2026-01-23 12:46:59 +05:30
}
targetSafeTile . InitPlayerPawn ( playerPawn , currentPlayerTypeTurn ) ;
targetPosition = targetSafeTile . GetPlacementPoint ( currentPlayerTypeTurn ) . position ;
}
else
{
targetSafeTile . InitPlayerPawn ( playerPawn , currentPlayerTypeTurn ) ;
targetPosition = targetTile . CenterPlacementPosition ;
}
}
else
{
// TODO :: Check the data if it's consistent
Debug . Log ( $"targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn): {targetSafeTile.ContainsPlayerType(currentPlayerTypeTurn)}" ) ;
if ( ! targetSafeTile . ContainsPlayerType ( currentPlayerTypeTurn ) )
{
Debug . Log ( $"targetSafeTile.PlayerTypesCount: {targetSafeTile.PlayerTypesCount}" ) ;
if ( targetSafeTile . PlayerTypesCount < 1 ) // he is the only player that is being added to the safe zone
{
targetSafeTile . InitPlayerPawn ( playerPawn , currentPlayerTypeTurn ) ;
targetPosition = targetTile . CenterPlacementPosition ;
}
else
{
targetSafeTile . InitPlayerPawn ( playerPawn , currentPlayerTypeTurn ) ;
targetPosition = targetSafeTile . GetPlacementPoint ( currentPlayerTypeTurn ) . position ;
}
}
else
{
targetSafeTile . InitPlayerPawn ( playerPawn , currentPlayerTypeTurn ) ;
targetPosition = targetSafeTile . GetPlacementPoint ( currentPlayerTypeTurn ) . position ;
}
}
return targetPosition ;
}
2026-01-21 20:27:45 +05:30
private void MoveThroughFinishingPath ( PlayerPawn playerPawn , int index , int targetIndex )
{
2026-01-28 16:57:27 +05:30
UpdatePlayerState ( playerPawn , PlayerState . InFinishingPath ) ;
2026-01-21 20:27:45 +05:30
playerPawn . MoveToTile (
2026-01-22 20:50:41 +05:30
tilesManager . RetrievePositionForFinishingTile ( currentPlayerTypeTurn , index ) . position ,
2026-01-21 20:27:45 +05:30
onComplete : ( ) = >
{
2026-01-22 20:50:41 +05:30
diceRolledValue - - ;
Debug . Log ( $"DiceRolledValue: {diceRolledValue}" ) ;
if ( diceRolledValue > 0 )
2026-01-21 20:27:45 +05:30
{
2026-01-22 20:50:41 +05:30
int tileIndex = GetNextFinishingTileIndex ( playerPawn ) ;
Debug . Log ( $"tileIndex: {tileIndex}, targetIndex: {targetIndex}" ) ;
if ( tileIndex < = targetIndex )
{
// MoveThroughTiles(playerPawn, index, targetIndex);
MoveThroughFinishingPath ( playerPawn , tileIndex , targetIndex ) ;
}
2026-01-21 20:27:45 +05:30
}
else
{
2026-01-22 20:50:41 +05:30
if ( playerPawn . CurrentTileIndex = = tilesManager . GetFinishingTileDataLength ( currentPlayerTypeTurn ) - 1 )
{
2026-01-28 16:57:27 +05:30
UpdatePlayerState ( playerPawn , PlayerState . HasFinished ) ;
2026-01-22 20:50:41 +05:30
playerGameDatasDict [ currentPlayerTypeTurn ] . totalPawnsFinished + + ;
2026-01-23 12:46:59 +05:30
if ( playerGameDatasDict [ currentPlayerTypeTurn ] . totalPawnsFinished = = playerGameDatasDict [ currentPlayerTypeTurn ] . playerPawnsDict . Count )
2026-01-22 20:50:41 +05:30
{
CanRollDiceAgain = false ;
SwitchPlayer ( ) ;
2026-01-27 20:55:55 +05:30
if ( allPlayerTypes . Contains ( currentPlayerTypeTurn ) )
allPlayerTypes . Remove ( currentPlayerTypeTurn ) ;
2026-01-22 20:50:41 +05:30
2026-01-27 20:55:55 +05:30
Debug . Log ( $"PlayerTypes: {allPlayerTypes.Count}" ) ;
2026-01-22 20:50:41 +05:30
}
else
{
CanRollDiceAgain = true ;
}
}
else
{
SwitchPlayer ( ) ;
}
CanRollDice = true ;
2026-01-21 20:27:45 +05:30
}
} ,
index ) ;
}
}