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
|
||||
// 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;
|
||||
|
||||
function srand(seed) {
|
||||
function srandjs(seed) {
|
||||
var m = Math.pow(2, 35) - 31;
|
||||
var a = 185852;
|
||||
var s = seed % m;
|
||||
|
@ -214,10 +364,26 @@ function srand(seed) {
|
|||
};
|
||||
}
|
||||
|
||||
function random(value) {
|
||||
function randomjs(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());
|
||||
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
|
@ -323,6 +489,7 @@ function initCursors() {
|
|||
// helper funcs
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
function set_bkg_tile_xy(x, y, tile) {
|
||||
"RAM";
|
||||
g.drawImage(currentTiles, SCREENOFFSETX + x * TILESIZE, screenOffsetY + y * TILESIZE, {
|
||||
frame: tile
|
||||
});
|
||||
|
@ -337,6 +504,7 @@ function get_bkg_data() {
|
|||
}
|
||||
|
||||
function set_bkg_tiles(x, y, map) {
|
||||
"RAM";
|
||||
g.drawImage(map, SCREENOFFSETX + x, screenOffsetY + y);
|
||||
}
|
||||
|
||||
|
@ -755,6 +923,116 @@ function intro() {
|
|||
// --------------------------------------------------------------------------------------------------
|
||||
// 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) {
|
||||
let tmp = level[aTile + boardSize - 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
|
||||
//as there are 16 tiles per tilegroup (no water, water, special start with water)
|
||||
|
@ -1401,11 +1588,13 @@ function levelSelect() {
|
|||
// printing functions
|
||||
// --------------------------------------------------------------------------------------------------
|
||||
function setCharAt(str, index, chr) {
|
||||
"RAM";
|
||||
if (index > str.length - 1) return str;
|
||||
return str.substring(0, index) + chr + str.substring(index + 1);
|
||||
}
|
||||
|
||||
function formatInteger(valinteger) {
|
||||
"RAM";
|
||||
const maxDigits = 10;
|
||||
let array = " ";
|
||||
|
||||
|
@ -1440,6 +1629,7 @@ function formatInteger(valinteger) {
|
|||
|
||||
//print a number on levelselect or game screen
|
||||
function printNumber(ax, ay, aNumber, maxDigits) {
|
||||
"RAM";
|
||||
const buffSize = 10;
|
||||
|
||||
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
|
||||
function printMessage(ax, ay, amsg) {
|
||||
"RAM";
|
||||
let aCode = 'A'.charCodeAt(0);
|
||||
let zCode = 'Z'.charCodeAt(0);
|
||||
let zeroCode = '0'.charCodeAt(0);
|
||||
|
|
Loading…
Reference in New Issue