240 lines
6.1 KiB
JavaScript
240 lines
6.1 KiB
JavaScript
const PACK = {
|
|
u8(value) {
|
|
return new Uint8Array([ value & 0xFF ]);
|
|
},
|
|
u16(value) {
|
|
return new Uint8Array([ (value >> 8) & 0xFF, value & 0xFF ]);
|
|
},
|
|
u32(value) {
|
|
return new Uint8Array([
|
|
(value >> 24) & 0xFF,
|
|
(value >> 16) & 0xFF,
|
|
(value >> 8) & 0xFF,
|
|
value & 0xFF
|
|
]);
|
|
},
|
|
base64(bytes) {
|
|
let str = "";
|
|
for(let i = 0; i < bytes.length; ++i) {
|
|
str += String.fromCharCode(bytes[i]);
|
|
}
|
|
return window.btoa(str);
|
|
},
|
|
};
|
|
|
|
const UNPACK = {
|
|
u8(data, index) {
|
|
let result = 0;
|
|
if(index + 1 <= data.length) {
|
|
result = data[index];
|
|
index += 1;
|
|
}
|
|
return { data: result, index: index };
|
|
},
|
|
u16(data, index) {
|
|
let result = 0;
|
|
if(index + 2 <= data.length) {
|
|
result = (data[index] << 8) + data[index + 1];
|
|
index += 2;
|
|
}
|
|
return { data: result, index: index };
|
|
},
|
|
u32(data, index) {
|
|
let result = 0;
|
|
if(index + 4 <= data.length) {
|
|
result = (data[index] << 24)
|
|
+ (data[index + 1] << 16)
|
|
+ (data[index + 2] << 8)
|
|
+ data[index + 3];
|
|
index += 4;
|
|
}
|
|
return { data: result, index: index };
|
|
},
|
|
string(data, index) {
|
|
let result = UNPACK.u16(data, index);
|
|
index = result.index;
|
|
let length = result.data;
|
|
|
|
let dec = new TextDecoder();
|
|
|
|
let result_str = "";
|
|
if(index + length <= data.length) {
|
|
let bytes = new Uint8Array(length);
|
|
for(let i = 0; i < length; ++i) {
|
|
bytes[i] = data[index + i];
|
|
}
|
|
index += length;
|
|
|
|
result_str = dec.decode(bytes);
|
|
} else { console.log("INV DATA LEN"); }
|
|
|
|
return { data: result_str, index: index };
|
|
},
|
|
move(bytes) {
|
|
function piece_by_id(id) {
|
|
switch(id) {
|
|
case 0: return "";
|
|
case 1: return "M";
|
|
case 2: return "N";
|
|
case 3: return "L";
|
|
case 4: return "T";
|
|
case 5: return "C";
|
|
case 6: return "D";
|
|
case 7: return "K";
|
|
}
|
|
}
|
|
|
|
/*
|
|
** From [6]
|
|
** To [6]
|
|
** Piece [3]
|
|
** Take [3]
|
|
**
|
|
*/
|
|
|
|
let from = (bytes[0] & 0xFC) >> 2;
|
|
let to = ((bytes[0] & 0x03) << 4) | ((bytes[1] & 0xC0) >> 6);
|
|
let piece = piece_by_id((bytes[1] & 0x38) >> 3);
|
|
let take = piece_by_id(bytes[1] & 0x07);
|
|
let source = (bytes[2] & 0x80) >> 7;
|
|
switch((bytes[2] & 0x60) >> 5) {
|
|
case 0: state = "";
|
|
case 1: state = "◇"; break;
|
|
case 2: state = "◈"; break;
|
|
case 3: state = "◆"; break;
|
|
}
|
|
|
|
let str = "";
|
|
if(state.length > 0) {
|
|
if(source == 1) {
|
|
str = "" + piece + " " + state + " " + to;
|
|
} else {
|
|
str = "" + from + " " + piece + " " + state + " " + to + " " + take;
|
|
}
|
|
if(take != "") { str += " " + take; }
|
|
}
|
|
return str;
|
|
},
|
|
base64(data) {
|
|
let str = window.atob(data);
|
|
let bytes = new Uint8Array(str.length);
|
|
for(let i = 0; i < bytes.length; ++i) {
|
|
bytes[i] = str.charCodeAt(i);
|
|
}
|
|
return bytes;
|
|
},
|
|
};
|
|
|
|
const BITWISE = {
|
|
lsb(x) {
|
|
// Least significant bit
|
|
return x & -x;
|
|
},
|
|
|
|
ffs(x) {
|
|
// Find first set
|
|
return 31 - Math.clz32(x & -x);
|
|
},
|
|
|
|
count(mask) {
|
|
// source: https://graphics.stanford.edu/~seander/bithacks.html
|
|
mask = mask|0;
|
|
mask = mask - ((mask >> 1) & 0x55555555);
|
|
mask = (mask & 0x33333333) + ((mask >> 2) & 0x33333333);
|
|
return ((mask + (mask >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
|
|
},
|
|
|
|
rotate_blocks(mask)
|
|
{
|
|
const r1 = 0x00003F; // first 6 bits
|
|
const r2 = 0x000FC0; // second 6 bits
|
|
const r3 = 0x03F000; // third 6 bits
|
|
|
|
let v1 = (r1 & mask) << 3;
|
|
let v2 = (r2 & mask) << 3;
|
|
let v3 = (r3 & mask) << 3;
|
|
|
|
v1 = (v1 & r1) | ((v1 & ~r1) >> 6);
|
|
v2 = (v2 & r2) | ((v2 & ~r2) >> 6);
|
|
v3 = (v3 & r3) | ((v3 & ~r3) >> 6);
|
|
|
|
return v1 | v2 | v3;
|
|
},
|
|
};
|
|
|
|
const MATH = {
|
|
Vec2: class {
|
|
constructor(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
add(v) {
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
}
|
|
|
|
mul(v) {
|
|
this.x *= v;
|
|
this.y *= v;
|
|
}
|
|
|
|
copy() {
|
|
return new MATH.Vec2(this.x, this.y);
|
|
}
|
|
},
|
|
|
|
sign(a) {
|
|
return 1 - ((a < 0) << 1);
|
|
},
|
|
|
|
mod(a, b) {
|
|
return ((a % b) + b) % b
|
|
},
|
|
|
|
sign_branch(v) {
|
|
return (v * 2) - 1;
|
|
},
|
|
};
|
|
|
|
const COLOR = {
|
|
rgba(r, g, b, a) {
|
|
let ur = Math.floor(r * 255);
|
|
let ug = Math.floor(r * 255);
|
|
let ub = Math.floor(r * 255);
|
|
let ua = Math.floor(r * 255);
|
|
return "rgba(" + ur + "," + ug + "," + ub + "," + ua + ")";
|
|
},
|
|
}
|
|
|
|
const HEX = {
|
|
hex_to_tile(hex) {
|
|
let a = ((hex.x + 4) * (hex.x + 5) / 2) - 10;
|
|
let b = (hex.x > 4) * ((hex.x - 4) + ((hex.x - 5) * (hex.x - 4)));
|
|
return a - b + hex.y;
|
|
},
|
|
|
|
tile_to_hex(tile) {
|
|
const ROWS = [ 0, 5, 11, 18, 26, 35, 43, 50, 56, 61 ];
|
|
let column = 0;
|
|
while(tile >= ROWS[column + 1]) { column += 1; }
|
|
let row = tile - ROWS[column] + ((column > 4) * (column - 4));
|
|
return new MATH.Vec2(column, row);
|
|
},
|
|
|
|
is_valid(hex) {
|
|
const COLUMNS = [
|
|
new MATH.Vec2(0, 4),
|
|
new MATH.Vec2(0, 5),
|
|
new MATH.Vec2(0, 6),
|
|
new MATH.Vec2(0, 7),
|
|
new MATH.Vec2(0, 8),
|
|
new MATH.Vec2(1, 8),
|
|
new MATH.Vec2(2, 8),
|
|
new MATH.Vec2(3, 8),
|
|
new MATH.Vec2(4, 8),
|
|
];
|
|
return (hex.x >= 0 && hex.x < 9 && hex.y >= COLUMNS[hex.x].x && hex.y <= COLUMNS[hex.x].y);
|
|
},
|
|
};
|