diff --git a/.gitignore b/.gitignore index efbc4095..f4a010bf 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,6 @@ testem.log ._* .AppleDouble .LSOverride -Icon? Thumbs.db # neutralino diff --git a/README.md b/README.md index 9745bb52..f0ea9c5d 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The original open-source Mahjong Solitaire game powering many Mahjong experience 🖼️ **Massive visual customization** - 8 image backgrounds, 375 pattern backgrounds, light/dark mode, 14 color themes -🏆 **3 difficulty levels** - from relaxed casual play to expert-level challenge +🏆 **Difficulty levels** - from relaxed casual play to expert-level challenge 💾 **Auto-save** - your game state and best times are saved locally in your browser, never to the cloud @@ -111,7 +111,7 @@ Most modern phones use `arm64`. Try these APK variants in order: ## 🙏 Acknowledgements -Mah's art is built on open-source creative work. See the credits for [artwork](src/assets/svg/README.md), [backgrounds](src/assets/img/README.md), [sounds](src/assets/sounds/README.md), and [fonts](src/fonts/README.md). +Mah's art is built on open-source creative work. See the credits for [artwork](src/assets/svg/README.md), [backgrounds](src/assets/img/README.md), [sounds](src/assets/sounds/README.md), [icons](src/app/components/icons/README.md) and [fonts](src/fonts/README.md). --- diff --git a/angular.json b/angular.json index 38899df2..ea562210 100644 --- a/angular.json +++ b/angular.json @@ -33,8 +33,6 @@ "src/assets" ], "styles": [ - "src/fonts/fontello/css/mah.css", - "src/fonts/editor/css/editor.css", "src/fonts/kulim-park/css/kulim-park.css", "src/styles.scss" ], diff --git a/resources/images/svg-to-png.mjs b/resources/images/svg-to-png.mjs index 790bb204..a769efc5 100644 --- a/resources/images/svg-to-png.mjs +++ b/resources/images/svg-to-png.mjs @@ -573,7 +573,7 @@ async function main() { const sample = nameGrid.flat().filter(Boolean).slice(0, 5).join(", "); console.log(`[t_preview] Detected layout ${cols}x${rows}; sample names: ${sample}`); } else { - console.log("[t_preview] Not found or unparsable — used fallback grid."); + console.log("[t_preview] Not found or unparsable - used fallback grid."); } } } diff --git a/src/app/components/choose-layout/choose-layout.component.html b/src/app/components/choose-layout/choose-layout.component.html index 0578ff65..13ca9bd3 100644 --- a/src/app/components/choose-layout/choose-layout.component.html +++ b/src/app/components/choose-layout/choose-layout.component.html @@ -1,24 +1,22 @@
- - @for (m of buildModes; track m) { - + }
- - @for (m of gameModes; track m) { - + }
@@ -27,3 +25,36 @@
+@if (activeInfo()) { +
+
+ + @if (activeInfo() === 'generator') { +

{{ 'BOARD_GENERATOR' | translate }}

+ @for (m of buildModes; track m) { +
+ {{ m.id | translate }} + {{ m.id + '_DESC' | translate }} +
+ } + } + @if (activeInfo() === 'mode') { +

{{ 'GAME_MODE' | translate }}

+ @for (m of gameModes; track m) { +
+ {{ m.id | translate }} + @if (m.features.length > 0) { +
    + @for (f of m.features; track f) { +
  • {{ f.title + '_LONG' | translate }}
  • + } +
+ } @else { + {{ 'GAME_MODE_NO_HELPERS' | translate }} + } +
+ } + } +
+
+} diff --git a/src/app/components/choose-layout/choose-layout.component.scss b/src/app/components/choose-layout/choose-layout.component.scss index 7926b4d8..e1293471 100644 --- a/src/app/components/choose-layout/choose-layout.component.scss +++ b/src/app/components/choose-layout/choose-layout.component.scss @@ -8,6 +8,7 @@ display: flex; flex-direction: column; overflow: hidden; + position: relative; .choose-buttons { padding-top: 10px; @@ -25,8 +26,11 @@ flex: 1; label { - display: block; - margin-bottom: 2px; + padding: 1px 5px 5px; + display: flex; + align-items: center; + user-select: none; + gap: 4px; } select { @@ -34,16 +38,6 @@ } } - .mode { - max-width: 30%; - } - - @include mixins.respond-to-height(medium-down) { - .mode { - max-width: 50%; - } - } - @include mixins.respond-to-height(small-down) { padding-top: 4px; } @@ -65,7 +59,7 @@ align-items: unset; label { - font-size: 0.7em; + font-size: 0.9em; } .mode { @@ -77,5 +71,82 @@ } } } + + label.info-label { + cursor: pointer; + transition: color 0.15s; + + &:hover { + color: var(--text-highlight-color); + } + } + + .info-overlay { + position: fixed; + inset: 0; + background: rgb(0 0 0 / 40%); + z-index: 100; + display: flex; + align-items: center; + justify-content: center; + + .info-popup { + position: relative; + background: var(--dialog-background-color); + border: 1px solid var(--dialog-border-color); + border-radius: 12px; + padding: 1.2em 1.5em 1em; + max-width: 90%; + max-height: 90%; + overflow-y: auto; + box-shadow: var(--overlay-popup-shadow); + color: var(--main-content-text-color); + + h2 { + margin: 0 0 0.8em; + font-size: 1em; + color: var(--dialog-headline-color); + text-align: center; + } + + .close { + position: absolute; + top: 0.5em; + right: 0.6em; + cursor: pointer; + color: var(--close-color); + line-height: 1; + + &:hover { + color: var(--close-color-hover); + } + } + + .info-item { + padding: 0.5em 0; + border-bottom: 1px solid var(--dialog-border-color); + + &:last-child { + border-bottom: none; + padding-bottom: 0; + } + + strong { + display: block; + margin-bottom: 0.2em; + } + + span, ul { + color: var(--main-content-text-color-muted); + font-size: 0.85em; + } + + ul { + margin: 0; + padding-left: 1.2em; + } + } + } + } } diff --git a/src/app/components/choose-layout/choose-layout.component.spec.ts b/src/app/components/choose-layout/choose-layout.component.spec.ts index 30fdbbf7..896373a1 100644 --- a/src/app/components/choose-layout/choose-layout.component.spec.ts +++ b/src/app/components/choose-layout/choose-layout.component.spec.ts @@ -57,8 +57,8 @@ describe('ChooseLayoutComponent', () => { it('should initialize with default values', () => { expect(component.gameMode()).toBe(GAME_MODE_EASY); - expect(component.buildMode).toBe(MODE_SOLVABLE); - expect(component.buildModes).toHaveLength(2); + expect(component.buildMode()).toBe(MODE_SOLVABLE); + expect(component.buildModes).toHaveLength(4); expect(component.gameModes).toHaveLength(3); }); @@ -111,7 +111,7 @@ describe('ChooseLayoutComponent', () => { fixture.detectChanges(); // Assert - expect(component.buildMode).toBe(MODE_RANDOM); + expect(component.buildMode()).toBe(MODE_RANDOM); }); it('should update gameMode when select is changed', () => { diff --git a/src/app/components/choose-layout/choose-layout.component.ts b/src/app/components/choose-layout/choose-layout.component.ts index 0e15be72..441c945f 100644 --- a/src/app/components/choose-layout/choose-layout.component.ts +++ b/src/app/components/choose-layout/choose-layout.component.ts @@ -1,11 +1,13 @@ -import { Component, inject, model, output } from '@angular/core'; -import { type BUILD_MODE_ID, BuilderModes, MODE_SOLVABLE } from '../../model/builder'; +import { Component, inject, model, output, signal } from '@angular/core'; +import { type BUILD_MODE_ID, BuilderModes, MODE_SOLVABLE, solvableModeForGameMode } from '../../model/builder'; import type { Layout } from '../../model/types'; import { LayoutService } from '../../service/layout.service'; import { LocalstorageService } from '../../service/localstorage.service'; import { type GAME_MODE_ID, GameModes } from '../../model/consts'; import { TranslatePipe } from '@ngx-translate/core'; import { LayoutListComponent } from '../layout-list/layout-list.component'; +import { IconInfoComponent } from '../icons/icon-info.component'; +import { IconCloseComponent } from '../icons/icon-close.component'; export interface StartEvent { layout: Layout; @@ -17,20 +19,26 @@ export interface StartEvent { selector: 'app-choose-layout', templateUrl: './choose-layout.component.html', styleUrls: ['./choose-layout.component.scss'], - imports: [LayoutListComponent, TranslatePipe] + imports: [LayoutListComponent, TranslatePipe, IconInfoComponent, IconCloseComponent] }) export class ChooseLayoutComponent { readonly startEvent = output(); readonly gameMode = model.required(); - buildMode: BUILD_MODE_ID = MODE_SOLVABLE; + readonly buildMode = model(MODE_SOLVABLE); buildModes = BuilderModes; gameModes = GameModes; + activeInfo = signal<'generator' | 'mode' | null>(null); layoutService = inject(LayoutService); storage = inject(LocalstorageService); + onGameModeChange(mode: GAME_MODE_ID): void { + this.gameMode.set(mode); + this.buildMode.set(solvableModeForGameMode(mode)); + } + onStart(layout: Layout): void { if (layout) { - this.startEvent.emit({ layout, buildMode: this.buildMode, gameMode: this.gameMode() }); + this.startEvent.emit({ layout, buildMode: this.buildMode(), gameMode: this.gameMode() }); this.storage.storeLastPlayed(layout.id); } } diff --git a/src/app/components/dialog/dialog.component.html b/src/app/components/dialog/dialog.component.html index b8c49a5c..bf45fdf0 100644 --- a/src/app/components/dialog/dialog.component.html +++ b/src/app/components/dialog/dialog.component.html @@ -3,10 +3,10 @@
@if (title()) { -

{{ title() }}

+

{{ title() }}

} @if (!noCloseButton()) { - + }
diff --git a/src/app/components/dialog/dialog.component.ts b/src/app/components/dialog/dialog.component.ts index b6823785..00a43101 100644 --- a/src/app/components/dialog/dialog.component.ts +++ b/src/app/components/dialog/dialog.component.ts @@ -1,11 +1,13 @@ import { Component, input, model, output } from '@angular/core'; import { TranslatePipe } from '@ngx-translate/core'; +import { IconCloseComponent } from '../icons/icon-close.component'; +import { IconLogoComponent } from '../icons/icon-logo.component'; @Component({ selector: 'app-dialog', templateUrl: './dialog.component.html', styleUrls: ['./dialog.component.scss'], - imports: [TranslatePipe] + imports: [TranslatePipe, IconLogoComponent, IconCloseComponent] }) export class DialogComponent { readonly title = input(); diff --git a/src/app/components/game/game-component.component.html b/src/app/components/game/game-component.component.html index 1b38dd42..161dc74d 100644 --- a/src/app/components/game/game-component.component.html +++ b/src/app/components/game/game-component.component.html @@ -1,25 +1,25 @@
@@ -35,21 +35,21 @@
@@ -88,7 +88,7 @@ @if (newgame.visible()) { - + } @@ -105,11 +105,11 @@
} diff --git a/src/app/components/game/game-component.component.scss b/src/app/components/game/game-component.component.scss index 8ad7d877..a363e82a 100644 --- a/src/app/components/game/game-component.component.scss +++ b/src/app/components/game/game-component.component.scss @@ -134,7 +134,7 @@ font-weight: 600; cursor: pointer; - .icon-logo { + app-icon-logo { color: red; } } diff --git a/src/app/components/game/game-component.component.ts b/src/app/components/game/game-component.component.ts index 7534ce0c..750cdfc8 100644 --- a/src/app/components/game/game-component.component.ts +++ b/src/app/components/game/game-component.component.ts @@ -17,6 +17,17 @@ import { BoardComponent } from '../board/board.component'; import { TutorialComponent } from '../tutorial/tutorial.component'; import { DurationPipe } from '../../pipes/duration.pipe'; import { GameModeEasyPipe, GameModeStandardPipe } from '../../pipes/game-mode.pipe'; +import { IconTilesinfoComponent } from '../icons/icon-tilesinfo.component'; +import { IconSettingsComponent } from '../icons/icon-settings.component'; +import { IconHintComponent } from '../icons/icon-hint.component'; +import { IconLogoComponent } from '../icons/icon-logo.component'; +import { IconRestartComponent } from '../icons/icon-restart.component'; +import { IconMenuComponent } from '../icons/icon-menu.component'; +import { IconPauseComponent } from '../icons/icon-pause.component'; +import { IconFullscreenComponent } from '../icons/icon-fullscreen.component'; +import { IconShuffleComponent } from '../icons/icon-shuffle.component'; +import { IconUndoComponent } from '../icons/icon-undo.component'; +import { IconMuteComponent } from '../icons/icon-mute.component'; interface DocumentExtended extends Document { fullScreen: boolean; @@ -66,7 +77,9 @@ function callFullscreenMethod( host: { '(document:keydown)': 'handleKeyDownEvent($event)' }, imports: [ BoardComponent, DurationPipe, GameModeStandardPipe, GameModeEasyPipe, - HelpComponent, TilesInfoComponent, SettingsComponent, ChooseLayoutComponent, TutorialComponent, TranslatePipe, DialogComponent + HelpComponent, TilesInfoComponent, SettingsComponent, ChooseLayoutComponent, TutorialComponent, TranslatePipe, DialogComponent, + IconTilesinfoComponent, IconSettingsComponent, IconHintComponent, IconLogoComponent, IconRestartComponent, + IconMenuComponent, IconPauseComponent, IconFullscreenComponent, IconShuffleComponent, IconUndoComponent, IconMuteComponent ] }) export class GameComponent { diff --git a/src/app/components/help/help.component.html b/src/app/components/help/help.component.html index c671a46b..9744609d 100644 --- a/src/app/components/help/help.component.html +++ b/src/app/components/help/help.component.html @@ -19,7 +19,7 @@ / {{ shortcut.altKey }} } - + {{ shortcut.name|translate }}
{{ (shortcut.name + '_LONG')|translate }} diff --git a/src/app/components/help/help.component.spec.ts b/src/app/components/help/help.component.spec.ts index ab460505..908b1dd8 100644 --- a/src/app/components/help/help.component.spec.ts +++ b/src/app/components/help/help.component.spec.ts @@ -35,7 +35,6 @@ describe('HelpComponent', () => { expect(component.shortcuts).toHaveLength(8); expect(component.shortcuts[0].key).toBe('T'); expect(component.shortcuts[0].name).toBe('HINT'); - expect(component.shortcuts[0].icon).toBe('icon-lightbulb'); }); it('should render the how to play section', () => { @@ -80,8 +79,8 @@ describe('HelpComponent', () => { const keyElement = firstShortcut.query(By.css('.key')); expect(keyElement.nativeElement.textContent).toBe('T'); - const iconElement = firstShortcut.query(By.css('i')); - expect(iconElement.nativeElement.className).toContain('icon-lightbulb'); + const iconElement = firstShortcut.query(By.css('app-icon-hint')); + expect(iconElement).toBeTruthy(); const nameElement = firstShortcut.query(By.css('.name')); expect(nameElement).toBeTruthy(); @@ -102,9 +101,13 @@ describe('HelpComponent', () => { const keyElement = shortcutElement.query(By.css('.key')); expect(keyElement.nativeElement.textContent).toBe(shortcut.key); - const iconElement = shortcutElement.query(By.css('i')); + const iconID = shortcut.icon.name.replace('Icon', '').replace('Component', '').toLowerCase(); + const iconName = `app-icon-${iconID}`; + const iconElement = shortcutElement.query(By.css(iconName)); + if (!iconElement) { + console.log(`Checking shortcut "${shortcut.name}" for icon "${iconName}"`); + } expect(iconElement).toBeTruthy(); - expect(iconElement.nativeElement.className).toContain(shortcut.icon); } }); diff --git a/src/app/components/help/help.component.ts b/src/app/components/help/help.component.ts index e8cd255f..b1bd7a0e 100644 --- a/src/app/components/help/help.component.ts +++ b/src/app/components/help/help.component.ts @@ -1,10 +1,19 @@ -import { Component, inject, output, type OnInit } from '@angular/core'; +import { Component, inject, output, type OnInit, type Type } from '@angular/core'; +import { NgComponentOutlet } from '@angular/common'; import { TranslatePipe, TranslateService } from '@ngx-translate/core'; import { clickExternalHref } from '../../model/external-links'; import { DurationPipe } from '../../pipes/duration.pipe'; import { LayoutService } from '../../service/layout.service'; import { LocalstorageService } from '../../service/localstorage.service'; import { log } from '../../model/log'; +import { IconTilesinfoComponent } from '../icons/icon-tilesinfo.component'; +import { IconSettingsComponent } from '../icons/icon-settings.component'; +import { IconHintComponent } from '../icons/icon-hint.component'; +import { IconLogoComponent } from '../icons/icon-logo.component'; +import { IconRestartComponent } from '../icons/icon-restart.component'; +import { IconPauseComponent } from '../icons/icon-pause.component'; +import { IconShuffleComponent } from '../icons/icon-shuffle.component'; +import { IconUndoComponent } from '../icons/icon-undo.component'; interface StatEntry { name: string; @@ -24,7 +33,7 @@ interface Stat { selector: 'app-help', templateUrl: './help.component.html', styleUrls: ['./help.component.scss'], - imports: [TranslatePipe, DurationPipe] + imports: [TranslatePipe, DurationPipe, NgComponentOutlet] }) export class HelpComponent implements OnInit { readonly showTutorial = output(); @@ -38,15 +47,15 @@ export class HelpComponent implements OnInit { private readonly storage = inject(LocalstorageService); private readonly translate = inject(TranslateService); - shortcuts: Array<{ icon: string; key: string; altKey?: string; name: string }> = [ - { icon: 'icon-lightbulb', key: 'T', name: 'HINT' }, - { icon: 'icon-spin1', key: 'M', name: 'SHUFFLE' }, - { icon: 'icon-undo', key: 'U', name: 'UNDO' }, - { icon: 'icon-loop', key: 'N', name: 'RESTART' }, - { icon: 'icon-pause', key: 'P', altKey: 'Space', name: 'PAUSE' }, - { icon: 'icon-calendar', key: 'I', name: 'INFO' }, - { icon: 'icon-cog', key: 'S', name: 'SETTINGS' }, - { icon: 'icon-logo', key: 'H', name: 'HELP' } + shortcuts: Array<{ icon: Type; key: string; altKey?: string; name: string }> = [ + { icon: IconHintComponent, key: 'T', name: 'HINT' }, + { icon: IconShuffleComponent, key: 'M', name: 'SHUFFLE' }, + { icon: IconUndoComponent, key: 'U', name: 'UNDO' }, + { icon: IconRestartComponent, key: 'N', name: 'RESTART' }, + { icon: IconPauseComponent, key: 'P', altKey: 'Space', name: 'PAUSE' }, + { icon: IconTilesinfoComponent, key: 'I', name: 'TILES_INFO' }, + { icon: IconSettingsComponent, key: 'S', name: 'SETTINGS' }, + { icon: IconLogoComponent, key: 'H', name: 'HELP' } ]; ngOnInit(): void { diff --git a/src/app/components/icons/README.md b/src/app/components/icons/README.md new file mode 100644 index 00000000..7b5c0aa6 --- /dev/null +++ b/src/app/components/icons/README.md @@ -0,0 +1,41 @@ +# Icons license info + +## Entypo + +Copyright (C) 2012 by Daniel Bruce + +Author: Daniel Bruce +License: SIL (http://scripts.sil.org/OFL) +Homepage: + +## Font Awesome + +Copyright (C) 2016 by Dave Gandy + +Author: Dave Gandy +License: SIL (http://scripts.sil.org/OFL) +Homepage: + +## Iconic + +Copyright (C) 2012 by P.J. Onori + +Author: P.J. Onori +License: SIL (http://scripts.sil.org/OFL) +Homepage: + +## Fontelico + +Copyright (C) 2012 by Fontello project + +Author: Crowdsourced, for Fontello project +License: SIL (http://scripts.sil.org/OFL) +Homepage: + +## Typicons + +(c) Stephen Hutchings 2012 + +Author: Stephen Hutchings +License: SIL (http://scripts.sil.org/OFL) +Homepage: http://typicons.com/ diff --git a/src/app/components/icons/icon-clear.component.html b/src/app/components/icons/icon-clear.component.html new file mode 100644 index 00000000..c7b7087a --- /dev/null +++ b/src/app/components/icons/icon-clear.component.html @@ -0,0 +1,11 @@ + diff --git a/src/app/components/icons/icon-clear.component.ts b/src/app/components/icons/icon-clear.component.ts new file mode 100644 index 00000000..2652f405 --- /dev/null +++ b/src/app/components/icons/icon-clear.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 3df1557e2d6e84ec32bd47aee5bfdf59, css: cancel-alt, src: typicons +@Component({ + selector: 'app-icon-clear', + templateUrl: './icon-clear.component.html', + host: { class: 'icon' } +}) +export class IconClearComponent { +} diff --git a/src/app/components/icons/icon-close.component.html b/src/app/components/icons/icon-close.component.html new file mode 100644 index 00000000..4a21fc52 --- /dev/null +++ b/src/app/components/icons/icon-close.component.html @@ -0,0 +1,10 @@ + diff --git a/src/app/components/icons/icon-close.component.ts b/src/app/components/icons/icon-close.component.ts new file mode 100644 index 00000000..33c7153d --- /dev/null +++ b/src/app/components/icons/icon-close.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 2e2dba0307a502a8507c1729084c7ab5, css: cancel-circled2, src: fontawesome +@Component({ + selector: 'app-icon-close', + templateUrl: './icon-close.component.html', + host: { class: 'icon' } +}) +export class IconCloseComponent { +} diff --git a/src/app/components/icons/icon-delete.component.html b/src/app/components/icons/icon-delete.component.html new file mode 100644 index 00000000..3115eb59 --- /dev/null +++ b/src/app/components/icons/icon-delete.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/components/icons/icon-delete.component.ts b/src/app/components/icons/icon-delete.component.ts new file mode 100644 index 00000000..5a35d195 --- /dev/null +++ b/src/app/components/icons/icon-delete.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 2626e3a1bbcd90e45849af3b58a1d594, css: trash, src: entypo +@Component({ + selector: 'app-icon-delete', + templateUrl: './icon-delete.component.html', + host: { class: 'icon' } +}) +export class IconDeleteComponent { +} diff --git a/src/app/components/icons/icon-down.component.html b/src/app/components/icons/icon-down.component.html new file mode 100644 index 00000000..968d1343 --- /dev/null +++ b/src/app/components/icons/icon-down.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/components/icons/icon-down.component.ts b/src/app/components/icons/icon-down.component.ts new file mode 100644 index 00000000..14dbc15b --- /dev/null +++ b/src/app/components/icons/icon-down.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: c16a63e911bc47b46dc2a7129d2f0c46, css: down-small, src: typicons +@Component({ + selector: 'app-icon-down', + templateUrl: './icon-down.component.html', + host: { class: 'icon' } +}) +export class IconDownComponent { +} diff --git a/src/app/components/icons/icon-duplicate.component.html b/src/app/components/icons/icon-duplicate.component.html new file mode 100644 index 00000000..1659296b --- /dev/null +++ b/src/app/components/icons/icon-duplicate.component.html @@ -0,0 +1,11 @@ + diff --git a/src/app/components/icons/icon-duplicate.component.ts b/src/app/components/icons/icon-duplicate.component.ts new file mode 100644 index 00000000..a4cda7f5 --- /dev/null +++ b/src/app/components/icons/icon-duplicate.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: c8585e1e5b0467f28b70bce765d5840c, css: docs, src: fontawesome +@Component({ + selector: 'app-icon-duplicate', + templateUrl: './icon-duplicate.component.html', + host: { class: 'icon' } +}) +export class IconDuplicateComponent { +} diff --git a/src/app/components/icons/icon-execute.component.html b/src/app/components/icons/icon-execute.component.html new file mode 100644 index 00000000..230d2f9b --- /dev/null +++ b/src/app/components/icons/icon-execute.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/components/icons/icon-execute.component.ts b/src/app/components/icons/icon-execute.component.ts new file mode 100644 index 00000000..a87770d0 --- /dev/null +++ b/src/app/components/icons/icon-execute.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 4b2321afcbe0505a70b80abd5c25e09b, css: paper-plane-empty, src: fontawesome +@Component({ + selector: 'app-icon-execute', + templateUrl: './icon-execute.component.html', + host: { class: 'icon' } +}) +export class IconExecuteComponent { +} diff --git a/src/app/components/icons/icon-fullscreen.component.html b/src/app/components/icons/icon-fullscreen.component.html new file mode 100644 index 00000000..bdc1ac97 --- /dev/null +++ b/src/app/components/icons/icon-fullscreen.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/components/icons/icon-fullscreen.component.ts b/src/app/components/icons/icon-fullscreen.component.ts new file mode 100644 index 00000000..445aab5b --- /dev/null +++ b/src/app/components/icons/icon-fullscreen.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 776687efbdb973ebc67e049cc4c41b13, css: resize-full-alt, src: iconic +@Component({ + selector: 'app-icon-fullscreen', + templateUrl: './icon-fullscreen.component.html', + host: { class: 'icon' } +}) +export class IconFullscreenComponent { +} diff --git a/src/app/components/icons/icon-hint.component.html b/src/app/components/icons/icon-hint.component.html new file mode 100644 index 00000000..312f6634 --- /dev/null +++ b/src/app/components/icons/icon-hint.component.html @@ -0,0 +1,12 @@ + diff --git a/src/app/components/icons/icon-hint.component.ts b/src/app/components/icons/icon-hint.component.ts new file mode 100644 index 00000000..ed50ec63 --- /dev/null +++ b/src/app/components/icons/icon-hint.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 5278ef7773e948d56c4d442c8c8c98cf, css: lightbulb, src: fontawesome +@Component({ + selector: 'app-icon-hint', + templateUrl: './icon-hint.component.html', + host: { class: 'icon' } +}) +export class IconHintComponent { +} diff --git a/src/app/components/icons/icon-info.component.html b/src/app/components/icons/icon-info.component.html new file mode 100644 index 00000000..adc2de87 --- /dev/null +++ b/src/app/components/icons/icon-info.component.html @@ -0,0 +1 @@ + diff --git a/src/app/components/icons/icon-info.component.ts b/src/app/components/icons/icon-info.component.ts new file mode 100644 index 00000000..6a520455 --- /dev/null +++ b/src/app/components/icons/icon-info.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-icon-info', + templateUrl: './icon-info.component.html', + host: { class: 'icon' } +}) +export class IconInfoComponent { +} diff --git a/src/app/components/icons/icon-left.component.html b/src/app/components/icons/icon-left.component.html new file mode 100644 index 00000000..9fdd68d0 --- /dev/null +++ b/src/app/components/icons/icon-left.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/components/icons/icon-left.component.ts b/src/app/components/icons/icon-left.component.ts new file mode 100644 index 00000000..a4642766 --- /dev/null +++ b/src/app/components/icons/icon-left.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 58b78b6ca784d5c3db5beefcd9e18061, css: left-small, src: typicons +@Component({ + selector: 'app-icon-left', + templateUrl: './icon-left.component.html', + host: { class: 'icon' } +}) +export class IconLeftComponent { +} diff --git a/src/app/components/icons/icon-list-add.component.html b/src/app/components/icons/icon-list-add.component.html new file mode 100644 index 00000000..2c5a5bed --- /dev/null +++ b/src/app/components/icons/icon-list-add.component.html @@ -0,0 +1,8 @@ + diff --git a/src/app/components/icons/icon-list-add.component.ts b/src/app/components/icons/icon-list-add.component.ts new file mode 100644 index 00000000..1cee3959 --- /dev/null +++ b/src/app/components/icons/icon-list-add.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 97bd5542ed3e143d2ee9b60e14487615, css: list-add, src: entypo +@Component({ + selector: 'app-icon-list-add', + templateUrl: './icon-list-add.component.html', + host: { class: 'icon' } +}) +export class IconListAddComponent { +} diff --git a/src/app/components/icons/icon-logo.component.html b/src/app/components/icons/icon-logo.component.html new file mode 100644 index 00000000..d7852e6f --- /dev/null +++ b/src/app/components/icons/icon-logo.component.html @@ -0,0 +1,13 @@ + diff --git a/src/app/components/icons/icon-logo.component.ts b/src/app/components/icons/icon-logo.component.ts new file mode 100644 index 00000000..d2497976 --- /dev/null +++ b/src/app/components/icons/icon-logo.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: b38002a7e1a57208ec9353285c99ed86, css: logo, src: custom_icons +@Component({ + selector: 'app-icon-logo', + templateUrl: './icon-logo.component.html', + host: { class: 'icon' } +}) +export class IconLogoComponent { +} diff --git a/src/app/components/icons/icon-menu.component.html b/src/app/components/icons/icon-menu.component.html new file mode 100644 index 00000000..82c9aef5 --- /dev/null +++ b/src/app/components/icons/icon-menu.component.html @@ -0,0 +1,9 @@ + diff --git a/src/app/components/icons/icon-menu.component.ts b/src/app/components/icons/icon-menu.component.ts new file mode 100644 index 00000000..ed6ba111 --- /dev/null +++ b/src/app/components/icons/icon-menu.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 559647a6f430b3aeadbecd67194451dd, css: menu, src: fontawesome +@Component({ + selector: 'app-icon-menu', + templateUrl: './icon-menu.component.html', + host: { class: 'icon' } +}) +export class IconMenuComponent { +} diff --git a/src/app/components/icons/icon-mute.component.html b/src/app/components/icons/icon-mute.component.html new file mode 100644 index 00000000..23e621e0 --- /dev/null +++ b/src/app/components/icons/icon-mute.component.html @@ -0,0 +1,9 @@ + diff --git a/src/app/components/icons/icon-mute.component.ts b/src/app/components/icons/icon-mute.component.ts new file mode 100644 index 00000000..7c204810 --- /dev/null +++ b/src/app/components/icons/icon-mute.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 43m0a70tvxqc6q7jxgzhz5lmlt3ce2iy, css: volume-low, src: typicons +@Component({ + selector: 'app-icon-mute', + templateUrl: './icon-mute.component.html', + host: { class: 'icon' } +}) +export class IconMuteComponent { +} diff --git a/src/app/components/icons/icon-ok.component.html b/src/app/components/icons/icon-ok.component.html new file mode 100644 index 00000000..60f97699 --- /dev/null +++ b/src/app/components/icons/icon-ok.component.html @@ -0,0 +1,6 @@ + diff --git a/src/app/components/icons/icon-ok.component.ts b/src/app/components/icons/icon-ok.component.ts new file mode 100644 index 00000000..83354fba --- /dev/null +++ b/src/app/components/icons/icon-ok.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 12f4ece88e46abd864e40b35e05b11cd, css: ok, src: fontawesome +@Component({ + selector: 'app-icon-ok', + templateUrl: './icon-ok.component.html', + host: { class: 'icon' } +}) +export class IconOkComponent { +} diff --git a/src/app/components/icons/icon-pause.component.html b/src/app/components/icons/icon-pause.component.html new file mode 100644 index 00000000..7584117c --- /dev/null +++ b/src/app/components/icons/icon-pause.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/components/icons/icon-pause.component.ts b/src/app/components/icons/icon-pause.component.ts new file mode 100644 index 00000000..95b72533 --- /dev/null +++ b/src/app/components/icons/icon-pause.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: d8d378d0ce413f231dfa37592e39c227, css: pause, src: entypo +@Component({ + selector: 'app-icon-pause', + templateUrl: './icon-pause.component.html', + host: { class: 'icon' } +}) +export class IconPauseComponent { +} diff --git a/src/app/components/icons/icon-restart.component.html b/src/app/components/icons/icon-restart.component.html new file mode 100644 index 00000000..e62c13a1 --- /dev/null +++ b/src/app/components/icons/icon-restart.component.html @@ -0,0 +1,9 @@ + diff --git a/src/app/components/icons/icon-restart.component.ts b/src/app/components/icons/icon-restart.component.ts new file mode 100644 index 00000000..d2a881b2 --- /dev/null +++ b/src/app/components/icons/icon-restart.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 5d3ef4b7c90d2931e641b840ee42f694, css: loop, src: iconic +@Component({ + selector: 'app-icon-restart', + templateUrl: './icon-restart.component.html', + host: { class: 'icon' } +}) +export class IconRestartComponent { +} diff --git a/src/app/components/icons/icon-right.component.html b/src/app/components/icons/icon-right.component.html new file mode 100644 index 00000000..af398dd8 --- /dev/null +++ b/src/app/components/icons/icon-right.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/components/icons/icon-right.component.ts b/src/app/components/icons/icon-right.component.ts new file mode 100644 index 00000000..707f7514 --- /dev/null +++ b/src/app/components/icons/icon-right.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 877a233d7fdca8a1d82615b96ed0d7a2, css: right-small, src: typicons +@Component({ + selector: 'app-icon-right', + templateUrl: './icon-right.component.html', + host: { class: 'icon' } +}) +export class IconRightComponent { +} diff --git a/src/app/components/icons/icon-settings.component.html b/src/app/components/icons/icon-settings.component.html new file mode 100644 index 00000000..2304fee3 --- /dev/null +++ b/src/app/components/icons/icon-settings.component.html @@ -0,0 +1,13 @@ + diff --git a/src/app/components/icons/icon-settings.component.ts b/src/app/components/icons/icon-settings.component.ts new file mode 100644 index 00000000..8910114d --- /dev/null +++ b/src/app/components/icons/icon-settings.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: e99461abfef3923546da8d745372c995, css: cog, src: fontawesome +@Component({ + selector: 'app-icon-settings', + templateUrl: './icon-settings.component.html', + host: { class: 'icon' } +}) +export class IconSettingsComponent { +} diff --git a/src/app/components/icons/icon-shuffle.component.html b/src/app/components/icons/icon-shuffle.component.html new file mode 100644 index 00000000..1b5c1046 --- /dev/null +++ b/src/app/components/icons/icon-shuffle.component.html @@ -0,0 +1,20 @@ + diff --git a/src/app/components/icons/icon-shuffle.component.ts b/src/app/components/icons/icon-shuffle.component.ts new file mode 100644 index 00000000..95f3e6c4 --- /dev/null +++ b/src/app/components/icons/icon-shuffle.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 72109d2fb3088d0e66ea6a9204297651, css: spin1, src: fontelico +@Component({ + selector: 'app-icon-shuffle', + templateUrl: './icon-shuffle.component.html', + host: { class: 'icon' } +}) +export class IconShuffleComponent { +} diff --git a/src/app/components/icons/icon-tilesinfo.component.html b/src/app/components/icons/icon-tilesinfo.component.html new file mode 100644 index 00000000..b1b6809b --- /dev/null +++ b/src/app/components/icons/icon-tilesinfo.component.html @@ -0,0 +1,14 @@ + diff --git a/src/app/components/icons/icon-tilesinfo.component.ts b/src/app/components/icons/icon-tilesinfo.component.ts new file mode 100644 index 00000000..94ce9b79 --- /dev/null +++ b/src/app/components/icons/icon-tilesinfo.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: c833c98d78cfebed5780cfaaa302a12b, css: calendar, src: iconic +@Component({ + selector: 'app-icon-tilesinfo', + templateUrl: './icon-tilesinfo.component.html', + host: { class: 'icon' } +}) +export class IconTilesinfoComponent { +} diff --git a/src/app/components/icons/icon-undo.component.html b/src/app/components/icons/icon-undo.component.html new file mode 100644 index 00000000..aabdfa1f --- /dev/null +++ b/src/app/components/icons/icon-undo.component.html @@ -0,0 +1,7 @@ + diff --git a/src/app/components/icons/icon-undo.component.ts b/src/app/components/icons/icon-undo.component.ts new file mode 100644 index 00000000..15b0b07d --- /dev/null +++ b/src/app/components/icons/icon-undo.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: ce5e29aa5208417700e7f7012a236c00, css: undo, src: iconic +@Component({ + selector: 'app-icon-undo', + templateUrl: './icon-undo.component.html', + host: { class: 'icon' } +}) +export class IconUndoComponent { +} diff --git a/src/app/components/icons/icon-up.component.html b/src/app/components/icons/icon-up.component.html new file mode 100644 index 00000000..2713d492 --- /dev/null +++ b/src/app/components/icons/icon-up.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/components/icons/icon-up.component.ts b/src/app/components/icons/icon-up.component.ts new file mode 100644 index 00000000..7a9b1c53 --- /dev/null +++ b/src/app/components/icons/icon-up.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +// uid: 62bc6fe2a82e4864e2b94d4c0985ee0c, css: up-small, src: typicons +@Component({ + selector: 'app-icon-up', + templateUrl: './icon-up.component.html', + host: { class: 'icon' } +}) +export class IconUpComponent { +} diff --git a/src/app/components/layout-list/layout-list.component.html b/src/app/components/layout-list/layout-list.component.html index c3866ba6..42b76d1b 100644 --- a/src/app/components/layout-list/layout-list.component.html +++ b/src/app/components/layout-list/layout-list.component.html @@ -12,9 +12,7 @@
{{ group.name | translateGroup }} - @if (!group.isRandom) { - [{{ group.layouts.length }}] - } +
} @if (group.expanded) { @@ -105,7 +103,7 @@
{{ item.bestTime|duration }} - +
} @@ -113,7 +111,7 @@ @if (item.layout.custom) { } diff --git a/src/app/components/layout-list/layout-list.component.scss b/src/app/components/layout-list/layout-list.component.scss index 43111898..91e07567 100644 --- a/src/app/components/layout-list/layout-list.component.scss +++ b/src/app/components/layout-list/layout-list.component.scss @@ -173,28 +173,50 @@ padding-bottom: 1.5em; } - .preview-custom, .preview-best-time { + .preview-best-time { position: absolute; right: 0; - background-color: var(--preview-overlay-background); color: var(--preview-overlay-text); text-shadow: 1px 1px var(--preview-overlay-text-shadow); + background-color: var(--preview-overlay-background); border-bottom-left-radius: 3px; padding: 3px 3px 3px 6px; + align-items: center; a { display: inline-block; min-width: 1.2em; text-align: right; transition: all 100ms; - margin-top: -1px; + font-size: 0.7em; + padding-left: 6px; - i { - font-size: 0.8em; + &:hover { + transform: scale(1.3); + color: var(--text-highlight-color); } + } + } + + .preview-custom { + position: absolute; + right: 0; + color: var(--preview-overlay-text); + text-shadow: 1px 1px var(--preview-overlay-text-shadow); + border-bottom-left-radius: 3px; + padding: 3px 3px 3px 6px; + + a { + display: inline-block; + min-width: 1.2em; + text-align: right; + transition: all 100ms; + font-size: 0.8em; + margin-bottom: -2px; &:hover { transform: scale(1.3); + color: var(--text-highlight-color); } } } diff --git a/src/app/components/layout-list/layout-list.component.ts b/src/app/components/layout-list/layout-list.component.ts index 270b68d1..96b1c929 100644 --- a/src/app/components/layout-list/layout-list.component.ts +++ b/src/app/components/layout-list/layout-list.component.ts @@ -11,6 +11,7 @@ import { generateRandomMapping } from '../../model/random-layout/random-layout'; import { RANDOM_LAYOUT_ID_PREFIX, type RandomSymmetry } from '../../model/random-layout/consts'; import { seedRNG, resetRNG, generateLayoutSeed } from '../../model/rng'; import { TranslateGroupPipe } from '../../pipes/translate-group.pipe'; +import { IconDeleteComponent } from '../icons/icon-delete.component'; export interface LayoutItem { layout: Layout; @@ -40,7 +41,7 @@ export interface RandomLayoutGroup extends LayoutGroup { selector: 'app-layout-list', templateUrl: './layout-list.component.html', styleUrls: ['./layout-list.component.scss'], - imports: [LayoutPreviewComponent, DurationPipe, TranslatePipe, TranslateGroupPipe, DeferLoadScrollHostDirective, DeferLoadDirective] + imports: [LayoutPreviewComponent, DurationPipe, TranslatePipe, TranslateGroupPipe, DeferLoadScrollHostDirective, DeferLoadDirective, IconDeleteComponent] }) export class LayoutListComponent implements OnInit, OnChanges { readonly layouts = input>(); diff --git a/src/app/model/board.ts b/src/app/model/board.ts index 6095e662..c3407546 100644 --- a/src/app/model/board.ts +++ b/src/app/model/board.ts @@ -21,6 +21,7 @@ export class Board { hints: Hints = { groups: [], current: undefined }; selected?: Stone = undefined; undo: Array = []; + buildMode: BUILD_MODE_ID = MODE_SOLVABLE; clearSelection(): void { if (this.selected) { @@ -138,7 +139,7 @@ export class Board { const tiles = new StoneTiles(unusedStones); const mapping: Mapping = unusedStones.map(s => [s.z, s.x, s.y]); const builder: Builder = new Builder(tiles); - const stones = builder.build(MODE_SOLVABLE, mapping); + const stones = builder.build(this.buildMode, mapping); if (!stones) { return; } @@ -175,6 +176,7 @@ export class Board { } applyMapping(mapping: Mapping, mode: BUILD_MODE_ID): void { + this.buildMode = mode; const builder: Builder = new Builder(new Tiles(mapping.length)); this.stones = builder.build(mode, mapping) || []; } diff --git a/src/app/model/builder.ts b/src/app/model/builder.ts index 22890917..4254d602 100644 --- a/src/app/model/builder.ts +++ b/src/app/model/builder.ts @@ -2,19 +2,36 @@ import type { Stone } from './stone'; import type { Tiles } from './tiles'; import type { Mapping, StoneMapping } from './types'; import { SolvableBoardBuilder } from './builder/solvable'; +import { SolvableBoardBuilderEasy } from './builder/solvable-easy'; +import { SolvableBoardBuilderExpert } from './builder/solvable-expert'; import { RandomBoardBuilder } from './builder/random'; import { LoadBoardBuilder } from './builder/load'; import type { BuilderType } from './builder/base'; +import { GAME_MODE_EASY, GAME_MODE_EXPERT, type GAME_MODE_ID } from './consts'; export const MODE_SOLVABLE = 'MODE_SOLVABLE'; +export const MODE_SOLVABLE_EASY = 'MODE_SOLVABLE_EASY'; +export const MODE_SOLVABLE_EXPERT = 'MODE_SOLVABLE_EXPERT'; export const MODE_RANDOM = 'MODE_RANDOM'; export const BuilderModes = [ + { id: MODE_SOLVABLE_EASY, builder: SolvableBoardBuilderEasy }, { id: MODE_SOLVABLE, builder: SolvableBoardBuilder }, + { id: MODE_SOLVABLE_EXPERT, builder: SolvableBoardBuilderExpert }, { id: MODE_RANDOM, builder: RandomBoardBuilder } ]; -export type BUILD_MODE_ID = 'MODE_SOLVABLE' | 'MODE_RANDOM'; +export type BUILD_MODE_ID = 'MODE_SOLVABLE_EASY' | 'MODE_SOLVABLE' | 'MODE_SOLVABLE_EXPERT' | 'MODE_RANDOM'; + +export function solvableModeForGameMode(mode: GAME_MODE_ID): BUILD_MODE_ID { + if (mode === GAME_MODE_EASY) { + return MODE_SOLVABLE_EASY; + } + if (mode === GAME_MODE_EXPERT) { + return MODE_SOLVABLE_EXPERT; + } + return MODE_SOLVABLE; +} export class Builder { constructor(private readonly tiles: Tiles) { diff --git a/src/app/model/builder/solvable-easy.ts b/src/app/model/builder/solvable-easy.ts new file mode 100644 index 00000000..ad882624 --- /dev/null +++ b/src/app/model/builder/solvable-easy.ts @@ -0,0 +1,8 @@ +import { SolvableBoardBuilderBase, type BreadthConstraint } from './solvable'; + +// Easy solvable - always at least 4 open pairs (freestones.length >= 8) +export class SolvableBoardBuilderEasy extends SolvableBoardBuilderBase { + protected override breadthConstraint(): BreadthConstraint { + return { min: 8, max: Infinity }; + } +} diff --git a/src/app/model/builder/solvable-expert.ts b/src/app/model/builder/solvable-expert.ts new file mode 100644 index 00000000..7e22ab06 --- /dev/null +++ b/src/app/model/builder/solvable-expert.ts @@ -0,0 +1,10 @@ +import { SolvableBoardBuilderBase, type BreadthConstraint } from './solvable'; + +// Expert solvable - at most 2 open pairs (freestones.length <= 4), more retries +export class SolvableBoardBuilderExpert extends SolvableBoardBuilderBase { + protected override maxRuns = 10_000; + + protected override breadthConstraint(): BreadthConstraint { + return { min: 2, max: 4 }; + } +} diff --git a/src/app/model/builder/solvable.spec.ts b/src/app/model/builder/solvable.spec.ts new file mode 100644 index 00000000..301b30c0 --- /dev/null +++ b/src/app/model/builder/solvable.spec.ts @@ -0,0 +1,166 @@ +import { SolvableBoardBuilder, SolvableBoardBuilderBase } from './solvable'; +import { SolvableBoardBuilderEasy } from './solvable-easy'; +import { SolvableBoardBuilderExpert } from './solvable-expert'; +import { Tiles } from '../tiles'; +import type { Mapping } from '../types'; +import { BuilderModes, MODE_SOLVABLE, MODE_SOLVABLE_EASY, MODE_SOLVABLE_EXPERT, solvableModeForGameMode } from '../builder'; +import { GAME_MODE_EASY, GAME_MODE_EXPERT, GAME_MODE_STANDARD } from '../consts'; + +// A flat 4-stone mapping - 2 pairs, no overlaps, no blocking +const MAPPING_4: Mapping = [[0, 0, 0], [0, 2, 0], [0, 4, 0], [0, 6, 0]]; + +// A flat 8-stone mapping - 4 pairs, none blocking +const MAPPING_8: Mapping = [ + [0, 0, 0], [0, 2, 0], [0, 4, 0], [0, 6, 0], + [0, 8, 0], [0, 10, 0], [0, 12, 0], [0, 14, 0] +]; + +// A flat 16-stone mapping - 8 pairs, none blocking +const MAPPING_16: Mapping = Array.from({ length: 16 }, (_, index) => [0, index * 2, 0] as [number, number, number]); + +describe('SolvableBoardBuilder (Standard)', () => { + let builder: SolvableBoardBuilder; + + beforeEach(() => { + builder = new SolvableBoardBuilder(); + }); + + it('should be an instance of SolvableBoardBuilderBase', () => { + expect(builder).toBeInstanceOf(SolvableBoardBuilderBase); + }); + + it('should produce a board for a 4-stone mapping', () => { + const stones = builder.build(MAPPING_4, new Tiles(4)); + expect(stones).toHaveLength(4); + }); + + it('should produce a board for a 16-stone mapping', () => { + const stones = builder.build(MAPPING_16, new Tiles(16)); + expect(stones).toHaveLength(16); + }); + + it('should assign matched pairs (each stone has at least one same-groupNr partner)', () => { + const stones = builder.build(MAPPING_16, new Tiles(16)); + for (const stone of stones) { + const partners = stones.filter(s => s !== stone && s.groupNr === stone.groupNr); + expect(partners.length).toBeGreaterThanOrEqual(1); + } + }); + + it('should assign a positive tile value to every stone', () => { + const stones = builder.build(MAPPING_4, new Tiles(4)); + for (const stone of stones) { + expect(stone.v).toBeGreaterThan(0); + } + }); +}); + +describe('SolvableBoardBuilderEasy', () => { + let builder: SolvableBoardBuilderEasy; + + beforeEach(() => { + builder = new SolvableBoardBuilderEasy(); + }); + + it('should be an instance of SolvableBoardBuilderBase', () => { + expect(builder).toBeInstanceOf(SolvableBoardBuilderBase); + }); + + it('should produce a valid board for a 16-stone mapping', () => { + const stones = builder.build(MAPPING_16, new Tiles(16)); + expect(stones).toHaveLength(16); + for (const stone of stones) { + expect(stone.v).toBeGreaterThan(0); + } + }); + + it('should fall back and still return a board when the constraint is impossible (4-stone layout)', () => { + // With only 4 stones, freestones.length can never reach 8 (Easy min). + // The constrained step must exhaust retries and fall back to unconstrained. + const stones = builder.build(MAPPING_4, new Tiles(4)); + expect(stones).toHaveLength(4); + for (const stone of stones) { + expect(stone.v).toBeGreaterThan(0); + } + }); + + it('should fall back and still return a board when the constraint is impossible (8-stone layout)', () => { + // With 8 flat unblocked stones, all 8 are free initially (freestones = 8 = min boundary). + // After first pair picked, freestones = 6 < 8, so constraint fails from step 2 onward. + // Should still produce a valid board via fallback. + const stones = builder.build(MAPPING_8, new Tiles(8)); + expect(stones).toHaveLength(8); + }); +}); + +describe('SolvableBoardBuilderExpert', () => { + let builder: SolvableBoardBuilderExpert; + + beforeEach(() => { + builder = new SolvableBoardBuilderExpert(); + }); + + it('should be an instance of SolvableBoardBuilderBase', () => { + expect(builder).toBeInstanceOf(SolvableBoardBuilderBase); + }); + + it('should produce a valid board for a 16-stone mapping', () => { + // 16 flat stones are all unblocked (freestones = 16 > 4), so constraint fails. + // Falls back to unconstrained - should still return valid board. + const stones = builder.build(MAPPING_16, new Tiles(16)); + expect(stones).toHaveLength(16); + for (const stone of stones) { + expect(stone.v).toBeGreaterThan(0); + } + }); + + it('should produce a valid board for a 4-stone mapping (constraint satisfied)', () => { + // 4 flat unblocked stones: freestones = 4 <= 4, constraint passes. + const stones = builder.build(MAPPING_4, new Tiles(4)); + expect(stones).toHaveLength(4); + for (const stone of stones) { + expect(stone.v).toBeGreaterThan(0); + } + }); +}); + +describe('BuilderModes registry', () => { + it('should include MODE_SOLVABLE_EASY', () => { + const entry = BuilderModes.find(m => m.id === MODE_SOLVABLE_EASY); + expect(entry).toBeDefined(); + }); + + it('should include MODE_SOLVABLE_EXPERT', () => { + const entry = BuilderModes.find(m => m.id === MODE_SOLVABLE_EXPERT); + expect(entry).toBeDefined(); + }); + + it('MODE_SOLVABLE_EASY builder should be SolvableBoardBuilderEasy', () => { + const entry = BuilderModes.find(m => m.id === MODE_SOLVABLE_EASY)!; + expect(new entry.builder()).toBeInstanceOf(SolvableBoardBuilderEasy); + }); + + it('MODE_SOLVABLE_EXPERT builder should be SolvableBoardBuilderExpert', () => { + const entry = BuilderModes.find(m => m.id === MODE_SOLVABLE_EXPERT)!; + expect(new entry.builder()).toBeInstanceOf(SolvableBoardBuilderExpert); + }); + + it('MODE_SOLVABLE builder should still be SolvableBoardBuilder (unchanged)', () => { + const entry = BuilderModes.find(m => m.id === MODE_SOLVABLE)!; + expect(new entry.builder()).toBeInstanceOf(SolvableBoardBuilder); + }); +}); + +describe('solvableModeForGameMode', () => { + it('should return MODE_SOLVABLE_EASY for GAME_MODE_EASY', () => { + expect(solvableModeForGameMode(GAME_MODE_EASY)).toBe(MODE_SOLVABLE_EASY); + }); + + it('should return MODE_SOLVABLE_EXPERT for GAME_MODE_EXPERT', () => { + expect(solvableModeForGameMode(GAME_MODE_EXPERT)).toBe(MODE_SOLVABLE_EXPERT); + }); + + it('should return MODE_SOLVABLE for GAME_MODE_STANDARD', () => { + expect(solvableModeForGameMode(GAME_MODE_STANDARD)).toBe(MODE_SOLVABLE); + }); +}); diff --git a/src/app/model/builder/solvable.ts b/src/app/model/builder/solvable.ts index 6c2f134b..19865e6c 100644 --- a/src/app/model/builder/solvable.ts +++ b/src/app/model/builder/solvable.ts @@ -7,44 +7,62 @@ import { RandomBoardBuilder } from './random'; const MAX_RUNS = 2000; const MAX_ALTERNATIVE_ATTEMPTS = 10; -export class SolvableBoardBuilder extends BuilderBase { +export interface BreadthConstraint { + min: number; + max: number; +} + +export abstract class SolvableBoardBuilderBase extends BuilderBase { + protected maxRuns: number = MAX_RUNS; + + protected breadthConstraint(): BreadthConstraint | undefined { + return undefined; + } + build(mapping: Mapping, tiles: Tiles): Array { - // Try the standard solvable algorithm - const result = this.buildSolvableWithRetries(mapping, tiles, MAX_RUNS); - if (result) { - return result; + const breadth = this.breadthConstraint(); + + // Step 1: constrained attempt (skipped when no constraint) + if (breadth) { + const result = this.buildSolvableWithRetries(mapping, tiles, this.maxRuns, breadth); + if (result) { + return result; + } } - // If standard algorithm fails, try alternative strategy - const alternativeResult = this.buildSolvableAlternative(mapping, tiles); - if (alternativeResult) { - return alternativeResult; + // Step 2: unconstrained solvable (always tried; same as original behaviour for Standard) + const unconstrained = this.buildSolvableWithRetries(mapping, tiles, MAX_RUNS, undefined); + if (unconstrained) { + return unconstrained; } - // Last resort: create a random board and try to solve it - // This ensures we always return a board, even if not guaranteed solvable + // Step 3: alternative strategy (reversed group order) + const alternative = this.buildSolvableAlternative(mapping, tiles); + if (alternative) { + return alternative; + } + + // Step 4: last resort - random fill, possibly unsolvable const randomBoard = new RandomBoardBuilder(); return randomBoard.build(mapping, tiles); } - private buildSolvableWithRetries(mapping: Mapping, tiles: Tiles, maxRuns: number): Array | undefined { - // Initialize a board with all matching faces + private buildSolvableWithRetries(mapping: Mapping, tiles: Tiles, maxRuns: number, breadth: BreadthConstraint | undefined): Array | undefined { const stones: Array = []; for (const st of mapping) { stones.push(new Stone(st[0], st[1], st[2], 0, 0)); } - BuilderBase.fillStones(stones, tiles); // grouping will be repaired later + BuilderBase.fillStones(stones, tiles); let runs = 0; - let pairs = this.assignTilePairs(stones, tiles); + let pairs = this.assignTilePairs(stones, tiles, false, breadth); while (pairs.length === 0 && runs < maxRuns) { - // Reset stones for retry for (const stone of stones) { stone.picked = false; stone.v = 0; stone.groupNr = 0; } - pairs = this.assignTilePairs(stones, tiles); + pairs = this.assignTilePairs(stones, tiles, false, breadth); runs++; } @@ -56,7 +74,6 @@ export class SolvableBoardBuilder extends BuilderBase { } private buildSolvableAlternative(mapping: Mapping, tiles: Tiles): Array | undefined { - // Alternative strategy: try building from scratch multiple times with different tile selection for (let attempt = 0; attempt < MAX_ALTERNATIVE_ATTEMPTS; attempt++) { const stones: Array = []; for (const st of mapping) { @@ -64,8 +81,7 @@ export class SolvableBoardBuilder extends BuilderBase { } BuilderBase.fillStones(stones, tiles); - // Try to solve with reversed group order for variety - const pairs = this.assignTilePairs(stones, tiles, attempt % 2 !== 0); + const pairs = this.assignTilePairs(stones, tiles, attempt % 2 !== 0, undefined); if (pairs.length > 0) { return this.finalizeBoard(stones, tiles); } @@ -82,7 +98,7 @@ export class SolvableBoardBuilder extends BuilderBase { return stones; } - private assignTilePairs(stones: Array, tiles: Tiles, reverse = false): Array> { + private assignTilePairs(stones: Array, tiles: Tiles, reverse = false, breadth: BreadthConstraint | undefined): Array> { const pairs: Array<[Tile, Tile]> = []; const allPairs: Array<[Tile, Tile]> = []; const maxPairs = stones.length / 2; @@ -111,6 +127,9 @@ export class SolvableBoardBuilder extends BuilderBase { if (freestones.length < 2) { return []; } + if (breadth && (freestones.length < breadth.min || freestones.length > breadth.max)) { + return []; + } const place1 = BuilderBase.randomExtract(freestones); const place2 = BuilderBase.randomExtract(freestones); place1.v = pair[0].v; @@ -126,3 +145,7 @@ export class SolvableBoardBuilder extends BuilderBase { return pairs; } } + +// Standard solvable - no breadth constraint (original behaviour) +export class SolvableBoardBuilder extends SolvableBoardBuilderBase { +} diff --git a/src/app/model/consts.spec.ts b/src/app/model/consts.spec.ts index 40dd975c..5fe1b4d1 100644 --- a/src/app/model/consts.spec.ts +++ b/src/app/model/consts.spec.ts @@ -52,7 +52,7 @@ describe('Constants', () => { // Check easy mode const easyMode = GameModes.find(mode => mode.id === GAME_MODE_EASY); expect(easyMode).toBeDefined(); - expect(easyMode?.features.length).toBe(3); + expect(easyMode?.features.length).toBe(4); // Check standard mode const standardMode = GameModes.find(mode => mode.id === GAME_MODE_STANDARD); diff --git a/src/app/model/consts.ts b/src/app/model/consts.ts index b6917901..eaf432fb 100644 --- a/src/app/model/consts.ts +++ b/src/app/model/consts.ts @@ -20,7 +20,8 @@ export const GameModes = [ features: [ { title: 'SHUFFLE' }, { title: 'HINT' }, - { title: 'UNDO' } + { title: 'UNDO' }, + { title: 'RESCUE_SHUFFLE' } ] }, { diff --git a/src/app/model/game.ts b/src/app/model/game.ts index 9c9867df..4124d3be 100644 --- a/src/app/model/game.ts +++ b/src/app/model/game.ts @@ -4,7 +4,7 @@ import { GAME_MODE_EASY, GAME_MODE_EXPERT, type GAME_MODE_ID, GAME_MODE_ID_DEFAU import { SOUNDS, Sound } from './sound'; import type { Stone } from './stone'; import type { GameStateStore, Layout, StorageProvider } from './types'; -import type { BUILD_MODE_ID } from './builder'; +import { type BUILD_MODE_ID, MODE_SOLVABLE } from './builder'; import { Music } from './music'; import { RANDOM_LAYOUT_ID_PREFIX } from './random-layout/consts'; @@ -166,6 +166,7 @@ export class Game { this.clock.elapsed = store.elapsed ?? 0; this.layoutID = store.layout; this.mode = store.gameMode ?? GAME_MODE_ID_DEFAULT; + this.board.buildMode = store.buildMode ?? MODE_SOLVABLE; this.state = store.state ?? STATES.idle; this.board.load(store.stones, store.undo ?? []); return true; @@ -186,6 +187,7 @@ export class Game { state: this.state, layout: this.layoutID, gameMode: this.mode, + buildMode: this.board.buildMode, undo: this.board.undo, stones: this.board.save() }); diff --git a/src/app/model/rng.spec.ts b/src/app/model/rng.spec.ts index 99eb3192..abb0e2b3 100644 --- a/src/app/model/rng.spec.ts +++ b/src/app/model/rng.spec.ts @@ -92,7 +92,7 @@ describe('rng', () => { seedRNG('fixed'); const seeded = rng(); resetRNG(); - // generateLayoutSeed uses Math.random directly, not rng() — + // generateLayoutSeed uses Math.random directly, not rng() // so seeding has no effect on it seedRNG('fixed'); generateLayoutSeed(); diff --git a/src/app/model/rng.ts b/src/app/model/rng.ts index 29ebe5f1..a1cdf0de 100644 --- a/src/app/model/rng.ts +++ b/src/app/model/rng.ts @@ -10,7 +10,7 @@ export function mulberry32(seed: number): () => number { // eslint-disable-next-line unicorn/prefer-math-trunc let state = seed | 0; return () => { - // | 0 wraps to int32 — required by the mulberry32 algorithm, not mere truncation + // | 0 wraps to int32 - required by the mulberry32 algorithm, not mere truncation // eslint-disable-next-line unicorn/prefer-math-trunc state = (state + 0x6D_2B_79_F5) | 0; let t = Math.imul(state ^ (state >>> 15), 1 | state); diff --git a/src/app/model/types.ts b/src/app/model/types.ts index 123561d2..298286b2 100644 --- a/src/app/model/types.ts +++ b/src/app/model/types.ts @@ -1,4 +1,5 @@ import type { GAME_MODE_ID } from './consts'; +import type { BUILD_MODE_ID } from './builder'; export type SafeUrlSVG = string; @@ -76,6 +77,7 @@ export class GameStateStore { state?: number; layout: string; gameMode: GAME_MODE_ID; + buildMode?: BUILD_MODE_ID; undo?: Array; stones?: Array; } diff --git a/src/app/modules/editor/components/editor/editor.component.html b/src/app/modules/editor/components/editor/editor.component.html index 2a23d40c..69906bb5 100644 --- a/src/app/modules/editor/components/editor/editor.component.html +++ b/src/app/modules/editor/components/editor/editor.component.html @@ -1,9 +1,9 @@
- +
    -
  • {{ 'EDITOR_TITLE' | translate }}
  • +
  • {{ 'EDITOR_TITLE' | translate }}
  • @@ -24,7 +24,7 @@
      -
    • {{ 'EDITOR_TITLE' | translate }}: {{ 'EDITOR_IMPORT' | translate }}
    • +
    • {{ 'EDITOR_TITLE' | translate }}: {{ 'EDITOR_IMPORT' | translate }}
    @@ -36,7 +36,7 @@
      -
    • {{ 'EDITOR_TITLE' | translate }}: {{ layout.name }}
    • +
    • {{ 'EDITOR_TITLE' | translate }}: {{ layout.name }}
    • diff --git a/src/app/modules/editor/components/editor/editor.component.scss b/src/app/modules/editor/components/editor/editor.component.scss index fc5f9eb3..7e5fa3e1 100644 --- a/src/app/modules/editor/components/editor/editor.component.scss +++ b/src/app/modules/editor/components/editor/editor.component.scss @@ -9,6 +9,16 @@ background-color: var(--editor-color-bg); z-index: 10001; + .editor-title { + display: flex; + align-items: center; + gap: 8px; + + app-icon-logo { + color: red; + } + } + a { color: var(--main-content-link-color); cursor: pointer; diff --git a/src/app/modules/editor/components/editor/editor.component.ts b/src/app/modules/editor/components/editor/editor.component.ts index 2bf1dd24..3b551ee0 100644 --- a/src/app/modules/editor/components/editor/editor.component.ts +++ b/src/app/modules/editor/components/editor/editor.component.ts @@ -7,12 +7,14 @@ import type { EditLayout } from '../../model/edit-layout'; import type { Layout } from '../../../../model/types'; import { ImportComponent } from '../import/import.component'; import { ManagerComponent } from '../manager/manager.component'; +import { IconCloseComponent } from '../../../../components/icons/icon-close.component'; +import { IconLogoComponent } from '../../../../components/icons/icon-logo.component'; @Component({ selector: 'app-editor-component', templateUrl: './editor.component.html', styleUrls: ['./editor.component.scss'], - imports: [LayoutComponent, ImportComponent, ManagerComponent, TranslatePipe] + imports: [LayoutComponent, IconLogoComponent, ImportComponent, ManagerComponent, TranslatePipe, IconCloseComponent] }) export class EditorComponent { readonly closeEvent = output(); diff --git a/src/app/modules/editor/components/import/import.component.html b/src/app/modules/editor/components/import/import.component.html index 43598db2..740765ba 100644 --- a/src/app/modules/editor/components/import/import.component.html +++ b/src/app/modules/editor/components/import/import.component.html @@ -11,7 +11,7 @@ @for (log of logs; track log) {

      @if (log.id) { - {{ log.msg }} + {{ log.msg }} } @if (!log.id) { {{ log.msg }} diff --git a/src/app/modules/editor/components/import/import.component.ts b/src/app/modules/editor/components/import/import.component.ts index 605ea12c..ed7ec7e4 100644 --- a/src/app/modules/editor/components/import/import.component.ts +++ b/src/app/modules/editor/components/import/import.component.ts @@ -5,12 +5,13 @@ import { log } from '../../../../model/log'; import { importLayouts } from '../../model/import'; import { TranslatePipe } from '@ngx-translate/core'; import { DropZoneDirective } from '../../directives/drop-zone.directive'; +import { IconOkComponent } from '../../../../components/icons/icon-ok.component'; @Component({ selector: 'app-import-component', templateUrl: './import.component.html', styleUrls: ['./import.component.scss'], - imports: [TranslatePipe, DropZoneDirective] + imports: [TranslatePipe, DropZoneDirective, IconOkComponent] }) export class ImportComponent { readonly editEvent = output(); diff --git a/src/app/modules/editor/components/layout/layout.component.html b/src/app/modules/editor/components/layout/layout.component.html index 90e6fa9d..dbd1c576 100644 --- a/src/app/modules/editor/components/layout/layout.component.html +++ b/src/app/modules/editor/components/layout/layout.component.html @@ -13,7 +13,7 @@

      @@ -25,19 +25,19 @@
      Level {{ this.currentZ }}
    @@ -74,16 +74,16 @@
    Tiles: {{ this.stats.totalCount }}
    @@ -132,7 +132,7 @@ @if (saveDialog) {
    - +
    diff --git a/src/app/modules/editor/components/layout/layout.component.ts b/src/app/modules/editor/components/layout/layout.component.ts index 91f8a5e5..8931fc1d 100644 --- a/src/app/modules/editor/components/layout/layout.component.ts +++ b/src/app/modules/editor/components/layout/layout.component.ts @@ -14,6 +14,15 @@ import { BoardComponent } from '../board/board.component'; import { CommonModule } from '@angular/common'; import { optimizeMapping } from '../../model/optimize'; import { mappingExtents } from '../../../../model/mapping'; +import { IconCloseComponent } from '../../../../components/icons/icon-close.component'; +import { IconListAddComponent } from '../../../../components/icons/icon-list-add.component'; +import { IconUpComponent } from '../../../../components/icons/icon-up.component'; +import { IconDownComponent } from '../../../../components/icons/icon-down.component'; +import { IconDuplicateComponent } from '../../../../components/icons/icon-duplicate.component'; +import { IconClearComponent } from '../../../../components/icons/icon-clear.component'; +import { IconDeleteComponent } from '../../../../components/icons/icon-delete.component'; +import { IconLeftComponent } from '../../../../components/icons/icon-left.component'; +import { IconRightComponent } from '../../../../components/icons/icon-right.component'; interface Stats { name: string; @@ -46,7 +55,9 @@ interface EditLevel { selector: 'app-editor-layout-component', templateUrl: './layout.component.html', styleUrls: ['./layout.component.scss'], - imports: [CommonModule, BoardComponent, LayoutPreviewComponent, ExportComponent, TranslatePipe] + imports: [CommonModule, BoardComponent, LayoutPreviewComponent, ExportComponent, TranslatePipe, IconCloseComponent, + IconListAddComponent, IconUpComponent, IconDownComponent, IconDuplicateComponent, + IconClearComponent, IconDeleteComponent, IconLeftComponent, IconRightComponent] }) export class LayoutComponent implements OnInit, OnChanges, OnDestroy { readonly layout = model.required(); diff --git a/src/app/modules/editor/components/manager/manager.component.html b/src/app/modules/editor/components/manager/manager.component.html index 3eec0e7f..3204f21b 100644 --- a/src/app/modules/editor/components/manager/manager.component.html +++ b/src/app/modules/editor/components/manager/manager.component.html @@ -14,12 +14,12 @@ {{ 'EDITOR_LAYOUT_NR_OF_STONES' | translate }} {{ 'EDITOR_COLUMN_TEST' | translate }} @@ -35,7 +35,7 @@ {{ layout.mapping.length }} @if (test[layout.id]) {
    @@ -51,7 +51,7 @@ @if (layout.custom) { } diff --git a/src/app/modules/editor/components/manager/manager.component.ts b/src/app/modules/editor/components/manager/manager.component.ts index 44237346..caf7c9ec 100644 --- a/src/app/modules/editor/components/manager/manager.component.ts +++ b/src/app/modules/editor/components/manager/manager.component.ts @@ -4,12 +4,14 @@ import { LayoutService } from '../../../../service/layout.service'; import { WorkerService } from '../../../../service/worker.service'; import { LayoutPreviewComponent } from '../../../../components/layout-preview/layout-preview.component'; import { TranslatePipe } from '@ngx-translate/core'; +import { IconDeleteComponent } from '../../../../components/icons/icon-delete.component'; +import { IconExecuteComponent } from '../../../../components/icons/icon-execute.component'; @Component({ selector: 'app-manager-component', templateUrl: './manager.component.html', styleUrls: ['./manager.component.scss'], - imports: [LayoutPreviewComponent, TranslatePipe] + imports: [LayoutPreviewComponent, TranslatePipe, IconDeleteComponent, IconExecuteComponent] }) export class ManagerComponent implements OnChanges, OnDestroy { readonly inputLayouts = input>(); diff --git a/src/assets/i18n/ar.json b/src/assets/i18n/ar.json index d19cb80e..8a2eab8d 100644 --- a/src/assets/i18n/ar.json +++ b/src/assets/i18n/ar.json @@ -30,7 +30,9 @@ "SETTINGS": "الإعدادات", "STATS": "الإحصائيات", "MODE": "خوارزمية ملء المجلس", - "MODE_SOLVABLE": "قابلة للحل", + "MODE_SOLVABLE": "قابلة للحل (معياري)", + "MODE_SOLVABLE_EASY": "قابل للحل (سهل)", + "MODE_SOLVABLE_EXPERT": "قابل للحل (خبير)", "MODE_RANDOM": "عشوائي", "RANDOM_GROUP": "عشوائي", "RANDOM_LAYOUT": "عشوائي", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://ar.wikipedia.org/wiki/Mahjong", "TILES_INFO": "معلومات البلاط", "TILES": "البلاط", - "INFO_LONG": "معلومات البلاط", + "TILES_INFO_LONG": "نظرة عامة على جميع البلاطات في اللعبة", "HELP": "مساعدة", "HELP_LONG": "إظهار / إخفاء هذا الحوار", "SETTINGS_LONG": "اضبط اللغة ومجموعات البلاط والألوان", - "MODE_SOLVABLE_DESC": "ملء عشوائي مع إمكانية حل واحدة على الأقل", - "MODE_RANDOM_DESC": "ملء عشوائي تماماً، قد يكون غير قابل للحل", + "MODE_SOLVABLE_DESC": "مضمون بوجود حل واحد على الأقل", + "MODE_SOLVABLE_EASY_DESC": "صعوبة مخففة - أزواج كثيرة متاحة للمطابقة", + "MODE_SOLVABLE_EXPERT_DESC": "أزواج قليلة متاحة في وقت واحد - يتطلب تخطيطاً دقيقاً", + "MODE_RANDOM_DESC": "تخطيط عشوائي كامل - قد يكون غير قابل للحل", "SELECT_BOARD": "اختر اللوح", "BOARD_GENERATOR": "مولد اللوح", "START_SELECTED": "ابدأ المحددة", - "START_RANDOM": "ابدأ عشوائياً", + "START_RANDOM": "العب لوحاً عشوائياً", "TILESET": "فن البلاط", "BACKGROUND": "خلفية", "INFO": "معلومات", @@ -190,10 +194,13 @@ "t_e9": "إضافي 9", "SHUFFLE": "الخلط", "SHUFFLE_LONG": "خلط الحجارة في اللعبة", + "RESCUE_SHUFFLE": "الخلط للمتابعة", + "RESCUE_SHUFFLE_LONG": "الخلط إذا لم تعد هناك حركات متاحة", "GAME_MODE": "الوضع", "GAME_MODE_EASY": "سهل", "GAME_MODE_STANDARD": "معياري", "GAME_MODE_EXPERT": "خبير", + "GAME_MODE_NO_HELPERS": "بدون مساعدات - مهارة خالصة مطلوبة", "HOW_TO_PLAY": "كيفية اللعب", "HOW_GOAL": "الهدف هو إزالة جميع البلاط في أزواج مفتوحة من لوحة اللعبة.", "HOW_OPEN": "مفتوح", diff --git a/src/assets/i18n/bn.json b/src/assets/i18n/bn.json index 2ccd2d75..7b0348c9 100644 --- a/src/assets/i18n/bn.json +++ b/src/assets/i18n/bn.json @@ -30,7 +30,9 @@ "SETTINGS": "সেটিংস", "STATS": "পরিসংখ্যান", "MODE": "বোর্ড ফিল অ্যালগরিদম", - "MODE_SOLVABLE": "সমাধানযোগ্য", + "MODE_SOLVABLE": "সমাধানযোগ্য (মানক)", + "MODE_SOLVABLE_EASY": "সমাধানযোগ্য (সহজ)", + "MODE_SOLVABLE_EXPERT": "সমাধানযোগ্য (বিশেষজ্ঞ)", "MODE_RANDOM": "এলোমেলো", "RANDOM_GROUP": "এলোমেলো", "RANDOM_LAYOUT": "এলোমেলো", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://bn.wikipedia.org/wiki/Mahjong", "TILES_INFO": "টাইলের তথ্য", "TILES": "টাইল", - "INFO_LONG": "টাইলের তথ্য", + "TILES_INFO_LONG": "গেমের সব টাইলের সারসংক্ষেপ", "HELP": "সাহায্য", "HELP_LONG": "এই ডায়ালগ দেখান/লুকান", "SETTINGS_LONG": "ভাষা, টাইল সেট ও রং সামঞ্জস্য করুন", - "MODE_SOLVABLE_DESC": "অন্তত একটি সমাধানের সম্ভাবনা সহ এলোমেলো পূরণ", - "MODE_RANDOM_DESC": "সম্পূর্ণ এলোমেলো পূরণ, হয়তো সমাধানযোগ্য নয়", + "MODE_SOLVABLE_DESC": "নিশ্চিতভাবে কমপক্ষে একটি সমাধান আছে", + "MODE_SOLVABLE_EASY_DESC": "সহজ কঠিনতা - মেলানোর জন্য প্রচুর জুড়ি উপলব্ধ", + "MODE_SOLVABLE_EXPERT_DESC": "একসাথে খুব কম জুড়ি উপলব্ধ - সতর্ক পরিকল্পনা প্রয়োজন", + "MODE_RANDOM_DESC": "সম্পূর্ণ এলোমেলো বিন্যাস - সম্ভবত সমাধানযোগ্য নয়", "SELECT_BOARD": "বোর্ড নির্বাচন করুন", "BOARD_GENERATOR": "বোর্ড জেনারেটর", "START_SELECTED": "নির্বাচিত শুরু করুন", - "START_RANDOM": "এলোমেলো শুরু করুন", + "START_RANDOM": "এলোমেলো বোর্ড খেলুন", "TILESET": "টাইলসেট আর্ট", "BACKGROUND": "পটভূমি", "INFO": "তথ্য", @@ -190,10 +194,13 @@ "t_e9": "অতিরিক্ত ৯", "SHUFFLE": "এলোমেলো করুন", "SHUFFLE_LONG": "গেমের পাথরগুলো এলোমেলো করুন", + "RESCUE_SHUFFLE": "চালিয়ে যেতে এলোমেলো করুন", + "RESCUE_SHUFFLE_LONG": "আর কোনো চাল না থাকলে এলোমেলো করুন", "GAME_MODE": "মোড", "GAME_MODE_EASY": "সহজ", "GAME_MODE_STANDARD": "মানক", "GAME_MODE_EXPERT": "বিশেষজ্ঞ", + "GAME_MODE_NO_HELPERS": "কোনো সাহায্য নেই - বিশুদ্ধ দক্ষতা প্রয়োজন", "HOW_TO_PLAY": "কীভাবে খেলবেন", "HOW_GOAL": "লক্ষ্য হলো গেম বোর্ড থেকে মুক্ত জোড়ায় সব টাইল সরানো।", "HOW_OPEN": "মুক্ত", diff --git a/src/assets/i18n/ca.json b/src/assets/i18n/ca.json index cc1355d2..8a26f241 100644 --- a/src/assets/i18n/ca.json +++ b/src/assets/i18n/ca.json @@ -30,7 +30,9 @@ "SETTINGS": "Configuració", "STATS": "Estadístiques", "MODE": "Algoritme d'ompliment de tauler", - "MODE_SOLVABLE": "Resoluble", + "MODE_SOLVABLE": "Resoluble (Estàndard)", + "MODE_SOLVABLE_EASY": "Resoluble (Fàcil)", + "MODE_SOLVABLE_EXPERT": "Resoluble (Expert)", "MODE_RANDOM": "Aleatori", "RANDOM_GROUP": "Aleatori", "RANDOM_LAYOUT": "Aleatori", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://ca.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Informació de fitxes", "TILES": "Fitxes", - "INFO_LONG": "Informació de fitxes", + "TILES_INFO_LONG": "Visió general de totes les fitxes del joc", "HELP": "Ajuda", "HELP_LONG": "Mostrar/amagar aquest diàleg", "SETTINGS_LONG": "Ajusta l'idioma, els conjunts de fitxes i els colors", - "MODE_SOLVABLE_DESC": "Un ompliment aleatori amb almenys una possibilitat de solució", - "MODE_RANDOM_DESC": "Un ompliment totalment aleatori, potser insoluble", + "MODE_SOLVABLE_DESC": "Garantit que té almenys una solució", + "MODE_SOLVABLE_EASY_DESC": "Dificultat relaxada - moltes parelles disponibles per combinar", + "MODE_SOLVABLE_EXPERT_DESC": "Poques parelles disponibles alhora - requereix planificació acurada", + "MODE_RANDOM_DESC": "Disposició completament aleatòria - possiblement insoluble", "SELECT_BOARD": "Selecciona el tauler", "BOARD_GENERATOR": "Generador de tauler", "START_SELECTED": "Comença seleccionar", - "START_RANDOM": "Comença aleatori", + "START_RANDOM": "Juga un tauler aleatori", "TILESET": "Art de fitxes", "BACKGROUND": "Fons", "INFO": "Informació", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Barallar", "SHUFFLE_LONG": "Baralla les pedres al joc", + "RESCUE_SHUFFLE": "Baralla per continuar", + "RESCUE_SHUFFLE_LONG": "Baralla si no hi ha més moviments", "GAME_MODE": "Mode", "GAME_MODE_EASY": "Fàcil", "GAME_MODE_STANDARD": "Estàndard", "GAME_MODE_EXPERT": "Expert", + "GAME_MODE_NO_HELPERS": "Sense ajudes - cal habilitat pura", "HOW_TO_PLAY": "Com jugar", "HOW_GOAL": "L'objectiu és eliminar totes les fitxes en parelles obertes del tauler de joc.", "HOW_OPEN": "Obrir", diff --git a/src/assets/i18n/cs.json b/src/assets/i18n/cs.json index d2e70195..03e9e96b 100644 --- a/src/assets/i18n/cs.json +++ b/src/assets/i18n/cs.json @@ -30,7 +30,9 @@ "SETTINGS": "Nastavení", "STATS": "Statistika", "MODE": "Algoritmus vyplnění desky", - "MODE_SOLVABLE": "Řešitelné", + "MODE_SOLVABLE": "Řešitelné (Standardní)", + "MODE_SOLVABLE_EASY": "Řešitelné (Snadné)", + "MODE_SOLVABLE_EXPERT": "Řešitelné (Expert)", "MODE_RANDOM": "Náhodné", "RANDOM_GROUP": "Náhodné", "RANDOM_LAYOUT": "Náhodné", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://cs.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Informace o dlaždicích", "TILES": "Dlaždice", - "INFO_LONG": "Informace o dlaždicích", + "TILES_INFO_LONG": "Přehled všech dlaždic ve hře", "HELP": "Pomoc", "HELP_LONG": "Zobrazit/skrýt tento dialog", "SETTINGS_LONG": "Upravte jazyk, sady dlaždic a barvy", - "MODE_SOLVABLE_DESC": "Náhodné vyplnění s alespoň jednou možností řešení", - "MODE_RANDOM_DESC": "Zcela náhodné vyplnění, možná neřešitelné", + "MODE_SOLVABLE_DESC": "Zaručeně má alespoň jedno řešení", + "MODE_SOLVABLE_EASY_DESC": "Uvolněná obtížnost - k párování je k dispozici mnoho párů", + "MODE_SOLVABLE_EXPERT_DESC": "Najednou je k dispozici málo párů - vyžaduje pečlivé plánování", + "MODE_RANDOM_DESC": "Zcela náhodné rozmístění - možná neřešitelné", "SELECT_BOARD": "Vybrat desku", "BOARD_GENERATOR": "Generátor desek", "START_SELECTED": "Spustit vybrané", - "START_RANDOM": "Spustit náhodné", + "START_RANDOM": "Hrát náhodnou desku", "TILESET": "Umění dlaždic", "BACKGROUND": "Pozadí", "INFO": "Info", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Zamíchat", "SHUFFLE_LONG": "Zamíchat kameny ve hře", + "RESCUE_SHUFFLE": "Zamíchat pro pokračování", + "RESCUE_SHUFFLE_LONG": "Zamíchat, pokud nejsou žádné další tahy", "GAME_MODE": "Režim", "GAME_MODE_EASY": "Snadné", "GAME_MODE_STANDARD": "Standardní", "GAME_MODE_EXPERT": "Expert", + "GAME_MODE_NO_HELPERS": "Bez pomůcek - vyžaduje čistou dovednost", "HOW_TO_PLAY": "Jak hrát", "HOW_GOAL": "Cílem je odstranit ze hracího pole všechny dlaždice v otevřených párech.", "HOW_OPEN": "Otevřít", diff --git a/src/assets/i18n/da.json b/src/assets/i18n/da.json index 2b7cf80a..72398bc7 100644 --- a/src/assets/i18n/da.json +++ b/src/assets/i18n/da.json @@ -30,7 +30,9 @@ "SETTINGS": "Indstillinger", "STATS": "Statistik", "MODE": "Algorithms til bræt-fyldning", - "MODE_SOLVABLE": "Løsbar", + "MODE_SOLVABLE": "Løsbar (Standard)", + "MODE_SOLVABLE_EASY": "Løsbar (Let)", + "MODE_SOLVABLE_EXPERT": "Løsbar (Ekspert)", "MODE_RANDOM": "Tilfældig", "RANDOM_GROUP": "Tilfældig", "RANDOM_LAYOUT": "Tilfældig", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://da.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Brikker information", "TILES": "Brikker", - "INFO_LONG": "Brikker information", + "TILES_INFO_LONG": "Oversigt over alle brikker i spillet", "HELP": "Hjælp", "HELP_LONG": "Vis/skjul denne dialog", "SETTINGS_LONG": "Juster sprog, brikkesæt og farver", - "MODE_SOLVABLE_DESC": "Tilfældig fyldning med mindst en løsningsmulighed", - "MODE_RANDOM_DESC": "Fuldstændig tilfældig fyldning, måske uløselig", + "MODE_SOLVABLE_DESC": "Garanteret at have mindst én løsning", + "MODE_SOLVABLE_EASY_DESC": "Afslappet sværhedsgrad - masser af par tilgængelige til matchning", + "MODE_SOLVABLE_EXPERT_DESC": "Få par tilgængelige ad gangen - kræver omhyggelig planlægning", + "MODE_RANDOM_DESC": "Fuldstændig tilfældig layout - muligvis uløselig", "SELECT_BOARD": "Vælg bræt", "BOARD_GENERATOR": "Bræt generator", "START_SELECTED": "Start valgt", - "START_RANDOM": "Start tilfældig", + "START_RANDOM": "Spil tilfældig bræt", "TILESET": "Brikke kunst", "BACKGROUND": "Baggrund", "INFO": "Info", @@ -190,10 +194,13 @@ "t_e9": "Ekstra 9", "SHUFFLE": "Bland", "SHUFFLE_LONG": "Bland sten i spillet", + "RESCUE_SHUFFLE": "Bland for at fortsætte", + "RESCUE_SHUFFLE_LONG": "Bland hvis der ikke er flere træk", "GAME_MODE": "Tilstand", "GAME_MODE_EASY": "Let", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Ekspert", + "GAME_MODE_NO_HELPERS": "Ingen hjælpemidler - ren dygtighed kræves", "HOW_TO_PLAY": "Sådan spiller du", "HOW_GOAL": "Målet er at fjerne alle brikker i åbne par fra spillebrættet.", "HOW_OPEN": "Åben", diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 977439f7..1e3fcec0 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -17,7 +17,7 @@ "MSG_PLAY_AGAIN": "Nochmal spielen", "MSG_BEST": "Gratulation, neue Bestzeit!", "MSG_GOOD": "Sehr schön!", - "MSG_FAIL": "Keine passenden Ziegel mehr.", + "MSG_FAIL": "Keine passenden Steine mehr.", "STATS_GAMES": "Anzahl Spiele", "STATS_NAME": "Name", "STATS_WIN_GAMES": "Gewonnen", @@ -30,7 +30,9 @@ "SETTINGS": "Einstellungen", "STATS": "Statistik", "MODE": "Spielbrett-Algorithmus", - "MODE_SOLVABLE": "Lösbar", + "MODE_SOLVABLE": "Lösbar (Standard)", + "MODE_SOLVABLE_EASY": "Lösbar (Einfach)", + "MODE_SOLVABLE_EXPERT": "Lösbar (Experte)", "MODE_RANDOM": "Zufällig", "RANDOM_GROUP": "Zufall", "RANDOM_LAYOUT": "Zufall", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://de.wikipedia.org/wiki/Mah-Jongg", "TILES_INFO": "Steinverzeichnis", "TILES": "Steine", - "INFO_LONG": "Steinverzeichnis", + "TILES_INFO_LONG": "Überblick über alle Steine im Spiel", "HELP": "Hilfe", "HELP_LONG": "Diesen Dialog anzeigen/ausblenden", "SETTINGS_LONG": "Sprache, Steine und Farben anpassen", - "MODE_SOLVABLE_DESC": "Fast zufälliger Aufbau mit mindestens einer Lösung", - "MODE_RANDOM_DESC": "Zufälliger Aufbau, vielleicht unlösbar", + "MODE_SOLVABLE_DESC": "Garantiert lösbar mit mindestens einer Lösung", + "MODE_SOLVABLE_EASY_DESC": "Entspannte Schwierigkeit - viele Paare verfügbar", + "MODE_SOLVABLE_EXPERT_DESC": "Wenige Paare auf einmal verfügbar - erfordert sorgfältige Planung", + "MODE_RANDOM_DESC": "Vollständig zufälliger Aufbau - möglicherweise unlösbar", "SELECT_BOARD": "Spielbrett auswählen", "BOARD_GENERATOR": "Spielgenerator", "START_SELECTED": "Auswahl starten", - "START_RANDOM": "Zufälliges starten", + "START_RANDOM": "Zufälliges Spielfeld spielen", "TILESET": "Stein-Motive", "BACKGROUND": "Hintergrund", "INFO": "Info", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Mischen", "SHUFFLE_LONG": "Steine im Spiel mischen", + "RESCUE_SHUFFLE": "Mischen zum Weiterspielen", + "RESCUE_SHUFFLE_LONG": "Mischen wenn keine Züge mehr möglich sind", "GAME_MODE": "Modus", "GAME_MODE_EASY": "Einfach", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Profi", + "GAME_MODE_NO_HELPERS": "Ohne Hilfsmittel - nur Können zählt", "HOW_TO_PLAY": "Spielanleitung", "HOW_GOAL": "Das Ziel ist es, alle Steine in offenen Paaren vom Spielbrett zu entfernen.", "HOW_OPEN": "Offen", @@ -214,20 +221,20 @@ "EDITOR_EXPORT": "Exportieren", "EDITOR_EXPORT_LONG": "Exportiere Boards in Dateien", "EDITOR_NEW_LAYER_LONG": "Neues Ebene unterhalb", - "EDITOR_MOVE_TILES_UP_LONG": "Kacheln nach oben verschieben", - "EDITOR_MOVE_TILES_DOWN_LONG": "Kacheln nach unten verschieben", - "EDITOR_MOVE_TILES_LEFT_LONG": "Kacheln nach links verschieben", - "EDITOR_MOVE_TILES_RIGHT_LONG": "Kacheln nach rechts verschieben", + "EDITOR_MOVE_TILES_UP_LONG": "Steine nach oben verschieben", + "EDITOR_MOVE_TILES_DOWN_LONG": "Steine nach unten verschieben", + "EDITOR_MOVE_TILES_LEFT_LONG": "Steine nach links verschieben", + "EDITOR_MOVE_TILES_RIGHT_LONG": "Steine nach rechts verschieben", "EDITOR_MOVE_LAYER_UP_LONG": "Ebene nach oben verschieben", "EDITOR_MOVE_LAYER_DOWN_LONG": "Ebene nach unten verschieben", "EDITOR_DUPLICATE_LAYER_LONG": "Ebene duplizieren", "EDITOR_CLEAR_LAYER_LONG": "Ebene leeren", "EDITOR_DELETE_LAYER_LONG": "Ebene löschen", "EDITOR_DISCARD_CHANGES_SURE": "Änderungen verwerfen?", - "EDITOR_MOVE_ALL_TILES_UP_LONG": "Alle Kacheln nach oben verschieben", - "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Alle Kacheln nach unten verschieben", - "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Alle Kacheln nach links verschieben", - "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Alle Kacheln nach rechts verschieben", + "EDITOR_MOVE_ALL_TILES_UP_LONG": "Alle Steine nach oben verschieben", + "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Alle Steine nach unten verschieben", + "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Alle Steine nach links verschieben", + "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Alle Steine nach rechts verschieben", "EDITOR_LAYOUT_NAME": "Name", "EDITOR_LAYOUT_BY": "Von", "EDITOR_LAYOUT_CATEGORY": "Kategorie", diff --git a/src/assets/i18n/el.json b/src/assets/i18n/el.json index ff49c2a4..10a0b405 100644 --- a/src/assets/i18n/el.json +++ b/src/assets/i18n/el.json @@ -30,7 +30,9 @@ "SETTINGS": "Ρυθμίσεις", "STATS": "Στατιστικά", "MODE": "Αλγόριθμος γεμίσματος σανίδας", - "MODE_SOLVABLE": "Επιλύσιμο", + "MODE_SOLVABLE": "Επιλύσιμο (Τυπικό)", + "MODE_SOLVABLE_EASY": "Επιλύσιμο (Εύκολο)", + "MODE_SOLVABLE_EXPERT": "Επιλύσιμο (Ειδικός)", "MODE_RANDOM": "Τυχαίο", "RANDOM_GROUP": "Τυχαίο", "RANDOM_LAYOUT": "Τυχαίο", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "Πληροφορίες πλακιδίων", "TILES": "Πλακάκια", - "INFO_LONG": "Πληροφορίες πλακιδίων", + "TILES_INFO_LONG": "Επισκόπηση όλων των πλακιδίων στο παιχνίδι", "HELP": "Βοήθεια", "HELP_LONG": "Εμφάνιση / απόκρυψη αυτού του διαλόγου", "SETTINGS_LONG": "Προσαρμόστε τη γλώσσα, τα σετ πλακιδίων και τα χρώματα", - "MODE_SOLVABLE_DESC": "Ένα τυχαίο γέμισμα με τουλάχιστον μία δυνατότητα επίλυσης", - "MODE_RANDOM_DESC": "Ένα εντελώς τυχαίο γέμισμα, ίσως άλυτο", + "MODE_SOLVABLE_DESC": "Εγγυημένα έχει τουλάχιστον μία λύση", + "MODE_SOLVABLE_EASY_DESC": "Χαλαρή δυσκολία - άφθονα ζεύγη διαθέσιμα για αντιστοίχιση", + "MODE_SOLVABLE_EXPERT_DESC": "Λίγα ζεύγη διαθέσιμα ταυτόχρονα - απαιτεί προσεκτικό σχεδιασμό", + "MODE_RANDOM_DESC": "Πλήρως τυχαία διάταξη - πιθανώς άλυτο", "SELECT_BOARD": "Επιλέξτε σανίδα", "BOARD_GENERATOR": "Γεννήτρια σανίδας", "START_SELECTED": "Ξεκίνημα επιλεγμένου", - "START_RANDOM": "Ξεκίνημα τυχαίου", + "START_RANDOM": "Παίξτε τυχαία σανίδα", "TILESET": "Τέχνη πλακιδίων", "BACKGROUND": "Φόντο", "INFO": "Πληροφορίες", @@ -190,10 +194,13 @@ "t_e9": "Επιπλέον 9", "SHUFFLE": "Ανακάτεψη", "SHUFFLE_LONG": "Ανακάτεψη πετρών στο παιχνίδι", + "RESCUE_SHUFFLE": "Ανακάτεψη για συνέχεια", + "RESCUE_SHUFFLE_LONG": "Ανακάτεψη αν δεν υπάρχουν άλλες κινήσεις", "GAME_MODE": "Κατάσταση λειτουργίας", "GAME_MODE_EASY": "Εύκολο", "GAME_MODE_STANDARD": "Τυπικό", "GAME_MODE_EXPERT": "Ειδικός", + "GAME_MODE_NO_HELPERS": "Χωρίς βοήθεια - απαιτείται καθαρή ικανότητα", "HOW_TO_PLAY": "Πώς να παίξετε", "HOW_GOAL": "Ο στόχος είναι να αφαιρεθούν όλα τα πλακάκια σε ανοιχτά ζεύγη από τη σανίδα παιχνιδιού.", "HOW_OPEN": "Ανοικτό", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 4c0cbbde..fbc1dada 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -8,7 +8,7 @@ "USE_NOW": "Use now", "FULLSCREEN": "Fullscreen", "HINT_LONG": "Show possible moves", - "UNDO_LONG": "Undo last move", + "UNDO_LONG": "Undo last moves", "RESTART_LONG": "Start a new game", "PAUSE_LONG": "Continue/Pause game", "MSG_CONTINUE_PAUSE": "Continue Game…", @@ -30,7 +30,9 @@ "SETTINGS": "Settings", "STATS": "Statistics", "MODE": "Board Fill Algorithm", - "MODE_SOLVABLE": "Solvable", + "MODE_SOLVABLE": "Solvable (Standard)", + "MODE_SOLVABLE_EASY": "Solvable (Easy)", + "MODE_SOLVABLE_EXPERT": "Solvable (Expert)", "MODE_RANDOM": "Random", "RANDOM_GROUP": "Random", "RANDOM_LAYOUT": "Random", @@ -52,16 +54,19 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "Tiles Information", "TILES": "Tiles", - "INFO_LONG": "Tiles Information", + "TILES_INFO_LONG": "Overview of all tiles in the game", "HELP": "Help", "HELP_LONG": "Show/hide this dialog", "SETTINGS_LONG": "Adjust language, tile sets & colors", - "MODE_SOLVABLE_DESC": "A random fill with at least one solving possibility", - "MODE_RANDOM_DESC": "A total random fill, maybe unsolvable", + "MODE_SOLVABLE_DESC": "Guaranteed to have at least one solution", + "MODE_SOLVABLE_EASY_DESC": "Relaxed difficulty - plenty of pairs available to match", + "MODE_SOLVABLE_EXPERT_DESC": "Few pairs available at once - demands careful planning", + "MODE_RANDOM_DESC": "Fully random layout - possibly unsolvable", + "GAME_MODE_NO_HELPERS": "No helpers - pure skill required", "SELECT_BOARD": "Select Board", "BOARD_GENERATOR": "Board Generator", "START_SELECTED": "Start Selected", - "START_RANDOM": "Start Random", + "START_RANDOM": "Play Random Board", "TILESET": "Tileset Art", "BACKGROUND": "Background", "INFO": "Info", @@ -190,6 +195,8 @@ "t_e9": "Extra 9", "SHUFFLE": "Shuffle", "SHUFFLE_LONG": "Shuffle stones in the game", + "RESCUE_SHUFFLE": "Shuffle to Continue", + "RESCUE_SHUFFLE_LONG": "Shuffle if there are no more moves", "GAME_MODE": "Mode", "GAME_MODE_EASY": "Easy", "GAME_MODE_STANDARD": "Standard", diff --git a/src/assets/i18n/es.json b/src/assets/i18n/es.json index ba981d34..ae721d92 100644 --- a/src/assets/i18n/es.json +++ b/src/assets/i18n/es.json @@ -30,7 +30,9 @@ "SETTINGS": "Ajustes", "STATS": "Estadísticas", "MODE": "Algoritmo de relleno del tablero", - "MODE_SOLVABLE": "Resoluble", + "MODE_SOLVABLE": "Resoluble (Normal)", + "MODE_SOLVABLE_EASY": "Resoluble (Fácil)", + "MODE_SOLVABLE_EXPERT": "Resoluble (Experto)", "MODE_RANDOM": "Aleatorio", "RANDOM_GROUP": "Aleatorio", "RANDOM_LAYOUT": "Aleatorio", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://es.wikipedia.org/wiki/Mahjong#fichas", "TILES_INFO": "Información sobre las fichas", "TILES": "Fichas", - "INFO_LONG": "Información sobre las fichas", + "TILES_INFO_LONG": "Resumen de todas las fichas del juego", "HELP": "Ayuda", "HELP_LONG": "Mostrar/ocultar esta ventana", "SETTINGS_LONG": "Configurar idioma, conjunto de fichas y colores", - "MODE_SOLVABLE_DESC": "Relleno aleatorio con al menos una solución posible", - "MODE_RANDOM_DESC": "Relleno totalmente aleatorio, quizás sin solución", + "MODE_SOLVABLE_DESC": "Garantizado que tiene al menos una solución", + "MODE_SOLVABLE_EASY_DESC": "Dificultad relajada - muchos pares disponibles para combinar", + "MODE_SOLVABLE_EXPERT_DESC": "Pocos pares disponibles a la vez - exige planificación cuidadosa", + "MODE_RANDOM_DESC": "Distribución completamente aleatoria - posiblemente sin solución", "SELECT_BOARD": "Seleccionar tablero", "BOARD_GENERATOR": "Generador de tablero", "START_SELECTED": "Iniciar seleccionado", - "START_RANDOM": "Iniciar aleatorio", + "START_RANDOM": "Jugar tablero aleatorio", "TILESET": "Diseño de las fichas", "BACKGROUND": "Fondo", "INFO": "Información", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Barajar", "SHUFFLE_LONG": "Barajar fichas en la partida", + "RESCUE_SHUFFLE": "Barajar para continuar", + "RESCUE_SHUFFLE_LONG": "Barajar si no hay más movimientos", "GAME_MODE": "Modo", "GAME_MODE_EASY": "Fácil", "GAME_MODE_STANDARD": "Normal", "GAME_MODE_EXPERT": "Experto", + "GAME_MODE_NO_HELPERS": "Sin ayudas - se requiere habilidad pura", "HOW_TO_PLAY": "Cómo jugar", "HOW_GOAL": "El objetivo es eliminar todos los pares de fichas abiertas del tablero de juego.", "HOW_OPEN": "Abierto", diff --git a/src/assets/i18n/eu.json b/src/assets/i18n/eu.json index 68f1c828..16e0f579 100644 --- a/src/assets/i18n/eu.json +++ b/src/assets/i18n/eu.json @@ -30,7 +30,9 @@ "SETTINGS": "Ezarpenak", "STATS": "Estatistikak", "MODE": "Taula betetzeko algoritmoa", - "MODE_SOLVABLE": "Ebazgarria", + "MODE_SOLVABLE": "Ebazgarria (Arrunta)", + "MODE_SOLVABLE_EASY": "Ebazgarria (Erraza)", + "MODE_SOLVABLE_EXPERT": "Ebazgarria (Aditua)", "MODE_RANDOM": "Ausaz", "RANDOM_GROUP": "Ausaz", "RANDOM_LAYOUT": "Ausaz", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "Fitxen informazioa", "TILES": "Fitxak", - "INFO_LONG": "Fitxen informazioa", + "TILES_INFO_LONG": "Jokoko fitxa guztien ikuspegi orokorra", "HELP": "Laguntza", "HELP_LONG": "Erakutsi/ezkutatu leiho hau", "SETTINGS_LONG": "Doitu hizkuntza, fitxa-sortak eta koloreak", - "MODE_SOLVABLE_DESC": "Ausaz osatu, gutxienez ebazteko aukera batekin", - "MODE_RANDOM_DESC": "Erabateko ausaz osatu, nahiz eta ebatzi ezina izan", + "MODE_SOLVABLE_DESC": "Gutxienez irtenbide bat duela bermatuta", + "MODE_SOLVABLE_EASY_DESC": "Zailtasun erlaxatua - pare ugari eskuragarri", + "MODE_SOLVABLE_EXPERT_DESC": "Pare gutxi aldi berean eskuragarri - plangintza arretatsua eskatzen du", + "MODE_RANDOM_DESC": "Ausazko banaketa osoa - agian ebaztezinik", "SELECT_BOARD": "Aukeratu taula", "BOARD_GENERATOR": "Taula-sortzailea", "START_SELECTED": "Hasi hautatutakoa", - "START_RANDOM": "Hasi ausazkoa", + "START_RANDOM": "Jolastu ausazko taula", "TILESET": "Fitxa-sorten artea", "BACKGROUND": "Atzeko planoa", "INFO": "Infoa", @@ -190,10 +194,13 @@ "t_e9": "Estra 9", "SHUFFLE": "Nahastu", "SHUFFLE_LONG": "Nahastu taulako harriak", + "RESCUE_SHUFFLE": "Nahastu jarraitzeko", + "RESCUE_SHUFFLE_LONG": "Nahastu mugimendurik ez badago", "GAME_MODE": "Modua", "GAME_MODE_EASY": "Erraza", "GAME_MODE_STANDARD": "Arrunta", "GAME_MODE_EXPERT": "Aditua", + "GAME_MODE_NO_HELPERS": "Laguntzarik gabe - trebetasun hutsa behar da", "HOW_TO_PLAY": "Nola jokatu", "HOW_GOAL": "Helburua taulatik fitxa gutziak kentzea da, aske dauden fitxekin bikoteak osatuz.", "HOW_OPEN": "Ireki", diff --git a/src/assets/i18n/fa.json b/src/assets/i18n/fa.json index 27220efc..d71cd05c 100644 --- a/src/assets/i18n/fa.json +++ b/src/assets/i18n/fa.json @@ -30,7 +30,9 @@ "SETTINGS": "تنظیمات", "STATS": "آمار", "MODE": "الگوریتم پر کردن صفحه", - "MODE_SOLVABLE": "قابل حل", + "MODE_SOLVABLE": "قابل حل (استاندارد)", + "MODE_SOLVABLE_EASY": "قابل حل (آسان)", + "MODE_SOLVABLE_EXPERT": "قابل حل (متخصص)", "MODE_RANDOM": "تصادفی", "RANDOM_GROUP": "تصادفی", "RANDOM_LAYOUT": "تصادفی", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://fa.wikipedia.org/wiki/ماجونگ", "TILES_INFO": "اطلاعات کاشی‌ها", "TILES": "کاشی‌ها", - "INFO_LONG": "اطلاعات کاشی‌ها", + "TILES_INFO_LONG": "مروری بر همه کاشی های بازی", "HELP": "راهنما", "HELP_LONG": "نمایش/مخفی کردن این پنجره", "SETTINGS_LONG": "تنظیم زبان، مجموعه کاشی و رنگ‌ها", - "MODE_SOLVABLE_DESC": "پر کردن تصادفی با حداقل یک راه‌حل", - "MODE_RANDOM_DESC": "پر کردن کاملاً تصادفی، شاید غیرقابل حل", + "MODE_SOLVABLE_DESC": "تضمین شده دارای حداقل یک راه‌حل است", + "MODE_SOLVABLE_EASY_DESC": "سختی آسان‌گیرانه - جفت‌های فراوانی برای تطبیق در دسترس", + "MODE_SOLVABLE_EXPERT_DESC": "جفت‌های کمی به‌طور همزمان در دسترس - نیاز به برنامه‌ریزی دقیق", + "MODE_RANDOM_DESC": "چیدمان کاملاً تصادفی - احتمالاً غیرقابل حل", "SELECT_BOARD": "انتخاب صفحه", "BOARD_GENERATOR": "سازنده صفحه", "START_SELECTED": "شروع انتخابی", - "START_RANDOM": "شروع تصادفی", + "START_RANDOM": "بازی صفحه تصادفی", "TILESET": "هنر کاشی", "BACKGROUND": "پس‌زمینه", "INFO": "اطلاعات", @@ -190,10 +194,13 @@ "t_e9": "اضافی ۹", "SHUFFLE": "به‌هم‌ریختن", "SHUFFLE_LONG": "به‌هم ریختن سنگ‌ها در بازی", + "RESCUE_SHUFFLE": "به‌هم‌ریختن برای ادامه", + "RESCUE_SHUFFLE_LONG": "به‌هم ریختن اگر حرکتی نمانده باشد", "GAME_MODE": "حالت", "GAME_MODE_EASY": "آسان", "GAME_MODE_STANDARD": "استاندارد", "GAME_MODE_EXPERT": "حرفه‌ای", + "GAME_MODE_NO_HELPERS": "بدون کمک - مهارت خالص لازم است", "HOW_TO_PLAY": "نحوه بازی", "HOW_GOAL": "هدف حذف تمام کاشی‌ها به صورت جفت‌های باز از صفحه بازی است.", "HOW_OPEN": "باز", diff --git a/src/assets/i18n/fi.json b/src/assets/i18n/fi.json index 53d4bc95..f8e7eaf2 100644 --- a/src/assets/i18n/fi.json +++ b/src/assets/i18n/fi.json @@ -30,7 +30,9 @@ "SETTINGS": "Asetukset", "STATS": "Tilastot", "MODE": "Lautapelin täyttöalgoritmi", - "MODE_SOLVABLE": "Ratkaistavissa", + "MODE_SOLVABLE": "Ratkaistavissa (Vakio)", + "MODE_SOLVABLE_EASY": "Ratkaistavissa (Helppo)", + "MODE_SOLVABLE_EXPERT": "Ratkaistavissa (Asiantuntija)", "MODE_RANDOM": "Satunnainen", "RANDOM_GROUP": "Satunnainen", "RANDOM_LAYOUT": "Satunnainen", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://fi.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Kivien tiedot", "TILES": "Kivet", - "INFO_LONG": "Kivien tiedot", + "TILES_INFO_LONG": "Yleiskatsaus kaikkiin pelin laattoihin", "HELP": "Ohje", "HELP_LONG": "Näytä/piilota tämä dialogi", "SETTINGS_LONG": "Säädä kieltä, kivisetejä ja värejä", - "MODE_SOLVABLE_DESC": "Satunnainen täyttö, jossa on vähintään yksi ratkaisumahdollisuus", - "MODE_RANDOM_DESC": "Täysin satunnainen täyttö, ehkä ratkaisematon", + "MODE_SOLVABLE_DESC": "Taattu vähintään yksi ratkaisu", + "MODE_SOLVABLE_EASY_DESC": "Rento vaikeustaso - runsaasti pareja yhdistettäväksi", + "MODE_SOLVABLE_EXPERT_DESC": "Vähän pareja kerrallaan saatavilla - vaatii huolellista suunnittelua", + "MODE_RANDOM_DESC": "Täysin satunnainen asettelu - mahdollisesti ratkaisematon", "SELECT_BOARD": "Valitse lauta", "BOARD_GENERATOR": "Lautapelin luoja", "START_SELECTED": "Aloita valittu", - "START_RANDOM": "Aloita satunnainen", + "START_RANDOM": "Pelaa satunnainen lauta", "TILESET": "Kivitaiteen tyyli", "BACKGROUND": "Tausta", "INFO": "Tiedot", @@ -190,10 +194,13 @@ "t_e9": "Lisä 9", "SHUFFLE": "Sekoita", "SHUFFLE_LONG": "Sekoita kivet pelissä", + "RESCUE_SHUFFLE": "Sekoita jatkaaksesi", + "RESCUE_SHUFFLE_LONG": "Sekoita jos ei ole enää siirtoja", "GAME_MODE": "Tila", "GAME_MODE_EASY": "Helppo", "GAME_MODE_STANDARD": "Vakio", "GAME_MODE_EXPERT": "Asiantuntija", + "GAME_MODE_NO_HELPERS": "Ei apuvälineitä - vaaditaan puhdasta taitoa", "HOW_TO_PLAY": "Kuinka pelata", "HOW_GOAL": "Tavoitteena on poistaa kaikki kivet avoimissa pareissa pelilauta.", "HOW_OPEN": "Avoin", diff --git a/src/assets/i18n/fil.json b/src/assets/i18n/fil.json index 728c24c8..45ab9f28 100644 --- a/src/assets/i18n/fil.json +++ b/src/assets/i18n/fil.json @@ -30,7 +30,9 @@ "SETTINGS": "Mga Setting", "STATS": "Estadistika", "MODE": "Paraan ng Pagpuno ng Board", - "MODE_SOLVABLE": "Malulutas", + "MODE_SOLVABLE": "Malulutas (Karaniwan)", + "MODE_SOLVABLE_EASY": "Malulutas (Madali)", + "MODE_SOLVABLE_EXPERT": "Malulutas (Eksperto)", "MODE_RANDOM": "Random", "RANDOM_GROUP": "Random", "RANDOM_LAYOUT": "Random", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://tl.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Impormasyon ng mga Tile", "TILES": "Mga Tile", - "INFO_LONG": "Impormasyon ng mga Tile", + "TILES_INFO_LONG": "Pangkalahatang-ideya ng lahat ng tile sa laro", "HELP": "Tulong", "HELP_LONG": "Ipakita/itago ang dialog na ito", "SETTINGS_LONG": "Ayusin ang wika, tile set at mga kulay", - "MODE_SOLVABLE_DESC": "Random na pagpuno na may kahit isang solusyon", - "MODE_RANDOM_DESC": "Ganap na random na pagpuno, maaaring hindi malulutas", + "MODE_SOLVABLE_DESC": "Garantisadong may kahit isang solusyon", + "MODE_SOLVABLE_EASY_DESC": "Nakakarelaks na kahirapan - maraming pares na available para itugma", + "MODE_SOLVABLE_EXPERT_DESC": "Kakaunting pares na available nang sabay - nangangailangan ng maingat na pagpaplano", + "MODE_RANDOM_DESC": "Ganap na random na layout - posibleng hindi malulutas", "SELECT_BOARD": "Pumili ng Board", "BOARD_GENERATOR": "Tagabuo ng Board", "START_SELECTED": "Simulan ang Napili", - "START_RANDOM": "Simulan ang Random", + "START_RANDOM": "Maglaro ng Random na Board", "TILESET": "Disenyo ng Tile", "BACKGROUND": "Background", "INFO": "Impormasyon", @@ -190,10 +194,13 @@ "t_e9": "Dagdag 9", "SHUFFLE": "Haluin", "SHUFFLE_LONG": "Haluin ang mga bato sa laro", + "RESCUE_SHUFFLE": "Haluin para Magpatuloy", + "RESCUE_SHUFFLE_LONG": "Haluin kung wala nang mga galaw", "GAME_MODE": "Mode", "GAME_MODE_EASY": "Madali", "GAME_MODE_STANDARD": "Karaniwan", "GAME_MODE_EXPERT": "Eksperto", + "GAME_MODE_NO_HELPERS": "Walang tulong - kailangan ng puro kasanayan", "HOW_TO_PLAY": "Paano maglaro", "HOW_GOAL": "Ang layunin ay alisin ang lahat ng tile sa mga bukas na pares mula sa board.", "HOW_OPEN": "Bukas", diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index c7d11c32..dba8bee6 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -30,7 +30,9 @@ "SETTINGS": "Paramètres", "STATS": "Statistiques", "MODE": "Algorithme de remplissage", - "MODE_SOLVABLE": "Résoluble", + "MODE_SOLVABLE": "Résoluble (Standard)", + "MODE_SOLVABLE_EASY": "Résoluble (Facile)", + "MODE_SOLVABLE_EXPERT": "Résoluble (Expert)", "MODE_RANDOM": "Aléatoire", "RANDOM_GROUP": "Aléatoire", "RANDOM_LAYOUT": "Aléatoire", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://fr.wikipedia.org/wiki/Mah-jong", "TILES_INFO": "Informations sur les tuiles", "TILES": "Tuiles", - "INFO_LONG": "Informations sur les tuiles", + "TILES_INFO_LONG": "Aperçu de toutes les tuiles du jeu", "HELP": "Aide", "HELP_LONG": "Afficher/masquer cette aide", "SETTINGS_LONG": "Ajuster la langue, les tuiles et les couleurs", - "MODE_SOLVABLE_DESC": "Un remplissage aléatoire avec au moins une solution possible", - "MODE_RANDOM_DESC": "Un remplissage totalement aléatoire, peut être impossible à résoudre", + "MODE_SOLVABLE_DESC": "Garanti d'avoir au moins une solution", + "MODE_SOLVABLE_EASY_DESC": "Difficulté détendue - de nombreuses paires disponibles à associer", + "MODE_SOLVABLE_EXPERT_DESC": "Peu de paires disponibles à la fois - exige une planification minutieuse", + "MODE_RANDOM_DESC": "Disposition entièrement aléatoire - peut être insoluble", "SELECT_BOARD": "Sélectionner un plateau", "BOARD_GENERATOR": "Générateur de plateau", "START_SELECTED": "Commencer la sélection", - "START_RANDOM": "Commencer aléatoirement", + "START_RANDOM": "Jouer un plateau aléatoire", "TILESET": "Style de tuiles", "BACKGROUND": "Arrière-plan", "INFO": "Info", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Mélanger", "SHUFFLE_LONG": "Mélanger les tuiles en jeu", + "RESCUE_SHUFFLE": "Mélanger pour continuer", + "RESCUE_SHUFFLE_LONG": "Mélanger s'il n'y a plus de mouvements", "GAME_MODE": "Mode", "GAME_MODE_EASY": "Facile", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Expert", + "GAME_MODE_NO_HELPERS": "Sans aide - pure habileté requise", "HOW_TO_PLAY": "Comment jouer", "HOW_GOAL": "Le but est d'éliminer toutes les paires de tuiles libres du plateau de jeu.", "HOW_OPEN": "Libre", diff --git a/src/assets/i18n/hi.json b/src/assets/i18n/hi.json index f8832e52..863fe5da 100644 --- a/src/assets/i18n/hi.json +++ b/src/assets/i18n/hi.json @@ -30,7 +30,9 @@ "SETTINGS": "सेटिंग्स", "STATS": "आँकड़े", "MODE": "बोर्ड भरण एल्गोरिथ्म", - "MODE_SOLVABLE": "हल करने योग्य", + "MODE_SOLVABLE": "हल करने योग्य (मानक)", + "MODE_SOLVABLE_EASY": "हल करने योग्य (आसान)", + "MODE_SOLVABLE_EXPERT": "हल करने योग्य (विशेषज्ञ)", "MODE_RANDOM": "यादृच्छिक", "RANDOM_GROUP": "यादृच्छिक", "RANDOM_LAYOUT": "यादृच्छिक", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "पत्थर की जानकारी", "TILES": "पत्थर", - "INFO_LONG": "पत्थर की जानकारी", + "TILES_INFO_LONG": "खेल में सभी टाइलों का अवलोकन", "HELP": "सहायता", "HELP_LONG": "इस संवाद को दिखाएँ/छुपाएँ", "SETTINGS_LONG": "भाषा, पत्थर सेट और रंग समायोजित करें", - "MODE_SOLVABLE_DESC": "कम से कम एक समाधान की संभावना के साथ यादृच्छिक भरण", - "MODE_RANDOM_DESC": "पूरी तरह यादृच्छिक भरण, शायद अघुलनशील", + "MODE_SOLVABLE_DESC": "कम से कम एक समाधान होने की गारंटी", + "MODE_SOLVABLE_EASY_DESC": "आसान कठिनाई - मिलान के लिए प्रचुर जोड़े उपलब्ध", + "MODE_SOLVABLE_EXPERT_DESC": "एक साथ कम जोड़े उपलब्ध - सावधानीपूर्ण योजना की मांग", + "MODE_RANDOM_DESC": "पूरी तरह यादृच्छिक लेआउट - संभवतः अघुलनशील", "SELECT_BOARD": "बोर्ड चुनें", "BOARD_GENERATOR": "बोर्ड जनरेटर", "START_SELECTED": "चयनित शुरू करें", - "START_RANDOM": "यादृच्छिक शुरू करें", + "START_RANDOM": "यादृच्छिक बोर्ड खेलें", "TILESET": "पत्थर कला", "BACKGROUND": "पृष्ठभूमि", "INFO": "जानकारी", @@ -190,10 +194,13 @@ "t_e9": "अतिरिक्त 9", "SHUFFLE": "फेरबदल", "SHUFFLE_LONG": "खेल में पत्थरों को फेरबदल करें", + "RESCUE_SHUFFLE": "जारी रखने के लिए फेरबदल", + "RESCUE_SHUFFLE_LONG": "फेरबदल करें यदि कोई और चाल नहीं है", "GAME_MODE": "तरीका", "GAME_MODE_EASY": "आसान", "GAME_MODE_STANDARD": "मानक", "GAME_MODE_EXPERT": "विशेषज्ञ", + "GAME_MODE_NO_HELPERS": "कोई सहायता नहीं - शुद्ध कौशल आवश्यक", "HOW_TO_PLAY": "कैसे खेलें", "HOW_GOAL": "लक्ष्य गेम बोर्ड से खुली जोड़ी में सभी पत्थरों को हटाना है।", "HOW_OPEN": "खुला", diff --git a/src/assets/i18n/hu.json b/src/assets/i18n/hu.json index 8ea49a4e..dfed3fe9 100644 --- a/src/assets/i18n/hu.json +++ b/src/assets/i18n/hu.json @@ -30,7 +30,9 @@ "SETTINGS": "Beállítások", "STATS": "Statisztika", "MODE": "Tábla kitöltési algoritmus", - "MODE_SOLVABLE": "Megoldható", + "MODE_SOLVABLE": "Megoldható (Szabványos)", + "MODE_SOLVABLE_EASY": "Megoldható (Könnyű)", + "MODE_SOLVABLE_EXPERT": "Megoldható (Szakértő)", "MODE_RANDOM": "Véletlen", "RANDOM_GROUP": "Véletlen", "RANDOM_LAYOUT": "Véletlen", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://hu.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Kőinformációk", "TILES": "Kövek", - "INFO_LONG": "Kőinformációk", + "TILES_INFO_LONG": "A játék összes kövének áttekintése", "HELP": "Súgó", "HELP_LONG": "Párbeszédablak megjelenítése/elrejtése", "SETTINGS_LONG": "Nyelv, kőszetek és színek beállítása", - "MODE_SOLVABLE_DESC": "Véletlenszerű kitöltés legalább egy megoldási lehetőséggel", - "MODE_RANDOM_DESC": "Teljesen véletlenszerű kitöltés, amely lehet, hogy megoldhatatlan", + "MODE_SOLVABLE_DESC": "Garantáltan legalább egy megoldással rendelkezik", + "MODE_SOLVABLE_EASY_DESC": "Könnyed nehézség - rengeteg pár elérhető a párosításhoz", + "MODE_SOLVABLE_EXPERT_DESC": "Kevés pár elérhető egyszerre - gondos tervezést igényel", + "MODE_RANDOM_DESC": "Teljesen véletlenszerű elrendezés - esetleg megoldhatatlan", "SELECT_BOARD": "Tábla kiválasztása", "BOARD_GENERATOR": "Tábla generátor", "START_SELECTED": "Kiválasztott indítása", - "START_RANDOM": "Véletlen indítása", + "START_RANDOM": "Véletlenszerű tábla játszása", "TILESET": "Kőszett", "BACKGROUND": "Háttér", "INFO": "Információ", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Keverés", "SHUFFLE_LONG": "Kövek keverése a játékban", + "RESCUE_SHUFFLE": "Keverés a folytatáshoz", + "RESCUE_SHUFFLE_LONG": "Keverés ha nincs több lépés", "GAME_MODE": "Mód", "GAME_MODE_EASY": "Könnyű", "GAME_MODE_STANDARD": "Szabványos", "GAME_MODE_EXPERT": "Haladó", + "GAME_MODE_NO_HELPERS": "Nincs segítség - tiszta ügyességre van szükség", "HOW_TO_PLAY": "Hogyan kell játszani", "HOW_GOAL": "A cél az összes nyitott pár eltávolítása a játéktábláról.", "HOW_OPEN": "Nyitott", diff --git a/src/assets/i18n/id.json b/src/assets/i18n/id.json index 402445e8..2ded3928 100644 --- a/src/assets/i18n/id.json +++ b/src/assets/i18n/id.json @@ -30,7 +30,9 @@ "SETTINGS": "Pengaturan", "STATS": "Statistik", "MODE": "Algoritma Pengisian Papan", - "MODE_SOLVABLE": "Dapat Dipecahkan", + "MODE_SOLVABLE": "Dapat Dipecahkan (Standar)", + "MODE_SOLVABLE_EASY": "Bisa Diselesaikan (Mudah)", + "MODE_SOLVABLE_EXPERT": "Bisa Diselesaikan (Ahli)", "MODE_RANDOM": "Acak", "RANDOM_GROUP": "Acak", "RANDOM_LAYOUT": "Acak", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://id.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Informasi Ubin", "TILES": "Ubin", - "INFO_LONG": "Informasi Ubin", + "TILES_INFO_LONG": "Ikhtisar semua ubin dalam permainan", "HELP": "Bantuan", "HELP_LONG": "Tampilkan/sembunyikan dialog ini", "SETTINGS_LONG": "Sesuaikan bahasa, set ubin & warna", - "MODE_SOLVABLE_DESC": "Pengisian acak dengan setidaknya satu kemungkinan solusi", - "MODE_RANDOM_DESC": "Pengisian acak total, mungkin tidak dapat dipecahkan", + "MODE_SOLVABLE_DESC": "Dijamin memiliki setidaknya satu solusi", + "MODE_SOLVABLE_EASY_DESC": "Tingkat kesulitan santai - banyak pasangan tersedia untuk dicocokkan", + "MODE_SOLVABLE_EXPERT_DESC": "Sedikit pasangan tersedia sekaligus - membutuhkan perencanaan cermat", + "MODE_RANDOM_DESC": "Tata letak sepenuhnya acak - mungkin tidak dapat diselesaikan", "SELECT_BOARD": "Pilih Papan", "BOARD_GENERATOR": "Generator Papan", "START_SELECTED": "Mulai Terpilih", - "START_RANDOM": "Mulai Acak", + "START_RANDOM": "Mainkan Papan Acak", "TILESET": "Seni Ubin", "BACKGROUND": "Latar Belakang", "INFO": "Info", @@ -190,10 +194,13 @@ "t_e9": "Ekstra 9", "SHUFFLE": "Acak", "SHUFFLE_LONG": "Acak batu dalam permainan", + "RESCUE_SHUFFLE": "Acak untuk Melanjutkan", + "RESCUE_SHUFFLE_LONG": "Acak jika tidak ada lagi gerakan", "GAME_MODE": "Mode", "GAME_MODE_EASY": "Mudah", "GAME_MODE_STANDARD": "Standar", "GAME_MODE_EXPERT": "Ahli", + "GAME_MODE_NO_HELPERS": "Tanpa bantuan - membutuhkan kemampuan murni", "HOW_TO_PLAY": "Cara bermain", "HOW_GOAL": "Tujuannya adalah menghapus semua ubin dalam pasangan terbuka dari papan permainan.", "HOW_OPEN": "Terbuka", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 3d9798ce..fd943d51 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -30,7 +30,9 @@ "SETTINGS": "Impostazioni", "STATS": "Statistiche", "MODE": "Algoritmo di riempimento tavola", - "MODE_SOLVABLE": "Risolvibile", + "MODE_SOLVABLE": "Risolvibile (Standard)", + "MODE_SOLVABLE_EASY": "Risolvibile (Facile)", + "MODE_SOLVABLE_EXPERT": "Risolvibile (Esperto)", "MODE_RANDOM": "Casuale", "RANDOM_GROUP": "Casuale", "RANDOM_LAYOUT": "Casuale", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://it.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Informazioni tessere", "TILES": "Tessere", - "INFO_LONG": "Informazioni tessere", + "TILES_INFO_LONG": "Panoramica di tutte le tessere nel gioco", "HELP": "Aiuto", "HELP_LONG": "Mostra/nascondi questo dialogo", "SETTINGS_LONG": "Regola la lingua, i set di tessere e i colori", - "MODE_SOLVABLE_DESC": "Un riempimento casuale con almeno una possibilità di soluzione", - "MODE_RANDOM_DESC": "Un riempimento completamente casuale, forse irrisolvibile", + "MODE_SOLVABLE_DESC": "Garantito almeno una soluzione", + "MODE_SOLVABLE_EASY_DESC": "Difficoltà rilassata - molte coppie disponibili da abbinare", + "MODE_SOLVABLE_EXPERT_DESC": "Poche coppie disponibili alla volta - richiede una pianificazione attenta", + "MODE_RANDOM_DESC": "Disposizione completamente casuale - possibilmente irrisolvibile", "SELECT_BOARD": "Seleziona tavola", "BOARD_GENERATOR": "Generatore di tavola", "START_SELECTED": "Inizia selezionato", - "START_RANDOM": "Inizia casuale", + "START_RANDOM": "Gioca un tabellone casuale", "TILESET": "Arte tessera", "BACKGROUND": "Sfondo", "INFO": "Informazioni", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Mescola", "SHUFFLE_LONG": "Mescola le pietre nel gioco", + "RESCUE_SHUFFLE": "Mescola per continuare", + "RESCUE_SHUFFLE_LONG": "Mescola se non ci sono più mosse", "GAME_MODE": "Modalità", "GAME_MODE_EASY": "Facile", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Esperto", + "GAME_MODE_NO_HELPERS": "Nessun aiuto - richiede abilità pura", "HOW_TO_PLAY": "Come giocare", "HOW_GOAL": "L'obiettivo è rimuovere tutte le tessere in coppie aperte dal tavolo di gioco.", "HOW_OPEN": "Aperto", diff --git a/src/assets/i18n/ja.json b/src/assets/i18n/ja.json index ce15393d..00b5c913 100644 --- a/src/assets/i18n/ja.json +++ b/src/assets/i18n/ja.json @@ -30,7 +30,9 @@ "SETTINGS": "設定", "STATS": "統計", "MODE": "ボード生成アルゴリズム", - "MODE_SOLVABLE": "解決可能", + "MODE_SOLVABLE": "解決可能(標準)", + "MODE_SOLVABLE_EASY": "解決可能(簡単)", + "MODE_SOLVABLE_EXPERT": "解決可能(エキスパート)", "MODE_RANDOM": "ランダム", "RANDOM_GROUP": "ランダム", "RANDOM_LAYOUT": "ランダム", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://ja.wikipedia.org/wiki/麻雀", "TILES_INFO": "牌の情報", "TILES": "牌", - "INFO_LONG": "牌の情報", + "TILES_INFO_LONG": "ゲーム内のすべての牌の概要", "HELP": "ヘルプ", "HELP_LONG": "このダイアログを表示/非表示", "SETTINGS_LONG": "言語、牌セット、色を調整", - "MODE_SOLVABLE_DESC": "少なくとも1つの解決可能な配置があるランダムな配置", - "MODE_RANDOM_DESC": "完全にランダムな配置(解決不能な場合もあります)", + "MODE_SOLVABLE_DESC": "少なくとも1つの解が保証されている", + "MODE_SOLVABLE_EASY_DESC": "気楽な難易度 - 多くのペアが利用可能", + "MODE_SOLVABLE_EXPERT_DESC": "一度に利用できるペアが少ない - 慎重な計画が必要", + "MODE_RANDOM_DESC": "完全ランダムな配置 - 解決不能な場合もあります", "SELECT_BOARD": "ボードを選択", "BOARD_GENERATOR": "ボードジェネレーター", "START_SELECTED": "選択を開始", - "START_RANDOM": "ランダムを開始", + "START_RANDOM": "ランダムボードをプレイ", "TILESET": "牌セット", "BACKGROUND": "背景", "INFO": "情報", @@ -190,10 +194,13 @@ "t_e9": "エキストラ9", "SHUFFLE": "シャッフル", "SHUFFLE_LONG": "ゲーム内の石をシャッフル", + "RESCUE_SHUFFLE": "続けるためにシャッフル", + "RESCUE_SHUFFLE_LONG": "手がなくなったらシャッフル", "GAME_MODE": "モード", "GAME_MODE_EASY": "簡単", "GAME_MODE_STANDARD": "標準", "GAME_MODE_EXPERT": "エキスパート", + "GAME_MODE_NO_HELPERS": "ヘルパーなし - 純粋なスキルが必要", "HOW_TO_PLAY": "遊び方", "HOW_GOAL": "目標は、オープンペアのすべての牌をゲームボードから取り除くことです。", "HOW_OPEN": "オープン", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index 1515cd7d..dc332a97 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -30,7 +30,9 @@ "SETTINGS": "설정", "STATS": "통계", "MODE": "보드 채우기 알고리즘", - "MODE_SOLVABLE": "해결 가능", + "MODE_SOLVABLE": "해결 가능 (표준)", + "MODE_SOLVABLE_EASY": "해결 가능 (쉬움)", + "MODE_SOLVABLE_EXPERT": "해결 가능 (전문가)", "MODE_RANDOM": "무작위", "RANDOM_GROUP": "무작위", "RANDOM_LAYOUT": "무작위", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://ko.wikipedia.org/wiki/마작", "TILES_INFO": "타일 정보", "TILES": "타일", - "INFO_LONG": "타일 정보", + "TILES_INFO_LONG": "게임의 모든 타일 개요", "HELP": "도움말", "HELP_LONG": "이 대화 상자 표시/숨기기", "SETTINGS_LONG": "언어, 타일 세트 및 색상 설정", - "MODE_SOLVABLE_DESC": "최소한 하나의 해결책이 있는 무작위 배치", - "MODE_RANDOM_DESC": "완전 무작위 배치, 풀 수 없을 수 있음", + "MODE_SOLVABLE_DESC": "최소 하나의 해결책이 보장됨", + "MODE_SOLVABLE_EASY_DESC": "여유로운 난이도 - 매칭할 쌍이 풍부하게 제공됨", + "MODE_SOLVABLE_EXPERT_DESC": "한 번에 가능한 쌍이 적음 - 신중한 계획 필요", + "MODE_RANDOM_DESC": "완전 무작위 배치 - 풀 수 없을 수도 있음", "SELECT_BOARD": "보드 선택", "BOARD_GENERATOR": "보드 생성기", "START_SELECTED": "선택한 것 시작", - "START_RANDOM": "무작위 시작", + "START_RANDOM": "무작위 보드 플레이", "TILESET": "타일 세트", "BACKGROUND": "배경", "INFO": "정보", @@ -190,10 +194,13 @@ "t_e9": "추가 9", "SHUFFLE": "섞기", "SHUFFLE_LONG": "게임의 타일 섞기", + "RESCUE_SHUFFLE": "계속하기 위해 섞기", + "RESCUE_SHUFFLE_LONG": "더 이상 이동이 없을 때 섞기", "GAME_MODE": "모드", "GAME_MODE_EASY": "쉬움", "GAME_MODE_STANDARD": "표준", "GAME_MODE_EXPERT": "전문가", + "GAME_MODE_NO_HELPERS": "도우미 없음 - 순수한 기술 필요", "HOW_TO_PLAY": "게임 방법", "HOW_GOAL": "목표는 게임 보드에서 모든 열린 짝의 타일을 제거하는 것입니다.", "HOW_OPEN": "열림", diff --git a/src/assets/i18n/ms.json b/src/assets/i18n/ms.json index f94b8a22..fb020f2c 100644 --- a/src/assets/i18n/ms.json +++ b/src/assets/i18n/ms.json @@ -30,7 +30,9 @@ "SETTINGS": "Tetapan", "STATS": "Statistik", "MODE": "Algoritma Pengisian Papan", - "MODE_SOLVABLE": "Boleh Diselesaikan", + "MODE_SOLVABLE": "Boleh Diselesaikan (Standard)", + "MODE_SOLVABLE_EASY": "Boleh Diselesaikan (Mudah)", + "MODE_SOLVABLE_EXPERT": "Boleh Diselesaikan (Pakar)", "MODE_RANDOM": "Rawak", "RANDOM_GROUP": "Rawak", "RANDOM_LAYOUT": "Rawak", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://ms.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Maklumat Jubin", "TILES": "Jubin", - "INFO_LONG": "Maklumat Jubin", + "TILES_INFO_LONG": "Gambaran keseluruhan semua jubin dalam permainan", "HELP": "Bantuan", "HELP_LONG": "Tunjuk/sembunyikan dialog ini", "SETTINGS_LONG": "Laraskan bahasa, set jubin & warna", - "MODE_SOLVABLE_DESC": "Pengisian rawak dengan sekurang-kurangnya satu kemungkinan penyelesaian", - "MODE_RANDOM_DESC": "Pengisian rawak sepenuhnya, mungkin tidak boleh diselesaikan", + "MODE_SOLVABLE_DESC": "Dijamin mempunyai sekurang-kurangnya satu penyelesaian", + "MODE_SOLVABLE_EASY_DESC": "Kesukaran santai - banyak pasangan tersedia untuk dipadankan", + "MODE_SOLVABLE_EXPERT_DESC": "Sedikit pasangan tersedia sekaligus - memerlukan perancangan yang teliti", + "MODE_RANDOM_DESC": "Susun atur rawak sepenuhnya - mungkin tidak dapat diselesaikan", "SELECT_BOARD": "Pilih Papan", "BOARD_GENERATOR": "Penjana Papan", "START_SELECTED": "Mula Yang Dipilih", - "START_RANDOM": "Mula Rawak", + "START_RANDOM": "Main Papan Rawak", "TILESET": "Seni Jubin", "BACKGROUND": "Latar Belakang", "INFO": "Info", @@ -190,10 +194,13 @@ "t_e9": "Tambahan 9", "SHUFFLE": "Kocok", "SHUFFLE_LONG": "Kocok batu dalam permainan", + "RESCUE_SHUFFLE": "Kocok untuk Meneruskan", + "RESCUE_SHUFFLE_LONG": "Kocok jika tiada lagi gerakan", "GAME_MODE": "Mod", "GAME_MODE_EASY": "Mudah", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Pakar", + "GAME_MODE_NO_HELPERS": "Tiada pembantu - kemahiran tulen diperlukan", "HOW_TO_PLAY": "Cara Bermain", "HOW_GOAL": "Matlamatnya adalah untuk membuang semua jubin secara berpasangan terbuka dari papan permainan.", "HOW_OPEN": "Terbuka", diff --git a/src/assets/i18n/nl.json b/src/assets/i18n/nl.json index 8fad97b2..fd0cffd2 100644 --- a/src/assets/i18n/nl.json +++ b/src/assets/i18n/nl.json @@ -30,7 +30,9 @@ "SETTINGS": "Instellingen", "STATS": "Statistieken", "MODE": "Legwijze", - "MODE_SOLVABLE": "Oplosbaar", + "MODE_SOLVABLE": "Oplosbaar (Standaard)", + "MODE_SOLVABLE_EASY": "Oplosbaar (Gemakkelijk)", + "MODE_SOLVABLE_EXPERT": "Oplosbaar (Expert)", "MODE_RANDOM": "Willekeurig", "RANDOM_GROUP": "Willekeurig", "RANDOM_LAYOUT": "Willekeurig", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://nl.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Toon informatie over de stenen", "TILES": "Stenen", - "INFO_LONG": "Toon informatie over de stenen", + "TILES_INFO_LONG": "Overzicht van alle stenen in het spel", "HELP": "Hulp", "HELP_LONG": "Toon/verberg dit dialoogvenster", "SETTINGS_LONG": "Taal, tegelsets en kleuren aanpassen", - "MODE_SOLVABLE_DESC": "Een willekeurige legwijze met ten minste één oplossing", - "MODE_RANDOM_DESC": "Een willekeurige legwijze, mogelijk zonder oplossing", + "MODE_SOLVABLE_DESC": "Gegarandeerd ten minste één oplossing", + "MODE_SOLVABLE_EASY_DESC": "Ontspannen moeilijkheidsgraad - voldoende paren beschikbaar om te matchen", + "MODE_SOLVABLE_EXPERT_DESC": "Weinig paren tegelijk beschikbaar - vereist zorgvuldige planning", + "MODE_RANDOM_DESC": "Volledig willekeurige indeling - mogelijk onoplosbaar", "SELECT_BOARD": "Kies een spelbord", "BOARD_GENERATOR": "Bordsamensteller", "START_SELECTED": "Gekozen bord neerleggen", - "START_RANDOM": "Willekeurig bord", + "START_RANDOM": "Speel willekeurig bord", "TILESET": "Steendecoraties", "BACKGROUND": "Achtergrond", "INFO": "Informatie", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Shuffle", "SHUFFLE_LONG": "Schud stenen in het spel", + "RESCUE_SHUFFLE": "Schudden om door te gaan", + "RESCUE_SHUFFLE_LONG": "Schudden als er geen zetten meer zijn", "GAME_MODE": "Modus", "GAME_MODE_EASY": "Eenvoudig", "GAME_MODE_STANDARD": "Standaard", "GAME_MODE_EXPERT": "Deskundige", + "GAME_MODE_NO_HELPERS": "Geen hulpmiddelen - puur vakmanschap vereist", "HOW_TO_PLAY": "Hoe te spelen", "HOW_GOAL": "Het doel is om alle tegels in open paren van het spelbord te verwijderen.", "HOW_OPEN": "Open", @@ -214,20 +221,20 @@ "EDITOR_EXPORT": "Exporteer", "EDITOR_EXPORT_LONG": "Exporteer borden naar bestanden", "EDITOR_NEW_LAYER_LONG": "Nieuwe laag hieronder", - "EDITOR_MOVE_TILES_UP_LONG": "Verplaats tegels omhoog", - "EDITOR_MOVE_TILES_DOWN_LONG": "Verplaats tegels omlaag", - "EDITOR_MOVE_TILES_LEFT_LONG": "Verplaats tegels naar links", - "EDITOR_MOVE_TILES_RIGHT_LONG": "Verplaats tegels naar rechts", + "EDITOR_MOVE_TILES_UP_LONG": "Verplaats stenen omhoog", + "EDITOR_MOVE_TILES_DOWN_LONG": "Verplaats stenen omlaag", + "EDITOR_MOVE_TILES_LEFT_LONG": "Verplaats stenen naar links", + "EDITOR_MOVE_TILES_RIGHT_LONG": "Verplaats stenen naar rechts", "EDITOR_MOVE_LAYER_UP_LONG": "Laag omhoog bewegen", "EDITOR_MOVE_LAYER_DOWN_LONG": "Laag omlaag bewegen", "EDITOR_DUPLICATE_LAYER_LONG": "Dupliceer laag", "EDITOR_CLEAR_LAYER_LONG": "Laag wissen", "EDITOR_DELETE_LAYER_LONG": "Laag verwijderen", "EDITOR_DISCARD_CHANGES_SURE": "Wijzigingen verwerpen?", - "EDITOR_MOVE_ALL_TILES_UP_LONG": "Verplaats alle tegels omhoog", - "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Verplaats alle tegels omlaag", - "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Verplaats alle tegels naar links", - "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Verplaats alle tegels naar rechts", + "EDITOR_MOVE_ALL_TILES_UP_LONG": "Verplaats alle stenen omhoog", + "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Verplaats alle stenen omlaag", + "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Verplaats alle stenen naar links", + "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Verplaats alle stenen naar rechts", "EDITOR_LAYOUT_NAME": "Naam", "EDITOR_LAYOUT_BY": "Op", "EDITOR_LAYOUT_CATEGORY": "Categorie", diff --git a/src/assets/i18n/no.json b/src/assets/i18n/no.json index 7008c928..19d73c34 100644 --- a/src/assets/i18n/no.json +++ b/src/assets/i18n/no.json @@ -30,7 +30,9 @@ "SETTINGS": "Innstillinger", "STATS": "Statistikk", "MODE": "Brett fylla algoritme", - "MODE_SOLVABLE": "Løselig", + "MODE_SOLVABLE": "Løselig (Standard)", + "MODE_SOLVABLE_EASY": "Løsbar (Lett)", + "MODE_SOLVABLE_EXPERT": "Løsbar (Ekspert)", "MODE_RANDOM": "Tilfeldig", "RANDOM_GROUP": "Tilfeldig", "RANDOM_LAYOUT": "Tilfeldig", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://no.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Steininformasjon", "TILES": "Steiner", - "INFO_LONG": "Steininformasjon", + "TILES_INFO_LONG": "Oversikt over alle brikker i spillet", "HELP": "Hjelp", "HELP_LONG": "Vis/skjul denne dialogen", "SETTINGS_LONG": "Juster språk, steinsamlinger og farger", - "MODE_SOLVABLE_DESC": "Tilfeldig fylling med minst en løsingsmulighet", - "MODE_RANDOM_DESC": "Helt tilfeldig fylling, kanskje uløselig", + "MODE_SOLVABLE_DESC": "Garantert å ha minst én løsning", + "MODE_SOLVABLE_EASY_DESC": "Avslappet vanskelighetsgrad - mange par tilgjengelig for matching", + "MODE_SOLVABLE_EXPERT_DESC": "Få par tilgjengelig om gangen - krever nøye planlegging", + "MODE_RANDOM_DESC": "Helt tilfeldig oppsett - muligens uløselig", "SELECT_BOARD": "Velg brett", "BOARD_GENERATOR": "Brett generator", "START_SELECTED": "Start valgt", - "START_RANDOM": "Start tilfeldig", + "START_RANDOM": "Spill tilfeldig brett", "TILESET": "Steinkunst", "BACKGROUND": "Bakgrunn", "INFO": "Info", @@ -190,10 +194,13 @@ "t_e9": "Ekstra 9", "SHUFFLE": "Bland", "SHUFFLE_LONG": "Bland steiner i spillet", + "RESCUE_SHUFFLE": "Bland for å fortsette", + "RESCUE_SHUFFLE_LONG": "Bland hvis det ikke er flere trekk", "GAME_MODE": "Modus", "GAME_MODE_EASY": "Lett", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Ekspert", + "GAME_MODE_NO_HELPERS": "Ingen hjelpemidler - rent dyktighet kreves", "HOW_TO_PLAY": "Hvordan spille", "HOW_GOAL": "Målet er å fjerne alle steiner i åpne par fra spillebrettet.", "HOW_OPEN": "Åpen", diff --git a/src/assets/i18n/pl.json b/src/assets/i18n/pl.json index b1bffd16..aa12ba2c 100644 --- a/src/assets/i18n/pl.json +++ b/src/assets/i18n/pl.json @@ -30,7 +30,9 @@ "SETTINGS": "Ustawienia", "STATS": "Statystyki", "MODE": "Algorytm wypełniania planszy", - "MODE_SOLVABLE": "Rozwiązywalny", + "MODE_SOLVABLE": "Rozwiązywalny (Standardowy)", + "MODE_SOLVABLE_EASY": "Rozwiązywalne (Łatwy)", + "MODE_SOLVABLE_EXPERT": "Rozwiązywalne (Ekspert)", "MODE_RANDOM": "Losowy", "RANDOM_GROUP": "Losowy", "RANDOM_LAYOUT": "Losowy", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://pl.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Informacje o kamieniach", "TILES": "Kamienie", - "INFO_LONG": "Informacje o kamieniach", + "TILES_INFO_LONG": "Przegląd wszystkich kamieni w grze", "HELP": "Pomoc", "HELP_LONG": "Pokaż/ukryj to okno dialogowe", "SETTINGS_LONG": "Dostosuj język, zestawy kamieni i kolory", - "MODE_SOLVABLE_DESC": "Losowe wypełnienie z co najmniej jedną możliwością rozwiązania", - "MODE_RANDOM_DESC": "Całkowicie losowe wypełnienie, może być nierozwiązywalne", + "MODE_SOLVABLE_DESC": "Gwarantowane przynajmniej jedno rozwiązanie", + "MODE_SOLVABLE_EASY_DESC": "Zrelaksowany poziom trudności - wiele par dostępnych do dopasowania", + "MODE_SOLVABLE_EXPERT_DESC": "Mało par dostępnych naraz - wymaga starannego planowania", + "MODE_RANDOM_DESC": "Całkowicie losowe rozmieszczenie - może być nierozwiązywalne", "SELECT_BOARD": "Wybierz planszę", "BOARD_GENERATOR": "Generator plansz", "START_SELECTED": "Rozpocznij wybraną", - "START_RANDOM": "Rozpocznij losową", + "START_RANDOM": "Graj losową planszę", "TILESET": "Zestaw kamieni", "BACKGROUND": "Tło", "INFO": "Informacje", @@ -190,10 +194,13 @@ "t_e9": "Dodatkowy 9", "SHUFFLE": "Tasuj", "SHUFFLE_LONG": "Tasuj kamienie w grze", + "RESCUE_SHUFFLE": "Przetasuj aby kontynuować", + "RESCUE_SHUFFLE_LONG": "Przetasuj jeśli nie ma więcej ruchów", "GAME_MODE": "Tryb", "GAME_MODE_EASY": "Łatwy", "GAME_MODE_STANDARD": "Standardowy", "GAME_MODE_EXPERT": "Ekspert", + "GAME_MODE_NO_HELPERS": "Brak pomocy - wymagane czyste umiejętności", "HOW_TO_PLAY": "Jak grać", "HOW_GOAL": "Celem jest usunięcie z planszy wszystkich kamieni w otwartych parach.", "HOW_OPEN": "Otwarty", diff --git a/src/assets/i18n/pt.json b/src/assets/i18n/pt.json index 475e0895..969b683d 100644 --- a/src/assets/i18n/pt.json +++ b/src/assets/i18n/pt.json @@ -30,7 +30,9 @@ "SETTINGS": "Configurações", "STATS": "Estatísticas", "MODE": "Algoritmo de preenchimento de placa", - "MODE_SOLVABLE": "Solúvel", + "MODE_SOLVABLE": "Solúvel (Padrão)", + "MODE_SOLVABLE_EASY": "Resolúvel (Fácil)", + "MODE_SOLVABLE_EXPERT": "Resolúvel (Especialista)", "MODE_RANDOM": "Aleatoriamente", "RANDOM_GROUP": "Aleatório", "RANDOM_LAYOUT": "Aleatório", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://pt.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Informações sobre as peças", "TILES": "Peças", - "INFO_LONG": "Informações sobre as peças", + "TILES_INFO_LONG": "Visão geral de todas as peças no jogo", "HELP": "Ajuda", "HELP_LONG": "Mostrar/ocultar esta caixa de diálogo", "SETTINGS_LONG": "Ajuste o idioma, conjuntos de blocos e cores", - "MODE_SOLVABLE_DESC": "Um preenchimento aleatório com pelo menos uma possibilidade de solução", - "MODE_RANDOM_DESC": "Um preenchimento totalmente aleatório, talvez insolúvel", + "MODE_SOLVABLE_DESC": "Garantido ter pelo menos uma solução", + "MODE_SOLVABLE_EASY_DESC": "Dificuldade relaxada - muitos pares disponíveis para combinar", + "MODE_SOLVABLE_EXPERT_DESC": "Poucos pares disponíveis de uma vez - exige planejamento cuidadoso", + "MODE_RANDOM_DESC": "Layout completamente aleatório - possivelmente insolúvel", "SELECT_BOARD": "Selecione o tabuleiro", "BOARD_GENERATOR": "Gerador de placa", "START_SELECTED": "Jogar Selecionado", - "START_RANDOM": "Jogar Aleatório", + "START_RANDOM": "Jogar Tabuleiro Aleatório", "TILESET": "Peças", "BACKGROUND": "Papel de Parede", "INFO": "Informações", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Embaralhar", "SHUFFLE_LONG": "Embaralhe pedras neste jogo", + "RESCUE_SHUFFLE": "Embaralhar para Continuar", + "RESCUE_SHUFFLE_LONG": "Embaralhar se não houver mais movimentos", "GAME_MODE": "Modo", "GAME_MODE_EASY": "Fácil", "GAME_MODE_STANDARD": "Padrão", "GAME_MODE_EXPERT": "Especialista", + "GAME_MODE_NO_HELPERS": "Sem ajudas - requer habilidade pura", "HOW_TO_PLAY": "Como jogar", "HOW_GOAL": "O objetivo é remover todas as peças em pares abertos do tabuleiro de jogo.", "HOW_OPEN": "Abrir", @@ -214,20 +221,20 @@ "EDITOR_EXPORT": "Exportar", "EDITOR_EXPORT_LONG": "Exportar boards para arquivos", "EDITOR_NEW_LAYER_LONG": "Nova camada abaixo", - "EDITOR_MOVE_TILES_UP_LONG": "Mover blocos para cima", - "EDITOR_MOVE_TILES_DOWN_LONG": "Mover blocos para baixo", - "EDITOR_MOVE_TILES_LEFT_LONG": "Mover blocos para esquerda", - "EDITOR_MOVE_TILES_RIGHT_LONG": "Mover blocos para direita", + "EDITOR_MOVE_TILES_UP_LONG": "Mover peças para cima", + "EDITOR_MOVE_TILES_DOWN_LONG": "Mover peças para baixo", + "EDITOR_MOVE_TILES_LEFT_LONG": "Mover peças para esquerda", + "EDITOR_MOVE_TILES_RIGHT_LONG": "Mover peças para direita", "EDITOR_MOVE_LAYER_UP_LONG": "Mover camada para cima", "EDITOR_MOVE_LAYER_DOWN_LONG": "Mover camada para baixo", "EDITOR_DUPLICATE_LAYER_LONG": "Duplicar camada", "EDITOR_CLEAR_LAYER_LONG": "Limpar camada", "EDITOR_DELETE_LAYER_LONG": "Eliminar camada", "EDITOR_DISCARD_CHANGES_SURE": "Descartar alterações?", - "EDITOR_MOVE_ALL_TILES_UP_LONG": "Mover todos os blocos para cima", - "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Mover todos os blocos para baixo", - "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Mover todos os blocos para a esquerda", - "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Mover todos os blocos para a direita", + "EDITOR_MOVE_ALL_TILES_UP_LONG": "Mover todas as peças para cima", + "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Mover todas as peças para baixo", + "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Mover todas as peças para a esquerda", + "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Mover todas as peças para a direita", "EDITOR_LAYOUT_NAME": "Nome", "EDITOR_LAYOUT_BY": "De", "EDITOR_LAYOUT_CATEGORY": "Categoria", diff --git a/src/assets/i18n/ro.json b/src/assets/i18n/ro.json index 1f23e1d6..5fa4e740 100644 --- a/src/assets/i18n/ro.json +++ b/src/assets/i18n/ro.json @@ -30,7 +30,9 @@ "SETTINGS": "Setări", "STATS": "Statistici", "MODE": "Algoritm de umplere tablă", - "MODE_SOLVABLE": "Rezolvabil", + "MODE_SOLVABLE": "Rezolvabil (Standard)", + "MODE_SOLVABLE_EASY": "Rezolvabil (Ușor)", + "MODE_SOLVABLE_EXPERT": "Rezolvabil (Expert)", "MODE_RANDOM": "Aleatoriu", "RANDOM_GROUP": "Aleatoriu", "RANDOM_LAYOUT": "Aleatoriu", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "Informații despre pietre", "TILES": "Pietre", - "INFO_LONG": "Informații despre pietre", + "TILES_INFO_LONG": "Prezentare generală a tuturor pieselor din joc", "HELP": "Ajutor", "HELP_LONG": "Arată/ascunde acest dialog", "SETTINGS_LONG": "Ajustați limba, seturile de pietre și culorile", - "MODE_SOLVABLE_DESC": "O umplere aleatorie cu cel puțin o posibilitate de rezolvare", - "MODE_RANDOM_DESC": "O umplere complet aleatorie, poate nerezolvabilă", + "MODE_SOLVABLE_DESC": "Garantat că are cel puțin o soluție", + "MODE_SOLVABLE_EASY_DESC": "Dificultate relaxată - multe perechi disponibile pentru potrivire", + "MODE_SOLVABLE_EXPERT_DESC": "Puține perechi disponibile odată - necesită planificare atentă", + "MODE_RANDOM_DESC": "Aranjament complet aleatoriu - posibil nerezolvabil", "SELECT_BOARD": "Selectare Tablă", "BOARD_GENERATOR": "Generator de Tablă", "START_SELECTED": "Începe Selectat", - "START_RANDOM": "Începe Aleatoriu", + "START_RANDOM": "Joacă tablă aleatorie", "TILESET": "Arta setului de pietre", "BACKGROUND": "Fundal", "INFO": "Informații", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Amesteacă", "SHUFFLE_LONG": "Amesteacă pietrele în joc", + "RESCUE_SHUFFLE": "Amestecă pentru a continua", + "RESCUE_SHUFFLE_LONG": "Amestecă dacă nu mai sunt mutări", "GAME_MODE": "Mod", "GAME_MODE_EASY": "Ușor", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Expert", + "GAME_MODE_NO_HELPERS": "Fără ajutoare - necesită pricepere pură", "HOW_TO_PLAY": "Cum să joci", "HOW_GOAL": "Scopul este să elimini toate pietrele în perechi deschise de pe tablă.", "HOW_OPEN": "Deschis", diff --git a/src/assets/i18n/ru.json b/src/assets/i18n/ru.json index 2ef71eef..fe83967c 100644 --- a/src/assets/i18n/ru.json +++ b/src/assets/i18n/ru.json @@ -30,7 +30,9 @@ "SETTINGS": "Настройки", "STATS": "Статистика", "MODE": "Алгоритм заполнения доски", - "MODE_SOLVABLE": "Разрешимый", + "MODE_SOLVABLE": "Разрешимый (Стандарт)", + "MODE_SOLVABLE_EASY": "Решаемо (Просто)", + "MODE_SOLVABLE_EXPERT": "Решаемо (Эксперт)", "MODE_RANDOM": "Случайный", "RANDOM_GROUP": "Случайный", "RANDOM_LAYOUT": "Случайный", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://ru.wikipedia.org/wiki/Маджонг", "TILES_INFO": "Информация о фишках", "TILES": "Фишки", - "INFO_LONG": "Информация о фишках", + "TILES_INFO_LONG": "Обзор всех фишек в игре", "HELP": "Помощь", "HELP_LONG": "Показать/скрыть этот диалог", "SETTINGS_LONG": "Настройка языка, наборов плиток и цветов", - "MODE_SOLVABLE_DESC": "Случайная заливка с хотя бы одной возможностью решения", - "MODE_RANDOM_DESC": "Полная случайная заливка, возможно, неразрешимая", + "MODE_SOLVABLE_DESC": "Гарантировано наличие хотя бы одного решения", + "MODE_SOLVABLE_EASY_DESC": "Расслабленная сложность - много пар для совпадения", + "MODE_SOLVABLE_EXPERT_DESC": "Мало пар доступно одновременно - требует тщательного планирования", + "MODE_RANDOM_DESC": "Полностью случайное расположение - возможно неразрешимое", "SELECT_BOARD": "Выбор карты", "BOARD_GENERATOR": "Генератор платы", "START_SELECTED": "Начать выбранное", - "START_RANDOM": "Начать случайное", + "START_RANDOM": "Сыграть случайную доску", "TILESET": "Внешний вид фишек", "BACKGROUND": "Фон", "INFO": "Информация", @@ -190,10 +194,13 @@ "t_e9": "Экстра 9", "SHUFFLE": "Перемешать", "SHUFFLE_LONG": "Перемешать камни в этой игре", + "RESCUE_SHUFFLE": "Перемешать для продолжения", + "RESCUE_SHUFFLE_LONG": "Перемешать если нет доступных ходов", "GAME_MODE": "Модус", "GAME_MODE_EASY": "Легко", "GAME_MODE_STANDARD": "Стандарт", "GAME_MODE_EXPERT": "Эксперт", + "GAME_MODE_NO_HELPERS": "Без помощников - требуется чистое мастерство", "HOW_TO_PLAY": "Как играть", "HOW_GOAL": "Цель состоит в том, чтобы удалить все плитки в открытых парах с игрового поля.", "HOW_OPEN": "Открытым", @@ -214,20 +221,20 @@ "EDITOR_EXPORT": "Экспорт", "EDITOR_EXPORT_LONG": "Экспортировать доски в файлы", "EDITOR_NEW_LAYER_LONG": "Новый слой ниже", - "EDITOR_MOVE_TILES_UP_LONG": "Переместить плитки вверх", - "EDITOR_MOVE_TILES_DOWN_LONG": "Переместить плитки вниз", - "EDITOR_MOVE_TILES_LEFT_LONG": "Переместить плитки влево", - "EDITOR_MOVE_TILES_RIGHT_LONG": "Переместить плитки вправо", + "EDITOR_MOVE_TILES_UP_LONG": "Переместить фишки вверх", + "EDITOR_MOVE_TILES_DOWN_LONG": "Переместить фишки вниз", + "EDITOR_MOVE_TILES_LEFT_LONG": "Переместить фишки влево", + "EDITOR_MOVE_TILES_RIGHT_LONG": "Переместить фишки вправо", "EDITOR_MOVE_LAYER_UP_LONG": "Переместить слой вверх", "EDITOR_MOVE_LAYER_DOWN_LONG": "Переместить слой вниз", "EDITOR_DUPLICATE_LAYER_LONG": "Дублировать слой", "EDITOR_CLEAR_LAYER_LONG": "Очистить слой", "EDITOR_DELETE_LAYER_LONG": "Удалить слой", "EDITOR_DISCARD_CHANGES_SURE": "Отменить изменения?", - "EDITOR_MOVE_ALL_TILES_UP_LONG": "Переместить все плитки вверх", - "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Переместить все плитки вниз", - "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Переместить все плитки влево", - "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Переместить все плитки вправо", + "EDITOR_MOVE_ALL_TILES_UP_LONG": "Переместить все фишки вверх", + "EDITOR_MOVE_ALL_TILES_DOWN_LONG": "Переместить все фишки вниз", + "EDITOR_MOVE_ALL_TILES_LEFT_LONG": "Переместить все фишки влево", + "EDITOR_MOVE_ALL_TILES_RIGHT_LONG": "Переместить все фишки вправо", "EDITOR_LAYOUT_NAME": "Имя", "EDITOR_LAYOUT_BY": "От", "EDITOR_LAYOUT_CATEGORY": "Категория", diff --git a/src/assets/i18n/sv.json b/src/assets/i18n/sv.json index 1a524231..c6435962 100644 --- a/src/assets/i18n/sv.json +++ b/src/assets/i18n/sv.json @@ -30,7 +30,9 @@ "SETTINGS": "Inställningar", "STATS": "Statistik", "MODE": "Algoritm för spelbräde", - "MODE_SOLVABLE": "Lösbar", + "MODE_SOLVABLE": "Lösbar (Standard)", + "MODE_SOLVABLE_EASY": "Lösbar (Lätt)", + "MODE_SOLVABLE_EXPERT": "Lösbar (Expert)", "MODE_RANDOM": "Slumpmässig", "RANDOM_GROUP": "Slumpmässig", "RANDOM_LAYOUT": "Slumpmässig", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://sv.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Information om stenar", "TILES": "Stenar", - "INFO_LONG": "Information om stenar", + "TILES_INFO_LONG": "Översikt över alla brickor i spelet", "HELP": "Hjälp", "HELP_LONG": "Visa/dölj denna dialog", "SETTINGS_LONG": "Justera språk, stenset och färger", - "MODE_SOLVABLE_DESC": "En slumpmässig fyllning med minst en lösning", - "MODE_RANDOM_DESC": "En helt slumpmässig fyllning, möjligtvis olösbar", + "MODE_SOLVABLE_DESC": "Garanterat att ha minst en lösning", + "MODE_SOLVABLE_EASY_DESC": "Avslappnad svårighetsgrad - gott om par tillgängliga att matcha", + "MODE_SOLVABLE_EXPERT_DESC": "Få par tillgängliga åt gången - kräver noggrann planering", + "MODE_RANDOM_DESC": "Helt slumpmässig layout - möjligtvis olösbar", "SELECT_BOARD": "Välj spelbräde", "BOARD_GENERATOR": "Spelbräde generator", "START_SELECTED": "Starta valt", - "START_RANDOM": "Starta slumpmässigt", + "START_RANDOM": "Spela slumpmässigt bräde", "TILESET": "Stenset-konst", "BACKGROUND": "Bakgrund", "INFO": "Information", @@ -190,10 +194,13 @@ "t_e9": "Extra 9", "SHUFFLE": "Blanda", "SHUFFLE_LONG": "Blanda stenar i spelet", + "RESCUE_SHUFFLE": "Blanda för att fortsätta", + "RESCUE_SHUFFLE_LONG": "Blanda om det inte finns fler drag", "GAME_MODE": "Läge", "GAME_MODE_EASY": "Lätt", "GAME_MODE_STANDARD": "Standard", "GAME_MODE_EXPERT": "Expert", + "GAME_MODE_NO_HELPERS": "Inga hjälpmedel - ren skicklighet krävs", "HOW_TO_PLAY": "Hur man spelar", "HOW_GOAL": "Målet är att ta bort alla stenar i öppna par från spelbrädet.", "HOW_OPEN": "Öppen", diff --git a/src/assets/i18n/sw.json b/src/assets/i18n/sw.json index 305676b2..f814575c 100644 --- a/src/assets/i18n/sw.json +++ b/src/assets/i18n/sw.json @@ -30,7 +30,9 @@ "SETTINGS": "Mipangilio", "STATS": "Takwimu", "MODE": "Algoriti ya Kujaza Ubao", - "MODE_SOLVABLE": "Inayoweza Kutatuliwa", + "MODE_SOLVABLE": "Inayoweza Kutatuliwa (Kawaida)", + "MODE_SOLVABLE_EASY": "Inayoweza Kutatuliwa (Rahisi)", + "MODE_SOLVABLE_EXPERT": "Inayoweza Kutatuliwa (Mtaalamu)", "MODE_RANDOM": "Nasibu", "RANDOM_GROUP": "Nasibu", "RANDOM_LAYOUT": "Nasibu", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "Taarifa za Vigae", "TILES": "Vigae", - "INFO_LONG": "Taarifa za Vigae", + "TILES_INFO_LONG": "Muhtasari wa vigae vyote kwenye mchezo", "HELP": "Msaada", "HELP_LONG": "Onyesha/ficha dirisha hili", "SETTINGS_LONG": "Rekebisha lugha, seti za vigae na rangi", - "MODE_SOLVABLE_DESC": "Kujazwa kwa nasibu na angalau uwezekano mmoja wa kutatua", - "MODE_RANDOM_DESC": "Kujazwa kwa nasibu kabisa, huenda isiweze kutatuliwa", + "MODE_SOLVABLE_DESC": "Imehakikishiwa kuwa na angalau suluhisho moja", + "MODE_SOLVABLE_EASY_DESC": "Ugumu wa burudani - jozi nyingi zinazopatikana kwa kulinganisha", + "MODE_SOLVABLE_EXPERT_DESC": "Jozi chache zinazopatikana kwa wakati mmoja - inahitaji mipango ya makini", + "MODE_RANDOM_DESC": "Mpangilio wa nasibu kabisa - huenda usiweze kutatuliwa", "SELECT_BOARD": "Chagua Ubao", "BOARD_GENERATOR": "Kizalishaji cha Ubao", "START_SELECTED": "Anza Uliochagua", - "START_RANDOM": "Anza kwa Nasibu", + "START_RANDOM": "Cheza Ubao wa Nasibu", "TILESET": "Sanaa ya Vigae", "BACKGROUND": "Mandhari ya Nyuma", "INFO": "Taarifa", @@ -190,10 +194,13 @@ "t_e9": "Ziada 9", "SHUFFLE": "Changanya", "SHUFFLE_LONG": "Changanya mawe katika mchezo", + "RESCUE_SHUFFLE": "Changanya ili Kuendelea", + "RESCUE_SHUFFLE_LONG": "Changanya kama hakuna hatua zaidi", "GAME_MODE": "Hali", "GAME_MODE_EASY": "Rahisi", "GAME_MODE_STANDARD": "Kawaida", "GAME_MODE_EXPERT": "Mtaalamu", + "GAME_MODE_NO_HELPERS": "Bila wasaidizi - unahitaji ujuzi safi", "HOW_TO_PLAY": "Jinsi ya kucheza", "HOW_GOAL": "Lengo ni kuondoa vigae vyote katika jozi zilizo wazi kutoka kwenye ubao wa mchezo.", "HOW_OPEN": "Wazi", diff --git a/src/assets/i18n/ta.json b/src/assets/i18n/ta.json index 145b8b08..992ba785 100644 --- a/src/assets/i18n/ta.json +++ b/src/assets/i18n/ta.json @@ -30,7 +30,9 @@ "SETTINGS": "அமைப்புகள்", "STATS": "புள்ளிவிவரங்கள்", "MODE": "பலகை நிரப்பும் வழிமுறை", - "MODE_SOLVABLE": "தீர்க்கக்கூடியது", + "MODE_SOLVABLE": "தீர்க்கக்கூடியது (நிலையானது)", + "MODE_SOLVABLE_EASY": "தீர்க்கக்கூடியது (எளிது)", + "MODE_SOLVABLE_EXPERT": "தீர்க்கக்கூடியது (நிபுணர்)", "MODE_RANDOM": "சீரற்றது", "RANDOM_GROUP": "சீரற்றது", "RANDOM_LAYOUT": "சீரற்றது", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "ஓடுகள் தகவல்", "TILES": "ஓடுகள்", - "INFO_LONG": "ஓடுகள் தகவல்", + "TILES_INFO_LONG": "விளையாட்டிலுள்ள அனைத்து ஓடுகளின் கண்ணோட்டம்", "HELP": "உதவி", "HELP_LONG": "இந்த உரையாடலைக் காட்டு/மறை", "SETTINGS_LONG": "மொழி, ஓடு தொகுப்புகள் மற்றும் வண்ணங்களை மாற்று", - "MODE_SOLVABLE_DESC": "குறைந்தது ஒரு தீர்வு சாத்தியமுள்ள சீரற்ற நிரப்புதல்", - "MODE_RANDOM_DESC": "முற்றிலும் சீரற்ற நிரப்புதல், தீர்க்க இயலாமல் இருக்கலாம்", + "MODE_SOLVABLE_DESC": "குறைந்தது ஒரு தீர்வு இருக்கும் என்று உறுதியாக உள்ளது", + "MODE_SOLVABLE_EASY_DESC": "தளர்வான கடினம் - பொருத்த நிறைய ஜோடிகள் உள்ளன", + "MODE_SOLVABLE_EXPERT_DESC": "ஒரே நேரத்தில் சில ஜோடிகள் மட்டுமே - கவனமான திட்டமிடல் தேவை", + "MODE_RANDOM_DESC": "முழுக்க சீரற்ற அமைப்பு - தீர்க்க இயலாமல் இருக்கலாம்", "SELECT_BOARD": "பலகையைத் தேர்ந்தெடு", "BOARD_GENERATOR": "பலகை உருவாக்கி", "START_SELECTED": "தேர்ந்தெடுத்ததைத் தொடங்கு", - "START_RANDOM": "சீரற்றதைத் தொடங்கு", + "START_RANDOM": "சீரற்ற பலகையை விளையாடு", "TILESET": "ஓடு தொகுப்பு கலை", "BACKGROUND": "பின்னணி", "INFO": "தகவல்", @@ -190,10 +194,13 @@ "t_e9": "கூடுதல் 9", "SHUFFLE": "கலக்கு", "SHUFFLE_LONG": "விளையாட்டில் கற்களைக் கலக்கு", + "RESCUE_SHUFFLE": "தொடர கலக்கு", + "RESCUE_SHUFFLE_LONG": "நகர்வுகள் இல்லாதபோது கலக்கு", "GAME_MODE": "முறை", "GAME_MODE_EASY": "எளிதானது", "GAME_MODE_STANDARD": "நிலையானது", "GAME_MODE_EXPERT": "நிபுணர்", + "GAME_MODE_NO_HELPERS": "உதவியில்லாமல் - தூய திறமை தேவை", "HOW_TO_PLAY": "விளையாடுவது எப்படி", "HOW_GOAL": "விளையாட்டுப் பலகையிலிருந்து திறந்த ஜோடிகளாக அனைத்து ஓடுகளையும் அகற்றுவதே குறிக்கோள்.", "HOW_OPEN": "திறந்த", diff --git a/src/assets/i18n/te.json b/src/assets/i18n/te.json index 0cf90aae..1399399c 100644 --- a/src/assets/i18n/te.json +++ b/src/assets/i18n/te.json @@ -30,7 +30,9 @@ "SETTINGS": "సెట్టింగ్‌లు", "STATS": "గణాంకాలు", "MODE": "బోర్డ్ నింపే అల్గారిథం", - "MODE_SOLVABLE": "సాధించగలిగేది", + "MODE_SOLVABLE": "సాధించగలిగేది (ప్రామాణికం)", + "MODE_SOLVABLE_EASY": "పరిష్కారయోగ్యం (సులభం)", + "MODE_SOLVABLE_EXPERT": "పరిష్కారయోగ్యం (నిపుణుడు)", "MODE_RANDOM": "యాదృచ్ఛికం", "RANDOM_GROUP": "యాదృచ్ఛికం", "RANDOM_LAYOUT": "యాదృచ్ఛికం", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "టైల్స్ సమాచారం", "TILES": "టైల్స్", - "INFO_LONG": "టైల్స్ సమాచారం", + "TILES_INFO_LONG": "గేమ్ లోని అన్ని టైల్స్ యొక్క సమీక్ష", "HELP": "సహాయం", "HELP_LONG": "ఈ డైలాగ్ చూపించు/దాచు", "SETTINGS_LONG": "భాష, టైల్ సెట్లు & రంగులు సర్దుబాటు చేయండి", - "MODE_SOLVABLE_DESC": "కనీసం ఒక పరిష్కార అవకాశం ఉన్న యాదృచ్ఛిక నింపుదల", - "MODE_RANDOM_DESC": "పూర్తిగా యాదృచ్ఛిక నింపుదల, పరిష్కారం సాధ్యం కాకపోవచ్చు", + "MODE_SOLVABLE_DESC": "కనీసం ఒక పరిష్కారం ఉంటుందని హామీ", + "MODE_SOLVABLE_EASY_DESC": "సరళమైన కష్టం - మ్యాచ్ చేయడానికి చాలా జంటలు అందుబాటులో", + "MODE_SOLVABLE_EXPERT_DESC": "ఒకేసారి తక్కువ జంటలు అందుబాటులో - జాగ్రత్తగా ప్లాన్ చేయాలి", + "MODE_RANDOM_DESC": "పూర్తిగా యాదృచ్ఛిక అమరిక - పరిష్కారం సాధ్యం కాకపోవచ్చు", "SELECT_BOARD": "బోర్డ్ ఎంచుకోండి", "BOARD_GENERATOR": "బోర్డ్ జనరేటర్", "START_SELECTED": "ఎంచుకున్నది ప్రారంభించు", - "START_RANDOM": "యాదృచ్ఛికంగా ప్రారంభించు", + "START_RANDOM": "యాదృచ్ఛిక బోర్డ్ ఆడు", "TILESET": "టైల్‌సెట్ కళ", "BACKGROUND": "నేపథ్యం", "INFO": "సమాచారం", @@ -190,10 +194,13 @@ "t_e9": "అదనపు 9", "SHUFFLE": "కలపు", "SHUFFLE_LONG": "ఆటలోని రాళ్ళను కలపు", + "RESCUE_SHUFFLE": "కొనసాగించడానికి కలపు", + "RESCUE_SHUFFLE_LONG": "ఇంకా కదలికలు లేకపోతే కలపు", "GAME_MODE": "మోడ్", "GAME_MODE_EASY": "సులభం", "GAME_MODE_STANDARD": "ప్రామాణికం", "GAME_MODE_EXPERT": "నిపుణుడు", + "GAME_MODE_NO_HELPERS": "సహాయకులు లేరు - స్వచ్ఛమైన నైపుణ్యం అవసరం", "HOW_TO_PLAY": "ఎలా ఆడాలి", "HOW_GOAL": "ఆట బోర్డ్ నుండి అన్ని టైల్స్‌ను తెరిచిన జతలలో తొలగించడమే లక్ష్యం.", "HOW_OPEN": "తెరిచినది", diff --git a/src/assets/i18n/th.json b/src/assets/i18n/th.json index d01037d9..8484465d 100644 --- a/src/assets/i18n/th.json +++ b/src/assets/i18n/th.json @@ -30,7 +30,9 @@ "SETTINGS": "การตั้งค่า", "STATS": "สถิติ", "MODE": "อัลกอริทึมการเติมกระดาน", - "MODE_SOLVABLE": "แก้ได้", + "MODE_SOLVABLE": "แก้ได้ (มาตรฐาน)", + "MODE_SOLVABLE_EASY": "แก้ได้ (ง่าย)", + "MODE_SOLVABLE_EXPERT": "แก้ได้ (ผู้เชี่ยวชาญ)", "MODE_RANDOM": "สุ่ม", "RANDOM_GROUP": "สุ่ม", "RANDOM_LAYOUT": "สุ่ม", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "ข้อมูลไพ่", "TILES": "ไพ่", - "INFO_LONG": "ข้อมูลไพ่", + "TILES_INFO_LONG": "ภาพรวมของไพ่ทั้งหมดในเกม", "HELP": "ช่วยเหลือ", "HELP_LONG": "แสดง/ซ่อนหน้าต่างนี้", "SETTINGS_LONG": "ปรับภาษา ชุดไพ่ และสี", - "MODE_SOLVABLE_DESC": "การเติมแบบสุ่มที่มีวิธีแก้อย่างน้อยหนึ่งวิธี", - "MODE_RANDOM_DESC": "การเติมแบบสุ่มทั้งหมด อาจแก้ไม่ได้", + "MODE_SOLVABLE_DESC": "รับประกันว่ามีคำตอบอย่างน้อยหนึ่งวิธี", + "MODE_SOLVABLE_EASY_DESC": "ความยากระดับผ่อนคลาย - มีคู่มากมายให้จับคู่", + "MODE_SOLVABLE_EXPERT_DESC": "มีคู่น้อยในแต่ละครั้ง - ต้องวางแผนอย่างรอบคอบ", + "MODE_RANDOM_DESC": "การจัดเรียงแบบสุ่มทั้งหมด - อาจแก้ไม่ได้", "SELECT_BOARD": "เลือกกระดาน", "BOARD_GENERATOR": "ตัวสร้างกระดาน", "START_SELECTED": "เริ่มที่เลือก", - "START_RANDOM": "เริ่มแบบสุ่ม", + "START_RANDOM": "เล่นกระดานสุ่ม", "TILESET": "ชุดลายไพ่", "BACKGROUND": "พื้นหลัง", "INFO": "ข้อมูล", @@ -190,10 +194,13 @@ "t_e9": "พิเศษ 9", "SHUFFLE": "สับไพ่", "SHUFFLE_LONG": "สับไพ่ในเกม", + "RESCUE_SHUFFLE": "สับไพ่เพื่อเล่นต่อ", + "RESCUE_SHUFFLE_LONG": "สับไพ่หากไม่มีการเคลื่อนไหวอีกต่อไป", "GAME_MODE": "โหมด", "GAME_MODE_EASY": "ง่าย", "GAME_MODE_STANDARD": "มาตรฐาน", "GAME_MODE_EXPERT": "ผู้เชี่ยวชาญ", + "GAME_MODE_NO_HELPERS": "ไม่มีผู้ช่วย - ต้องใช้ทักษะล้วนๆ", "HOW_TO_PLAY": "วิธีเล่น", "HOW_GOAL": "เป้าหมายคือการนำไพ่ที่เปิดอยู่ออกเป็นคู่จากกระดานจนหมด", "HOW_OPEN": "เปิด", diff --git a/src/assets/i18n/tr.json b/src/assets/i18n/tr.json index 375f7339..f73d424f 100644 --- a/src/assets/i18n/tr.json +++ b/src/assets/i18n/tr.json @@ -30,7 +30,9 @@ "SETTINGS": "Ayarlar", "STATS": "İstatistikler", "MODE": "Tablo Doldurma Algoritması", - "MODE_SOLVABLE": "Çözülebilir", + "MODE_SOLVABLE": "Çözülebilir (Standart)", + "MODE_SOLVABLE_EASY": "Çözülebilir (Kolay)", + "MODE_SOLVABLE_EXPERT": "Çözülebilir (Uzman)", "MODE_RANDOM": "Rastgele", "RANDOM_GROUP": "Rastgele", "RANDOM_LAYOUT": "Rastgele", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://tr.wikipedia.org/wiki/Mahjong", "TILES_INFO": "Taş Bilgileri", "TILES": "Taşlar", - "INFO_LONG": "Taş Bilgileri", + "TILES_INFO_LONG": "Oyundaki tüm taşların genel görünümü", "HELP": "Yardım", "HELP_LONG": "Bu iletişim kutusunu göster/gizle", "SETTINGS_LONG": "Dil, taş setleri ve renkleri ayarla", - "MODE_SOLVABLE_DESC": "En az bir çözüm olasılığı olan rastgele doldurma", - "MODE_RANDOM_DESC": "Tamamen rastgele doldurma, belki çözülemez", + "MODE_SOLVABLE_DESC": "En az bir çözümü olduğu garantidir", + "MODE_SOLVABLE_EASY_DESC": "Rahat zorluk - eşleştirmek için bolca çift mevcut", + "MODE_SOLVABLE_EXPERT_DESC": "Aynı anda az çift mevcut - dikkatli planlama gerektirir", + "MODE_RANDOM_DESC": "Tamamen rastgele düzen - çözülemez olabilir", "SELECT_BOARD": "Tabloyu Seç", "BOARD_GENERATOR": "Tablo Üreticisi", "START_SELECTED": "Seçileni Başlat", - "START_RANDOM": "Rastgeleyi Başlat", + "START_RANDOM": "Rastgele Tahtayı Oyna", "TILESET": "Taş Seti Sanatı", "BACKGROUND": "Arka Plan", "INFO": "Bilgi", @@ -190,10 +194,13 @@ "t_e9": "Ekstra 9", "SHUFFLE": "Karıştır", "SHUFFLE_LONG": "Oyundaki taşları karıştır", + "RESCUE_SHUFFLE": "Devam etmek için Karıştır", + "RESCUE_SHUFFLE_LONG": "Daha fazla hamle yoksa karıştır", "GAME_MODE": "Mod", "GAME_MODE_EASY": "Kolay", "GAME_MODE_STANDARD": "Standart", "GAME_MODE_EXPERT": "Uzman", + "GAME_MODE_NO_HELPERS": "Yardımcı yok - salt beceri gerektirir", "HOW_TO_PLAY": "Nasıl Oynanır", "HOW_GOAL": "Amaç, oyun tablosundan tüm açık çiftler taşları çıkarmaktır.", "HOW_OPEN": "Açık", diff --git a/src/assets/i18n/uk.json b/src/assets/i18n/uk.json index 27d72ce9..a229164f 100644 --- a/src/assets/i18n/uk.json +++ b/src/assets/i18n/uk.json @@ -30,7 +30,9 @@ "SETTINGS": "Параметри", "STATS": "Статистика", "MODE": "Алгоритм заповнення дошки", - "MODE_SOLVABLE": "Розв'язуваний", + "MODE_SOLVABLE": "Розв'язуваний (Стандарт)", + "MODE_SOLVABLE_EASY": "Вирішуване (Легко)", + "MODE_SOLVABLE_EXPERT": "Вирішуване (Експерт)", "MODE_RANDOM": "Випадковий", "RANDOM_GROUP": "Випадковий", "RANDOM_LAYOUT": "Випадковий", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://uk.wikipedia.org/wiki/Маджонг", "TILES_INFO": "Інформація про камені", "TILES": "Камені", - "INFO_LONG": "Інформація про камені", + "TILES_INFO_LONG": "Огляд усіх плиток у грі", "HELP": "Довідка", "HELP_LONG": "Показати/приховати цей діалог", "SETTINGS_LONG": "Налаштуйте мову, набори каменів та кольори", - "MODE_SOLVABLE_DESC": "Випадкове заповнення з щонайменше однією можливістю розв'язання", - "MODE_RANDOM_DESC": "Повністю випадкове заповнення, можливо нерозв'язуване", + "MODE_SOLVABLE_DESC": "Гарантовано має щонайменше одне рішення", + "MODE_SOLVABLE_EASY_DESC": "Розслаблений рівень складності - багато пар для з'єднання", + "MODE_SOLVABLE_EXPERT_DESC": "Мало пар одночасно - вимагає ретельного планування", + "MODE_RANDOM_DESC": "Повністю випадкове розташування - можливо нерозв'язуване", "SELECT_BOARD": "Вибрати дошку", "BOARD_GENERATOR": "Генератор дошки", "START_SELECTED": "Почати вибрану", - "START_RANDOM": "Почати випадкову", + "START_RANDOM": "Грати випадкову дошку", "TILESET": "Мистецтво набору каменів", "BACKGROUND": "Фон", "INFO": "Інформація", @@ -190,10 +194,13 @@ "t_e9": "Додатково 9", "SHUFFLE": "Перемішати", "SHUFFLE_LONG": "Перемішати камені в грі", + "RESCUE_SHUFFLE": "Перемішати для продовження", + "RESCUE_SHUFFLE_LONG": "Перемішати якщо немає доступних ходів", "GAME_MODE": "Режим", "GAME_MODE_EASY": "Легко", "GAME_MODE_STANDARD": "Стандарт", "GAME_MODE_EXPERT": "Експерт", + "GAME_MODE_NO_HELPERS": "Без помічників - потрібна чиста майстерність", "HOW_TO_PLAY": "Як грати", "HOW_GOAL": "Мета - видалити всі камені у відкритих парах з ігрової дошки.", "HOW_OPEN": "Відкрити", diff --git a/src/assets/i18n/ur.json b/src/assets/i18n/ur.json index 43467dac..28551531 100644 --- a/src/assets/i18n/ur.json +++ b/src/assets/i18n/ur.json @@ -30,7 +30,9 @@ "SETTINGS": "ترتیبات", "STATS": "اعداد و شمار", "MODE": "بورڈ بھرنے کا الگورتھم", - "MODE_SOLVABLE": "حل ہونے والا", + "MODE_SOLVABLE": "حل ہونے والا (معیاری)", + "MODE_SOLVABLE_EASY": "حل ہونے والا (آسان)", + "MODE_SOLVABLE_EXPERT": "حل ہونے والا (ماہر)", "MODE_RANDOM": "بے ترتیب", "RANDOM_GROUP": "بے ترتیب", "RANDOM_LAYOUT": "بے ترتیب", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "ٹائلوں کی معلومات", "TILES": "ٹائلیں", - "INFO_LONG": "ٹائلوں کی معلومات", + "TILES_INFO_LONG": "کھیل میں تمام ٹائلز کا جائزہ", "HELP": "مدد", "HELP_LONG": "یہ ڈائیلاگ دکھائیں/چھپائیں", "SETTINGS_LONG": "زبان، ٹائل سیٹ اور رنگ ایڈجسٹ کریں", - "MODE_SOLVABLE_DESC": "کم از کم ایک حل کے ساتھ بے ترتیب بھرائی", - "MODE_RANDOM_DESC": "مکمل بے ترتیب بھرائی، شاید حل نہ ہو", + "MODE_SOLVABLE_DESC": "کم از کم ایک حل ہونے کی ضمانت", + "MODE_SOLVABLE_EASY_DESC": "آسان مشکل - ملانے کے لیے بہت سے جوڑے دستیاب", + "MODE_SOLVABLE_EXPERT_DESC": "ایک وقت میں کم جوڑے دستیاب - محتاط منصوبہ بندی کی ضرورت", + "MODE_RANDOM_DESC": "مکمل بے ترتیب ترتیب - شاید حل نہ ہو", "SELECT_BOARD": "بورڈ منتخب کریں", "BOARD_GENERATOR": "بورڈ جنریٹر", "START_SELECTED": "منتخب شروع کریں", - "START_RANDOM": "بے ترتیب شروع کریں", + "START_RANDOM": "بے ترتیب بورڈ کھیلیں", "TILESET": "ٹائل سیٹ آرٹ", "BACKGROUND": "پس منظر", "INFO": "معلومات", @@ -190,10 +194,13 @@ "t_e9": "اضافی 9", "SHUFFLE": "خلط ملط", "SHUFFLE_LONG": "گیم میں پتھر خلط ملط کریں", + "RESCUE_SHUFFLE": "جاری رکھنے کے لیے خلط ملط", + "RESCUE_SHUFFLE_LONG": "خلط ملط کریں اگر مزید حرکات نہ ہوں", "GAME_MODE": "موڈ", "GAME_MODE_EASY": "آسان", "GAME_MODE_STANDARD": "معیاری", "GAME_MODE_EXPERT": "ماہر", + "GAME_MODE_NO_HELPERS": "کوئی مددگار نہیں - خالص مہارت درکار ہے", "HOW_TO_PLAY": "کیسے کھیلیں", "HOW_GOAL": "مقصد گیم بورڈ سے کھلے جوڑوں میں تمام ٹائلیں ہٹانا ہے۔", "HOW_OPEN": "کھلی", diff --git a/src/assets/i18n/vi.json b/src/assets/i18n/vi.json index d5d7dd7e..67ecc04c 100644 --- a/src/assets/i18n/vi.json +++ b/src/assets/i18n/vi.json @@ -30,7 +30,9 @@ "SETTINGS": "Cài Đặt", "STATS": "Thống Kê", "MODE": "Thuật Toán Điền Bảng", - "MODE_SOLVABLE": "Có Thể Giải", + "MODE_SOLVABLE": "Có Thể Giải (Tiêu Chuẩn)", + "MODE_SOLVABLE_EASY": "Có Thể Giải (Dễ)", + "MODE_SOLVABLE_EXPERT": "Có Thể Giải (Chuyên Gia)", "MODE_RANDOM": "Ngẫu Nhiên", "RANDOM_GROUP": "Ngẫu Nhiên", "RANDOM_LAYOUT": "Ngẫu Nhiên", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://en.wikipedia.org/wiki/Mahjong_tiles", "TILES_INFO": "Thông Tin Đá", "TILES": "Đá", - "INFO_LONG": "Thông Tin Đá", + "TILES_INFO_LONG": "Tổng quan về tất cả quân trong trò chơi", "HELP": "Trợ Giúp", "HELP_LONG": "Hiển thị/ẩn hộp thoại này", "SETTINGS_LONG": "Điều chỉnh ngôn ngữ, bộ đá và màu sắc", - "MODE_SOLVABLE_DESC": "Một cách điền ngẫu nhiên với ít nhất một khả năng giải", - "MODE_RANDOM_DESC": "Một cách điền hoàn toàn ngẫu nhiên, có thể không thể giải", + "MODE_SOLVABLE_DESC": "Đảm bảo có ít nhất một lời giải", + "MODE_SOLVABLE_EASY_DESC": "Độ khó thoải mái - nhiều cặp sẵn có để ghép", + "MODE_SOLVABLE_EXPERT_DESC": "Ít cặp sẵn có cùng lúc - đòi hỏi lập kế hoạch cẩn thận", + "MODE_RANDOM_DESC": "Bố cục hoàn toàn ngẫu nhiên - có thể không thể giải", "SELECT_BOARD": "Chọn Bảng", "BOARD_GENERATOR": "Trình Tạo Bảng", "START_SELECTED": "Bắt Đầu Đã Chọn", - "START_RANDOM": "Bắt Đầu Ngẫu Nhiên", + "START_RANDOM": "Chơi Bảng Ngẫu Nhiên", "TILESET": "Nghệ Thuật Bộ Đá", "BACKGROUND": "Hình Nền", "INFO": "Thông Tin", @@ -190,10 +194,13 @@ "t_e9": "Thêm 9", "SHUFFLE": "Xáo Trộn", "SHUFFLE_LONG": "Xáo trộn đá trong trò chơi", + "RESCUE_SHUFFLE": "Xáo Trộn để Tiếp Tục", + "RESCUE_SHUFFLE_LONG": "Xáo trộn nếu không còn nước đi nào", "GAME_MODE": "Chế Độ", "GAME_MODE_EASY": "Dễ", "GAME_MODE_STANDARD": "Tiêu Chuẩn", "GAME_MODE_EXPERT": "Chuyên Gia", + "GAME_MODE_NO_HELPERS": "Không có trợ giúp - chỉ dựa vào kỹ năng thuần túy", "HOW_TO_PLAY": "Cách Chơi", "HOW_GOAL": "Mục tiêu là loại bỏ tất cả đá ở các cặp mở từ bảng trò chơi.", "HOW_OPEN": "Mở", diff --git a/src/assets/i18n/zh.json b/src/assets/i18n/zh.json index 2745a032..c58cc0f1 100644 --- a/src/assets/i18n/zh.json +++ b/src/assets/i18n/zh.json @@ -30,7 +30,9 @@ "SETTINGS": "设置", "STATS": "统计", "MODE": "牌局填充算法", - "MODE_SOLVABLE": "可解", + "MODE_SOLVABLE": "可解(标准)", + "MODE_SOLVABLE_EASY": "可解(简单)", + "MODE_SOLVABLE_EXPERT": "可解(专家)", "MODE_RANDOM": "随机", "RANDOM_GROUP": "随机", "RANDOM_LAYOUT": "随机", @@ -52,16 +54,18 @@ "READ_MORE_WIKIPEDIA_URL": "https://zh.wikipedia.org/wiki/麻将牌", "TILES_INFO": "牌信息", "TILES": "牌", - "INFO_LONG": "牌信息", + "TILES_INFO_LONG": "游戏中所有牌的概览", "HELP": "帮助", "HELP_LONG": "显示/隐藏此对话框", "SETTINGS_LONG": "调整语言、牌组和颜色", - "MODE_SOLVABLE_DESC": "随机填充但至少有一种解法", - "MODE_RANDOM_DESC": "完全随机填充,可能无解", + "MODE_SOLVABLE_DESC": "保证至少有一种解法", + "MODE_SOLVABLE_EASY_DESC": "难度轻松 - 有大量配对可供匹配", + "MODE_SOLVABLE_EXPERT_DESC": "同时可用的配对很少 - 需要仔细规划", + "MODE_RANDOM_DESC": "完全随机布局 - 可能无解", "SELECT_BOARD": "选择牌局", "BOARD_GENERATOR": "牌局生成器", "START_SELECTED": "开始选中的", - "START_RANDOM": "开始随机的", + "START_RANDOM": "玩随机棋盘", "TILESET": "牌组", "BACKGROUND": "背景", "INFO": "信息", @@ -190,10 +194,13 @@ "t_e9": "额外9", "SHUFFLE": "洗牌", "SHUFFLE_LONG": "洗牌重新排列", + "RESCUE_SHUFFLE": "洗牌以继续", + "RESCUE_SHUFFLE_LONG": "如果没有更多移动则洗牌", "GAME_MODE": "游戏模式", "GAME_MODE_EASY": "简单", "GAME_MODE_STANDARD": "标准", "GAME_MODE_EXPERT": "专家", + "GAME_MODE_NO_HELPERS": "没有助手 - 需要纯粹的技能", "HOW_TO_PLAY": "如何游戏", "HOW_GOAL": "目标是将游戏板上所有开放的配对牌全部移除。", "HOW_OPEN": "开放", diff --git a/src/fonts/README.md b/src/fonts/README.md index 6a5d961e..b8f5601f 100644 --- a/src/fonts/README.md +++ b/src/fonts/README.md @@ -1,9 +1,9 @@ # Fonts -`Fontello Icon` -SIL License - - `Kulim Park` SIL License + + +For information about the icons please see + diff --git a/src/fonts/editor/LICENSE.txt b/src/fonts/editor/LICENSE.txt deleted file mode 100644 index 81e755e8..00000000 --- a/src/fonts/editor/LICENSE.txt +++ /dev/null @@ -1,30 +0,0 @@ -Font license info - - -## Typicons - - (c) Stephen Hutchings 2012 - - Author: Stephen Hutchings - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://typicons.com/ - - -## Entypo - - Copyright (C) 2012 by Daniel Bruce - - Author: Daniel Bruce - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://www.entypo.com - - -## Font Awesome - - Copyright (C) 2016 by Dave Gandy - - Author: Dave Gandy - License: SIL () - Homepage: http://fortawesome.github.com/Font-Awesome/ - - diff --git a/src/fonts/editor/config.json b/src/fonts/editor/config.json deleted file mode 100644 index 62b11545..00000000 --- a/src/fonts/editor/config.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "name": "editor", - "css_prefix_text": "icon-editor-", - "css_use_suffix": false, - "hinting": true, - "units_per_em": 1000, - "ascent": 850, - "glyphs": [ - { - "uid": "c16a63e911bc47b46dc2a7129d2f0c46", - "css": "down-small", - "code": 59392, - "src": "typicons" - }, - { - "uid": "58b78b6ca784d5c3db5beefcd9e18061", - "css": "left-small", - "code": 59393, - "src": "typicons" - }, - { - "uid": "877a233d7fdca8a1d82615b96ed0d7a2", - "css": "right-small", - "code": 59394, - "src": "typicons" - }, - { - "uid": "62bc6fe2a82e4864e2b94d4c0985ee0c", - "css": "up-small", - "code": 59395, - "src": "typicons" - }, - { - "uid": "2626e3a1bbcd90e45849af3b58a1d594", - "css": "trash", - "code": 59396, - "src": "entypo" - }, - { - "uid": "3df1557e2d6e84ec32bd47aee5bfdf59", - "css": "cancel-alt", - "code": 59397, - "src": "typicons" - }, - { - "uid": "c8585e1e5b0467f28b70bce765d5840c", - "css": "docs", - "code": 61637, - "src": "fontawesome" - }, - { - "uid": "97bd5542ed3e143d2ee9b60e14487615", - "css": "list-add", - "code": 59442, - "src": "entypo" - }, - { - "uid": "12f4ece88e46abd864e40b35e05b11cd", - "css": "ok", - "code": 59408, - "src": "fontawesome" - }, - { - "uid": "4b2321afcbe0505a70b80abd5c25e09b", - "css": "paper-plane-empty", - "code": 61913, - "src": "fontawesome" - } - ] -} \ No newline at end of file diff --git a/src/fonts/editor/css/editor.css b/src/fonts/editor/css/editor.css deleted file mode 100644 index 993ba3b8..00000000 --- a/src/fonts/editor/css/editor.css +++ /dev/null @@ -1,72 +0,0 @@ -@font-face { - font-family: editor; - src: url('../font/editor.eot?76220897'); - src: url('../font/editor.eot?76220897#iefix') format('embedded-opentype'), - url('../font/editor.woff2?76220897') format('woff2'), - url('../font/editor.woff?76220897') format('woff'), - url('../font/editor.ttf?76220897') format('truetype'), - url('../font/editor.svg?76220897#editor') format('svg'); - font-weight: normal; - font-style: normal; -} - -/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ - -/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ - -/* -@media screen and (-webkit-min-device-pixel-ratio:0) { - @font-face { - font-family: 'editor'; - src: url('../font/editor.svg?76220897#editor') format('svg'); - } -} -*/ -[class^="icon-editor-"]::before, [class*=" icon-editor-"]::before { - font-family: editor, emoji; - font-style: normal; - font-weight: normal; - speak: never; - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - - /* opacity: .8; */ - - /* For safety - reset parent styles, that can break glyph codes */ - font-variant: normal; - text-transform: none; - - /* fix buttons height, for twitter bootstrap */ - line-height: 1em; - - /* Animation center compensation - margins should be symmetric */ - - /* remove if not needed */ - margin-left: .2em; - - /* you can be more comfortable with increased icons size */ - - /* font-size: 120%; */ - - /* Font smoothing. That was taken from TWBS */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - /* Uncomment for 3D effect */ - - /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ -} - -.icon-editor-down-small::before { content: '\e800'; } /* '' */ -.icon-editor-left-small::before { content: '\e801'; } /* '' */ -.icon-editor-right-small::before { content: '\e802'; } /* '' */ -.icon-editor-up-small::before { content: '\e803'; } /* '' */ -.icon-editor-trash::before { content: '\e804'; } /* '' */ -.icon-editor-cancel-alt::before { content: '\e805'; } /* '' */ -.icon-editor-ok::before { content: '\e810'; } /* '' */ -.icon-editor-list-add::before { content: '\e832'; } /* '' */ -.icon-editor-docs::before { content: '\f0c5'; } /* '' */ -.icon-editor-paper-plane-empty::before { content: '\f1d9'; } /* '' */ diff --git a/src/fonts/editor/font/editor.eot b/src/fonts/editor/font/editor.eot deleted file mode 100644 index ff62ffa7..00000000 Binary files a/src/fonts/editor/font/editor.eot and /dev/null differ diff --git a/src/fonts/editor/font/editor.svg b/src/fonts/editor/font/editor.svg deleted file mode 100644 index 4a4240fe..00000000 --- a/src/fonts/editor/font/editor.svg +++ /dev/null @@ -1,30 +0,0 @@ - - - -Copyright (C) 2024 by original authors @ fontello.com - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/fonts/editor/font/editor.ttf b/src/fonts/editor/font/editor.ttf deleted file mode 100644 index e69c4498..00000000 Binary files a/src/fonts/editor/font/editor.ttf and /dev/null differ diff --git a/src/fonts/editor/font/editor.woff b/src/fonts/editor/font/editor.woff deleted file mode 100644 index 6f38aeff..00000000 Binary files a/src/fonts/editor/font/editor.woff and /dev/null differ diff --git a/src/fonts/editor/font/editor.woff2 b/src/fonts/editor/font/editor.woff2 deleted file mode 100644 index 94ba94bc..00000000 Binary files a/src/fonts/editor/font/editor.woff2 and /dev/null differ diff --git a/src/fonts/fontello/LICENSE.txt b/src/fonts/fontello/LICENSE.txt deleted file mode 100644 index 31735b8f..00000000 --- a/src/fonts/fontello/LICENSE.txt +++ /dev/null @@ -1,48 +0,0 @@ -Font license info - - -## Entypo - - Copyright (C) 2012 by Daniel Bruce - - Author: Daniel Bruce - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://www.entypo.com - - -## Font Awesome - - Copyright (C) 2016 by Dave Gandy - - Author: Dave Gandy - License: SIL () - Homepage: http://fortawesome.github.com/Font-Awesome/ - - -## Iconic - - Copyright (C) 2012 by P.J. Onori - - Author: P.J. Onori - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://somerandomdude.com/work/iconic/ - - -## Fontelico - - Copyright (C) 2012 by Fontello project - - Author: Crowdsourced, for Fontello project - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://fontello.com - - -## Typicons - - (c) Stephen Hutchings 2012 - - Author: Stephen Hutchings - License: SIL (http://scripts.sil.org/OFL) - Homepage: http://typicons.com/ - - diff --git a/src/fonts/fontello/config.json b/src/fonts/fontello/config.json deleted file mode 100644 index d0f75393..00000000 --- a/src/fonts/fontello/config.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "name": "mah", - "css_prefix_text": "icon-", - "css_use_suffix": false, - "hinting": true, - "units_per_em": 1000, - "ascent": 850, - "glyphs": [ - { - "uid": "5278ef7773e948d56c4d442c8c8c98cf", - "css": "lightbulb", - "code": 59395, - "src": "fontawesome" - }, - { - "uid": "ce5e29aa5208417700e7f7012a236c00", - "css": "undo", - "code": 59399, - "src": "iconic" - }, - { - "uid": "72109d2fb3088d0e66ea6a9204297651", - "css": "spin1", - "code": 59400, - "src": "fontelico" - }, - { - "uid": "2e2dba0307a502a8507c1729084c7ab5", - "css": "cancel-circled2", - "code": 59401, - "src": "fontawesome" - }, - { - "uid": "c833c98d78cfebed5780cfaaa302a12b", - "css": "calendar", - "code": 59402, - "src": "iconic" - }, - { - "uid": "fda731b5a4026685e1a9c7e64228e2b2", - "css": "note-beamed", - "code": 59403, - "src": "entypo" - }, - { - "uid": "43m0a70tvxqc6q7jxgzhz5lmlt3ce2iy", - "css": "volume-low", - "code": 59406, - "src": "typicons" - }, - { - "uid": "776687efbdb973ebc67e049cc4c41b13", - "css": "resize-full-alt", - "code": 59405, - "src": "iconic" - }, - { - "uid": "5d3ef4b7c90d2931e641b840ee42f694", - "css": "loop", - "code": 59410, - "src": "iconic" - }, - { - "uid": "e99461abfef3923546da8d745372c995", - "css": "cog", - "code": 59411, - "src": "fontawesome" - }, - { - "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", - "css": "trash-empty", - "code": 59413, - "src": "fontawesome" - }, - { - "uid": "d8d378d0ce413f231dfa37592e39c227", - "css": "pause", - "code": 59392, - "src": "entypo" - }, - { - "uid": "559647a6f430b3aeadbecd67194451dd", - "css": "menu", - "code": 61641, - "src": "fontawesome" - }, - { - "uid": "b38002a7e1a57208ec9353285c99ed86", - "css": "logo", - "code": 59393, - "src": "custom_icons", - "selected": true, - "svg": { - "path": "M460.6 66.7C451.5 75.8 453.5 104 464.6 140.9 471.7 162.6 475.3 190.4 476.3 224.2L477.3 274.7 431.8 289.4C407.1 297 373.2 308.1 357.1 313.1L327.3 322.7 311.6 307.1C287.9 284.8 264.6 276.3 248 284.3 240.9 287.9 234.3 295.5 233.3 301 231.8 310.6 266.7 369.7 355.1 508.6 366.2 526.3 378.8 540.9 383.3 540.9 398.5 541.9 411.6 539.4 418.2 533.8 425.8 527.8 479.8 523.2 480.3 528.8 480.8 531.3 481.3 570.2 482.3 616.2 485.9 770.7 488.9 828.3 498 870.2 509.6 927.3 525.3 941.4 531.8 901.5 533.3 892.9 535.9 880.8 537.4 873.7 547 834.3 549.5 787.4 552.5 622.2 553.5 568.7 555.6 523.7 557.6 521.7 561.1 518.2 567.2 517.7 622.7 513.1 658.6 510.6 669.7 501.5 709.6 441.9 765.7 357.6 770.2 339.9 744.9 303 698.5 234.3 662.1 220.2 591.9 241.9L559.6 252 561.1 213.1C562.1 191.9 566.2 164.6 570.2 152.5 580.3 124.7 577.3 120.2 527.8 86.9 487.4 60.6 471.7 55.6 460.6 66.7ZM652 319.2C658.6 330.8 655.1 356.1 640.9 403.5L628.8 442.9 596 448C577.8 451 561.6 452.5 559.6 451 554.5 448.5 557.1 330.3 562.1 324.7 567.2 319.7 613.6 310.1 632.8 310.6 640.9 310.6 649.5 314.1 652 319.2ZM479.3 403.5L480.3 463.6 456.1 469.2C433.3 474.2 431.3 473.7 421.7 462.1 415.7 455.1 405.1 437.4 397.5 422.7 389.9 408.6 379.3 389.4 373.7 380.8L363.6 365.2 394.9 358.6C412.6 355.6 427.8 352.5 429.3 352 430.8 352 440.9 349 452 345.5 463.1 342.4 473.7 340.4 475.3 341.4 477.3 342.4 479.3 370.7 479.3 403.5Z", - "width": 1000 - }, - "search": [ - "logo" - ] - } - ] -} \ No newline at end of file diff --git a/src/fonts/fontello/css/mah.css b/src/fonts/fontello/css/mah.css deleted file mode 100644 index d72c2596..00000000 --- a/src/fonts/fontello/css/mah.css +++ /dev/null @@ -1,60 +0,0 @@ -@font-face { - font-family: mah; - src: url('../font/mah.eot?71598379'); - src: url('../font/mah.eot?71598379#iefix') format('embedded-opentype'), - url('../font/mah.woff2?71598379') format('woff2'), - url('../font/mah.woff?71598379') format('woff'), - url('../font/mah.ttf?71598379') format('truetype'), - url('../font/mah.svg?71598379#mah') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"]::before, [class*=" icon-"]::before { - font-family: mah, emoji; - font-style: normal; - font-weight: normal; - speak: never; - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - - /* For safety - reset parent styles, that can break glyph codes */ - font-variant: normal; - text-transform: none; - - /* fix buttons height, for twitter bootstrap */ - line-height: 1em; - - /* Animation center compensation - margins should be symmetric */ - margin-left: .2em; - - /* you can be more comfortable with increased icons size */ - - /* font-size: 120%; */ - - /* Font smoothing. That was taken from TWBS */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - /* Uncomment for 3D effect */ - - /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ -} - -.icon-pause::before { content: '\e800'; } /* '' */ -.icon-logo::before { content: '\e801'; } /* '' */ -.icon-lightbulb::before { content: '\e803'; } /* '' */ -.icon-undo::before { content: '\e807'; } /* '' */ -.icon-spin1::before { content: '\e808'; } /* '' */ -.icon-cancel-circled2::before { content: '\e809'; } /* '' */ -.icon-calendar::before { content: '\e80a'; } /* '' */ -.icon-note-beamed::before { content: '\e80b'; } /* '' */ -.icon-resize-full-alt::before { content: '\e80d'; } /* '' */ -.icon-volume-low::before { content: '\e80e'; } /* '' */ -.icon-loop::before { content: '\e812'; } /* '' */ -.icon-cog::before { content: '\e813'; } /* '' */ -.icon-trash-empty::before { content: '\e815'; } /* '' */ -.icon-menu::before { content: '\f0c9'; } /* '' */ diff --git a/src/fonts/fontello/font/mah.eot b/src/fonts/fontello/font/mah.eot deleted file mode 100644 index 1bad35d1..00000000 Binary files a/src/fonts/fontello/font/mah.eot and /dev/null differ diff --git a/src/fonts/fontello/font/mah.svg b/src/fonts/fontello/font/mah.svg deleted file mode 100644 index a6a13a5d..00000000 --- a/src/fonts/fontello/font/mah.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - -Copyright (C) 2025 by original authors @ fontello.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/fonts/fontello/font/mah.ttf b/src/fonts/fontello/font/mah.ttf deleted file mode 100644 index 76d64414..00000000 Binary files a/src/fonts/fontello/font/mah.ttf and /dev/null differ diff --git a/src/fonts/fontello/font/mah.woff b/src/fonts/fontello/font/mah.woff deleted file mode 100644 index d88a1e39..00000000 Binary files a/src/fonts/fontello/font/mah.woff and /dev/null differ diff --git a/src/fonts/fontello/font/mah.woff2 b/src/fonts/fontello/font/mah.woff2 deleted file mode 100644 index eb96d778..00000000 Binary files a/src/fonts/fontello/font/mah.woff2 and /dev/null differ diff --git a/src/styles.scss b/src/styles.scss index 45f2c9d0..79e52a52 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -5,6 +5,18 @@ box-sizing: border-box; } +.icon { + display: contents; + + svg { + display: block; + width: 1em; + height: 1em; + fill: currentColor; + flex-shrink: 0; + } +} + html { --main-bg-color: #2b424f; --main-bg-color-lt: #2e4856; @@ -564,7 +576,7 @@ p { border-radius: 12px; box-shadow: var(--overlay-popup-shadow); - .icon-logo { + app-icon-logo { color: red; } @@ -609,7 +621,7 @@ p { } } - // Size classes — applied to the outer .overlay div, target .overlay-popup inside + // Size classes - applied to the outer .overlay div, target .overlay-popup inside &.overlay-size-large { .overlay-popup { @@ -682,7 +694,7 @@ p { } } - // Per-dialog variants — z-index and behavior only, no sizing + // Per-dialog variants - z-index and behavior only, no sizing &.overlay-info { z-index: 10010;