From 36beef59daed4bfe87f449784944c7fa46c72e25 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Wed, 16 Sep 2026 21:56:41 -0400 Subject: [PATCH 1/6] Use American spelling in Honour/initialise test names. Co-authored-by: Cursor --- library/tests/system/configure_tt_api_test.cpp | 4 ++-- library/tests/system/worker_count_test.cpp | 2 +- library/tests/trans_table/trans_table_p_test.cpp | 2 +- specs/solver-context.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/tests/system/configure_tt_api_test.cpp b/library/tests/system/configure_tt_api_test.cpp index 4a36751ef..57683994e 100644 --- a/library/tests/system/configure_tt_api_test.cpp +++ b/library/tests/system/configure_tt_api_test.cpp @@ -142,7 +142,7 @@ auto stays_under(TransTable& tt, const double cap_kb) -> bool /// A configuration that sets only the maximum must yield a table capped at /// that maximum when it is created lazily; the built-in default used for the /// unset value may not lift the cap. -TEST(ConfigureTtApiTest, AMaximumOnlyConfigurationIsHonouredOnLazyCreation) +TEST(ConfigureTtApiTest, AMaximumOnlyConfigurationIsHonoredOnLazyCreation) { // Arrange ScopedEnv no_kind("DDS_TT_KIND", nullptr); @@ -177,7 +177,7 @@ auto solve_known_deal(SolverContext& ctx, FutureTricks& fut) -> int /// A table recreated between two solves of the same deal has not seen that /// deal; the next solve must initialize it again rather than run against an /// inert (never init()-ed) cache. -TEST(ConfigureTtApiTest, ATableRecreatedBetweenSolvesOfTheSameDealIsInitialisedAgain) +TEST(ConfigureTtApiTest, ATableRecreatedBetweenSolvesOfTheSameDealIsInitializedAgain) { // Arrange: one solve, then a kind change and back, which recreates the table. ScopedEnv no_kind("DDS_TT_KIND", nullptr); diff --git a/library/tests/system/worker_count_test.cpp b/library/tests/system/worker_count_test.cpp index 7b799225f..de751e51c 100644 --- a/library/tests/system/worker_count_test.cpp +++ b/library/tests/system/worker_count_test.cpp @@ -37,7 +37,7 @@ TEST(ResolveWorkerCount, CapLargerThanCountClampsToCount) EXPECT_EQ(resolve_worker_count(1000, 5), 5); } -TEST(ResolveWorkerCount, CapSmallerThanCountAndHardwareIsHonoured) +TEST(ResolveWorkerCount, CapSmallerThanCountAndHardwareIsHonored) { // A cap of 1 is always <= count and <= hardware_concurrency. EXPECT_EQ(resolve_worker_count(1, 8), 1); diff --git a/library/tests/trans_table/trans_table_p_test.cpp b/library/tests/trans_table/trans_table_p_test.cpp index ed978d782..5480160b3 100644 --- a/library/tests/trans_table/trans_table_p_test.cpp +++ b/library/tests/trans_table/trans_table_p_test.cpp @@ -1122,7 +1122,7 @@ TEST(TransTablePMemoryTest, PoolingOutgrownBlocksNeverExceedsTheMaximum) /// A caller that configures only the hard maximum gets exactly that maximum; /// the unset default limit must not be replaced by a built-in value that then /// floors the cap far above what was asked for. -TEST(TransTablePMemoryTest, AMaximumSetWithoutADefaultIsHonouredAsTheCap) +TEST(TransTablePMemoryTest, AMaximumSetWithoutADefaultIsHonoredAsTheCap) { // Arrange TransTableP tt; diff --git a/specs/solver-context.md b/specs/solver-context.md index 05dc9e2c7..d3765b8a7 100644 --- a/specs/solver-context.md +++ b/specs/solver-context.md @@ -78,7 +78,7 @@ the opaque handle. See [dds-public-api](dds-public-api.md). — even of the same cards — is treated as a new deal and runs `SetDealTables()`, which `init()`s the replacement table; otherwise a table recreated between two solves of one deal would never see the deal (inert on - `TransTableP`). Guarded by `ConfigureTtApiTest.ATableRecreatedBetweenSolvesOfTheSameDealIsInitialisedAgain`. + `TransTableP`). Guarded by `ConfigureTtApiTest.ATableRecreatedBetweenSolvesOfTheSameDealIsInitializedAgain`. - **Hot-path facades are value-typed and inline-friendly, with different holds.** `MoveGenContext` holds a raw `ThreadData*` so `move_gen()` can return a value-typed facade without an atomic `shared_ptr` bump on every call. From a79535a8babafb3569f76eae5696bb263f731c7e Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Thu, 17 Sep 2026 06:53:26 -0400 Subject: [PATCH 2/6] Prefer American -ization/-ized spelling in remaining docs and comments. Co-authored-by: Cursor --- README.md | 8 ++++---- benchmarks/BUILD.bazel | 4 ++-- benchmarks/README.md | 2 +- benchmarks/recording.cpp | 2 +- docs/coding_standards_and_ai_advice.md | 2 +- specs/build-system.md | 2 +- specs/python-binding.md | 2 +- specs/web.md | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index afc394932..81b9416fc 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ ## Introduction to DDS3 -DDS3 is a double dummy solver for bridge hands. It is a drop-in replacement for DDS 2.9.0 which has been the leading solver for many years, based on the initial work of Bo Haglund in 2006 and the previous modernisation by Søren Hein in 2014. With Søren's encouragement, I have updated the official release in order to retain continuity for the user base, and I have been added as an administrator. +DDS3 is a double dummy solver for bridge hands. It is a drop-in replacement for DDS 2.9.0 which has been the leading solver for many years, based on the initial work of Bo Haglund in 2006 and the previous modernization by Søren Hein in 2014. With Søren's encouragement, I have updated the official release in order to retain continuity for the user base, and I have been added as an administrator. DDS3 is a double dummy solver for bridge hands. Version 3.0 uses the same -search algorithm as version 2.x, but the source code has been modernised. The +search algorithm as version 2.x, but the source code has been modernized. The project has been split into several subcomponents, each responsible for a -specific part of the search algorithm. This modularisation makes the codebase +specific part of the search algorithm. This modularization makes the codebase easier to read and reason about, which helps not only humans but also modern coding agents. Throughout the codebase, you will find evidence that Claude Code and GitHub Copilot have made significant contributions to the -modernisation. +modernization. There are build scripts for macOS, Linux, and Windows but I have myself only used the library on macOS. diff --git a/benchmarks/BUILD.bazel b/benchmarks/BUILD.bazel index 47c337491..1543f676a 100644 --- a/benchmarks/BUILD.bazel +++ b/benchmarks/BUILD.bazel @@ -2,7 +2,7 @@ load("//:CPPVARIABLES.bzl", "DDS_CPPOPTS", "DDS_LINKOPTS", "DDS_LOCAL_DEFINES") load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test") # Reader + replay engine for recorded DDS workloads. Split from the CLI so the -# parsing and result-canonicalisation logic can be unit tested. +# parsing and result-canonicalization logic can be unit tested. cc_library( name = "replay_lib", srcs = [ @@ -75,7 +75,7 @@ cc_test( ) # Smoke test over a small committed recording, so the replay path (JSON parsing, -# PBN decoding, batching, result canonicalisation, verification) stays correct +# PBN decoding, batching, result canonicalization, verification) stays correct # without needing a large recording. The sample was cut from a real session. cc_test( name = "replay_test", diff --git a/benchmarks/README.md b/benchmarks/README.md index c53f3e970..ba4979c52 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -115,7 +115,7 @@ python game.py --boards "Camrose 1-32.pbn" --auto True \ `testdata/sample-recording.jsonl` is a 6-call excerpt of the same file. It backs the fast `//benchmarks:replay_test` smoke test, so CI exercises the replay path -(JSON parsing, PBN decoding, batching, result canonicalisation, verification) +(JSON parsing, PBN decoding, batching, result canonicalization, verification) without spending two minutes on the full workload. Run it on its own with: ```sh diff --git a/benchmarks/recording.cpp b/benchmarks/recording.cpp index 74c2504b2..65c210aa6 100644 --- a/benchmarks/recording.cpp +++ b/benchmarks/recording.cpp @@ -247,7 +247,7 @@ auto find_runfile(const std::string& logical, const std::string& argv0) } } - // Materialised runfiles tree (Linux/macOS), or a run from the workspace root. + // Materialized runfiles tree (Linux/macOS), or a run from the workspace root. std::vector candidates; for (const char* var : {"TEST_SRCDIR", "RUNFILES_DIR"}) if (const char* root = std::getenv(var)) diff --git a/docs/coding_standards_and_ai_advice.md b/docs/coding_standards_and_ai_advice.md index 6fc3952ad..bf58b6286 100644 --- a/docs/coding_standards_and_ai_advice.md +++ b/docs/coding_standards_and_ai_advice.md @@ -1,6 +1,6 @@ # Coding Agents and Coding Standards -Coding agents are improving quickly, and the best tool or model for a task can change from one month to the next. This note collects coding guidance and tooling recommendations assembled during the first quarter of 2026, when most of the modernisation work for release 3.0.0 was completed. +Coding agents are improving quickly, and the best tool or model for a task can change from one month to the next. This note collects coding guidance and tooling recommendations assembled during the first quarter of 2026, when most of the modernization work for release 3.0.0 was completed. This document does not prescribe a specific MCP server setup. MCP servers can be powerful, but they also introduce security risks, so the right deployment strategy depends on the environment. diff --git a/specs/build-system.md b/specs/build-system.md index 8a5c7111d..8903a5206 100644 --- a/specs/build-system.md +++ b/specs/build-system.md @@ -60,7 +60,7 @@ than re-encoding toolchain knowledge. `cc_library`; `DDS_SCHEDULER_DEFINE` is appended only where scheduler timing is wanted** (`local_defines = DDS_LOCAL_DEFINES + DDS_SCHEDULER_DEFINE`). Off by default, these add zero cost. -- **WASM link flags are centralised** in `wasm_compat.bzl` (`WASM_LINKOPTS`): +- **WASM link flags are centralized** in `wasm_compat.bzl` (`WASM_LINKOPTS`): memory growth, 256 MB initial memory, an 8 MB stack (DDS search recursion overflows Emscripten's 64 KB default), and `PTHREAD_POOL_SIZE=8`. WASM `wasm_cc_binary` targets also set `threads = "emscripten"` — see diff --git a/specs/python-binding.md b/specs/python-binding.md index 735e7a2c3..bfe7fc486 100644 --- a/specs/python-binding.md +++ b/specs/python-binding.md @@ -45,7 +45,7 @@ context API and the flat API from [dds-public-api](dds-public-api.md). C++ [solver-context](solver-context.md); holding one across multiple solves reuses its transposition table, mirroring the C++ reuse model. Guarded by `context_reuse_test`. -- **Type conversions are centralised.** `converters.{cpp,hpp}` marshal Python +- **Type conversions are centralized.** `converters.{cpp,hpp}` marshal Python values ↔ the C++ deal/table/par structs; the conversion contract (PBN strings, binary deals, table/par result shapes) is guarded by `type_conversions_test`. - **Wheels are built from the same package.** `dds3_wheel` (`py_wheel`, diff --git a/specs/web.md b/specs/web.md index 2e466b05a..f7832ca0f 100644 --- a/specs/web.md +++ b/specs/web.md @@ -22,7 +22,7 @@ DOM wiring) with an automated test pyramid. > Per-file detail is in the BUILD file and the site sources; these are the > capability-wide facts. -- **A dedicated, modularised WASM module — not the example CLIs.** `dds_web_wasm` +- **A dedicated, modularized WASM module — not the example CLIs.** `dds_web_wasm` (`wasm_cc_binary` over `dds_web_wasm_cc`, source `dds_web_wasm.cpp`, `threads = "emscripten"`) is built with `WASM_WEB_LINKOPTS`: `MODULARIZE=1`, `EXPORT_NAME=createDdsModule`, exported entries `_dds_web_calc_table` and From f8759b2bc346d2d542f9d9ed762c142a0b53bc06 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Thu, 17 Sep 2026 06:54:44 -0400 Subject: [PATCH 3/6] Prefer American honoured/analogue/amongst spellings in tests and comments. Co-authored-by: Cursor --- dotnet/DDS_Core.Tests/SmokeTests.cs | 2 +- library/src/trans_table/trans_table_s.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/DDS_Core.Tests/SmokeTests.cs b/dotnet/DDS_Core.Tests/SmokeTests.cs index 42862189a..d18e8d59d 100644 --- a/dotnet/DDS_Core.Tests/SmokeTests.cs +++ b/dotnet/DDS_Core.Tests/SmokeTests.cs @@ -3,7 +3,7 @@ namespace DDS_Core.Tests; /// -/// End-to-end solving through the retargeted binding — the .NET analogue of +/// End-to-end solving through the retargeted binding — the .NET analog of /// DdsSmokeTest.java. These are what prove the dds_c_* entry /// points actually resolve and marshal correctly on a non-Windows platform. /// diff --git a/library/src/trans_table/trans_table_s.cpp b/library/src/trans_table/trans_table_s.cpp index f51980b83..28c604f2a 100644 --- a/library/src/trans_table/trans_table_s.cpp +++ b/library/src/trans_table/trans_table_s.cpp @@ -778,7 +778,7 @@ auto TransTableS::build_path( { /* Find all winning nodes that correspond to current position */ found = false; - while (1) /* Find node amongst alternatives */ + while (1) /* Find node among alternatives */ { if ((np->win_mask_ == win_mask_[suit]) && (np->order_set_ == win_order_set[suit])) From a34b5378706a9edd98f58da28e74d8f2beb1e553 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Thu, 17 Sep 2026 06:56:39 -0400 Subject: [PATCH 4/6] Prefer American analyzes in the .NET play-analysis docs. Co-authored-by: Cursor --- docs/dotnet_interface.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/dotnet_interface.md b/docs/dotnet_interface.md index 08f78614b..31e4163aa 100644 --- a/docs/dotnet_interface.md +++ b/docs/dotnet_interface.md @@ -349,13 +349,13 @@ and should be used with caution, as they may not manage resources as efficiently ### Play Analysis - **int AnalysePlay(Deal dl, PlayTraceBin play, ...)** - analyses a play sequence for a single deal. Deprecated, but not yet implemented in the modern api. + analyzes a play sequence for a single deal. Deprecated, but not yet implemented in the modern api. - **int AnalysePlay(DealPBN dl, PlayTracePBN play, ...)** PBN-version. Deprecated, but not yet implemented in the modern api. - **int AnalyseAllPlays(...)** - analyses multiple play sequences across multiple deals. Deprecated, but not yet implemented in the modern api. + analyzes multiple play sequences across multiple deals. Deprecated, but not yet implemented in the modern api. --- From 23edcca15931247c203ba6959b313d58d1e7db0e Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Thu, 17 Sep 2026 06:58:01 -0400 Subject: [PATCH 5/6] Prefer American artifacts in the gitignore comment. Co-authored-by: Cursor --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bcfbf7e8b..4af3931cc 100644 --- a/.gitignore +++ b/.gitignore @@ -82,7 +82,7 @@ dist/ build/ # -# Build artefacts are placed in these directories. +# Build artifacts are placed in these directories. # bin/ build/ From f80ff2cea98be411e2f2384705f92155658a2500 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Thu, 17 Sep 2026 07:15:03 -0400 Subject: [PATCH 6/6] Prefer American analyzing/materialize/parallelize in comments and docs. Co-authored-by: Cursor --- .bazelrc | 2 +- benchmarks/recording.hpp | 2 +- docs/python_interface.md | 2 +- python/src/bindings.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bazelrc b/.bazelrc index 7bf162412..329707297 100644 --- a/.bazelrc +++ b/.bazelrc @@ -15,7 +15,7 @@ common --lockfile_mode=error # We build nothing for Android, but rules_jvm_external (the //jni Maven jar) # depends on rules_android, whose android_sdk_repository extension probes -# $ANDROID_HOME while analysing *any* target. When ANDROID_HOME is exported but +# $ANDROID_HOME while analyzing *any* target. When ANDROID_HOME is exported but # the SDK has no platform APIs installed — as on GitHub's ubuntu runners after # the free-disk-space step removes the SDK — that extension hard-fails and takes # down unrelated builds (e.g. //wasm, //web). Pinning the var to empty makes the diff --git a/benchmarks/recording.hpp b/benchmarks/recording.hpp index f03cc7bd7..28a6c6157 100644 --- a/benchmarks/recording.hpp +++ b/benchmarks/recording.hpp @@ -125,7 +125,7 @@ auto load_recording(const std::string& path, Recording& out, std::string& error) -> bool; // Resolve a Bazel runfile (e.g. "_main/benchmarks/testdata/x.jsonl") to a real -// path, or "" if it cannot be found. Windows does not materialise the runfiles +// path, or "" if it cannot be found. Windows does not materialize the runfiles // tree -- that would need symlinks -- so the manifest has to be consulted there. // `bazel test` exports the manifest location in the environment; `bazel run` // does not, so pass argv[0] and the manifest beside the binary will be used. diff --git a/docs/python_interface.md b/docs/python_interface.md index f7041486f..6c8562910 100644 --- a/docs/python_interface.md +++ b/docs/python_interface.md @@ -277,7 +277,7 @@ Batched form of `analyse_play_pbn` (wraps `AnalyseAllPlaysPBN`). Legacy thread-resource hook (wraps the **deprecated** `SetMaxThreads` C API). This does **not** control DDS's batch parallelism and is kept only for backward -compatibility. `solve_all_boards_*` already parallelise across the machine's +compatibility. `solve_all_boards_*` already parallelize across the machine's hardware threads automatically (via `solve_boards_n`) — the value passed here does not size that pool. `analyse_all_plays_pbn` currently runs sequentially. `user_threads` must be `>= 0` (`0` = auto); raises `ValueError` for negative values. diff --git a/python/src/bindings.cpp b/python/src/bindings.cpp index 096016433..d231365c9 100644 --- a/python/src/bindings.cpp +++ b/python/src/bindings.cpp @@ -623,7 +623,7 @@ auto register_analysis_bindings(py::module_& module) -> void { // initialize_static_memory: allocate the solver's static memory pools and // perform one-time lookup-table initialization. This does NOT control the - // worker-thread count; use solve_all_boards_* (which parallelise across the + // worker-thread count; use solve_all_boards_* (which parallelize across the // machine's hardware threads automatically) or one SolverContext per worker // thread for per-board concurrency. module.def( @@ -635,7 +635,7 @@ auto register_analysis_bindings(py::module_& module) -> void "Initialize the solver's static memory.\n\n" "Allocates the transposition-table memory pools and performs one-time\n" "lookup-table initialization. This does NOT control the number of worker\n" - "threads: solve_all_boards_* parallelise across the machine's hardware\n" + "threads: solve_all_boards_* parallelize across the machine's hardware\n" "threads automatically, and for per-board concurrency from Python you\n" "create one SolverContext per worker thread and pass it to solve_board /\n" "solve_board_pbn.");