chore: small improvements to the slightly smart cpu
This commit is contained in:
parent
7a8b5e198d
commit
9904439a78
@ -1,96 +1,102 @@
|
||||
import { Play, PLAYER_OPTIONS, PlayerAction } from "../game";
|
||||
|
||||
export type CPUNAME = "CPU Random" | "CPU Always Rock" | "Slightly Smart";
|
||||
export const CPUS_NAMES: CPUNAME[] = ["CPU Random", "CPU Always Rock", "Slightly Smart"];
|
||||
export const CPUS_NAMES: CPUNAME[] = [
|
||||
"CPU Random",
|
||||
"CPU Always Rock",
|
||||
"Slightly Smart",
|
||||
];
|
||||
|
||||
export const CPU_FUNCTION_MAPING: Record<CPUNAME, (plays: Play[]) => PlayerAction> = {
|
||||
"CPU Random": CpuRandom,
|
||||
"CPU Always Rock": () => 'Rock',
|
||||
"Slightly Smart": CpuSlightlySmart,
|
||||
}
|
||||
export const CPU_FUNCTION_MAPING: Record<
|
||||
CPUNAME,
|
||||
(plays: Play[]) => PlayerAction
|
||||
> = {
|
||||
"CPU Random": CpuRandom,
|
||||
"CPU Always Rock": () => "Rock",
|
||||
"Slightly Smart": CpuSlightlySmart,
|
||||
};
|
||||
|
||||
export const CPU_FUNCTION_MAPING_END: ((plays: Play[], user: string) => void)[] = [
|
||||
CpuSlightlySmartEnd
|
||||
]
|
||||
export const CPU_FUNCTION_MAPING_END: ((
|
||||
plays: Play[],
|
||||
user: string,
|
||||
) => void)[] = [CpuSlightlySmartEnd];
|
||||
|
||||
function CpuRandom(): PlayerAction {
|
||||
return PLAYER_OPTIONS[Math.floor(Math.random() * PLAYER_OPTIONS.length)];
|
||||
return PLAYER_OPTIONS[Math.floor(Math.random() * PLAYER_OPTIONS.length)];
|
||||
}
|
||||
|
||||
//
|
||||
// CPU slightly Smart
|
||||
//
|
||||
// Keeps track of the all users plays and then use that to modify the chance
|
||||
// of an action to be played. The action will be weigthed based on the actions
|
||||
// that are likely to win agains the trend of what players have been playing
|
||||
//
|
||||
const CpuSlightlySmartValue = PLAYER_OPTIONS.reduce(
|
||||
(acc, a) => {
|
||||
acc[a] = 1;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<PlayerAction, number>,
|
||||
);
|
||||
function CpuSlightlySmart(plays: Play[]): PlayerAction {
|
||||
const turn = plays.length;
|
||||
const turn = plays.length;
|
||||
|
||||
function runTurn(extractFromStorage: 'st' | 'nd' | 'rd') {
|
||||
let base = PLAYER_OPTIONS.reduce((acc, a) => {
|
||||
acc[a] = 1;
|
||||
return acc;
|
||||
}, {} as Record<PlayerAction, number>);
|
||||
let base = CpuSlightlySmartValue;
|
||||
try {
|
||||
const newBase = JSON.parse(
|
||||
localStorage.getItem("slightly-smart-cpu-data") ?? "",
|
||||
);
|
||||
base = { ...base, ...newBase[turn] };
|
||||
} catch {
|
||||
// Do nothing use the default
|
||||
}
|
||||
|
||||
try {
|
||||
const newBase = JSON.parse(localStorage.getItem('slightly-smart-cpu-data') ?? '');
|
||||
base = { ...base, ...newBase[extractFromStorage] };
|
||||
} catch {
|
||||
// Do nothing use the default
|
||||
}
|
||||
const sum = PLAYER_OPTIONS.reduce((acc, a) => acc + base[a], 0);
|
||||
const choise = Math.floor(Math.random() * sum);
|
||||
let runningCount = 0;
|
||||
|
||||
let sum = PLAYER_OPTIONS.reduce((acc, a) => acc + base[a], 0);
|
||||
const choise = Math.floor(Math.random() * sum);
|
||||
let runningCount = 0;
|
||||
for (const a of PLAYER_OPTIONS) {
|
||||
const newSum = runningCount + base[a];
|
||||
if (choise > runningCount && choise < newSum) {
|
||||
return a;
|
||||
}
|
||||
runningCount = newSum;
|
||||
}
|
||||
|
||||
for (const a of PLAYER_OPTIONS) {
|
||||
let newSum = runningCount + base[a];
|
||||
if (choise > runningCount && choise < newSum) {
|
||||
return a;
|
||||
}
|
||||
runningCount = newSum;
|
||||
}
|
||||
// it shouldn't reach here but if it does just return something random
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (turn === 0) {
|
||||
const res = runTurn('st')
|
||||
if (res !== undefined) return res;
|
||||
} else if (turn === 1) {
|
||||
const res = runTurn('nd')
|
||||
if (res !== undefined) return res;
|
||||
}
|
||||
else if (turn === 2) {
|
||||
const res = runTurn('rd')
|
||||
if (res !== undefined) return res;
|
||||
}
|
||||
else throw 'unrechable';
|
||||
|
||||
|
||||
return PLAYER_OPTIONS[Math.floor(Math.random() * PLAYER_OPTIONS.length)];
|
||||
return PLAYER_OPTIONS[Math.floor(Math.random() * PLAYER_OPTIONS.length)];
|
||||
}
|
||||
function CpuSlightlySmartEnd(plays: Play[]) {
|
||||
let storageData: {
|
||||
st: Partial<Record<PlayerAction, number>>
|
||||
nd: Partial<Record<PlayerAction, number>>
|
||||
rd: Partial<Record<PlayerAction, number>>
|
||||
} = { st: {}, nd: {}, rd: {} };
|
||||
try {
|
||||
// It's ok for this to error
|
||||
storageData = JSON.parse(localStorage.getItem('slightly-smart-cpu-data') ?? '');
|
||||
} catch {
|
||||
// do nothing just goto the default value
|
||||
}
|
||||
let storageData: Partial<Record<PlayerAction, number>>[] = [{}, {}, {}];
|
||||
try {
|
||||
// It's ok for this to error
|
||||
storageData = JSON.parse(
|
||||
localStorage.getItem("slightly-smart-cpu-data") ?? "",
|
||||
);
|
||||
// Handle the old version of the data
|
||||
if (!Array.isArray(storageData)) {
|
||||
storageData = [{}, {}, {}];
|
||||
}
|
||||
} catch {
|
||||
// do nothing just goto the default value
|
||||
}
|
||||
|
||||
const ResultReverseMappings: Record<PlayerAction, PlayerAction[]> = {
|
||||
"Scissors": ["Rock", "Spock"],
|
||||
"Paper": ["Scissors", "Lizard"],
|
||||
"Rock": ["Paper", "Spock"],
|
||||
"Lizard": ["Scissors", "Rock"],
|
||||
"Spock": ["Paper", "Lizard"],
|
||||
};
|
||||
const ResultReverseMappings: Record<PlayerAction, PlayerAction[]> = {
|
||||
Scissors: ["Rock", "Spock"],
|
||||
Paper: ["Scissors", "Lizard"],
|
||||
Rock: ["Paper", "Spock"],
|
||||
Lizard: ["Scissors", "Rock"],
|
||||
Spock: ["Paper", "Lizard"],
|
||||
};
|
||||
|
||||
ResultReverseMappings[plays[0].user].forEach((a: PlayerAction) => { storageData.st[a] = (storageData.st[a] ?? 0) + 1; })
|
||||
ResultReverseMappings[plays[1].user].forEach((a: PlayerAction) => { storageData.nd[a] = (storageData.nd[a] ?? 0) + 1; })
|
||||
ResultReverseMappings[plays[2].user].forEach((a: PlayerAction) => { storageData.rd[a] = (storageData.rd[a] ?? 0) + 1; })
|
||||
for (let i = 0; i < 3; i++) {
|
||||
ResultReverseMappings[plays[i].user].forEach((a: PlayerAction) => {
|
||||
storageData[i][a] = (storageData[i][a] ?? 0) + 1;
|
||||
});
|
||||
}
|
||||
|
||||
localStorage.setItem('slightly-smart-cpu-data', JSON.stringify(storageData));
|
||||
localStorage.setItem(
|
||||
"slightly-smart-cpu-data",
|
||||
JSON.stringify(storageData),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user