pgn2 1.0.0 → 1.2.0

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.
@@ -8,7 +8,7 @@ require 'racc/parser.rb'
8
8
  module PGN
9
9
  class PgnParser < Racc::Parser
10
10
 
11
- module_eval(<<'...end pgn_parser.y/module_eval...', 'pgn_parser.y', 91)
11
+ module_eval(<<'...end pgn_parser.y/module_eval...', 'pgn_parser.y', 97)
12
12
 
13
13
  def parse(input)
14
14
  @lexer = PGN::Lexer.new(input)
@@ -19,27 +19,26 @@ module_eval(<<'...end pgn_parser.y/module_eval...', 'pgn_parser.y', 91)
19
19
  end
20
20
 
21
21
  def next_token
22
- t = @lexer.next_token
23
- return [false, false] unless t
24
- [translate_type(t.type), t.value]
22
+ pair = @lexer.next_token_pair
23
+ return [false, false] unless pair
24
+ type, value = pair
25
+ [translate_type(type), value]
25
26
  end
26
27
 
27
28
  private
28
29
 
30
+ # Punctuation tokens are racc'd by their literal character (taken from
31
+ # PGN::Lexer::LITERAL_BYTES, the single source of truth for those
32
+ # characters); everything else is racc'd by the upcased lexer symbol.
33
+ # A complete frozen lookup keeps this a plain hash read for every token
34
+ # instead of allocating two Strings (`to_s` + `upcase`) per token.
35
+ TOKEN_TRANSLATIONS = PGN::Lexer::LITERAL_BYTES.values.to_h.merge(
36
+ string: :STRING, comment: :COMMENT, game_termination: :GAME_TERMINATION,
37
+ san_move: :SAN_MOVE, nag: :NAG, move_number: :MOVE_NUMBER, tag_name: :TAG_NAME
38
+ ).freeze
39
+
29
40
  def translate_type(sym)
30
- case sym
31
- when :string then :STRING
32
- when :comment then :COMMENT
33
- when :game_termination then :GAME_TERMINATION
34
- when :san_move then :SAN_MOVE
35
- when :nag then :NAG
36
- when :move_number then :MOVE_NUMBER
37
- when :tag_name then :TAG_NAME
38
- when :lbracket then '['
39
- when :rbracket then ']'
40
- when :lparen then '('
41
- when :rparen then ')'
42
- else
41
+ TOKEN_TRANSLATIONS.fetch(sym) do
43
42
  raise "PGN::Lexer produced an unknown token type: #{sym.inspect}"
44
43
  end
45
44
  end
@@ -65,42 +64,42 @@ module_eval(<<'...end pgn_parser.y/module_eval...', 'pgn_parser.y', 91)
65
64
  ##### State transition tables begin ###
66
65
 
67
66
  racc_action_table = [
68
- 2, 16, 7, 17, 22, 14, 6, 24, 11, 6,
69
- 31, 16, 12, 17, 29, 14, 18, 30, 21, 25,
70
- 21, 24, 30 ]
67
+ 2, 16, 7, 17, 23, 14, 6, 25, 11, 6,
68
+ 32, 16, 12, 17, 30, 14, 18, 31, 21, 26,
69
+ 21, 25, 31 ]
71
70
 
72
71
  racc_action_check = [
73
- 1, 27, 2, 27, 17, 27, 5, 17, 6, 1,
74
- 27, 9, 9, 9, 23, 9, 11, 23, 15, 18,
75
- 20, 22, 28 ]
72
+ 1, 28, 2, 28, 17, 28, 5, 17, 6, 1,
73
+ 28, 9, 9, 9, 24, 9, 11, 24, 15, 18,
74
+ 20, 23, 29 ]
76
75
 
77
76
  racc_action_pointer = [
78
77
  nil, 0, 2, nil, nil, -3, 0, nil, nil, 8,
79
78
  nil, 14, nil, nil, nil, 7, nil, 1, 9, nil,
80
- 9, nil, 15, 11, nil, nil, nil, -2, 16, nil,
81
- nil, nil ]
79
+ 9, nil, nil, 15, 11, nil, nil, nil, -2, 16,
80
+ nil, nil, nil ]
82
81
 
83
82
  racc_action_default = [
84
- -1, -24, -24, -2, -8, -4, -24, 32, -3, -24,
85
- -5, -24, -7, -9, -10, -11, -13, -14, -24, -12,
86
- -21, -8, -15, -16, -19, -6, -22, -24, -18, -17,
87
- -20, -23 ]
83
+ -1, -25, -25, -2, -8, -4, -25, 33, -3, -25,
84
+ -5, -25, -7, -9, -10, -11, -13, -14, -25, -12,
85
+ -22, -8, -15, -16, -17, -20, -6, -23, -25, -19,
86
+ -18, -21, -24 ]
88
87
 
89
88
  racc_goto_table = [
90
- 9, 19, 23, 1, 4, 3, 26, 28, 10, 8,
91
- nil, nil, nil, nil, nil, nil, nil, 27 ]
89
+ 9, 24, 4, 19, 1, 3, 10, 29, 27, 8,
90
+ 22, nil, nil, nil, nil, nil, nil, 28 ]
92
91
 
93
92
  racc_goto_check = [
94
- 6, 9, 10, 1, 3, 2, 9, 10, 3, 4,
95
- nil, nil, nil, nil, nil, nil, nil, 6 ]
93
+ 6, 11, 3, 9, 1, 2, 3, 11, 9, 4,
94
+ 10, nil, nil, nil, nil, nil, nil, 6 ]
96
95
 
97
96
  racc_goto_pointer = [
98
- nil, 3, 4, 3, 5, nil, -4, nil, nil, -14,
99
- -15, nil ]
97
+ nil, 4, 4, 1, 5, nil, -4, nil, nil, -12,
98
+ -7, -16, nil ]
100
99
 
101
100
  racc_goto_default = [
102
101
  nil, nil, nil, nil, nil, 5, nil, 13, 15, nil,
103
- nil, 20 ]
102
+ nil, nil, 20 ]
104
103
 
105
104
  racc_reduce_table = [
106
105
  0, 0, :racc_error,
@@ -119,18 +118,19 @@ racc_reduce_table = [
119
118
  1, 20, :_reduce_13,
120
119
  1, 21, :_reduce_14,
121
120
  2, 21, :_reduce_15,
122
- 2, 21, :_reduce_16,
123
- 3, 21, :_reduce_17,
124
- 3, 21, :_reduce_18,
125
- 1, 23, :_reduce_19,
126
- 2, 23, :_reduce_20,
127
- 1, 22, :_reduce_21,
128
- 2, 22, :_reduce_22,
129
- 3, 24, :_reduce_23 ]
121
+ 1, 23, :_reduce_16,
122
+ 1, 23, :_reduce_17,
123
+ 2, 23, :_reduce_18,
124
+ 2, 23, :_reduce_19,
125
+ 1, 24, :_reduce_20,
126
+ 2, 24, :_reduce_21,
127
+ 1, 22, :_reduce_22,
128
+ 2, 22, :_reduce_23,
129
+ 3, 25, :_reduce_24 ]
130
130
 
131
- racc_reduce_n = 24
131
+ racc_reduce_n = 25
132
132
 
133
- racc_shift_n = 32
133
+ racc_shift_n = 33
134
134
 
135
135
  racc_token_table = {
136
136
  false => 0,
@@ -192,6 +192,7 @@ Racc_token_to_s_table = [
192
192
  "element",
193
193
  "san_move_annotated",
194
194
  "variation_list",
195
+ "move_trailer",
195
196
  "annotation_list",
196
197
  "variation" ]
197
198
  Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)
@@ -202,21 +203,21 @@ Racc_debug_parser = false
202
203
 
203
204
  # reduce 0 omitted
204
205
 
205
- module_eval(<<'.,.,', 'pgn_parser.y', 7)
206
+ module_eval(<<'.,.,', 'pgn_parser.y', 9)
206
207
  def _reduce_1(val, _values, result)
207
208
  result = []
208
209
  result
209
210
  end
210
211
  .,.,
211
212
 
212
- module_eval(<<'.,.,', 'pgn_parser.y', 8)
213
+ module_eval(<<'.,.,', 'pgn_parser.y', 10)
213
214
  def _reduce_2(val, _values, result)
214
215
  result = val[0] << val[1]
215
216
  result
216
217
  end
217
218
  .,.,
218
219
 
219
- module_eval(<<'.,.,', 'pgn_parser.y', 13)
220
+ module_eval(<<'.,.,', 'pgn_parser.y', 15)
220
221
  def _reduce_3(val, _values, result)
221
222
  result = val[1].pop
222
223
  result = {
@@ -231,14 +232,14 @@ module_eval(<<'.,.,', 'pgn_parser.y', 13)
231
232
  end
232
233
  .,.,
233
234
 
234
- module_eval(<<'.,.,', 'pgn_parser.y', 24)
235
+ module_eval(<<'.,.,', 'pgn_parser.y', 26)
235
236
  def _reduce_4(val, _values, result)
236
237
  result = val[0]
237
238
  result
238
239
  end
239
240
  .,.,
240
241
 
241
- module_eval(<<'.,.,', 'pgn_parser.y', 27)
242
+ module_eval(<<'.,.,', 'pgn_parser.y', 29)
242
243
  def _reduce_5(val, _values, result)
243
244
  # Right-recursive with section.merge(pair) reproduces the legacy
244
245
  # whittle parser's tag semantics exactly: reverse source insertion
@@ -250,28 +251,28 @@ module_eval(<<'.,.,', 'pgn_parser.y', 27)
250
251
  end
251
252
  .,.,
252
253
 
253
- module_eval(<<'.,.,', 'pgn_parser.y', 35)
254
+ module_eval(<<'.,.,', 'pgn_parser.y', 37)
254
255
  def _reduce_6(val, _values, result)
255
256
  result = { val[1] => val[2][1...-1] }
256
257
  result
257
258
  end
258
259
  .,.,
259
260
 
260
- module_eval(<<'.,.,', 'pgn_parser.y', 38)
261
+ module_eval(<<'.,.,', 'pgn_parser.y', 40)
261
262
  def _reduce_7(val, _values, result)
262
263
  result = val[0] << val[1]
263
264
  result
264
265
  end
265
266
  .,.,
266
267
 
267
- module_eval(<<'.,.,', 'pgn_parser.y', 41)
268
+ module_eval(<<'.,.,', 'pgn_parser.y', 43)
268
269
  def _reduce_8(val, _values, result)
269
270
  result = []
270
271
  result
271
272
  end
272
273
  .,.,
273
274
 
274
- module_eval(<<'.,.,', 'pgn_parser.y', 44)
275
+ module_eval(<<'.,.,', 'pgn_parser.y', 46)
275
276
  def _reduce_9(val, _values, result)
276
277
  result = val[1].nil? ? val[0] : val[0] << val[1]
277
278
 
@@ -279,7 +280,7 @@ module_eval(<<'.,.,', 'pgn_parser.y', 44)
279
280
  end
280
281
  .,.,
281
282
 
282
- module_eval(<<'.,.,', 'pgn_parser.y', 48)
283
+ module_eval(<<'.,.,', 'pgn_parser.y', 50)
283
284
  def _reduce_10(val, _values, result)
284
285
  result = nil
285
286
  result
@@ -288,7 +289,7 @@ module_eval(<<'.,.,', 'pgn_parser.y', 48)
288
289
 
289
290
  # reduce 11 omitted
290
291
 
291
- module_eval(<<'.,.,', 'pgn_parser.y', 52)
292
+ module_eval(<<'.,.,', 'pgn_parser.y', 54)
292
293
  def _reduce_12(val, _values, result)
293
294
  result = val[0]
294
295
  result.variations = val[1]
@@ -298,7 +299,7 @@ module_eval(<<'.,.,', 'pgn_parser.y', 52)
298
299
  end
299
300
  .,.,
300
301
 
301
- module_eval(<<'.,.,', 'pgn_parser.y', 58)
302
+ module_eval(<<'.,.,', 'pgn_parser.y', 60)
302
303
  def _reduce_13(val, _values, result)
303
304
  # A standalone comment (not attached to a move) becomes the game
304
305
  # comment; the last such comment in the game wins.
@@ -309,64 +310,71 @@ module_eval(<<'.,.,', 'pgn_parser.y', 58)
309
310
  end
310
311
  .,.,
311
312
 
312
- module_eval(<<'.,.,', 'pgn_parser.y', 65)
313
+ module_eval(<<'.,.,', 'pgn_parser.y', 67)
313
314
  def _reduce_14(val, _values, result)
314
315
  result = MoveText.new(val[0])
315
316
  result
316
317
  end
317
318
  .,.,
318
319
 
319
- module_eval(<<'.,.,', 'pgn_parser.y', 66)
320
+ module_eval(<<'.,.,', 'pgn_parser.y', 68)
320
321
  def _reduce_15(val, _values, result)
321
- result = MoveText.new(val[0], nil, val[1])
322
+ result = MoveText.new(val[0], *val[1])
322
323
  result
323
324
  end
324
325
  .,.,
325
326
 
326
- module_eval(<<'.,.,', 'pgn_parser.y', 67)
327
+ module_eval(<<'.,.,', 'pgn_parser.y', 72)
327
328
  def _reduce_16(val, _values, result)
328
- result = MoveText.new(val[0], val[1])
329
+ result = [nil, val[0]]
329
330
  result
330
331
  end
331
332
  .,.,
332
333
 
333
- module_eval(<<'.,.,', 'pgn_parser.y', 68)
334
+ module_eval(<<'.,.,', 'pgn_parser.y', 73)
334
335
  def _reduce_17(val, _values, result)
335
- result = MoveText.new(val[0], val[1], val[2])
336
+ result = [val[0], nil]
336
337
  result
337
338
  end
338
339
  .,.,
339
340
 
340
- module_eval(<<'.,.,', 'pgn_parser.y', 69)
341
+ module_eval(<<'.,.,', 'pgn_parser.y', 74)
341
342
  def _reduce_18(val, _values, result)
342
- result = MoveText.new(val[0], val[2], val[1])
343
+ result = [val[0], val[1]]
343
344
  result
344
345
  end
345
346
  .,.,
346
347
 
347
- module_eval(<<'.,.,', 'pgn_parser.y', 72)
348
+ module_eval(<<'.,.,', 'pgn_parser.y', 75)
348
349
  def _reduce_19(val, _values, result)
349
- result = [val[0]]
350
+ result = [val[1], val[0]]
350
351
  result
351
352
  end
352
353
  .,.,
353
354
 
354
- module_eval(<<'.,.,', 'pgn_parser.y', 73)
355
+ module_eval(<<'.,.,', 'pgn_parser.y', 78)
355
356
  def _reduce_20(val, _values, result)
356
- result = val[0] << val[1]
357
+ result = [val[0]]
357
358
  result
358
359
  end
359
360
  .,.,
360
361
 
361
- module_eval(<<'.,.,', 'pgn_parser.y', 76)
362
+ module_eval(<<'.,.,', 'pgn_parser.y', 79)
362
363
  def _reduce_21(val, _values, result)
363
- result = [val[0]]
364
+ result = val[0] << val[1]
364
365
  result
365
366
  end
366
367
  .,.,
367
368
 
368
- module_eval(<<'.,.,', 'pgn_parser.y', 79)
369
+ module_eval(<<'.,.,', 'pgn_parser.y', 82)
369
370
  def _reduce_22(val, _values, result)
371
+ result = [val[0]]
372
+ result
373
+ end
374
+ .,.,
375
+
376
+ module_eval(<<'.,.,', 'pgn_parser.y', 85)
377
+ def _reduce_23(val, _values, result)
370
378
  # Right-recursive prepend reproduces the legacy whittle parser's
371
379
  # variation-order reversal on every parse. This keeps parsed-game
372
380
  # serialization byte-compatible with the legacy behavior; the quirk
@@ -377,8 +385,8 @@ module_eval(<<'.,.,', 'pgn_parser.y', 79)
377
385
  end
378
386
  .,.,
379
387
 
380
- module_eval(<<'.,.,', 'pgn_parser.y', 87)
381
- def _reduce_23(val, _values, result)
388
+ module_eval(<<'.,.,', 'pgn_parser.y', 93)
389
+ def _reduce_24(val, _values, result)
382
390
  result = val[1]
383
391
  result
384
392
  end
data/lib/pgn/pgn_parser.y CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class PGN::PgnParser
2
4
 
3
5
  token STRING COMMENT GAME_TERMINATION SAN_MOVE NAG MOVE_NUMBER TAG_NAME
@@ -64,10 +66,14 @@ rule
64
66
 
65
67
  san_move_annotated:
66
68
  SAN_MOVE { result = MoveText.new(val[0]) }
67
- | SAN_MOVE COMMENT { result = MoveText.new(val[0], nil, val[1]) }
68
- | SAN_MOVE annotation_list { result = MoveText.new(val[0], val[1]) }
69
- | SAN_MOVE annotation_list COMMENT { result = MoveText.new(val[0], val[1], val[2]) }
70
- | SAN_MOVE COMMENT annotation_list { result = MoveText.new(val[0], val[2], val[1]) }
69
+ | SAN_MOVE move_trailer { result = MoveText.new(val[0], *val[1]) }
70
+
71
+ # [annotation_list, comment], in whichever order they followed the move.
72
+ move_trailer:
73
+ COMMENT { result = [nil, val[0]] }
74
+ | annotation_list { result = [val[0], nil] }
75
+ | annotation_list COMMENT { result = [val[0], val[1]] }
76
+ | COMMENT annotation_list { result = [val[1], val[0]] }
71
77
 
72
78
  annotation_list:
73
79
  NAG { result = [val[0]] }
@@ -98,27 +104,26 @@ rule
98
104
  end
99
105
 
100
106
  def next_token
101
- t = @lexer.next_token
102
- return [false, false] unless t
103
- [translate_type(t.type), t.value]
107
+ pair = @lexer.next_token_pair
108
+ return [false, false] unless pair
109
+ type, value = pair
110
+ [translate_type(type), value]
104
111
  end
105
112
 
106
113
  private
107
114
 
115
+ # Punctuation tokens are racc'd by their literal character (taken from
116
+ # PGN::Lexer::LITERAL_BYTES, the single source of truth for those
117
+ # characters); everything else is racc'd by the upcased lexer symbol.
118
+ # A complete frozen lookup keeps this a plain hash read for every token
119
+ # instead of allocating two Strings (`to_s` + `upcase`) per token.
120
+ TOKEN_TRANSLATIONS = PGN::Lexer::LITERAL_BYTES.values.to_h.merge(
121
+ string: :STRING, comment: :COMMENT, game_termination: :GAME_TERMINATION,
122
+ san_move: :SAN_MOVE, nag: :NAG, move_number: :MOVE_NUMBER, tag_name: :TAG_NAME
123
+ ).freeze
124
+
108
125
  def translate_type(sym)
109
- case sym
110
- when :string then :STRING
111
- when :comment then :COMMENT
112
- when :game_termination then :GAME_TERMINATION
113
- when :san_move then :SAN_MOVE
114
- when :nag then :NAG
115
- when :move_number then :MOVE_NUMBER
116
- when :tag_name then :TAG_NAME
117
- when :lbracket then '['
118
- when :rbracket then ']'
119
- when :lparen then '('
120
- when :rparen then ')'
121
- else
126
+ TOKEN_TRANSLATIONS.fetch(sym) do
122
127
  raise "PGN::Lexer produced an unknown token type: #{sym.inspect}"
123
128
  end
124
129
  end
data/lib/pgn/position.rb CHANGED
@@ -81,7 +81,8 @@ module PGN
81
81
  move = PGN::Move.new(str, player)
82
82
  calculator = PGN::MoveCalculator.new(board, move)
83
83
 
84
- new_castling = castling - calculator.castling_restrictions
84
+ restrictions = calculator.castling_restrictions
85
+ new_castling = restrictions.empty? ? castling : castling - restrictions
85
86
  new_halfmove = if calculator.increment_halfmove?
86
87
  halfmove + 1
87
88
  else
@@ -106,7 +107,7 @@ module PGN
106
107
  # @return [Symbol] the next player to move
107
108
  #
108
109
  def next_player
109
- (PLAYERS - [player]).first
110
+ player == :white ? :black : :white
110
111
  end
111
112
 
112
113
  def inspect
data/lib/pgn/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module PGN
2
- VERSION = '1.0.0'.freeze
2
+ VERSION = '1.2.0'.freeze
3
3
  end
data/spec/parser_spec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'pry'
3
5
 
@@ -25,7 +27,7 @@ describe PGN do
25
27
  games.each do |game|
26
28
  expect(game.tags['White']).to eq 'Fool'
27
29
  expect(game.result).to eq '0-1'
28
- expect(game.moves.last).to eq 'Qh4#'
30
+ expect(game.moves.last).to eq 'Qh4#'
29
31
  end
30
32
  end
31
33
 
@@ -39,7 +41,7 @@ describe PGN do
39
41
  game = games.first
40
42
  expect(game.tags['White']).to eq 'Scholar'
41
43
  expect(game.result).to eq '1-0'
42
- expect(game.moves.last).to eq 'Qxf7#'
44
+ expect(game.moves.last).to eq 'Qxf7#'
43
45
  end
44
46
 
45
47
  it 'should handle multiline comments' do
@@ -47,7 +49,7 @@ describe PGN do
47
49
  game = games.first
48
50
  expect(game.tags['White']).to eq 'Scholar'
49
51
  expect(game.result).to eq '1-0'
50
- expect(game.moves.last).to eq 'Qxf7#'
52
+ expect(game.moves.last).to eq 'Qxf7#'
51
53
  end
52
54
 
53
55
  it 'should handle nested comments' do
@@ -57,12 +59,6 @@ describe PGN do
57
59
  expect(game.moves.last).to eq 'Nf6'
58
60
  end
59
61
 
60
- it 'handles two annotations' do
61
- games = PGN.parse(File.read('./spec/pgn_files/two_annotations.pgn'))
62
- game = games.first
63
- expect(game.moves[1].annotation).to eq ['$2', '$11']
64
- end
65
-
66
62
  it 'returns empty array when no variations' do
67
63
  games = PGN.parse(File.read('./spec/pgn_files/variations.pgn'))
68
64
  game = games.first
@@ -84,13 +80,6 @@ describe PGN do
84
80
  expect(game.moves[-2].variations.first).to eq %w[f4 exf4]
85
81
  end
86
82
 
87
- it 'should handle empty variation moves' do
88
- games = PGN.parse(File.read('./spec/pgn_files/empty_variation_move.pgn'))
89
- game = games.first
90
- expect(game.result).to eq '*'
91
- expect(game.moves.last).to eq 'Ng5'
92
- end
93
-
94
83
  it 'should handle complex files' do
95
84
  games = PGN.parse(File.read('./spec/pgn_files/test.pgn'))
96
85
  game = games.first
@@ -103,7 +92,7 @@ describe PGN do
103
92
  expect(game.moves[35].variations.size).to eq 1
104
93
  variation = game.moves[35].variations[0]
105
94
  expect(variation.size).to eq 2
106
- expect(variation[0]).to eq 'exf3'
95
+ expect(variation[0]).to eq 'exf3'
107
96
  end
108
97
 
109
98
  it 'should handle files with starting position' do
@@ -133,26 +122,5 @@ describe PGN do
133
122
  expect { game.positions }.not_to raise_error
134
123
  expect(game.moves).not_to be_empty
135
124
  end
136
-
137
- it 'gets game comment' do
138
- games = PGN.parse(File.read('./spec/pgn_files/no_moves.pgn'))
139
- game = games.last
140
- expect(game.comment).to eq('{game comment}')
141
- end
142
-
143
- it 'tag_values with double quotes' do
144
- games = PGN.parse(File.read('./spec/pgn_files/doublequotes.pgn'))
145
- game = games.last
146
- expect(game.tags['Event']).to eq('IRT BLITZ "Sub Zonal"')
147
- end
148
-
149
- it 'set encoding' do
150
- file = File.read('./spec/pgn_files/specialcharacters.pgn')
151
- games = PGN.parse(file, Encoding::UTF_8)
152
- game1 = games.first
153
- game2 = games.last
154
- expect(game1.tags['WhiteTeam']).to eq('NARIÑO')
155
- expect(game2.tags['Site']).to eq('HOTEL CAFEIRA Calle 18 Nro. 5 – 38 Centro de Pereira – Risaralda')
156
- end
157
125
  end
158
126
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgn2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stacey Touset
@@ -133,6 +133,7 @@ extra_rdoc_files: []
133
133
  files:
134
134
  - ".github/workflows/ci.yml"
135
135
  - ".github/workflows/publish.yml"
136
+ - ".github/workflows/release.yml"
136
137
  - ".gitignore"
137
138
  - ".rspec"
138
139
  - ".rubocop.yml"
@@ -145,8 +146,10 @@ files:
145
146
  - bench/.keep
146
147
  - bench/IMPROVEMENTS.md
147
148
  - bench/baseline_moves.pre-optimization.txt
149
+ - bench/baseline_moves.pre-quickwins.txt
148
150
  - bench/baseline_moves.txt
149
151
  - bench/baseline_parse.pre-optimization.txt
152
+ - bench/baseline_parse.pre-quickwins.txt
150
153
  - bench/baseline_parse.racc.txt
151
154
  - bench/baseline_parse.txt
152
155
  - bench/profile_moves.rb
@@ -156,6 +159,7 @@ files:
156
159
  - docs/superpowers/plans/2026-08-12-to-pgn-serialization.md
157
160
  - docs/superpowers/plans/2026-08-13-whittle-to-racc-migration.md
158
161
  - docs/superpowers/specs/2026-08-12-to-pgn-serialization-design.md
162
+ - docs/superpowers/specs/2026-08-13-pgn-performance-quick-wins-design.md
159
163
  - examples/immortal_game.pgn
160
164
  - lib/pgn.rb
161
165
  - lib/pgn/board.rb