[IPvGO] Docs improvements and other feedback (#1011)

This commit is contained in:
Michael Ficocelli 2024-01-05 20:50:28 -05:00 committed by GitHub
parent 0da9d9d3c0
commit 7e721c144e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 33 additions and 9 deletions

@ -169,7 +169,7 @@ That info can be used to make decisions about where to place routers.
In order to expand the area that is controlled by the player's networks, connecting to friendly routers (when possible) is a strong move. This can be done with a very similar implementation to `getRandomMove()`, with the additional check of looking for a neighboring friendly router. For each point on the board: In order to expand the area that is controlled by the player's networks, connecting to friendly routers (when possible) is a strong move. This can be done with a very similar implementation to `getRandomMove()`, with the additional check of looking for a neighboring friendly router. For each point on the board:
``` ```text
Detect expansion moves: Detect expansion moves:
For each point on the board: For each point on the board:
* If the empty point is a valid move, and * If the empty point is a valid move, and
@ -207,7 +207,7 @@ If the opposing faction's network is down to its last open port, placing a route
To find out what networks are in danger of capture, `ns.go.analysis.getLiberties()` shows how many empty nodes / open ports each network has. As with `getBoardState()` and `getValidMoves()` , the number of liberties (open ports) for a given point's network can be retrieved via its coordinates `[x][y]` on the grid returned by `getLiberties()` To find out what networks are in danger of capture, `ns.go.analysis.getLiberties()` shows how many empty nodes / open ports each network has. As with `getBoardState()` and `getValidMoves()` , the number of liberties (open ports) for a given point's network can be retrieved via its coordinates `[x][y]` on the grid returned by `getLiberties()`
``` ```text
Detect moves to capture the opponent's routers: Detect moves to capture the opponent's routers:
For each point on the board: For each point on the board:
* If the empty point is a valid move, and * If the empty point is a valid move, and
@ -223,7 +223,7 @@ Detect moves to capture the opponent's routers:
`getLiberties()` can also be used to detect your own networks that are in danger of being captured, and look for moves to try and save it. `getLiberties()` can also be used to detect your own networks that are in danger of being captured, and look for moves to try and save it.
``` ```text
Detect moves to defend a threatened network: Detect moves to defend a threatened network:
For each point on the board: For each point on the board:
* If the empty point is a valid move, and * If the empty point is a valid move, and
@ -264,6 +264,15 @@ This is similar to the logic for defending your networks from immediate capture.
### Move option: Encircling space to control empty nodes ### Move option: Encircling space to control empty nodes
A key part of the strategy of Go is fully encircling groups of empty nodes. The examples at the start of this doc simply leave out specific nodes and hope they stay empty, but this can be done in much better ways.
As a simple approach, look for possible moves that are:
- adjacent to two separate empty nodes (open areas it will divide up)
- adjacent a friendly piece and the edge of a board (or a second friendly piece from a different chain than the first)
This will find moves which are connecting your chains together, or connecting to the edge of the board, and dividing up empty space in the process. This allows you to control space, making it harder to capture your chains in the process.
   
### Choosing a good move option ### Choosing a good move option
@ -301,3 +310,13 @@ There are a lot of strong shapes in Go, that are worth attempting to re-create.
If a single network fully encloses two different disconnected empty nodes, it can never be taken. (If it only had one inner airspace, the opponent could eventually surround and then fill it to capture the network. If there is two, however, the suicide rule prevents them from filling either inner empty space.) Detecting moves that make figure-8 type shapes, or split an encircled empty node chain into two smaller ones, are very strong. If a single network fully encloses two different disconnected empty nodes, it can never be taken. (If it only had one inner airspace, the opponent could eventually surround and then fill it to capture the network. If there is two, however, the suicide rule prevents them from filling either inner empty space.) Detecting moves that make figure-8 type shapes, or split an encircled empty node chain into two smaller ones, are very strong.
In addition, if the opponent has only a single such move, playing there first to block it is often extremely disruptive, and can even lead to their network being captured. In addition, if the opponent has only a single such move, playing there first to block it is often extremely disruptive, and can even lead to their network being captured.
 
A deeper dive into this idea will involve making your own code to identify chains of pieces (and continuous empty nodes).
- Find all moves that divide up empty space and connect two chains or a chain and the edge as in the 'encircling empty space' idea above
- Apply the move on a sample board in memory, one at a time
- Identify all chains and continuous groups of empty nodes in the resulting board, and which color pieces surround the new empty node groups
- Prioritize the move that makes the most empty node groups fully surrounded by your player color.
- Alternatively, count how many empty node groups each friendly chain is touching, and prioritize moves that create a second of these "eyes" for friendly chains

@ -576,8 +576,8 @@ export const boardStyles = makeStyles((theme: Theme) =>
}, },
instructionsBlurb: { instructionsBlurb: {
width: "60%", width: "60%",
minWidth: "500px", minWidth: "300px",
marginRight: "20px", marginRight: "15px",
}, },
translucent: { translucent: {
opacity: 0.6, opacity: 0.6,

@ -14,7 +14,7 @@ export function CalculateEffect(nodes: number, faction: opponents): number {
const power = getEffectPowerForFaction(faction); const power = getEffectPowerForFaction(faction);
const sourceFileBonus = Player.sourceFileLvl(14) ? 1.25 : 1; const sourceFileBonus = Player.sourceFileLvl(14) ? 1.25 : 1;
return ( return (
1 + Math.log(nodes + 1) * Math.pow(nodes + 1, 0.33) * 0.005 * power * currentNodeMults.GoPower * sourceFileBonus 1 + Math.log(nodes + 1) * Math.pow(nodes + 1, 0.3) * 0.004 * power * currentNodeMults.GoPower * sourceFileBonus
); );
} }

@ -41,6 +41,11 @@ export async function makePlayerMove(logger: (s: string) => void, x: number, y:
if (validity !== validityReason.valid || !result) { if (validity !== validityReason.valid || !result) {
await sleep(500); await sleep(500);
logger(`ERROR: Invalid move: ${validity}`); logger(`ERROR: Invalid move: ${validity}`);
if (validity === validityReason.notYourTurn) {
logger("Do you have multiple scripts running, or did you forget to await makeMove() ?");
}
return Promise.resolve(invalidMoveResponse); return Promise.resolve(invalidMoveResponse);
} }

@ -212,8 +212,8 @@ export const GoInstructionsPage = (): React.ReactElement => {
<br /> <br />
* If a network surrounds a single empty node, the opponent can eventually capture it by filling in that * If a network surrounds a single empty node, the opponent can eventually capture it by filling in that
node. However, if your network has two separate empty nodes inside of it, the suicide rule prevents the node. However, if your network has two separate empty nodes inside of it, the suicide rule prevents the
opponent from filling up either of them. This means your network cannot be captured! Try to place your opponent from filling up either of them. This means your network cannot be captured! Try to build your
networks surround several different empty nodes, and avoid filling in your network's empty nodes when networks to surround several different empty nodes, and avoid filling in your network's empty nodes when
possible. possible.
<br /> <br />
<br /> <br />

@ -4138,7 +4138,7 @@ export interface Go {
x1: number, x1: number,
y1: number, y1: number,
x2: number, x2: number,
x2: number, y2: number,
): Promise<{ ): Promise<{
type: "invalid" | "move" | "pass" | "gameOver"; type: "invalid" | "move" | "pass" | "gameOver";
x: number; x: number;