fixed game logic
This commit is contained in:
@@ -1,52 +1,52 @@
|
||||
# Pieces representation
|
||||
|
||||
## What are polyominos ?
|
||||
## What are polyominoes ?
|
||||
|
||||
In this game, pieces are represented as a polyomino and a block type.
|
||||
Polyominos are mathematical objects consisting of multiple edge-touching squares.
|
||||
Polyominoes are mathematical objects consisting of multiple edge-touching squares.
|
||||
There must be a path from every square to every other square, going from square to square only through the sides and not the corners.
|
||||
Polyominos can be classified in 3 ways:
|
||||
Polyominoes can be classified in 3 ways:
|
||||
|
||||
- Fixed polyominos : only translation is allowed
|
||||
- One-sided polyominos : only translation and rotation are allowed
|
||||
- Fixed polyominoes : only translation is allowed
|
||||
- One-sided polyominoes : only translation and rotation are allowed
|
||||
- Free polyomins : translation, rotation, and reflection are allowed
|
||||
|
||||
For more detailed informations about polyominos, check the [Wikipedia page](https://en.wikipedia.org/wiki/Polyomino).
|
||||
For more detailed informations about polyominoes, check the [Wikipedia page](https://en.wikipedia.org/wiki/Polyomino).
|
||||
|
||||
Most stacker game uses all one-sided polyominos of size 4 (called tetrominos), which results in 7 distinct polyominos.
|
||||
In this game too, one-sided polyominos will be used since we will only allow to move and rotate the pieces.
|
||||
Most stacker game uses all one-sided polyominoes of size 4 (called tetrominos), which results in 7 distinct polyominoes.
|
||||
In this game too, one-sided polyominoes will be used since we will only allow to move and rotate the pieces.
|
||||
|
||||
Internally, polyominos are represented as a set of positions on a 2D grid.
|
||||
This means that 2 polyominos of same shape but at different places will be interpreted as different polyominos.
|
||||
To solve this, when doing equality checks, we normalize the polyominos so that their left-most column is at x=0 and their bottom-most row at y=0.
|
||||
Internally, polyominoes are represented as a set of positions on a 2D grid.
|
||||
This means that 2 polyominoes of same shape but at different places will be interpreted as different polyominoes.
|
||||
To solve this, when doing equality checks, we normalize the polyominoes so that their left-most column is at x=0 and their bottom-most row at y=0.
|
||||
|
||||
Even if there is only 7 one-sided 4-minos, there is already more than 9,000 one-sided 10-minos.
|
||||
Since the aim of this game is to be playable with polyominos of any size, listing all polyominos manually isn't viable.
|
||||
Since the aim of this game is to be playable with polyominoes of any size, listing all polyominoes manually isn't viable.
|
||||
We will need a way to automatically:
|
||||
|
||||
1. Generate all one-sided polyominos of size n
|
||||
1. Generate all one-sided polyominoes of size n
|
||||
2. Set their spawn positions and rotation centers
|
||||
|
||||
Aditionally, for this game we will also a want a way to separate the polyominos into multiple categories, specifically to allow removing those with holes who are harder to play with.
|
||||
Aditionally, for this game we will also a want a way to separate the polyominoes into multiple categories, specifically to allow removing those with holes who are harder to play with.
|
||||
|
||||
## Ordering the polyominos
|
||||
## Ordering the polyominoes
|
||||
|
||||
For practical reasons, we want to be able to sort all polyominos of the same size.
|
||||
For practical reasons, we want to be able to sort all polyominoes of the same size.
|
||||
But to sort objects we need a way to compare them.
|
||||
|
||||
When a polyomino is created, an attribute named its length is computed. This is simply the max between its width and its height. Thus the polyomino can be inscribed in a box of size ``length``.
|
||||
We will now assume that our polyominos are always inscribed in a box of origin (0,0) and size ``length`` (which should always be the case under normal circumstances).
|
||||
We will now assume that our polyominoes are always inscribed in a box of origin (0,0) and size ``length`` (which should always be the case under normal circumstances).
|
||||
|
||||
We can now compare polyominos using this method:
|
||||
We can now compare polyominoes using this method:
|
||||
|
||||
- If one polyomino has an inferior length than another, it is deemed inferior
|
||||
- If two polyomino have the same length, we check all the positions of their box, from left to right, and repeating from up to bottom, for the first position where a polyomino has a square and the another doesn't, the present polyomino which has a square is deemed inferior
|
||||
|
||||
A nice side-effect is that, once the polyomino are ordered, it is very simple to attribute them a block type, we can simply iterate through the list while looping over the block list.
|
||||
|
||||
## 1. Generating polyominos
|
||||
## 1. Generating polyominoes
|
||||
|
||||
The method used to generate polyominos is similar to the [inductive method](https://en.wikipedia.org/wiki/Polyomino#Inductive_algorithms) described in the previously mentionned Wikipedia page.
|
||||
The method used to generate polyominoes is similar to the [inductive method](https://en.wikipedia.org/wiki/Polyomino#Inductive_algorithms) described in the previously mentionned Wikipedia page.
|
||||
|
||||
The algorithm is the following:
|
||||
|
||||
@@ -64,15 +64,15 @@ The algorithm is the following:
|
||||
1. We add this square to the polyomino
|
||||
2. We call the generator function (recursive function!)
|
||||
3. We remove this square from the polyomino
|
||||
3. Return the list of polyominos
|
||||
3. Return the list of polyominoes
|
||||
|
||||
The exact number of one-sided polyominos up to size 15 (and higher, but we only generated up to size 15) is known, and this method generated exactly theses numbers, without duplicates.
|
||||
The exact number of one-sided polyominoes up to size 15 (and higher, but we only generated up to size 15) is known, and this method generated exactly theses numbers, without duplicates.
|
||||
|
||||
By marking squares and adding only ones that have a higher number than the last one everytime, we generate each fixed polyomino exactly n times. By ignoring the squares below y=0, or at exactly x=0 and y<0, we generate each fixed polyomino exactly 1 time.
|
||||
An one-sided polyomino has 4 rotations, some of which can be the same if the polyomino has symmetries. 2 rotations that are the same corresponds to 1 fixed polyomino, we will refer to theses 2 rotation as 1 "unique" rotation.
|
||||
Because we generate every fixed polyomino exactly 1 time, that means each "unique" rotation of an one-sided polyomino is generated exactly one-time, which includes its lowest rotation. That's how we can get away with only checking the rotation of the polyomino and not comparing it to the rest of the generated polyominos.
|
||||
Because we generate every fixed polyomino exactly 1 time, that means each "unique" rotation of an one-sided polyomino is generated exactly one-time, which includes its lowest rotation. That's how we can get away with only checking the rotation of the polyomino and not comparing it to the rest of the generated polyominoes.
|
||||
|
||||
## 2. Setting the spawn position of polyominos
|
||||
## 2. Setting the spawn position of polyominoes
|
||||
|
||||
Since we assume the polyomino is always inscribed in a box at origin (0,0), we can use formulae close to matrix rotations to rotate the piece:
|
||||
|
||||
@@ -91,19 +91,19 @@ The current algorithm for doing so is the following:
|
||||
1. Check if the polyomino has more lines horizontally or vertically, this will determine either 2 or 4 sides which are wider than the others, and the others will be discarded
|
||||
2. For each potential side check the number of square on the first line, if one has more than every others, then this side is choosed, else we only keep the sides that tied and repeat for the next line
|
||||
3. If we still have at least 2 sides tied, we do the same again but check the flatness of the side to the left instead, this will make the pieces overall have more squares to their left at spawn
|
||||
4. If there is still no winner, we sort the remaining sides (by simulating having them selectionned and then sorting the resulting polyominos) and keep the lowest
|
||||
4. If there is still no winner, we sort the remaining sides (by simulating having them selectionned and then sorting the resulting polyominoes) and keep the lowest
|
||||
5. We rotate the piece so that the chosen side ends up at the bottom of the polyomino
|
||||
6. We center the polyomino inside its box, since we chose the widest side it will always fill the width of the square, but for the height it can be asymmetric, in that case we place it one line closer to the top than the bottom
|
||||
|
||||
_Note we could actually just skip straight to step 4 because it always give the same orientation, but we want the spawn rotations to follow somewhat of a logic. Step 1 to 3 actually already works for 99% of polyominos and they constrain step 4 too by preselecting certain sides._
|
||||
_Note we could actually just skip straight to step 4 because it always give the same orientation, but we want the spawn rotations to follow somewhat of a logic. Step 1 to 3 actually already works for 99% of polyominoes and they constrain step 4 too by preselecting certain sides._
|
||||
|
||||
## 3. Separating the polyominos into categories
|
||||
## 3. Separating the polyominoes into categories
|
||||
|
||||
For this game, we want the polyominos to be broken down into 3 categories:
|
||||
For this game, we want the polyominoes to be broken down into 3 categories:
|
||||
|
||||
- Convex: this is said of a polyomino where every row and column is formed of at most one continous line of squares
|
||||
- Holeless: the polyominos which are neither convex nor have a hole
|
||||
- Others: the polyominos who have a hole (thoses are by definition not convex)
|
||||
- Holeless: the polyominoes which are neither convex nor have a hole
|
||||
- Others: the polyominoes who have a hole (thoses are by definition not convex)
|
||||
|
||||
To check for convexity, we simply iterate trough each row and column, and check if all the squares are contiguous.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user