DefinitelyTyped/types/rot-js/rot-js-tests.ts
Andy 239dc996ad
rot-js: Fix lint (#29103)
* rot-js: Fix lint

* Improve type
2018-09-24 09:13:57 -07:00

1152 lines
29 KiB
TypeScript

import * as ROT from 'rot-js';
// All the documentation uses a function called `SHOW` to do results; stubbing it out here
// so that I can copy/paste directly.
function SHOW(...something: any[]): any {
console.log(something);
}
let w = 80;
let h = 40;
let display: ROT.Display;
// Introduction / Browser Support
SHOW(
ROT.isSupported()
);
// JS Enhancements / Array
SHOW(
["apples", "oranges", "zombies"].random(),
["apples", "oranges", "zombies"].randomize()
);
// JS Enhancements / String
SHOW(
"hello world".capitalize(),
"hello %s, this is %s".format("world", "sparta"),
"7".lpad("0", 3),
"123".rpad(".", 6)
);
// JS Enhancements / Number
SHOW(
(15) % 7,
(-15) % 7,
(15).mod(7),
(-15).mod(7)
);
// JS Enhancements / (Object | Function) not included, as TS does that for us
// JS Enhancements / String formatting
SHOW(
String.format("%s %s", "hello", "world"),
"%s %s".format("hello", "world")
);
// ----
const myObj = {
foo() { return "bar"; }
};
String.format.map['f'] = "foo";
SHOW("%f".format(myObj));
// ----
class Item {
constructor(private readonly name: string) { }
a() {
const first = self.name.charAt(0);
return `${first.match(/[aeiouy]/i) ? "an" : "a"} ${this.name}`;
}
the() {
return `the ${this.name}`;
}
}
String.format.map['a'] = "a";
String.format.map['the'] = "the";
const apple = new Item("apple");
const banana = new Item("banana");
let template = "You eat %a. %The was delicious.";
SHOW(template.format(apple, apple));
SHOW(template.format(banana, banana));
// ----
class Animal {
constructor(private readonly name: string) { }
adjective(x: string) {
return `${x} ${this.name}`;
}
}
String.format.map['adjective'] = "adjective";
const cat = new Animal("cat");
template = "You see a %{adjective,black}.";
SHOW(template.format(cat));
// Keyboard Handling not included, as nothing ROT specific in there
// RNG / Generating random values
SHOW(
ROT.RNG.getUniform(),
ROT.RNG.getNormal(0, 10),
ROT.RNG.getPercentage()
);
// ----
const canvas = document.createElement("canvas");
canvas.width = 500;
canvas.height = 200;
SHOW(canvas);
const ctx = canvas.getContext("2d");
ctx!.fillStyle = "#fff";
ctx!.fillRect(0, 0, canvas.width, canvas.height);
ctx!.fillStyle = "#f00";
const data = new Array<any>();
for (let i = 0; i < 40000; i++) { /* generate histogram */
const num = Math.round(ROT.RNG.getNormal(250, 100));
data[num] = (data[num] || 0) + 1;
}
for (let i = 0; i < data.length; i++) { /* plot histogram */
ctx!.fillRect(i, canvas.height - data[i], 1, data[i]);
}
// RNG / Working with RNG state
const state = ROT.RNG.getState();
SHOW(ROT.RNG.getUniform());
ROT.RNG.setState(state);
SHOW(ROT.RNG.getUniform());
// ----
const seed = ROT.RNG.getSeed();
ROT.RNG.setSeed(12345);
SHOW(
ROT.RNG.getUniform(),
ROT.RNG.getUniform()
);
ROT.RNG.setSeed(12345);
SHOW(
ROT.RNG.getUniform(),
ROT.RNG.getUniform()
);
// RNG / Cloning a RNG
const clone = ROT.RNG.clone();
SHOW(ROT.RNG.getUniform());
SHOW(clone.getUniform());
ROT.RNG.setSeed(123);
SHOW(ROT.RNG.getUniform());
SHOW(clone.getUniform());
clone.getWeightedValue({} as any); // $ExpectType string
clone.getWeightedValue({ a: 1, b: 2 }); // $ExpectType "a" | "b"
// RNG / Picking a weighted value
const monsters = {
orc: 3,
ogre: 1,
rat: 5
};
for (let i = 0; i < 20; i++) {
SHOW(ROT.RNG.getWeightedValue(monsters));
}
// Console Display / Creating a display
display = new ROT.Display({ width: 20, height: 5 });
SHOW(display.getContainer()); /* do not forget to append to page! */
// Console Display / Configuring the display
display = new ROT.Display({ width: 20, height: 5 });
SHOW(display.getContainer());
display.setOptions({
width: 30,
fontSize: 8,
fontStyle: "bold",
bg: "#a00"
});
// Console Display / Drawing individual characters
display = new ROT.Display({ width: 40, height: 9 });
SHOW(display.getContainer());
display.draw(5, 4, "@");
display.draw(15, 4, "%", "#0f0"); /* foreground color */
display.draw(25, 4, "#", "#f00", "#009"); /* and background color */
// Console Display / Drawing strings
display = new ROT.Display({ width: 40, height: 20 });
SHOW(display.getContainer());
display.drawText(5, 2, "Hello world");
/* last argument specifies maximum length */
display.drawText(20, 5, "This line of text is very long.", 16);
/* lines are broken at word boundaries; lines are trimmed */
const words = ["lorem", "ipsum", "dolor", "sit", "amet"];
const long: string[] = [];
for (let i = 0; i < 30; i++) { long.push(words.random()); }
const longer = long.join(" ");
display.drawText(1, 10, longer, 38);
// Console Display / Specifying foreground/background color in strings
display = new ROT.Display({ width: 40, height: 5 });
SHOW(display.getContainer());
let str = "Goodbye %c{red}cr%b{blue}u%b{}el %c{}world";
display.drawText(5, 2, str);
// Console Display / Forced square aspect ratio
let options: ROT.DisplayOptions = {
width: 20,
height: 8,
fontSize: 18,
forceSquareRatio: true
};
display = new ROT.Display(options);
SHOW(display.getContainer());
str = "Using a regular grid\n@....%b{blue}#%b{}##.%b{red}.%b{}.$$$";
display.drawText(2, 2, str);
// Console display / graphical tiles
let tileSet = document.createElement("img");
tileSet.src = "tiles.png";
options = {
layout: "tile",
bg: "transparent",
tileWidth: 64,
tileHeight: 64,
tileSet,
tileMap: {
"@": [0, 0],
"#": [0, 64],
a: [64, 0],
"!": [64, 64]
},
width: 3,
height: 3
};
display = new ROT.Display(options);
SHOW(display.getContainer());
tileSet.onload = () => {
display.draw(1, 1, "@");
display.draw(0, 0, "#");
display.draw(0, 1, "#");
display.draw(1, 0, "#");
display.draw(0, 2, "#");
display.draw(2, 2, "a");
display.draw(2, 0, "!");
display.draw(2, 1, "!");
};
// Console display / graphical tiles / Multiple tiles at one place
tileSet = document.createElement("img");
tileSet.src = "tiles.png";
options = {
layout: "tile",
bg: "transparent",
tileWidth: 64,
tileHeight: 64,
tileSet,
tileMap: {
"@": [0, 0],
"#": [0, 64]
},
width: 1,
height: 1
};
display = new ROT.Display(options);
SHOW(display.getContainer());
tileSet.onload = () => {
display.draw(0, 0, ["#", "@"]);
};
// Console display / graphical tiles / Colorizing tiles
tileSet = document.createElement("img");
tileSet.src = "tiles.png";
options = {
layout: "tile",
tileWidth: 64,
tileHeight: 64,
tileSet,
tileMap: {
"@": [0, 0],
"#": [0, 64],
a: [64, 0],
"!": [64, 64]
},
width: 3,
height: 2,
tileColorize: true
};
display = new ROT.Display(options);
SHOW(display.getContainer());
tileSet.onload = () => {
display.draw(0, 0, "@", "transparent");
display.draw(1, 0, "@", "green", "red");
display.draw(2, 0, "@", "rgba(30, 200, 30, 0.5)", "red");
display.draw(0, 1, "#", "transparent");
display.draw(1, 1, "#", "white");
display.draw(2, 1, "#", "transparent", "rgba(250, 250, 0, 0.5)");
};
// Console display / graphical tiles / Colorized tile stacks
tileSet = document.createElement("img");
tileSet.src = "tiles.png";
options = {
layout: "tile",
bg: "transparent",
tileWidth: 64,
tileHeight: 64,
tileSet,
tileColorize: true,
tileMap: {
"@": [0, 0],
"#": [0, 64]
},
width: 1,
height: 1
};
display = new ROT.Display(options);
SHOW(display.getContainer());
tileSet.onload = () => {
const ch = ["#", "@"];
const fg = ["rgba(255, 0, 0, 0.5)", "rgba(0, 0, 255, 0.5)"];
const bg = ["transparent", "transparent"];
display.draw(0, 0, ch, fg, bg);
};
// Map creation
let map = new ROT.Map.Arena(3, 3);
const userCallback = (x: number, y: number, value: number) => {
SHOW("Value %s generated at [%s,%s]".format(value, x, y));
};
map.create(userCallback);
map = new ROT.Map.Arena(10, 5);
const display1 = new ROT.Display({ width: 10, height: 5, fontSize: 18 });
SHOW(display1.getContainer());
map.create((x, y, wall) => {
display1.draw(x, y, wall ? "#" : ".");
});
/* debugging with small font */
const display2 = new ROT.Display({ width: 10, height: 5, fontSize: 8 });
SHOW(display2.getContainer());
map.create(display2.DEBUG);
// Map creation / Maze / DividedMaze
const dm = new ROT.Map.DividedMaze(w, h);
for (let i = 0; i < 4; i++) {
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
dm.create(display.DEBUG);
}
// Map creation / Maze / Icey's Maze
for (let i = 0; i < 4; i++) {
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
const maze = new ROT.Map.IceyMaze(w, h, 4 * i);
maze.create(display.DEBUG);
}
// Map creation / Maze / Eller's Perfect Maze
const em = new ROT.Map.EllerMaze(w, h);
for (let i = 0; i < 4; i++) {
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
em.create(display.DEBUG);
}
// Map creation / Cellular
let cellular = new ROT.Map.Cellular(w, h);
/* cells with 1/2 probability */
cellular.randomize(0.5);
/* generate and show four generations */
for (let i = 0; i < 4; i++) {
display = new ROT.Display({ width: w, height: h, fontSize: 4 });
SHOW(display.getContainer());
cellular.create(display.DEBUG);
}
// ----
w = 100; h = 60;
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
/* custom born/survive rules */
cellular = new ROT.Map.Cellular(w, h, {
born: [4, 5, 6, 7, 8],
survive: [2, 3, 4, 5]
});
cellular.randomize(0.9);
/* generate fifty iterations, show the last one */
for (let i = 49; i >= 0; i--) {
cellular.create(i ? undefined : display.DEBUG);
}
// ----
/* create a connected map where the player can reach all non-wall sections */
cellular = new ROT.Map.Cellular(w, h, { connected: true });
/* cells with 1/2 probability */
cellular.randomize(0.5);
/* make a few generations */
for (let i = 0; i < 4; i++) cellular.create();
/* display only the final map */
display = new ROT.Display({ width: w, height: h, fontSize: 4 });
SHOW(display.getContainer());
cellular.create(display.DEBUG);
/* now connect the maze */
display = new ROT.Display({ width: w, height: h, fontSize: 4 });
SHOW(display.getContainer());
cellular.connect(display.DEBUG);
// ----
/* create a connected map where the player can reach all non-wall sections */
cellular = new ROT.Map.Cellular(w, h, { connected: true });
/* cells with 1/2 probability */
cellular.randomize(0.5);
/* make a few generations */
for (let i = 0; i < 4; i++) cellular.create();
/* display only the final map */
display = new ROT.Display({ width: w, height: h, fontSize: 4 });
SHOW(display.getContainer());
cellular.create(display.DEBUG);
/* now connect the maze */
display = new ROT.Display({ width: w, height: h, fontSize: 4 });
SHOW(display.getContainer());
cellular.connect(display.DEBUG, 1);
// ----
/* create a connected map where the player can reach all non-wall sections */
cellular = new ROT.Map.Cellular(w, h, { connected: true });
/* cells with 1/2 probability */
cellular.randomize(0.5);
/* make a few generations */
for (let i = 0; i < 4; i++) cellular.create();
/* display only the final map */
display = new ROT.Display({ width: w, height: h, fontSize: 4 });
SHOW(display.getContainer());
cellular.create(display.DEBUG);
/* now connect the maze */
display = new ROT.Display({ width: w, height: h, fontSize: 4 });
SHOW(display.getContainer());
cellular.connect(display.DEBUG, 0, (from, to) => {
SHOW(`Connection was made ${from} to ${to}`);
});
// Map creation / Dungeon
ROT.RNG.setSeed(1234);
let dungeon = new ROT.Map.Digger();
display = new ROT.Display({ fontSize: 8 });
SHOW(display.getContainer());
dungeon.create(display.DEBUG);
const drawDoor = (x: number, y: number) => {
display.draw(x, y, "", "", "red");
};
const rooms = dungeon.getRooms();
for (let i = 0; i < rooms.length; i++) {
const room = rooms[i];
SHOW("Room #%s: [%s, %s] => [%s, %s]".format(
(i + 1),
room.getLeft(), room.getTop(),
room.getRight(), room.getBottom()
));
room.getDoors(drawDoor);
}
// Map creation / Dungeon / Digger
dungeon = new ROT.Map.Digger(w, h);
for (let i = 0; i < 4; i++) {
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
dungeon.create(display.DEBUG);
}
// Map creation / Dungeon / Uniform
const uniform = new ROT.Map.Uniform(w, h);
for (let i = 0; i < 4; i++) {
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
uniform.create(display.DEBUG);
}
// Map creation / Dungeon / Rogue
const rogue = new ROT.Map.Rogue(w, h);
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
rogue.create(display.DEBUG);
// FOV computation / Precise shadowcasting
ROT.RNG.setSeed(12345);
// Not supported in ES6/TS2
// ROT.DEFAULT_WIDTH = 80;
// ROT.DEFAULT_HEIGHT = 30;
display = new ROT.Display({ fontSize: 2 });
SHOW(display.getContainer());
/* create a map */
let data_uniform: any = {};
new ROT.Map.Uniform().create((x: number, y: number, type: number) => {
data_uniform[`${x},${y}`] = type;
display.DEBUG(x, y, type);
});
/* input callback */
let lightPasses = (x: number, y: number) => {
const key = `${x},${y}`;
if (key in data_uniform) { return (data_uniform[key] === 0); }
return false;
};
let fov = new ROT.FOV.PreciseShadowcasting(lightPasses);
/* output callback */
fov.compute(50, 22, 10, (x, y, r, visibility) => {
const ch = (r ? "" : "@");
const color = (data_uniform[`${x},${y}`] ? "#aa0" : "#660");
display.draw(x, y, ch, "#fff", color);
});
// FOV computation / Recursive shadowcasting
ROT.RNG.setSeed(12345);
const DIR_NORTH = 0;
const DIR_WEST = 6;
display = new ROT.Display({ fontSize: 12 });
SHOW(display.getContainer());
/* create a map */
data_uniform = {};
new ROT.Map.Uniform().create((x: number, y: number, type: number) => {
data_uniform[`${x},${y}`] = type;
display.DEBUG(x, y, type);
});
/* input callback */
lightPasses = (x: number, y: number) => {
const key = `${x},${y}`;
if (key in data_uniform) { return (data_uniform[key] === 0); }
return false;
};
const fov2 = new ROT.FOV.RecursiveShadowcasting(lightPasses);
/* output callback for mob with bad vision */
fov2.compute90(50, 22, 10, DIR_WEST, (x: number, y: number, r: number, visibility: number) => {
const ch = (r ? "1" : "@");
const color = (data_uniform[`${x},${y}`] ? "#aa0" : "#660");
display.draw(x, y, ch, "#fff", color);
});
/* output callback for second mob with better vision */
fov2.compute180(57, 14, 10, DIR_NORTH, (x: number, y: number, r: number, visibility: number) => {
const ch = (r ? "2" : "@");
const color = (data_uniform[`${x},${y}`] ? "#aa0" : "#660");
display.draw(x, y, ch, "#fff", color);
});
/* output callback for third mob with supernatural vision */
fov2.compute(65, 5, 10, (x: number, y: number, r: number, visibility: number) => {
const ch = (r ? "3" : "@");
const color = (data_uniform[`${x},${y}`] ? "#aa0" : "#660");
display.draw(x, y, ch, "#fff", color);
});
// Color / Converting string → array
SHOW(
ROT.Color.fromString("rgb(10, 128, 230)"),
ROT.Color.fromString("#faa"),
ROT.Color.fromString("#83fcc4"),
ROT.Color.fromString("goldenrod")
);
// Color / Converting array → string
SHOW(
ROT.Color.toRGB([10, 128, 230]),
ROT.Color.toHex([10, 128, 230])
);
// Color / Converting between RGB and HSL
SHOW(
ROT.Color.rgb2hsl([51, 102, 51]),
ROT.Color.hsl2rgb([0.333, 0.333, 0.3])
);
// Color / Adding and mixing colors
SHOW(/* addition = lightening */
ROT.Color.add([10, 128, 230], [200, 10, 15], [30, 30, 100]),
ROT.Color.add_([10, 128, 230], [200, 10, 15])
);
SHOW(/* multiplication = darkening */
ROT.Color.multiply([10, 128, 230], [200, 10, 15]),
ROT.Color.multiply_([10, 128, 230], [200, 10, 15])
);
// Color / Interpolating between two colors
SHOW(
/* computed in RGB space */
ROT.Color.interpolate([10, 128, 230], [30, 255, 255], 0.3),
/* computed in HSL space */
ROT.Color.interpolateHSL([10, 128, 230], [30, 255, 255], 0.3)
);
// Color / Creating random letiants
SHOW(
ROT.Color.randomize([100, 128, 230], [30, 10, 20]),
ROT.Color.randomize([100, 128, 230], [30, 10, 20]),
ROT.Color.randomize([100, 128, 230], [30, 10, 20])
);
// Color / Lighting
ROT.RNG.setSeed(12345);
const mapData: any = {};
const lightData: { [key: string]: [number, number, number] } = {};
/* build a map */
cellular = new ROT.Map.Cellular().randomize(0.5);
const createCallback = (x: number, y: number, value: number) => {
mapData[`${x},${y}`] = value;
};
for (let i = 0; i < 4; i++) {
cellular.create(createCallback);
}
/* prepare a FOV algorithm */
lightPasses = (x: number, y: number) => {
return (mapData[`${x},${y}`] === 1);
};
fov = new ROT.FOV.PreciseShadowcasting(lightPasses, { topology: 4 });
/* prepare a lighting algorithm */
const reflectivity = (x: number, y: number) => {
return (mapData[`${x},${y}`] === 1 ? 0.3 : 0);
};
const lighting = new ROT.Lighting(reflectivity, { range: 12, passes: 2 });
lighting.setFOV(fov);
lighting.setLight(12, 12, [240, 240, 30]);
lighting.setLight(20, 20, [240, 60, 60]);
lighting.setLight(45, 25, [200, 200, 200]);
const lightingCallback = (x: number, y: number, color: [number, number, number]) => {
lightData[`${x},${y}`] = color;
};
lighting.compute(lightingCallback);
/* draw the resulting mix of mapData and lightData */
display = new ROT.Display({ fontSize: 8 });
SHOW(display.getContainer());
/* all cells are lit by ambient light; some are also lit by light sources */
const ambientLight: ROT.ColorArray = [100, 100, 100];
for (const id in mapData) {
const parts = id.split(",");
const x = parseInt(parts[0], 10);
const y = parseInt(parts[1], 10);
const baseColor: ROT.ColorArray = (mapData[id] ? [100, 100, 100] : [50, 50, 50]);
let light = ambientLight;
if (id in lightData) { /* add light from our computation */
light = ROT.Color.add(light, lightData[id]);
}
const finalColor = ROT.Color.multiply(baseColor, light);
display.draw(x, y, "@", "white", ROT.Color.toRGB(finalColor));
}
// Pathfinding / Dijkstra's algorithm
ROT.RNG.setSeed(12345);
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
/* generate map and store its data */
const uni_data: any = {};
let uni_map = new ROT.Map.Uniform(w, h);
uni_map.create((x, y, value) => {
uni_data[`${x},${y}`] = value;
display.DEBUG(x, y, value);
});
/* input callback informs about map structure */
let passableCallback = (x: number, y: number) => {
return (uni_data[`${x},${y}`] === 0);
};
/* prepare path to given coords */
let dijkstra = new ROT.Path.Dijkstra(98, 38, passableCallback);
/* compute from given coords #1 */
dijkstra.compute(8, 45, (x: number, y: number) => {
display.draw(x, y, "", "", "#800");
});
/* compute from given coords #2 */
dijkstra.compute(130, 8, (x: number, y: number) => {
display.draw(x, y, "", "", "#800");
});
/* highlight */
display.draw(8, 45, "", "", "#3f3");
display.draw(130, 8, "", "", "#3f3");
display.draw(98, 38, "", "", "#f33");
// Pathfinding / A* algorithm
ROT.RNG.setSeed(12345);
display = new ROT.Display({ width: w, height: h, fontSize: 6 });
SHOW(display.getContainer());
/* generate map and store its data */
uni_map = new ROT.Map.Uniform(w, h);
uni_map.create((x: number, y: number, value: number) => {
uni_data[`${x},${y}`] = value;
display.DEBUG(x, y, value);
});
/* input callback informs about map structure */
passableCallback = (x: number, y: number) => {
return (uni_data[`${x},${y}`] === 0);
};
/* prepare path to given coords */
const astar = new ROT.Path.AStar(98, 38, passableCallback);
/* compute from given coords #1 */
astar.compute(8, 45, (x: number, y: number) => {
display.draw(x, y, "", "", "#800");
});
/* compute from given coords #2 */
astar.compute(130, 8, (x: number, y: number) => {
display.draw(x, y, "", "", "#800");
});
/* highlight */
display.draw(8, 45, "", "", "#3f3");
display.draw(130, 8, "", "", "#3f3");
display.draw(98, 38, "", "", "#f33");
// Noise Generation
let noise = new ROT.Noise.Simplex();
display = new ROT.Display({ width: w, height: h, fontSize: 3 });
SHOW(display.getContainer());
for (let j = 0; j < h; j++) {
for (let i = 0; i < w; i++) {
const val = noise.get(i / 20, j / 20) * 255;
const r = ~~(val > 0 ? val : 0);
const g = ~~(val < 0 ? -val : 0);
display.draw(i, j, "", "", `rgb(${r},${g},0)`);
}
}
// ----
noise = new ROT.Noise.Simplex();
display = new ROT.Display({ width: w, height: h, fontSize: 12, layout: "hex" });
SHOW(display.getContainer());
for (let j = 0; j < h; j++) {
for (let i = j % 2; i < w; i += 2) {
const val = noise.get(i / 60, j / 60) * 255;
const r = ~~(val > 0 ? val : 0);
const g = ~~(val < 0 ? -val : 0);
display.draw(i, j, "", "", `rgb(${r},${g},0)`);
}
}
// Timing & scheduling / event queue
const queue = new ROT.EventQueue();
queue.add("event 1", 100); /* queued after 100 time units */
queue.add("event 2", 10); /* queued after 10 time units */
queue.add("event 3", 50); /* queued after 50 time units */
queue.remove("event 2");
SHOW(
queue.get(),
queue.get(),
queue.getTime()
);
// Timing & scheduling / Simple scheduler
let scheduler = new ROT.Scheduler.Simple();
/* generate some actors */
for (let i = 0; i < 4; i++) {
scheduler.add(i + 1, true); /* true = recurring actor */
}
/* simulate several turns */
let turns: any = [];
for (let i = 0; i < 20; i++) {
const current = scheduler.next();
turns.push(current);
}
SHOW("\nGenerated order of actors:");
SHOW(turns.join(" ") + " ...");
// Timing & scheduling / Speed scheduler
scheduler = new ROT.Scheduler.Speed();
class Actor {
constructor(public speed: number, public number: number) { }
getSpeed() { return this.speed; }
}
/* generate some actors */
for (let i = 0; i < 4; i++) {
const actor = new Actor(ROT.RNG.getPercentage(), i + 1);
scheduler.add(actor, true);
SHOW("Object #%s has speed %s.".format(actor.number, actor.speed));
}
/* simulate several turns */
turns = [];
for (let i = 0; i < 40; i++) {
const current = scheduler.next();
turns.push(current.number);
}
SHOW("\nGenerated order of turns:");
SHOW(turns.join(" ") + " ...");
// Timing & scheduling / Action-duration scheduler
const act_scheduler = new ROT.Scheduler.Action();
/* generate some actors */
for (let i = 0; i < 4; i++) {
act_scheduler.add(i + 1, true, i); /* last argument - initial delay */
}
/* simulate several turns */
template = "Actor %s performing action for %s time units (current time: %s)";
for (let i = 0; i < 20; i++) {
const current = act_scheduler.next();
const actionDuration = Math.ceil(ROT.RNG.getUniform() * 20);
act_scheduler.setDuration(actionDuration);
const padded = actionDuration.toString().lpad("0");
SHOW(template.format(current, padded, act_scheduler.getTime()));
}
// Timing & scheduling / Engine / Asynchronous game engine
scheduler = new ROT.Scheduler.Simple();
let engine = new ROT.Engine(scheduler);
let output: any = [];
class Actor1 {
constructor(public lives: number) { }
act() {
output.push(".");
this.lives--;
if (!this.lives) {
scheduler.remove(actor1);
engine.lock(); /* pause execution */
setTimeout(unlock, 500); /* wait for 500ms */
}
}
}
/* sample actor: pauses the execution when dead */
const actor1 = new Actor1(3);
scheduler.add(actor1, true);
class Actor2 {
act() {
output.push("@");
}
}
const unlock = () => { /* called asynchronously */
const actor2 = new Actor2();
output = [];
scheduler.add(actor2, false); /* add second (non-repeating) actor */
engine.unlock(); /* continue execution */
SHOW(output.join(""));
};
engine.start();
SHOW(output.join(""));
// Timing & scheduling / Engine / Promises
scheduler = new ROT.Scheduler.Simple();
engine = new ROT.Engine(scheduler);
output = [];
/* sample actor: pauses the execution when dead */
class Actor3 {
constructor(public lives: number) { }
act() {
let done: any = null;
const promise = {
then(cb: any) { done = cb; }
};
output.push(".");
SHOW(output.join(""));
this.lives--;
/* if alive, wait for 500ms for next turn */
if (this.lives) {
setTimeout(() => { done(); }, 500);
}
return promise;
}
}
const actor3 = new Actor3(3);
scheduler.add(actor3, true);
engine.start();
// String generator
const sg = new ROT.StringGenerator();
const req = new XMLHttpRequest();
req.open("get", "java.txt", true);
req.send();
req.onreadystatechange = () => {
if (req.readyState !== 4) { return; }
const lines = req.responseText.split("\n");
while (lines.length) {
const line = lines.pop()!.trim();
if (!line) { continue; }
sg.observe(line);
}
for (let i = 0; i < 20; i++) { SHOW(sg.generate()); }
};
// Hex support / Displaying hexes
display = new ROT.Display({ width: 8, height: 5 });
SHOW(display.getContainer());
for (let y = 0; y < 5; y++) {
for (let x = y % 2; x < 8; x += 2) {
display.draw(x, y, "•");
}
}
// ----
display = new ROT.Display({ width: 8, height: 5, layout: "hex" });
SHOW(display.getContainer());
for (let y = 0; y < 5; y++) {
for (let x = y % 2; x < 8; x += 2) {
const bg = ["#333", "#666", "#999", "#ccc", "#fff"].random();
display.draw(x, y, "•", "#000", bg);
}
}
// ----
display = new ROT.Display({
width: 10, height: 4, spacing: 2.5,
layout: "hex", transpose: true
});
SHOW(display.getContainer());
for (let y = 0; y < 4; y++) {
for (let x = y % 2; x < 10; x += 2) {
const bg = ["#333", "#666", "#999", "#ccc", "#fff"].random();
display.draw(x, y, `${x},${y}`, "#000", bg);
}
}
// Hex support / Cellular dungeon generator
display = new ROT.Display({ width: w, height: h, fontSize: 10, layout: "hex" });
SHOW(display.getContainer());
/* hexagonal map and rules */
let cell_map = new ROT.Map.Cellular(w, h, {
topology: 6,
born: [4, 5, 6],
survive: [3, 4, 5, 6]
});
/* initialize with irregularly random values */
for (let i = 0; i < w; i++) {
for (let j = 0; j < h; j++) {
const dx = i / w - 0.5;
const dy = j / h - 0.5;
const dist = Math.pow(dx * dx + dy * dy, 0.3);
if (ROT.RNG.getUniform() < dist) { cell_map.set(i, j, 1); }
}
}
/* generate four iterations, show the last one */
for (let i = 4; i >= 0; i--) {
cell_map.create(i ? undefined : display.DEBUG);
}
// Hex support / Pathfinding
ROT.RNG.setSeed(12345);
display = new ROT.Display({ width: w, height: h, fontSize: 6, layout: "hex" });
SHOW(display.getContainer());
/* generate map and store its data */
let cell_data: any = {};
cell_map = new ROT.Map.Cellular(w, h, {
topology: 6,
born: [4, 5, 6],
survive: [3, 4, 5, 6]
});
cell_map.randomize(0.48);
cell_map.create(); /* two iterations */
cell_map.create((x: number, y: number, value: number) => {
cell_data[`${x},${y}`] = value;
display.DEBUG(x, y, value);
});
/* input callback informs about map structure */
passableCallback = (x: number, y: number) => {
return (cell_data[`${x},${y}`] === 0);
};
/* prepare path to given coords */
dijkstra = new ROT.Path.Dijkstra(120, 64, passableCallback, { topology: 6 });
/* compute from given coords */
dijkstra.compute(30, 16, (x: number, y: number) => {
display.draw(x, y, "", "", "#800");
});
/* highlight */
display.draw(30, 16, "", "", "#3f3");
display.draw(120, 64, "", "", "#f33");
// Hex support / Field of view
ROT.RNG.setSeed(12345);
display = new ROT.Display({ fontSize: 12, layout: "hex" });
SHOW(display.getContainer());
/* generate map and store its data */
cell_data = {};
cell_map = new ROT.Map.Cellular(undefined, undefined, {
topology: 6,
born: [4, 5, 6],
survive: [3, 4, 5, 6]
});
cell_map.randomize(0.4);
cell_map.create((x: number, y: number, value: number) => {
cell_data[`${x},${y}`] = value;
display.DEBUG(x, y, value);
});
/* input callback */
lightPasses = (x: number, y: number) => {
const key = `${x},${y}`;
if (key in cell_data) { return (cell_data[key] === 0); }
return false;
};
fov = new ROT.FOV.PreciseShadowcasting(lightPasses, { topology: 6 });
/* output callback */
fov.compute(20, 14, 6, (x, y, r, vis) => {
const ch = (r ? "" : "@");
const color = (cell_data[`${x},${y}`] ? "#aa0" : "#660");
display.draw(x, y, ch, "#fff", color);
});