chore: восстановление репозитория из снапшота v0.3.1
Прежняя git-история утрачена при переносе проекта на машину владельца (снапшот без .git). Хэши коммитов в docs/reports/* относятся к утраченной истории. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
1c85091186
184 changed files with 33303 additions and 0 deletions
345
apps/web/src/content/content.test.ts
Normal file
345
apps/web/src/content/content.test.ts
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
/**
|
||||
* Валидация контента этапа 6: задачи (TaskV1 + SGF-деревья решений) и уроки.
|
||||
* Читает файлы через node:fs, движок — только @go-learn/core.
|
||||
*
|
||||
* Проверки задач: обязательные поля, уникальность id, префикс id по kind,
|
||||
* легальность позиции (buildPosition), парсинг SGF, разметка цели на корне
|
||||
* (TR — capture-target/liberties/two-eyes, CR — connect) на камнях нужного
|
||||
* цвета, легальность каждой вариации от позиции задачи (applyMove),
|
||||
* чередование цветов от toPlay. Сводные: ≥30 цумэ-го, ≥3 на каждую
|
||||
* градацию difficulty 1–5.
|
||||
*
|
||||
* Проверки уроков: frontmatter (title/section/order/summary), section из
|
||||
* программы курса, существование data-task-id, покрытие всех 10 разделов,
|
||||
* объём текста 300–700 слов.
|
||||
*/
|
||||
import { readdirSync, readFileSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { BoardSize, BoardState, CellState, Color, GameNode, Point } from '@go-learn/core';
|
||||
import { applyMove, buildPosition, cellAt, opposite, parseSgf } from '@go-learn/core';
|
||||
|
||||
type Goal =
|
||||
| { readonly type: 'capture-target' }
|
||||
| { readonly type: 'liberties'; readonly count: number }
|
||||
| { readonly type: 'connect' }
|
||||
| { readonly type: 'two-eyes' };
|
||||
|
||||
interface TaskV1 {
|
||||
readonly id: string;
|
||||
readonly kind: 'lesson' | 'tsumego';
|
||||
readonly title: string;
|
||||
readonly topics: readonly string[];
|
||||
readonly difficulty: number;
|
||||
readonly size: BoardSize;
|
||||
readonly toPlay: Color;
|
||||
readonly setupBlack: readonly Point[];
|
||||
readonly setupWhite: readonly Point[];
|
||||
readonly sgf: string;
|
||||
readonly goal: Goal;
|
||||
readonly hint: string;
|
||||
}
|
||||
|
||||
const SECTIONS: readonly string[] = [
|
||||
'Дамэ и захват',
|
||||
'Атари, лестница, сеть',
|
||||
'Самоубийство и ко',
|
||||
'Глаза: жизнь и смерть',
|
||||
'Подсчёт и конец партии',
|
||||
'Связь и разрезание',
|
||||
'Углы, стороны, центр',
|
||||
'Базовые дзёсэки',
|
||||
'Форма',
|
||||
'Простое ёсэ',
|
||||
];
|
||||
|
||||
/** Разделы, в уроках которых обязателен интерактив (уроки 1–6 и 10). */
|
||||
const INTERACTIVE_SECTIONS: readonly string[] = [
|
||||
'Дамэ и захват',
|
||||
'Атари, лестница, сеть',
|
||||
'Самоубийство и ко',
|
||||
'Глаза: жизнь и смерть',
|
||||
'Подсчёт и конец партии',
|
||||
'Связь и разрезание',
|
||||
'Простое ёсэ',
|
||||
];
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function fail(ctx: string, message: string): never {
|
||||
throw new Error(`${ctx}: ${message}`);
|
||||
}
|
||||
|
||||
function parsePoints(value: unknown, ctx: string): Point[] {
|
||||
if (!Array.isArray(value)) fail(ctx, 'ожидался массив точек');
|
||||
return value.map((item, index) => {
|
||||
if (!isRecord(item)) fail(`${ctx}[${index}]`, 'точка — не объект');
|
||||
const { x, y } = item;
|
||||
if (!Number.isInteger(x) || !Number.isInteger(y)) {
|
||||
fail(`${ctx}[${index}]`, 'координаты x/y должны быть целыми');
|
||||
}
|
||||
return { x: x as number, y: y as number };
|
||||
});
|
||||
}
|
||||
|
||||
function parseGoal(value: unknown, ctx: string): Goal {
|
||||
if (!isRecord(value)) fail(ctx, 'goal — не объект');
|
||||
const type = value['type'];
|
||||
if (type === 'capture-target' || type === 'connect' || type === 'two-eyes') {
|
||||
return { type };
|
||||
}
|
||||
if (type === 'liberties') {
|
||||
const count = value['count'];
|
||||
if (!Number.isInteger(count) || (count as number) < 1) {
|
||||
fail(ctx, 'goal.count должен быть целым ≥ 1');
|
||||
}
|
||||
return { type, count: count as number };
|
||||
}
|
||||
return fail(ctx, `неизвестный goal.type «${String(type)}»`);
|
||||
}
|
||||
|
||||
function parseTask(raw: unknown, ctx: string): TaskV1 {
|
||||
if (!isRecord(raw)) fail(ctx, 'задача — не объект');
|
||||
const { id, kind, title, topics, difficulty, size, toPlay, sgf, hint } = raw;
|
||||
if (typeof id !== 'string' || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(id)) {
|
||||
fail(ctx, 'id должен быть kebab-case');
|
||||
}
|
||||
if (kind !== 'lesson' && kind !== 'tsumego') fail(ctx, 'kind должен быть lesson|tsumego');
|
||||
const prefix = kind === 'lesson' ? 'lsn-' : 'tsm-';
|
||||
if (!id.startsWith(prefix)) fail(ctx, `id должен начинаться с «${prefix}»`);
|
||||
if (typeof title !== 'string' || title.trim() === '') fail(ctx, 'пустой title');
|
||||
if (
|
||||
!Array.isArray(topics) ||
|
||||
topics.length === 0 ||
|
||||
!topics.every((t) => typeof t === 'string' && t.trim() !== '')
|
||||
) {
|
||||
fail(ctx, 'topics должен быть непустым массивом строк');
|
||||
}
|
||||
if (!Number.isInteger(difficulty) || (difficulty as number) < 1 || (difficulty as number) > 5) {
|
||||
fail(ctx, 'difficulty должен быть целым 1–5');
|
||||
}
|
||||
if (size !== 9 && size !== 13 && size !== 19) fail(ctx, 'size должен быть 9|13|19');
|
||||
if (toPlay !== 'black' && toPlay !== 'white') fail(ctx, 'toPlay должен быть black|white');
|
||||
if (typeof sgf !== 'string' || sgf.trim() === '') fail(ctx, 'пустой sgf');
|
||||
if (typeof hint !== 'string' || hint.trim() === '') fail(ctx, 'пустой hint');
|
||||
const goal = parseGoal(raw['goal'], ctx);
|
||||
return {
|
||||
id,
|
||||
kind,
|
||||
title,
|
||||
topics: topics as string[],
|
||||
difficulty: difficulty as number,
|
||||
size,
|
||||
toPlay,
|
||||
setupBlack: parsePoints(raw['setupBlack'], `${ctx}.setupBlack`),
|
||||
setupWhite: parsePoints(raw['setupWhite'], `${ctx}.setupWhite`),
|
||||
sgf,
|
||||
goal,
|
||||
hint,
|
||||
};
|
||||
}
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const tasksDir = join(here, 'tasks');
|
||||
const lessonsDir = join(here, 'lessons');
|
||||
|
||||
const loadErrors: string[] = [];
|
||||
const allTasks: TaskV1[] = [];
|
||||
const taskFiles = readdirSync(tasksDir)
|
||||
.filter((name) => name.endsWith('.json'))
|
||||
.sort();
|
||||
for (const file of taskFiles) {
|
||||
try {
|
||||
const raw: unknown = JSON.parse(readFileSync(join(tasksDir, file), 'utf8'));
|
||||
if (!Array.isArray(raw)) fail(file, 'корень JSON — не массив');
|
||||
raw.forEach((item, index) => {
|
||||
allTasks.push(parseTask(item, `${file}[${index}]`));
|
||||
});
|
||||
} catch (error) {
|
||||
loadErrors.push(error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
}
|
||||
|
||||
describe('задачи (tasks/*.json)', () => {
|
||||
it('все файлы парсятся как массивы TaskV1', () => {
|
||||
expect(loadErrors).toEqual([]);
|
||||
expect(taskFiles.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('id уникальны', () => {
|
||||
const seen = new Set<string>();
|
||||
const duplicates: string[] = [];
|
||||
for (const task of allTasks) {
|
||||
if (seen.has(task.id)) duplicates.push(task.id);
|
||||
seen.add(task.id);
|
||||
}
|
||||
expect(duplicates).toEqual([]);
|
||||
});
|
||||
|
||||
for (const task of allTasks) {
|
||||
describe(task.id, () => {
|
||||
it('позиция легальна (buildPosition не бросает)', () => {
|
||||
expect(() =>
|
||||
buildPosition(task.size, task.setupBlack, task.setupWhite, task.toPlay),
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it('SGF парсится, размер совпадает', () => {
|
||||
const tree = parseSgf(task.sgf);
|
||||
expect(tree.size).toBe(task.size);
|
||||
});
|
||||
|
||||
it('на корне есть разметка цели на камнях нужного цвета', () => {
|
||||
const tree = parseSgf(task.sgf);
|
||||
const position = buildPosition(task.size, task.setupBlack, task.setupWhite, task.toPlay);
|
||||
const marked =
|
||||
task.goal.type === 'connect' ? tree.root.markup.circles : tree.root.markup.triangles;
|
||||
expect(marked.length).toBeGreaterThan(0);
|
||||
const want: CellState =
|
||||
task.goal.type === 'capture-target' ? opposite(task.toPlay) : task.toPlay;
|
||||
for (const point of marked) {
|
||||
expect(cellAt(position, point)).toBe(want);
|
||||
}
|
||||
});
|
||||
|
||||
it('каждая вариация легальна от позиции задачи, цвета чередуются', () => {
|
||||
const tree = parseSgf(task.sgf);
|
||||
const initial = buildPosition(task.size, task.setupBlack, task.setupWhite, task.toPlay);
|
||||
expect(tree.root.children.length).toBeGreaterThan(0);
|
||||
const walk = (
|
||||
node: GameNode,
|
||||
state: BoardState,
|
||||
expectColor: Color,
|
||||
path: string,
|
||||
): void => {
|
||||
node.children.forEach((child, index) => {
|
||||
const childPath = `${path}/${index}`;
|
||||
expect(child.move, `${task.id}${childPath}: узел без хода`).not.toBeNull();
|
||||
if (child.move === null) return;
|
||||
expect(child.move.color, `${task.id}${childPath}: нарушено чередование`).toBe(
|
||||
expectColor,
|
||||
);
|
||||
const result = applyMove(state, child.move);
|
||||
expect(
|
||||
result.ok,
|
||||
`${task.id}${childPath}: нелегальный ход ${result.ok === false ? result.error : ''}`,
|
||||
).toBe(true);
|
||||
if (result.ok) walk(child, result.state, opposite(expectColor), childPath);
|
||||
});
|
||||
};
|
||||
walk(tree.root, initial, task.toPlay, '');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('не менее 30 цумэ-го', () => {
|
||||
expect(allTasks.filter((task) => task.kind === 'tsumego').length).toBeGreaterThanOrEqual(30);
|
||||
});
|
||||
|
||||
it('на каждую градацию difficulty 1–5 не менее 3 цумэ-го', () => {
|
||||
for (let difficulty = 1; difficulty <= 5; difficulty += 1) {
|
||||
const count = allTasks.filter(
|
||||
(task) => task.kind === 'tsumego' && task.difficulty === difficulty,
|
||||
).length;
|
||||
expect(count, `difficulty ${difficulty}`).toBeGreaterThanOrEqual(3);
|
||||
}
|
||||
});
|
||||
|
||||
it('задачи уроков — на доске 9×9', () => {
|
||||
for (const task of allTasks.filter((item) => item.kind === 'lesson')) {
|
||||
expect(task.size, task.id).toBe(9);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
interface LessonDoc {
|
||||
readonly file: string;
|
||||
readonly frontmatter: Record<string, string> | null;
|
||||
readonly body: string;
|
||||
}
|
||||
|
||||
function parseFrontmatter(text: string): Record<string, string> | null {
|
||||
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
|
||||
if (match === null) return null;
|
||||
const out: Record<string, string> = {};
|
||||
for (const line of (match[1] ?? '').split(/\r?\n/)) {
|
||||
const kv = /^([A-Za-z]+):\s*(.*)$/.exec(line);
|
||||
if (kv !== null) {
|
||||
let value = (kv[2] ?? '').trim();
|
||||
if (
|
||||
(value.startsWith('"') && value.endsWith('"')) ||
|
||||
(value.startsWith("'") && value.endsWith("'"))
|
||||
) {
|
||||
value = value.slice(1, -1);
|
||||
}
|
||||
out[kv[1] ?? ''] = value;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
const lessonFiles = readdirSync(lessonsDir)
|
||||
.filter((name) => name.endsWith('.md'))
|
||||
.sort();
|
||||
const lessons: LessonDoc[] = lessonFiles.map((file) => {
|
||||
const text = readFileSync(join(lessonsDir, file), 'utf8');
|
||||
return { file, frontmatter: parseFrontmatter(text), body: text };
|
||||
});
|
||||
|
||||
describe('уроки (lessons/*.md)', () => {
|
||||
it('уроков не менее 10', () => {
|
||||
expect(lessons.length).toBeGreaterThanOrEqual(10);
|
||||
});
|
||||
|
||||
for (const lesson of lessons) {
|
||||
describe(lesson.file, () => {
|
||||
it('есть frontmatter с title/section/order/summary', () => {
|
||||
const fm = lesson.frontmatter;
|
||||
expect(fm, 'frontmatter не найден').not.toBeNull();
|
||||
if (fm === null) return;
|
||||
expect(fm['title'] ?? '', 'title').not.toBe('');
|
||||
expect(fm['section'] ?? '', 'section').not.toBe('');
|
||||
expect(fm['summary'] ?? '', 'summary').not.toBe('');
|
||||
expect(Number.isInteger(Number(fm['order'])), 'order — целое число').toBe(true);
|
||||
});
|
||||
|
||||
it('section входит в программу курса', () => {
|
||||
expect(SECTIONS).toContain(lesson.frontmatter?.['section']);
|
||||
});
|
||||
|
||||
it('объём текста 300–700 слов', () => {
|
||||
const withoutFrontmatter = lesson.body.replace(/^---\r?\n[\s\S]*?\r?\n---/, '');
|
||||
const words = withoutFrontmatter.split(/\s+/).filter((word) => /\p{L}/u.test(word));
|
||||
expect(words.length).toBeGreaterThanOrEqual(300);
|
||||
expect(words.length).toBeLessThanOrEqual(700);
|
||||
});
|
||||
|
||||
it('все data-task-id существуют среди задач', () => {
|
||||
const ids = new Set(allTasks.map((task) => task.id));
|
||||
const refs = [...lesson.body.matchAll(/data-task-id="([^"]+)"/g)].map(
|
||||
(match) => match[1] ?? '',
|
||||
);
|
||||
for (const ref of refs) {
|
||||
expect(ids.has(ref), `нет задачи «${ref}»`).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('разделы 1–6 и 10 содержат интерактивную задачу', () => {
|
||||
const section = lesson.frontmatter?.['section'] ?? '';
|
||||
if (INTERACTIVE_SECTIONS.includes(section)) {
|
||||
expect(lesson.body).toMatch(/<go-task data-task-id="lsn-/);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('все 10 разделов программы покрыты уроками', () => {
|
||||
const covered = new Set(lessons.map((lesson) => lesson.frontmatter?.['section'] ?? ''));
|
||||
for (const section of SECTIONS) {
|
||||
expect(covered.has(section), `нет урока по разделу «${section}»`).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
74
apps/web/src/content/lessons/01-dame-i-zahvat.md
Normal file
74
apps/web/src/content/lessons/01-dame-i-zahvat.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
title: 'Дамэ и захват'
|
||||
section: 'Дамэ и захват'
|
||||
order: 1
|
||||
summary: 'Что такое дамэ (дыхания) группы, как считать их и как происходит захват камней. Основа всех правил Го.'
|
||||
---
|
||||
|
||||
# Дамэ и захват
|
||||
|
||||
Камень в Го «живёт», пока у него есть **дамэ** — свободные соседние пункты по
|
||||
линиям доски (по горизонтали и вертикали, диагонали не считаются). Дамэ — это
|
||||
«дыхание» камня: как только последнее дамэ исчезает, камень снимается с доски.
|
||||
|
||||
## Как считать дамэ
|
||||
|
||||
У одинокого камня в центре доски четыре дамэ: сверху, снизу, слева и справа.
|
||||
На краю доски — три, в углу — всего два:
|
||||
|
||||
```
|
||||
A B C A B C
|
||||
1 . . . 1 X . .
|
||||
2 . X . 2 . . .
|
||||
3 . . . 3 . . .
|
||||
центр: 4 угол A1: 2 (B1 и A2)
|
||||
```
|
||||
|
||||
Камни одного цвета, стоящие рядом по линиям, образуют **группу**. Группа
|
||||
делит дамэ на всех: у цепочки из двух камней в центре уже шесть дамэ.
|
||||
Захватывается всегда группа целиком — нельзя снять «половину» цепочки.
|
||||
|
||||
## Захват
|
||||
|
||||
Когда вы ставите камень так, что у группы противника не остаётся ни одного
|
||||
дамэ, эта группа немедленно снимается с доски и становится вашими пленниками.
|
||||
|
||||
```
|
||||
A B C
|
||||
1 . B .
|
||||
2 B W .
|
||||
3 . . .
|
||||
Белый B2 в атari: осталось одно дамэ — B3.
|
||||
```
|
||||
|
||||
Ситуация, когда у группы осталось ровно одно дамэ, называется **атари** —
|
||||
это предупреждение: «ещё один ход, и камни снимут». В обучающих партиях с
|
||||
новичками «атари» принято говорить вслух — так учатся замечать угрозы;
|
||||
опытные игроки вслух его обычно не объявляют. Начинающим полезно замечать
|
||||
атари самостоятельно, пересчитывая дамэ после каждого хода.
|
||||
|
||||
## Почему это важно
|
||||
|
||||
Всё в Го построено на подсчёте дамэ: и борьба за жизнь группы, и захваты,
|
||||
и гонки «кто кого первым снимет». Простейшая тактика звучит так: у группы
|
||||
противника мало дамэ — сокращайте их; у вашей группы мало дамэ — добавляйте
|
||||
(продлевайтесь, соединяйтесь с друзьями).
|
||||
|
||||
Типичная ошибка новичка — не заметить, что его собственная группа уже в
|
||||
атари, и потерять её. После каждого хода противника спрашивайте себя:
|
||||
«Сколько теперь дамэ у моих групп?»
|
||||
|
||||
## Практика
|
||||
|
||||
В задаче ниже белый камень окружён с трёх сторон и у него осталось одно
|
||||
дамэ. Найдите этот пункт и поставьте туда чёрный камень — белый будет
|
||||
захвачен.
|
||||
|
||||
<go-task data-task-id="lsn-dame-capture">Запасной текст: попробуйте решить задачу (нужен включённый JavaScript).</go-task>
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Дамэ — свободные соседние пункты камня или группы.
|
||||
- Нет дамэ — камни снимаются с доски.
|
||||
- Одно дамэ — атари, группа под угрозой.
|
||||
- Группа делит дамэ на все свои камни.
|
||||
83
apps/web/src/content/lessons/02-atari-lestnitsa-set.md
Normal file
83
apps/web/src/content/lessons/02-atari-lestnitsa-set.md
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
title: 'Атари, лестница, сеть'
|
||||
section: 'Атари, лестница, сеть'
|
||||
order: 1
|
||||
summary: 'Три базовых тактических приёма: атари как угроза, лестница как погоня по диагонали и сеть как тихий захват без атари.'
|
||||
---
|
||||
|
||||
# Атари, лестница, сеть
|
||||
|
||||
## Атари
|
||||
|
||||
**Атари** — позиция, в которой у группы осталось одно дамэ. Поставить атари —
|
||||
значит пригрозить захватом на следующий ход. Атари — самое сильное оружие
|
||||
новичка: оно часто вынуждает противника отвечать. Впрочем, отвечать не
|
||||
обязательно: сильный игрок может сознательно проигнорировать атари ради
|
||||
большего хода в другом месте. Но помните: атари ради атари —
|
||||
плохая привычка. Каждый раз спрашивайте себя: «А что я получу, если он
|
||||
спасётся?»
|
||||
|
||||
## Лестница
|
||||
|
||||
Если загонять камень атари за атари так, что у него всякий раз остаётся
|
||||
ровно один путь к бегству, получается **лестница** — зигзагообразная погоня
|
||||
через всю доску:
|
||||
|
||||
```
|
||||
A B C D E
|
||||
1 . . W B .
|
||||
2 . B W . .
|
||||
3 B . . . .
|
||||
лестница бежит по диагонали к углу
|
||||
```
|
||||
|
||||
Лестница работает, если на её пути нет камней противника. Если по диагонали
|
||||
бега стоит хоть один вражеский камень (**ситё-прерыватель** — «лестничная
|
||||
опора», англ. ladder breaker, ход ситё-атари), погоня срывается: убегающая
|
||||
группа соединяется с опорой и получает новые дамэ. Поэтому перед тем как начать лестницу, прочитайте её до конца:
|
||||
проследите зигзаг глазами до края доски. Лестница либо захватывает, либо
|
||||
катастрофически проигрывает — середины нет.
|
||||
|
||||
Край доски — лучший друг лестницы: у камня на первой линии всего три дамэ,
|
||||
и убегать ему некуда. Погоня, прижатая к краю, заканчивается захватом
|
||||
гарантированно.
|
||||
|
||||
## Сеть
|
||||
|
||||
Когда лестница не работает, камень часто можно поймать **сетью** (гэта):
|
||||
тихим ходом, который не ставит атари, но заранее закрывает все пути
|
||||
к бегству:
|
||||
|
||||
```
|
||||
A B C D
|
||||
1 . B . .
|
||||
2 W . . .
|
||||
3 . . B .
|
||||
чёрный D-подобный ход накрывает белый камень сетью
|
||||
```
|
||||
|
||||
Классическая сеть ставится через один пункт от цели (конём, как в шахматах).
|
||||
Куда бы белый ни продлился, следующее атари оставляет его без дамэ.
|
||||
Признак того, что пора думать о сети: у камня два дамэ, а прямое атари
|
||||
ведёт в лестницу с вражеской опорой на пути.
|
||||
|
||||
## Как выбирать приём
|
||||
|
||||
1. Сначала посмотрите на лестницу: чистый ли путь?
|
||||
2. Если лестница сломана опорой — ищите сеть.
|
||||
3. Если не работает ни то, ни другое — не гонитесь: слабый камень противника
|
||||
никуда не денется, займитесь своими группами.
|
||||
|
||||
## Практика
|
||||
|
||||
В задаче чёрные загоняют белый камень лестницей прямо на край доски.
|
||||
Проведите всю погоню до захвата.
|
||||
|
||||
<go-task data-task-id="lsn-ladder">Запасной текст: попробуйте решить задачу (нужен включённый JavaScript).</go-task>
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Атари — угроза захвата в один ход.
|
||||
- Лестница — серия атари, оставляющих один путь; проверяйте диагональ на
|
||||
наличие опоры.
|
||||
- Сеть — тихий захват без атари, когда лестница не проходит.
|
||||
78
apps/web/src/content/lessons/03-samoubiystvo-i-ko.md
Normal file
78
apps/web/src/content/lessons/03-samoubiystvo-i-ko.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
title: 'Самоубийство и ко'
|
||||
section: 'Самоубийство и ко'
|
||||
order: 1
|
||||
summary: 'Почему нельзя ставить камень в пункт без дамэ, когда такой ход всё же легален, и как работает правило ко.'
|
||||
---
|
||||
|
||||
# Самоубийство и ко
|
||||
|
||||
## Запрет самоубийства
|
||||
|
||||
Ход, после которого у вашей собственной группы не остаётся ни одного дамэ,
|
||||
**запрещён**. Нельзя «пожертвовать» камень, просто поставив его в полностью
|
||||
окружённый пункт: по официальным правилам (например, AGA) такой ход
|
||||
отменяется и засчитывается как пас, а на этом сайте движок просто не даст
|
||||
поставить такой камень.
|
||||
|
||||
```
|
||||
A B C
|
||||
1 . W .
|
||||
2 W . W точка B2 для чёрных — под запретом:
|
||||
3 . W . чёрный камень там сразу останется без дамэ
|
||||
```
|
||||
|
||||
## Важное исключение: захват
|
||||
|
||||
Если ход в «запретный» пункт **снимает** группу противника, он легален:
|
||||
снятые камни освобождают пункты, и у вашего камня появляются дамэ. Поэтому
|
||||
ход, выглядящий как самоубийство, иногда оказывается решающим ударом.
|
||||
Всегда проверяйте: не в атари ли группа, внутрь которой вы ставите камень?
|
||||
|
||||
## Правило ко
|
||||
|
||||
Представьте форму, где чёрные снимают один белый камень, а белые могут
|
||||
тут же снять в ответ один чёрный — и позиция возвращается к исходной.
|
||||
Без ограничения такая пара захватов повторялась бы бесконечно. Поэтому
|
||||
действует правило **ко** (по-японски — «вечность»):
|
||||
|
||||
> Немедленно возвращать захваченный камень нельзя. Сначала нужно сделать
|
||||
> ход в другом месте доски.
|
||||
|
||||
```
|
||||
A B C D
|
||||
2 . B . .
|
||||
3 B W . B чёрные снимают W на C3 — белые не могут
|
||||
4 . W W . ответить захватом сразу: это ко
|
||||
```
|
||||
|
||||
После того как соперник сходил в другую точку, запрет снимается: если он не
|
||||
закрыл ко, вы можете вернуться и выиграть его.
|
||||
|
||||
## Ко-борьба
|
||||
|
||||
Из правила ко рождается целая стратегия. Ход в другом месте, который требует
|
||||
ответа, называется **ко-угрозой**. Выигрывает ко тот, у кого больше угроз:
|
||||
вы ставите угрозу, соперник отвечает, вы забираете ко обратно. Ценность ко
|
||||
и ценность угроз нужно сравнивать: иногда выгоднее «продать» ко, получив
|
||||
два хода подряд в другом месте.
|
||||
|
||||
Для начинающего достаточно трёх правил:
|
||||
|
||||
1. Начав ко, знайте, зачем: выигрыш ко должен чего-то стоить.
|
||||
2. Перед ко посчитайте свои ко-угрозы — хотя бы одна должна быть.
|
||||
3. Не отвечайте на мелкие угрозы, если ко дороже.
|
||||
|
||||
## Практика
|
||||
|
||||
В задаче чёрные снимают белый камень, образуя ко. Белые не могут вернуть
|
||||
камень немедленно и ходят в сторону — после этого чёрные спокойно закрывают
|
||||
ко соединением.
|
||||
|
||||
<go-task data-task-id="lsn-ko">Запасной текст: попробуйте решить задачу (нужен включённый JavaScript).</go-task>
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Ход без дамэ запрещён — если только он не захватывает.
|
||||
- Ко запрещает немедленный обратный захват одного камня.
|
||||
- Ко-угроза — способ «купить» право вернуться в ко.
|
||||
81
apps/web/src/content/lessons/04-glaza-zhizn-i-smert.md
Normal file
81
apps/web/src/content/lessons/04-glaza-zhizn-i-smert.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
title: 'Глаза: жизнь и смерть'
|
||||
section: 'Глаза: жизнь и смерть'
|
||||
order: 1
|
||||
summary: 'Что такое глаз, почему два глаза дают вечную жизнь, и как отличить настоящий глаз от ложного.'
|
||||
---
|
||||
|
||||
# Глаза: жизнь и смерть
|
||||
|
||||
## Что такое глаз
|
||||
|
||||
**Глаз** — это один или несколько соседних пустых пунктов, полностью
|
||||
окружённых камнями одного цвета:
|
||||
|
||||
```
|
||||
A B C
|
||||
1 B B .
|
||||
2 B . B точка B2 — глаз чёрных
|
||||
3 B B .
|
||||
```
|
||||
|
||||
Противник не может просто поставить камень в глаз: это самоубийство. Единственный
|
||||
способ сыграть туда — сначала снять все внешние дамэ группы, то есть поставить
|
||||
её в атари.
|
||||
|
||||
## Два глаза — жизнь
|
||||
|
||||
Если у группы есть **два отдельных глаза**, она неуязвима. Чтобы захватить
|
||||
группу, противнику нужно заполнить оба глаза, но ход в первый глаз —
|
||||
самоубийство, пока не заполнен второй, и наоборот. Логическая ловушка
|
||||
замыкается: группа с двумя глазами живёт вечно, сколько бы камней ни
|
||||
теснилось вокруг.
|
||||
|
||||
Отсюда главная цель обороны в Го: **построить два глаза**. И главная цель
|
||||
нападения: не дать их построить.
|
||||
|
||||
Один большой глаз — это ещё не жизнь. Если всё внутреннее пространство группы
|
||||
связно, противник рано или поздно займёт его ключевую точку. Поэтому
|
||||
пространство нужно **разделять** на две независимые области.
|
||||
|
||||
## Ложный глаз
|
||||
|
||||
Не всякий глаз настоящий. Посмотрите на форму:
|
||||
|
||||
```
|
||||
A B C
|
||||
1 . W .
|
||||
2 W . W
|
||||
3 . W .
|
||||
```
|
||||
|
||||
Точка B2 выглядит как глаз белых, но четыре белых камня вокруг неё
|
||||
**не связаны** между собой — они касаются друг друга только по диагонали.
|
||||
Чёрные могут поставить атари на один из них, а затем занять «глаз».
|
||||
Такой глаз называется **ложным**: он есть на бумаге, но не даёт жизни.
|
||||
|
||||
Признак настоящего глаза: все камни вокруг него соединены в одну крепкую
|
||||
группу, и противник не может ни разрезать их, ни поставить в атари.
|
||||
Прежде чем рассчитывать на глаз, проверьте диагонали: именно по диагоналям
|
||||
глаз чаще всего оказывается ложным.
|
||||
|
||||
## Жизнь и смерть в задачах
|
||||
|
||||
Типичная задача на жизнь и смерть формулируется так: «чёрные ходят и живут»
|
||||
или «чёрные ходят и убивают». Решение почти всегда — **жизненная точка**:
|
||||
единственный пункт, который делит пространство на два глаза (для жизни) или
|
||||
мешает противнику это сделать (для убийства). Ищите центр симметрии формы —
|
||||
чаще всего он и есть ответ.
|
||||
|
||||
## Практика
|
||||
|
||||
Белые рассчитывают на глаз, но их камни вокруг него не связаны — глаз ложный.
|
||||
Найдите ход, который разрушает иллюзию и захватывает отмеченные камни.
|
||||
|
||||
<go-task data-task-id="lsn-false-eye">Запасной текст: попробуйте решить задачу (нужен включённый JavaScript).</go-task>
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Глаз — пустое пространство, окружённое одним цветом.
|
||||
- Два глаза = вечная жизнь; один глаз = смерть под вопросом.
|
||||
- Ложный глаз не защищает: проверяйте связность камней вокруг него.
|
||||
76
apps/web/src/content/lessons/05-podschyot-i-konets-partii.md
Normal file
76
apps/web/src/content/lessons/05-podschyot-i-konets-partii.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
title: 'Подсчёт и конец партии'
|
||||
section: 'Подсчёт и конец партии'
|
||||
order: 1
|
||||
summary: 'Как заканчивается партия (два паса), что такое территория и как подсчитывается результат по китайским правилам.'
|
||||
---
|
||||
|
||||
# Подсчёт и конец партии
|
||||
|
||||
## Когда партия заканчивается
|
||||
|
||||
Партия в Го не заканчивается матом — она заканчивается согласием. Когда оба
|
||||
игрока считают, что выгодных ходов не осталось, они пасуют. **Два паса
|
||||
подряд — конец партии.**
|
||||
|
||||
Перед пасом проверьте:
|
||||
|
||||
- все ли границы территорий закрыты;
|
||||
- нет ли незакрытых дамэ между группами, через которые противник может
|
||||
разрезать;
|
||||
- не осталось ли ваших камней в атари, которые ещё можно спасти, и чужих —
|
||||
которые можно добрать.
|
||||
|
||||
Пасовать раньше времени — отдавать очки. Пасовать позже — тоже ошибка:
|
||||
по японским правилам ход в свою территорию стоит очко, а по китайским
|
||||
(нашим) счёт не меняется, но ход впустую отдаёт инициативу.
|
||||
|
||||
## Мёртвые камни
|
||||
|
||||
После двух пасов игроки договариваются, какие группы **мёртвы** — обречены,
|
||||
хотя формально стоят на доске. Мёртвые камни убираются с доски как пленники.
|
||||
Если игроки не согласны — партия просто продолжается, и спорная группа
|
||||
доказывает свою судьбу игрой. Это честное правило: «сомневаешься — играй».
|
||||
|
||||
## Что такое территория
|
||||
|
||||
**Территория** — пустые пункты, окружённые живыми камнями одного цвета так,
|
||||
что противник не может вторгнуться с надеждой выжить. Каждый такой пункт —
|
||||
очко.
|
||||
|
||||
## Подсчёт по-китайски (площадь)
|
||||
|
||||
Мы используем китайские правила: очки каждого игрока — это
|
||||
|
||||
> **его живые камни на доске + его территория.**
|
||||
|
||||
Белые дополнительно получают **коми** — компенсацию за второй ход
|
||||
(в наших партиях — 6,5 очка на большой доске и 5,5 — на доске 9×9; стандарт
|
||||
китайских правил на большой доске — 7,5; пол-очка исключает ничью).
|
||||
|
||||
Пример. У чёрных: 30 камней на доске и 20 пунктов территории — 50 очков.
|
||||
У белых: 28 камней и 16 пунктов территории — 44, плюс коми 5,5 — итого 49,5.
|
||||
Чёрные выиграли с перевесом 0,5 очка.
|
||||
|
||||
Обратите внимание: по китайским правилам ход внутрь своей территории не
|
||||
меняет счёта (камень занимает пункт территории), а по японским — потерял бы
|
||||
очко. Поэтому в конце партии по нашим правилам можно безопасно «доукрепляться».
|
||||
|
||||
## Оценка позиции по ходу партии
|
||||
|
||||
Грубая прикидка «кто выигрывает» — полезный навык: посчитайте очевидную
|
||||
территорию обоих, добавьте коми белым, сравните. Если вы впереди — играйте
|
||||
проще и надёжнее; если позади — ищите более острые варианты.
|
||||
|
||||
## Практика
|
||||
|
||||
Перед подсчётом нужно прибрать доску: два белых камня внутри чёрной
|
||||
территории в атари. Снимите их — иначе при подсчёте начнутся споры.
|
||||
|
||||
<go-task data-task-id="lsn-endgame-capture">Запасной текст: попробуйте решить задачу (нужен включённый JavaScript).</go-task>
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Два паса подряд заканчивают партию.
|
||||
- Счёт: камни + территория; белые получают коми.
|
||||
- Мёртвые камни снимаются по согласию; спор решается доигрыванием.
|
||||
75
apps/web/src/content/lessons/06-svyaz-i-razrezanie.md
Normal file
75
apps/web/src/content/lessons/06-svyaz-i-razrezanie.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
title: 'Связь и разрезание'
|
||||
section: 'Связь и разрезание'
|
||||
order: 1
|
||||
summary: 'Почему связанные группы сильнее, как соединять свои камни надёжно и как разрезать камни противника.'
|
||||
---
|
||||
|
||||
# Связь и разрезание
|
||||
|
||||
## Сила связи
|
||||
|
||||
Камни, соединённые в одну группу, делят дамэ и строят глаза вместе.
|
||||
Две слабые группы по три дамэ — две проблемы; одна связанная группа с шестью
|
||||
дамэ — крепость. Поэтому **соединяйте свои группы и разрезайте чужие** —
|
||||
это называют главной тактической идеей Го.
|
||||
|
||||
## Надёжные и ненадёжные связи
|
||||
|
||||
Камни, стоящие вплотную по линии, связаны абсолютно — их нельзя разрезать.
|
||||
Но многие «красивые» формы связаны лишь условно:
|
||||
|
||||
```
|
||||
A B C D
|
||||
1 B . B . ход через один пункт (иккэн):
|
||||
2 . . . . белые могут попытаться вклиниться в B1
|
||||
```
|
||||
|
||||
Связь через один пункт надёжна, только если вы готовы ответить соединением
|
||||
на вклинивание. Диагональный ход (косуми) — тоже не абсолютная связь, но
|
||||
сам по себе он локально неразрезаем: на разрез в один пункт вы отвечаете
|
||||
соединением в другой (миаи). Уязвимо косуми лишь тогда, когда вокруг уже
|
||||
стоят сильные камни противника.
|
||||
|
||||
## Типичные способы соединения
|
||||
|
||||
- **Прямое соединение** — поставить камень в разрыв цепочки.
|
||||
- **Соединение снизу** — соединиться по первой линии, под защитой края.
|
||||
- **Захват разрезающего камня** — если вклинившийся камень слаб, снимите его:
|
||||
связь восстановится сама собой.
|
||||
|
||||
Выбирая, соединяться ли, спросите: «Что случится, если меня разрежут?»
|
||||
Если обе части живут сами — не тратьте ход. Если одна погибнет — соединяйтесь
|
||||
немедленно.
|
||||
|
||||
## Как разрезать
|
||||
|
||||
Разрезание — зеркальный приём: ищите **точку разреза** — пункт, через который
|
||||
противник соединял бы свои группы. Часто это единственный пункт между двумя
|
||||
диагонально стоящими камнями. Но помните: разрезающий ход должен сам выжить.
|
||||
Разрезать и тут же потерять разрезающий камень — значит подарить противнику
|
||||
и связь, и материал.
|
||||
|
||||
## Когда связь важнее территории
|
||||
|
||||
Новички жертвуют связью ради пары пунктов. Почти всегда это ошибка:
|
||||
разрезанная группа бежит, отдаёт инициативу и тащит за собой потери по всей
|
||||
доске. Сильные игроки говорят: «Соединяйся — и получишь ход в другом месте».
|
||||
|
||||
Полезно и обратное наблюдение: если противник потратил ход на разрезание,
|
||||
а обе ваши половины спокойно живут, — он просто подарил вам темп. Ценность
|
||||
разреза и связи всегда измеряется судьбой групп, а не самим фактом
|
||||
«разрезал» или «соединил».
|
||||
|
||||
## Практика
|
||||
|
||||
Белый камень вклинился между двумя чёрными группами, но он в атари. Снимите
|
||||
его — и группы соединятся сами.
|
||||
|
||||
<go-task data-task-id="lsn-connect">Запасной текст: попробуйте решить задачу (нужен включённый JavaScript).</go-task>
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Связанная группа сильнее суммы частей.
|
||||
- Косуми само по себе неразрезаемо, но уязвимо при сильных камнях вокруг.
|
||||
- Разрезая, позаботьтесь о жизни разрезающего камня.
|
||||
70
apps/web/src/content/lessons/07-ugly-storony-tsentr.md
Normal file
70
apps/web/src/content/lessons/07-ugly-storony-tsentr.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
title: 'Углы, стороны, центр'
|
||||
section: 'Углы, стороны, центр'
|
||||
order: 1
|
||||
summary: 'Почему партия начинается с углов, как край доски работает готовой стеной, и что такое линии доски.'
|
||||
---
|
||||
|
||||
# Углы, стороны, центр
|
||||
|
||||
## Неравенство частей доски
|
||||
|
||||
Территория в Го строится у краёв доски, потому что сам край работает как
|
||||
готовая стена. Сравните, сколько стен нужно построить, чтобы оградить
|
||||
территорию:
|
||||
|
||||
- **Угол**: два края доски — уже две готовые стены, достроить остаётся две.
|
||||
- **Сторона**: один край — одна готовая стена, строить придётся три.
|
||||
- **Центр**: краёв нет — нужны все четыре стены.
|
||||
|
||||
Отсюда знаменитый порядок начала партии: **сначала углы, потом стороны,
|
||||
потом центр**. Новичок, тянущийся в центр с первых ходов, строит забор
|
||||
посреди поля — дорого и бесполезно.
|
||||
|
||||
## Линии доски
|
||||
|
||||
У линий доски есть имена и характер:
|
||||
|
||||
- **Первая линия** — край доски: у камня на ней всего три дамэ, в дебюте
|
||||
туда играть не стоит.
|
||||
- **Вторая линия** — «линия поражения»: территория есть, но мала и уязвима.
|
||||
- **Третья линия** — «линия территории»: оптимум для ограждения земли.
|
||||
- **Четвёртая линия** — «линия влияния»: территории меньше, зато больше
|
||||
давления на центр и стороны.
|
||||
|
||||
Классический баланс дебюта — игра на третьей и четвёртой линиях.
|
||||
|
||||
## Ключевые пункты угла
|
||||
|
||||
- **3-3** (сан-сан): камень глубоко в углу. Надёжно забирает угол, но низко,
|
||||
мало влияния.
|
||||
- **3-4** (комоку): самый популярный первый ход. Угол почти ваш, остаётся
|
||||
гибкость.
|
||||
- **4-4** (хоси): звёздный пункт. Угол можно оспорить (вторжение 3-3), зато
|
||||
камень сильнее тянется к центру.
|
||||
- **3-5** (мокухадзуси) и **4-5** (такамоку) — реже, с уклоном в сторону
|
||||
и влияние соответственно.
|
||||
|
||||
## Что делает центр полезным
|
||||
|
||||
Центр не даёт много территории напрямую, но камни в центре:
|
||||
|
||||
- перерезают пути бегства и соединения;
|
||||
- усиливают вторжения и погони (лестницы!);
|
||||
- превращают соседние стороны в большие рамки (**мойо**).
|
||||
|
||||
Центр — это сила, а не земля. Играть туда стоит, когда углы и стороны уже
|
||||
заняты и началась борьба.
|
||||
|
||||
## Практический рецепт для новичка
|
||||
|
||||
1. Первые ходы — в свободные углы (3-4 или 4-4).
|
||||
2. Дальше — подходы к углам и задержки по сторонам.
|
||||
3. В центр — только с конкретной целью: атака, спасение, перерезание.
|
||||
4. Никогда не играйте на первой-второй линии в дебюте без причины.
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Край доски — бесплатная стена; центр её лишён.
|
||||
- Порядок дебюта: углы → стороны → центр.
|
||||
- Третья линия — территория, четвёртая — влияние.
|
||||
82
apps/web/src/content/lessons/08-bazovye-dzyoseki.md
Normal file
82
apps/web/src/content/lessons/08-bazovye-dzyoseki.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
title: 'Базовые дзёсэки'
|
||||
section: 'Базовые дзёсэки'
|
||||
order: 1
|
||||
summary: 'Что такое дзёсэки, зачем их учить, и три простейших угловых образца: занятие угла 3-3, цукэ-хики и вторжение 3-3.'
|
||||
---
|
||||
|
||||
# Базовые дзёсэки
|
||||
|
||||
## Что такое дзёсэки
|
||||
|
||||
**Дзёсэки** — устоявшаяся «правильная» последовательность ходов в углу,
|
||||
проверенная поколениями игроков. Итог дзёсэки считается равным (или
|
||||
почти равным) для обеих сторон: один получает угол, другой — стену или
|
||||
инициативу.
|
||||
|
||||
Зачем учить дзёсэки новичку? Не для зазубривания, а чтобы:
|
||||
|
||||
- не проигрывать угол за пять ходов из-за типовой ошибки;
|
||||
- понимать типичные формы: где слабость, где разрез, где жизненная точка;
|
||||
- освободить внимание для борьбы в других местах доски.
|
||||
|
||||
Важно: дзёсэки — не догма. «Правильный» ход зависит от всей доски; на 9×9
|
||||
влияние центра сильнее, чем на 19×19, и многие классические дзёсэки там
|
||||
ведут себя иначе. Учите идею, а не только порядок ходов.
|
||||
|
||||
## Дзёсэки 1: занятие угла 3-3
|
||||
|
||||
Простейший способ забрать угол — поставить камень прямо на пункт 3-3.
|
||||
Соперник прижмёт сверху, вы ответите по краю:
|
||||
|
||||
```
|
||||
A B C D E
|
||||
1 . . . . .
|
||||
2 . . W . .
|
||||
3 . . B . .
|
||||
4 . . . . .
|
||||
```
|
||||
|
||||
Чёрный камень на C3 почти неуязвим: у него сразу задел на угол.
|
||||
Дальше белые обычно давят снаружи, а чёрные ползут по второй-третьей линии,
|
||||
выстраивая жизнь. Идея: **угол — мой, влияние — ваше**.
|
||||
|
||||
## Дзёсэки 2: цукэ-хики — прижатие и отступление
|
||||
|
||||
Чёрные заняли угол ходом 3-4, белые подошли к нему. Классический образец —
|
||||
**цукэ-хики**: чёрные прижимаются к подошедшему камню (**цукэ**), белые
|
||||
отвечают **ханэ** (изгибом вокруг чёрного камня), а чёрные спокойно
|
||||
отступают (**хики**):
|
||||
|
||||
```
|
||||
A B C D E
|
||||
1 . . . . .
|
||||
2 . . B . .
|
||||
3 . B W . .
|
||||
4 . . . . .
|
||||
```
|
||||
|
||||
Хики укрепляет угол чёрных, белые получают внешнюю позицию — это один из
|
||||
первых дзёсэки, которые стоит узнать новичку. Ключевой урок:
|
||||
**отступление — не трусость**, а способ сохранить форму без разрезов.
|
||||
|
||||
## Дзёсэки 3: вторжение 3-3 под хоси
|
||||
|
||||
Если соперник начал с 4-4 (хоси), угол ещё не закрыт — вторгайтесь на 3-3.
|
||||
Дальше развивается типовая борьба: хозяин хоси давит с двух сторон,
|
||||
вторгшийся ползёт по краю и живёт маленькой группой. Хозяин строит внешнюю
|
||||
стену. Итог: земля против влияния, равенство.
|
||||
|
||||
## Как относиться к дзёсэки на практике
|
||||
|
||||
1. Знайте два-три образца для каждого углового пункта — этого хватит надолго.
|
||||
2. После каждой партии смотрите: не вышел ли угол «криво»? Если да —
|
||||
найдите, где отступили от образца.
|
||||
3. Помните, что дзёсэки обновляются: профессионалы постоянно находят новые
|
||||
варианты, а с появлением сильных программ многие оценки изменились.
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Дзёсэки — эталонные угловые размены, равные для обеих сторон.
|
||||
- Учите смысл ходов, а не только их порядок.
|
||||
- На малой доске классические дзёсэки работают с поправкой на центр.
|
||||
84
apps/web/src/content/lessons/09-forma.md
Normal file
84
apps/web/src/content/lessons/09-forma.md
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
---
|
||||
title: 'Форма'
|
||||
section: 'Форма'
|
||||
order: 1
|
||||
summary: 'Хорошие и плохие формы камней: тигровая пасть, бамбук, пустой треугольник, данго. Как форма влияет на эффективность.'
|
||||
---
|
||||
|
||||
# Форма
|
||||
|
||||
## Что такое форма
|
||||
|
||||
Два игрока могут поставить одинаковое число камней, но у одного они будут
|
||||
работать на все сто процентов, а у другого — вполсилы. Разница — в **форме**:
|
||||
в том, насколько камни связаны, гибки и лишены слабостей. Хорошая форма
|
||||
экономит ходы; плохая форма тащит лишний вес.
|
||||
|
||||
## Хорошие формы
|
||||
|
||||
**Тигровая пасть (кошачья пасть)** — три камня вокруг пустого пункта:
|
||||
|
||||
```
|
||||
A B C
|
||||
1 . B .
|
||||
2 B . .
|
||||
3 . B .
|
||||
```
|
||||
|
||||
Пустой пункт — почти соединение: если противник вклинится туда, вы ответите
|
||||
и соединитесь окончательно. Пасть защищает разрез одним камнем.
|
||||
|
||||
**Бамбук (такэфу)** — два камня вплотную и ещё два через пункт:
|
||||
|
||||
```
|
||||
A B C D E
|
||||
1 B B . B B
|
||||
2 . . . . .
|
||||
```
|
||||
|
||||
Связь короткая, пружинящая: разрезать бамбук почти невозможно, а тянется он
|
||||
быстро.
|
||||
|
||||
**Вытягивание (ноби)** — простой ход вперёд от своего камня. Скромный, но
|
||||
самый надёжный способ добавить дамэ и не создать слабостей.
|
||||
|
||||
## Плохие формы
|
||||
|
||||
**Пустой треугольник** — три своих камня треугольником вокруг пустого пункта,
|
||||
который ничего не защищает:
|
||||
|
||||
```
|
||||
A B C
|
||||
1 . B .
|
||||
2 B B .
|
||||
```
|
||||
|
||||
Три камня делают работу двух: тот же пункт можно было прикрыть экономнее.
|
||||
Поговорка гласит: «пустой треугольник — не ставь никогда».
|
||||
|
||||
**Данго** — «пельменная форма»: бесформенный ком камней без глаз и с малым
|
||||
числом дамэ. Такая масса тяжела: её легко атаковать, а камни в ней работают
|
||||
плохо. Данго — признак того, что вас гонят, а вы просто соединяетесь, не
|
||||
думая.
|
||||
|
||||
**Перегруппировка** — слишком много камней в малой области: они мешают друг
|
||||
другу строить глаза и дают противнику лишние точки атаки.
|
||||
|
||||
## Как вырабатывать вкус формы
|
||||
|
||||
1. После каждого хода спрашивайте: «Не пустой ли это треугольник?»
|
||||
2. Предпочитайте ходы, которые делают две вещи сразу: соединяют и строят
|
||||
глаз, атакуют и укрепляются.
|
||||
3. Смотрите на свои группы целиком: есть ли у них «головы» (выход наружу),
|
||||
«ноги» (опора у края) и место для глаз?
|
||||
4. Пересматривайте свои партии и отмечайте тяжёлые формы — со временем они
|
||||
начнут сами резать глаз.
|
||||
|
||||
Форма — это эстетика, проверенная логикой: красивый ход в Го почти всегда
|
||||
оказывается и сильным.
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Тигровая пасть и бамбук — образцы экономной защиты.
|
||||
- Пустой треугольник и данго — типичные ошибки новичка.
|
||||
- Хорошая форма = связность + гибкость + потенциал глаз.
|
||||
73
apps/web/src/content/lessons/10-prostoe-yose.md
Normal file
73
apps/web/src/content/lessons/10-prostoe-yose.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
title: 'Простое ёсэ'
|
||||
section: 'Простое ёсэ'
|
||||
order: 1
|
||||
summary: 'Эндшпиль по-гошному: ханэ на первой линии, сэнтэ и готэ, почему мелкие ходы в конце решают партию.'
|
||||
---
|
||||
|
||||
# Простое ёсэ
|
||||
|
||||
## Что такое ёсэ
|
||||
|
||||
**Ёсэ** — эндшпиль: стадия, когда большие территории уже очерчены и игроки
|
||||
уточняют границы. Ходы ёсэ обычно мельче ходов миттельшпиля, но среди них
|
||||
бывают и дорогие: комбинация ханэ у края может стоить около десяти очков.
|
||||
Партия между равными часто решается именно здесь. Пропустить пару ходов
|
||||
ёсэ — значит проиграть выигранную партию.
|
||||
|
||||
## Ханэ на первой линии
|
||||
|
||||
Классический приём ёсэ — **ханэ у края**: ход, изгибающийся вокруг камня
|
||||
противника на первой линии:
|
||||
|
||||
```
|
||||
A B C D
|
||||
8 B W . .
|
||||
9 B W . .
|
||||
```
|
||||
|
||||
Ханэ отодвигает границу на один пункт в вашу пользу. Если соперник ответит —
|
||||
вы сохранили инициативу; если нет — вы продолжаете ползти дальше. Пара ханэ
|
||||
«с двух сторон» одной и той же границы стоит уже несколько очков.
|
||||
|
||||
## Сэнтэ и готэ
|
||||
|
||||
- **Сэнтэ** — ход, требующий ответа: после него инициатива (право ходить
|
||||
первым в новом месте) остаётся у вас.
|
||||
- **Готэ** — ход, на который можно не отвечать: инициатива переходит
|
||||
сопернику.
|
||||
|
||||
Правило ёсэ: **сначала играйте сэнтэ-ходы, потом готэ.** Сэнтэ бесплатен:
|
||||
соперник ответит, и вы снова выбираете, куда ходить. Готэ-ход «покупает»
|
||||
пункты ценой инициативы — берите его, когда сэнтэ кончились.
|
||||
|
||||
## Как оценивать ходы ёсэ
|
||||
|
||||
Считайте разницу «мы сыграли здесь / соперник сыграл здесь». Если ваш ход
|
||||
даёт +2 очка вам, а ход соперника там же дал бы +2 ему, ценность пункта —
|
||||
4 очка. Берите самые дорогие пункты первыми. Когда останутся только
|
||||
одноочковые размены (**дамэ** — нейтральные пункты), партия близка к концу.
|
||||
|
||||
## Типичные ошибки новичка в ёсэ
|
||||
|
||||
1. Играть в свою территорию «для надёжности» — ход ничего не защищает,
|
||||
а инициативу отдаёт.
|
||||
2. Отвечать на готэ-угрозы — соперник даром получает темп.
|
||||
3. Не добрать последние атари: мёртвые на вид камни иногда спасаются
|
||||
на одну темповую ошибку.
|
||||
|
||||
Хорошая привычка на 9×9 — за десяток ходов до конца мысленно прикинуть
|
||||
счёт: это подскажет, нужен ли спокойный ёсэ или пора рисковать.
|
||||
|
||||
## Практика
|
||||
|
||||
Чёрные прижимают белых к самому краю: краевая погоня в духе ёсэ заканчивается
|
||||
захватом двух камней. Найдите последовательность до конца.
|
||||
|
||||
<go-task data-task-id="lsn-yose">Запасной текст: попробуйте решить задачу (нужен включённый JavaScript).</go-task>
|
||||
|
||||
## Запомнить
|
||||
|
||||
- Ёсэ — игра за очки на границах; мелочей не бывает.
|
||||
- Сэнтэ раньше готэ; считайте ценность каждого пункта.
|
||||
- Ханэ на первой линии — рабочая лошадка эндшпиля.
|
||||
284
apps/web/src/content/tasks/lessons.json
Normal file
284
apps/web/src/content/tasks/lessons.json
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
[
|
||||
{
|
||||
"id": "lsn-dame-capture",
|
||||
"kind": "lesson",
|
||||
"title": "Последнее дамэ",
|
||||
"topics": ["атари", "захват"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ee];B[ef])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "У белого камня осталось одно дамэ — займите его."
|
||||
},
|
||||
{
|
||||
"id": "lsn-ladder",
|
||||
"kind": "lesson",
|
||||
"title": "Лестница у края",
|
||||
"topics": ["лестница", "атари"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[cb];B[db];W[ca];B[ba];W[da];B[ea])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Гоните камень к краю: каждое атари оставляет белым один путь."
|
||||
},
|
||||
{
|
||||
"id": "lsn-ko",
|
||||
"kind": "lesson",
|
||||
"title": "Захват в ко",
|
||||
"topics": ["захват"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 6
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ee];B[ef];W[aa];B[ee])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Снимите камень — белые не смогут вернуть его сразу: это ко."
|
||||
},
|
||||
{
|
||||
"id": "lsn-false-eye",
|
||||
"kind": "lesson",
|
||||
"title": "Ложный глаз",
|
||||
"topics": ["глаза", "захват"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[bc][cb];B[bb];W[ii])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Камни вокруг «глаза» не связаны — займите центр и снимите два камня."
|
||||
},
|
||||
{
|
||||
"id": "lsn-endgame-capture",
|
||||
"kind": "lesson",
|
||||
"title": "Чистка территории",
|
||||
"topics": ["захват", "ёсэ"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[dd][ed];B[ee])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Два белых камня в атари — доберите их перед подсчётом."
|
||||
},
|
||||
{
|
||||
"id": "lsn-connect",
|
||||
"kind": "lesson",
|
||||
"title": "Соединение через разрез",
|
||||
"topics": ["связь", "разрезание"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]CR[dc][de];B[cd];W[bd])",
|
||||
"goal": {
|
||||
"type": "connect"
|
||||
},
|
||||
"hint": "Снимите разрезающий камень — группы соединятся сами."
|
||||
},
|
||||
{
|
||||
"id": "lsn-yose",
|
||||
"kind": "lesson",
|
||||
"title": "Ёсэ у края",
|
||||
"topics": ["ёсэ", "захват"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 7
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 8
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ah][ai];B[ag];W[bi];B[ci])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Прижмите белых к краю: они не убегут."
|
||||
}
|
||||
]
|
||||
751
apps/web/src/content/tasks/tsumego-atari-zahvat.json
Normal file
751
apps/web/src/content/tasks/tsumego-atari-zahvat.json
Normal file
|
|
@ -0,0 +1,751 @@
|
|||
[
|
||||
{
|
||||
"id": "tsm-atari-corner",
|
||||
"kind": "tsumego",
|
||||
"title": "Атари в углу",
|
||||
"topics": ["атари", "захват"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[aa];B[ab])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "У камня в углу всего два дамэ, одно уже занято."
|
||||
},
|
||||
{
|
||||
"id": "tsm-atari-edge",
|
||||
"kind": "tsumego",
|
||||
"title": "Атари на краю",
|
||||
"topics": ["атари"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ae];B[af])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Осталось одно дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-atari-center",
|
||||
"kind": "tsumego",
|
||||
"title": "Одинокий камень",
|
||||
"topics": ["атари", "захват"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ee];B[ef])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Закройте последнее дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-capture-pair",
|
||||
"kind": "tsumego",
|
||||
"title": "Два камня в сети",
|
||||
"topics": ["захват"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ee][ef];B[eg])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "У группы из двух камней одно общее дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-capture-edge-pair",
|
||||
"kind": "tsumego",
|
||||
"title": "Пара у края",
|
||||
"topics": ["захват", "атари"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ad][ae];B[af])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Край доски не даёт лишних дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-ladder-edge",
|
||||
"kind": "tsumego",
|
||||
"title": "Лестница к углу",
|
||||
"topics": ["лестница"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 5,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 6,
|
||||
"y": 1
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[gb];B[hb];W[ga];B[fa];W[ha];B[ia])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Атари за атари — белые упираются в угол."
|
||||
},
|
||||
{
|
||||
"id": "tsm-double-atari",
|
||||
"kind": "tsumego",
|
||||
"title": "Двойное атари",
|
||||
"topics": ["атари", "захват"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[dc];B[dd];W[ce];B[cc])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Один ход — два атари; белые спасут лишь один камень."
|
||||
},
|
||||
{
|
||||
"id": "tsm-liberties-escape",
|
||||
"kind": "tsumego",
|
||||
"title": "Выход из атари",
|
||||
"topics": ["атари"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ee];B[fe];W[ge])",
|
||||
"goal": {
|
||||
"type": "liberties",
|
||||
"count": 3
|
||||
},
|
||||
"hint": "Вытяните камень — пусть у группы станет три дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-kill-corner",
|
||||
"kind": "tsumego",
|
||||
"title": "Угол без глаз",
|
||||
"topics": ["захват", "жизнь и смерть"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[aa][ba];B[bb];W[ab];B[ac])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Займите точку глаза — белым некуда бежать."
|
||||
},
|
||||
{
|
||||
"id": "tsm-ladder-down",
|
||||
"kind": "tsumego",
|
||||
"title": "Лестница вниз",
|
||||
"topics": ["лестница"],
|
||||
"difficulty": 3,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 6
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 7
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ch];B[dh];W[ci];B[bi];W[di];B[ei])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Та же лестница, но к нижнему краю."
|
||||
},
|
||||
{
|
||||
"id": "tsm-capture-three-corner",
|
||||
"kind": "tsumego",
|
||||
"title": "Тройка в углу",
|
||||
"topics": ["захват", "жизнь и смерть"],
|
||||
"difficulty": 3,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[aa][ba][bb];B[bc];W[ii];B[ab])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Белые не могут выйти: любое продление — самоубийство."
|
||||
},
|
||||
{
|
||||
"id": "tsm-liberties-wall",
|
||||
"kind": "tsumego",
|
||||
"title": "Прорвите стену",
|
||||
"topics": ["атари", "жизнь и смерть"],
|
||||
"difficulty": 3,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ec][ed];B[ee];W[de])",
|
||||
"goal": {
|
||||
"type": "liberties",
|
||||
"count": 4
|
||||
},
|
||||
"hint": "Вытяните группу вниз — нужно четыре дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-ko-fight",
|
||||
"kind": "tsumego",
|
||||
"title": "Выигранное ко",
|
||||
"topics": ["захват"],
|
||||
"difficulty": 4,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 6,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 7,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 6,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 7,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 6
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ge];B[gf];W[aa];B[ge])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Начните ко — у белых нет угроз, закройте его."
|
||||
},
|
||||
{
|
||||
"id": "tsm-double-atari-save",
|
||||
"kind": "tsumego",
|
||||
"title": "Двойная угроза",
|
||||
"topics": ["атари", "захват"],
|
||||
"difficulty": 4,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[dd];B[de](;W[dg])(;W[ii]))",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Захват и атари одним ходом — белые не спасут оба камня."
|
||||
},
|
||||
{
|
||||
"id": "tsm-corner-chase",
|
||||
"kind": "tsumego",
|
||||
"title": "Погоня по краю",
|
||||
"topics": ["захват", "жизнь и смерть"],
|
||||
"difficulty": 4,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ae][af][bf];B[bg];W[ag];B[ah])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Сокращайте дамэ по очереди — край не оставит места."
|
||||
},
|
||||
{
|
||||
"id": "tsm-capture-race",
|
||||
"kind": "tsumego",
|
||||
"title": "Гонка захватов",
|
||||
"topics": ["захват", "жизнь и смерть"],
|
||||
"difficulty": 4,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 6,
|
||||
"y": 8
|
||||
},
|
||||
{
|
||||
"x": 7,
|
||||
"y": 8
|
||||
},
|
||||
{
|
||||
"x": 7,
|
||||
"y": 6
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 8,
|
||||
"y": 8
|
||||
},
|
||||
{
|
||||
"x": 8,
|
||||
"y": 7
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ih][ii];B[hh];W[ig];B[if])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "У белых два дамэ, у вас темп — начинайте первым."
|
||||
},
|
||||
{
|
||||
"id": "tsm-ko-threat",
|
||||
"kind": "tsumego",
|
||||
"title": "Ко с угрозой",
|
||||
"topics": ["захват"],
|
||||
"difficulty": 5,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 7
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[df];B[dg];W[ii];B[df])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Захватите ко, переждите угрозу и закройте его."
|
||||
},
|
||||
{
|
||||
"id": "tsm-chase-six",
|
||||
"kind": "tsumego",
|
||||
"title": "Шесть камней к краю",
|
||||
"topics": ["захват", "жизнь и смерть"],
|
||||
"difficulty": 5,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ab][ac][ad][ae][af];B[ag];W[aa];B[ba])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Выберите правильный конец — второй ведёт в угол."
|
||||
},
|
||||
{
|
||||
"id": "tsm-liberties-five",
|
||||
"kind": "tsumego",
|
||||
"title": "Пять дамэ",
|
||||
"topics": ["атари", "жизнь и смерть"],
|
||||
"difficulty": 5,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ee][ef];B[ed];W[eg];B[ec])",
|
||||
"goal": {
|
||||
"type": "liberties",
|
||||
"count": 5
|
||||
},
|
||||
"hint": "Одного продления мало — вытягивайтесь дважды."
|
||||
}
|
||||
]
|
||||
432
apps/web/src/content/tasks/tsumego-glaza.json
Normal file
432
apps/web/src/content/tasks/tsumego-glaza.json
Normal file
|
|
@ -0,0 +1,432 @@
|
|||
[
|
||||
{
|
||||
"id": "tsm-eyes-three",
|
||||
"kind": "tsumego",
|
||||
"title": "Три в ряд",
|
||||
"topics": ["глаза", "жизнь и смерть"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 5
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ba][ac][cc][be];B[bc])",
|
||||
"goal": {
|
||||
"type": "two-eyes"
|
||||
},
|
||||
"hint": "Центральная точка делит пространство на два глаза."
|
||||
},
|
||||
{
|
||||
"id": "tsm-eyes-corner-five",
|
||||
"kind": "tsumego",
|
||||
"title": "Пять точек в углу",
|
||||
"topics": ["глаза", "жизнь и смерть"],
|
||||
"difficulty": 3,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[bb][db][cd];B[ba])",
|
||||
"goal": {
|
||||
"type": "two-eyes"
|
||||
},
|
||||
"hint": "Разделите пространство на глаз и глаз."
|
||||
},
|
||||
{
|
||||
"id": "tsm-eyes-side-resist",
|
||||
"kind": "tsumego",
|
||||
"title": "Два глаза на стороне",
|
||||
"topics": ["глаза", "жизнь и смерть"],
|
||||
"difficulty": 4,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 5,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ab][cb][ea];B[ba];W[ca];B[da])",
|
||||
"goal": {
|
||||
"type": "two-eyes"
|
||||
},
|
||||
"hint": "Разделите пространство; на вторжение отвечайте захватом."
|
||||
},
|
||||
{
|
||||
"id": "tsm-eyes-bottom-resist",
|
||||
"kind": "tsumego",
|
||||
"title": "Глаза на нижнем краю",
|
||||
"topics": ["глаза", "жизнь и смерть"],
|
||||
"difficulty": 4,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 8
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 8
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ah][ch][ei];B[ci];W[bi];B[ai])",
|
||||
"goal": {
|
||||
"type": "two-eyes"
|
||||
},
|
||||
"hint": "Правильное деление даёт два глаза даже после вторжения."
|
||||
},
|
||||
{
|
||||
"id": "tsm-eyes-tee",
|
||||
"kind": "tsumego",
|
||||
"title": "Т-образное пространство",
|
||||
"topics": ["глаза", "жизнь и смерть"],
|
||||
"difficulty": 5,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 7,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 7,
|
||||
"y": 0
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[db][fb][ed];B[eb])",
|
||||
"goal": {
|
||||
"type": "two-eyes"
|
||||
},
|
||||
"hint": "Центральная точка превращает Т-форму в два глаза."
|
||||
}
|
||||
]
|
||||
254
apps/web/src/content/tasks/tsumego-svyaz.json
Normal file
254
apps/web/src/content/tasks/tsumego-svyaz.json
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
[
|
||||
{
|
||||
"id": "tsm-connect-gap",
|
||||
"kind": "tsumego",
|
||||
"title": "Закройте щель",
|
||||
"topics": ["связь"],
|
||||
"difficulty": 1,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]CR[cc][ce];B[cd])",
|
||||
"goal": {
|
||||
"type": "connect"
|
||||
},
|
||||
"hint": "Соедините свои камни до того, как белые разрежут."
|
||||
},
|
||||
{
|
||||
"id": "tsm-connect-cut-stone",
|
||||
"kind": "tsumego",
|
||||
"title": "Снимите разрезающий камень",
|
||||
"topics": ["связь", "разрезание"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]CR[cc][ce];B[dd];W[ed];B[cd])",
|
||||
"goal": {
|
||||
"type": "connect"
|
||||
},
|
||||
"hint": "Сначала снимите вклинившийся камень, потом соединитесь."
|
||||
},
|
||||
{
|
||||
"id": "tsm-cut-wedge",
|
||||
"kind": "tsumego",
|
||||
"title": "Вклинивание",
|
||||
"topics": ["разрезание", "захват"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[fd];B[ed])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Встаньте между белыми камнями — слабый погибнет."
|
||||
},
|
||||
{
|
||||
"id": "tsm-connect-choice",
|
||||
"kind": "tsumego",
|
||||
"title": "Единственная связь",
|
||||
"topics": ["связь"],
|
||||
"difficulty": 3,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 1,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]CR[bc][dd];B[cd];W[ce])",
|
||||
"goal": {
|
||||
"type": "connect"
|
||||
},
|
||||
"hint": "Соединяйтесь снизу — сверху стоит белый камень."
|
||||
},
|
||||
{
|
||||
"id": "tsm-connect-atari",
|
||||
"kind": "tsumego",
|
||||
"title": "Связь с атари",
|
||||
"topics": ["связь", "атари"],
|
||||
"difficulty": 3,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 5,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]CR[dd][fe];B[ed](;W[ef])(;W[ii];B[ef]))",
|
||||
"goal": {
|
||||
"type": "connect"
|
||||
},
|
||||
"hint": "Ход соединяет группы и одновременно ставит атари."
|
||||
},
|
||||
{
|
||||
"id": "tsm-connect-through",
|
||||
"kind": "tsumego",
|
||||
"title": "Соединение сквозь клин",
|
||||
"topics": ["связь", "разрезание"],
|
||||
"difficulty": 5,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 5
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 2,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 4
|
||||
},
|
||||
{
|
||||
"x": 4,
|
||||
"y": 2
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
{
|
||||
"x": 3,
|
||||
"y": 4
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]CR[db][dg];B[cd];W[ed];B[fd];W[ii];B[dd];W[ih];B[de])",
|
||||
"goal": {
|
||||
"type": "connect"
|
||||
},
|
||||
"hint": "Загоните клин в атари, доберите — и заполните брешь."
|
||||
}
|
||||
]
|
||||
108
apps/web/src/content/tasks/tsumego-yose-joseki.json
Normal file
108
apps/web/src/content/tasks/tsumego-yose-joseki.json
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
[
|
||||
{
|
||||
"id": "tsm-yose-edge",
|
||||
"kind": "tsumego",
|
||||
"title": "Дожим на первой линии",
|
||||
"topics": ["ёсэ", "захват"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 7,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 7,
|
||||
"y": 7
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 8,
|
||||
"y": 6
|
||||
},
|
||||
{
|
||||
"x": 8,
|
||||
"y": 7
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ig][ih];B[if];W[ii];B[hi])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Край помогает: у белых всё меньше дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-joseki-corner",
|
||||
"kind": "tsumego",
|
||||
"title": "Наказание в углу 3-3",
|
||||
"topics": ["дзёсэки", "захват"],
|
||||
"difficulty": 2,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 1
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 1
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[aa][ba][ab];B[ac])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Белые ошиблись в дзёсэки — у группы одно дамэ."
|
||||
},
|
||||
{
|
||||
"id": "tsm-yose-hane",
|
||||
"kind": "tsumego",
|
||||
"title": "Ханэ в углу",
|
||||
"topics": ["ёсэ", "захват"],
|
||||
"difficulty": 3,
|
||||
"size": 9,
|
||||
"toPlay": "black",
|
||||
"setupBlack": [
|
||||
{
|
||||
"x": 7,
|
||||
"y": 8
|
||||
},
|
||||
{
|
||||
"x": 6,
|
||||
"y": 7
|
||||
}
|
||||
],
|
||||
"setupWhite": [
|
||||
{
|
||||
"x": 8,
|
||||
"y": 7
|
||||
},
|
||||
{
|
||||
"x": 8,
|
||||
"y": 8
|
||||
}
|
||||
],
|
||||
"sgf": "(;GM[1]SZ[9]TR[ih][ii];B[ig];W[hh];B[hg])",
|
||||
"goal": {
|
||||
"type": "capture-target"
|
||||
},
|
||||
"hint": "Прижмите к краю и доберите."
|
||||
}
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue