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

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