mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-10-23 18:23:15 +02:00
4e5ebcfe6f
v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame) ------- Passive faction reputation * Reworked, from 1 rep / 2 minute. Now is a complicated percentage of the reputation you'd gain working for them. It's not op but it feels a bit more useful. Netscript * print/tprint now take any number of arguments. * print/tprint will now print object as json. * print/tprint now handle passing in an undefined argument properly. Casino * Cannot bet negative money anymore. * Roulette max bet is a bit higher. * Coin Flip has a small cooldown. * All buttons reject unstrusted mouse events. Documentation * Changed a message that said nsjs only works on Chrome. Bugfix * hacknet.maxNumNodes now works for both nodes and servers. * Fixed a bug where the popup boxes would contain data from previous popup boxes. * .js files will also have the export async function boilerplate. Misc. * turned off autocomplete for the terminal text input. * Fixed an issue on Windows+Firefox where pressing up on the terminal would bring the cursor to the begining of the line. (Issue #836) * Hacknet node names is easier to handle for screen readers. * Money spent on classes is now tracked independently of work money. * running coding contract from the terminal will display its name.
239 lines
7.7 KiB
TypeScript
239 lines
7.7 KiB
TypeScript
import * as React from "react";
|
|
|
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
import { StdButton } from "../ui/React/StdButton";
|
|
import { Money } from "../ui/React/Money";
|
|
import { WHRNG } from "./RNG";
|
|
import { Game } from "./Game";
|
|
import { trusted } from "./utils";
|
|
|
|
type IProps = {
|
|
p: IPlayer;
|
|
}
|
|
|
|
type IState = {
|
|
index: number[];
|
|
locks: number[];
|
|
investment: number;
|
|
canPlay: boolean;
|
|
status: string | JSX.Element;
|
|
}
|
|
|
|
// statically shuffled array of symbols.
|
|
let symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C",
|
|
"*", "D", "♥", "B", "A", "A", "A", "C", "A", "D", "B", "E", "?", "D", "*",
|
|
"@", "♥", "B", "E", "?"];
|
|
|
|
function getPayout(s: string, n: number): number {
|
|
switch (s) {
|
|
case "$":
|
|
return [20, 200, 1000][n];
|
|
case "@":
|
|
return [8, 80, 400][n];
|
|
case "♥":
|
|
case "?":
|
|
return [6, 20, 150][n];
|
|
case "D":
|
|
case "E":
|
|
return [1, 8, 30][n];
|
|
default:
|
|
return [1, 5, 20][n];
|
|
}
|
|
}
|
|
|
|
const payLines = [
|
|
// lines
|
|
[[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]],
|
|
[[1, 0], [1, 1], [1, 2], [1, 3], [1, 4]],
|
|
[[2, 0], [2, 1], [2, 2], [2, 3], [2, 4]],
|
|
|
|
// Vs
|
|
[[2, 0], [1, 1], [0, 2], [1, 3], [2, 4]],
|
|
[[0, 0], [1, 1], [2, 2], [1, 3], [0, 4]],
|
|
|
|
// rest
|
|
[[0, 0], [1, 1], [1, 2], [1, 3], [0, 4]],
|
|
[[2, 0], [1, 1], [1, 2], [1, 3], [2, 4]],
|
|
[[1, 0], [0, 1], [0, 2], [0, 3], [1, 4]],
|
|
[[1, 0], [2, 1], [2, 2], [2, 3], [1, 4]],
|
|
];
|
|
|
|
const minPlay = 0;
|
|
const maxPlay = 1e6;
|
|
|
|
export class SlotMachine extends Game<IProps, IState> {
|
|
rng: WHRNG;
|
|
interval: number = -1;
|
|
|
|
constructor(props: IProps) {
|
|
super(props);
|
|
this.rng = new WHRNG(this.props.p.totalPlaytime);
|
|
|
|
this.state = {
|
|
index: [0, 0, 0, 0, 0],
|
|
investment: 1000,
|
|
locks: [0, 0, 0, 0, 0],
|
|
canPlay: true,
|
|
status: 'waiting',
|
|
};
|
|
|
|
this.play = this.play.bind(this);
|
|
this.lock = this.lock.bind(this);
|
|
this.unlock = this.unlock.bind(this);
|
|
this.step = this.step.bind(this);
|
|
this.checkWinnings = this.checkWinnings.bind(this);
|
|
this.getTable = this.getTable.bind(this);
|
|
this.updateInvestment = this.updateInvestment.bind(this);
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.interval = setInterval(this.step, 50);
|
|
}
|
|
|
|
step() {
|
|
let stoppedOne = false;
|
|
const index = this.state.index.slice();
|
|
for(const i in index) {
|
|
if (index[i] === this.state.locks[i] && !stoppedOne) continue;
|
|
index[i] = (index[i] + 1) % symbols.length;
|
|
stoppedOne = true;
|
|
}
|
|
|
|
this.setState({index: index});
|
|
|
|
if(stoppedOne && index.every((e, i) => e === this.state.locks[i])) {
|
|
this.checkWinnings();
|
|
}
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
clearInterval(this.interval);
|
|
}
|
|
|
|
getTable(): string[][] {
|
|
return [
|
|
[symbols[(this.state.index[0]+symbols.length-1)%symbols.length], symbols[(this.state.index[1]+symbols.length-1)%symbols.length], symbols[(this.state.index[2]+symbols.length-1)%symbols.length], symbols[(this.state.index[3]+symbols.length-1)%symbols.length], symbols[(this.state.index[4]+symbols.length-1)%symbols.length]],
|
|
[symbols[this.state.index[0]], symbols[this.state.index[1]], symbols[this.state.index[2]], symbols[this.state.index[3]], symbols[this.state.index[4]]],
|
|
[symbols[(this.state.index[0]+1)%symbols.length], symbols[(this.state.index[1]+1)%symbols.length], symbols[(this.state.index[2]+1)%symbols.length], symbols[(this.state.index[3]+1)%symbols.length], symbols[(this.state.index[4]+1)%symbols.length]],
|
|
];
|
|
}
|
|
|
|
play() {
|
|
if(this.reachedLimit(this.props.p)) return;
|
|
this.setState({status: 'playing'});
|
|
this.win(this.props.p, -this.state.investment);
|
|
if(!this.state.canPlay) return;
|
|
this.unlock();
|
|
setTimeout(this.lock, this.rng.random()*2000+1000);
|
|
}
|
|
|
|
lock() {
|
|
this.setState({
|
|
locks: [
|
|
Math.floor(this.rng.random()*symbols.length),
|
|
Math.floor(this.rng.random()*symbols.length),
|
|
Math.floor(this.rng.random()*symbols.length),
|
|
Math.floor(this.rng.random()*symbols.length),
|
|
Math.floor(this.rng.random()*symbols.length),
|
|
],
|
|
})
|
|
}
|
|
|
|
checkWinnings() {
|
|
const t = this.getTable();
|
|
const getPaylineData = function(payline: number[][]): string[] {
|
|
let data = [];
|
|
for(const point of payline) {
|
|
data.push(t[point[0]][point[1]]);
|
|
}
|
|
return data;
|
|
}
|
|
|
|
const countSequence = function(data: string[]): number {
|
|
let count = 1;
|
|
for(let i = 1; i < data.length; i++) {
|
|
if (data[i]!==data[i-1]) break;
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
let gains = -this.state.investment;
|
|
for (const payline of payLines) {
|
|
const data = getPaylineData(payline);
|
|
const count = countSequence(data);
|
|
if (count < 3) continue;
|
|
const payout = getPayout(data[0], count-3);
|
|
gains += this.state.investment*payout;
|
|
this.win(this.props.p, this.state.investment*payout);
|
|
}
|
|
|
|
this.setState({
|
|
status: <>{gains>0?"gained":"lost"} {Money(Math.abs(gains))}</>,
|
|
canPlay: true,
|
|
})
|
|
if(this.reachedLimit(this.props.p)) return;
|
|
}
|
|
|
|
unlock() {
|
|
this.setState({
|
|
locks: [-1, -1, -1, -1, -1],
|
|
canPlay: false,
|
|
})
|
|
}
|
|
|
|
updateInvestment(e: React.FormEvent<HTMLInputElement>) {
|
|
let investment: number = parseInt(e.currentTarget.value);
|
|
if (isNaN(investment)) {
|
|
investment = minPlay;
|
|
}
|
|
if (investment > maxPlay) {
|
|
investment = maxPlay;
|
|
}
|
|
if (investment < minPlay) {
|
|
investment = minPlay;
|
|
}
|
|
this.setState({investment: investment});
|
|
}
|
|
|
|
render() {
|
|
const t = this.getTable();
|
|
return <>
|
|
<pre>
|
|
+———————————————————————+<br />
|
|
| | {t[0][0]} | {t[0][1]} | {t[0][2]} | {t[0][3]} | {t[0][4]} | |<br />
|
|
| | | | | | | |<br />
|
|
| | {symbols[this.state.index[0]]} | {symbols[this.state.index[1]]} | {symbols[this.state.index[2]]} | {symbols[this.state.index[3]]} | {symbols[this.state.index[4]]} | |<br />
|
|
| | | | | | | |<br />
|
|
| | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |<br />
|
|
+———————————————————————+<br />
|
|
</pre>
|
|
<input type="number" className='text-input' onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} />
|
|
<StdButton onClick={trusted(this.play)} text={"Spin!"} disabled={!this.state.canPlay} />
|
|
<h1>{this.state.status}</h1>
|
|
<h2>Pay lines</h2>
|
|
<pre>
|
|
----- ····· ····· <br />
|
|
····· ----- ····· <br />
|
|
····· ····· ----- <br />
|
|
</pre>
|
|
<br />
|
|
|
|
<pre>
|
|
··^·· \···/ \···/<br />
|
|
·/·\· ·\·/· ·---·<br />
|
|
/···\ ··v·· ·····<br />
|
|
</pre>
|
|
<br />
|
|
|
|
<pre>
|
|
····· ·---· ·····<br />
|
|
·---· /···\ \···/<br />
|
|
/···\ ····· ·---·<br />
|
|
</pre>
|
|
</>
|
|
}
|
|
}
|
|
|
|
// https://felgo.com/doc/how-to-make-a-slot-game-tutorial/
|