Skip to content

harry5z/Sanguosha

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

Repository files navigation

Table of Content

  1. Overview
  2. How To Play
  3. Architecture
  4. System Design
  5. TODOs/Further Thought

Overview

Sanguosha, or loosely translated as "Battles of the Three Kingdoms", is a multiplayer turn-based board game. This project implements Sanguosha as an online multiplayer game.

Implementation: It includes both the game server written in Java and a game client implemented with Java Swing library. The server and client communicate via Java Socket.

Size: As of 06/11/2022, about 20K lines of code.

Click to see details

Sanguosha was a popular board game in China. The game is based on the historical events of the Three Kingdoms, a historical period in ancient China around 220–280 AD. See also Sanguosha official website (in Chinese).

The core part of the game is the variety of heroes and their skills, which by an implicit rule maintain that the name and description of a hero's skill should more or less reflect the historical facts about the hero. Many even learned a lot about the history of the Three Kingdoms through playing different heroes. In the early 2010s, many players of the game invented their own versions of Sanguosha, in which heroes are replaced with friends, family members, celebrities, etc. Most of these "heroes" also abide by the rule of accuracy of facts. For example, a student with skill "diligence" (whose effect may be "drawing extra X cards each turn"), a teacher with skill "homework", or perhaps Obama with skill "medicare" (description may be "let a player discard 1 card to regain 1 HP when their HP is below 2").

However, most of these designs were limited to a graphic design of the hero card, as actually printing and playing these hero cards were infeasible to most people. The player base was primarily students busy at schoolwork who had little time to gather for a game, which usually lasts more than 20 minutes. Additionally, due to the complex system of rules of Sanguosha, face-to-face games are prone to human errors (e.g. forgetting to trigger a passive skill), which sometimes can be very frustrating. As an example, see this page, also in Chinese, for a detailed breakdown of rules and game flow.

These issues were the original motives of my project. A big fan of Sanguosha, I wanted to build a secure, consistent, and extensible Sanguosha framework that allowed my friends and I to play online with few errors in game flow and allowed easy addition of custom "heroes" and skills.

How to play

Play on live server

Run/Test locally

Architecture

Both the game server and Java Swing client are MVC based and event-driven to maximize extensibility and modularity. Several components are used by both server and client because of their similarity.

Model

The game essentially evolves around the states of its Players, each of whom has a Role, a Hero, some Cards, and some statuses such as Health Points. The game ends when a player of certain Role dies, see game-end conditions.

The majority of player information is public (e.g. a player's Hero, Equipments, HP) to all players. The only information private to a player themselves is their hand (of cards) and their Role (except the Emperor), which is revealed only upon death. As such, a player sees other players as SimplePlayers without Role and hand information, and themselves as a CompletePlayer with all information available.

  • At server side, all Players are initialized as CompletePlayer as server is omniscient.
  • At client side, only a player themselves is initialized as CompletePlayer, while all other players are represented as SimplePlayer.

View

The view on both server and client is represented by a number of Listeners on Player reacting to state changes such as receiving/losing Cards, gaining/losing HP.

  • At server side, Server-side Listeners are synchronizers that simply send SyncCommands to clients to update client-side player statuses, see example.
  • At client side, Client-side Listeners are GUI components that visually shows the statuses to the human player, see example.

Controller

  • At server side, the game employs a Stack of GameControllers that control the gameflow and modify Players, each with a Stage to track the progress of its own lifecycle. See an example.
  • At client side, there is no "Controller". The client is designed with Server-driven UI, specifically, only a SyncCommand from server may modify client-side Model, which must always be consistent with server.

Event-driven Game Flow

Sanguosha is characterized by a turn-based game flow with many actively or passively triggered Hero Skills and Equipment abilities, which frequently interrupt the game to wait for player actions to proceed.

At server side, the game continuously drive the current GameController (which may push other GameControllers on top of itself), until a player action is required and the GameController throws a GameFlowInterrupedException to "pause" the game and send a PlayerActionGameClientCommand to request player action. The player may respond with an InGameServerCommand (or server takes a default response upon timeout), which "resumes" the game until the next player action is required.

System Design

Overview

The design concerns are listed below ranked by importance (high to low):

Tier 1
  • Extensibility: The framework must be extensible to allow easy addition of new heroes, skills, features, etc.
  • Security: The game must avoid cheating, leaking, and sniffing for personal information, etc.
Tier 2
  • Recovery: Must be internally tolerant to errors like race conditions, and externally tolerant to user failures like internet disconnection.
  • Performance: Minimize network usage, memory & CPU usage, and avoid memory leaks.
Tier 3

A few other common design concerns have been deprioritized for various reasons, listed below:

  • Scalability: As a turn-based game, the frequency of client-server communication is significantly lower than a real-time game. If server capacity is reached, we can move ongoing games (the most traffic-intense part) to dedicated servers.
  • Cross-platform API: For the first iteration, the game is built with a Java Swing client communicating with server via Socket. In future iterations, a generic API for cross-platform clients (e.g. Android/iOS, web, PC/Mac native app) can be built on top of the existing framework.
  • Unit/Integration Testing: In my opinion, testing is necessary for a real-world online game, but the workload overhead is beyond the capability of one developer.

Additionally, the game client's UI and UX are deprioritized, because (1) the first iteration focuses on functionality and proof of concept, and (2) players of this game should already know how to play without hints, as they should have played the in-person board game already.


Extensibility

The MVC architecture is built so that new heroes and skills can be added quickly, with minimum edits to existing code. For example, see the commits for:

  • Wei Yan, a hero with a passive skill (no player action). 100 lines.
  • Huang Zhong, a hero with a passively-triggered skill (player must confirm). 150 lines.
  • Yuan Shao, a hero with an active skill (player proactively activates). 240 lines.

Security

The game's security consists of 3 parts, Anti-cheat, Anti-leak, and Anti-sniff.

  • Anti-cheat: there are

    • Illegal Player Actions. A player may attempt to set an invalid target, use a Card/Equipment/Skill they do not have, use fewer/more than required Cards, etc.

    • Game Flow Disruption. A player may attempt to act when not allowed to, or the game may receive a previously valid but currently illegal action due to network delay.

      • Solution: Send a server-generated Response ID to accept actions only from players who may act. See example.
    • Impersonation. A player may attempt to act on behalf of another player.

  • Anti-leak: The game does not send to players any information they should not know of. For example, a player's hand is private, so when a player receives/loses a Card, only that player is sent the concrete Card information, whereas other players only receive a command to increment/decrement that player's card count.

  • Anti-sniff: The client-server communication is currently unencyrpted, because no password information is present. However, it is therefore vulnerable to man-in-the-middle attacks. See TODO list.

Recovery

Player Reconnection

If a player disconnects while in-game, the server marks them as disconnected, and if they reconnects in time, they will be redirected back into the game and sent the latest game states, so that they can resume playing. If a player disconnects while not in-game, they're considered logged out.

Performance

As a turn-based game, the server sends frequent updates to clients while in-game, while clients only send sporadic actions to server.

  • Throttling: Server periodically flushes all updates sent to a client. Current "server tick" interval is 0.1s
  • Aggregated Request: All updates to be sent to a client during a server tick is combined into a single request

Learnability

As the project grows in size, components must be easily understandable and built to avoid human errors such as using the wrong method by accident. For example:

TODO List

Server-side

  • Build generic JSON-based API for clients on different platforms
  • Add HTTPS-like encryption for client-server communication
  • Cover major game flows with integration tests
  • Add CPU & Memory monitoring and create alerts

Client-side

  • Synchronous Execution. Make sure to execute updates sent by the server in chronological order
  • Prettify client UI and add animations
  • Allow Chats

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages