1
0

House Rules almost done

This commit is contained in:
James Ketr 2025-09-25 13:22:46 -07:00
parent 279fc68718
commit 613e81dbd0
16 changed files with 129 additions and 60 deletions

View File

@ -10,8 +10,11 @@ Guidelines for contributors and automated assistants
- Use the provided Docker and docker-compose workflows for development and
building. The repository's `Dockerfile` and `docker-compose.yml` are the
canonical way to install dependencies and run the app.
- If you need to run a command locally for quick checks, prefer run commands in
the project's container environment. Example (copy-paste):
- For development mode (hot-reload), set `PRODUCTION=0` and run `./launch.sh`.
- For production mode (static build), set `PRODUCTION=1` and run `./launch.sh`.
- For manual building of the production image, run `docker-compose build`.
- If you need to run a command for quick checks, use the project's container
environment. Example (copy-paste):
```bash
docker compose run --rm peddlers-of-ketran bash
@ -20,12 +23,6 @@ Guidelines for contributors and automated assistants
npm run build
```
- For lightweight commands, you can run one-off containers:
```bash
docker run --rm -v "$PWD":/app -w /app node:20 bash -lc 'cd client && npm ci && npm run type-check'
```
- Do not suggest or perform `npm install` or `npm ci` on the host machine in
repository files, PRs, or automated edits. If a change requires dependency
updates, update package.json and lockfiles via a CI job or in-container run,

View File

@ -23,8 +23,22 @@ import TableRow from "@mui/material/TableRow";
// import "./HouseRules.css";
import boardImg from "./assets/category-board.png";
import expansionImg from "./assets/category-expansion.png";
import rollingImg from "./assets/category-rolling.png";
import rulesImg from "./assets/category-rules.png";
import volcanoTile from "./assets/single-volcano.png";
import { GlobalContext } from "./GlobalContext";
import { Placard } from "./Placard";
import Box from "@mui/material/Box/Box";
const categoryImages: { [key: string]: string } = {
board: boardImg,
expansion: expansionImg,
rolling: rollingImg,
rules: rulesImg,
};
/* eslint-disable @typescript-eslint/no-explicit-any */
@ -111,13 +125,36 @@ const Volcano: React.FC<VolcanoProps> = ({ ws, rules, field, disabled }) => {
};
return (
<div className="Volcano">
<Box
className="Volcano"
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: 2,
marginTop: 2,
}}
>
<Box
sx={{
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: 2,
}}
>
<img
src={volcanoTile}
alt={"Volcano"}
style={{ width: "100px", height: "100px" }}
/>
<div>
The Volcano replaces the Desert. When the Volcano erupts, roll a die to
determine the direction the lava will flow. One of the six intersections
on the Volcano tile will be affected. If there is a settlement on the
selected intersection, it is destroyed!
The Volcano replaces the Desert. When the Volcano erupts, roll a die
to determine the direction the lava will flow. One of the six
intersections on the Volcano tile will be affected. If there is a
settlement on the selected intersection, it is destroyed!
</div>
</Box>
<div>
Remove it from the board (its owner may rebuild it later). If a city is
located there, it is reduced to a settlement! Replace the city with a
@ -129,16 +166,19 @@ const Volcano: React.FC<VolcanoProps> = ({ ws, rules, field, disabled }) => {
from erupting.
</div>
<div>
Roll {number} and the Volcano erupts!
<button onClick={() => update(+1)}>up</button>&nbsp;/&nbsp;
<button onClick={() => update(-1)}> down</button>
Roll <b>{number}</b> and the Volcano erupts!
<Button onClick={() => update(+1)}>up</Button>&nbsp;/&nbsp;
<Button onClick={() => update(-1)}> down</Button>
</div>
<div className="HouseSelector">
<div>
<b>Volcanoes have gold!</b>: Volcano can produce resources when its
number is rolled.
</div>
<div>
<Paper sx={{ flexGrow: 1, width: "100%" }}>
<Table>
<TableRow>
<TableCell>
<b>Volcanoes have gold!</b>
<br />
Volcano can produce resources when its number is rolled.
</TableCell>
<TableCell>
<Switch
size={"small"}
className="RuleSwitch"
@ -146,21 +186,33 @@ const Volcano: React.FC<VolcanoProps> = ({ ws, rules, field, disabled }) => {
onChange={() => toggleGold()}
{...{ disabled }}
/>
</div>
</TableCell>
</TableRow>
{gold && (
<TableRow>
<TableCell colSpan={3}>
<Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
<div>
Volcanoes tend to be rich in valuable minerals such as gold
or gems. Each settlement that is adjacent to the Volcano
when it erupts may produce any one of the five resources
it&apos;s owner desires.
</div>
<div>
Volcanoes tend to be rich in valuable minerals such as gold or gems.
Each settlement that is adjacent to the Volcano when it erupts may
produce any one of the five resources it&apos;s owner desires.
</div>
<div>
Each city adjacent to the Volcano may produce any two resources. This
resource production is taken before the results of the volcano eruption
are resolved. Note that while the Robber can not prevent the Volcano
from erupting, he does prevent any player from producing resources from
the Volcano hex if he has been placed there.
</div>
Each city adjacent to the Volcano may produce any two
resources. This resource production is taken before the
results of the volcano eruption are resolved. Note that
while the Robber can not prevent the Volcano from erupting,
he does prevent any player from producing resources from the
Volcano hex if he has been placed there.
</div>
</Box>
</TableCell>
</TableRow>
)}
</Table>
</Paper>
</Box>
);
};
@ -205,9 +257,9 @@ const VictoryPoints: React.FC<VictoryPointsProps> = ({ ws, rules, field }) => {
return (
<div className="VictoryPoints">
{points} points.
<button onClick={() => update(+1)}>up</button>&nbsp;/&nbsp;
<button onClick={() => update(-1)}> down</button>
<b>{points}</b> points.
<Button onClick={() => update(+1)}>up</Button>&nbsp;/&nbsp;
<Button onClick={() => update(-1)}> down</Button>
</div>
);
};
@ -336,7 +388,7 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive }) => {
},
{
key: "most-developed",
label: "You are so developed",
label: "You are so developed!",
description:
"The player with the most development cards (more than 4) receives 2VP.",
category: "expansion",
@ -345,7 +397,7 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive }) => {
},
{
key: "port-of-call",
label: "Another round of port",
label: "Another round of port?",
description:
"The player with the most harbor ports (more than 2) receives 2VP.",
category: "expansion",
@ -354,7 +406,7 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive }) => {
},
{
key: "slowest-turn",
label: "Why you play so slowf",
label: "Why you play so slow?",
description:
"The player with the longest turn idle time (longer than 2 minutes) so far loses 2VP.",
category: "expansion",
@ -395,7 +447,7 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive }) => {
defaultChecked: false,
element: <></>,
},
],
].sort((a, b) => a.category.localeCompare(b.category)),
[rules, setRules, state, ws, setRule, name, gameState]
);
@ -404,12 +456,21 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive }) => {
}
return (
<Paper sx={{ p: 1, maxWidth: 600, margin: "1rem auto", flexDirection: "column", display: "flex" }} className="HouseRules" elevation={3}>
<Paper
sx={{
p: 1,
maxWidth: 600,
margin: "1rem auto",
flexDirection: "column",
display: "flex",
}}
className="HouseRules"
elevation={3}
>
<DialogTitle>House Rules</DialogTitle>
<DialogContent>
<TableContainer>
<Table>
<Table sx={{ tableLayout: "fixed" }}>
<TableBody>
{ruleList.map((item) => {
const defaultChecked = item.defaultChecked;
@ -426,11 +487,20 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive }) => {
return (
<React.Fragment key={item.key}>
<TableRow>
<TableCell>
<b>{item.label}</b>
<TableCell sx={{ width: "50px" }}>
{/* Fixed width for image */}
<img
src={categoryImages[item.category]}
alt={item.category}
style={{ width: "50px", height: "68px" }}
/>
</TableCell>
<TableCell>{item.description}</TableCell>
<TableCell>
<TableCell sx={{ width: "auto" }}>
<b>{item.label}</b>
<br />
{item.description}
</TableCell>
<TableCell sx={{ width: "100px" }}>
<Switch
size={"small"}
className="RuleSwitch"

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

View File

@ -7,6 +7,8 @@ declare module 'Trade' {
declare module '*.svg';
declare module '*.png';
declare module "./Trade" {
const Trade: unknown;
export default Trade;