1. Model and Engine - meng-zx/aechess-team GitHub Wiki
Story Map

Engine Architecture

Front-end AR Rendering
ARGomoku is a Gomoku game based on the Vuforia Engine. The engine receives camera input and track markers around the chess board and on the newly put chess, so as to get the 3D coordinate of the chess board and chess piece.
Rendering AR image on the user's phone is done by Unity.
The AR engine runs on the front-end. As a result, we will build our front-end application with Unity, which is well-compatible with Vuforia. After getting the chess board location from Vuforia Engine and opponent's chess pieces location from the back-end, the opponent's chess pieces can be rendered by Unity on user's phone.
Game Registration
The player could start matchmaking with a button click on the front-end. Before the game starts, the user will need to send their info to the matchmaking server to find an opponent. The info includes user's identifier and preferred game rules. The server will find an opponent or create an AI opponent for the player, then return info of the new game, including game id and other game configs.
Once searching is done on the matchmaking server, the player's front-end will be notified and connect to the game server with game id. A game starts when both sides have established connection with the game server.
During Game
The game proceeds as players take turns to put pieces onto the board. A sample movement in player 1's round goes as follows:
Player 1 puts a chess piece on a physical board, and then put an AR marker on it. The AR Engine will read camera input and get the position of the new chess piece relative to the board. We then calculate its relative location to the board. The 3D coordinate for the relative location will be sent to the game server and stored. The server computes which cross the chess is put on, and decides whether the game is over. The locations for all of the player 1's chess pieces will be sent to player 2's front-end, and they will be rendered on player 2's device. Now player 1's round finishes, and player 2's round will similarly proceeds.
Store Chess Positions in PostgreSQL database
When the player, rival player/AI has played a move, the game server stores that move into the corresponding table associated with the game ID. This in turns allow huge amount of data to be indexed on the game server. So multiple gameplays can be established and run concurrently.
Gomoku API (not implemented): If the user has selected the
game_with_aimode, the game server would connect to a Gomoku API. Then whenever the player plays a move, the server would send that move to that Gomoku API and send back the AI's corresponding move.
Detailed Implementation
Database Schema
1. Match queue
MATCH_QUEUE is used to store the user information for matching purpose. Record won't be deleted when users are matched, but it will be deleted when user finishes the game and send clearrecords request. This is to ensure every active user has a unique USERID.
MATCH_QUEUE:
| field | type | description |
|---|---|---|
USERID |
int | user's unique id |
RULEID |
int | user's choice of rule |
TIMESTAMP |
Date/Time Types | user's last request time |
MATCHED |
bool | whether user has been matched |
2.Game info
GAME_INFO stores the status of a game, such as whose turn is it now, whether the game has ended etc.
GAME_INFO:
| field | type | description |
|---|---|---|
USERID |
int | user's unique id |
OPPONENTID |
int | opponent's userid |
PLAYER_TURN |
bool | whether it's this player's turn |
GAME_STATUS |
string | The status of game. Can be "OnGoing", "Win", or "Lose". |
PIECE_CNT |
int | Count how many pieces user has put. |
3.New piece info
NEW_PIECE_INFO stores the position of the newly put piece.
NEW_PIECE_INFO:
| field | type | description |
|---|---|---|
USERID |
int | user's unique id |
X |
int | x component of the newly put piece |
Z |
int | z component of the newly put piece |
4. All pieces info
ALL_PIECES_INFO stores all the pieces in all the games.
ALL_PIECES_INFO :
| field | type | description |
|---|---|---|
USERID |
int | user's unique id |
X |
int | x component of the piece |
Z |
int | z component of the piece |
Backend Implementation
1.1 Game matching
When the front-end start matching, the backend either matches the player with an opponent with the same game rule or places it in the matching queue. Link to code
Endpoint: POST /gamestart/
Request Parameters:
| key | type | description |
|---|---|---|
| ruleid | int | user's choice of rule |
Steps:
-
- Assign a unique
useridto the user.
- Assign a unique
-
- Push the record into
MATCH_QUEUE.
- Push the record into
-
- [MVP] Delete the record if the timestamp is longer than 10 min.
-
- Search in the
MATCH_QUEUE, check if there's any record match this one (Same rule)
- Search in the
-
- If found a record that match, set
MATCHEDtoTruefor both record, and create records inGAME_INFOfor both of them.
- If found a record that match, set
-
- If no match, do nothing, leave the record there.
-
- Return
useridno matter matched or not.
- Return
2.1 Wait for match
The backend either returns the information of the matched player or tells the front end it's still queuing. Link to code
Endpoint: POST /waitformatch/
Request Parameters:
| key | type | description |
|---|---|---|
| userid | int | user's assigned id |
Steps:
-
- Check whether user's record is in
GAME_INFO. If user's record inGAME_INFO, return:
- Check whether user's record is in
| key | type | description |
|---|---|---|
| isFirst | boolean | First to go or not |
| status | string | "matched" |
-
- If user record not in
GAME_INFO, it means user is not matched. [MVP] Update the timestamp inMATCH_QUEUE.
- If user record not in
-
- Return:
| key | type | description |
|---|---|---|
| isFirst | bool | True |
| status | string | "continue waiting" |
2.2 Player send new piece
Store the new piece placed by the user into the database. Link to code Also the back end will check if the new piece leads to the wining of that player. Link to code If so, the back end returns the winning state of the game.
Endpoint POST /sendpiece/
Request Parameters:
| key | type | description |
|---|---|---|
| userid | int | user's assigned id |
| marker_location | string | (x,y,z) of the marker's relative position |
Steps:
-
- Check the
GAME_STATUSinGAME_INFO, if the game has ended, return:
- Check the
| key | type | description |
|---|---|---|
| status | string | "end game" |
-
- Change the new piece in
NEW_PIECE_INFOtomarker_location.
- Change the new piece in
-
- Add the record to
ALL_PIECES_INFO.
- Add the record to
-
- In
GAME_INFOtable, correspondingPIECE_CNT+=1.
- In
-
- [MVP] Calculate whether player wins. If player wins, change player's
GAME_STATUSinGAME_INFOfrom"OnGoing"to"Win", change opponent'sGAME_STATUSfrom"OnGoing"to"Lose".
- [MVP] Calculate whether player wins. If player wins, change player's
-
- Set player's
PLAYER_TURNinGAME_INFOtoFalse, opponent'sPLAYER_TURNtoTrue
- Set player's
-
- Return:
| key | type | description |
|---|---|---|
| status | string | "opponent turn" |
2.3 Check game status
The back end returns the status of the game (ongoing/win/lose). Link to code
Endpoint: POST /checkstatus/
Request Parameters:
| key | type | description |
|---|---|---|
| userid | int | user's assigned id |
Steps:
-
- Check the
GAME_STATUSinGAME_INFO, if the game has ended, return:
- Check the
| key | type | description |
|---|---|---|
| status | string | "end game" |
| new_piece_location | string | (0,0,0) |
-
- Check if it's player's turn by
PLAYER_TURNinGame_info
- Check if it's player's turn by
-
- If
PLAYER_TURN == False, return:
- If
| key | type | description |
|---|---|---|
| status | string | "opponent turn" |
| new_piece_location | string | (0,0,0) |
-
- If
PLAYER_TURN == True, find opponent's new piece, return:
- If
| key | type | description |
|---|---|---|
| status | string | "player turn" |
| new_piece_location | string | opponent's new piece (x,y,z) |
2.4 End game request:
The front-end user leaves the game, the back-end lets this user lose the game. Link to code
Endpoint: POST /endgame/
Request Parameters:
| key | type | description |
|---|---|---|
| userid | int | user's assigned id |
Steps:
-
- If
useridis inGame_info, set player'sGAME_STATUSinGAME_INFOfrom"OnGoing"to"Lose", set opponent'sGAME_STATUSfrom"OnGoing"to"Win".
- If
-
- If player is unmatched in the
MATCH_QUEUE, setMATCHEDtoTrue.
- If player is unmatched in the
-
- Return
status = 'ended'
- Return
3.1 Check end game stats
Check the stats of the game after game ends. Link to code
Endpoint POST /checkwin/
Request Parameters:
| key | type | description |
|---|---|---|
| userid | int | user's assigned id |
Steps:
-
- If
useridinGame_info, returns:
- If
| key | type | description |
|---|---|---|
| isWin | bool | True if win, "False" otherwise |
| num_piece | int | number of pieces in the game |
-
- Otherwise, return:
| key | type | description |
|---|---|---|
| isWin | bool | False |
| num_piece | int | number of pieces in the game |
3.2 Clear user records in database
Clear user records regarding this game in the database. Link to code
Endpoint: POST /clearrecords/
Request Parameters:
| key | type | description |
|---|---|---|
| userid | int | user's assigned id |
Steps:
-
- Clear all the records related to
useridinGAME_INFO,NEW_PIECE_INFO, andALL_PIECES_INFO.
- Clear all the records related to
-
- Clear all the records related to
useridinMATCH_QUEUE.
- Clear all the records related to
-
- Return:
status = 'cleared'
- Return: