此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/39671/259481/lib_number_one.js
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展(如 Stylus)后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
您需要先安装一款用户样式管理器扩展后才能安装此样式。
(我已经安装了用户样式管理器,让我安装!)
- /** Functions to handle game state **/
-
- /** objects we handle:
- probability object: map from bullet use number to probability we should pick it
- like { "-1":0.25, "0":0.25, "1":0.5 }
- player object: essentially
- struct player {
- char hp; // ranges from -1 to 5
- unsigned char bullets; // ranges from 0 to 6
- unsigned char fatigue; // ranges from 0 to 3
- enum player_type type; // ranges from 0 to 3
- };
- game state object:
- struct game_state {
- struct player p1;
- struct player p2;
- unsigned char round; // ranges from 1 to 16
- };
- strategy object:
- member p1Move for p1's first action
- + map from p2's action to p1's doubletime action
- **/
-
-
- // deep copy plain data object
- // why is there no builtin equivalent to this
- // javascript pls
- function copy(obj) {
- return JSON.parse(JSON.stringify(obj));
- }
-
- var PREPARATION = 0;
- var CATCH = 1;
- var PIERCE = 2;
- var AURA = 3;
-
- function player_rep(p) {
- var ret = p.hp+2;
- ret = ret | (p.bullets << 3);
- ret = ret | (p.fatigue << 6);
- // prep and aura both act only at the game start so states have same action probabilities
- ret = ret | ((p.type == AURA ? PREPARATION : p.type) << 8);
- return ret;
- }
-
- function game_state_rep(x) {
- return ((player_rep(x.p1) << 14) ^
- (player_rep(x.p2) << 4) ^
- (x.round - 1));
- }
-
- function act(s, act1, act2) {
- var new_state = copy(s);
-
- // Resolve round change and HP damage due to round 10+
- if (new_state.round >= 10) {
- new_state.p1.hp--;
- new_state.p2.hp--;
- }
- new_state.round += 1;
-
- // Resolve bullet count change
- new_state.p1.bullets -= act1;
- new_state.p2.bullets -= act2;
- // should add some asserts here really
-
- // Resolve fatigue and effects thereof
- if (act1 || (act2 > 0)) {
- // player 1 did not block, or blocked a shot
- new_state.p1.fatigue = 0;
- } else if (act2 <= 0) {
- switch (new_state.p1.fatigue) {
- case 0:
- new_state.p1.fatigue = 1;
- break;
- case 1:
- new_state.p1.fatigue = 2;
- break;
- case 2:
- new_state.p1.fatigue = 3;
- // fall through
- case 3:
- new_state.p1.hp--;
- break;
- }
- }
-
- if (act2 || (act1 > 0)) {
- // player 2 did not block, or blocked a shot
- new_state.p2.fatigue = 0;
- } else if (act1 <= 0) {
- switch (new_state.p2.fatigue) {
- case 0:
- new_state.p2.fatigue = 1;
- break;
- case 1:
- new_state.p2.fatigue = 2;
- break;
- case 2:
- new_state.p2.fatigue = 3;
- // fall through
- case 3:
- new_state.p2.hp--;
- break;
- }
- }
-
- // Resolve results of shooting
- if (act1 > 0) {
- if (act2 > 0) {
- // both players shot
- if (act1 > act2) {
- // p2 loses
- new_state.p2.hp = -10;
- } else if (act1 < act2 ||
- (new_state.p2.type == PIERCE &&
- new_state.p1.type != PIERCE)) {
- // p1 loses
- new_state.p1.hp = -10;
- } else if (new_state.p1.type == PIERCE &&
- new_state.p2.type != PIERCE) {
- // p2 loses
- new_state.p2.hp = -10;
- }
- } else if (act2) {
- // p2 reloaded and therefore loses
- new_state.p2.hp = -10;
- } else {
- // p2 blocked
- new_state.p2.hp -= (act1 - 1);
- if (new_state.p2.type == CATCH) {
- // bullet was caught
- new_state.p2.bullets++;
- }
- }
- } else if (act2 > 0) {
- if (act1) {
- // p1 reloaded and loses
- new_state.p1.hp = -10;
- } else {
- // p1 blocked
- new_state.p1.hp -= (act2 - 1);
- if (new_state.p1.type == CATCH) {
- new_state.p1.bullets++;
- }
- }
- }
- // cap bullet count
- if (new_state.p1.bullets > 6) {
- new_state.p1.bullets = 6;
- }
- if (new_state.p2.bullets > 6) {
- new_state.p2.bullets = 6;
- }
- // cap hp count
- if (new_state.p1.hp < 0) {
- new_state.p1.hp = -1;
- }
- if (new_state.p2.hp < 0) {
- new_state.p2.hp = -1;
- }
- return new_state;
- }
-
- function pick_action(probabilities, bullets) {
- if (probabilities == undefined || probabilities == null) {
- // trivial/unreachable state, reload
- return -1;
- }
-
- var accu = Math.random();
-
- for(var act = -1; act <= bullets; act++) {
- var p = probabilities[act];
-
- if(p == undefined || p == null) {
- // something weird happened but whatever
- return Math.max(-1, act-1);
- }
-
- if (p >= accu) {
- return act;
- }
-
- accu -= p;
- }
-
- // rounding error might have the sum of probabilities be less than accu
- // in which case
- return bullets;
- }
-
- // from text representation of the states, get the state object for
- // the state s
- // we avoid JSON parsing because we only want 1 state among millions
- function get_state(states, s) {
- var rep = game_state_rep(s);
- // essentially
- // "$rep": { .* }
- var reg = new RegExp ('"' + rep + '"[^:]*:[^{]*({[^}]*})', "m");
-
- //console.log("getting state " + JSON.stringify(s) + " rep " + rep);
- var matches = states.match(reg);
- if (matches == null || matches.length < 2)
- return null;
-
- var res = matches[1];
- //console.log("results in " + res);
- return JSON.parse(res);
- }
-
- // states: map from state ids to probabilities
- function get_doubletime_strat(states, s) {
- var strat = {};
- var p1Move = pick_action(get_state(states, s), s.p1.bullets);
- strat["p1Move"] = p1Move;
-
- for(var p2Move = -1; p2Move <= s.p2.bullets; p2Move++) {
- var s2 = act(s, p1Move, p2Move);
- if (s2.p1.bullets == 0 && s2.p2.bullets == 0)
- s2 = act(s2, -1, -1);
-
- strat[p2Move] = pick_action(get_state(states,s2), s2.p1.bullets);
- }
- return strat;
- }
-
- function get_winchance(wins, state) {
- var rep = game_state_rep(state);
- var reg = new RegExp ("" + rep + ":(.*)");
-
- var matches = wins.match(reg);
- if (matches == null || matches.length < 2) {
- console.log("N1 win chances: unknown state " + JSON.stringify(state) + " rep " + rep);
- return "-1";
- }
- return matches[1];
- }
-
- // parsing used to be based on https://greasyfork.org/en/scripts/18136-n1bot-inputs
-
- /* A game is displayed in a big <td> whose text goes
- Tier X Event
- Battle Y
- You (win-loss)
- HP: $HP1
- Ammo: $bullets1
- Fatigue: $fatigue1
- Power: Prep|Catch|Pierce|Aura
- <hr>
- P2name
- $P2block (same as P1)
- <hr>
- Round $round
- <hr>
- then some stuff about previous actions,
- then <select> elements to input actions, going
- P1 first move - if P2 reloads - if P2 blocks - if P2 fires 1 to P2 bullets
- The values are according to action_map below.
- We need to parse the 2 player blocks + the round count, send the
- resulting game state to the background script then use the response
- to fill in the selects.
- */
- var action_map = {
- "-1": "1^0",
- "0": "2^0",
- "1": "3^1",
- "2": "3^2",
- "3": "3^3",
- "4": "3^4",
- "5": "3^5",
- "6": "3^6"
- };
-
- var power_map = {
- "Prep": 0,
- "Catch": 1,
- "Pierce": 2,
- "Aura": 3
- }
-
- function parseGame(elmt) {
- var txt = elmt.textContent;
-
- var state = {p1:{}, p2:{}};
-
- var hp_patt = /HP: (\d)/g;
- state.p1.hp = parseInt(hp_patt.exec(txt)[1]);
- state.p2.hp = parseInt(hp_patt.exec(txt)[1]);
-
- var bullet_patt = /Ammo: (\d)/g;
- state.p1.bullets = parseInt(bullet_patt.exec(txt)[1]);
- state.p2.bullets = parseInt(bullet_patt.exec(txt)[1]);
-
- var fatigue_patt = /Fatigue: (\d)/g;
- state.p1.fatigue = parseInt(fatigue_patt.exec(txt)[1]);
- state.p2.fatigue = parseInt(fatigue_patt.exec(txt)[1]);
-
- var pow_patt = /Power: (\w+)/g;
- state.p1.type = power_map[pow_patt.exec(txt)[1]];
- state.p2.type = power_map[pow_patt.exec(txt)[1]];
-
- var round_patt = /Round (\d+)/;
- state.round = parseInt(round_patt.exec(txt)[1]);
-
- return state;
- }