refactor: delete all landlords card game code and obsolete docs

Remove ~35 files: poker entities/enums/helpers, old robot AI,
legacy server/client event handlers, Chinese i18n, docker configs,
and obsolete markdown docs.
This commit is contained in:
2026-04-09 17:16:04 +07:00
parent 0d71b39f60
commit d871cc2352
38 changed files with 0 additions and 3114 deletions
-165
View File
@@ -1,165 +0,0 @@
# Gomoku Conversion Summary
## Overview
Successfully converted the Landlords card game server-client project to a Gomoku (Five-in-a-Row) game while preserving the underlying Netty-based architecture and event-driven communication system.
## Key Changes Made
### 1. Enums Updated for Gomoku
**ServerEventCode.java**
- Replaced landlord-specific events with Gomoku events
- Added: `CODE_GAME_MOVE`, `CODE_GAME_RESET`
- Removed: `CODE_GAME_LANDLORD_ELECT`, `CODE_GAME_POKER_PLAY*`
**ClientEventCode.java**
- Updated with Gomoku-specific client events
- Added: `CODE_GAME_MOVE_SUCCESS`, `CODE_GAME_MOVE_INVALID`, `CODE_GAME_WIN`, `CODE_GAME_LOSE`, `CODE_GAME_DRAW`
- Replaced: `CODE_SHOW_POKERS``CODE_SHOW_BOARD`
**SellType.java → PieceType.java**
- Complete replacement for Gomoku pieces
- Enum values: `EMPTY`, `BLACK`, `WHITE`
**New GameResult.java**
- Enum for game outcomes: `BLACK_WIN`, `WHITE_WIN`, `DRAW`, `IN_PROGRESS`
**ClientRole.java**
- Added: `BLACK_PLAYER`, `WHITE_PLAYER`
### 2. New Game Entities
**Board.java**
- 15x15 game board implementation
- Win detection for 5-in-a-row (horizontal, vertical, diagonal)
- Move validation and game state management
**GameMove.java**
- Represents a single move with position, piece type, and player ID
- Timestamp tracking for move history
**Room.java Updates**
- Removed landlord/poker-specific fields
- Added: `gameBoard`, `blackPlayerId`, `whitePlayerId`, `currentTurn`, `moveHistory`
- Added game management methods: `switchTurn()`, `resetGame()`, `isPlayerTurn()`
**ClientSide.java Updates**
- Removed poker-specific fields (`pokers`)
- Simplified for Gomoku gameplay
### 3. Game Logic Implementation
**GomokuHelper.java**
- Core game logic utilities
- Move validation and execution
- Board display formatting
- Move history formatting
- Win condition checking
**GomokuAI.java**
- Three difficulty levels (Easy, Medium, Hard)
- Strategic move evaluation
- Threat detection and blocking
- Position scoring system
### 4. Documentation Updates
**README.md**
- Updated title and description for Gomoku
- New gameplay rules and commands
- Board position format (row,col)
- Game commands: board, history, reset, pass, exit
**PROTOCO_CN.md**
- Updated from Landlords to Gomoku terminology
- Protocol documentation updated for game moves
**messages_zh_CN.properties**
- Added Gomoku-specific messages
- Move validation error messages
- Game result messages
### 5. Testing
**GomokuHelperTest.java**
- Comprehensive unit tests for game logic
- Tests for win conditions, move validation, turn management
- Board formatting and game reset functionality
## Architecture Preserved
### Network Layer
- Netty 4.x server-client communication maintained
- Protobuf serialization for data transfer
- TCP and WebSocket protocol support
### Event-Driven System
- Event listener pattern preserved
- Client-server event codes updated for Gomoku
- Reactive architecture maintained
### Room Management
- Multi-room support
- Spectator functionality
- PvP and PvE modes
## Game Features
### Core Gameplay
- 15x15 board with standard Gomoku rules
- Turn-based gameplay (Black moves first)
- Win condition: 5 pieces in a row
- Real-time move validation
### AI Support
- Three difficulty levels
- Strategic positioning algorithms
- Threat detection and blocking
### User Experience
- Command-line interface preserved
- Board visualization
- Move history tracking
- Real-time game state updates
### Multiplayer Features
- Room-based gameplay
- Spectator mode
- Player rankings and statistics
## Technical Implementation
### Game Board
- 2D array representation (15x15)
- Efficient win detection algorithms
- Move validation with bounds checking
### Turn Management
- Player role assignment (Black/White)
- Turn switching logic
- Game state tracking
### Communication Protocol
- Event-based messaging
- JSON data structures for game state
- Protobuf serialization for network efficiency
## Future Enhancements
### Planned Features
- Advanced AI algorithms (minimax with alpha-beta pruning)
- Tournament mode support
- Replay system
- Enhanced ranking system
- Move undo functionality
- Time limits per move
### Technical Improvements
- Performance optimizations for large-scale deployment
- Database integration for persistent game history
- Web-based client interface
- Mobile app support
## Conclusion
The conversion successfully transforms the Landlords game into a fully functional Gomoku game while maintaining the robust networking architecture and event-driven design patterns. The modular structure allows for easy extension and customization, making it suitable for both casual play and competitive gaming scenarios.
-176
View File
@@ -1,176 +0,0 @@
[toc]
# Gomoku-Client Development Documentation
## Introduction
### What is Gomoku Game
This is a project that allows you to play Gomoku (Five-in-a-Row) in the command line. You can use a compact jar package to play games in terminals with JVM environment, supporting both player vs player and player vs AI modes to enrich your leisure time!
The game is developed using Java language, with [Netty 4.x](https://github.com/netty/netty) network framework combined with [protobuf](https://github.com/protocolbuffers/protobuf) data protocol, supporting multiple clients playing simultaneously.
### Gomoku-Client Extension
The game is designed with reactive architecture, communicating through event codes. For Gomoku-Client, it supports cross-platform extension. In other words, any backend language can develop Gomoku-Client!
Before developing Gomoku-Client, you should know:
- Gomoku Server-Client interaction network protocol is ``TCP/IP``.
- Gomoku Server-Client interaction data protocol is [protobuf](https://github.com/protocolbuffers/protobuf).
- Gomoku is event-driven, connecting various components in the Client.
- All text content in Gomoku is displayed by the Client.
## Integration
### Architect Your Client
We can rewrite the Gomoku client using any backend language. The default Gomoku client is written in Java. If you want to rewrite it in other languages, here's a recommended architecture:
![](https://user-gold-cdn.xitu.io/2018/11/17/16720fa649dfaea0?w=898&h=500&f=png&s=33655)
This architecture is very friendly for event handling. You can design an abstract ``Event-Listener`` interface, then develop different implementations to handle response data for different ``CODE`` values. For example, a simple example - Poker display, here's the pseudo code for our processing flow:
```
1. Decode server response data ->
decode(msg)
2. Decoded data ->
ClientData{
String code;
String data;
}
3. Find corresponding EventListener through code ->
showPokersEventListener = Map<code, EventListener>.get(code)
4. Process response data ->
showPokersEventListener.call(server, data){
show(data);
server.write(msg);
}
```
The above is just a simple ``Server-Client`` interaction flow. Sometimes there might be ``Client-Client`` scenarios, such as displaying client option panels. When we switch from layer A to layer B, then return from layer B to layer A, we need to handle ``Client-Client`` interactions.
Of course, most interactions focus on ``Server-Client``. On the other hand, clients mostly handle and display server response data, with little actual business interaction. For clients, as long as events are absolutely rich, the client flow will be absolutely flexible. Therefore, Ratel's client response events are several times more numerous than server response events, so the architectural requirement for clients is to have sufficient flexibility to support the following two business flows:
- Server-Client-Server
- Server-Client-Client-Server
Next, let's move to the next step!
### Define Data Entities
For data interaction between client and server, we need to design two classes to store encoded and decoded data. It's worth mentioning that client and server have the same data structure, both composed of three fields: ``CODE``, ``DATA``, and ``INFO``:
- CODE - Corresponding event
- DATA - Transmitted data
- INFO - Information (not used for now)
Our encoding/decoding method is ``Protobuf`` serialization. Please refer to the files [here](https://github.com/ainilili/ratel/tree/master/protoc-resource).
### Integration Protocol
After preparing for integration, you can start implementing client business through the following protocol documentation!
#### Client Events
##### Connection Success Event
- ``CODE`` - CODE_CLIENT_CONNECT
- ``TYPE`` - TEXT
- ``DATA`` - Client assigned ID
##### Exit Room Event
- ``CODE`` - CODE_CLIENT_EXIT
- ``TYPE`` - JSON
- ``DATA`` - As follows
Field Name | Meaning
---|---
roomId | Room ID
exitClientId | Exiting player ID
exitClientNickname | Exiting player nickname
Reference data:
```
{"roomId":14,"exitClientId":64330,"exitClientNickname":"nico"}
```
##### Client Kick Event
- ``CODE`` - CODE_CLIENT_KICK
- ``TYPE`` - Text
- ``DATA`` - NULL
##### Set Nickname Event
- ``CODE`` - CODE_CLIENT_NICKNAME_SET
- ``TYPE`` - JSON
- ``DATA`` - As follows
Field Name | Meaning
---|---
invalidLength | Valid length, this field is returned when setting nickname exceeds 10 bytes
Reference data:
```
{"invalidLength":10}
```
##### Landlord Election - Landlord Confirmed Event
- ``CODE`` - CODE_GAME_LANDLORD_CONFIRM
- ``TYPE`` - JSON
- ``DATA`` - As follows
Field Name | Meaning
---|---
roomId | Room ID
roomOwner | Room owner nickname
roomClientCount | Room player count
landlordNickname | Landlord nickname
landlordId | Landlord ID
additionalPokers | Additional three cards
Reference data:
```
{"roomId":14,"roomOwner":"nico","roomClientCount":3,"landlordNickname":"robot_2","landlordId":-8,"additionalPokers":[{"level":"LEVEL_5","type":"DIAMOND"},{"level":"LEVEL_6","type":"CLUB"},{"level":"LEVEL_A","type":"DIAMOND"}]}
```
##### Landlord Election - No One Elected Event
- ``CODE`` - CODE_GAME_LANDLORD_CYCLE
- ``TYPE`` - TEXT
- ``DATA`` - NULL
TIP: After this event triggers, a restart game event will be triggered continuously
##### Landlord Election - Landlord Election Decision Event
- ``CODE`` - CODE_GAME_LANDLORD_ELECT
- ``TYPE`` - JSON
- ``DATA`` - As follows
Field Name | Meaning
---|---
roomId | Room ID
roomOwner | Room owner nickname
roomClientCount | Room player count
preClientNickname | Previous client nickname
nextClientNickname | Next client nickname
nextClientId | Next client ID
Reference data:
```
{"roomId":14,"roomOwner":"nico","roomClientCount":3,"preClientNickname":"nico1","nextClientNickname":"nico2","nextClientId":2}
```
##### Game Over Event
- ``CODE`` - CODE_GAME_OVER
- ``TYPE`` - JSON
- ``DATA`` - As follows
Field Name | Meaning
---|---
winnerNickname | Winner nickname
winnerType | Winner type (Landlord? Peasant)
Reference data:
```
{"winnerNickname":"nico","winnerType":"LANDLORD?PEASANT"}
```
-13
View File
@@ -1,13 +0,0 @@
> Version 1.0.0 Updated
- Create room
- Join room
- Play game
> Version 1.1.0 Updated
- Service list selection
- The Robot model
- Nickname length verify
- Room timeout detection
- Let's replace the room timeout with Robot
-60
View File
@@ -1,60 +0,0 @@
1. [安装`docker`](https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-using-the-convenience-script)
```
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
2. 客户端
+ 直接使用已经编译好的客户端
- `docker` 运行客户端,默认加入公网服务器 `39.105.65.8`
```
docker run --rm -it kebyn/ratel:client
```
等同于
```
docker run --rm -it kebyn/ratel:client -- 'java -jar *.jar -h 39.105.65.8'
```
- `docker` 运行客户端,加入公网服务器 `x.x.x.x`
```
docker run --rm -it kebyn/ratel:client -- 'java -jar *.jar -h x.x.x.x'
```
+ 自行编译 `docker` 客户端
- 下载并编译
```
git clone https://github.com/ainilili/ratel.git
cd ratel/docker/client
docker build -f Dockerfile -t ratel:client .
```
- 使用 `docker` 运行客户端,默认加入公网服务器 `39.105.65.8`
```
docker run --rm -it ratel:client
```
等同于
```
docker run --rm -it ratel:client -- 'java -jar *.jar -h 39.105.65.8'
```
- `docker` 运行客户端,加入公网服务器 `x.x.x.x`
```
docker run --rm -it kebyn/ratel:client -- 'java -jar *.jar -h x.x.x.x'
```
3. 服务端
+ 直接使用已经编译好的服务端
- `docker` 运行客户端,并指定使用`1024`端口
```
docker run --rm -d -p 1024:1024 kebyn/ratel:server
```
+ 自行编译 `docker` 客户端
- 下载并编译
```
git clone https://github.com/ainilili/ratel.git
cd ratel/docker/server
docker build -f Dockerfile -t ratel:server .
```
- 使用 `docker` 运行客户端
```
docker run --rm -d -p 1024:1024 ratel:server
```
等同于
```
docker run --rm -d -p 1024:1024 ratel:server -- 'java -jar *.jar -p 1024'
```
> 确保服务器防火墙允许`1024`端口访问,并且没有其它应用占用`1024`端口
-10
View File
@@ -1,10 +0,0 @@
FROM maven:3-jdk-8
RUN git clone https://github.com/ainilili/ratel.git
WORKDIR /ratel
RUN mvn install package
FROM openjdk:8-slim
COPY --from=0 /ratel/landlords-client/target/*.jar /opt
WORKDIR /opt
ENTRYPOINT ["bash", "-c"]
CMD ["java -jar *.jar -h 39.105.65.8"]
-10
View File
@@ -1,10 +0,0 @@
FROM maven:3-jdk-8
RUN git clone https://github.com/ainilili/ratel.git
WORKDIR /ratel
RUN mvn install package
FROM openjdk:8-slim
COPY --from=0 /ratel/landlords-server/target/*.jar /opt
WORKDIR /opt
ENTRYPOINT ["bash", "-c"]
CMD ["java -jar *.jar -p 1024"]
@@ -1,39 +0,0 @@
package org.nico.ratel.landlords.client.event;
import java.util.List;
import java.util.Map;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_LANDLORD_CONFIRM extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
String landlordNickname = String.valueOf(map.get("landlordNickname"));
int baseScore = (Integer) map.get("baseScore");
String baseScoreString;
if (baseScore == 1) {
baseScoreString = "1 score";
} else {
baseScoreString = baseScore + " scores";
}
SimplePrinter.printNotice(landlordNickname + " has become the landlord with " + baseScoreString + " and gotten three extra cards");
List<Poker> additionalPokers = Noson.convert(map.get("additionalPokers"), new NoType<List<Poker>>() {});
SimplePrinter.printPokers(additionalPokers);
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}
@@ -1,15 +0,0 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_LANDLORD_CYCLE extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("No player takes the landlord, so redealing cards.");
}
}
@@ -1,79 +0,0 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_LANDLORD_ELECT extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
int turnClientId = (int) map.get("nextClientId");
int highestScore = (int) map.get("highestScore");
if (map.containsKey("preClientNickname")) {
if (highestScore != 0 && map.get("preClientId") == map.get("currentLandlordId")) {
SimplePrinter.printNotice(map.get("preClientNickname") + " robs the landlord with " + highestScore + " score" + (highestScore == 1 ? "" : "s") + "!");
} else {
SimplePrinter.printNotice(map.get("preClientNickname") + " don't rob the landlord!");
}
}
if (turnClientId != SimpleClient.id) {
SimplePrinter.printNotice("It's " + map.get("nextClientNickname") + "'s turn. Please wait patiently for his/her confirmation !");
} else {
String message = "It's your turn. What score do you want to rob the landlord? [0";
for(int i = highestScore + 1; i <= 3; ++i) {
message = message + "/" + i;
}
message = message + "] (enter [exit|e] to exit current room)";
SimplePrinter.printNotice(message);
String line = SimpleWriter.write("getScore");
if (!line.equalsIgnoreCase("exit") && !line.equalsIgnoreCase("e")) {
try {
int currentScore = Integer.parseInt(line);
if (currentScore <= highestScore && currentScore != 0 || currentScore > 3) {
SimplePrinter.printNotice("Invalid options");
this.call(channel, data);
return;
}
String result;
if (currentScore > highestScore) {
result = MapHelper.newInstance()
.put("highestScore", currentScore)
.put("currentLandlordId", SimpleClient.id)
.json();
} else if (map.containsKey("currentLandlordId")) {
result = MapHelper.newInstance()
.put("highestScore", highestScore)
.put("currentLandlordId", (int) map.get("currentLandlordId"))
.json();
} else {
result = MapHelper.newInstance()
.put("highestScore", 0)
.json();
}
this.pushToServer(channel, ServerEventCode.CODE_GAME_LANDLORD_ELECT, result);
} catch (Exception e) {
SimplePrinter.printNotice("Invalid options");
this.call(channel, data);
}
} else {
this.pushToServer(channel, ServerEventCode.CODE_CLIENT_EXIT);
}
}
}
}
@@ -1,130 +0,0 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.print.SimpleWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ClientEventListener_CODE_GAME_POKER_PLAY extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice("It's your turn to play, your cards are as follows: ");
List<Poker> pokers = Noson.convert(map.get("pokers"), new NoType<List<Poker>>() {
});
SimplePrinter.printPokers(pokers);
SimplePrinter.printNotice("Last cards are");
SimplePrinter.printNotice(map.containsKey("lastPokers")?map.get("lastPokers").toString():"");
SimplePrinter.printNotice("Please enter the combination you came up with (enter [exit|e] to exit current room, enter [pass|p] to jump current round, enter [view|v] to show all valid combinations.)");
String line = SimpleWriter.write(User.INSTANCE.getNickname(), "combination");
if (line == null) {
SimplePrinter.printNotice("Invalid enter");
call(channel, data);
} else {
if (line.equalsIgnoreCase("pass") || line.equalsIgnoreCase("p")) {
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_PASS);
} else if (line.equalsIgnoreCase("exit") || line.equalsIgnoreCase("e")) {
pushToServer(channel, ServerEventCode.CODE_CLIENT_EXIT);
} else if (line.equalsIgnoreCase("view") || line.equalsIgnoreCase("v")) {
if (!map.containsKey("lastSellPokers") || !map.containsKey("lastSellClientId")) {
SimplePrinter.printNotice("Current server version unsupport this feature, need more than v1.2.4.");
call(channel, data);
return;
}
Object lastSellPokersObj = map.get("lastSellPokers");
if (lastSellPokersObj == null || Integer.valueOf(SimpleClient.id).equals(map.get("lastSellClientId"))) {
SimplePrinter.printNotice("Up to you !");
call(channel, data);
return;
} else {
List<Poker> lastSellPokers = Noson.convert(lastSellPokersObj, new NoType<List<Poker>>() {});
List<PokerSell> sells = PokerHelper.validSells(PokerHelper.checkPokerType(lastSellPokers), pokers);
if (sells.size() == 0) {
SimplePrinter.printNotice("It is a pity that, there is no winning combination...");
call(channel, data);
return;
}
for (int i = 0; i < sells.size(); i++) {
SimplePrinter.printNotice(i + 1 + ". " + PokerHelper.textOnlyNoType(sells.get(i).getSellPokers()));
}
while (true) {
SimplePrinter.printNotice("You can enter index to choose anyone.(enter [back|b] to go back.)");
line = SimpleWriter.write(User.INSTANCE.getNickname(), "choose");
if (line.equalsIgnoreCase("back") || line.equalsIgnoreCase("b")) {
call(channel, data);
return;
} else {
try {
int choose = Integer.valueOf(line);
if (choose < 1 || choose > sells.size()) {
SimplePrinter.printNotice("The input number must be in the range of 1 to " + sells.size() + ".");
} else {
List<Poker> choosePokers = sells.get(choose - 1).getSellPokers();
List<Character> options = new ArrayList<>();
for (Poker poker : choosePokers) {
options.add(poker.getLevel().getAlias()[0]);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY, Noson.reversal(options.toArray(new Character[]{})));
break;
}
} catch (NumberFormatException e) {
SimplePrinter.printNotice("Please input a number.");
}
}
}
}
// PokerHelper.validSells(lastPokerSell, pokers);
} else {
String[] strs = line.split(" ");
List<Character> options = new ArrayList<>();
boolean access = true;
for (int index = 0; index < strs.length; index++) {
String str = strs[index];
for (char c : str.toCharArray()) {
if (c == ' ' || c == '\t') {
} else {
if (!PokerLevel.aliasContains(c)) {
access = false;
break;
} else {
options.add(c);
}
}
}
}
if (access) {
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY, Noson.reversal(options.toArray(new Character[]{})));
} else {
SimplePrinter.printNotice("Invalid enter");
if (lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
call(channel, data);
}
}
}
}
}
@@ -1,16 +0,0 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_CANT_PASS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("You played the previous card, so you can't pass.");
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}
@@ -1,23 +0,0 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_INVALID extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("This combination is invalid.");
if(lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}
@@ -1,22 +0,0 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_LESS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("Your combination has lower rank than the previous. You cannot play this combination!");
if(lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}
@@ -1,27 +0,0 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_MISMATCH extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice("Your combination is " + map.get("playType") + " (" + map.get("playCount") + "), but the previous combination is " + map.get("preType") + " (" + map.get("preCount") + "). Mismatch!");
if(lastPokers != null) {
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
SimplePrinter.printPokers(lastPokers);
}
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}
@@ -1,15 +0,0 @@
package org.nico.ratel.landlords.client.event;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_ORDER_ERROR extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
SimplePrinter.printNotice("It is not your turn yet. Please wait for other players!");
}
}
@@ -1,26 +0,0 @@
package org.nico.ratel.landlords.client.event;
import java.util.Map;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_GAME_POKER_PLAY_PASS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice(map.get("clientNickname") + " passed. It is now " + map.get("nextClientNickname") + "'s turn.");
int turnClientId = (int) map.get("nextClientId");
if (SimpleClient.id == turnClientId) {
pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
}
}
@@ -1,48 +0,0 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.client.SimpleClient;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.FormatPrinter;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.util.List;
import java.util.Map;
import static org.nico.ratel.landlords.client.event.ClientEventListener_CODE_CLIENT_NICKNAME_SET.NICKNAME_MAX_LENGTH;
public class ClientEventListener_CODE_GAME_POKER_PLAY_REDIRECT extends ClientEventListener {
private static String[] choose = new String[]{"UP", "DOWN"};
private static String format = "\n[%-4s] %-" + NICKNAME_MAX_LENGTH + "s surplus %-2s [%-8s]";
@SuppressWarnings("unchecked")
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
int sellClientId = (int) map.get("sellClientId");
List<Map<String, Object>> clientInfos = (List<Map<String, Object>>) map.get("clientInfos");
for (int index = 0; index < 2; index++) {
for (Map<String, Object> clientInfo : clientInfos) {
String position = (String) clientInfo.get("position");
if (position.equalsIgnoreCase(choose[index])) {
FormatPrinter.printNotice(format, clientInfo.get("position"), clientInfo.get("clientNickname"), clientInfo.get("surplus"), clientInfo.get("type"));
}
}
}
SimplePrinter.printNotice("");
if (sellClientId == SimpleClient.id) {
get(ClientEventCode.CODE_GAME_POKER_PLAY).call(channel, data);
} else {
SimplePrinter.printNotice("It is " + map.get("sellClientNickname") + "'s turn. Please wait for him to play his cards.");
}
}
}
@@ -1,33 +0,0 @@
package org.nico.ratel.landlords.client.event;
import java.util.List;
import java.util.Map;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import io.netty.channel.Channel;
public class ClientEventListener_CODE_SHOW_POKERS extends ClientEventListener {
@Override
public void call(Channel channel, String data) {
Map<String, Object> map = MapHelper.parser(data);
lastSellClientNickname = (String) map.get("clientNickname");
lastSellClientType = (String) map.get("clientType");
SimplePrinter.printNotice(lastSellClientNickname + "[" + lastSellClientType + "] played:");
lastPokers = Noson.convert(map.get("pokers"), new NoType<List<Poker>>() {});
SimplePrinter.printPokers(lastPokers);
if (map.containsKey("sellClientNickname")) {
SimplePrinter.printNotice("Next player is " + map.get("sellClientNickname") + ". Please wait for him to play his combination.");
}
}
}
@@ -1,70 +0,0 @@
package org.nico.ratel.landlords.entity;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
/**
* Poke, with {@link PokerLevel} and {@link PokerType}
*
* @author nico
*/
public class Poker {
private PokerLevel level;
private PokerType type;
public Poker() {
}
public Poker(PokerLevel level, PokerType type) {
this.level = level;
this.type = type;
}
public final PokerLevel getLevel() {
return level;
}
public final void setLevel(PokerLevel level) {
this.level = level;
}
public final PokerType getType() {
return type;
}
public final void setType(PokerType type) {
this.type = type;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((level == null) ? 0 : level.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Poker other = (Poker) obj;
if (level != other.level)
return false;
return type == other.type;
}
@Override
public String toString() {
return level.getLevel() + " ";
}
}
@@ -1,62 +0,0 @@
package org.nico.ratel.landlords.entity;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
import java.util.List;
public class PokerSell {
private int score;
private SellType sellType;
private List<Poker> sellPokers;
private int coreLevel;
public PokerSell(SellType sellType, List<Poker> sellPokers, int coreLevel) {
this.score = PokerHelper.parseScore(sellType, coreLevel);
this.sellType = sellType;
this.sellPokers = sellPokers;
this.coreLevel = coreLevel;
}
public final int getCoreLevel() {
return coreLevel;
}
public final void setCoreLevel(int coreLevel) {
this.coreLevel = coreLevel;
}
public final int getScore() {
return score;
}
public final void setScore(int score) {
this.score = score;
}
public final SellType getSellType() {
return sellType;
}
public final void setSellType(SellType sellType) {
this.sellType = sellType;
}
public final List<Poker> getSellPokers() {
return sellPokers;
}
public final void setSellPokers(List<Poker> sellPokers) {
this.sellPokers = sellPokers;
}
@Override
public String toString() {
return sellType + "\t| " + score + "\t|" + sellPokers;
}
}
@@ -1,113 +0,0 @@
package org.nico.ratel.landlords.enums;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Poker level
*
* @author nico
*/
public enum PokerLevel {
LEVEL_3(3, "3", new Character[]{'3'}),
LEVEL_4(4, "4", new Character[]{'4'}),
LEVEL_5(5, "5", new Character[]{'5'}),
LEVEL_6(6, "6", new Character[]{'6'}),
LEVEL_7(7, "7", new Character[]{'7'}),
LEVEL_8(8, "8", new Character[]{'8'}),
LEVEL_9(9, "9", new Character[]{'9'}),
LEVEL_10(10, "10", new Character[]{'T', 't', '0'}),
LEVEL_J(11, "J", new Character[]{'J', 'j'}),
LEVEL_Q(12, "Q", new Character[]{'Q', 'q'}),
LEVEL_K(13, "K", new Character[]{'K', 'k'}),
LEVEL_A(14, "A", new Character[]{'A', 'a', '1'}),
LEVEL_2(15, "2", new Character[]{'2'}),
LEVEL_SMALL_KING(16, "S", new Character[]{'S', 's'}),
LEVEL_BIG_KING(17, "X", new Character[]{'X', 'x'}),
;
private int level;
private String name;
private Character[] alias;
private static Set<Character> aliasSet = new HashSet<>();
static {
for (PokerLevel level : PokerLevel.values()) {
PokerLevel.aliasSet.addAll(Arrays.asList(level.getAlias()));
}
}
private PokerLevel(int level, String name, Character[] alias) {
this.level = level;
this.name = name;
this.alias = alias;
}
public static boolean aliasContains(char key) {
return aliasSet.contains(key);
}
public final Character[] getAlias() {
return alias;
}
public final void setAlias(Character[] alias) {
this.alias = alias;
}
public final String getName() {
return name;
}
public final void setName(String name) {
this.name = name;
}
public final int getLevel() {
return level;
}
public final void setLevel(int level) {
this.level = level;
}
public static final PokerLevel parseByName(String name) {
if(name == null) {
return null;
}
for(PokerLevel level: PokerLevel.values()) {
if(level.name.equals(name.toUpperCase())) {
return level;
}
}
return null;
}
public static final PokerLevel parseByLevel(int l) {
for(PokerLevel level: PokerLevel.values()) {
if(level.level == l) {
return level;
}
}
return null;
}
}
@@ -1,29 +0,0 @@
package org.nico.ratel.landlords.enums;
/**
* Poker type Spade、 Heart、 Diamond、 Club
*
* @author nico
*/
public enum PokerType {
BLANK(" "),
DIAMOND(""),
CLUB(""),
SPADE(""),
HEART("");
private final String name;
PokerType(String name) {
this.name = name;
}
public final String getName() {
return name;
}
}
@@ -1,632 +0,0 @@
package org.nico.ratel.landlords.helper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.utils.ListUtils;
public class PokerHelper {
/**
* Print the type of poker style
*/
public static int pokerPrinterType = 0;
public static int totalPrinters = 5;
/**
* The list of all pokers, by 54
*/
private static final List<Poker> basePokers = new ArrayList<>(54);
private static final Comparator<Poker> pokerComparator = (o1, o2) -> o1.getLevel().getLevel() - o2.getLevel().getLevel();
static {
PokerLevel[] pokerLevels = PokerLevel.values();
PokerType[] pokerTypes = PokerType.values();
for (PokerLevel level : pokerLevels) {
if (level == PokerLevel.LEVEL_BIG_KING) {
basePokers.add(new Poker(level, PokerType.BLANK));
continue;
}
if (level == PokerLevel.LEVEL_SMALL_KING) {
basePokers.add(new Poker(level, PokerType.BLANK));
continue;
}
for (PokerType type : pokerTypes) {
if (type == PokerType.BLANK) {
continue;
}
basePokers.add(new Poker(level, type));
}
}
}
public static void sortPoker(List<Poker> pokers) {
pokers.sort(pokerComparator);
}
public static List<Poker> clonePokers(List<Poker> pokers){
List<Poker> newPokers = new ArrayList<Poker>(pokers.size());
for(Poker poker: pokers) {
newPokers.add(new Poker(poker.getLevel(), poker.getType()));
}
return newPokers;
}
public static List<PokerSell> validSells(PokerSell lastPokerSell, List<Poker> pokers) {
List<PokerSell> sells = PokerHelper.parsePokerSells(pokers);
if(lastPokerSell == null) {
return sells;
}
List<PokerSell> validSells = new ArrayList<PokerSell>();
for(PokerSell sell: sells) {
if(sell.getSellType() == lastPokerSell.getSellType()) {
if(sell.getScore() > lastPokerSell.getScore() && sell.getSellPokers().size() == lastPokerSell.getSellPokers().size()) {
validSells.add(sell);
}
}
if(sell.getSellType() == SellType.KING_BOMB) {
validSells.add(sell);
}
}
if(lastPokerSell.getSellType() != SellType.BOMB) {
for(PokerSell sell: sells) {
if(sell.getSellType() == SellType.BOMB) {
validSells.add(sell);
}
}
}
return validSells;
}
public static int[] getIndexes(Character[] options, List<Poker> pokers) {
List<Poker> copyList = new ArrayList<>(pokers.size());
copyList.addAll(pokers);
int[] indexes = new int[options.length];
for (int index = 0; index < options.length; index++) {
char option = options[index];
boolean isTarget = false;
for (int pi = 0; pi < copyList.size(); pi++) {
Poker poker = copyList.get(pi);
if (poker == null) {
continue;
}
if (Arrays.asList(poker.getLevel().getAlias()).contains(option)) {
isTarget = true;
//Index start from 1, not 0
indexes[index] = pi + 1;
copyList.set(pi, null);
break;
}
}
if (!isTarget) {
return null;
}
}
Arrays.sort(indexes);
return indexes;
}
public static boolean checkPokerIndex(int[] indexes, List<Poker> pokers) {
if (indexes == null || indexes.length == 0) {
return false;
}
for (int index : indexes) {
if (index > pokers.size() || index < 1) {
return false;
}
}
return true;
}
public static PokerSell checkPokerType(List<Poker> pokers) {
if (pokers == null || pokers.isEmpty()) {
return new PokerSell(SellType.ILLEGAL, null, -1);
}
sortPoker(pokers);
int[] levelTable = new int[20];
for (Poker poker : pokers) {
levelTable[poker.getLevel().getLevel()]++;
}
int startIndex = -1;
int endIndex = -1;
int count = 0;
int singleCount = 0;
int doubleCount = 0;
int threeCount = 0;
int threeStartIndex = -1;
int threeEndIndex = -1;
int fourCount = 0;
int fourStartIndex = -1;
int fourEndIndex = -1;
for (int index = 0; index < levelTable.length; index++) {
int value = levelTable[index];
if (value == 0) {
continue;
}
endIndex = index;
count++;
if (startIndex == -1) {
startIndex = index;
}
if (value == 1) {
singleCount++;
} else if (value == 2) {
doubleCount++;
} else if (value == 3) {
if (threeStartIndex == -1) {
threeStartIndex = index;
}
threeEndIndex = index;
threeCount++;
} else if (value == 4) {
if (fourStartIndex == -1) {
fourStartIndex = index;
}
fourEndIndex = index;
fourCount++;
}
}
if (singleCount == doubleCount && singleCount == threeCount && singleCount == 0 && fourCount == 1) {
return new PokerSell(SellType.BOMB, pokers, startIndex);
}
if (singleCount == 2 && startIndex == PokerLevel.LEVEL_SMALL_KING.getLevel() && endIndex == PokerLevel.LEVEL_BIG_KING.getLevel()) {
return new PokerSell(SellType.KING_BOMB, pokers, PokerLevel.LEVEL_SMALL_KING.getLevel());
}
if (startIndex == endIndex) {
if (levelTable[startIndex] == 1) {
return new PokerSell(SellType.SINGLE, pokers, startIndex);
} else if (levelTable[startIndex] == 2) {
return new PokerSell(SellType.DOUBLE, pokers, startIndex);
} else if (levelTable[startIndex] == 3) {
return new PokerSell(SellType.THREE, pokers, startIndex);
}
}
if (endIndex - startIndex == count - 1 && endIndex < PokerLevel.LEVEL_2.getLevel()) {
if (levelTable[startIndex] == 1 && singleCount > 4 && doubleCount + threeCount + fourCount == 0) {
return new PokerSell(SellType.SINGLE_STRAIGHT, pokers, endIndex);
} else if (levelTable[startIndex] == 2 && doubleCount > 2 && singleCount + threeCount + fourCount == 0) {
return new PokerSell(SellType.DOUBLE_STRAIGHT, pokers, endIndex);
} else if (levelTable[startIndex] == 3 && threeCount > 1 && doubleCount + singleCount + fourCount == 0) {
return new PokerSell(SellType.THREE_STRAIGHT, pokers, endIndex);
} else if (levelTable[startIndex] == 4 && fourCount > 1 && doubleCount + threeCount + singleCount == 0) {
return new PokerSell(SellType.FOUR_STRAIGHT, pokers, endIndex);
}
}
if (threeCount != 0) {
if (singleCount != 0 && singleCount == threeCount && doubleCount == 0 && fourCount == 0) {
if (threeCount == 1) {
return new PokerSell(SellType.THREE_ZONES_SINGLE, pokers, threeEndIndex);
}
if (threeEndIndex - threeStartIndex + 1 == threeCount && threeEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.THREE_STRAIGHT_WITH_SINGLE, pokers, threeEndIndex);
}
} else if (doubleCount != 0 && doubleCount == threeCount && singleCount == 0 && fourCount == 0) {
if (threeCount == 1) {
return new PokerSell(SellType.THREE_ZONES_DOUBLE, pokers, threeEndIndex);
}
if (threeEndIndex - threeStartIndex + 1 == threeCount && threeEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.THREE_STRAIGHT_WITH_DOUBLE, pokers, threeEndIndex);
}
} else if (singleCount + doubleCount * 2 == threeCount && fourCount == 0) {
return new PokerSell(SellType.THREE_STRAIGHT_WITH_SINGLE, pokers, threeEndIndex);
}
}
if (fourCount != 0) {
if (singleCount != 0 && singleCount == fourCount * 2 && doubleCount == 0 && threeCount == 0) {
if (fourCount == 1) {
return new PokerSell(SellType.FOUR_ZONES_SINGLE, pokers, fourEndIndex);
}
if (fourEndIndex - fourStartIndex + 1 == fourCount && fourEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.FOUR_STRAIGHT_WITH_SINGLE, pokers, fourEndIndex);
}
} else if (doubleCount != 0 && doubleCount == fourCount * 2 && singleCount == 0 && threeCount == 0) {
if (fourCount == 1) {
return new PokerSell(SellType.FOUR_ZONES_DOUBLE, pokers, fourEndIndex);
}
if (fourEndIndex - fourStartIndex + 1 == fourCount && fourEndIndex < PokerLevel.LEVEL_2.getLevel()) {
return new PokerSell(SellType.FOUR_STRAIGHT_WITH_DOUBLE, pokers, fourEndIndex);
}
}
}
return new PokerSell(SellType.ILLEGAL, null, -1);
}
public static int parseScore(SellType sellType, int level) {
if (sellType == SellType.BOMB) {
return level * 4 + 999;
} else if (sellType == SellType.KING_BOMB) {
return Integer.MAX_VALUE;
} else if (sellType == SellType.SINGLE || sellType == SellType.DOUBLE || sellType == SellType.THREE) {
return level;
} else if (sellType == SellType.SINGLE_STRAIGHT || sellType == SellType.DOUBLE_STRAIGHT || sellType == SellType.THREE_STRAIGHT || sellType == SellType.FOUR_STRAIGHT) {
return level;
} else if (sellType == SellType.THREE_ZONES_SINGLE || sellType == SellType.THREE_STRAIGHT_WITH_SINGLE || sellType == SellType.THREE_ZONES_DOUBLE || sellType == SellType.THREE_STRAIGHT_WITH_DOUBLE) {
return level;
} else if (sellType == SellType.FOUR_ZONES_SINGLE || sellType == SellType.FOUR_STRAIGHT_WITH_SINGLE || sellType == SellType.FOUR_ZONES_DOUBLE || sellType == SellType.FOUR_STRAIGHT_WITH_DOUBLE) {
return level;
}
return -1;
}
public static List<Poker> getPoker(int[] indexes, List<Poker> pokers) {
List<Poker> resultPokers = new ArrayList<>(indexes.length);
for (int index : indexes) {
resultPokers.add(pokers.get(index - 1));
}
sortPoker(resultPokers);
return resultPokers;
}
public static boolean comparePoker(List<Poker> pres, List<Poker> currents) {
return true;
}
public static List<List<Poker>> distributePoker() {
Collections.shuffle(basePokers);
List<List<Poker>> pokersList = new ArrayList<List<Poker>>();
List<Poker> pokers1 = new ArrayList<>(17);
pokers1.addAll(basePokers.subList(0, 17));
List<Poker> pokers2 = new ArrayList<>(17);
pokers2.addAll(basePokers.subList(17, 34));
List<Poker> pokers3 = new ArrayList<>(17);
pokers3.addAll(basePokers.subList(34, 51));
List<Poker> pokers4 = new ArrayList<>(3);
pokers4.addAll(basePokers.subList(51, 54));
pokersList.add(pokers1);
pokersList.add(pokers2);
pokersList.add(pokers3);
pokersList.add(pokers4);
for (List<Poker> pokers : pokersList) {
sortPoker(pokers);
}
return pokersList;
}
public static String printPoker(List<Poker> pokers) {
sortPoker(pokers);
switch (pokerPrinterType) {
case 0:
return buildHandStringSharp(pokers);
case 1:
return buildHandStringRounded(pokers);
case 2:
return textOnly(pokers);
case 3:
return textOnlyNoType(pokers);
default:
return buildHandStringSharp(pokers);
}
}
private static String buildHandStringSharp(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("┌──┐");
} else {
builder.append("──┐");
}
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("");
}
String name = pokers.get(index).getLevel().getName();
builder.append(name).append(name.length() == 1 ? " " : "").append("|");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("");
}
builder.append(pokers.get(index).getType().getName()).append(" |");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("└──┘");
} else {
builder.append("──┘");
}
}
}
return builder.toString();
}
private static String buildHandStringRounded(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("┌──╮");
} else {
builder.append("──╮");
}
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("");
}
String name = pokers.get(index).getLevel().getName();
builder.append(name).append(name.length() == 1 ? " " : "").append("|");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("");
}
builder.append(pokers.get(index).getType().getName()).append(" |");
}
builder.append(System.lineSeparator());
for (int index = 0; index < pokers.size(); index++) {
if (index == 0) {
builder.append("└──╯");
} else {
builder.append("──╯");
}
}
}
return builder.toString();
}
private static String textOnly(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (Poker poker : pokers) {
String name = poker.getLevel().getName();
String type = poker.getType().getName();
builder.append(name).append(type);
}
}
return builder.toString();
}
public static String textOnlyNoType(List<Poker> pokers) {
StringBuilder builder = new StringBuilder();
if (pokers != null && pokers.size() > 0) {
for (Poker poker : pokers) {
String name = poker.getLevel().getName();
builder.append(name).append(" ");
}
}
return builder.toString();
}
public static int parsePokerColligationScore(List<Poker> pokers) {
int score = 0;
int count = 0;
int increase = 0;
int lastLevel = -1;
if (pokers != null && !pokers.isEmpty()) {
for (int index = 0; index < pokers.size(); index++) {
int level = pokers.get(index).getLevel().getLevel();
if (lastLevel == -1) {
increase++;
count++;
score += lastLevel;
} else {
if (level == lastLevel) {
++count;
} else {
count = 1;
}
if (level < PokerLevel.LEVEL_2.getLevel() && level - 1 == lastLevel) {
++increase;
} else {
increase = 1;
}
score += (count + (increase > 4 ? increase : 0)) * level;
}
if (level == PokerLevel.LEVEL_2.getLevel()) {
score += level * 2;
} else if (level > PokerLevel.LEVEL_2.getLevel()) {
score += level * 3;
}
lastLevel = level;
}
}
return score;
}
public static List<PokerSell> parsePokerSells(List<Poker> pokers) {
List<PokerSell> pokerSells = new ArrayList<>();
int size = pokers.size();
//all single or double
{
int count = 0;
int lastLevel = -1;
List<Poker> sellPokers = new ArrayList<>(4);
for (Poker poker : pokers) {
int level = poker.getLevel().getLevel();
if (lastLevel == -1) {
++count;
} else {
if (level == lastLevel) {
++count;
} else {
count = 1;
sellPokers.clear();
}
}
sellPokers.add(poker);
if (count == 1) {
pokerSells.add(new PokerSell(SellType.SINGLE, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
} else if (count == 2) {
pokerSells.add(new PokerSell(SellType.DOUBLE, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
} else if (count == 3) {
pokerSells.add(new PokerSell(SellType.THREE, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
} else if (count == 4) {
pokerSells.add(new PokerSell(SellType.BOMB, ListUtils.getList(sellPokers), poker.getLevel().getLevel()));
}
lastLevel = level;
}
}
//Shunzi
{
parsePokerSellStraight(pokerSells, SellType.SINGLE);
parsePokerSellStraight(pokerSells, SellType.DOUBLE);
parsePokerSellStraight(pokerSells, SellType.THREE);
parsePokerSellStraight(pokerSells, SellType.BOMB);
}
//Shunzi with args
{
for (int index = 0; index < pokerSells.size(); index++) {
PokerSell sell = pokerSells.get(index);
if (sell.getSellType() == SellType.THREE) {
parseArgs(pokerSells, sell, 1, SellType.SINGLE, SellType.THREE_ZONES_SINGLE);
parseArgs(pokerSells, sell, 1, SellType.DOUBLE, SellType.THREE_ZONES_DOUBLE);
} else if (sell.getSellType() == SellType.BOMB) {
parseArgs(pokerSells, sell, 2, SellType.SINGLE, SellType.FOUR_ZONES_SINGLE);
parseArgs(pokerSells, sell, 2, SellType.DOUBLE, SellType.FOUR_ZONES_DOUBLE);
} else if (sell.getSellType() == SellType.THREE_STRAIGHT) {
int count = sell.getSellPokers().size() / 3;
parseArgs(pokerSells, sell, count, SellType.SINGLE, SellType.THREE_STRAIGHT_WITH_SINGLE);
parseArgs(pokerSells, sell, count, SellType.DOUBLE, SellType.THREE_STRAIGHT_WITH_DOUBLE);
} else if (sell.getSellType() == SellType.FOUR_STRAIGHT) {
int count = (sell.getSellPokers().size() / 4) * 2;
parseArgs(pokerSells, sell, count, SellType.SINGLE, SellType.FOUR_STRAIGHT_WITH_SINGLE);
parseArgs(pokerSells, sell, count, SellType.DOUBLE, SellType.FOUR_STRAIGHT_WITH_DOUBLE);
}
}
}
//king boom
{
if (size > 1) {
if (pokers.get(size - 1).getLevel() == PokerLevel.LEVEL_BIG_KING && pokers.get(size - 2).getLevel() == PokerLevel.LEVEL_SMALL_KING) {
pokerSells.add(new PokerSell(SellType.KING_BOMB, ListUtils.getList(new Poker[]{pokers.get(size - 2), pokers.get(size - 1)}), PokerLevel.LEVEL_BIG_KING.getLevel()));
}
}
}
return pokerSells;
}
private static void parseArgs(List<PokerSell> pokerSells, PokerSell pokerSell, int deep, SellType sellType, SellType targetSellType) {
Set<Integer> existLevelSet = new HashSet<>();
for (Poker p : pokerSell.getSellPokers()) {
existLevelSet.add(p.getLevel().getLevel());
}
parseArgs(existLevelSet, pokerSells, new HashSet<>(), pokerSell, deep, sellType, targetSellType);
}
private static void parseArgs(Set<Integer> existLevelSet, List<PokerSell> pokerSells, Set<List<Poker>> pokersList, PokerSell pokerSell, int deep, SellType sellType, SellType targetSellType) {
if (deep == 0) {
List<Poker> allPokers = new ArrayList<>(pokerSell.getSellPokers());
for (List<Poker> ps : pokersList) {
allPokers.addAll(ps);
}
pokerSells.add(new PokerSell(targetSellType, allPokers, pokerSell.getCoreLevel()));
return;
}
for (int index = 0; index < pokerSells.size(); index++) {
PokerSell subSell = pokerSells.get(index);
if (subSell.getSellType() == sellType && !existLevelSet.contains(subSell.getCoreLevel())) {
pokersList.add(subSell.getSellPokers());
existLevelSet.add(subSell.getCoreLevel());
parseArgs(existLevelSet, pokerSells, pokersList, pokerSell, deep - 1, sellType, targetSellType);
existLevelSet.remove(subSell.getCoreLevel());
pokersList.remove(subSell.getSellPokers());
}
}
}
private static void parsePokerSellStraight(List<PokerSell> pokerSells, SellType sellType) {
int minLength = -1;
int width = -1;
SellType targetSellType = null;
if (sellType == SellType.SINGLE) {
minLength = 5;
width = 1;
targetSellType = SellType.SINGLE_STRAIGHT;
} else if (sellType == SellType.DOUBLE) {
minLength = 3;
width = 2;
targetSellType = SellType.DOUBLE_STRAIGHT;
} else if (sellType == SellType.THREE) {
minLength = 2;
width = 3;
targetSellType = SellType.THREE_STRAIGHT;
} else if (sellType == SellType.BOMB) {
minLength = 2;
width = 4;
targetSellType = SellType.FOUR_STRAIGHT;
}
int increase_1 = 0;
int lastLevel_1 = -1;
List<Poker> sellPokers_1 = new ArrayList<>(4);
for (int index = 0; index < pokerSells.size(); index++) {
PokerSell sell = pokerSells.get(index);
if (sell.getSellType() != sellType) {
continue;
}
int level = sell.getCoreLevel();
if (lastLevel_1 == -1) {
++increase_1;
} else {
if (level - 1 == lastLevel_1 && level != PokerLevel.LEVEL_2.getLevel()) {
++increase_1;
} else {
addPokers(pokerSells, minLength, width, targetSellType, increase_1, sellPokers_1);
increase_1 = 1;
}
}
sellPokers_1.addAll(sell.getSellPokers());
lastLevel_1 = level;
}
addPokers(pokerSells, minLength, width, targetSellType, increase_1, sellPokers_1);
}
private static void addPokers(List<PokerSell> pokerSells, int minLenght, int width, SellType targetSellType, int increase_1, List<Poker> sellPokers_1) {
if (increase_1 >= minLenght) {
for (int s = 0; s <= increase_1 - minLenght; s++) {
int len = minLenght + s;
for (int subIndex = 0; subIndex <= increase_1 - len; subIndex++) {
List<Poker> pokers = ListUtils.getList(sellPokers_1.subList(subIndex * width, (subIndex + len) * width));
pokerSells.add(new PokerSell(targetSellType, pokers, pokers.get(pokers.size() - 1).getLevel().getLevel()));
}
}
}
sellPokers_1.clear();
}
}
@@ -1,20 +0,0 @@
package org.nico.ratel.landlords.robot;
import java.util.List;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
/**
*
* @author nico
* @version createTime2018年11月15日 上午12:12:15
*/
public abstract class AbstractRobotDecisionMakers {
public abstract PokerSell howToPlayPokers(PokerSell lastPokerSell, ClientSide robot);
public abstract int getLandlordScore(List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers);
}
@@ -1,73 +0,0 @@
package org.nico.ratel.landlords.robot;
import java.util.List;
import java.util.Random;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
/**
* @author nico
* @date 2018-11-15 12:13:49
*/
public class EasyRobotDecisionMakers extends AbstractRobotDecisionMakers {
private static Random random = new Random();
@Override
public PokerSell howToPlayPokers(PokerSell lastPokerSell, ClientSide robot) {
if (lastPokerSell != null && lastPokerSell.getSellType() == SellType.KING_BOMB) {
return null;
}
List<PokerSell> sells = PokerHelper.parsePokerSells(robot.getPokers());
if (lastPokerSell == null) {
return sells.get(random.nextInt(sells.size()));
}
for (PokerSell sell : sells) {
if (sell.getSellType() == lastPokerSell.getSellType()) {
if (sell.getScore() > lastPokerSell.getScore() && sell.getSellPokers().size() == lastPokerSell.getSellPokers().size()) {
return sell;
}
}
}
if (lastPokerSell.getSellType() != SellType.BOMB) {
for (PokerSell sell : sells) {
if (sell.getSellType() == SellType.BOMB) {
return sell;
}
}
}
for (PokerSell sell : sells) {
if (sell.getSellType() == SellType.KING_BOMB) {
return sell;
}
}
return null;
}
@Override
public int getLandlordScore(List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers) {
List<PokerSell> leftSells = PokerHelper.parsePokerSells(leftPokers);
List<PokerSell> mySells = PokerHelper.parsePokerSells(myPokers);
List<PokerSell> rightSells = PokerHelper.parsePokerSells(rightPokers);
int expectedScore = 0;
if (mySells.size() > leftSells.size()) {
++expectedScore;
}
if (mySells.size() > rightSells.size()) {
++expectedScore;
}
if (expectedScore != 0) {
++expectedScore;
}
return expectedScore;
}
}
@@ -1,152 +0,0 @@
package org.nico.ratel.landlords.robot;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
/**
* Trial game algorithm
*
* @author nico
* @date 2020-12-19 16:36
*/
public class MediumRobotDecisionMakers extends AbstractRobotDecisionMakers {
private static final Long DEDUCE_LIMIT = 100 * 3L;
public MediumRobotDecisionMakers() {}
@Override
public PokerSell howToPlayPokers(PokerSell lastPokerSell, ClientSide robot) {
if(lastPokerSell != null && lastPokerSell.getSellType() == SellType.KING_BOMB) {
return null;
}
List<Poker> selfPoker = PokerHelper.clonePokers(robot.getPokers());
List<Poker> leftPoker = PokerHelper.clonePokers(robot.getPre().getPokers());
List<Poker> rightPoker = PokerHelper.clonePokers(robot.getNext().getPokers());
PokerHelper.sortPoker(selfPoker);
PokerHelper.sortPoker(leftPoker);
PokerHelper.sortPoker(rightPoker);
List<List<Poker>> pokersList = new ArrayList<List<Poker>>();
pokersList.add(selfPoker);
pokersList.add(rightPoker);
pokersList.add(leftPoker);
List<PokerSell> sells = PokerHelper.validSells(lastPokerSell, selfPoker);
if(sells.size() == 0) {
return null;
}
PokerSell bestSell = null;
Long weight = null;
for(PokerSell sell: sells) {
List<Poker> pokers = PokerHelper.clonePokers(selfPoker);
pokers.removeAll(sell.getSellPokers());
if(pokers.size() == 0) {
return sell;
}
pokersList.set(0, pokers);
AtomicLong counter = new AtomicLong();
deduce(0, sell, 1, pokersList, counter);
if(weight == null) {
bestSell = sell;
weight = counter.get();
}else if (counter.get() > weight){
bestSell = sell;
weight = counter.get();
}
pokersList.set(0, selfPoker);
}
return bestSell;
}
private Boolean deduce(int sellCursor, PokerSell lastPokerSell, int cursor, List<List<Poker>> pokersList, AtomicLong counter) {
if(cursor > 2) {
cursor = 0;
}
if(sellCursor == cursor) {
lastPokerSell = null;
}
List<Poker> original = pokersList.get(cursor);
List<PokerSell> sells = PokerHelper.validSells(lastPokerSell, original);
if(sells.size() == 0) {
if(sellCursor != cursor) {
return deduce(sellCursor, lastPokerSell, cursor + 1, pokersList, counter);
}
}
for(PokerSell sell: sells) {
List<Poker> pokers = PokerHelper.clonePokers(original);
pokers.removeAll(sell.getSellPokers());
if(pokers.size() == 0) {
return cursor == 0;
}else {
pokersList.set(cursor, pokers);
Boolean suc = deduce(cursor, sell, cursor + 1, pokersList, counter);
if(cursor != 0) {
pokersList.set(cursor, original);
return suc;
}
if(Math.abs(counter.get()) > DEDUCE_LIMIT) {
pokersList.set(cursor, original);
return counter.get() > DEDUCE_LIMIT;
}
if(suc != null) {
counter.addAndGet((long)(suc ? 1 : -1));
}
pokersList.set(cursor, original);
}
}
return null;
}
private static String serialPokers(List<Poker> pokers){
if(pokers == null || pokers.size() == 0) {
return "n";
}
StringBuilder builder = new StringBuilder();
for(int index = 0; index < pokers.size(); index ++) {
builder.append(pokers.get(index).getLevel().getLevel()).append(index == pokers.size() - 1 ? "" : "_");
}
return builder.toString();
}
private static String serialPokersList(List<List<Poker>> pokersList){
StringBuilder builder = new StringBuilder();
for(int index = 0; index < pokersList.size(); index ++) {
List<Poker> pokers = pokersList.get(index);
builder.append(serialPokers(pokers)).append(index == pokersList.size() - 1 ? "" : "m");
}
return builder.toString();
}
@Override
public int getLandlordScore(List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers) {
int leftScore = PokerHelper.parsePokerColligationScore(leftPokers);
int rightScore = PokerHelper.parsePokerColligationScore(rightPokers);
int myScore = PokerHelper.parsePokerColligationScore(myPokers);
int expectedScore = 0;
if (myScore >= Math.min(leftScore, rightScore)) {
++expectedScore;
}
if (myScore * 2 >= leftScore + rightScore) {
++expectedScore;
}
if (myScore >= Math.max(leftScore, rightScore)) {
++expectedScore;
}
return expectedScore;
}
}
@@ -1,37 +0,0 @@
package org.nico.ratel.landlords.robot;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
/**
* How does the machine decide on a better strategy to win the game
*
* @author nico
*/
public class RobotDecisionMakers {
private static final Map<Integer, AbstractRobotDecisionMakers> decisionMakersMap = new HashMap<Integer, AbstractRobotDecisionMakers>();
public static void init() {
decisionMakersMap.put(1, new EasyRobotDecisionMakers());
decisionMakersMap.put(2, new MediumRobotDecisionMakers());
}
public static boolean contains(int difficultyCoefficient) {
return decisionMakersMap.containsKey(difficultyCoefficient);
}
public static PokerSell howToPlayPokers(int difficultyCoefficient, PokerSell lastPokerSell, ClientSide robot){
return decisionMakersMap.get(difficultyCoefficient).howToPlayPokers(lastPokerSell, robot);
}
public static int getLandlordScore(int difficultyCoefficient, List<Poker> leftPokers, List<Poker> rightPokers, List<Poker> myPokers) {
return decisionMakersMap.get(difficultyCoefficient).getLandlordScore(leftPokers, rightPokers, myPokers);
}
}
@@ -1,65 +0,0 @@
package org.nico.ratel.landlords.utils;
import org.nico.ratel.landlords.entity.Poker;
import java.util.*;
public class LastCardsUtils {
private static final List<String> defSort = new ArrayList(){{
add("3");
add("4");
add("5");
add("6");
add("7");
add("8");
add("9");
add("10");
add("J");
add("Q");
add("K");
add("A");
add("2");
add("S");
add("X");
}};
public static String getLastCards(List<List<Poker>> pokers){
StringBuffer lastCards = new StringBuffer();
Map<String, Integer> lastCardMap = initLastCards();
for(int i = 0; i < pokers.size(); i++){
List<Poker> pokerList = pokers.get(i);
for(int a = 0; a < pokerList.size(); a++){
Poker poker = pokerList.get(a);
lastCardMap.put(poker.getLevel().getName(),(lastCardMap.get(poker.getLevel().getName())+1));
}
}
for(int i = 0; i < defSort.size(); i++){
String key = defSort.get(i);
lastCards.append(key + "["+lastCardMap.get(key)+"] ");
}
return lastCards.toString();
}
private static Map<String, Integer> initLastCards(){
Map<String, Integer> lastCardMap = new HashMap<>();
lastCardMap.put("A",0);
lastCardMap.put("2",0);
lastCardMap.put("3",0);
lastCardMap.put("4",0);
lastCardMap.put("5",0);
lastCardMap.put("6",0);
lastCardMap.put("7",0);
lastCardMap.put("8",0);
lastCardMap.put("9",0);
lastCardMap.put("10",0);
lastCardMap.put("J",0);
lastCardMap.put("Q",0);
lastCardMap.put("K",0);
lastCardMap.put("S",0);
lastCardMap.put("X",0);
return lastCardMap;
}
}
@@ -1,16 +0,0 @@
pls_select_srv=Please select a server:
srv_addr_not_exist=Server address does not exist!
try_connect_%s_failed_%s=Failed to connect to server %s, reason: %s
game_move_invalid=Invalid move! Please try again.
game_move_occupied=Position already occupied!
game_move_out_of_bounds=Move out of bounds!
game_move_not_your_turn=It's not your turn!
game_black_win=Black player wins!
game_white_win=White player wins!
game_draw=Game ended in a draw!
board_display_title=Current Board:
move_history_title=Move History:
waiting_for_opponent=Waiting for opponent...
your_turn=Your turn!
spectator_joined=Spectator joined the game.
spectator_left=Spectator left the game.
@@ -1,243 +0,0 @@
package org.nico.ratel.landlords.helper.tests;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
import java.util.ArrayList;
public class PokerHelperTest {
private ArrayList<Poker> pokers = new ArrayList<>();
@Before
public void setUp() {
pokers.add(new Poker(PokerLevel.LEVEL_3, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.DIAMOND));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.DIAMOND));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.CLUB));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.CLUB));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.CLUB));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.SPADE));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
}
@Test
public void testComparePoker() {
Assert.assertTrue(PokerHelper.comparePoker(new ArrayList<>(), new ArrayList<>()));
}
@Test
public void testCheckPokerIndex() {
Assert.assertFalse(PokerHelper.checkPokerIndex(new int[]{}, new ArrayList<>()));
Assert.assertFalse(PokerHelper.checkPokerIndex(new int[]{2, -4_194_302}, new ArrayList<>()));
}
@Test
public void testGetIndexes() {
Assert.assertNull(PokerHelper.getIndexes(new Character[]{'3', '4', '5', '6', '7', '8'}, pokers));
Assert.assertNotNull(PokerHelper.getIndexes(new Character[]{}, new ArrayList<>()));
Assert.assertEquals(0, PokerHelper.getIndexes(new Character[]{}, new ArrayList<>()).length);
}
@Test
public void testGetPoker() {
Assert.assertEquals(PokerLevel.LEVEL_3, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(0).getLevel());
Assert.assertEquals(PokerType.BLANK, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(0).getType());
Assert.assertEquals(PokerLevel.LEVEL_4, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(1).getLevel());
Assert.assertEquals(PokerType.DIAMOND, PokerHelper.getPoker(new int[]{1, 2}, pokers).get(1).getType());
}
@Test
public void testPrintPoker() {
Assert.assertNotNull(PokerHelper.printPoker(pokers));
}
@Test
public void testDistributePoker() {
Assert.assertNotNull(PokerHelper.distributePoker());
}
@Test
public void testCheckPokerType1() {
pokers.clear();
Assert.assertNull(PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(-1, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.ILLEGAL, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_SMALL_KING, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_BIG_KING, PokerType.DIAMOND));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(2147483647, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.KING_BOMB, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType2() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(1027, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.BOMB, PokerHelper.checkPokerType(pokers).getSellType());
pokers.remove(pokers.size() - 1);
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_ZONES_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(7, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_ZONES_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT_WITH_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT_WITH_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType3() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.SINGLE_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.DOUBLE_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(10, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_STRAIGHT, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType4() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_ZONES_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_STRAIGHT_WITH_SINGLE, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType5() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_9, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_10, PokerType.BLANK));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_ZONES_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.HEART));
Assert.assertEquals(pokers, PokerHelper.checkPokerType(pokers).getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.FOUR_STRAIGHT_WITH_DOUBLE, PokerHelper.checkPokerType(pokers).getSellType());
}
@Test
public void testCheckPokerType6() {
pokers.clear();
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_6, PokerType.HEART));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_7, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_8, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_4, PokerType.BLANK));
pokers.add(new Poker(PokerLevel.LEVEL_5, PokerType.BLANK));
PokerSell pokerSell = PokerHelper.checkPokerType(pokers);
Assert.assertEquals(pokers, pokerSell.getSellPokers());
Assert.assertEquals(8, PokerHelper.checkPokerType(pokers).getScore());
Assert.assertEquals(SellType.THREE_STRAIGHT_WITH_SINGLE, pokerSell.getSellType());
}
}
@@ -1,63 +0,0 @@
package org.nico.ratel.landlords.robot.tests;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.robot.MediumRobotDecisionMakers;
public class MediumRobotDecisionMakersTests {
private List<Poker> buildPokers(Object[] values){
List<Poker> pokers = new ArrayList<Poker>();
for(Object v: values) {
if(v == null){
continue;
}
if(v instanceof String) {
pokers.add(new Poker(PokerLevel.parseByName((String)v), PokerType.CLUB));
}else if(v instanceof Integer || v.getClass() == int.class) {
pokers.add(new Poker(PokerLevel.parseByLevel((int)v), PokerType.CLUB));
}
}
return pokers;
}
@Test
public void testMedium_1() {
ClientSide self = new ClientSide();
ClientSide right = new ClientSide();
ClientSide left = new ClientSide();
self.setPre(left);
self.setNext(right);
left.setPre(right);
left.setNext(self);
right.setPre(self);
right.setNext(left);
self.setPokers(buildPokers(new Object[] {3,3,3,4,4,4,5,6,8,8,11,12,13,13,14,15,15}));
right.setPokers(buildPokers(new Object[] {3,4,5,6,7,9,9,11,11,12,12,12,14,16}));
left.setPokers(buildPokers(new Object[] {6,6,7,7,7,8,8,9,9,10,10,10,10,11,13,14,14,17}));
// self.setPokers(buildPokers(new Object[] {9,9,3,4}));
// right.setPokers(buildPokers(new Object[] {3,3,9,9,10}));
// left.setPokers(buildPokers(new Object[] {6,6,8,8}));
MediumRobotDecisionMakers mediumRobot = new MediumRobotDecisionMakers();
PokerSell lastSell = PokerHelper.checkPokerType(buildPokers(new Object[] {5,5}));
PokerSell sell = mediumRobot.howToPlayPokers(lastSell, self);
if(sell == null) {
System.out.println("Cannot play");
}else {
System.out.println(PokerHelper.printPoker(sell.getSellPokers()));
}
}
}
@@ -1,156 +0,0 @@
package org.nico.ratel.landlords.server.event;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ClientRole;
import org.nico.ratel.landlords.enums.ClientType;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.server.ServerContains;
import org.nico.ratel.landlords.server.robot.RobotEventListener;
import java.util.Map;
public class ServerEventListener_CODE_GAME_LANDLORD_ELECT implements ServerEventListener {
@Override
public void call(ClientSide clientSide, String data) {
Room room = ServerContains.getRoom(clientSide.getRoomId());
Map<String, Object> map = MapHelper.parser(data);
int highestScore = (Integer)map.get("highestScore");
if (room == null) {
return;
}
if (highestScore == 3) {
room.setBaseScore(highestScore);
confirmLandlord(clientSide, room);
return;
}
if (clientSide.getNext().getId() == room.getFirstSellClient()) {
if (highestScore == 0) {
for (ClientSide client : room.getClientSideList()) {
if (client.getRole() == ClientRole.PLAYER) {
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_CYCLE, null);
}
}
ServerEventListener.get(ServerEventCode.CODE_GAME_STARTING).call(clientSide, null);
return;
} else {
room.setBaseScore(highestScore);
int landlordId = (Integer)map.get("currentLandlordId");
for (ClientSide client : room.getClientSideList())
if (client.getId() == landlordId) {
confirmLandlord(client, room);
return;
}
}
}
ClientSide turnClientSide = clientSide.getNext();
room.setCurrentSellClient(turnClientSide.getId());
String result;
if (highestScore != 0) {
result = MapHelper.newInstance()
.put("roomId", room.getId())
.put("roomOwner", room.getRoomOwner())
.put("roomClientCount", room.getClientSideList().size())
.put("preClientNickname", clientSide.getNickname())
.put("preClientId", clientSide.getId())
.put("nextClientNickname", turnClientSide.getNickname())
.put("nextClientId", turnClientSide.getId())
.put("highestScore", highestScore)
.put("currentLandlordId", (Integer)map.get("currentLandlordId"))
.json();
} else {
result = MapHelper.newInstance()
.put("roomId", room.getId())
.put("roomOwner", room.getRoomOwner())
.put("roomClientCount", room.getClientSideList().size())
.put("preClientNickname", clientSide.getNickname())
.put("nextClientNickname", turnClientSide.getNickname())
.put("nextClientId", turnClientSide.getId())
.put("highestScore", 0)
.json();
}
for (ClientSide client : room.getClientSideList()) {
if (client.getRole() == ClientRole.PLAYER) {
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_ELECT, result);
continue;
}
if (client.getId() == turnClientSide.getId()) {
RobotEventListener.get(ClientEventCode.CODE_GAME_LANDLORD_ELECT).call(client, result);
}
}
notifyWatcherRobLandlord(room, clientSide);
}
public void confirmLandlord(ClientSide clientSide, Room room) {
clientSide.getPokers().addAll(room.getLandlordPokers());
PokerHelper.sortPoker(clientSide.getPokers());
int currentClientId = clientSide.getId();
room.setLandlordId(currentClientId);
room.setLastSellClient(currentClientId);
room.setCurrentSellClient(currentClientId);
clientSide.setType(ClientType.LANDLORD);
for (ClientSide client : room.getClientSideList()) {
String result = MapHelper.newInstance()
.put("roomId", room.getId())
.put("roomOwner", room.getRoomOwner())
.put("roomClientCount", room.getClientSideList().size())
.put("landlordNickname", clientSide.getNickname())
.put("landlordId", clientSide.getId())
.put("additionalPokers", room.getLandlordPokers())
.put("baseScore", room.getBaseScore())
.json();
client.resetRound();
if (client.getRole() == ClientRole.PLAYER) {
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_CONFIRM, result);
continue;
}
if (currentClientId == client.getId()) {
RobotEventListener.get(ClientEventCode.CODE_GAME_POKER_PLAY).call(client, result);
}
}
notifyWatcherConfirmLandlord(room, clientSide);
}
/**
* 通知房间内的观战人员谁是地主
*
* @param room 房间
* @param landlord 地主
*/
private void notifyWatcherConfirmLandlord(Room room, ClientSide landlord) {
String json = MapHelper.newInstance()
.put("landlord", landlord.getNickname())
.put("additionalPokers", room.getLandlordPokers())
.json();
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_CONFIRM, json);
}
}
/**
* 通知房间内的观战人员抢地主情况
*
* @param room 房间
*/
private void notifyWatcherRobLandlord(Room room, ClientSide player) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_ELECT, player.getNickname());
}
}
}
@@ -1,231 +0,0 @@
package org.nico.ratel.landlords.server.event;
import java.util.ArrayList;
import java.util.List;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.*;
import org.nico.ratel.landlords.features.Features;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.server.ServerContains;
import org.nico.ratel.landlords.server.robot.RobotEventListener;
import org.nico.ratel.landlords.utils.LastCardsUtils;
public class ServerEventListener_CODE_GAME_POKER_PLAY implements ServerEventListener {
@Override
public void call(ClientSide clientSide, String data) {
Room room = ServerContains.getRoom(clientSide.getRoomId());
if (room == null) {
return;
}
if (room.getCurrentSellClient() != clientSide.getId()) {
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_ORDER_ERROR, null);
return;
}
Character[] options = Noson.convert(data, Character[].class);
int[] indexes = PokerHelper.getIndexes(options, clientSide.getPokers());
if (!PokerHelper.checkPokerIndex(indexes, clientSide.getPokers())) {
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_INVALID, null);
return;
}
boolean sellFlag = true;
List<Poker> currentPokers = PokerHelper.getPoker(indexes, clientSide.getPokers());
PokerSell currentPokerSell = PokerHelper.checkPokerType(currentPokers);
if (currentPokerSell.getSellType() == SellType.ILLEGAL) {
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_INVALID, null);
return;
}
if (room.getLastSellClient() != clientSide.getId() && room.getLastPokerShell() != null) {
PokerSell lastPokerSell = room.getLastPokerShell();
if ((lastPokerSell.getSellType() != currentPokerSell.getSellType() || lastPokerSell.getSellPokers().size() != currentPokerSell.getSellPokers().size()) && currentPokerSell.getSellType() != SellType.BOMB && currentPokerSell.getSellType() != SellType.KING_BOMB) {
String result = MapHelper.newInstance()
.put("playType", currentPokerSell.getSellType())
.put("playCount", currentPokerSell.getSellPokers().size())
.put("preType", lastPokerSell.getSellType())
.put("preCount", lastPokerSell.getSellPokers().size())
.json();
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_MISMATCH, result);
return;
}
if (lastPokerSell.getScore() >= currentPokerSell.getScore()) {
String result = MapHelper.newInstance()
.put("playScore", currentPokerSell.getScore())
.put("preScore", lastPokerSell.getScore())
.json();
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_LESS, result);
return;
}
}
ClientSide next = clientSide.getNext();
clientSide.addRound();
if (currentPokerSell.getSellType() == SellType.BOMB || currentPokerSell.getSellType() == SellType.KING_BOMB) {
// Bomb doubles the score
room.increaseRate();
}
room.setLastSellClient(clientSide.getId());
room.setLastPokerShell(currentPokerSell);
room.setCurrentSellClient(next.getId());
List<List<Poker>> lastPokerList = new ArrayList<>();
for(int i = 0; i < room.getClientSideList().size(); i++){
if(room.getClientSideList().get(i).getId() != clientSide.getId()){
lastPokerList.add(room.getClientSideList().get(i).getPokers());
}
}
String lastPokers = LastCardsUtils.getLastCards(lastPokerList);
lastPokerList = new ArrayList<>();
clientSide.getPokers().removeAll(currentPokers);
MapHelper mapHelper = MapHelper.newInstance()
.put("clientId", clientSide.getId())
.put("clientNickname", clientSide.getNickname())
.put("clientType", clientSide.getType())
.put("pokers", currentPokers)
.put("lastSellClientId", clientSide.getId())
.put("lastSellPokers", currentPokers)
.put("lastPokers",lastPokers);
if (!clientSide.getPokers().isEmpty()) {
mapHelper.put("sellClientNickname", next.getNickname());
}
String result = mapHelper.json();
for (ClientSide client : room.getClientSideList()) {
if (client.getRole() == ClientRole.PLAYER) {
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_SHOW_POKERS, result);
}
}
notifyWatcherPlayPoker(room, result);
if (!clientSide.getPokers().isEmpty()) {
if (next.getRole() == ClientRole.ROBOT) {
RobotEventListener.get(ClientEventCode.CODE_GAME_POKER_PLAY).call(next, data);
} else {
ServerEventListener.get(ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT).call(next, result);
}
return;
}
gameOver(clientSide, room);
// ServerEventListener.get(ServerEventCode.CODE_GAME_STARTING).call(clientSide, data);
}
private void setRoomClientScore(Room room, ClientType winnerType) {
int landLordScore = room.getScore() * 2;
int peasantScore = room.getScore();
// Losing side gets negative score
if (winnerType == ClientType.LANDLORD) {
peasantScore = -peasantScore;
} else {
landLordScore = -landLordScore;
}
for (ClientSide client : room.getClientSideList()) {
if (client.getType() == ClientType.LANDLORD) {
client.addScore(landLordScore);
} else {
client.addScore(peasantScore);
}
}
}
private void gameOver(ClientSide winner, Room room) {
ClientType winnerType = winner.getType();
if (isSpring(winner, room)) {
room.increaseRate();
}
setRoomClientScore(room, winnerType);
ArrayList<Object> clientScores = new ArrayList<>();
for (ClientSide client : room.getClientSideList()) {
MapHelper score = MapHelper.newInstance()
.put("clientId", client.getId())
.put("nickName", client.getNickname())
.put("score", client.getScore())
.put("scoreInc", client.getScoreInc())
.put("pokers", client.getPokers());
clientScores.add(score.map());
}
SimplePrinter.serverLog(clientScores.toString());
String result = MapHelper.newInstance()
.put("winnerNickname", winner.getNickname())
.put("winnerType", winner.getType())
.put("scores", clientScores)
.json();
boolean supportReady = true;
for (ClientSide client : room.getClientSideList()) {
if (client.getRole() == ClientRole.ROBOT || ! Features.supported(client.getVersion(), Features.READY)) {
supportReady = false;
break;
}
}
if (supportReady){
room.setStatus(RoomStatus.WAIT);
room.initScoreRate();
for (ClientSide client : room.getClientSideList()) {
client.setStatus(ClientStatus.NO_READY);
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_OVER, result);
}
}else{
ServerEventListener.get(ServerEventCode.CODE_CLIENT_EXIT).call(winner, "");
}
notifyWatcherGameOver(room, result);
}
private boolean isSpring(ClientSide winner, Room room) {
boolean isSpring = true;
for (ClientSide client: room.getClientSideList()) {
if (client.getType() == winner.getType()) {
continue;
}
if (client.getType() == ClientType.PEASANT && client.getRound() > 0) {
isSpring = false;
}
if (client.getType() == ClientType.LANDLORD && client.getRound() > 1) {
isSpring = false;
}
}
return isSpring;
}
/**
* Notify spectators of card playing information
*
* @param room room
* @param result card playing information
*/
private void notifyWatcherPlayPoker(Room room, String result) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_SHOW_POKERS, result);
}
}
/**
* Notify spectators of game over
*
* @param room room
* @param result card playing information
*/
private void notifyWatcherGameOver(Room room, String result) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_OVER, result);
}
}
}
@@ -1,64 +0,0 @@
package org.nico.ratel.landlords.server.event;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ClientRole;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.server.ServerContains;
import org.nico.ratel.landlords.server.robot.RobotEventListener;
public class ServerEventListener_CODE_GAME_POKER_PLAY_PASS implements ServerEventListener {
@Override
public void call(ClientSide clientSide, String data) {
Room room = ServerContains.getRoom(clientSide.getRoomId());
if(room != null) {
if(room.getCurrentSellClient() == clientSide.getId()) {
if(clientSide.getId() != room.getLastSellClient()) {
ClientSide turnClient = clientSide.getNext();
room.setCurrentSellClient(turnClient.getId());
for(ClientSide client: room.getClientSideList()) {
String result = MapHelper.newInstance()
.put("clientId", clientSide.getId())
.put("clientNickname", clientSide.getNickname())
.put("nextClientId", turnClient.getId())
.put("nextClientNickname", turnClient.getNickname())
.json();
if(client.getRole() == ClientRole.PLAYER) {
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_PASS, result);
}else {
if(client.getId() == turnClient.getId()) {
RobotEventListener.get(ClientEventCode.CODE_GAME_POKER_PLAY).call(turnClient, data);
}
}
}
notifyWatcherPlayPass(room, clientSide);
}else {
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_CANT_PASS, null);
}
}else {
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_ORDER_ERROR, null);
}
}else {
// ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_PLAY_FAIL_BY_INEXIST, null);
}
}
/**
* 通知观战者玩家不出牌
*
* @param room 房间
* @param player 不出牌的玩家
*/
private void notifyWatcherPlayPass(Room room, ClientSide player) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_PASS, player.getNickname());
}
}
}
@@ -1,63 +0,0 @@
package org.nico.ratel.landlords.server.event;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.nico.noson.Noson;
import org.nico.noson.util.string.StringUtils;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.server.ServerContains;
import org.nico.ratel.landlords.utils.LastCardsUtils;
public class ServerEventListener_CODE_GAME_POKER_PLAY_REDIRECT implements ServerEventListener{
@Override
public void call(ClientSide clientSide, String data) {
Room room = ServerContains.getRoom(clientSide.getRoomId());
Map<String, Object> datas = new HashMap<String, Object>();
if(StringUtils.isNotBlank(data)) {
datas = Noson.parseMap(data);
}
List<Map<String, Object>> clientInfos = new ArrayList<Map<String,Object>>(3);
for(ClientSide client : room.getClientSideList()) {
if(clientSide.getId() != client.getId()) {
clientInfos.add(MapHelper.newInstance()
.put("clientId", client.getId())
.put("clientNickname", client.getNickname())
.put("type", client.getType())
.put("surplus", client.getPokers().size())
.put("position", clientSide.getPre().getId() == client.getId() ? "UP" : "DOWN")
.map());
}
}
List<List<Poker>> lastPokerList = new ArrayList<>();
for(int i = 0; i < room.getClientSideList().size(); i++){
if(room.getClientSideList().get(i).getId() != clientSide.getId()){
lastPokerList.add(room.getClientSideList().get(i).getPokers());
}
}
String lastPokers = LastCardsUtils.getLastCards(lastPokerList);
lastPokerList = new ArrayList<>();
String result = MapHelper.newInstance()
.put("pokers", clientSide.getPokers())
.put("lastSellPokers", datas.get("lastSellPokers"))
.put("lastSellClientId", datas.get("lastSellClientId"))
.put("clientInfos", clientInfos)
.put("sellClientId", room.getCurrentSellClient())
.put("sellClientNickname", ServerContains.CLIENT_SIDE_MAP.get(room.getCurrentSellClient()).getNickname())
.put("lastPokers",lastPokers)
.json();
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_REDIRECT, result);
}
}
@@ -1,58 +0,0 @@
package org.nico.ratel.landlords.server.robot;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.helper.TimeHelper;
import org.nico.ratel.landlords.robot.RobotDecisionMakers;
import org.nico.ratel.landlords.server.ServerContains;
import org.nico.ratel.landlords.server.event.ServerEventListener;
public class RobotEventListener_CODE_GAME_LANDLORD_ELECT implements RobotEventListener {
@Override
public void call(ClientSide robot, String data) {
ServerContains.THREAD_EXCUTER.execute(() -> {
Room room = ServerContains.getRoom(robot.getRoomId());
List<Poker> landlordPokers = new ArrayList<>(20);
landlordPokers.addAll(robot.getPokers());
landlordPokers.addAll(room.getLandlordPokers());
List<Poker> leftPokers = new ArrayList<>(17);
leftPokers.addAll(robot.getPre().getPokers());
List<Poker> rightPokers = new ArrayList<>(17);
rightPokers.addAll(robot.getNext().getPokers());
PokerHelper.sortPoker(landlordPokers);
PokerHelper.sortPoker(leftPokers);
PokerHelper.sortPoker(rightPokers);
TimeHelper.sleep(300);
Map<String, Object> map = MapHelper.parser(data);
int expectedScore = RobotDecisionMakers.getLandlordScore(room.getDifficultyCoefficient(), leftPokers, rightPokers, landlordPokers);
int highestScore = (Integer)map.get("highestScore");
String result;
if (expectedScore > highestScore) {
result = MapHelper.newInstance()
.put("highestScore", expectedScore)
.put("currentLandlordId", robot.getId())
.json();
} else {
result = data;
}
ServerEventListener.get(ServerEventCode.CODE_GAME_LANDLORD_ELECT).call(robot, result);
});
}
}
@@ -1,52 +0,0 @@
package org.nico.ratel.landlords.server.robot;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.PokerSell;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.SellType;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.helper.TimeHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.nico.ratel.landlords.robot.RobotDecisionMakers;
import org.nico.ratel.landlords.server.ServerContains;
import org.nico.ratel.landlords.server.event.ServerEventListener;
public class RobotEventListener_CODE_GAME_POKER_PLAY implements RobotEventListener {
@Override
public void call(ClientSide robot, String data) {
ServerContains.THREAD_EXCUTER.execute(() -> {
Room room = ServerContains.getRoom(robot.getRoomId());
PokerSell lastPokerSell = null;
PokerSell pokerSell = null;
if (room.getLastSellClient() != robot.getId()) {
lastPokerSell = room.getLastPokerShell();
pokerSell = RobotDecisionMakers.howToPlayPokers(room.getDifficultyCoefficient(), lastPokerSell, robot);
} else {
pokerSell = RobotDecisionMakers.howToPlayPokers(room.getDifficultyCoefficient(), null, robot);
}
if (pokerSell != null && lastPokerSell != null) {
SimplePrinter.serverLog("Robot monitoring[room:" + room.getId() + "]");
SimplePrinter.serverLog("last sell -> " + lastPokerSell.toString());
SimplePrinter.serverLog("robot sell -> " + pokerSell.toString());
SimplePrinter.serverLog("robot poker -> " + PokerHelper.textOnlyNoType(robot.getPokers()));
}
TimeHelper.sleep(300);
if (pokerSell == null || pokerSell.getSellType() == SellType.ILLEGAL) {
ServerEventListener.get(ServerEventCode.CODE_GAME_POKER_PLAY_PASS).call(robot, data);
} else {
Character[] cs = new Character[pokerSell.getSellPokers().size()];
for (int index = 0; index < cs.length; index++) {
cs[index] = pokerSell.getSellPokers().get(index).getLevel().getAlias()[0];
}
ServerEventListener.get(ServerEventCode.CODE_GAME_POKER_PLAY).call(robot, Noson.reversal(cs));
}
});
}
}
-8
View File
@@ -1,8 +0,0 @@
[
"49.235.95.125:1024:Nico[v1.4.0]",
"47.103.16.48:1024:jsClient[v1.2.7]",
"s2.imlazy.ink:25020:FxCraft[v1.2.6]",
"47.240.60.124:6565:ChenCodeX[v1.2.6]",
"cmi.zerodream.net:1919:ZeroDream[v1.2.2]",
"106.14.125.226:1024:jipaiqi[v1.4.0]"
]