@pkmn/engine 0.1.0-dev.c5fe6d07 → 0.1.0-dev.cdc837af

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +46 -19
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +44 -0
  5. package/build/pkg/addon/browser.js.map +1 -0
  6. package/build/pkg/addon/node.d.ts +3 -0
  7. package/build/pkg/addon/node.js +97 -0
  8. package/build/pkg/addon/node.js.map +1 -0
  9. package/build/pkg/addon/wasm.d.ts +2 -0
  10. package/build/pkg/addon/wasm.js +21 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +22 -0
  13. package/build/pkg/addon.js +35 -58
  14. package/build/pkg/addon.js.map +1 -1
  15. package/build/pkg/data/ids.json +12 -12
  16. package/build/pkg/data/layout.json +2 -2
  17. package/build/pkg/data/protocol.json +69 -12
  18. package/build/pkg/data.d.ts +27 -5
  19. package/build/pkg/data.js.map +1 -1
  20. package/build/pkg/gen1.js +3 -3
  21. package/build/pkg/gen1.js.map +1 -1
  22. package/build/pkg/index.d.ts +24 -10
  23. package/build/pkg/index.js +15 -10
  24. package/build/pkg/index.js.map +1 -1
  25. package/build/pkg/protocol.d.ts +20 -1
  26. package/build/pkg/protocol.js +123 -102
  27. package/build/pkg/protocol.js.map +1 -1
  28. package/build/tools/debug.js +36 -68
  29. package/build/tools/debug.js.map +1 -1
  30. package/build/tools/display/debug.jsx +141 -0
  31. package/build/tools/display/debug.jsx.map +1 -0
  32. package/build/tools/display/index.js +141 -0
  33. package/build/tools/display/index.js.map +1 -0
  34. package/build/tools/display/ui.jsx +349 -0
  35. package/build/tools/display/ui.jsx.map +1 -0
  36. package/build/tools/display/util.js +18 -0
  37. package/build/tools/display/util.js.map +1 -0
  38. package/build.zig +259 -107
  39. package/package.json +72 -32
  40. package/src/bin/install-pkmn-engine +29 -19
  41. package/src/bin/pkmn-debug +1 -1
  42. package/src/lib/common/array.zig +77 -0
  43. package/src/lib/common/data.zig +12 -24
  44. package/src/lib/common/debug.zig +39 -8
  45. package/src/lib/common/js.zig +4 -2
  46. package/src/lib/common/optional.zig +21 -10
  47. package/src/lib/common/options.zig +4 -0
  48. package/src/lib/common/protocol.zig +808 -332
  49. package/src/lib/common/rational.zig +132 -36
  50. package/src/lib/common/rng.zig +22 -15
  51. package/src/lib/common/util.zig +50 -1
  52. package/src/lib/gen1/calc.zig +688 -162
  53. package/src/lib/gen1/chance.zig +436 -295
  54. package/src/lib/gen1/data/moves.zig +193 -183
  55. package/src/lib/gen1/data/species.zig +4 -6
  56. package/src/lib/gen1/data/types.zig +8 -9
  57. package/src/lib/gen1/data.zig +55 -70
  58. package/src/lib/gen1/helpers.zig +91 -562
  59. package/src/lib/gen1/mechanics.zig +610 -561
  60. package/src/lib/gen2/calc.zig +153 -0
  61. package/src/lib/gen2/chance.zig +902 -0
  62. package/src/lib/gen2/data/items.zig +13 -21
  63. package/src/lib/gen2/data/moves.zig +664 -572
  64. package/src/lib/gen2/data/species.zig +2 -4
  65. package/src/lib/gen2/data/types.zig +135 -33
  66. package/src/lib/gen2/data.zig +115 -91
  67. package/src/lib/gen2/generated.zig +801 -0
  68. package/src/lib/gen2/helpers.zig +54 -37
  69. package/src/lib/gen2/mechanics.zig +3569 -29
  70. package/src/lib/{binding/node.zig → node.zig} +9 -14
  71. package/src/lib/pkmn.zig +36 -15
  72. package/src/lib/{binding/wasm.zig → wasm.zig} +1 -1
  73. package/src/tools/display/dom.ts +96 -0
  74. package/src/tools/display/ui.css +354 -0
  75. package/build/test/display.js +0 -400
  76. package/build/test/display.js.map +0 -1
  77. package/src/lib/gen1/README.md +0 -892
  78. package/src/lib/gen2/README.md +0 -308
  79. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,31 +1,22 @@
1
- const std = @import("std");
2
-
3
1
  const common = @import("../common/data.zig");
2
+ const data = @import("data.zig");
3
+ const gen1 = @import("../gen1/data.zig");
4
4
  const options = @import("../common/options.zig");
5
- const protocol = @import("../common/protocol.zig");
6
5
  const rng = @import("../common/rng.zig");
7
-
8
- const gen1 = @import("../gen1/data.zig");
9
-
10
- const data = @import("data.zig");
6
+ const std = @import("std");
11
7
 
12
8
  const assert = std.debug.assert;
13
-
14
- const expectEqual = std.testing.expectEqual;
15
-
16
9
  const Choice = common.Choice;
17
-
18
- const showdown = options.showdown;
19
-
20
- const PSRNG = rng.PSRNG;
21
-
22
10
  const DVs = data.DVs;
23
11
  const Item = data.Item;
24
12
  const Move = data.Move;
25
13
  const MoveSlot = data.MoveSlot;
14
+ const PSRNG = rng.PSRNG;
15
+ const showdown = options.showdown;
26
16
  const Species = data.Species;
27
17
  const Stats = data.Stats;
28
- const Status = data.Status;
18
+
19
+ const Struct = if (@hasField(std.builtin.Type, "struct")) .@"struct" else .Struct;
29
20
 
30
21
  pub const Options = struct {
31
22
  cleric: bool = showdown,
@@ -48,7 +39,7 @@ pub const Battle = struct {
48
39
  comptime rolls: anytype,
49
40
  p1: []const Pokemon,
50
41
  p2: []const Pokemon,
51
- ) data.Battle(rng.FixedRNG(1, rolls.len)) {
42
+ ) data.Battle(rng.FixedRNG(2, rolls.len)) {
52
43
  return .{
53
44
  .rng = .{ .rolls = rolls },
54
45
  .sides = .{ Side.init(p1), Side.init(p2) },
@@ -65,17 +56,47 @@ pub const Battle = struct {
65
56
  };
66
57
 
67
58
  pub fn prng(rand: *PSRNG) data.PRNG {
68
- // FIXME: what is max range in gen2?
69
59
  return .{
70
60
  .src = .{
71
61
  .seed = if (showdown)
72
62
  rand.newSeed()
73
- else
74
- .{
75
- rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
76
- rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
77
- rand.range(u8, 0, 256), rand.range(u8, 0, 256), rand.range(u8, 0, 256),
78
- },
63
+ else seed: {
64
+ // GLITCH: The initial RNG seed in Gen II link battles is heavily constrained
65
+ // https://www.smogon.com/forums/threads/rng-in-rby-link-battles.3746779
66
+ var seed = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
67
+
68
+ // Bytes in seed can only range from 0-252, not 0-255
69
+ const max: u8 = 253;
70
+ // Instructions take multiples of 4 cycles to execute
71
+ var timer: u16 = 4 * rand.range(u16, 0, 16384);
72
+ var add: u8 = rand.range(u8, 0, 256);
73
+ var sub: u8 = rand.range(u8, 0, 256);
74
+ var carry: u8 = 0;
75
+ var div: u8 = 0;
76
+
77
+ var i: u8 = 0;
78
+ while (i < seed.len) {
79
+ div = @intCast(timer >> 8);
80
+ // This is effectively @addWithOverflow but with three operands
81
+ const result = @as(u16, add) + @as(u16, div) + @as(u16, carry);
82
+ add = @intCast(result & 255);
83
+ carry = @intFromBool(result > 255);
84
+ timer +%= 44;
85
+ div = @intCast(timer >> 8);
86
+ sub -%= div +% carry;
87
+
88
+ if (sub < max) {
89
+ seed[i] = sub;
90
+ i += 1;
91
+ timer +%= 152;
92
+ carry = 1;
93
+ } else {
94
+ timer +%= 132;
95
+ carry = 0;
96
+ }
97
+ }
98
+ break :seed seed;
99
+ },
79
100
  },
80
101
  };
81
102
  }
@@ -87,7 +108,7 @@ pub const Side = struct {
87
108
 
88
109
  for (0..ps.len) |i| {
89
110
  side.pokemon[i] = Pokemon.init(ps[i]);
90
- // FIXME side.order[i] = i + 1;
111
+ side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
91
112
  }
92
113
  return side;
93
114
  }
@@ -98,7 +119,7 @@ pub const Side = struct {
98
119
 
99
120
  for (0..n) |i| {
100
121
  side.pokemon[i] = Pokemon.random(rand, opt);
101
- side.pokemon[i].position = i + 1;
122
+ side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
102
123
  }
103
124
 
104
125
  return side;
@@ -121,7 +142,7 @@ pub const Pokemon = struct {
121
142
  var pokemon = data.Pokemon{};
122
143
  pokemon.species = p.species;
123
144
  const species = Species.get(p.species);
124
- inline for (@typeInfo(@TypeOf(pokemon.stats)).Struct.fields) |field| {
145
+ inline for (@field(@typeInfo(@TypeOf(pokemon.stats)), @tagName(Struct)).fields) |field| {
125
146
  const hp = comptime std.mem.eql(u8, field.name, "hp");
126
147
  const spc =
127
148
  comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
@@ -135,12 +156,9 @@ pub const Pokemon = struct {
135
156
  }
136
157
  assert(p.moves.len > 0 and p.moves.len <= 4);
137
158
  for (p.moves, 0..) |m, j| {
138
- pokemon.moves[j] = .{
139
- .id = m,
140
- .pp_ups = 3,
141
- // NB: PP can be at most 61 legally (though can overflow to 63)
142
- .pp = @intCast(@min(Move.pp(m) / 5 * 8, 61)),
143
- };
159
+ pokemon.moves[j].id = m;
160
+ // NB: PP can be at most 61 legally (though can overflow to 63)
161
+ pokemon.moves[j].pp = @intCast(@min(Move.pp(m) / 5 * 8, 61));
144
162
  }
145
163
  pokemon.item = p.item;
146
164
  if (p.hp) |hp| {
@@ -151,7 +169,7 @@ pub const Pokemon = struct {
151
169
  pokemon.status = p.status;
152
170
  pokemon.types = species.types;
153
171
  pokemon.level = p.level;
154
- pokemon.dvs = DVs.from(p.dvs);
172
+ pokemon.dvs = DVs.from(p.species, p.dvs);
155
173
  return pokemon;
156
174
  }
157
175
 
@@ -165,7 +183,7 @@ pub const Pokemon = struct {
165
183
 
166
184
  var stats: Stats(u16) = .{};
167
185
  const dvs = gen1.DVs.random(rand);
168
- inline for (@typeInfo(@TypeOf(stats)).Struct.fields) |field| {
186
+ inline for (@field(@typeInfo(@TypeOf(stats)), @tagName(Struct)).fields) |field| {
169
187
  const hp = std.mem.eql(u8, field.name, "hp");
170
188
  const spc = std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
171
189
  @field(stats, field.name) = Stats(u16).calc(
@@ -192,14 +210,13 @@ pub const Pokemon = struct {
192
210
  const max_pp: u8 = @intCast(Move.pp(m) + pp_ups * @min(Move.pp(m) / 5, 7));
193
211
  ms[i] = .{
194
212
  .id = m,
195
- .pp_ups = pp_ups,
196
213
  .pp = if (opt.cleric) max_pp else rand.range(u8, 0, max_pp + 1),
197
214
  };
198
215
  }
199
216
  return .{
200
217
  .species = s,
201
218
  .types = species.types,
202
- .dvs = DVs.from(dvs),
219
+ .dvs = DVs.from(s, dvs),
203
220
  .level = lvl,
204
221
  .stats = stats,
205
222
  .hp = if (opt.cleric) stats.hp else rand.range(u16, 0, stats.hp + 1),