@logic-pad/core
Version:
240 lines (239 loc) • 7.11 kB
JavaScript
import { ConfigType } from '../config.js';
import GridData from '../grid.js';
import { Color, Orientation, State, } from '../primitives.js';
import Rule from './rule.js';
import validateGrid from '../validate.js';
import Symbol from '../symbols/symbol.js';
import LetterSymbol from '../symbols/letterSymbol.js';
import GalaxySymbol from '../symbols/galaxySymbol.js';
import LotusSymbol from '../symbols/lotusSymbol.js';
import AreaNumberSymbol from '../symbols/areaNumberSymbol.js';
class IgnoredSymbol extends Symbol {
constructor(symbol, state) {
super(symbol.x, symbol.y);
Object.defineProperty(this, "symbol", {
enumerable: true,
configurable: true,
writable: true,
value: symbol
});
Object.defineProperty(this, "state", {
enumerable: true,
configurable: true,
writable: true,
value: state
});
this.symbol = symbol;
this.state = state;
}
get id() {
return `ignored_${this.symbol.id}`;
}
get explanation() {
return this.symbol.explanation;
}
get configs() {
return [];
}
createExampleGrid() {
return this.symbol.createExampleGrid();
}
get necessaryForCompletion() {
return this.symbol.necessaryForCompletion;
}
get visibleWhenSolving() {
return this.symbol.visibleWhenSolving;
}
get sortOrder() {
return this.symbol.sortOrder;
}
validateSymbol(_grid, _solution) {
return this.state;
}
copyWith({ symbol, state }) {
return new IgnoredSymbol(symbol ?? this.symbol, state ?? this.state);
}
withSymbol(symbol) {
return this.copyWith({ symbol });
}
equals(other) {
return other === this;
}
}
class IgnoredRule extends Rule {
constructor(rule, state) {
super();
Object.defineProperty(this, "rule", {
enumerable: true,
configurable: true,
writable: true,
value: rule
});
Object.defineProperty(this, "state", {
enumerable: true,
configurable: true,
writable: true,
value: state
});
this.rule = rule;
this.state = state;
}
get searchVariants() {
return [];
}
get id() {
return `ignored_${this.rule.id}`;
}
get explanation() {
return this.rule.explanation;
}
get configs() {
return [];
}
createExampleGrid() {
return this.rule.createExampleGrid();
}
get necessaryForCompletion() {
return this.rule.necessaryForCompletion;
}
get visibleWhenSolving() {
return this.rule.visibleWhenSolving;
}
get isSingleton() {
return this.rule.isSingleton;
}
validateGrid(_grid) {
if (this.state === State.Error)
return { state: State.Error, positions: [] };
else
return { state: this.state };
}
copyWith({ rule, state }) {
return new IgnoredRule(rule ?? this.rule, state ?? this.state);
}
equals(other) {
return other === this;
}
}
class LyingSymbolRule extends Rule {
/**
* **<count> symbols are lying and are incorrect**
*
* @param count Number of lying symbols
*/
constructor(count) {
super();
Object.defineProperty(this, "count", {
enumerable: true,
configurable: true,
writable: true,
value: count
});
this.count = count;
}
get id() {
return `lying_symbols`;
}
get explanation() {
return `${this.count} symbol${this.count <= 1 ? ' is' : 's are'} *lying* and ${this.count <= 1 ? 'is' : 'are'} incorrect`;
}
get configs() {
return LyingSymbolRule.CONFIGS;
}
createExampleGrid() {
return LyingSymbolRule.EXAMPLE_GRID;
}
get searchVariants() {
return LyingSymbolRule.SEARCH_VARIANTS;
}
validateGrid(_) {
return { state: State.Incomplete };
}
get isSingleton() {
return true;
}
onFinalValidation(grid, solution, state) {
const ignoredSymbols = [];
state.symbols.forEach((values, key) => {
values.forEach((state, idx) => {
if (state === State.Error)
ignoredSymbols.push([key, idx]);
});
});
if (ignoredSymbols.length > this.count) {
const thisIdx = grid.rules.findIndex(rule => rule.id === this.id);
return {
final: State.Error,
rules: state.rules.map((rule, idx) => idx === thisIdx ? { state: State.Error, positions: [] } : rule),
symbols: state.symbols,
};
}
const newSymbols = new Map();
grid.symbols.forEach((values, key) => {
values.forEach((symbol, idx) => {
if (!newSymbols.has(key)) {
newSymbols.set(key, []);
}
if (ignoredSymbols.some(([k, i]) => k === key && i === idx)) {
newSymbols.get(key).push(new IgnoredSymbol(symbol, State.Ignored));
}
else {
newSymbols.get(key).push(symbol);
}
});
});
const newRules = grid.rules.map(rule => rule.id === this.id
? new IgnoredRule(this, ignoredSymbols.length === this.count
? State.Satisfied
: grid.getTileCount(true, false, Color.Gray) === 0
? State.Error
: State.Incomplete)
: rule);
return validateGrid(grid.copyWith({ rules: newRules, symbols: newSymbols }), solution);
}
copyWith({ count }) {
return new LyingSymbolRule(count ?? this.count);
}
withCount(count) {
return this.copyWith({ count });
}
}
Object.defineProperty(LyingSymbolRule, "EXAMPLE_GRID", {
enumerable: true,
configurable: true,
writable: true,
value: Object.freeze(GridData.create(['bbbbw', 'wwbbb', 'bbbbw', 'wbbww']).withSymbols([
new LetterSymbol(4, 0, 'A'),
new GalaxySymbol(1, 1),
new LotusSymbol(2, 2, Orientation.Up),
new LetterSymbol(0, 3, 'A'),
new AreaNumberSymbol(4, 3, 1),
]))
});
Object.defineProperty(LyingSymbolRule, "CONFIGS", {
enumerable: true,
configurable: true,
writable: true,
value: Object.freeze([
{
type: ConfigType.Number,
default: 1,
min: 1,
max: 100,
step: 1,
field: 'count',
description: 'Number of liars',
configurable: true,
},
])
});
Object.defineProperty(LyingSymbolRule, "SEARCH_VARIANTS", {
enumerable: true,
configurable: true,
writable: true,
value: [
new LyingSymbolRule(1).searchVariant(),
]
});
export default LyingSymbolRule;
export const instance = new LyingSymbolRule(1);