Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // use node.js
- const fs = require("fs");
- const zlib = require("zlib");
- const MapSize = 1024;
- const BlockSize = 64;
- const BlockBytes = BlockSize * BlockSize * 3;
- let MapBlocks = Array(20);
- for(let z=0; z<20; z++){
- MapBlocks[z] = {};
- }
- function GetBlockIndex(x, y){
- return (~~(y / BlockSize) * MapSize) + ~~(x / BlockSize);
- }
- function GetTileIndex(x, y){
- return ((y % BlockSize) * BlockSize) + (x % BlockSize);
- }
- // Reading map data
- let FileBuffer = fs.readFileSync("minimap.map");
- let FileSignature = FileBuffer.readUInt32LE(0);
- if(FileSignature == 0x4D4D544F){
- let Start = FileBuffer.readUInt16LE(4);
- let Version = FileBuffer.readUInt16LE(6);
- let Flags = FileBuffer.readUInt32LE(8);
- if(Version == 1){
- let FilePosition = Start;
- while(true){
- let x = FileBuffer.readUInt16LE(FilePosition + 0);
- let y = FileBuffer.readUInt16LE(FilePosition + 2);
- let z = FileBuffer.readUInt8(FilePosition + 4);
- if(x == 65535 && y == 65535 && z == 255){
- FilePosition = FilePosition + 5;
- break;
- }
- let BlockLength = FileBuffer.readUInt16LE(FilePosition + 5);
- let BlockBuffer = FileBuffer.subarray(FilePosition + 7, FilePosition + 7 + BlockLength);
- let BlockUncompressedBuffer = zlib.unzipSync(BlockBuffer);
- if(BlockUncompressedBuffer.length != BlockBytes){
- return;
- }
- let BlockTiles = [];
- for(let b=0; b<(BlockSize*BlockSize); b++){
- let BlockPosition = b * 3;
- let flags = BlockUncompressedBuffer.readUInt8(BlockPosition + 0);
- let color = BlockUncompressedBuffer.readUInt8(BlockPosition + 1);
- let speed = BlockUncompressedBuffer.readUInt8(BlockPosition + 2);
- BlockTiles.push({"flags": flags, "color": color, "speed": speed});
- }
- MapBlocks[z][GetBlockIndex(x, y)] = BlockTiles;
- FilePosition = FilePosition + 7 + BlockLength;
- }
- }
- }
- // Trying to find map matches that are similar to mask from the book:
- // I generate vectors of colors within patch separately for 1s in mask and 0s in mask and compare using https://en.wikipedia.org/wiki/Cosine_similarity Probably there are better ways to do this.
- let Book_Mask = `00001000
- 01011001
- 00101100
- 01001100
- 00011010
- 01010101`;
- Book_Mask = Book_Mask.replace(/\r?\n|\r/g, "");
- Book_Mask = Book_Mask.split("").map(c => parseInt(c));
- let Book_Mask_w = 8;
- let Book_Mask_h = 6;
- function GetTileRel(x, y, Block, BlockR, BlockB, BlockRB){
- let FromBlock = Block;
- if(x >= BlockSize && y >= BlockSize){
- FromBlock = BlockRB;
- }else if(x >= BlockSize){
- FromBlock = BlockR;
- }else if(y >= BlockSize){
- FromBlock = BlockB;
- }
- if(FromBlock){
- return FromBlock[GetTileIndex(x, y)];
- }
- return null;
- }
- let MinCosineSimilarity = Infinity;
- let MaxCosineSimilarity = -Infinity;
- let Candidates = [];
- for(let z=0; z<16; z++){
- console.log("Floor z =", z);
- for(let i in MapBlocks[z]){
- i = parseInt(i);
- let Bx = (i % MapSize) * BlockSize;
- let By = (~~(i / MapSize)) * BlockSize;
- let Block = MapBlocks[z][i];
- let BlockR = MapBlocks[z][GetBlockIndex(Bx + BlockSize, By)];
- let BlockB = MapBlocks[z][GetBlockIndex(Bx, By + BlockSize)];
- let BlockRB = MapBlocks[z][GetBlockIndex(Bx + BlockSize, By + BlockSize)];
- for(let y=0; y<BlockSize; y++){
- for(let x=0; x<BlockSize; x++){
- let CanCompare = true;
- let ColorsMap = [];
- for(let my=0; my<Book_Mask_h; my++){
- for(let mx=0; mx<Book_Mask_w; mx++){
- let Tile = GetTileRel(x + mx, y + my, Block, BlockR, BlockB, BlockRB);
- if(Tile){
- ColorsMap.push(Tile.color);
- }else{
- CanCompare = false;
- break;
- }
- }
- if(!CanCompare){
- break;
- }
- }
- if(CanCompare){
- let CountsOne = Array(256).fill(0);
- let CountsZero = Array(256).fill(0);
- for(let m=0; m<Book_Mask.length; m++){
- let k = ColorsMap[m];
- if(Book_Mask[m]){
- CountsOne[k]++;
- }else{
- CountsZero[k]++;
- }
- }
- let HadamardProduct = 0;
- let CountsOneSumSquared = 0;
- let CountsZeroSumSquared = 0;
- for(let v=0; v<256; v++){
- HadamardProduct += CountsOne[v] * CountsZero[v];
- CountsOneSumSquared += (CountsOne[v] * CountsOne[v]);
- CountsZeroSumSquared += (CountsZero[v] * CountsZero[v]);
- }
- let CosineSimilarity = HadamardProduct / Math.sqrt(CountsOneSumSquared) / Math.sqrt(CountsZeroSumSquared);
- MinCosineSimilarity = Math.min(MinCosineSimilarity, CosineSimilarity);
- MaxCosineSimilarity = Math.max(MaxCosineSimilarity, CosineSimilarity);
- // Calculated from the center of the rectangle
- let Delta = ((Bx + x + 3.5) + (By + y + 2.5) + z) - 65175;
- let IsCandidate = false;
- if(CosineSimilarity <= 0.5){
- IsCandidate = true;
- }
- if(CosineSimilarity <= 0.7){
- if(Math.abs(Delta) <= 10){
- IsCandidate = true;
- }
- }
- if(IsCandidate){
- let Candidate = {"x": (Bx + x), "y": (By + y), "z": z, "CosineSimilarity": CosineSimilarity, "Delta": Delta};
- Candidates.push(Candidate);
- console.log(Candidate);
- }
- }
- }
- }
- }
- }
- console.log("MinCosineSimilarity", MinCosineSimilarity);
- console.log("MaxCosineSimilarity", MaxCosineSimilarity);
- Candidates.sort(function(a, b){
- return a.CosineSimilarity - b.CosineSimilarity;
- });
- let Output = JSON.stringify(Candidates);
- fs.writeFile("output.txt", Output, "utf8", function(err){
- if(err){
- console.log(err);
- }
- });
- // Get all map points matching formula from the book:
- let MatchingPoints = [];
- for(let z=0; z<16; z++){
- for(let i in MapBlocks[z]){
- i = parseInt(i);
- let Bx = (i % MapSize) * BlockSize;
- let By = (~~(i / MapSize)) * BlockSize;
- for(let y=0; y<BlockSize; y++){
- for(let x=0; x<BlockSize; x++){
- if((Bx + x + By + y + z) == 65175){
- let Block = MapBlocks[z][i];
- let Tile = Block[GetTileIndex(Bx + x, By + y)];
- let color = Tile.color;
- let r = ~~(color / 36) % 6 * 51;
- let g = ~~(color / 6) % 6 * 51;
- let b = color % 6 * 51;
- MatchingPoints.push({"x": (Bx + x), "y": (By + y), "z": z, "color": [r, g, b]});
- }
- }
- }
- }
- }
- console.log("MatchingPoints", MatchingPoints.length);
- let OutputPoints = JSON.stringify(MatchingPoints);
- fs.writeFile("points.txt", OutputPoints, "utf8", function(err){
- if(err){
- console.log(err);
- }
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement