|
using System; |
|
using UnityEngine; |
|
|
|
namespace Unity.MLAgents.Integrations.Match3 |
|
{ |
|
|
|
|
|
|
|
public enum Direction |
|
{ |
|
|
|
|
|
|
|
Up, |
|
|
|
|
|
|
|
|
|
Down, |
|
|
|
|
|
|
|
|
|
Left, |
|
|
|
|
|
|
|
|
|
Right, |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public struct Move |
|
{ |
|
|
|
|
|
|
|
public int MoveIndex; |
|
|
|
|
|
|
|
|
|
public int Row; |
|
|
|
|
|
|
|
|
|
public int Column; |
|
|
|
|
|
|
|
|
|
public Direction Direction; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Move FromMoveIndex(int moveIndex, BoardSize maxBoardSize) |
|
{ |
|
var maxRows = maxBoardSize.Rows; |
|
var maxCols = maxBoardSize.Columns; |
|
|
|
if (moveIndex < 0 || moveIndex >= NumPotentialMoves(maxBoardSize)) |
|
{ |
|
throw new ArgumentOutOfRangeException("moveIndex"); |
|
} |
|
Direction dir; |
|
int row, col; |
|
if (moveIndex < (maxCols - 1) * maxRows) |
|
{ |
|
dir = Direction.Right; |
|
col = moveIndex % (maxCols - 1); |
|
row = moveIndex / (maxCols - 1); |
|
} |
|
else |
|
{ |
|
dir = Direction.Up; |
|
var offset = moveIndex - (maxCols - 1) * maxRows; |
|
col = offset % maxCols; |
|
row = offset / maxCols; |
|
} |
|
return new Move |
|
{ |
|
MoveIndex = moveIndex, |
|
Direction = dir, |
|
Row = row, |
|
Column = col |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void Next(BoardSize maxBoardSize) |
|
{ |
|
var maxRows = maxBoardSize.Rows; |
|
var maxCols = maxBoardSize.Columns; |
|
|
|
var switchoverIndex = (maxCols - 1) * maxRows; |
|
|
|
MoveIndex++; |
|
if (MoveIndex < switchoverIndex) |
|
{ |
|
Column++; |
|
if (Column == maxCols - 1) |
|
{ |
|
Row++; |
|
Column = 0; |
|
} |
|
} |
|
else if (MoveIndex == switchoverIndex) |
|
{ |
|
|
|
Row = 0; |
|
Column = 0; |
|
Direction = Direction.Up; |
|
} |
|
else |
|
{ |
|
Column++; |
|
if (Column == maxCols) |
|
{ |
|
Row++; |
|
Column = 0; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Move FromPositionAndDirection(int row, int col, Direction dir, BoardSize maxBoardSize) |
|
{ |
|
|
|
if (row < 0 || row >= maxBoardSize.Rows) |
|
{ |
|
throw new IndexOutOfRangeException($"row was {row}, but must be between 0 and {maxBoardSize.Rows - 1}."); |
|
} |
|
|
|
if (col < 0 || col >= maxBoardSize.Columns) |
|
{ |
|
throw new IndexOutOfRangeException($"col was {col}, but must be between 0 and {maxBoardSize.Columns - 1}."); |
|
} |
|
|
|
|
|
if ( |
|
row == 0 && dir == Direction.Down || |
|
row == maxBoardSize.Rows - 1 && dir == Direction.Up || |
|
col == 0 && dir == Direction.Left || |
|
col == maxBoardSize.Columns - 1 && dir == Direction.Right |
|
) |
|
{ |
|
throw new IndexOutOfRangeException($"Cannot move cell at row={row} col={col} in Direction={dir}"); |
|
} |
|
|
|
|
|
if (dir == Direction.Left) |
|
{ |
|
dir = Direction.Right; |
|
col = col - 1; |
|
} |
|
else if (dir == Direction.Down) |
|
{ |
|
dir = Direction.Up; |
|
row = row - 1; |
|
} |
|
|
|
int moveIndex; |
|
if (dir == Direction.Right) |
|
{ |
|
moveIndex = col + row * (maxBoardSize.Columns - 1); |
|
} |
|
else |
|
{ |
|
var offset = (maxBoardSize.Columns - 1) * maxBoardSize.Rows; |
|
moveIndex = offset + col + row * maxBoardSize.Columns; |
|
} |
|
|
|
return new Move |
|
{ |
|
Row = row, |
|
Column = col, |
|
Direction = dir, |
|
MoveIndex = moveIndex, |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public bool InRangeForBoard(BoardSize boardSize) |
|
{ |
|
var (otherRow, otherCol) = OtherCell(); |
|
|
|
var maxMoveRow = Mathf.Max(Row, otherRow); |
|
var maxMoveCol = Mathf.Max(Column, otherCol); |
|
return maxMoveRow < boardSize.Rows && maxMoveCol < boardSize.Columns; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public (int Row, int Column) OtherCell() |
|
{ |
|
switch (Direction) |
|
{ |
|
case Direction.Up: |
|
return (Row + 1, Column); |
|
case Direction.Down: |
|
return (Row - 1, Column); |
|
case Direction.Left: |
|
return (Row, Column - 1); |
|
case Direction.Right: |
|
return (Row, Column + 1); |
|
default: |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public Direction OtherDirection() |
|
{ |
|
switch (Direction) |
|
{ |
|
case Direction.Up: |
|
return Direction.Down; |
|
case Direction.Down: |
|
return Direction.Up; |
|
case Direction.Left: |
|
return Direction.Right; |
|
case Direction.Right: |
|
return Direction.Left; |
|
default: |
|
throw new ArgumentOutOfRangeException(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static int NumPotentialMoves(BoardSize maxBoardSize) |
|
{ |
|
return maxBoardSize.Rows * (maxBoardSize.Columns - 1) + (maxBoardSize.Rows - 1) * (maxBoardSize.Columns); |
|
} |
|
} |
|
} |
|
|