From d81358c80f1ef37321b7ef13dc1ba3855d57905c Mon Sep 17 00:00:00 2001
From: Michael Ficocelli Retrieves a simplified version of the board state. "X" represents black pieces, "O" white, and "." empty points. "\#" are dead nodes that are not part of the subnet. (They are not territory nor open nodes.) For example, a 5x5 board might look like this: Each string represents a vertical column on the board, and each character in the string represents a point. Traditional notation for Go is e.g. "B,1" referring to second ("B") column, first rank. This is the equivalent of index \[1\]\[0\]. Note that the \[0\]\[0\] point is shown on the bottom-left on the visual board (as is traditional), and each string represents a vertical column on the board. In other words, the printed example above can be understood to be rotated 90 degrees clockwise compared to the board UI as shown in the IPvGO subnet tab. Retrieves a simplified version of the board state. "X" represents black pieces, "O" white, and "." empty points. "\#" are dead nodes that are not part of the subnet. (They are not territory nor open nodes.) For example, a 5x5 board might look like this: \[ "XX.O.", "X..OO", ".XO..", "XXO.\#", ".XO.\#", \]
+
Each string represents a vertical column on the board, and each character in the string represents a point.
Traditional notation for Go is e.g. "B,1" referring to second ("B") column, first rank. This is the equivalent of index \[1\]\[0\].
diff --git a/markdown/bitburner.go.getcurrentplayer.md b/markdown/bitburner.go.getcurrentplayer.md
new file mode 100644
index 000000000..03bb8d61d
--- /dev/null
+++ b/markdown/bitburner.go.getcurrentplayer.md
@@ -0,0 +1,19 @@
+
+
+[Home](./index.md) > [bitburner](./bitburner.md) > [Go](./bitburner.go.md) > [getCurrentPlayer](./bitburner.go.getcurrentplayer.md)
+
+## Go.getCurrentPlayer() method
+
+Returns the color of the current player, or 'None' if the game is over.
+
+**Signature:**
+
+```typescript
+getCurrentPlayer(): "White" | "Black" | "None";
+```
+**Returns:**
+
+"White" \| "Black" \| "None"
+
+"White" \| "Black" \| "None"
+
diff --git a/markdown/bitburner.go.getgamestate.md b/markdown/bitburner.go.getgamestate.md
new file mode 100644
index 000000000..56bb4016e
--- /dev/null
+++ b/markdown/bitburner.go.getgamestate.md
@@ -0,0 +1,22 @@
+
+
+[Home](./index.md) > [bitburner](./bitburner.md) > [Go](./bitburner.go.md) > [getGameState](./bitburner.go.getgamestate.md)
+
+## Go.getGameState() method
+
+Gets the status of the current game. Shows the current player, current score, and the previous move coordinates. Previous move coordinates will be \[-1, -1\] for a pass, or if there are no prior moves.
+
+**Signature:**
+
+```typescript
+getGameState(): {
+ currentPlayer: "White" | "Black" | "None";
+ whiteScore: number;
+ blackScore: number;
+ previousMove: [number, number] | null;
+ };
+```
+**Returns:**
+
+{ currentPlayer: "White" \| "Black" \| "None"; whiteScore: number; blackScore: number; previousMove: \[number, number\] \| null; }
+
diff --git a/markdown/bitburner.go.makemove.md b/markdown/bitburner.go.makemove.md
index eb336d7ad..cd229be4c 100644
--- a/markdown/bitburner.go.makemove.md
+++ b/markdown/bitburner.go.makemove.md
@@ -13,10 +13,9 @@ makeMove(
x: number,
y: number,
): Promise<{
- type: "invalid" | "move" | "pass" | "gameOver";
- x: number;
- y: number;
- success: boolean;
+ type: "move" | "pass" | "gameOver";
+ x: number | null;
+ y: number | null;
}>;
```
@@ -29,7 +28,7 @@ makeMove(
**Returns:**
-Promise<{ type: "invalid" \| "move" \| "pass" \| "gameOver"; x: number; y: number; success: boolean; }>
+Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }>
a promise that contains if your move was valid and successful, the opponent move's x and y coordinates (or pass) in response, or an indication if the game has ended
diff --git a/markdown/bitburner.go.md b/markdown/bitburner.go.md
index af3341053..fc5dea287 100644
--- a/markdown/bitburner.go.md
+++ b/markdown/bitburner.go.md
@@ -17,25 +17,18 @@ export interface Go
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [analysis](./bitburner.go.analysis.md) | | { getValidMoves(): boolean\[\]\[\]; getChains(): (number \| null)\[\]\[\]; getLiberties(): number\[\]\[\]; getControlledEmptyNodes(): string\[\]; } | Tools to analyze the IPvGO subnet. |
-| [cheat](./bitburner.go.cheat.md) | | { getCheatSuccessChance(): number; removeRouter( x: number, y: number, ): Promise<{ type: "invalid" \| "move" \| "pass" \| "gameOver"; x: number; y: number; success: boolean; }>; playTwoMoves( x1: number, y1: number, x2: number, y2: number, ): Promise<{ type: "invalid" \| "move" \| "pass" \| "gameOver"; x: number; y: number; success: boolean; }>; repairOfflineNode( x: number, y: number, ): Promise<{ type: "invalid" \| "move" \| "pass" \| "gameOver"; x: number; y: number; success: boolean; }>; destroyNode( x: number, y: number, ): Promise<{ type: "invalid" \| "move" \| "pass" \| "gameOver"; x: number; y: number; success: boolean; }>; } | Illicit and dangerous IPvGO tools. Not for the faint of heart. Requires Bitnode 14.2 to use. |
+| [cheat](./bitburner.go.cheat.md) | | { getCheatSuccessChance(): number; removeRouter( x: number, y: number, ): Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }>; playTwoMoves( x1: number, y1: number, x2: number, y2: number, ): Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }>; repairOfflineNode( x: number, y: number, ): Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }>; destroyNode( x: number, y: number, ): Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }>; } | Illicit and dangerous IPvGO tools. Not for the faint of heart. Requires Bitnode 14.2 to use. |
## Methods
| Method | Description |
| --- | --- |
-| [getBoardState()](./bitburner.go.getboardstate.md) | \[ "XX.O.", "X..OO", ".XO..", "XXO.\#", ".XO.\#", \]
Each string represents a vertical column on the board, and each character in the string represents a point.
Traditional notation for Go is e.g. "B,1" referring to second ("B") column, first rank. This is the equivalent of index \[1\]\[0\].
Note that the \[0\]\[0\] point is shown on the bottom-left on the visual board (as is traditional), and each string represents a vertical column on the board. In other words, the printed example above can be understood to be rotated 90 degrees clockwise compared to the board UI as shown in the IPvGO subnet tab.
| +| [getCurrentPlayer()](./bitburner.go.getcurrentplayer.md) | Returns the color of the current player, or 'None' if the game is over. | +| [getGameState()](./bitburner.go.getgamestate.md) | Gets the status of the current game. Shows the current player, current score, and the previous move coordinates. Previous move coordinates will be \[-1, -1\] for a pass, or if there are no prior moves. | | [getOpponent()](./bitburner.go.getopponent.md) | Returns the name of the opponent faction in the current subnet. | | [makeMove(x, y)](./bitburner.go.makemove.md) | Make a move on the IPvGO subnet gameboard, and await the opponent's response. x:0 y:0 represents the bottom-left corner of the board in the UI. | +| [opponentNextTurn(logOpponentMove)](./bitburner.go.opponentnextturn.md) | Returns a promise that resolves with the success or failure state of your last move, and the AI's response, if applicable. x:0 y:0 represents the bottom-left corner of the board in the UI. | | [passTurn()](./bitburner.go.passturn.md) |Pass the player's turn rather than making a move, and await the opponent's response. This ends the game if the opponent passed on the previous turn, or if the opponent passes on their following turn.
This can also be used if you pick up the game in a state where the opponent needs to play next. For example: if BitBurner was closed while waiting for the opponent to make a move, you may need to call passTurn() to get them to play their move on game start.
| | [resetBoardState(opponent, boardSize)](./bitburner.go.resetboardstate.md) |Gets new IPvGO subnet with the specified size owned by the listed faction, ready for the player to make a move. This will reset your win streak if the current game is not complete and you have already made moves.
Note that some factions will have a few routers on the subnet at this state.
opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Daedalus" or "Illuminati",
| diff --git a/markdown/bitburner.go.opponentnextturn.md b/markdown/bitburner.go.opponentnextturn.md new file mode 100644 index 000000000..d3b1b2630 --- /dev/null +++ b/markdown/bitburner.go.opponentnextturn.md @@ -0,0 +1,34 @@ + + +[Home](./index.md) > [bitburner](./bitburner.md) > [Go](./bitburner.go.md) > [opponentNextTurn](./bitburner.go.opponentnextturn.md) + +## Go.opponentNextTurn() method + +Returns a promise that resolves with the success or failure state of your last move, and the AI's response, if applicable. x:0 y:0 represents the bottom-left corner of the board in the UI. + +**Signature:** + +```typescript +opponentNextTurn(logOpponentMove: boolean = true): Promise<{ + type: "move" | "pass" | "gameOver"; + x: number | null; + y: number | null; + }>; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| logOpponentMove | boolean | _(Optional)_ optional, if false prevents logging opponent move | + +**Returns:** + +Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }> + +a promise that contains if your last move was valid and successful, the opponent move's x and y coordinates (or pass) in response, or an indication if the game has ended + +## Remarks + +RAM cost: 0 GB + diff --git a/markdown/bitburner.go.passturn.md b/markdown/bitburner.go.passturn.md index ea742ff42..5bedddaf1 100644 --- a/markdown/bitburner.go.passturn.md +++ b/markdown/bitburner.go.passturn.md @@ -12,15 +12,14 @@ This can also be used if you pick up the game in a state where the opponent need ```typescript passTurn(): Promise<{ - type: "invalid" | "move" | "pass" | "gameOver"; - x: number; - y: number; - success: boolean; + type: "move" | "pass" | "gameOver"; + x: number | null; + y: number | null; }>; ``` **Returns:** -Promise<{ type: "invalid" \| "move" \| "pass" \| "gameOver"; x: number; y: number; success: boolean; }> +Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }> a promise that contains if your move was valid and successful, the opponent move's x and y coordinates (or pass) in response, or an indication if the game has ended diff --git a/src/Documentation/doc/programming/go_algorithms.md b/src/Documentation/doc/programming/go_algorithms.md index c9a660536..8d7e75d4a 100644 --- a/src/Documentation/doc/programming/go_algorithms.md +++ b/src/Documentation/doc/programming/go_algorithms.md @@ -97,8 +97,8 @@ Both `makeMove()` and `passTurn()` , when awaited, return an object that tells y success: boolean; // If the opponent moved or passed, or if the game is now over, or if your move was invalid type: "invalid" | "move" | "pass" | "gameOver"; - x: number; // Opponent move's x coord (if applicable) - y: number; // Opponent move's y coord (if applicable) + x: number | null; // Opponent move's x coord (if applicable) + y: number | null; // Opponent move's y coord (if applicable) } ``` @@ -130,14 +130,14 @@ export async function main(ns) { result = await ns.go.makeMove(x, y); } + // Log opponent's next move, once it happens + await ns.go.opponentNextTurn(); + await ns.sleep(200); // Keep looping as long as the opponent is playing moves } while (result?.type !== "gameOver"); - // After the opponent passes, end the game by passing as well - await ns.go.passTurn(); - // TODO: add a loop to keep playing // TODO: reset board, e.g. `ns.go.resetBoardState("Netburners", 7)` } diff --git a/src/Go/Enums.ts b/src/Go/Enums.ts index 7a2d4b63d..250966cc3 100644 --- a/src/Go/Enums.ts +++ b/src/Go/Enums.ts @@ -27,7 +27,6 @@ export enum GoValidity { } export enum GoPlayType { - invalid = "invalid", move = "move", pass = "pass", gameOver = "gameOver", diff --git a/src/Go/Go.ts b/src/Go/Go.ts index ece1fb52d..53360beb9 100644 --- a/src/Go/Go.ts +++ b/src/Go/Go.ts @@ -1,5 +1,5 @@ -import type { GoOpponent } from "./Enums"; -import type { BoardState, OpponentStats } from "./Types"; +import type { GoOpponent } from "@enums"; +import type { BoardState, OpponentStats, Play } from "./Types"; import { getRecordValues, PartialRecord } from "../Types/Record"; import { getNewBoardState } from "./boardState/boardState"; @@ -10,6 +10,7 @@ export class GoObject { previousGame: BoardState | null = null; currentGame: BoardState = getNewBoardState(7); stats: PartialRecord
+ * [
+ * "XX.O.",
+ * "X..OO",
+ * ".XO..",
+ * "XXO.#",
+ * ".XO.#",
+ * ]
+ *
*
* Each string represents a vertical column on the board, and each character in the string represents a point.
*
@@ -3995,6 +4011,24 @@ export interface Go {
*/
getBoardState(): string[];
+ /**
+ * Returns the color of the current player, or 'None' if the game is over.
+ * @returns "White" | "Black" | "None"
+ */
+ getCurrentPlayer(): "White" | "Black" | "None";
+
+ /**
+ * Gets the status of the current game.
+ * Shows the current player, current score, and the previous move coordinates.
+ * Previous move coordinates will be [-1, -1] for a pass, or if there are no prior moves.
+ */
+ getGameState(): {
+ currentPlayer: "White" | "Black" | "None";
+ whiteScore: number;
+ blackScore: number;
+ previousMove: [number, number] | null;
+ };
+
/**
* Returns the name of the opponent faction in the current subnet.
*/
@@ -4024,11 +4058,9 @@ export interface Go {
* Shows if each point on the board is a valid move for the player.
*
* The true/false validity of each move can be retrieved via the X and Y coordinates of the move.
-```
- const validMoves = ns.go.analysis.getValidMoves();
-
- const moveIsValid = validMoves[x][y];
-```
+ * `const validMoves = ns.go.analysis.getValidMoves();`
+ *
+ * `const moveIsValid = validMoves[x][y];`
*
* Note that the [0][0] point is shown on the bottom-left on the visual board (as is traditional), and each
* string represents a vertical column on the board. In other words, the printed example above can be understood to
@@ -4048,16 +4080,15 @@ export interface Go {
*
* For example, a 5x5 board might look like this. There is a large chain #1 on the left side, smaller chains
* 2 and 3 on the right, and a large chain 0 taking up the center of the board.
- *
-```
- [
- [ 0,0,0,3,4],
- [ 1,0,0,3,3],
- [ 1,1,0,0,0],
- [null,1,0,2,2],
- [null,1,0,2,5],
- ]
-```
+ *
+ * [
+ * [ 0,0,0,3,4],
+ * [ 1,0,0,3,3],
+ * [ 1,1,0,0,0],
+ * [null,1,0,2,2],
+ * [null,1,0,2,5],
+ * ]
+ *
* @remarks
* RAM cost: 16 GB
* (This is intentionally expensive; you can derive this info from just getBoardState() )
@@ -4072,15 +4103,15 @@ export interface Go {
* For example, a 5x5 board might look like this. The chain in the top-left touches 5 total empty nodes, and the one
* in the center touches four. The group in the bottom-right only has one liberty; it is in danger of being captured!
*
-```
- [
- [-1, 5,-1,-1, 2],
- [ 5, 5,-1,-1,-1],
- [-1,-1, 4,-1,-1],
- [ 3,-1,-1, 3, 1],
- [ 3,-1,-1, 3, 1],
- ]
-```
+ *
+ * [
+ * [-1, 5,-1,-1, 2],
+ * [ 5, 5,-1,-1,-1],
+ * [-1,-1, 4,-1,-1],
+ * [ 3,-1,-1, 3, 1],
+ * [ 3,-1,-1, 3, 1],
+ * ]
+ *
*
* @remarks
* RAM cost: 16 GB
@@ -4096,15 +4127,16 @@ export interface Go {
* Filled points of any color are indicated with '.'
*
* In this example, white encircles some space in the top-left, black encircles some in the top-right, and between their routers is contested space in the center:
-```
- [
- "OO..?",
- "OO.?.",
- "O.?.X",
- ".?.XX",
- "?..X#",
- ]
-```
+ *
+ *
+ * [
+ * "OO..?",
+ * "OO.?.",
+ * "O.?.X",
+ * ".?.XX",
+ * "?..X#",
+ * ]
+ *
*
* @remarks
* RAM cost: 16 GB
@@ -4147,10 +4179,9 @@ export interface Go {
x: number,
y: number,
): Promise<{
- type: "invalid" | "move" | "pass" | "gameOver";
- x: number;
- y: number;
- success: boolean;
+ type: "move" | "pass" | "gameOver";
+ x: number | null;
+ y: number | null;
}>;
/**
* Attempts to place two routers at once on empty nodes. Note that this ignores other move restrictions, so you can
@@ -4173,10 +4204,9 @@ export interface Go {
x2: number,
y2: number,
): Promise<{
- type: "invalid" | "move" | "pass" | "gameOver";
- x: number;
- y: number;
- success: boolean;
+ type: "move" | "pass" | "gameOver";
+ x: number | null;
+ y: number | null;
}>;
/**
@@ -4197,10 +4227,9 @@ export interface Go {
x: number,
y: number,
): Promise<{
- type: "invalid" | "move" | "pass" | "gameOver";
- x: number;
- y: number;
- success: boolean;
+ type: "move" | "pass" | "gameOver";
+ x: number | null;
+ y: number | null;
}>;
/**
@@ -4222,10 +4251,9 @@ export interface Go {
x: number,
y: number,
): Promise<{
- type: "invalid" | "move" | "pass" | "gameOver";
- x: number;
- y: number;
- success: boolean;
+ type: "move" | "pass" | "gameOver";
+ x: number | null;
+ y: number | null;
}>;
};
}
diff --git a/test/jest/Go/NetscriptGo.test.ts b/test/jest/Go/NetscriptGo.test.ts
index 6039c96b7..8599093cc 100644
--- a/test/jest/Go/NetscriptGo.test.ts
+++ b/test/jest/Go/NetscriptGo.test.ts
@@ -8,12 +8,13 @@ import {
cheatRepairOfflineNode,
getChains,
getControlledEmptyNodes,
+ getGameState,
getLiberties,
getValidMoves,
handlePassTurn,
- invalidMoveResponse,
makePlayerMove,
resetBoardState,
+ validateMove,
} from "../../../src/Go/effects/netscriptGoImplementation";
import { PlayerObject } from "../../../src/PersonObjects/Player/PlayerObject";
import "../../../src/Faction/Factions";
@@ -31,11 +32,13 @@ describe("Netscript Go API unit tests", () => {
const board = ["XOO..", ".....", ".....", ".....", "....."];
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
const mockLogger = jest.fn();
+ const mockError = jest.fn(() => {
+ throw new Error("Invalid");
+ });
- const result = await makePlayerMove(mockLogger, 0, 0);
+ await makePlayerMove(mockLogger, mockError, 0, 0).catch((_) => _);
- expect(result).toEqual(invalidMoveResponse);
- expect(mockLogger).toHaveBeenCalledWith("ERROR: Invalid move: That node is already occupied by a piece");
+ expect(mockError).toHaveBeenCalledWith("Invalid move: 0 0. That node is already occupied by a piece.");
});
it("should update the board with valid player moves", async () => {
@@ -43,10 +46,10 @@ describe("Netscript Go API unit tests", () => {
const boardState = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
Go.currentGame = boardState;
const mockLogger = jest.fn();
+ const mockError = jest.fn();
- const result = await makePlayerMove(mockLogger, 1, 0);
+ await makePlayerMove(mockLogger, mockError, 1, 0);
- expect(result.success).toEqual(true);
expect(mockLogger).toHaveBeenCalledWith("Go move played: 1, 0");
expect(boardState.board[1]?.[0]?.color).toEqual(GoColor.black);
expect(boardState.board[0]?.[0]?.color).toEqual(GoColor.empty);
@@ -59,7 +62,6 @@ describe("Netscript Go API unit tests", () => {
const result = await handlePassTurn(mockLogger);
- expect(result.success).toEqual(true);
expect(result.type).toEqual(GoPlayType.move);
});
});
@@ -75,6 +77,24 @@ describe("Netscript Go API unit tests", () => {
});
});
+ describe("getGameState() tests", () => {
+ it("should correctly retrieve the current game state", async () => {
+ const board = ["OXX..", ".....", ".....", "...XX", "...X."];
+ const boardState = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.black);
+ boardState.previousBoard = ["OX..", ".....", ".....", "...XX", "...X."];
+ Go.currentGame = boardState;
+
+ const result = getGameState();
+
+ expect(result).toEqual({
+ currentPlayer: GoColor.white,
+ whiteScore: 6.5,
+ blackScore: 6,
+ previousMove: [0, 2],
+ });
+ });
+ });
+
describe("resetBoardState() tests", () => {
it("should set the player's board to the requested size and opponent", () => {
const board = ["OXX..", ".....", ".....", ".....", "..###"];
@@ -170,12 +190,14 @@ describe("Netscript Go API unit tests", () => {
it("should handle invalid moves", async () => {
const board = ["XOO..", ".....", ".....", ".....", "....."];
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
- const mockLogger = jest.fn();
-
- const result = await cheatPlayTwoMoves(mockLogger, 0, 0, 1, 0, 0, 0);
-
- expect(result).toEqual(invalidMoveResponse);
- expect(mockLogger).toHaveBeenCalledWith("The point 0,0 is not empty, so you cannot place a router there.");
+ const mockError = jest.fn();
+ validateMove(mockError, 0, 0, "playTwoMoves", {
+ repeat: false,
+ suicide: false,
+ });
+ expect(mockError).toHaveBeenCalledWith(
+ "The point 0,0 is occupied by a router, so you cannot place a router there",
+ );
});
it("should update the board with both player moves if nodes are unoccupied and cheat is successful", async () => {
@@ -183,9 +205,8 @@ describe("Netscript Go API unit tests", () => {
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
const mockLogger = jest.fn();
- const result = await cheatPlayTwoMoves(mockLogger, 4, 3, 3, 4, 0, 0);
+ await cheatPlayTwoMoves(mockLogger, 4, 3, 3, 4, 0, 0);
expect(mockLogger).toHaveBeenCalledWith("Cheat successful. Two go moves played: 4,3 and 3,4");
- expect(result.success).toEqual(true);
expect(Go.currentGame.board[4]?.[3]?.color).toEqual(GoColor.black);
expect(Go.currentGame.board[3]?.[4]?.color).toEqual(GoColor.black);
expect(Go.currentGame.board[4]?.[4]?.color).toEqual(GoColor.empty);
@@ -196,9 +217,8 @@ describe("Netscript Go API unit tests", () => {
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
const mockLogger = jest.fn();
- const result = await cheatPlayTwoMoves(mockLogger, 4, 3, 3, 4, 2, 1);
+ await cheatPlayTwoMoves(mockLogger, 4, 3, 3, 4, 2, 1);
expect(mockLogger).toHaveBeenCalledWith("Cheat failed. Your turn has been skipped.");
- expect(result.success).toEqual(false);
expect(Go.currentGame.board[4]?.[3]?.color).toEqual(GoColor.empty);
expect(Go.currentGame.board[3]?.[4]?.color).toEqual(GoColor.empty);
expect(Go.currentGame.board[4]?.[4]?.color).toEqual(GoColor.white);
@@ -210,9 +230,8 @@ describe("Netscript Go API unit tests", () => {
Go.currentGame.cheatCount = 1;
const mockLogger = jest.fn();
- const result = await cheatPlayTwoMoves(mockLogger, 4, 3, 3, 4, 1, 0);
+ await cheatPlayTwoMoves(mockLogger, 4, 3, 3, 4, 1, 0);
expect(mockLogger).toHaveBeenCalledWith("Cheat failed! You have been ejected from the subnet.");
- expect(result.success).toEqual(false);
expect(Go.currentGame.previousBoard).toEqual(null);
});
});
@@ -220,12 +239,14 @@ describe("Netscript Go API unit tests", () => {
it("should handle invalid moves", async () => {
const board = ["XOO..", ".....", ".....", ".....", "....."];
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
- const mockLogger = jest.fn();
-
- const result = await cheatRemoveRouter(mockLogger, 1, 0, 0, 0);
-
- expect(result).toEqual(invalidMoveResponse);
- expect(mockLogger).toHaveBeenCalledWith(
+ const mockError = jest.fn();
+ validateMove(mockError, 1, 0, "removeRouter", {
+ emptyNode: false,
+ requireNonEmptyNode: true,
+ repeat: false,
+ suicide: false,
+ });
+ expect(mockError).toHaveBeenCalledWith(
"The point 1,0 does not have a router on it, so you cannot clear this point with removeRouter().",
);
});
@@ -235,9 +256,8 @@ describe("Netscript Go API unit tests", () => {
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
const mockLogger = jest.fn();
- const result = await cheatRemoveRouter(mockLogger, 0, 0, 0, 0);
+ await cheatRemoveRouter(mockLogger, 0, 0, 0, 0);
- expect(result.success).toEqual(true);
expect(mockLogger).toHaveBeenCalledWith("Cheat successful. The point 0,0 was cleared.");
expect(Go.currentGame.board[0][0]?.color).toEqual(GoColor.empty);
});
@@ -248,9 +268,8 @@ describe("Netscript Go API unit tests", () => {
Go.currentGame.cheatCount = 1;
const mockLogger = jest.fn();
- const result = await cheatRemoveRouter(mockLogger, 0, 0, 1, 0);
+ await cheatRemoveRouter(mockLogger, 0, 0, 1, 0);
expect(mockLogger).toHaveBeenCalledWith("Cheat failed! You have been ejected from the subnet.");
- expect(result.success).toEqual(false);
expect(Go.currentGame.previousBoard).toEqual(null);
});
});
@@ -258,12 +277,16 @@ describe("Netscript Go API unit tests", () => {
it("should handle invalid moves", async () => {
const board = ["XOO..", ".....", ".....", ".....", "....#"];
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
- const mockLogger = jest.fn();
+ const mockError = jest.fn();
+ validateMove(mockError, 0, 0, "repairOfflineNode", {
+ emptyNode: false,
+ repeat: false,
+ onlineNode: false,
+ requireOfflineNode: true,
+ suicide: false,
+ });
- const result = await cheatRepairOfflineNode(mockLogger, 0, 0);
-
- expect(result).toEqual(invalidMoveResponse);
- expect(mockLogger).toHaveBeenCalledWith("The node 0,0 is not offline, so you cannot repair the node.");
+ expect(mockError).toHaveBeenCalledWith("The node 0,0 is not offline, so you cannot repair the node.");
});
it("should update the board with the repaired node if the cheat is successful", async () => {
@@ -271,9 +294,8 @@ describe("Netscript Go API unit tests", () => {
Go.currentGame = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.white);
const mockLogger = jest.fn();
- const result = await cheatRepairOfflineNode(mockLogger, 4, 4, 0, 0);
+ await cheatRepairOfflineNode(mockLogger, 4, 4, 0, 0);
expect(mockLogger).toHaveBeenCalledWith("Cheat successful. The point 4,4 was repaired.");
- expect(result.success).toEqual(true);
expect(Go.currentGame.board[4]?.[4]?.color).toEqual(GoColor.empty);
});
});