633 lines
23 KiB
TypeScript
633 lines
23 KiB
TypeScript
import { GetCurrentTerminal } from '../app'
|
|
import type { Item } from '../fs/Item'
|
|
import type { SimpleStream } from '../utils/SimpleStream'
|
|
import { Program } from './Program'
|
|
|
|
type SmokeState = {
|
|
y: number
|
|
x: number
|
|
ptrn: number
|
|
kind: number
|
|
}
|
|
|
|
type SlOptions = {
|
|
accident: boolean
|
|
fly: boolean
|
|
logo: boolean
|
|
c51: boolean
|
|
}
|
|
|
|
export class Sl extends Program {
|
|
private static readonly D51_HEIGHT = 10
|
|
private static readonly D51_FUNNEL = 7
|
|
private static readonly D51_LENGTH = 83
|
|
private static readonly D51_PATTERNS = 6
|
|
|
|
private static readonly LOGO_HEIGHT = 6
|
|
private static readonly LOGO_FUNNEL = 4
|
|
private static readonly LOGO_LENGTH = 84
|
|
private static readonly LOGO_PATTERNS = 6
|
|
|
|
private static readonly C51_HEIGHT = 11
|
|
private static readonly C51_FUNNEL = 7
|
|
private static readonly C51_LENGTH = 87
|
|
private static readonly C51_PATTERNS = 6
|
|
|
|
private static readonly SMOKE_PATTERNS = 16
|
|
private static readonly MAX_SMOKE = 1000
|
|
|
|
private smokes: SmokeState[] = []
|
|
private smokeSum = 0
|
|
|
|
public async Exec(
|
|
_: SimpleStream<string>,
|
|
stdout: SimpleStream<string>,
|
|
__: Item,
|
|
args: string[],
|
|
): Promise<number> {
|
|
const options = this.parseOptions(args)
|
|
const terminal = GetCurrentTerminal()
|
|
const cols = Math.max(1, Math.floor(terminal.GetWidthCells()))
|
|
const lines = Math.max(1, Math.floor(terminal.GetHeightCells()))
|
|
|
|
this.resetSmoke()
|
|
|
|
// Clear screen and move cursor home (ANSI CSI)
|
|
stdout.emit('\x1b[2J\x1b[H')
|
|
|
|
for (let x = cols - 1; ; --x) {
|
|
const ok = options.logo
|
|
? this.addSl(x, stdout, cols, lines, options)
|
|
: options.c51
|
|
? this.addC51(x, stdout, cols, lines, options)
|
|
: this.addD51(x, stdout, cols, lines, options)
|
|
|
|
if (!ok)
|
|
break
|
|
|
|
await this.sleep(40)
|
|
}
|
|
|
|
stdout.emit(`\x1b[${Math.max(1, lines)};1H\n`)
|
|
return 0
|
|
}
|
|
|
|
private parseOptions(args: string[]): SlOptions {
|
|
const options: SlOptions = {
|
|
accident: false,
|
|
fly: false,
|
|
logo: false,
|
|
c51: false,
|
|
}
|
|
|
|
for (const arg of args.slice(1)) {
|
|
if (!arg.startsWith('-'))
|
|
continue
|
|
|
|
for (const flag of arg.slice(1)) {
|
|
switch (flag) {
|
|
case 'a':
|
|
options.accident = true
|
|
break
|
|
case 'F':
|
|
options.fly = true
|
|
break
|
|
case 'l':
|
|
options.logo = true
|
|
break
|
|
case 'c':
|
|
options.c51 = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return options
|
|
}
|
|
|
|
private addSl(
|
|
x: number,
|
|
stdout: SimpleStream<string>,
|
|
cols: number,
|
|
lines: number,
|
|
options: SlOptions,
|
|
): boolean {
|
|
if (x < -Sl.LOGO_LENGTH)
|
|
return false
|
|
|
|
let y = Math.max(0, Math.floor(lines / 2) - 3)
|
|
let py1 = 0
|
|
let py2 = 0
|
|
let py3 = 0
|
|
|
|
if (options.fly) {
|
|
y = Math.trunc(x / 6) + lines - Math.trunc(cols / 6) - Sl.LOGO_HEIGHT
|
|
py1 = 2
|
|
py2 = 4
|
|
py3 = 6
|
|
}
|
|
|
|
const pattern = Math.floor((Sl.LOGO_LENGTH + x) / 3) % Sl.LOGO_PATTERNS
|
|
|
|
for (let i = 0; i <= Sl.LOGO_HEIGHT; i++) {
|
|
this.drawString(stdout, cols, lines, y + i, x, Sl.LOGO[pattern][i])
|
|
this.drawString(stdout, cols, lines, y + i + py1, x + 21, Sl.LOGO_COAL[i])
|
|
this.drawString(stdout, cols, lines, y + i + py2, x + 42, Sl.LOGO_CAR[i])
|
|
this.drawString(stdout, cols, lines, y + i + py3, x + 63, Sl.LOGO_CAR[i])
|
|
}
|
|
|
|
if (options.accident) {
|
|
this.addMan(stdout, cols, lines, y + 1, x + 14)
|
|
this.addMan(stdout, cols, lines, y + 1 + py2, x + 45)
|
|
this.addMan(stdout, cols, lines, y + 1 + py2, x + 53)
|
|
this.addMan(stdout, cols, lines, y + 1 + py3, x + 66)
|
|
this.addMan(stdout, cols, lines, y + 1 + py3, x + 74)
|
|
}
|
|
|
|
this.addSmoke(stdout, cols, lines, y - 1, x + Sl.LOGO_FUNNEL)
|
|
return true
|
|
}
|
|
|
|
private addD51(
|
|
x: number,
|
|
stdout: SimpleStream<string>,
|
|
cols: number,
|
|
lines: number,
|
|
options: SlOptions,
|
|
): boolean {
|
|
if (x < -Sl.D51_LENGTH)
|
|
return false
|
|
|
|
let y = Math.max(0, Math.floor(lines / 2) - 5)
|
|
let dy = 0
|
|
|
|
if (options.fly) {
|
|
y = Math.trunc(x / 7) + lines - Math.trunc(cols / 7) - Sl.D51_HEIGHT
|
|
dy = 1
|
|
}
|
|
|
|
const pattern = (Sl.D51_LENGTH + x) % Sl.D51_PATTERNS
|
|
|
|
for (let i = 0; i <= Sl.D51_HEIGHT; i++) {
|
|
this.drawString(stdout, cols, lines, y + i, x, Sl.D51[pattern][i])
|
|
this.drawString(stdout, cols, lines, y + i + dy, x + 53, Sl.D51_COAL[i])
|
|
}
|
|
|
|
if (options.accident) {
|
|
this.addMan(stdout, cols, lines, y + 2, x + 43)
|
|
this.addMan(stdout, cols, lines, y + 2, x + 47)
|
|
}
|
|
|
|
this.addSmoke(stdout, cols, lines, y - 1, x + Sl.D51_FUNNEL)
|
|
return true
|
|
}
|
|
|
|
private addC51(
|
|
x: number,
|
|
stdout: SimpleStream<string>,
|
|
cols: number,
|
|
lines: number,
|
|
options: SlOptions,
|
|
): boolean {
|
|
if (x < -Sl.C51_LENGTH)
|
|
return false
|
|
|
|
let y = Math.max(0, Math.floor(lines / 2) - 5)
|
|
let dy = 0
|
|
|
|
if (options.fly) {
|
|
y = Math.trunc(x / 7) + lines - Math.trunc(cols / 7) - Sl.C51_HEIGHT
|
|
dy = 1
|
|
}
|
|
|
|
const pattern = (Sl.C51_LENGTH + x) % Sl.C51_PATTERNS
|
|
|
|
for (let i = 0; i <= Sl.C51_HEIGHT; i++) {
|
|
this.drawString(stdout, cols, lines, y + i, x, Sl.C51[pattern][i])
|
|
this.drawString(stdout, cols, lines, y + i + dy, x + 55, Sl.C51_COAL[i])
|
|
}
|
|
|
|
if (options.accident) {
|
|
this.addMan(stdout, cols, lines, y + 3, x + 45)
|
|
this.addMan(stdout, cols, lines, y + 3, x + 49)
|
|
}
|
|
|
|
this.addSmoke(stdout, cols, lines, y - 1, x + Sl.C51_FUNNEL)
|
|
return true
|
|
}
|
|
|
|
private addMan(
|
|
stdout: SimpleStream<string>,
|
|
cols: number,
|
|
lines: number,
|
|
y: number,
|
|
x: number,
|
|
) {
|
|
const man = [['', '(O)'], ['Help!', '\\O/']]
|
|
const index = Math.floor((Sl.LOGO_LENGTH + x) / 12) % 2
|
|
|
|
for (let i = 0; i < 2; i++)
|
|
this.drawString(stdout, cols, lines, y + i, x, man[index][i])
|
|
}
|
|
|
|
private addSmoke(
|
|
stdout: SimpleStream<string>,
|
|
cols: number,
|
|
lines: number,
|
|
y: number,
|
|
x: number,
|
|
) {
|
|
if (x % 4 !== 0)
|
|
return
|
|
|
|
for (let i = 0; i < this.smokeSum; i++) {
|
|
const smoke = this.smokes[i]
|
|
|
|
this.drawString(stdout, cols, lines, smoke.y, smoke.x, Sl.SMOKE_ERASER[smoke.ptrn])
|
|
smoke.y -= Sl.SMOKE_DY[smoke.ptrn]
|
|
smoke.x += Sl.SMOKE_DX[smoke.ptrn]
|
|
smoke.ptrn = smoke.ptrn < Sl.SMOKE_PATTERNS - 1 ? smoke.ptrn + 1 : smoke.ptrn
|
|
this.drawString(stdout, cols, lines, smoke.y, smoke.x, Sl.SMOKE[smoke.kind][smoke.ptrn])
|
|
}
|
|
|
|
this.drawString(stdout, cols, lines, y, x, Sl.SMOKE[this.smokeSum % 2][0])
|
|
|
|
if (this.smokeSum < Sl.MAX_SMOKE) {
|
|
this.smokes[this.smokeSum] = { y, x, ptrn: 0, kind: this.smokeSum % 2 }
|
|
this.smokeSum++
|
|
}
|
|
}
|
|
|
|
private drawString(
|
|
stdout: SimpleStream<string>,
|
|
cols: number,
|
|
lines: number,
|
|
y: number,
|
|
x: number,
|
|
text: string,
|
|
) {
|
|
if (y < 0 || y >= lines)
|
|
return
|
|
|
|
let cursorX = x
|
|
let out = text
|
|
|
|
if (cursorX < 0) {
|
|
out = out.slice(-cursorX)
|
|
cursorX = 0
|
|
}
|
|
|
|
if (cursorX >= cols || out.length === 0)
|
|
return
|
|
|
|
if (cursorX + out.length > cols)
|
|
out = out.slice(0, cols - cursorX)
|
|
|
|
stdout.emit(`\x1b[${y + 1};${cursorX + 1}H${out}`)
|
|
}
|
|
|
|
private resetSmoke() {
|
|
this.smokes = []
|
|
this.smokeSum = 0
|
|
}
|
|
|
|
private sleep(ms: number): Promise<void> {
|
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
}
|
|
|
|
private static readonly LOGO: string[][] = [
|
|
[
|
|
' ++ +------ ',
|
|
' || |+-+ | ',
|
|
' /---------|| | | ',
|
|
' + ======== +-+ | ',
|
|
' _|--O========O~\\-+ ',
|
|
'//// \\_/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ++ +------ ',
|
|
' || |+-+ | ',
|
|
' /---------|| | | ',
|
|
' + ======== +-+ | ',
|
|
' _|--/O========O\\-+ ',
|
|
'//// \\_/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ++ +------ ',
|
|
' || |+-+ | ',
|
|
' /---------|| | | ',
|
|
' + ======== +-+ | ',
|
|
' _|--/~O========O-+ ',
|
|
'//// \\_/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ++ +------ ',
|
|
' || |+-+ | ',
|
|
' /---------|| | | ',
|
|
' + ======== +-+ | ',
|
|
' _|--/~\\------/~\\-+ ',
|
|
'//// \\_O========O ',
|
|
' ',
|
|
],
|
|
[
|
|
' ++ +------ ',
|
|
' || |+-+ | ',
|
|
' /---------|| | | ',
|
|
' + ======== +-+ | ',
|
|
' _|--/~\\------/~\\-+ ',
|
|
'//// \\O========O/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ++ +------ ',
|
|
' || |+-+ | ',
|
|
' /---------|| | | ',
|
|
' + ======== +-+ | ',
|
|
' _|--/~\\------/~\\-+ ',
|
|
'//// O========O_/ ',
|
|
' ',
|
|
],
|
|
]
|
|
|
|
private static readonly LOGO_COAL = [
|
|
'____ ',
|
|
'| \\@@@@@@@@@@@ ',
|
|
'| \\@@@@@@@@@@@@@_ ',
|
|
'| | ',
|
|
'|__________________| ',
|
|
' (O) (O) ',
|
|
' ',
|
|
]
|
|
|
|
private static readonly LOGO_CAR = [
|
|
'____________________ ',
|
|
'| ___ ___ ___ ___ | ',
|
|
'| |_| |_| |_| |_| | ',
|
|
'|__________________| ',
|
|
'|__________________| ',
|
|
' (O) (O) ',
|
|
' ',
|
|
]
|
|
|
|
private static readonly D51 = [
|
|
[
|
|
' ==== ________ ___________ ',
|
|
' _D _| |_______/ \\__I_I_____===__|_________| ',
|
|
' |(_)--- | H\\________/ | | =|___ ___| ',
|
|
' / | | H | | | | ||_| |_|| ',
|
|
' | | | H |__--------------------| [___] | ',
|
|
' | ________|___H__/__|_____/[][]~\\_______| | ',
|
|
' |/ | |-----------I_____I [][] [] D |=======|__ ',
|
|
'__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ',
|
|
' |/-=|___|= || || || |_____/~\\___/ ',
|
|
' \\_/ \\O=====O=====O=====O_/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ==== ________ ___________ ',
|
|
' _D _| |_______/ \\__I_I_____===__|_________| ',
|
|
' |(_)--- | H\\________/ | | =|___ ___| ',
|
|
' / | | H | | | | ||_| |_|| ',
|
|
' | | | H |__--------------------| [___] | ',
|
|
' | ________|___H__/__|_____/[][]~\\_______| | ',
|
|
' |/ | |-----------I_____I [][] [] D |=======|__ ',
|
|
'__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ',
|
|
' |/-=|___|=O=====O=====O=====O |_____/~\\___/ ',
|
|
' \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ==== ________ ___________ ',
|
|
' _D _| |_______/ \\__I_I_____===__|_________| ',
|
|
' |(_)--- | H\\________/ | | =|___ ___| ',
|
|
' / | | H | | | | ||_| |_|| ',
|
|
' | | | H |__--------------------| [___] | ',
|
|
' | ________|___H__/__|_____/[][]~\\_______| | ',
|
|
' |/ | |-----------I_____I [][] [] D |=======|__ ',
|
|
'__/ =| o |=-O=====O=====O=====O \\ ____Y___________|__ ',
|
|
' |/-=|___|= || || || |_____/~\\___/ ',
|
|
' \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ==== ________ ___________ ',
|
|
' _D _| |_______/ \\__I_I_____===__|_________| ',
|
|
' |(_)--- | H\\________/ | | =|___ ___| ',
|
|
' / | | H | | | | ||_| |_|| ',
|
|
' | | | H |__--------------------| [___] | ',
|
|
' | ________|___H__/__|_____/[][]~\\_______| | ',
|
|
' |/ | |-----------I_____I [][] [] D |=======|__ ',
|
|
'__/ =| o |=-~O=====O=====O=====O\\ ____Y___________|__ ',
|
|
' |/-=|___|= || || || |_____/~\\___/ ',
|
|
' \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ==== ________ ___________ ',
|
|
' _D _| |_______/ \\__I_I_____===__|_________| ',
|
|
' |(_)--- | H\\________/ | | =|___ ___| ',
|
|
' / | | H | | | | ||_| |_|| ',
|
|
' | | | H |__--------------------| [___] | ',
|
|
' | ________|___H__/__|_____/[][]~\\_______| | ',
|
|
' |/ | |-----------I_____I [][] [] D |=======|__ ',
|
|
'__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ',
|
|
' |/-=|___|= O=====O=====O=====O|_____/~\\___/ ',
|
|
' \\_/ \\__/ \\__/ \\__/ \\__/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ==== ________ ___________ ',
|
|
' _D _| |_______/ \\__I_I_____===__|_________| ',
|
|
' |(_)--- | H\\________/ | | =|___ ___| ',
|
|
' / | | H | | | | ||_| |_|| ',
|
|
' | | | H |__--------------------| [___] | ',
|
|
' | ________|___H__/__|_____/[][]~\\_______| | ',
|
|
' |/ | |-----------I_____I [][] [] D |=======|__ ',
|
|
'__/ =| o |=-~~\\ /~~\\ /~~\\ /~~\\ ____Y___________|__ ',
|
|
' |/-=|___|= || || || |_____/~\\___/ ',
|
|
' \\_/ \\_O=====O=====O=====O/ \\_/ ',
|
|
' ',
|
|
],
|
|
]
|
|
|
|
private static readonly D51_COAL = [
|
|
' ',
|
|
' ',
|
|
' _________________ ',
|
|
' _| \\_____A ',
|
|
' =| | ',
|
|
' -| | ',
|
|
'__|________________________|_ ',
|
|
'|__________________________|_ ',
|
|
' |_D__D__D_| |_D__D__D_| ',
|
|
' \\_/ \\_/ \\_/ \\_/ ',
|
|
' ',
|
|
]
|
|
|
|
private static readonly C51 = [
|
|
[
|
|
' ___ ',
|
|
' _|_|_ _ __ __ ___________',
|
|
' D__/ \\_(_)___| |__H__| |_____I_Ii_()|_________|',
|
|
' | `---\' |:: `--\' H `--\' | |___ ___| ',
|
|
' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ',
|
|
' || | :: H +=====+ | |:: ...| ',
|
|
'| | _______|_::-----------------[][]-----| | ',
|
|
'| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__',
|
|
'------\'|oOo|=[]=- || || | ||=======_|__',
|
|
'/~\\____|___|/~\\_| O=======O=======O |__|+-/~\\_| ',
|
|
'\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ___ ',
|
|
' _|_|_ _ __ __ ___________',
|
|
' D__/ \\_(_)___| |__H__| |_____I_Ii_()|_________|',
|
|
' | `---\' |:: `--\' H `--\' | |___ ___| ',
|
|
' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ',
|
|
' || | :: H +=====+ | |:: ...| ',
|
|
'| | _______|_::-----------------[][]-----| | ',
|
|
'| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__',
|
|
'------\'|oOo|=[]=- O=======O=======O | ||=======_|__',
|
|
'/~\\____|___|/~\\_| || || |__|+-/~\\_| ',
|
|
'\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ___ ',
|
|
' _|_|_ _ __ __ ___________',
|
|
' D__/ \\_(_)___| |__H__| |_____I_Ii_()|_________|',
|
|
' | `---\' |:: `--\' H `--\' | |___ ___| ',
|
|
' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ',
|
|
' || | :: H +=====+ | |:: ...| ',
|
|
'| | _______|_::-----------------[][]-----| | ',
|
|
'| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__',
|
|
'------\'|oOo|==[]=- O=======O=======O | ||=======_|__',
|
|
'/~\\____|___|/~\\_| || || |__|+-/~\\_| ',
|
|
'\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ___ ',
|
|
' _|_|_ _ __ __ ___________',
|
|
' D__/ \\_(_)___| |__H__| |_____I_Ii_()|_________|',
|
|
' | `---\' |:: `--\' H `--\' | |___ ___| ',
|
|
' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ',
|
|
' || | :: H +=====+ | |:: ...| ',
|
|
'| | _______|_::-----------------[][]-----| | ',
|
|
'| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__',
|
|
'------\'|oOo|===[]=- O=======O=======O | ||=======_|__',
|
|
'/~\\____|___|/~\\_| || || |__|+-/~\\_| ',
|
|
'\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ___ ',
|
|
' _|_|_ _ __ __ ___________',
|
|
' D__/ \\_(_)___| |__H__| |_____I_Ii_()|_________|',
|
|
' | `---\' |:: `--\' H `--\' | |___ ___| ',
|
|
' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ',
|
|
' || | :: H +=====+ | |:: ...| ',
|
|
'| | _______|_::-----------------[][]-----| | ',
|
|
'| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__',
|
|
'------\'|oOo|===[]=- || || | ||=======_|__',
|
|
'/~\\____|___|/~\\_| O=======O=======O |__|+-/~\\_| ',
|
|
'\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ ',
|
|
' ',
|
|
],
|
|
[
|
|
' ___ ',
|
|
' _|_|_ _ __ __ ___________',
|
|
' D__/ \\_(_)___| |__H__| |_____I_Ii_()|_________|',
|
|
' | `---\' |:: `--\' H `--\' | |___ ___| ',
|
|
' +|~~~~~~~~++::~~~~~~~H~~+=====+~~~~~~|~~||_| |_|| ',
|
|
' || | :: H +=====+ | |:: ...| ',
|
|
'| | _______|_::-----------------[][]-----| | ',
|
|
'| /~~ || |-----/~~~~\\ /[I_____I][][] --|||_______|__',
|
|
'------\'|oOo|==[]=- || || | ||=======_|__',
|
|
'/~\\____|___|/~\\_| O=======O=======O |__|+-/~\\_| ',
|
|
'\\_/ \\_/ \\____/ \\____/ \\____/ \\_/ ',
|
|
' ',
|
|
],
|
|
]
|
|
|
|
private static readonly C51_COAL = [
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' _________________ ',
|
|
' _| \\_____A ',
|
|
' =| | ',
|
|
' -| | ',
|
|
'__|________________________|_ ',
|
|
'|__________________________|_ ',
|
|
' |_D__D__D_| |_D__D__D_| ',
|
|
' \\_/ \\_/ \\_/ \\_/ ',
|
|
' ',
|
|
]
|
|
|
|
private static readonly SMOKE = [
|
|
[
|
|
'( )',
|
|
'( )',
|
|
'( )',
|
|
'( )',
|
|
'( )',
|
|
'( )',
|
|
'( )',
|
|
'( )',
|
|
'()',
|
|
'()',
|
|
'O',
|
|
'O',
|
|
'O',
|
|
'O',
|
|
'O',
|
|
' ',
|
|
],
|
|
[
|
|
'(@@@)',
|
|
'(@@@@)',
|
|
'(@@@@)',
|
|
'(@@@)',
|
|
'(@@)',
|
|
'(@@)',
|
|
'(@)',
|
|
'(@)',
|
|
'@@',
|
|
'@@',
|
|
'@',
|
|
'@',
|
|
'@',
|
|
'@',
|
|
'@',
|
|
' ',
|
|
],
|
|
]
|
|
|
|
private static readonly SMOKE_ERASER = [
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
' ',
|
|
]
|
|
|
|
private static readonly SMOKE_DY = [2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
private static readonly SMOKE_DX = [-2, -1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3]
|
|
}
|