koishi-plugin-satori-ai 1.2.11 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/abstractGame.d.ts +5 -5
- package/lib/game.d.ts +1 -1
- package/lib/gamefencing.d.ts +35 -0
- package/lib/gamegobang.d.ts +10 -5
- package/lib/gobang-ai.exe +0 -0
- package/{wasm → lib}/gobang.cpp +48 -84
- package/lib/index.d.ts +2 -0
- package/lib/index.js +659 -41
- package/lib/types.d.ts +4 -1
- package/package.json +1 -2
- package/wasm/gobang.js +0 -21
- package/wasm/gobang.wasm +0 -0
package/lib/abstractGame.d.ts
CHANGED
|
@@ -15,11 +15,11 @@ export declare abstract class abstractGameSingleGame {
|
|
|
15
15
|
protected session: Session;
|
|
16
16
|
protected disposeListener: () => boolean;
|
|
17
17
|
constructor(disposeListener: () => boolean, session: Session);
|
|
18
|
-
startGame(): string
|
|
19
|
-
endGame(): {
|
|
18
|
+
startGame(): Promise<string>;
|
|
19
|
+
endGame(): Promise<{
|
|
20
20
|
message: string;
|
|
21
21
|
gameName: string;
|
|
22
|
-
}
|
|
22
|
+
}>;
|
|
23
23
|
processInput(str: string): Promise<string>;
|
|
24
24
|
}
|
|
25
25
|
type Constructor<T> = new (...args: any[]) => T;
|
|
@@ -43,10 +43,10 @@ export declare abstract class abstractGame<T extends abstractGameSingleGame> {
|
|
|
43
43
|
* @param ctx Koishi 上下文
|
|
44
44
|
* @param args 启动参数(如难度等级)
|
|
45
45
|
*/
|
|
46
|
-
startGame(session: Session, ctx: Context, args: string[]): abstractGameSingleGame | null
|
|
46
|
+
startGame(session: Session, ctx: Context, args: string[]): Promise<abstractGameSingleGame | null>;
|
|
47
47
|
/**
|
|
48
48
|
* 结束游戏实例,触发结果事件
|
|
49
49
|
*/
|
|
50
|
-
endGame(session: Session, ctx: Context): string
|
|
50
|
+
endGame(session: Session, ctx: Context): Promise<string>;
|
|
51
51
|
}
|
|
52
52
|
export {};
|
package/lib/game.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare class Game {
|
|
|
13
13
|
private sat;
|
|
14
14
|
constructor(ctx: Context, cfg: Sat.Config, sat: SAT);
|
|
15
15
|
private registerCommands;
|
|
16
|
-
startGame(session: Session, gameName: string, args: string[]): Promise<
|
|
16
|
+
startGame(session: Session, gameName: string, args: string[]): Promise<string>;
|
|
17
17
|
endGame(session: Session): Promise<string>;
|
|
18
18
|
private selectGame;
|
|
19
19
|
private chat;
|
package/lib/gamefencing.d.ts
CHANGED
|
@@ -1 +1,36 @@
|
|
|
1
|
+
import { Session } from 'koishi';
|
|
2
|
+
import { abstractGame, abstractGameSingleGame, gameResult } from './abstractGame';
|
|
3
|
+
export declare enum winFlag {
|
|
4
|
+
win = 1,
|
|
5
|
+
lose = 2,
|
|
6
|
+
draw = 3,
|
|
7
|
+
pending = 4
|
|
8
|
+
}
|
|
9
|
+
export interface fencingGameResult extends gameResult {
|
|
10
|
+
win: winFlag;
|
|
11
|
+
}
|
|
12
|
+
declare enum fencingAction {
|
|
13
|
+
attack = 1,
|
|
14
|
+
defence = 2
|
|
15
|
+
}
|
|
16
|
+
declare class fencingSingleGame extends abstractGameSingleGame {
|
|
17
|
+
private winningFlag;
|
|
18
|
+
private playerPosition;
|
|
19
|
+
private enemyPosition;
|
|
20
|
+
private availablePlayerActions;
|
|
21
|
+
static fencingActionHint: Map<fencingAction, string>;
|
|
22
|
+
constructor(disposeListener: () => boolean, session: Session);
|
|
23
|
+
private render;
|
|
24
|
+
startGame: () => Promise<string>;
|
|
25
|
+
endGame: () => Promise<{
|
|
26
|
+
message: string;
|
|
27
|
+
win: winFlag;
|
|
28
|
+
gameName: string;
|
|
29
|
+
}>;
|
|
30
|
+
private enemyDecision;
|
|
31
|
+
processInput(str: string): Promise<string>;
|
|
32
|
+
}
|
|
33
|
+
export declare class fencing extends abstractGame<fencingSingleGame> {
|
|
34
|
+
constructor();
|
|
35
|
+
}
|
|
1
36
|
export {};
|
package/lib/gamegobang.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export declare enum winFlag {
|
|
|
8
8
|
}
|
|
9
9
|
export interface goBangGameResult extends gameResult {
|
|
10
10
|
win: winFlag;
|
|
11
|
-
|
|
11
|
+
message: string;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* 五子棋单局实现类,继承自 abstractGameSingleGame
|
|
@@ -18,27 +18,32 @@ declare class goBangSingleGame extends abstractGameSingleGame {
|
|
|
18
18
|
private winningFlag;
|
|
19
19
|
level: number;
|
|
20
20
|
private board;
|
|
21
|
+
private lastScore;
|
|
22
|
+
private turnsCount;
|
|
21
23
|
constructor(disposeListener: () => boolean, session: Session);
|
|
22
|
-
startGame: () => string
|
|
23
|
-
endGame: () => {
|
|
24
|
+
startGame: () => Promise<string>;
|
|
25
|
+
endGame: () => Promise<{
|
|
24
26
|
message: string;
|
|
25
27
|
win: winFlag;
|
|
26
28
|
gameName: string;
|
|
27
|
-
}
|
|
29
|
+
}>;
|
|
28
30
|
/**
|
|
29
31
|
* 处理玩家输入(落子坐标)
|
|
30
32
|
* @param str 输入内容,格式为 "x y"
|
|
31
33
|
*/
|
|
32
34
|
processInput(str: string): Promise<string>;
|
|
35
|
+
private getAIMove;
|
|
33
36
|
private checkWin;
|
|
34
37
|
private checkDirection;
|
|
38
|
+
private place;
|
|
35
39
|
private printBoard;
|
|
40
|
+
private generateChat;
|
|
36
41
|
}
|
|
37
42
|
/**
|
|
38
43
|
* 五子棋管理类,继承自 abstractGame
|
|
39
44
|
*/
|
|
40
45
|
export declare class goBang extends abstractGame<goBangSingleGame> {
|
|
41
46
|
constructor();
|
|
42
|
-
startGame(session: Session, ctx: Context, args: string[]): goBangSingleGame
|
|
47
|
+
startGame(session: Session, ctx: Context, args: string[]): Promise<goBangSingleGame>;
|
|
43
48
|
}
|
|
44
49
|
export {};
|
|
Binary file
|
package/{wasm → lib}/gobang.cpp
RENAMED
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
1
|
+
// 使用DEV-C++编译器编译
|
|
3
2
|
#define _CRT_SECURE_NO_WARNINGS
|
|
4
3
|
#include <stdio.h>
|
|
5
4
|
#include <stdlib.h>
|
|
6
5
|
#include <string.h>
|
|
7
6
|
#include <string>
|
|
7
|
+
#include <iostream>
|
|
8
|
+
#include <sstream>
|
|
8
9
|
#define BOARD_SIZE 12 // 棋盘大小
|
|
9
10
|
#define EMPTY 0 // 空位
|
|
10
11
|
#define BLACK 1 // 黑棋
|
|
11
12
|
#define WHITE 2 // 白棋
|
|
12
13
|
#define INF 2147483647 // 正无穷
|
|
13
14
|
#define _INF -2147483647 // 负无穷
|
|
14
|
-
#define DEPTH 5 // 搜索深度
|
|
15
|
-
#define START "START" // 开始游戏
|
|
16
|
-
#define PLACE "PLACE" // 放置棋子
|
|
17
|
-
#define TURN "TURN" // 轮到我方下棋
|
|
18
|
-
#define END "END" // 游戏结束
|
|
19
|
-
const int BOARD_MIDDLE_1 = (BOARD_SIZE + 1) / 2 - 1;
|
|
20
|
-
const int BOARD_MIDDLE_2 = BOARD_SIZE / 2;
|
|
21
15
|
struct chessType {
|
|
22
16
|
int win5; // 连五
|
|
23
17
|
int alive4; // 活4
|
|
@@ -29,7 +23,6 @@ struct chessType {
|
|
|
29
23
|
int conti2; // 眠2
|
|
30
24
|
int jump2; // 跳2
|
|
31
25
|
int alive1; // 活1
|
|
32
|
-
int conti1; // 眠1
|
|
33
26
|
};
|
|
34
27
|
// 坐标结构体
|
|
35
28
|
struct coordinate {
|
|
@@ -43,31 +36,19 @@ struct coordinate {
|
|
|
43
36
|
struct Nude {
|
|
44
37
|
int board[BOARD_SIZE][BOARD_SIZE] = {{0}}; // 棋盘状态
|
|
45
38
|
int state = 0; // 棋盘状态标识
|
|
46
|
-
Nude() {
|
|
47
|
-
// 初始化棋盘,放置初始棋子
|
|
48
|
-
board[BOARD_MIDDLE_1][BOARD_MIDDLE_1] = WHITE;
|
|
49
|
-
board[BOARD_MIDDLE_2][BOARD_MIDDLE_2] = WHITE;
|
|
50
|
-
board[BOARD_MIDDLE_2][BOARD_MIDDLE_1] = BLACK;
|
|
51
|
-
board[BOARD_MIDDLE_1][BOARD_MIDDLE_2] = BLACK;
|
|
52
|
-
}
|
|
53
|
-
void arr_input(int x, int y, int playerround) {
|
|
54
|
-
board[x][y] = playerround; // 在指定位置放置棋子
|
|
55
|
-
}
|
|
39
|
+
Nude() {}
|
|
56
40
|
};
|
|
57
41
|
class Game {
|
|
58
42
|
public:
|
|
59
43
|
int myFlag;
|
|
60
44
|
int enemyFlag;
|
|
45
|
+
int inspireSearchLength;
|
|
61
46
|
bool draw;
|
|
62
47
|
Nude MAP;
|
|
63
48
|
Game() :
|
|
64
|
-
|
|
49
|
+
myFlag(0), enemyFlag(0), draw(0) {}
|
|
65
50
|
};
|
|
66
|
-
|
|
67
|
-
void debug(const char *str) {
|
|
68
|
-
printf("DEBUG %s\n", str);
|
|
69
|
-
fflush(stdout);
|
|
70
|
-
}
|
|
51
|
+
|
|
71
52
|
// 判断坐标是否在棋盘范围内
|
|
72
53
|
bool judgeInRange(coordinate temp) {
|
|
73
54
|
if (temp.x < 0)
|
|
@@ -87,9 +68,10 @@ int getColor(coordinate target, const Game &game) {
|
|
|
87
68
|
else
|
|
88
69
|
return game.enemyFlag;
|
|
89
70
|
}
|
|
71
|
+
|
|
90
72
|
// 在指定位置放置棋子
|
|
91
73
|
void place(coordinate target, int player, Game &game) {
|
|
92
|
-
|
|
74
|
+
game.MAP.board[target.x][target.y] = player;
|
|
93
75
|
}
|
|
94
76
|
// 快速排序函数
|
|
95
77
|
int partition(coordinate *s, int high, int low) {
|
|
@@ -109,6 +91,7 @@ int partition(coordinate *s, int high, int low) {
|
|
|
109
91
|
return i;
|
|
110
92
|
}
|
|
111
93
|
void quickSort(coordinate *s, int high, int low = 0) {
|
|
94
|
+
if (high < 0) return;
|
|
112
95
|
if (low < high) {
|
|
113
96
|
int pi = partition(s, high, low);
|
|
114
97
|
quickSort(s, pi - 1, low);
|
|
@@ -388,8 +371,7 @@ chessType typeAnalysis(coordinate p, int dire, int player, const Game &game) {
|
|
|
388
371
|
else if (b[3] == 0)
|
|
389
372
|
temp.conti2++; // 001012xxx
|
|
390
373
|
}
|
|
391
|
-
}
|
|
392
|
-
temp.conti1++; // xxx012xxx
|
|
374
|
+
}
|
|
393
375
|
}
|
|
394
376
|
} else {
|
|
395
377
|
if (b[4] == 0) {
|
|
@@ -414,8 +396,6 @@ chessType typeAnalysis(coordinate p, int dire, int player, const Game &game) {
|
|
|
414
396
|
} else if (b[6] == 0) {
|
|
415
397
|
if (b[7] == player)
|
|
416
398
|
temp.conti2++; // xxx210001
|
|
417
|
-
else if (b[7] == 0)
|
|
418
|
-
temp.conti1++; // xxx210000
|
|
419
399
|
}
|
|
420
400
|
}
|
|
421
401
|
}
|
|
@@ -426,9 +406,9 @@ chessType typeAnalysis(coordinate p, int dire, int player, const Game &game) {
|
|
|
426
406
|
// 单点得分
|
|
427
407
|
int singleScore(coordinate p, int player, const Game &game) {
|
|
428
408
|
chessType chesstype = typeAnalysis(p, 0, player, game);
|
|
409
|
+
int score = 0;
|
|
429
410
|
for (int i = 1; i < 4; i++) {
|
|
430
|
-
chessType temp;
|
|
431
|
-
temp = typeAnalysis(p, i, player, game);
|
|
411
|
+
chessType temp = typeAnalysis(p, i, player, game);
|
|
432
412
|
chesstype.win5 += temp.win5;
|
|
433
413
|
chesstype.alive4 += temp.alive4;
|
|
434
414
|
chesstype.conti4 += temp.conti4;
|
|
@@ -439,16 +419,12 @@ int singleScore(coordinate p, int player, const Game &game) {
|
|
|
439
419
|
chesstype.conti2 += temp.conti2;
|
|
440
420
|
chesstype.jump2 += temp.jump2;
|
|
441
421
|
chesstype.alive1 += temp.alive1;
|
|
442
|
-
chesstype.conti1 += temp.conti1;
|
|
443
422
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
(chesstype.alive1 << 3) + chesstype.conti1);
|
|
450
|
-
if (chesstype.alive3 >= 2 || (chesstype.conti4 && chesstype.alive3) || chesstype.alive4 || chesstype.conti4 >= 2) // 必胜?
|
|
451
|
-
score += 65536;
|
|
423
|
+
score += chesstype.win5 << 20;
|
|
424
|
+
score += ((chesstype.conti4 << 9) + (chesstype.alive3 << 8) + (chesstype.conti3 << 7) +
|
|
425
|
+
(chesstype.jump3 << 6) + (chesstype.alive2 << 5) + (chesstype.jump2 << 3) + chesstype.conti2 + chesstype.alive1);
|
|
426
|
+
if (chesstype.alive3 > 1 || (chesstype.conti4 && chesstype.alive3) || chesstype.alive4 || chesstype.conti4 > 1) // 必胜?
|
|
427
|
+
score += (1 << 12);
|
|
452
428
|
return score;
|
|
453
429
|
}
|
|
454
430
|
// 棋盘整体局面分
|
|
@@ -474,10 +450,9 @@ int inspireSearch(coordinate *scoreBoard, int player, Game &game) {
|
|
|
474
450
|
for (int j = 0; j < BOARD_SIZE; j++) {
|
|
475
451
|
if (game.MAP.board[i][j] == 0) {
|
|
476
452
|
coordinate temp = {i, j, 0};
|
|
477
|
-
if (hasNeighbor(temp,
|
|
453
|
+
if (hasNeighbor(temp, 2, game)) {
|
|
478
454
|
scoreBoard[length] = temp;
|
|
479
|
-
scoreBoard[length].score = singleScore(temp, 3 - player, game);
|
|
480
|
-
scoreBoard[length].score += singleScore(temp, player, game);
|
|
455
|
+
scoreBoard[length].score = singleScore(temp, 3 - player, game) + singleScore(temp, player, game);
|
|
481
456
|
length++;
|
|
482
457
|
}
|
|
483
458
|
}
|
|
@@ -487,7 +462,7 @@ int inspireSearch(coordinate *scoreBoard, int player, Game &game) {
|
|
|
487
462
|
quickSort(scoreBoard, length - 1);
|
|
488
463
|
// 找到最高分数
|
|
489
464
|
int maxScore = scoreBoard[0].score;
|
|
490
|
-
if (maxScore < 5)
|
|
465
|
+
if (maxScore < 5 || length == 0)
|
|
491
466
|
game.draw = 1;
|
|
492
467
|
const int threshold = maxScore / 3;
|
|
493
468
|
// 找到分界线
|
|
@@ -501,8 +476,9 @@ int inspireSearch(coordinate *scoreBoard, int player, Game &game) {
|
|
|
501
476
|
// 更新 length 为分界线的位置
|
|
502
477
|
length = boundary;
|
|
503
478
|
// 返回 length,最多不超过
|
|
504
|
-
return length >
|
|
479
|
+
return length > game.inspireSearchLength ? game.inspireSearchLength : length;
|
|
505
480
|
}
|
|
481
|
+
|
|
506
482
|
// 负极大极小值搜索
|
|
507
483
|
coordinate alphaBeta(int depth, int alpha, int beta, int player, coordinate command, coordinate current, Game &game) {
|
|
508
484
|
coordinate temp = command;
|
|
@@ -512,9 +488,7 @@ coordinate alphaBeta(int depth, int alpha, int beta, int player, coordinate comm
|
|
|
512
488
|
}
|
|
513
489
|
coordinate steps[BOARD_SIZE * BOARD_SIZE];
|
|
514
490
|
int length = inspireSearch(steps, player, game); // 搜索可落子点
|
|
515
|
-
if (length >
|
|
516
|
-
depth--;
|
|
517
|
-
else if (length > 2)
|
|
491
|
+
if (length > 2)
|
|
518
492
|
depth--;
|
|
519
493
|
for (int i = 0; i < length; i++) {
|
|
520
494
|
place(steps[i], player, game); // 模拟落子
|
|
@@ -554,39 +528,29 @@ coordinate entrance(int depth, int alpha, int beta, int player, coordinate comma
|
|
|
554
528
|
return best;
|
|
555
529
|
}
|
|
556
530
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
* outScore: 落子分数
|
|
568
|
-
* -1: 游戏平局
|
|
569
|
-
*/
|
|
570
|
-
extern "C" void decideMove(const int board[BOARD_SIZE * BOARD_SIZE], int myFlag, int depth, int* outX, int* outY, int* outScore) {
|
|
571
|
-
Game localGame;
|
|
572
|
-
for (int i = 0; i < BOARD_SIZE; i++) {
|
|
573
|
-
for (int j = 0; j < BOARD_SIZE; j++) {
|
|
574
|
-
localGame.MAP.board[i][j] = board[i * BOARD_SIZE + j];
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
localGame.myFlag = myFlag;
|
|
578
|
-
localGame.enemyFlag = 3 - myFlag;
|
|
579
|
-
localGame.draw = 0;
|
|
531
|
+
coordinate calculateNextMove(const std::string& boardStr, int playerFlag, int difficulty, int inspireSearchLength) {
|
|
532
|
+
Game game;
|
|
533
|
+
game.myFlag = playerFlag;
|
|
534
|
+
game.enemyFlag = 3 - playerFlag;
|
|
535
|
+
game.inspireSearchLength = inspireSearchLength;
|
|
536
|
+
// 解析棋盘字符串
|
|
537
|
+
std::istringstream iss(boardStr);
|
|
538
|
+
for(int i=0; i<BOARD_SIZE; ++i)
|
|
539
|
+
for(int j=0; j<BOARD_SIZE; ++j)
|
|
540
|
+
iss >> game.MAP.board[i][j];
|
|
580
541
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
542
|
+
int depth = difficulty + 1;
|
|
543
|
+
coordinate best = entrance(depth, _INF, INF, game.myFlag, coordinate(), coordinate(), game);
|
|
544
|
+
if (game.draw) {
|
|
545
|
+
best.x = -1;
|
|
546
|
+
best.y = -1;
|
|
547
|
+
best.score = -1;
|
|
548
|
+
}
|
|
549
|
+
return best;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
int main(int argc, char* argv[]) {
|
|
553
|
+
coordinate result = calculateNextMove(argv[1], atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
|
|
554
|
+
std::cout << result.x << " " << result.y << " " << result.score;
|
|
555
|
+
return 0;
|
|
592
556
|
}
|
package/lib/index.d.ts
CHANGED