Go で書き直した Ikemen
修订版 | 69c6b071d0f95f00f038e2d1741857babaf7b623 (tree) |
---|---|
时间 | 2016-12-12 00:20:43 |
作者 | SUEHIRO <supersuehiro@user...> |
Commiter | SUEHIRO |
ステートコントローラーのバイトコードを考えた
@@ -56,11 +56,7 @@ const ( | ||
56 | 56 | type OpCode byte |
57 | 57 | |
58 | 58 | const ( |
59 | - OC_var0 OpCode = 0 | |
60 | - OC_sysvar0 OpCode = 60 | |
61 | - OC_fvar0 OpCode = 65 | |
62 | - OC_sysfvar0 OpCode = 105 | |
63 | - OC_var OpCode = iota + 110 | |
59 | + OC_var OpCode = iota + 110 | |
64 | 60 | OC_sysvar |
65 | 61 | OC_fvar |
66 | 62 | OC_sysfvar |
@@ -190,6 +186,9 @@ const ( | ||
190 | 186 | OC_hitvel_y |
191 | 187 | OC_roundno |
192 | 188 | OC_roundsexisted |
189 | + OC_matchno | |
190 | + OC_ishometeam | |
191 | + OC_tickspersecond | |
193 | 192 | OC_parent |
194 | 193 | OC_root |
195 | 194 | OC_helper |
@@ -201,7 +200,12 @@ const ( | ||
201 | 200 | OC_p2 |
202 | 201 | OC_const_ |
203 | 202 | OC_gethitvar_ |
203 | + OC_stagevar_ | |
204 | 204 | OC_ex_ |
205 | + OC_var0 OpCode = 0 | |
206 | + OC_sysvar0 OpCode = 60 | |
207 | + OC_fvar0 OpCode = 65 | |
208 | + OC_sysfvar0 OpCode = 105 | |
205 | 209 | ) |
206 | 210 | const ( |
207 | 211 | OC_const_data_life OpCode = iota |
@@ -329,6 +333,11 @@ const ( | ||
329 | 333 | OC_gethitvar_fall_envshake_phase |
330 | 334 | ) |
331 | 335 | const ( |
336 | + OC_stagevar_info_author OpCode = iota | |
337 | + OC_stagevar_info_displayname | |
338 | + OC_stagevar_info_name | |
339 | +) | |
340 | +const ( | |
332 | 341 | OC_ex_name OpCode = iota |
333 | 342 | OC_ex_authorname |
334 | 343 | OC_ex_p2name |
@@ -350,15 +359,6 @@ const ( | ||
350 | 359 | OC_ex_loseko |
351 | 360 | OC_ex_losetime |
352 | 361 | OC_ex_drawgame |
353 | - OC_ex_matchno | |
354 | - OC_ex_ishometeam | |
355 | - OC_ex_tickspersecond | |
356 | - OC_ex_stagevar_ | |
357 | -) | |
358 | -const ( | |
359 | - OC_ex_stagevar_info_author OpCode = iota | |
360 | - OC_ex_stagevar_info_displayname | |
361 | - OC_ex_stagevar_info_name | |
362 | 362 | ) |
363 | 363 | |
364 | 364 | type StringPool struct { |
@@ -385,11 +385,16 @@ func (sp *StringPool) Add(s string) int { | ||
385 | 385 | type BytecodeExp []OpCode |
386 | 386 | |
387 | 387 | func (be *BytecodeExp) appendFloat(f float32) { |
388 | - *be = append(append(*be, OC_float), | |
389 | - (*(*[4]OpCode)(unsafe.Pointer(&f)))[:]...) | |
388 | + *be = append(*be, (*(*[4]OpCode)(unsafe.Pointer(&f)))[:]...) | |
390 | 389 | } |
391 | 390 | func (be *BytecodeExp) appendInt(i int32) { |
392 | - *be = append(append(*be, OC_int), (*(*[4]OpCode)(unsafe.Pointer(&i)))[:]...) | |
391 | + *be = append(*be, (*(*[4]OpCode)(unsafe.Pointer(&i)))[:]...) | |
392 | +} | |
393 | +func (be BytecodeExp) toF() float32 { | |
394 | + return *(*float32)(unsafe.Pointer(&be[0])) | |
395 | +} | |
396 | +func (be BytecodeExp) toI() int32 { | |
397 | + return *(*int32)(unsafe.Pointer(&be[0])) | |
393 | 398 | } |
394 | 399 | func (be *BytecodeExp) AppendValue(t ValueType, v float64) (ok bool) { |
395 | 400 | if math.IsNaN(v) { |
@@ -397,11 +402,13 @@ func (be *BytecodeExp) AppendValue(t ValueType, v float64) (ok bool) { | ||
397 | 402 | } |
398 | 403 | switch t { |
399 | 404 | case VT_Float: |
405 | + *be = append(*be, OC_float) | |
400 | 406 | be.appendFloat(float32(v)) |
401 | 407 | case VT_Int: |
402 | 408 | if v >= -128 || v <= 127 { |
403 | 409 | *be = append(*be, OC_int8, OpCode(v)) |
404 | 410 | } else { |
411 | + *be = append(*be, OC_int) | |
405 | 412 | be.appendInt(int32(v)) |
406 | 413 | } |
407 | 414 | case VT_Bool: |
@@ -415,11 +422,79 @@ func (be *BytecodeExp) AppendValue(t ValueType, v float64) (ok bool) { | ||
415 | 422 | } |
416 | 423 | return true |
417 | 424 | } |
425 | +func (be BytecodeExp) run(c *Char) (t ValueType, v float64) { | |
426 | + unimplemented() | |
427 | + return VT_Int, 0 | |
428 | +} | |
429 | +func (be BytecodeExp) eval(c *Char) float64 { | |
430 | + _, v := be.run(c) | |
431 | + return v | |
432 | +} | |
433 | + | |
434 | +type StateController interface { | |
435 | + Run(c *Char) (changeState bool) | |
436 | +} | |
437 | + | |
438 | +const ( | |
439 | + SCID_trigger byte = 0 | |
440 | + SCID_const byte = 128 | |
441 | +) | |
442 | + | |
443 | +type StateControllerBase []byte | |
444 | + | |
445 | +func (scb StateControllerBase) beToExp(be ...BytecodeExp) []BytecodeExp { | |
446 | + return be | |
447 | +} | |
448 | +func (scb StateControllerBase) fToExp(f ...float32) (exp []BytecodeExp) { | |
449 | + for _, v := range f { | |
450 | + var be BytecodeExp | |
451 | + be.appendFloat(v) | |
452 | + exp = append(exp, be) | |
453 | + } | |
454 | + return | |
455 | +} | |
456 | +func (scb StateControllerBase) iToExp(i ...int32) (exp []BytecodeExp) { | |
457 | + for _, v := range i { | |
458 | + var be BytecodeExp | |
459 | + be.appendInt(v) | |
460 | + exp = append(exp, be) | |
461 | + } | |
462 | + return | |
463 | +} | |
464 | +func (scb *StateControllerBase) add(id byte, exp []BytecodeExp) { | |
465 | + *scb = append(*scb, id, byte(len(exp))) | |
466 | + for _, e := range exp { | |
467 | + l := int32(len(e)) | |
468 | + *scb = append(*scb, (*(*[4]byte)(unsafe.Pointer(&l)))[:]...) | |
469 | + *scb = append(*scb, (*(*[]byte)(unsafe.Pointer(&e)))...) | |
470 | + } | |
471 | +} | |
472 | +func (scb StateControllerBase) run(f func(byte, []BytecodeExp) bool) bool { | |
473 | + for i := 0; i < len(scb); { | |
474 | + id := scb[i] | |
475 | + i++ | |
476 | + n := scb[i] | |
477 | + i++ | |
478 | + exp := make([]BytecodeExp, n) | |
479 | + for m := byte(0); m < n; m++ { | |
480 | + l := *(*int32)(unsafe.Pointer(&scb[i])) | |
481 | + i += 4 | |
482 | + exp[m] = (*(*BytecodeExp)(unsafe.Pointer(&scb)))[i : i+int(l)] | |
483 | + i += int(l) | |
484 | + } | |
485 | + if !f(id, exp) { | |
486 | + return false | |
487 | + } | |
488 | + } | |
489 | + return true | |
490 | +} | |
418 | 491 | |
419 | 492 | type StateBytecode struct { |
420 | 493 | stateType StateType |
421 | 494 | moveType MoveType |
422 | 495 | physics StateType |
496 | + stateDef StateController | |
497 | + ctrls []StateController | |
423 | 498 | } |
424 | 499 | |
425 | 500 | func newStateBytecode() *StateBytecode { |
@@ -276,6 +276,8 @@ type Char struct { | ||
276 | 276 | playerno int |
277 | 277 | keyctrl bool |
278 | 278 | player bool |
279 | + sprpriority int32 | |
280 | + juggle int32 | |
279 | 281 | size CharSize |
280 | 282 | } |
281 | 283 |
@@ -533,3 +535,21 @@ func (c *Char) load(def string) error { | ||
533 | 535 | } |
534 | 536 | return nil |
535 | 537 | } |
538 | +func (c *Char) clearHitCount() { | |
539 | + unimplemented() | |
540 | +} | |
541 | +func (c *Char) clearMoveHit() { | |
542 | + unimplemented() | |
543 | +} | |
544 | +func (c *Char) clearHitDef() { | |
545 | + unimplemented() | |
546 | +} | |
547 | +func (c *Char) faceP2() { | |
548 | + unimplemented() | |
549 | +} | |
550 | +func (c *Char) setXV(xv float32) { | |
551 | + unimplemented() | |
552 | +} | |
553 | +func (c *Char) setYV(yv float32) { | |
554 | + unimplemented() | |
555 | +} |
@@ -8,6 +8,72 @@ import ( | ||
8 | 8 | |
9 | 9 | const kuuhaktokigou = " !=<>()|&+-*/%,[]^|:\"\t\r\n" |
10 | 10 | |
11 | +type stateDef StateControllerBase | |
12 | + | |
13 | +const ( | |
14 | + stateDef_hitcountpersist byte = iota + 1 | |
15 | + stateDef_movehitpersist | |
16 | + stateDef_hitdefpersist | |
17 | + stateDef_sprpriority | |
18 | + stateDef_facep2 | |
19 | + stateDef_juggle | |
20 | + stateDef_velset | |
21 | + stateDef_hitcountpersist_c = stateDef_hitcountpersist + SCID_const | |
22 | + stateDef_movehitpersist_c = stateDef_movehitpersist + SCID_const | |
23 | + stateDef_hitdefpersist_c = stateDef_hitdefpersist + SCID_const | |
24 | + stateDef_sprpriority_c = stateDef_sprpriority + SCID_const | |
25 | + stateDef_facep2_c = stateDef_facep2 + SCID_const | |
26 | + stateDef_juggle_c = stateDef_juggle + SCID_const | |
27 | + stateDef_velset_c = stateDef_velset + SCID_const | |
28 | +) | |
29 | + | |
30 | +func (sd stateDef) Run(c *Char) bool { | |
31 | + StateControllerBase(sd).run(func(id byte, exp []BytecodeExp) bool { | |
32 | + switch id { | |
33 | + case stateDef_hitcountpersist, stateDef_hitcountpersist_c: | |
34 | + if id == stateDef_hitcountpersist_c || exp[0].eval(c) == 0 { | |
35 | + c.clearHitCount() | |
36 | + } | |
37 | + case stateDef_movehitpersist, stateDef_movehitpersist_c: | |
38 | + if id == stateDef_movehitpersist_c || exp[0].eval(c) == 0 { | |
39 | + c.clearMoveHit() | |
40 | + } | |
41 | + case stateDef_hitdefpersist, stateDef_hitdefpersist_c: | |
42 | + if id == stateDef_hitdefpersist_c || exp[0].eval(c) == 0 { | |
43 | + c.clearHitDef() | |
44 | + } | |
45 | + case stateDef_sprpriority: | |
46 | + c.sprpriority = int32(exp[0].eval(c)) | |
47 | + case stateDef_sprpriority_c: | |
48 | + c.sprpriority = exp[0].toI() | |
49 | + case stateDef_facep2, stateDef_facep2_c: | |
50 | + if id == stateDef_facep2_c || exp[0].eval(c) != 0 { | |
51 | + c.faceP2() | |
52 | + } | |
53 | + case stateDef_juggle: | |
54 | + c.juggle = int32(exp[0].eval(c)) | |
55 | + case stateDef_juggle_c: | |
56 | + c.juggle = exp[0].toI() | |
57 | + case stateDef_velset: | |
58 | + c.setXV(float32(exp[0].eval(c))) | |
59 | + if len(exp) > 1 { | |
60 | + c.setYV(float32(exp[1].eval(c))) | |
61 | + if len(exp) > 2 { | |
62 | + exp[2].eval(c) | |
63 | + } | |
64 | + } | |
65 | + case stateDef_velset_c: | |
66 | + c.setXV(exp[0].toF()) | |
67 | + if len(exp) > 1 { | |
68 | + c.setYV(exp[1].toF()) | |
69 | + } | |
70 | + } | |
71 | + unimplemented() | |
72 | + return true | |
73 | + }) | |
74 | + return false | |
75 | +} | |
76 | + | |
11 | 77 | type ExpFunc func(out *BytecodeExp, in *string) (ValueType, float64, error) |
12 | 78 | type Compiler struct{ cmdl *CommandList } |
13 | 79 |
@@ -147,16 +213,34 @@ func (c *Compiler) typedExp(ef ExpFunc, out *BytecodeExp, in *string, | ||
147 | 213 | out.AppendValue(t, v) |
148 | 214 | return math.NaN(), nil |
149 | 215 | } |
150 | -func (c *Compiler) fullExpression(out *BytecodeExp, in *string, | |
151 | - vt ValueType) (float64, error) { | |
152 | - v, err := c.typedExp(c.expBoolOr, out, in, vt) | |
216 | +func (c *Compiler) argExpression(in *string, | |
217 | + vt ValueType) (BytecodeExp, float64, error) { | |
218 | + var be BytecodeExp | |
219 | + v, err := c.typedExp(c.expBoolOr, &be, in, vt) | |
153 | 220 | if err != nil { |
154 | - return 0, err | |
221 | + return nil, 0, err | |
222 | + } | |
223 | + oldin := *in | |
224 | + if token := c.tokenizer(in); len(token) > 0 { | |
225 | + if token == "," { | |
226 | + *in = oldin | |
227 | + } else { | |
228 | + return nil, 0, Error(token + "が不正です") | |
229 | + } | |
230 | + } | |
231 | + return be, v, nil | |
232 | +} | |
233 | +func (c *Compiler) fullExpression(in *string, | |
234 | + vt ValueType) (BytecodeExp, float64, error) { | |
235 | + var be BytecodeExp | |
236 | + v, err := c.typedExp(c.expBoolOr, &be, in, vt) | |
237 | + if err != nil { | |
238 | + return nil, 0, err | |
155 | 239 | } |
156 | 240 | if token := c.tokenizer(in); len(token) > 0 { |
157 | - return 0, Error(token + "が不正です") | |
241 | + return nil, 0, Error(token + "が不正です") | |
158 | 242 | } |
159 | - return v, nil | |
243 | + return be, v, nil | |
160 | 244 | } |
161 | 245 | func (c *Compiler) parseSection(lines []string, i *int, |
162 | 246 | sctrl func(name, data string) error) (IniSection, error) { |
@@ -243,8 +327,54 @@ func (c *Compiler) stateParam(is IniSection, name string, | ||
243 | 327 | } |
244 | 328 | return nil |
245 | 329 | } |
330 | +func (c *Compiler) scAdd(sc *StateControllerBase, id byte, | |
331 | + data string, vt ValueType, numArg int) error { | |
332 | + bes, vs := []BytecodeExp{}, []float64{} | |
333 | + for n := 1; n <= numArg; n++ { | |
334 | + var be BytecodeExp | |
335 | + var v float64 | |
336 | + var err error | |
337 | + if n < numArg { | |
338 | + be, v, err = c.argExpression(&data, vt) | |
339 | + } else { | |
340 | + be, v, err = c.fullExpression(&data, vt) | |
341 | + } | |
342 | + if err != nil { | |
343 | + return err | |
344 | + } | |
345 | + bes = append(bes, be) | |
346 | + vs = append(vs, v) | |
347 | + } | |
348 | + cns := true | |
349 | + for i, v := range vs { | |
350 | + if math.IsNaN(v) { | |
351 | + cns = false | |
352 | + } else { | |
353 | + bes[i].AppendValue(vt, v) | |
354 | + } | |
355 | + } | |
356 | + if cns { | |
357 | + if vt == VT_Float { | |
358 | + floats := make([]float32, len(vs)) | |
359 | + for i := range floats { | |
360 | + floats[i] = float32(vs[i]) | |
361 | + } | |
362 | + sc.add(id+SCID_const, sc.fToExp(floats...)) | |
363 | + } else { | |
364 | + ints := make([]int32, len(vs)) | |
365 | + for i := range ints { | |
366 | + ints[i] = int32(vs[i]) | |
367 | + } | |
368 | + sc.add(id+SCID_const, sc.iToExp(ints...)) | |
369 | + } | |
370 | + } else { | |
371 | + sc.add(id, bes) | |
372 | + } | |
373 | + return nil | |
374 | +} | |
246 | 375 | func (c *Compiler) stateDef(is IniSection, sbc *StateBytecode) error { |
247 | 376 | return c.stateSec(is, func() error { |
377 | + var sc StateControllerBase | |
248 | 378 | if err := c.stateParam(is, "type", func(data string) error { |
249 | 379 | if len(data) == 0 { |
250 | 380 | return Error("値が指定されていません") |
@@ -309,15 +439,99 @@ func (c *Compiler) stateDef(is IniSection, sbc *StateBytecode) error { | ||
309 | 439 | }); err != nil { |
310 | 440 | return err |
311 | 441 | } |
442 | + b := false | |
312 | 443 | if err := c.stateParam(is, "hitcountpersist", func(data string) error { |
313 | - var be BytecodeExp | |
314 | - v, err := c.fullExpression(&be, &data, VT_Bool) | |
315 | - unimplemented() | |
444 | + b = true | |
445 | + be, v, err := c.fullExpression(&data, VT_Bool) | |
446 | + if err != nil { | |
447 | + return err | |
448 | + } | |
449 | + if math.IsNaN(v) { | |
450 | + sc.add(stateDef_hitcountpersist, sc.beToExp(be)) | |
451 | + } else if v == 0 { // falseのときだけクリアする | |
452 | + sc.add(stateDef_hitcountpersist_c, nil) | |
453 | + } | |
316 | 454 | return nil |
317 | 455 | }); err != nil { |
318 | 456 | return err |
319 | 457 | } |
458 | + if !b { | |
459 | + sc.add(stateDef_hitcountpersist_c, nil) | |
460 | + } | |
461 | + b = false | |
462 | + if err := c.stateParam(is, "movehitpersist", func(data string) error { | |
463 | + b = true | |
464 | + be, v, err := c.fullExpression(&data, VT_Bool) | |
465 | + if err != nil { | |
466 | + return err | |
467 | + } | |
468 | + if math.IsNaN(v) { | |
469 | + sc.add(stateDef_movehitpersist, sc.beToExp(be)) | |
470 | + } else if v == 0 { // falseのときだけクリアする | |
471 | + sc.add(stateDef_movehitpersist_c, nil) | |
472 | + } | |
473 | + return nil | |
474 | + }); err != nil { | |
475 | + return err | |
476 | + } | |
477 | + if !b { | |
478 | + sc.add(stateDef_movehitpersist_c, nil) | |
479 | + } | |
480 | + b = false | |
481 | + if err := c.stateParam(is, "hitdefpersist", func(data string) error { | |
482 | + b = true | |
483 | + be, v, err := c.fullExpression(&data, VT_Bool) | |
484 | + if err != nil { | |
485 | + return err | |
486 | + } | |
487 | + if math.IsNaN(v) { | |
488 | + sc.add(stateDef_hitdefpersist, sc.beToExp(be)) | |
489 | + } else if v == 0 { // falseのときだけクリアする | |
490 | + sc.add(stateDef_hitdefpersist_c, nil) | |
491 | + } | |
492 | + return nil | |
493 | + }); err != nil { | |
494 | + return err | |
495 | + } | |
496 | + if !b { | |
497 | + sc.add(stateDef_hitdefpersist_c, nil) | |
498 | + } | |
499 | + if err := c.stateParam(is, "sprpriority", func(data string) error { | |
500 | + return c.scAdd(&sc, stateDef_sprpriority, data, VT_Int, 1) | |
501 | + }); err != nil { | |
502 | + return err | |
503 | + } | |
504 | + if err := c.stateParam(is, "facep2", func(data string) error { | |
505 | + be, v, err := c.fullExpression(&data, VT_Bool) | |
506 | + if err != nil { | |
507 | + return err | |
508 | + } | |
509 | + if math.IsNaN(v) { | |
510 | + sc.add(stateDef_facep2, sc.beToExp(be)) | |
511 | + } else if v != 0 { | |
512 | + sc.add(stateDef_facep2_c, nil) | |
513 | + } | |
514 | + return nil | |
515 | + }); err != nil { | |
516 | + return err | |
517 | + } | |
518 | + b = false | |
519 | + if err := c.stateParam(is, "juggle", func(data string) error { | |
520 | + b = true | |
521 | + return c.scAdd(&sc, stateDef_juggle, data, VT_Int, 1) | |
522 | + }); err != nil { | |
523 | + return err | |
524 | + } | |
525 | + if !b { | |
526 | + sc.add(stateDef_juggle_c, sc.iToExp(0)) | |
527 | + } | |
528 | + if err := c.stateParam(is, "velset", func(data string) error { | |
529 | + return c.scAdd(&sc, stateDef_velset, data, VT_Float, 3) | |
530 | + }); err != nil { | |
531 | + return err | |
532 | + } | |
320 | 533 | unimplemented() |
534 | + sbc.stateDef = stateDef(sc) | |
321 | 535 | return nil |
322 | 536 | }) |
323 | 537 | } |