mirror of https://github.com/espruino/BangleApps
Add C alternatives for generateLevel and random functions but keep the javascript ones for the emulator + put certain functions always in ram
parent
6d47b4d994
commit
003a307280
|
@ -200,12 +200,162 @@ const TITLE = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
// C Code
|
||||||
|
//
|
||||||
// random stuff
|
// random stuff
|
||||||
// https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript#72732727
|
// https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript#72732727
|
||||||
|
// https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf
|
||||||
|
//
|
||||||
|
// power2 function
|
||||||
|
// https://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//this will give an uncaught exception in emulator
|
||||||
|
//but code will still run fine as i'll run javascript versions then
|
||||||
|
var c = E.compiledC(`
|
||||||
|
//void srand(int)
|
||||||
|
//int random(int)
|
||||||
|
//void generateLevel(int,int,int)
|
||||||
|
|
||||||
|
unsigned int m;
|
||||||
|
unsigned int a;
|
||||||
|
unsigned int s;
|
||||||
|
|
||||||
|
int power2 (int x, unsigned int y)
|
||||||
|
{
|
||||||
|
int temp;
|
||||||
|
if (y == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
temp = power2 (x, y / 2);
|
||||||
|
if ((y % 2) == 0)
|
||||||
|
return temp * temp;
|
||||||
|
else
|
||||||
|
return x * temp * temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srand(int seed)
|
||||||
|
{
|
||||||
|
m = power2(2, 16) - 15;
|
||||||
|
a = 33285;
|
||||||
|
s = seed % m;
|
||||||
|
}
|
||||||
|
|
||||||
|
int random(int value)
|
||||||
|
{
|
||||||
|
s = s * a % m;
|
||||||
|
return s % value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateLevel(unsigned char* level, int boardWidth, int boardHeight ) {
|
||||||
|
int cc = 0;
|
||||||
|
int currentPoint = 0;
|
||||||
|
int visitedRooms = 1;
|
||||||
|
int tmp, tmp2;
|
||||||
|
int selectedNeighbour;
|
||||||
|
int neighboursFound;
|
||||||
|
int lookUpX, lookUpY;
|
||||||
|
int rnd;
|
||||||
|
int neighbours[4];
|
||||||
|
int cellStack[(boardWidth*boardHeight) +1];
|
||||||
|
|
||||||
|
|
||||||
|
//intial all walls value in every room we will remove bits of this value to remove walls
|
||||||
|
for (int i = 0; i < boardWidth*boardHeight; i++)
|
||||||
|
level[i] = 0xf;
|
||||||
|
|
||||||
|
while (visitedRooms != boardWidth * boardHeight) {
|
||||||
|
neighboursFound = 0;
|
||||||
|
lookUpX = currentPoint % boardWidth;
|
||||||
|
lookUpY = (currentPoint / boardWidth) | 0;
|
||||||
|
|
||||||
|
tmp = currentPoint + 1;
|
||||||
|
//tile has neighbour to the right which we did not handle yet
|
||||||
|
if ((lookUpX + 1 < boardWidth) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
tmp = currentPoint - 1;
|
||||||
|
//tile has neighbour to the left which we did not handle yet
|
||||||
|
if ((lookUpX > 0) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
tmp = currentPoint - boardWidth;
|
||||||
|
//tile has neighbour the north which we did not handle yet
|
||||||
|
if ((lookUpY > 0) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
tmp = currentPoint + boardWidth;
|
||||||
|
//tile has neighbour the south which we did not handle yet
|
||||||
|
if ((lookUpY + 1 < boardHeight) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
if (neighboursFound == 0)
|
||||||
|
{
|
||||||
|
currentPoint = cellStack[--cc];
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
rnd = random(neighboursFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedNeighbour = neighbours[rnd];
|
||||||
|
tmp = (selectedNeighbour % boardWidth);
|
||||||
|
//tile has neighbour to the east
|
||||||
|
if (tmp > lookUpX) {
|
||||||
|
//remove west wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(8);
|
||||||
|
//remove east wall tile
|
||||||
|
level[currentPoint] &= ~(2);
|
||||||
|
} else {
|
||||||
|
// tile has neighbour to the west
|
||||||
|
if (tmp < lookUpX) {
|
||||||
|
//remove east wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(2);
|
||||||
|
//remove west wall tile
|
||||||
|
level[currentPoint] &= ~(8);
|
||||||
|
} else {
|
||||||
|
// tile has neighbour to the north
|
||||||
|
tmp2 = selectedNeighbour / boardWidth;
|
||||||
|
if (tmp2 < lookUpY) {
|
||||||
|
//remove south wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(4);
|
||||||
|
//remove north wall tile
|
||||||
|
level[currentPoint] &= ~(1);
|
||||||
|
} else {
|
||||||
|
// tile has neighbour to the south
|
||||||
|
if (tmp2 > lookUpY) {
|
||||||
|
//remove north wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(1);
|
||||||
|
//remove south wall tile
|
||||||
|
level[currentPoint] &= ~(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add tile to the cellstack
|
||||||
|
if (neighboursFound > 1) {
|
||||||
|
cellStack[cc++] = currentPoint;
|
||||||
|
}
|
||||||
|
//set tile to the neighbour
|
||||||
|
currentPoint = selectedNeighbour;
|
||||||
|
visitedRooms++;
|
||||||
|
}
|
||||||
|
}`);
|
||||||
|
|
||||||
|
//when using C Code it will generate levels
|
||||||
|
//a lot faster on the device.
|
||||||
|
//levels generated by the C Code are not the same
|
||||||
|
//as levels generated by the JS Code!
|
||||||
|
const USECCODE = c !== undefined;
|
||||||
|
print("Using C Code:" + USECCODE.toString());
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
// random stuff
|
||||||
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
let randfunc;
|
let randfunc;
|
||||||
|
|
||||||
function srand(seed) {
|
function srandjs(seed) {
|
||||||
var m = Math.pow(2, 35) - 31;
|
var m = Math.pow(2, 35) - 31;
|
||||||
var a = 185852;
|
var a = 185852;
|
||||||
var s = seed % m;
|
var s = seed % m;
|
||||||
|
@ -214,10 +364,26 @@ function srand(seed) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function random(value) {
|
function randomjs(value) {
|
||||||
return Math.floor(randfunc()) % value;
|
return Math.floor(randfunc()) % value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function srand(seed) {
|
||||||
|
"RAM";
|
||||||
|
if(USECCODE)
|
||||||
|
c.srand(seed);
|
||||||
|
else
|
||||||
|
srandjs(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function random(value) {
|
||||||
|
"RAM";
|
||||||
|
if(USECCODE)
|
||||||
|
return c.random(value);
|
||||||
|
else
|
||||||
|
return randomjs(value);
|
||||||
|
}
|
||||||
|
|
||||||
srand(Date().getTime());
|
srand(Date().getTime());
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
@ -323,6 +489,7 @@ function initCursors() {
|
||||||
// helper funcs
|
// helper funcs
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
function set_bkg_tile_xy(x, y, tile) {
|
function set_bkg_tile_xy(x, y, tile) {
|
||||||
|
"RAM";
|
||||||
g.drawImage(currentTiles, SCREENOFFSETX + x * TILESIZE, screenOffsetY + y * TILESIZE, {
|
g.drawImage(currentTiles, SCREENOFFSETX + x * TILESIZE, screenOffsetY + y * TILESIZE, {
|
||||||
frame: tile
|
frame: tile
|
||||||
});
|
});
|
||||||
|
@ -337,6 +504,7 @@ function get_bkg_data() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_bkg_tiles(x, y, map) {
|
function set_bkg_tiles(x, y, map) {
|
||||||
|
"RAM";
|
||||||
g.drawImage(map, SCREENOFFSETX + x, screenOffsetY + y);
|
g.drawImage(map, SCREENOFFSETX + x, screenOffsetY + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,6 +923,116 @@ function intro() {
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
// Level Stuff
|
// Level Stuff
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function generateLeveljs() {
|
||||||
|
let neighbours = new Uint8Array(4);
|
||||||
|
let cellStack = [];//new Uint8Array(boardSize + 1);
|
||||||
|
let cc = 0;
|
||||||
|
let currentPoint = 0;
|
||||||
|
let visitedRooms = 1;
|
||||||
|
let tmp, tmp2;
|
||||||
|
let selectedNeighbour;
|
||||||
|
let neighboursFound;
|
||||||
|
let lookUpX, lookUpY;
|
||||||
|
let rnd;
|
||||||
|
|
||||||
|
//intial all walls value in every room we will remove bits of this value to remove walls
|
||||||
|
level.fill(0xf, 0, boardSize);
|
||||||
|
|
||||||
|
while (visitedRooms != boardSize) {
|
||||||
|
neighboursFound = 0;
|
||||||
|
lookUpX = currentPoint % boardWidth;
|
||||||
|
lookUpY = (currentPoint / boardWidth) | 0;
|
||||||
|
|
||||||
|
tmp = currentPoint + 1;
|
||||||
|
//tile has neighbour to the right which we did not handle yet
|
||||||
|
if ((lookUpX + 1 < boardWidth) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
tmp = currentPoint - 1;
|
||||||
|
//tile has neighbour to the left which we did not handle yet
|
||||||
|
if ((lookUpX > 0) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
tmp = currentPoint - boardWidth;
|
||||||
|
//tile has neighbour the north which we did not handle yet
|
||||||
|
if ((lookUpY > 0) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
tmp = currentPoint + boardWidth;
|
||||||
|
//tile has neighbour the south which we did not handle yet
|
||||||
|
if ((lookUpY + 1 < boardHeight) && (level[tmp] == 0xf))
|
||||||
|
neighbours[neighboursFound++] = tmp;
|
||||||
|
|
||||||
|
if (neighboursFound == 0)
|
||||||
|
{
|
||||||
|
currentPoint = cellStack[--cc];
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
rnd = random(neighboursFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedNeighbour = neighbours[rnd];
|
||||||
|
tmp = (selectedNeighbour % boardWidth);
|
||||||
|
//tile has neighbour to the east
|
||||||
|
if (tmp > lookUpX) {
|
||||||
|
//remove west wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(8);
|
||||||
|
//remove east wall tile
|
||||||
|
level[currentPoint] &= ~(2);
|
||||||
|
} else {
|
||||||
|
// tile has neighbour to the west
|
||||||
|
if (tmp < lookUpX) {
|
||||||
|
//remove east wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(2);
|
||||||
|
//remove west wall tile
|
||||||
|
level[currentPoint] &= ~(8);
|
||||||
|
} else {
|
||||||
|
// tile has neighbour to the north
|
||||||
|
tmp2 = selectedNeighbour / boardWidth;
|
||||||
|
if (tmp2 < lookUpY) {
|
||||||
|
//remove south wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(4);
|
||||||
|
//remove north wall tile
|
||||||
|
level[currentPoint] &= ~(1);
|
||||||
|
} else {
|
||||||
|
// tile has neighbour to the south
|
||||||
|
if (tmp2 > lookUpY) {
|
||||||
|
//remove north wall neighbour
|
||||||
|
level[selectedNeighbour] &= ~(1);
|
||||||
|
//remove south wall tile
|
||||||
|
level[currentPoint] &= ~(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add tile to the cellstack
|
||||||
|
if (neighboursFound > 1) {
|
||||||
|
cellStack[cc++] = currentPoint;
|
||||||
|
}
|
||||||
|
//set tile to the neighbour
|
||||||
|
currentPoint = selectedNeighbour;
|
||||||
|
visitedRooms++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateLevel()
|
||||||
|
{
|
||||||
|
"RAM";
|
||||||
|
if(USECCODE)
|
||||||
|
{
|
||||||
|
var cellstack = new Uint8Array(MAXBOARDSIZE + 1);
|
||||||
|
var neighbours = new Uint8Array(4);
|
||||||
|
var addrLevel = E.getAddressOf(level,true);
|
||||||
|
c.generateLevel(addrLevel, boardWidth, boardHeight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
generateLeveljs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function moveBlockDown(aTile) {
|
function moveBlockDown(aTile) {
|
||||||
let tmp = level[aTile + boardSize - boardWidth];
|
let tmp = level[aTile + boardSize - boardWidth];
|
||||||
for (let i = boardSize - boardWidth; i != 0; i -= boardWidth)
|
for (let i = boardSize - boardWidth; i != 0; i -= boardWidth)
|
||||||
|
@ -1027,98 +1305,7 @@ function updateConnected() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateLevel() {
|
|
||||||
let neighbours = new Uint8Array(4);
|
|
||||||
let cellStack = [];//new Uint8Array(boardSize + 1);
|
|
||||||
let cc = 0;
|
|
||||||
let currentPoint = 0;
|
|
||||||
let visitedRooms = 1;
|
|
||||||
let tmp, tmp2;
|
|
||||||
let selectedNeighbour;
|
|
||||||
let neighboursFound;
|
|
||||||
let lookUpX, lookUpY;
|
|
||||||
let rnd;
|
|
||||||
|
|
||||||
//intial all walls value in every room we will remove bits of this value to remove walls
|
|
||||||
level.fill(0xf, 0, boardSize);
|
|
||||||
|
|
||||||
while (visitedRooms != boardSize) {
|
|
||||||
neighboursFound = 0;
|
|
||||||
lookUpX = currentPoint % boardWidth;
|
|
||||||
lookUpY = (currentPoint / boardWidth) | 0;
|
|
||||||
|
|
||||||
tmp = currentPoint + 1;
|
|
||||||
//tile has neighbour to the right which we did not handle yet
|
|
||||||
if ((lookUpX + 1 < boardWidth) && (level[tmp] == 0xf))
|
|
||||||
neighbours[neighboursFound++] = tmp;
|
|
||||||
|
|
||||||
tmp = currentPoint - 1;
|
|
||||||
//tile has neighbour to the left which we did not handle yet
|
|
||||||
if ((lookUpX > 0) && (level[tmp] == 0xf))
|
|
||||||
neighbours[neighboursFound++] = tmp;
|
|
||||||
|
|
||||||
tmp = currentPoint - boardWidth;
|
|
||||||
//tile has neighbour the north which we did not handle yet
|
|
||||||
if ((lookUpY > 0) && (level[tmp] == 0xf))
|
|
||||||
neighbours[neighboursFound++] = tmp;
|
|
||||||
|
|
||||||
tmp = currentPoint + boardWidth;
|
|
||||||
//tile has neighbour the south which we did not handle yet
|
|
||||||
if ((lookUpY + 1 < boardHeight) && (level[tmp] == 0xf))
|
|
||||||
neighbours[neighboursFound++] = tmp;
|
|
||||||
|
|
||||||
if (neighboursFound == 0)
|
|
||||||
{
|
|
||||||
currentPoint = cellStack[--cc];
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
rnd = random(neighboursFound);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedNeighbour = neighbours[rnd];
|
|
||||||
tmp = (selectedNeighbour % boardWidth);
|
|
||||||
//tile has neighbour to the east
|
|
||||||
if (tmp > lookUpX) {
|
|
||||||
//remove west wall neighbour
|
|
||||||
level[selectedNeighbour] &= ~(8);
|
|
||||||
//remove east wall tile
|
|
||||||
level[currentPoint] &= ~(2);
|
|
||||||
} else {
|
|
||||||
// tile has neighbour to the west
|
|
||||||
if (tmp < lookUpX) {
|
|
||||||
//remove east wall neighbour
|
|
||||||
level[selectedNeighbour] &= ~(2);
|
|
||||||
//remove west wall tile
|
|
||||||
level[currentPoint] &= ~(8);
|
|
||||||
} else {
|
|
||||||
// tile has neighbour to the north
|
|
||||||
tmp2 = selectedNeighbour / boardWidth;
|
|
||||||
if (tmp2 < lookUpY) {
|
|
||||||
//remove south wall neighbour
|
|
||||||
level[selectedNeighbour] &= ~(4);
|
|
||||||
//remove north wall tile
|
|
||||||
level[currentPoint] &= ~(1);
|
|
||||||
} else {
|
|
||||||
// tile has neighbour to the south
|
|
||||||
if (tmp2 > lookUpY) {
|
|
||||||
//remove north wall neighbour
|
|
||||||
level[selectedNeighbour] &= ~(1);
|
|
||||||
//remove south wall tile
|
|
||||||
level[currentPoint] &= ~(4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//add tile to the cellstack
|
|
||||||
if (neighboursFound > 1) {
|
|
||||||
cellStack[cc++] = currentPoint;
|
|
||||||
}
|
|
||||||
//set tile to the neighbour
|
|
||||||
currentPoint = selectedNeighbour;
|
|
||||||
visitedRooms++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//when all board tiles are not below 16, the level is cleared
|
//when all board tiles are not below 16, the level is cleared
|
||||||
//as there are 16 tiles per tilegroup (no water, water, special start with water)
|
//as there are 16 tiles per tilegroup (no water, water, special start with water)
|
||||||
|
@ -1401,11 +1588,13 @@ function levelSelect() {
|
||||||
// printing functions
|
// printing functions
|
||||||
// --------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------
|
||||||
function setCharAt(str, index, chr) {
|
function setCharAt(str, index, chr) {
|
||||||
|
"RAM";
|
||||||
if (index > str.length - 1) return str;
|
if (index > str.length - 1) return str;
|
||||||
return str.substring(0, index) + chr + str.substring(index + 1);
|
return str.substring(0, index) + chr + str.substring(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatInteger(valinteger) {
|
function formatInteger(valinteger) {
|
||||||
|
"RAM";
|
||||||
const maxDigits = 10;
|
const maxDigits = 10;
|
||||||
let array = " ";
|
let array = " ";
|
||||||
|
|
||||||
|
@ -1440,6 +1629,7 @@ function formatInteger(valinteger) {
|
||||||
|
|
||||||
//print a number on levelselect or game screen
|
//print a number on levelselect or game screen
|
||||||
function printNumber(ax, ay, aNumber, maxDigits) {
|
function printNumber(ax, ay, aNumber, maxDigits) {
|
||||||
|
"RAM";
|
||||||
const buffSize = 10;
|
const buffSize = 10;
|
||||||
|
|
||||||
let ret = formatInteger(aNumber);
|
let ret = formatInteger(aNumber);
|
||||||
|
@ -1455,6 +1645,7 @@ function printNumber(ax, ay, aNumber, maxDigits) {
|
||||||
|
|
||||||
//print a message on the title screen on ax,ay, the tileset from titlescreen contains an alphabet
|
//print a message on the title screen on ax,ay, the tileset from titlescreen contains an alphabet
|
||||||
function printMessage(ax, ay, amsg) {
|
function printMessage(ax, ay, amsg) {
|
||||||
|
"RAM";
|
||||||
let aCode = 'A'.charCodeAt(0);
|
let aCode = 'A'.charCodeAt(0);
|
||||||
let zCode = 'Z'.charCodeAt(0);
|
let zCode = 'Z'.charCodeAt(0);
|
||||||
let zeroCode = '0'.charCodeAt(0);
|
let zeroCode = '0'.charCodeAt(0);
|
||||||
|
|
Loading…
Reference in New Issue