IPVGO: add scoring rules explanations to how to play page and score modal (#1558)

This commit is contained in:
Michael Ficocelli 2024-08-08 20:44:19 -04:00 committed by GitHub
parent 59bb58535e
commit e16ac34c15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 68 additions and 4 deletions

@ -585,6 +585,9 @@ export const boardStyles = makeStyles<void, Size | "background">({ uniqId: "boar
scoreModal: { scoreModal: {
width: "400px", width: "400px",
}, },
scoreExplanationModal: {
width: "80vw",
},
centeredText: { centeredText: {
textAlign: "center", textAlign: "center",
}, },

@ -19,6 +19,7 @@ import { GoGameboard } from "./GoGameboard";
import { GoSubnetSearch } from "./GoSubnetSearch"; import { GoSubnetSearch } from "./GoSubnetSearch";
import { CorruptableText } from "../../ui/React/CorruptableText"; import { CorruptableText } from "../../ui/React/CorruptableText";
import { makeAIMove, resolveCurrentTurn } from "../boardAnalysis/goAI"; import { makeAIMove, resolveCurrentTurn } from "../boardAnalysis/goAI";
import { GoScoreExplanation } from "./GoScoreExplanation";
interface GoGameboardWrapperProps { interface GoGameboardWrapperProps {
showInstructions: () => void; showInstructions: () => void;
@ -44,6 +45,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps
const traditional = Settings.GoTraditionalStyle; const traditional = Settings.GoTraditionalStyle;
const [showPriorMove, setShowPriorMove] = useState(false); const [showPriorMove, setShowPriorMove] = useState(false);
const [scoreOpen, setScoreOpen] = useState(false); const [scoreOpen, setScoreOpen] = useState(false);
const [scoreExplanationOpen, setScoreExplanationOpen] = useState(false);
const [searchOpen, setSearchOpen] = useState(false); const [searchOpen, setSearchOpen] = useState(false);
const { classes } = boardStyles(); const { classes } = boardStyles();
@ -203,7 +205,9 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps
newSubnet={() => newSubnet()} newSubnet={() => newSubnet()}
finalScore={score} finalScore={score}
opponent={Go.currentGame.ai} opponent={Go.currentGame.ai}
></GoScoreModal> showScoreExplanation={() => setScoreExplanationOpen(true)}
/>
<GoScoreExplanation onClose={() => setScoreExplanationOpen(false)} open={scoreExplanationOpen} />
<div className={classes.boardFrame}> <div className={classes.boardFrame}>
{traditional ? ( {traditional ? (
"" ""

@ -151,6 +151,13 @@ export const GoInstructionsPage = (): React.ReactElement => {
<br /> <br />
Win streaks against a faction will give you +1 favor to that faction at certain numbers of wins (up to a 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. max of {getMaxFavor()} favor), if you are currently a member of that faction.
<br />
<br />
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.
</Typography> </Typography>
</Grid> </Grid>
</Grid> </Grid>

@ -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 (
<Modal open={open} onClose={onClose}>
<>
<div className={classes.scoreExplanationModal}>
<Typography>
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. <br /> <br />
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.
<br /> <br />
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.
<br /> <br />
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).
</Typography>
</div>
</>
</Modal>
);
};

@ -1,6 +1,6 @@
import type { GoScore } from "../Types"; import type { GoScore } from "../Types";
import React from "react"; import React from "react";
import { Button, Typography } from "@mui/material"; import { Button, Typography, Box } from "@mui/material";
import { GoOpponent, GoColor } from "@enums"; import { GoOpponent, GoColor } from "@enums";
import { Modal } from "../../ui/React/Modal"; import { Modal } from "../../ui/React/Modal";
@ -13,10 +13,18 @@ interface Props {
onClose: () => void; onClose: () => void;
finalScore: GoScore; finalScore: GoScore;
newSubnet: () => void; newSubnet: () => void;
showScoreExplanation: () => void;
opponent: GoOpponent; 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 { classes } = boardStyles();
const blackScore = finalScore[GoColor.black]; const blackScore = finalScore[GoColor.black];
@ -47,7 +55,10 @@ export const GoScoreModal = ({ open, onClose, finalScore, newSubnet, opponent }:
) : ( ) : (
"" ""
)} )}
<Button onClick={newSubnet}>New Subnet</Button> <Box className={classes.inlineFlexBox}>
<Button onClick={showScoreExplanation}>Score Explanation</Button>
<Button onClick={newSubnet}>New Subnet</Button>
</Box>
</div> </div>
</> </>
</Modal> </Modal>