# Slots
Code name: `slots` (plural, because this is for a set of multiple games on the
FE menu, not just a single game).
## About
There's a box contains multiple reels, each reels has a number of symbols (9,
10 or even 12). User can place bet follow some custom rules, and spin the
reels. After that, base on the visible part of the reels and predefined set of
paylines, user may or may not get reward.
Let see some example before going through more concepts.
## Examples
### Slots 3x3
- 3 reels
- Each one has many symbols, minimum is 9.
- Each real has 3 visible symbols after spin, there symbols may or may not be
repeated, may or may not maintain the order. This can be customized from our
game config.

### Slots 3x5
- 5 reels
- Each one has many symbols, minimum is 9.
- Each real has 3 visible symbols after spin, there symbols may or may not be
repeated, may or may not maintain the order. This can be customized from our
game config.

## Concepts
### Traditional Slot
The reels in physical slots machines is has 9 symbols, fixed order, thus, we
can have 9^3 possible output for `slot_3x3` and 9^5 possible output for
`slot_3x5`. The chances to win this is quite small.
To support this type of slots, our implementation should take following params:
- Number of reels: 3 or 5
- Number of symbols per reels: minimum is 9
- Skins for the symbols.
- All reels need to maintains same order of symbols (1, 2, 3, ... 10)
- The paylines for this type of games, vary depends on number of reels.
### Video Slot
Since computer become popular, the game is implemented using software. And
because it's not physical machine, there's no need to keep the symbols order,
and no need to avoid repeated symbols. So, some casinos add mew rules, new
symbols, more increase the possible patterns, and more chance for user to
wins.
To support this type of slots, our implementation should take the same params
with Traditional Slot, with following changes:
- There's some special symbols that can change how the paylines are constructed
and the reward.
- Reels no need to maintain symbol orders.
- Symbols can or can not repeat within a reel.
### Symbols
There's can be 3 kinds
- `Normal`: Traditional slots only have this kind of symbols. They're label from
1 to `n` (`n` is number of Normal symbols).
Video Slot can contains following symbols, and it's up to us to implement them
or not:
- `Wild`: can substitute any other symbols to make the best paylines, can
appear only in reel 2, 3, 4 and 5.
- `Bonus`: when this type of symbols appears on the reels, user may get
additional reward or some mini games are triggered. This is totally up to our
implementation and the business/marketing.
- `Free spins`: similar to `Bonus` types, if the `Free spins` symbols appear
and match game condition, user will get additional spins for free.
### Paylines
Paylines are special patterns of the reels that rarely happens.
Let's consider slot 3x5 matrix, with `X` is one of our symbols, following
pattern of `X` are most common paylines (there's over 30 possible paylines for
3x5):
```
X X X X X
- - - - -
- - - - -
```
```
- - - - -
X X X X X
- - - - -
```
```
- - - - -
- - - - -
X X X X X
```
Note that `Wild` (`W`) can replace any `X` and still turn above pattern valid
paylines
```
- - - - -
- - - - -
W X X X X
```
```
- - - - -
- - - - -
X W X X X
```
- Paylines are predefined for each slots games.
- Paylines are only from left to right.
- For each bet, user can pay an amount on a payline, and can pay for one or
many paylines as their will.
- For each selected paylines appears in the visible patterns after spin, user
get corresponding reward.
## API
Since this game is complicarted, we will start with the API design and explain
our thought before get to the DB design.
### RPC API
#### User to place bet
```
POST /api/game/slots/bet
```
Request:
```json
{
"game_type": 2,
"bet_per_pay_line": 100,
"pay_lines": [
"3X3_01",
"3X3_02",
"3X3_03"
]
}
```
Explain the request:
- `pay_lines` contains a list of selected paylines
- `bet_per_pay_line` is amount of money per payline. The total bet amount will
be the multiplication of number of paylines and `bet_per_payl_ine`
- `game_type` is the enum value of the game type. For the example, let just say
`4` mean `slot_3x5_video`. The server will base on the game type, generate
reels data and calculate bet result.
Response
```json
{
"all_reels": [
[1, 13, 12],
[1, 15, 11],
[1, 15, 11]
],
"pay_line_results": [
{
"game_result": 1,
"pay_line": "3X3_01",
"reward_amount": 500,
"symbol": 1,
"symbol_count": 3
},
{
"game_result": 2,
"pay_line": "3X3_02",
"reward_amount": 0,
"symbol": 13,
"symbol_count": 1
},
{
"game_result": 2,
"pay_line": "3X3_03",
"reward_amount": 0,
"symbol": 12,
"symbol_count": 1
},
{
"game_result": 2,
"pay_line": "3X3_04",
"reward_amount": 0,
"symbol": 15,
"symbol_count": 2
},
{
"game_result": 2,
"pay_line": "3X3_05",
"reward_amount": 0,
"symbol": 12,
"symbol_count": 1
}
],
"total_reward_amount": 500
}
```
### User to query game records
Since we have only 1 endpoint to support multiple type of slots, caller needs to
specify game type to query correct game records.
`POST /api/me/slot/get?q[game_type]=eq:4`
Request:
api/game/slot/bet
```json
{
"game_type": 2,
"bet_per_pay_line": 1000000,
"pay_lines": ["3X3_01","3X3_02","3X3_03","3X3_04","3X3_05"]
}
```
Response:
```json
{
"all_reels": [
[14, 15, 12],
[17, 17, 12],
[18, 13, 15]
],
"pay_line_results": [
{
"game_result": 2,
"pay_line": "3X3_01",
"reward_amount": 0,
"symbol": 14,
"symbol_count": 1
},
{
"game_result": 2,
"pay_line": "3X3_02",
"reward_amount": 0,
"symbol": 15,
"symbol_count": 1
},
{
"game_result": 2,
"pay_line": "3X3_03",
"reward_amount": 0,
"symbol": 12,
"symbol_count": 2
}
],
"total_reward_amount": 0
}
```
You might notice that the response is just a con of user bes request and
response. Yes, that would be enough for to display game history.
However, this design can't fully support history tracing. If we change the
paytables, i.e: increase pay rate of full 5 slots from 10x to 20x; user might
get confused when checking their game records.
## DB
Now we understand how the API should works, let see how the we organize the
data.
### Game config
- Table name: `slots_game_config`
- Should have Audit and Comment
- Fields:
- `id`, `ctime`, `mtime`, `status`
- `game_type`: not null, enum, skin of the game, this is related to a game on
FE game menu, and each one has a different paytable.
- `partner_id`: not null, but unlike other tables, this is not unique, because each
Partner might choose to enable one or more skins.
- unique key on `(partner_id, game_type)`.
### Game record
- Name: `slots_game_record`
- Fields:
- `id`, `ctime`: no `mtime` and `status` because this is read-only
- `total_bet_amount`: how much money user bet for all of his selected
paylines.
- `total_reward_amount`: how much money user got after the bet
- `bets`: JSON string of the `bets` map of payline and amout for that line.
- `game_type`
- `all_reels`: JSON string of the generated matrix.
- `payline_results`: JSON array of number of the winning lines and respective
reward.
- `result_type`: `UserWin` if `total_bet_amount` is less than
`total_reward_amount`, or `UserLose` otherwise.
Note that to support dynamic data, we have to compromise our design, use JSON
to store the bets and the matrix instead of named columns. This is acceptable
given our data size is small (up to 1000 paylines, 15 number for the `all_reels`,
and up to 1000 key-value for the `payline_results`).
> TODO (jl): check if we can use postgres jsonb for those JSON fields.
> sqlboiler seems to be able to generate it >
## Game Type
- This is an enum.
- Each game type related to a visible game on the game menu
- Each game type has its own paytable (it doesn't prevent 2 game types to have same
paytable, though).
- Each game type has its own graphics (game types might have same graphics, but
different in other params, such as number of Symbols, or Paytable, ...)
- Example possible values:
- `slot_3x3_traditional`: 1
- `slot_3x3_video`: 2
- `slot_3x5_traditional`: 3
- `slot_3x5_video`: 4
- `slot_3x3_video_with_bonus`: 5
- `slot_3x3_traditional_jungle`: 6
- `slot_3x3_traditional_batman`: 7
- `slot_3x3_video_jungle`: 8
- `slot_3x3_video_batman`: 9
Given above requirements, we can see that whenever we add a new game types,
following things must be done:
- BA design the pay tables and rate, make sure that we won't lost money with
that paytable.
- BE add new game type, associates it with the defined paytable.
- Designer works on new symbol graphics.
- FE add new game on the menu, with the new graphics.
## Implementation
- A user enter game table and press play
- Card backend (CB) authorize user session. If session valid move to next step,
otherwise return 401
- CB validate user's bet. If request valid move to next step, otherwise return
403
- validate whether bet amount exceed user's balance
- CB generate 3 values of first_reel, second_reel, third_reel, fourth_reel, and
fifth_reel
- CB compute winning_lines and total_reward
- CB create a slot_3x5_game_record
- CB create a bet transaction
- CB update user wallet, that the balance is deducted by amount of user's bet
- If the user win any bet, reward user
- CB create a reward transaction, with change equal to total reward amount
- CB update user wallet, that the balance is added up by total reward amount
- CB return back to user
## Enums
Please refer [slot_enum](./slot_enum.md)
## References
- https://www.winkslots.com/skin/magazine/slots-paylines.php
- https://en.wikipedia.org/wiki/Slot_machine
- https://www.onlinecasinoselite.org/free-slots/3-reels
- http://stoppredatorygambling.org/wp-content/uploads/2012/12/The-Secrets-of-a-Slot-Machine.pdf
this link is very good about internal of physical slots machine.