rewrite sim.rs in javascript for tidepool-utils
This commit is contained in:
parent
059c059fdd
commit
2a083b1cf5
|
@ -0,0 +1,143 @@
|
|||
import { Field, Mino } from 'tetris-fumen'
|
||||
import { SplitMix64 } from './prng.js'
|
||||
|
||||
export class Simul {
|
||||
constructor(seed, config) {
|
||||
let rng1 = new SplitMix64(seed);
|
||||
let rng2 = rng1.clone();
|
||||
this.queue = new Queue(rng1, config.rules.previews);
|
||||
this.cheese = new Cheese(rng2, config.goal, config.rules.min, config.rules.max);
|
||||
this.matrix = this.cheese.generate(0, false);
|
||||
this._nextField = Field.create(this.matrix);
|
||||
}
|
||||
|
||||
play(mino) {
|
||||
let page = {
|
||||
field: this._nextField,
|
||||
comment: this.queue.quiz(),
|
||||
operation: mino,
|
||||
};
|
||||
this._nextField = undefined;
|
||||
|
||||
this.queue.remove(mino.type);
|
||||
|
||||
let field = Field.create(this.matrix);
|
||||
field.fill(mino);
|
||||
let matrix1 = field.str(FLATTEN);
|
||||
|
||||
field.clearLine();
|
||||
let matrix2 = field.str(FLATTEN);
|
||||
|
||||
let comboing = matrix1 !== matrix2;
|
||||
let level = getGarbageLevel(matrix2);
|
||||
let garbage = this.cheese.generate(level, comboing);
|
||||
this.matrix = matrix2 + garbage;
|
||||
|
||||
if (garbage !== '') {
|
||||
this._nextField = Field.create(this.matrix);
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
}
|
||||
|
||||
const FLATTEN = { reduced: true, separator: '', garbage: false };
|
||||
|
||||
export class Queue {
|
||||
constructor(rng, previews) {
|
||||
// see `static tidepool::sim::PIECES`
|
||||
this._bag = 'IJLOSTZ'.split('');
|
||||
this._pos = 0;
|
||||
this._rng = rng;
|
||||
this.hold = null;
|
||||
this.next = [];
|
||||
while (this.next.length < previews) {
|
||||
this.next.push(this._pop());
|
||||
}
|
||||
}
|
||||
|
||||
_pop() {
|
||||
// see `static tidepool::sim::Bag::pop()`
|
||||
let i = this._pos;
|
||||
this._pos += 1;
|
||||
this._pos %= this._bag.length;
|
||||
let j = this._rng.genRange(i, this._bag.length);
|
||||
let tmp = this._bag[j];
|
||||
this._bag[j] = this._bag[i];
|
||||
this._bag[i] = tmp;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
quiz() {
|
||||
return `#Q=[${this.hold||''}](${this.next[0]})${this.next.slice(1).join('')}`;
|
||||
}
|
||||
|
||||
remove(ty) {
|
||||
let top = this.next.shift();
|
||||
this.next.push(this._pop());
|
||||
if (this.hold === ty || top !== ty) {
|
||||
if (!this.hold) {
|
||||
this.next.shift();
|
||||
this.next.push(this._pop());
|
||||
}
|
||||
this.hold = top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Cheese {
|
||||
constructor(rng, total, min, max) {
|
||||
this._col = rng.genRange(0, 10);
|
||||
this._rng = rng;
|
||||
this.linesLeft = total;
|
||||
this._level = 0;
|
||||
this._remaining = total;
|
||||
this._min = min;
|
||||
this._max = max;
|
||||
}
|
||||
|
||||
_nextColumn() {
|
||||
// see `static tidepool::sim::Cheese::next()`
|
||||
this._col += this._rng.genRange(1, 10);
|
||||
this._col %= 10;
|
||||
return this._col;
|
||||
}
|
||||
|
||||
generate(level, comboing = false) {
|
||||
let target = comboing ? this._min : this._max;
|
||||
let count = Math.min(this._remaining, Math.max(0, target - level));
|
||||
this._remaining -= count;
|
||||
|
||||
let result = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
let col = this._nextColumn();
|
||||
for (let x = 0; x < 10; x++) {
|
||||
result.push((x === col) ? '_' : 'X');
|
||||
}
|
||||
}
|
||||
return result.join('');
|
||||
}
|
||||
}
|
||||
|
||||
function getGarbageLevel(matrix) {
|
||||
let level = 0;
|
||||
for (let i = 0; i < matrix.length; i++) {
|
||||
let y = Math.floor(i / 10);
|
||||
let cell = matrix[matrix.length - i - 1];
|
||||
if (cell === 'X') {
|
||||
level = y + 1;
|
||||
}
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
if (true) {
|
||||
// see `tidepool::sim::test::test_deterministic()`
|
||||
let sim = new Simul("0x1234567800ABCDEF", {
|
||||
goal: 100,
|
||||
rules: { min: 0, max: 9, previews: 7 },
|
||||
});
|
||||
console.log(sim.queue.next.join(',')); // J,L,T,Z,S,O,I
|
||||
console.log(sim.matrix);
|
||||
// XXX_XXXXXXXXXXX_XXXX_XXXXXXXXXXXX_XXXXXXX_XXXXXXXX_XXXXXXXXXXXXXXXXXX_XXXX_XXXXX_XXXXXXXXX
|
||||
}
|
Loading…
Reference in New Issue