bitburner-src/src/Casino/Roulette.tsx

587 lines
16 KiB
TypeScript
Raw Normal View History

import * as React from "react";
2021-09-05 01:09:30 +02:00
import { IPlayer } from "../PersonObjects/IPlayer";
import { StdButton } from "../ui/React/StdButton";
2021-09-05 01:09:30 +02:00
import { Money } from "../ui/React/Money";
import { Game } from "./Game";
import { WHRNG } from "./RNG";
import { trusted } from "./utils";
type IProps = {
2021-09-05 01:09:30 +02:00
p: IPlayer;
};
type IState = {
2021-09-05 01:09:30 +02:00
investment: number;
canPlay: boolean;
status: string | JSX.Element;
n: number;
lock: boolean;
strategy: Strategy;
};
const minPlay = 0;
const maxPlay = 1e7;
function isRed(n: number): boolean {
2021-09-05 01:09:30 +02:00
return [
1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36,
].includes(n);
}
type Strategy = {
2021-09-05 01:09:30 +02:00
match: (n: number) => boolean;
payout: number;
};
2021-09-05 01:09:30 +02:00
const redNumbers: number[] = [
1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36,
];
const strategies: {
2021-09-05 01:09:30 +02:00
Red: Strategy;
Black: Strategy;
Odd: Strategy;
Even: Strategy;
High: Strategy;
Low: Strategy;
Third1: Strategy;
Third2: Strategy;
Third3: Strategy;
} = {
2021-09-05 01:09:30 +02:00
Red: {
match: (n: number): boolean => {
if (n === 0) return false;
return redNumbers.includes(n);
},
2021-09-05 01:09:30 +02:00
payout: 1,
},
Black: {
match: (n: number): boolean => {
return !redNumbers.includes(n);
},
2021-09-05 01:09:30 +02:00
payout: 1,
},
Odd: {
match: (n: number): boolean => {
if (n === 0) return false;
return n % 2 === 1;
},
2021-09-05 01:09:30 +02:00
payout: 1,
},
Even: {
match: (n: number): boolean => {
if (n === 0) return false;
return n % 2 === 0;
},
2021-09-05 01:09:30 +02:00
payout: 1,
},
High: {
match: (n: number): boolean => {
if (n === 0) return false;
return n > 18;
},
2021-09-05 01:09:30 +02:00
payout: 1,
},
Low: {
match: (n: number): boolean => {
if (n === 0) return false;
return n < 19;
},
2021-09-05 01:09:30 +02:00
payout: 1,
},
Third1: {
match: (n: number): boolean => {
if (n === 0) return false;
return n <= 12;
},
2021-09-05 01:09:30 +02:00
payout: 2,
},
Third2: {
match: (n: number): boolean => {
if (n === 0) return false;
return n >= 13 && n <= 24;
},
2021-09-05 01:09:30 +02:00
payout: 2,
},
Third3: {
match: (n: number): boolean => {
if (n === 0) return false;
return n >= 25;
},
2021-09-05 01:09:30 +02:00
payout: 2,
},
};
function Single(s: number): Strategy {
2021-09-05 01:09:30 +02:00
return {
match: (n: number): boolean => {
return s === n;
},
payout: 36,
};
}
export class Roulette extends Game<IProps, IState> {
2021-09-05 01:09:30 +02:00
interval = -1;
rng: WHRNG;
2021-09-05 01:09:30 +02:00
constructor(props: IProps) {
super(props);
2021-09-05 01:09:30 +02:00
this.rng = new WHRNG(new Date().getTime());
this.state = {
investment: 1000,
canPlay: true,
status: "waiting",
n: 0,
lock: true,
strategy: {
payout: 0,
match: (): boolean => {
return false;
},
},
};
2021-09-05 01:09:30 +02:00
this.step = this.step.bind(this);
this.currentNumber = this.currentNumber.bind(this);
this.updateInvestment = this.updateInvestment.bind(this);
}
2021-09-05 01:09:30 +02:00
componentDidMount(): void {
this.interval = window.setInterval(this.step, 50);
}
2021-09-05 01:09:30 +02:00
step(): void {
if (!this.state.lock) {
this.setState({ n: Math.floor(Math.random() * 37) });
}
2021-09-05 01:09:30 +02:00
}
2021-09-05 01:09:30 +02:00
componentWillUnmount(): void {
clearInterval(this.interval);
}
2021-09-05 01:09:30 +02:00
updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) {
investment = minPlay;
}
2021-09-05 01:09:30 +02:00
if (investment > maxPlay) {
investment = maxPlay;
}
2021-09-05 01:09:30 +02:00
if (investment < minPlay) {
investment = minPlay;
}
2021-09-05 01:09:30 +02:00
this.setState({ investment: investment });
}
2021-09-05 01:09:30 +02:00
currentNumber(): string {
if (this.state.n === 0) return "0";
const color = isRed(this.state.n) ? "R" : "B";
return `${this.state.n}${color}`;
}
2021-09-05 01:09:30 +02:00
play(s: Strategy): void {
if (this.reachedLimit(this.props.p)) return;
this.setState({
canPlay: false,
lock: false,
status: "playing",
strategy: s,
});
setTimeout(() => {
let n = Math.floor(this.rng.random() * 37);
let status = <></>;
let gain = 0;
let playerWin = this.state.strategy.match(n);
// oh yeah, the house straight up cheats. Try finding the seed now!
if (playerWin && Math.random() > 0.9) {
playerWin = false;
while (this.state.strategy.match(n)) {
n++;
}
}
if (playerWin) {
gain = this.state.investment * this.state.strategy.payout;
status = (
<>
won <Money money={gain} />
</>
);
} else {
gain = -this.state.investment;
status = (
<>
lost <Money money={-gain} />
</>
);
}
this.win(this.props.p, gain);
this.setState({
canPlay: true,
lock: true,
status: status,
n: n,
});
this.reachedLimit(this.props.p);
}, 1600);
}
2021-09-05 01:09:30 +02:00
render(): React.ReactNode {
return (
<>
<h1>{this.currentNumber()}</h1>
2021-09-05 01:09:30 +02:00
<input
type="number"
className="text-input"
onChange={this.updateInvestment}
placeholder={"Amount to play"}
value={this.state.investment}
disabled={!this.state.canPlay}
/>
<h1>{this.state.status}</h1>
<table>
2021-09-05 01:09:30 +02:00
<tbody>
<tr>
<td>
<StdButton
text={"3"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(3)))}
/>
</td>
<td>
<StdButton
text={"6"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(6)))}
/>
</td>
<td>
<StdButton
text={"9"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(9)))}
/>
</td>
<td>
<StdButton
text={"12"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(12)))}
/>
</td>
<td>
<StdButton
text={"15"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(15)))}
/>
</td>
<td>
<StdButton
text={"18"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(18)))}
/>
</td>
<td>
<StdButton
text={"21"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(21)))}
/>
</td>
<td>
<StdButton
text={"24"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(24)))}
/>
</td>
<td>
<StdButton
text={"27"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(27)))}
/>
</td>
<td>
<StdButton
text={"30"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(30)))}
/>
</td>
<td>
<StdButton
text={"33"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(33)))}
/>
</td>
<td>
<StdButton
text={"36"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(36)))}
/>
</td>
</tr>
<tr>
<td>
<StdButton
text={"2"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(2)))}
/>
</td>
<td>
<StdButton
text={"5"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(5)))}
/>
</td>
<td>
<StdButton
text={"8"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(8)))}
/>
</td>
<td>
<StdButton
text={"11"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(11)))}
/>
</td>
<td>
<StdButton
text={"14"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(14)))}
/>
</td>
<td>
<StdButton
text={"17"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(17)))}
/>
</td>
<td>
<StdButton
text={"20"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(20)))}
/>
</td>
<td>
<StdButton
text={"23"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(23)))}
/>
</td>
<td>
<StdButton
text={"26"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(26)))}
/>
</td>
<td>
<StdButton
text={"29"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(29)))}
/>
</td>
<td>
<StdButton
text={"32"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(32)))}
/>
</td>
<td>
<StdButton
text={"35"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(35)))}
/>
</td>
</tr>
<tr>
<td>
<StdButton
text={"1"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(1)))}
/>
</td>
<td>
<StdButton
text={"4"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(4)))}
/>
</td>
<td>
<StdButton
text={"7"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(7)))}
/>
</td>
<td>
<StdButton
text={"10"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(10)))}
/>
</td>
<td>
<StdButton
text={"13"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(13)))}
/>
</td>
<td>
<StdButton
text={"16"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(16)))}
/>
</td>
<td>
<StdButton
text={"19"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(19)))}
/>
</td>
<td>
<StdButton
text={"22"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(22)))}
/>
</td>
<td>
<StdButton
text={"25"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(25)))}
/>
</td>
<td>
<StdButton
text={"28"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(28)))}
/>
</td>
<td>
<StdButton
text={"31"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(31)))}
/>
</td>
<td>
<StdButton
text={"34"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(34)))}
/>
</td>
</tr>
<tr>
<td colSpan={4}>
<StdButton
text={"1 to 12"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Third1))}
/>
</td>
<td colSpan={4}>
<StdButton
text={"13 to 24"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Third2))}
/>
</td>
<td colSpan={4}>
<StdButton
text={"25 to 36"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Third3))}
/>
</td>
</tr>
<tr>
<td colSpan={2}>
<StdButton
text={"Red"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Red))}
/>
</td>
<td colSpan={2}>
<StdButton
text={"Black"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Black))}
/>
</td>
<td colSpan={2}>
<StdButton
text={"Odd"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Odd))}
/>
</td>
<td colSpan={2}>
<StdButton
text={"Even"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Even))}
/>
</td>
<td colSpan={2}>
<StdButton
text={"High"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.High))}
/>
</td>
<td colSpan={2}>
<StdButton
text={"Low"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(strategies.Low))}
/>
</td>
</tr>
<tr>
<td>
<StdButton
text={"0"}
disabled={!this.state.canPlay}
onClick={trusted(() => this.play(Single(0)))}
/>
</td>
</tr>
</tbody>
</table>
2021-09-05 01:09:30 +02:00
</>
);
}
}