@pkmn/engine 0.1.0-dev.7963b917 → 0.1.0-dev.79957401

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 (85) hide show
  1. package/LICENSE +1 -3
  2. package/README.md +70 -28
  3. package/build/pkg/addon/browser.d.ts +3 -0
  4. package/build/pkg/addon/browser.js +47 -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 +110 -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 +53 -0
  11. package/build/pkg/addon/wasm.js.map +1 -0
  12. package/build/pkg/addon.d.ts +26 -4
  13. package/build/pkg/addon.js +39 -71
  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 +17 -4
  17. package/build/pkg/data/protocol.json +84 -13
  18. package/build/pkg/data.d.ts +27 -5
  19. package/build/pkg/data.js.map +1 -1
  20. package/build/pkg/gen1.d.ts +15 -18
  21. package/build/pkg/gen1.js +30 -21
  22. package/build/pkg/gen1.js.map +1 -1
  23. package/build/pkg/index.d.ts +42 -91
  24. package/build/pkg/index.js +23 -70
  25. package/build/pkg/index.js.map +1 -1
  26. package/build/pkg/protocol.d.ts +29 -1
  27. package/build/pkg/protocol.js +123 -102
  28. package/build/pkg/protocol.js.map +1 -1
  29. package/build/tools/debug.js +84 -73
  30. package/build/tools/debug.js.map +1 -1
  31. package/build/tools/display/debug.jsx +66 -0
  32. package/build/tools/display/debug.jsx.map +1 -0
  33. package/build/tools/display/index.js +152 -0
  34. package/build/tools/display/index.js.map +1 -0
  35. package/build/tools/display/ui.jsx +360 -0
  36. package/build/tools/display/ui.jsx.map +1 -0
  37. package/build/tools/display/util.js +157 -0
  38. package/build/tools/display/util.js.map +1 -0
  39. package/build.zig +397 -149
  40. package/package.json +62 -123
  41. package/src/bin/install-pkmn-engine +43 -22
  42. package/src/bin/pkmn-debug +1 -1
  43. package/src/lib/bindings/c.zig +201 -0
  44. package/src/lib/{binding → bindings}/node.zig +15 -32
  45. package/src/lib/bindings/wasm.zig +51 -0
  46. package/src/lib/common/array.zig +70 -0
  47. package/src/lib/common/data.zig +12 -24
  48. package/src/lib/common/debug.zig +46 -30
  49. package/src/lib/common/js.zig +3 -7
  50. package/src/lib/common/optional.zig +30 -24
  51. package/src/lib/common/options.zig +6 -0
  52. package/src/lib/common/protocol.zig +961 -450
  53. package/src/lib/common/rational.zig +341 -254
  54. package/src/lib/common/rng.zig +26 -19
  55. package/src/lib/common/util.zig +53 -1
  56. package/src/lib/gen1/calc.zig +726 -178
  57. package/src/lib/gen1/chance.zig +526 -324
  58. package/src/lib/gen1/data/moves.zig +193 -183
  59. package/src/lib/gen1/data/species.zig +4 -6
  60. package/src/lib/gen1/data/types.zig +9 -10
  61. package/src/lib/gen1/data.zig +78 -90
  62. package/src/lib/gen1/helpers.zig +114 -422
  63. package/src/lib/gen1/mechanics.zig +699 -615
  64. package/src/lib/gen2/calc.zig +150 -0
  65. package/src/lib/gen2/chance.zig +914 -0
  66. package/src/lib/gen2/data/items.zig +13 -21
  67. package/src/lib/gen2/data/moves.zig +664 -572
  68. package/src/lib/gen2/data/species.zig +2 -4
  69. package/src/lib/gen2/data/types.zig +139 -34
  70. package/src/lib/gen2/data.zig +131 -103
  71. package/src/lib/gen2/generated.zig +801 -0
  72. package/src/lib/gen2/helpers.zig +76 -51
  73. package/src/lib/gen2/mechanics.zig +3569 -29
  74. package/src/lib/napi.h +2 -0
  75. package/src/lib/node.zig +14 -0
  76. package/src/lib/pkmn.zig +125 -29
  77. package/src/lib/wasm.zig +13 -0
  78. package/src/tools/display/dom.ts +108 -0
  79. package/src/tools/display/ui.css +354 -0
  80. package/build/test/display.js +0 -400
  81. package/build/test/display.js.map +0 -1
  82. package/src/lib/binding/wasm.zig +0 -12
  83. package/src/lib/gen1/README.md +0 -812
  84. package/src/lib/gen2/README.md +0 -308
  85. package/src/test/display/pkmn.html.tmpl +0 -368
@@ -1,31 +1,20 @@
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;
29
18
 
30
19
  pub const Options = struct {
31
20
  cleric: bool = showdown,
@@ -48,7 +37,7 @@ pub const Battle = struct {
48
37
  comptime rolls: anytype,
49
38
  p1: []const Pokemon,
50
39
  p2: []const Pokemon,
51
- ) data.Battle(rng.FixedRNG(1, rolls.len)) {
40
+ ) data.Battle(rng.FixedRNG(2, rolls.len)) {
52
41
  return .{
53
42
  .rng = .{ .rolls = rolls },
54
43
  .sides = .{ Side.init(p1), Side.init(p2) },
@@ -65,17 +54,47 @@ pub const Battle = struct {
65
54
  };
66
55
 
67
56
  pub fn prng(rand: *PSRNG) data.PRNG {
68
- // FIXME: what is max range in gen2?
69
57
  return .{
70
58
  .src = .{
71
59
  .seed = if (showdown)
72
60
  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
- },
61
+ else seed: {
62
+ // GLITCH: The initial RNG seed in Gen II link battles is heavily constrained
63
+ // https://www.smogon.com/forums/threads/rng-in-rby-link-battles.3746779
64
+ var seed = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0 };
65
+
66
+ // Bytes in seed can only range from 0-252, not 0-255
67
+ const max: u8 = 253;
68
+ // Instructions take multiples of 4 cycles to execute
69
+ var timer: u16 = 4 * rand.range(u16, 0, 16384);
70
+ var add: u8 = rand.range(u8, 0, 256);
71
+ var sub: u8 = rand.range(u8, 0, 256);
72
+ var carry: u8 = 0;
73
+ var div: u8 = 0;
74
+
75
+ var i: usize = 0;
76
+ while (i < seed.len) {
77
+ div = @intCast(timer >> 8);
78
+ // This is effectively @addWithOverflow but with three operands
79
+ const result = @as(u16, add) + @as(u16, div) + @as(u16, carry);
80
+ add = @intCast(result & 255);
81
+ carry = @intFromBool(result > 255);
82
+ timer +%= 44;
83
+ div = @intCast(timer >> 8);
84
+ sub -%= div +% carry;
85
+
86
+ if (sub < max) {
87
+ seed[i] = sub;
88
+ i += 1;
89
+ timer +%= 152;
90
+ carry = 1;
91
+ } else {
92
+ timer +%= 132;
93
+ carry = 0;
94
+ }
95
+ }
96
+ break :seed seed;
97
+ },
79
98
  },
80
99
  };
81
100
  }
@@ -87,7 +106,7 @@ pub const Side = struct {
87
106
 
88
107
  for (0..ps.len) |i| {
89
108
  side.pokemon[i] = Pokemon.init(ps[i]);
90
- // FIXME side.order[i] = i + 1;
109
+ side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
91
110
  }
92
111
  return side;
93
112
  }
@@ -98,7 +117,7 @@ pub const Side = struct {
98
117
 
99
118
  for (0..n) |i| {
100
119
  side.pokemon[i] = Pokemon.random(rand, opt);
101
- side.pokemon[i].position = i + 1;
120
+ side.pokemon[i].position = @as(u4, @intCast(i)) + 1;
102
121
  }
103
122
 
104
123
  return side;
@@ -121,26 +140,28 @@ pub const Pokemon = struct {
121
140
  var pokemon = data.Pokemon{};
122
141
  pokemon.species = p.species;
123
142
  const species = Species.get(p.species);
124
- inline for (@typeInfo(@TypeOf(pokemon.stats)).Struct.fields) |field| {
125
- const hp = comptime std.mem.eql(u8, field.name, "hp");
143
+ inline for (if (@hasField(@TypeOf(@typeInfo(@TypeOf(pokemon.stats)).@"struct"), "fields"))
144
+ @typeInfo(@TypeOf(pokemon.stats)).@"struct".fields
145
+ else
146
+ @typeInfo(@TypeOf(pokemon.stats)).@"struct".field_names) |field|
147
+ {
148
+ const field_name = if (@hasField(@TypeOf(field), "name")) field.name else field;
149
+ const hp = comptime std.mem.eql(u8, field_name, "hp");
126
150
  const spc =
127
- comptime std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
128
- @field(pokemon.stats, field.name) = Stats(u16).calc(
129
- field.name,
130
- @field(species.stats, field.name),
131
- if (hp) p.dvs.hp() else if (spc) p.dvs.spc else @field(p.dvs, field.name),
132
- @field(p.stats, field.name),
151
+ comptime std.mem.eql(u8, field_name, "spa") or std.mem.eql(u8, field_name, "spd");
152
+ @field(pokemon.stats, field_name) = Stats(u16).calc(
153
+ field_name,
154
+ @field(species.stats, field_name),
155
+ if (hp) p.dvs.hp() else if (spc) p.dvs.spc else @field(p.dvs, field_name),
156
+ @field(p.stats, field_name),
133
157
  p.level,
134
158
  );
135
159
  }
136
160
  assert(p.moves.len > 0 and p.moves.len <= 4);
137
161
  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
- };
162
+ pokemon.moves[j].id = m;
163
+ // NB: PP can be at most 61 legally (though can overflow to 63)
164
+ pokemon.moves[j].pp = @intCast(@min(Move.pp(m) / 5 * 8, 61));
144
165
  }
145
166
  pokemon.item = p.item;
146
167
  if (p.hp) |hp| {
@@ -151,7 +172,7 @@ pub const Pokemon = struct {
151
172
  pokemon.status = p.status;
152
173
  pokemon.types = species.types;
153
174
  pokemon.level = p.level;
154
- pokemon.dvs = DVs.from(p.dvs);
175
+ pokemon.dvs = DVs.from(p.species, p.dvs);
155
176
  return pokemon;
156
177
  }
157
178
 
@@ -165,19 +186,24 @@ pub const Pokemon = struct {
165
186
 
166
187
  var stats: Stats(u16) = .{};
167
188
  const dvs = gen1.DVs.random(rand);
168
- inline for (@typeInfo(@TypeOf(stats)).Struct.fields) |field| {
169
- const hp = std.mem.eql(u8, field.name, "hp");
170
- const spc = std.mem.eql(u8, field.name, "spa") or std.mem.eql(u8, field.name, "spd");
171
- @field(stats, field.name) = Stats(u16).calc(
172
- field.name,
173
- @field(species.stats, field.name),
174
- if (hp) dvs.hp() else if (spc) dvs.spc else @field(dvs, field.name),
189
+ inline for (if (@hasField(@TypeOf(@typeInfo(@TypeOf(stats)).@"struct"), "fields"))
190
+ @typeInfo(@TypeOf(stats)).@"struct".fields
191
+ else
192
+ @typeInfo(@TypeOf(stats)).@"struct".field_names) |field|
193
+ {
194
+ const field_name = if (@hasField(@TypeOf(field), "name")) field.name else field;
195
+ const hp = std.mem.eql(u8, field_name, "hp");
196
+ const spc = std.mem.eql(u8, field_name, "spa") or std.mem.eql(u8, field_name, "spd");
197
+ @field(stats, field_name) = Stats(u16).calc(
198
+ field_name,
199
+ @field(species.stats, field_name),
200
+ if (hp) dvs.hp() else if (spc) dvs.spc else @field(dvs, field_name),
175
201
  if (rand.chance(u8, 1, 20)) rand.range(u8, 0, 255 + 1) else 255,
176
202
  lvl,
177
203
  );
178
204
  }
179
205
 
180
- var ms = [_]MoveSlot{.{}} ** 4;
206
+ var ms: [4]MoveSlot = @splat(.{});
181
207
  const n = if (rand.chance(u8, 1, 100)) rand.range(u4, 1, 3 + 1) else 4;
182
208
  for (0..n) |i| {
183
209
  var m: Move = .None;
@@ -192,14 +218,13 @@ pub const Pokemon = struct {
192
218
  const max_pp: u8 = @intCast(Move.pp(m) + pp_ups * @min(Move.pp(m) / 5, 7));
193
219
  ms[i] = .{
194
220
  .id = m,
195
- .pp_ups = pp_ups,
196
221
  .pp = if (opt.cleric) max_pp else rand.range(u8, 0, max_pp + 1),
197
222
  };
198
223
  }
199
224
  return .{
200
225
  .species = s,
201
226
  .types = species.types,
202
- .dvs = DVs.from(dvs),
227
+ .dvs = DVs.from(s, dvs),
203
228
  .level = lvl,
204
229
  .stats = stats,
205
230
  .hp = if (opt.cleric) stats.hp else rand.range(u16, 0, stats.hp + 1),