diff --git a/src/Go/boardState/goStyles.ts b/src/Go/boardState/goStyles.ts index ad29e2808..b2385b2e0 100644 --- a/src/Go/boardState/goStyles.ts +++ b/src/Go/boardState/goStyles.ts @@ -585,6 +585,9 @@ export const boardStyles = makeStyles({ uniqId: "boar scoreModal: { width: "400px", }, + scoreExplanationModal: { + width: "80vw", + }, centeredText: { textAlign: "center", }, diff --git a/src/Go/ui/GoGameboardWrapper.tsx b/src/Go/ui/GoGameboardWrapper.tsx index 92c7edc1a..ddfb83782 100644 --- a/src/Go/ui/GoGameboardWrapper.tsx +++ b/src/Go/ui/GoGameboardWrapper.tsx @@ -19,6 +19,7 @@ import { GoGameboard } from "./GoGameboard"; import { GoSubnetSearch } from "./GoSubnetSearch"; import { CorruptableText } from "../../ui/React/CorruptableText"; import { makeAIMove, resolveCurrentTurn } from "../boardAnalysis/goAI"; +import { GoScoreExplanation } from "./GoScoreExplanation"; interface GoGameboardWrapperProps { showInstructions: () => void; @@ -44,6 +45,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps const traditional = Settings.GoTraditionalStyle; const [showPriorMove, setShowPriorMove] = useState(false); const [scoreOpen, setScoreOpen] = useState(false); + const [scoreExplanationOpen, setScoreExplanationOpen] = useState(false); const [searchOpen, setSearchOpen] = useState(false); const { classes } = boardStyles(); @@ -203,7 +205,9 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps newSubnet={() => newSubnet()} finalScore={score} opponent={Go.currentGame.ai} - > + showScoreExplanation={() => setScoreExplanationOpen(true)} + /> + setScoreExplanationOpen(false)} open={scoreExplanationOpen} />
{traditional ? ( "" diff --git a/src/Go/ui/GoInstructionsPage.tsx b/src/Go/ui/GoInstructionsPage.tsx index 7ea4ed27f..2a20f7acc 100644 --- a/src/Go/ui/GoInstructionsPage.tsx +++ b/src/Go/ui/GoInstructionsPage.tsx @@ -151,6 +151,13 @@ export const GoInstructionsPage = (): React.ReactElement => {
Win streaks against a faction will give you +1 favor to that faction at certain numbers of wins (up to a max of {getMaxFavor()} favor), if you are currently a member of that faction. +
+
+ For experienced Go players: IPvGO uses the old traditional Go score rules, area scoring, rather than the + Japanese territory scoring that was popular in the mid-21st century. All stones are alive and count + towards score unless captured during the game. Chains that could be dead are not automatically captured + after the game, and prisoners are not calculated. This was chosen for its simplicity to teach and to + calculate, rather than using the territory scoring shortcuts designed to make physical games quicker. diff --git a/src/Go/ui/GoScoreExplanation.tsx b/src/Go/ui/GoScoreExplanation.tsx new file mode 100644 index 000000000..107a5e3d4 --- /dev/null +++ b/src/Go/ui/GoScoreExplanation.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import { Typography } from "@mui/material"; + +import { Modal } from "../../ui/React/Modal"; +import { boardStyles } from "../boardState/goStyles"; + +interface Props { + open: boolean; + onClose: () => void; +} + +export const GoScoreExplanation = ({ open, onClose }: Props): React.ReactElement => { + const { classes } = boardStyles(); + + return ( + + <> +
+ + IPvGO uses one of the oldest scoring systems in Go, "area scoring", rather than "territory scoring" later + popularized by Japan. All stones are alive unless captured, chains that could be dead are not automatically + captured after the game, and prisoners are not calculated. The displayed score is always the ending score if + both players pass.

+ This scoring ruleset was chosen for its simplicity to teach and to calculate, rather than using territory + scoring shortcuts designed to make physical games quicker. +

+ Territory scoring relies heavily on all players having a clear understanding of which chains on the board + will be "alive" or "dead" given future perfect play. It is much more complicated to implement, and requires + a much deeper knowledge of Go for new players, and for their IPvGO automation scripts. +

+ In most cases the winner, and the difference in score between players, comes out to be the same in both + scoring systems, but in area scoring you "show your work" and prove that something is alive or dead, and + gives opportunities for the player to capitalize on the computer's mistakes (or vice versa). +
+
+ +
+ ); +}; diff --git a/src/Go/ui/GoScoreModal.tsx b/src/Go/ui/GoScoreModal.tsx index 94bc2ba49..7d25f8467 100644 --- a/src/Go/ui/GoScoreModal.tsx +++ b/src/Go/ui/GoScoreModal.tsx @@ -1,6 +1,6 @@ import type { GoScore } from "../Types"; import React from "react"; -import { Button, Typography } from "@mui/material"; +import { Button, Typography, Box } from "@mui/material"; import { GoOpponent, GoColor } from "@enums"; import { Modal } from "../../ui/React/Modal"; @@ -13,10 +13,18 @@ interface Props { onClose: () => void; finalScore: GoScore; newSubnet: () => void; + showScoreExplanation: () => void; opponent: GoOpponent; } -export const GoScoreModal = ({ open, onClose, finalScore, newSubnet, opponent }: Props): React.ReactElement => { +export const GoScoreModal = ({ + open, + onClose, + finalScore, + newSubnet, + showScoreExplanation, + opponent, +}: Props): React.ReactElement => { const { classes } = boardStyles(); const blackScore = finalScore[GoColor.black]; @@ -47,7 +55,10 @@ export const GoScoreModal = ({ open, onClose, finalScore, newSubnet, opponent }: ) : ( "" )} - + + + +