One of the primary motivations for positioning pawns at runtime is to vary gameplay on each playthrough.
If pawns are placed within the editor and not moved each playthrough, once you play a single round, you will know exactly where those pawns are placed each time. If instead, you randomly place pawns each time, there are multiple starting configurations.
To put this into perspective, if you have a board that is 5 x 5 tiles and five pawns, there are (25 choose 5) 53,130 distinct configurations. If you increase the board by just 1 more space in each dimension to 6 x 6 and keep five pawns, that number goes up to (36 choose 5) 11,686,752.
Randomization can be a powerful tool to create varied gameplay.
Generate a Random Tile Coordinate
To randomly place a pawn, you need to generate a random tile coordinate within the bounds of a board. There are many different ways to randomly generate a coordinate in two-dimensional space. The most common is uniform distribution, which is what you will use for this example. A uniform distribution places an equal likelihood for a pawn to be put on any tile on the board. For more information, see https://en.wikipedia.org/wiki/Discrete_uniform_distribution . To this end, construct a utility function named GenerateUniformRandomTileCoordinate that takes in a bounds object to know what domain to generate the coordinate within.
To generate a uniformly distributed tile coordinate in two-dimensional space, randomly generate an integer in each dimension independently, then combine them in a tile coordinate object.
using { /Verse.org/Simulation }
using { /Verse.org/Random }
UtilityFunctions<public> := module:
...
GenerateUniformRandomTileCoordinate<public>(BoardBounds:board_bounds)<transacts>:tile_coordinate =
tile_coordinate:
Left := GetRandomInt(BoardBounds.LeftBounds.Low, BoardBounds.LeftBounds.High)
This function performs the following steps:
Generate a random integer within the left bounds of the board.
Generate a random integer within the forward bounds of the board.
Combine these into a tile coordinate object.
For a list of more discrete distributions with finite support, see the following table https://en.wikipedia.org/wiki/List_of_probability_distributions . You can try to create functions of your own that generate coordinates with respect to some of these distributions and see how the pawn placement changes.
Ensure Enough Open Spaces
One additional consideration before placing pawns on the board is to determine whether there are enough board spaces available for the number of pawns. This can be done by creating a utility function named `NumberOfTileCoordinates` that takes in a board bounds object and outputs the number of tiles on the board.
using { /Verse.org/Simulation }
using { /Verse.org/Random }
UtilityFunctions<public> := module:
...
NumberOfTileCoordinates<public>(BoardBounds:board_bounds)<transacts>:int =
(BoardBounds.LeftBounds.High - BoardBounds.LeftBounds.Low) * (BoardBounds.ForwardBounds.High - BoardBounds.ForwardBounds.Low)Randomly Place a Pawn
To randomly place the pawns on the board, you need to know how many pawns to generate. Add this as an editable variable on the board class.
After determining the number of pawns on the board, the procedure for placing pawns is:
Ensure there are enough tile coordinates available for the number of pawns with
NumberOfTileCoordinates.Randomly generate a tile coordinate with
GenerateUniformRandomTileCoordinate.Decide if there is already a pawn at that coordinate.
If yes, go back to step 1.
If no, go to step 4.
Decide if
SetPawnat the generated coordinate succeeds.If yes, move on to the next pawn.
If not, produce an error.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
This function succeeds if and only if:
There are enough board spaces for the prescribed number of pawns.
Each pawn is successfully placed at a coordinate that does not already have a pawn there.
Generate the Board at Runtime
To generate the board at runtime, all that is left to do is override the board OnBegin function and call PlacePawns:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
Summary
To summarize, this page has taken you through the following step:
Randomly place all pawns on the board.
Files
using { /Verse.org/Simulation }
using { /Verse.org/Random }
DataTypes<public> := module:
tile_coordinate<public> := class<concrete>:
@editable
Left<public>:int = 0
@editable
Forward<public>:int = 0
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):