我正在尝试使用node.js运行代码,当前出现错误:
意外的标识符
代码文件如下:
/*
This script will bruteforce a live match from the TPP API
in Defiance mode and estimate winrates.
Requirements:
-An oauth for the TPP API: https://twitchplayspokemon.tv/show_oauth_token
-Node.js: https://nodejs.org/en/download/
-sync-request for Node.js: `npm install -g sync-request` (NPM should come
installed with Node.js)
-Pokemon Showdown: https://github.com/Zarel/Pokemon-Showdown
You don't need to install its dependencies, the simulator itself does not
require them.
-My PBR mod for Pokemon Showdown: https://github.com/mathfreak231/random-
showdown-mods
enter code here`enter code here`This is required to accurately simulate PBR.
Note that it is still in development.
Setup steps:
Copy the pbr directory from random-showdown-mods into Pokemon-Showdown/mods.
Fill in the relative path to Pokemon-Showdown/sim below
Fill in your TPP API oauth token below
Change the number constants if you wish
Then just `node defiancechan.js`, sit back, and enjoy your simulation!
Note that the PBR mod is *not* entirely accurate. Known inaccuracies
include,
but are not limited to: draws are not handled properly, and Fury Cutter
still resets when it shouldn't.
*/
// Replace this with a relative path to Pokemon-Showdown/sim
const Sim = require('./../Pokemon-Showdown/sim');
// Replace this with your TPP oauth token
const TPP_OAUTH = "abc123xyz69420";
// Absolute maximum sample size.
const MAX_SAMPLE_SIZE = 1000;
// z* for your desired confidence level. This is used to calculate
// the margin of sampling error. Some common values:
// For 95% confidence: 1.959963986
// For 99% confidence: 2.575829303
// In practice this means that C% of your simulations will
// have the true proportion within the margin of error from
// the sampled proportion.
// If you don't know what any of this means, don't bother changing
// or paying attention to the "Margin of error" output at the end.
const Z_STAR = 2.575829303;
// Maximum time to run the simulation for, in milliseconds.
const MAX_TIME = 30000;
// If this is true, it prints some match logs (1 in DEBUG_EVERY) to stdout
while it's bashing them.
const DEBUG = false;
const DEBUG_EVERY = 50;
// Set this to require a .json file to bash a match there instead of a live
match.
const TEST_MATCH_PATH = null;
/////////////////////////////////////////
// DON'T EDIT ANYTHING BELOW THIS LINE //
/////////////////////////////////////////
const request = require('sync-request');
const PBR_FORMAT = {
id: 'tppbr',
name: 'TPPBR',
mod: 'pbr',
ruleset: ["PBR Sleep Clause", "PBR Freeze Clause", "PBR Self-Destruct
Clause", "PBR Destiny Bond Clause"],
banlist: [],
unbanlist: [],
debug: true,
}
/**
* because pokecat TriHard
*/
function convert_stats_table(stats) {
let newstats = {};
for (statname in stats) {
newstats[statname.toLowerCase()] = stats[statname];
}
return newstats;
}
function main() {
console.log("Getting current match...");
let match;
if (TEST_MATCH_PATH) {
match = require(TEST_MATCH_PATH);
} else {
const res = request('GET',
"https://twitchplayspokemon.tv/api/current_match", {
headers: {
'OAuth-Token': TPP_OAUTH
},
});
match = JSON.parse(res.getBody('utf8'));
}
console.log("Done.");
if ((match.base_gimmicks.includes('blind_bet') ||
match.base_gimmicks.includes('secrecy')) && !match.started) {
throw new Error("Can't analyze a match unless all the Pokemon have been
revealed.");
}
if (!match.base_gimmicks.includes('defiance')) {
console.log("WARNING: This is not a defiance match!");
}
const startTime = Date.now();
let wincounter = {
Blue: 0,
Red: 0,
draw: 0,
};
let teams = [[], []];
for (let i = 0; i < teams.length; i++) {
for (const pokemon of match.teams[i]) {
teams[i].push({
name: pokemon.ingamename,
species: pokemon.species.name, // TODO: handle forms
item: pokemon.item.name,
ability: pokemon.ability.name,
moves: pokemon.moves.map(move => move.name),
nature: pokemon.nature.name,
gender: pokemon.gender ? pokemon.gender.toUpperCase() : 'N',
evs: convert_stats_table(pokemon.evs),
ivs: convert_stats_table(pokemon.ivs),
level: pokemon.level,
shiny: pokemon.shiny,
happiness: pokemon.happiness,
});
}
}
const isRandomOrder = match.base_gimmicks.includes('random_order');
const isTraitor = match.base_gimmicks.includes('traitor');
const isFog = match.base_gimmicks.includes('fog');
let battle;
let i;
console.log("Begin simulation of matches...");
for (i = 1; i <= MAX_SAMPLE_SIZE; i++) {
battle = new Sim.Battle({
formatid: PBR_FORMAT,
});
// prevent battle from starting so we can edit stuff first
battle.started = true;
let newTeams = teams;
if (isRandomOrder || isTraitor) {
// TODO: In what order are these gimmicks applied?
newTeams = battle.deepClone(teams);
if (isRandomOrder) {
for (let team of newTeams) {
battle.shuffle(team);
}
}
if (isTraitor) {
// swap 2 pokes, same position
const p = battle.random(3);
const temp = newTeams[0][p];
newTeams[0][p] = newTeams[1][p];
newTeams[1][p] = temp;
}
}
battle.join('p1', 'Blue', 1, newTeams[0]);
battle.join('p2', 'Red', 2, newTeams[1]);
for (const side of battle.sides) {
for (const pokemon of side.pokemon) {
pokemon.originalPosition = pokemon.position;
for (const [m, move] of pokemon.baseMoveSlots.entries()) {
// change move PP
const moveData = battle.getMove(move.id);
const oldMoveData = match.teams[side.n]
[pokemon.position].moves[m];
move.pp = oldMoveData.pp;
move.maxpp = moveData.pp * (5 + oldMoveData.pp_ups) / 5;
}
pokemon.clearVolatile(); // actually update the moveslots TriHard
}
}
if (match.stage) {
battle.colosseum = match.stage;
} else if (isFog && battle.randomChance(1,2)) {
// TODO: confirm this is correct
battle.colosseum = 'courtyard';
} else {
battle.colosseum = battle.sample([
'gateway', 'mainstreet', 'waterfall', 'neon', 'crystal',
'sunnypark', 'magma', 'sunset', 'stargazer', 'lagoon',
]);
}
battle.started = false;
battle.start();
if (isFog) battle.setWeather('fog');
while (!battle.ended) {
if (battle.turn > 500) {
console.log('===BEGIN BAD MATCH LOG EXPORT===');
console.log(battle.log.join('\n'));
console.log('===END BAD MATCH LOG EXPORT===');
console.log('===BEGIN BAD MATCH INPUT LOG EXPORT===');
console.log(battle.inputLog.join('\n'));
console.log('===END BAD MATCH INPUT LOG EXPORT===');
throw new Error("The match fucked up somehow.");
}
for (const side of battle.sides) {
let result;
switch (side.currentRequest) {
case 'switch':
// TPPBR switching rules.
let target = null;
for (let i = side.active.length; i < side.pokemon.length; i++) {
const pokemon = side.pokemon[i];
if (!(pokemon.fainted) && (!target || pokemon.originalPosition
< target.originalPosition)) {
target = pokemon;
}
}
result = battle.choose(side.id, `switch ${target.position +
1}`);
if (!result) throw new Error(side.choice.error);
break;
case 'move':
// Same as TPPBR, choose random moves until one works
let tries = 0;
do {
result = battle.choose(side.id, `move ${battle.random(4) + 1}`);
if (++tries > 50) throw new Error(`${side.id} stuck on a move
choice: ${side.choice.error}`);
} while (!result);
break;
}
}
}
wincounter[battle.winner || 'draw']++;
if (DEBUG && i % DEBUG_EVERY === 0) {
console.log('===BEGIN RANDOM MATCH LOG EXPORT===');
console.log(battle.log.join('\n'));
console.log('===END RANDOM MATCH LOG EXPORT===');
console.log('===BEGIN RANDOM MATCH INPUT LOG EXPORT===');
console.log(battle.inputLog.join('\n'));
console.log('===END RANDOM MATCH INPUT LOG EXPORT===');
}
battle.destroy();
if (MAX_TIME && Date.now() - startTime >= MAX_TIME) {
break;
}
}
console.log(`Simulated ${i} battles in ${Date.now() - startTime}ms.`);
console.log(`Blue win chance: ${wincounter['Blue'] / i}`);
console.log(`Red win chance: ${wincounter['Red'] / i}`);
console.log(`Draw chance: ${wincounter['draw'] / i}`);
// Large Counts condition
if (wincounter['Blue'] >= 10 && wincounter['Red'] >= 10) {
let favoredWinrate = Math.max(wincounter['Blue'], wincounter['Red']) /
i;
let standardError = Math.sqrt(favoredWinrate * (1-favoredWinrate) / i);
console.log(`Margin of error: ${Z_STAR * standardError}`);
} else {
console.log("Counts are too small to infer a margin of error.");
}
}
main();
我已经填写了PC的所有信息以及应该执行的所有代码和下载,但我不确定自己做错了什么。帮助将不胜感激。谢谢。如果更简单,我还将提供我从中获取此代码的Github链接。 https://gist.github.com/mathfreak231/4229a28f419f4aa10fcb2eba9fdd57e9
答案 0 :(得分:0)
我不确定这是否就是SO的格式,但是这里有一些多余的换行符:
ruleset: ["PBR Sleep Clause", "PBR Freeze Clause", "PBR Self-Destruct
在一起。下一行以Clause
开头,这不是有效的JS关键字,因此会出现错误throw new Error("Can't analyze a match unless all the Pokemon have been
的行上,再次出现不必要的换行符。// If this is true, it prints some match logs (1 in DEBUG_EVERY) to stdout
开头的注释行有换行符。// Set this to require a .json file to bash a match there instead of a live
开头的注释行有换行符。通常,请更明确地读取错误消息。几乎总是会明确告诉您它认为错误在哪里。