Go で書き直した Ikemen
Revisão | d8bc640e1564e1f073a8a643ad8a6d3fbe3c22af (tree) |
---|---|
Hora | 2017-01-04 00:26:06 |
Autor | SUEHIRO <supersuehiro@user...> |
Commiter | SUEHIRO |
スタンドアロンで動かすために必要な common1 を書いていく
@@ -6,6 +6,9 @@ | ||
6 | 6 | # ignorehitpause{} を含んでいる if も実行される |
7 | 7 | # Explod は ignorehitpause を任意に指定できる |
8 | 8 | # ignorehitpause persistent(2) if 1 {} ブロックの特性を複数指定 if は最後に |
9 | +# VarSet, VarAdd は使えない代わりに := による代入を含む式を書ける | |
10 | +# 代入式は末尾に ; をつける | |
11 | + | |
9 | 12 | |
10 | 13 | [Statedef 0; type: S; physics: S; |
11 | 14 | sprpriority: 0;] |
@@ -15,7 +18,7 @@ if cond(Anim = 5, AnimTime = 0, Anim != 0) { | ||
15 | 18 | if Time = 0 { |
16 | 19 | VelSet{y: 0} |
17 | 20 | } |
18 | -if Time = 4 || abs(vel x) < cond(MajorVersion = 1, | |
21 | +if Time = 4 || abs(vel x) < ifelse(MajorVersion = 1, | |
19 | 22 | Const(movement.stand.friction.threshold), 2) { |
20 | 23 | VelSet{x: 0} |
21 | 24 | } |
@@ -23,6 +26,7 @@ if !alive { | ||
23 | 26 | ChangeState{value: 5050; ctrl: 0} |
24 | 27 | } |
25 | 28 | |
29 | + | |
26 | 30 | [Statedef 10; type: C; physics: C; |
27 | 31 | anim: 10;] |
28 | 32 | if Time = 0 { |
@@ -35,6 +39,7 @@ if AnimTime = 0 { | ||
35 | 39 | ChangeState{value: 11} |
36 | 40 | } |
37 | 41 | |
42 | + | |
38 | 43 | [Statedef 11; type: C; physics: C; |
39 | 44 | anim: 11; sprpriority: 0;] |
40 | 45 | if Anim = 6 && AnimTime = 0 { |
@@ -44,12 +49,14 @@ if abs(vel x) < Const(movement.crouch.friction.threshold) { | ||
44 | 49 | VelSet{x: 0} |
45 | 50 | } |
46 | 51 | |
52 | + | |
47 | 53 | [Statedef 12; type: S; physics: S; |
48 | 54 | anim: 12;] |
49 | 55 | if AnimTime = 0 { |
50 | 56 | ChangeState{value: 0} |
51 | 57 | } |
52 | 58 | |
59 | + | |
53 | 60 | [Statedef 20; type: S; physics: S; |
54 | 61 | sprpriority: 0;] |
55 | 62 | if command = "holdback" { |
@@ -67,3 +74,123 @@ if vel x > 0 { | ||
67 | 74 | } |
68 | 75 | } |
69 | 76 | |
77 | + | |
78 | +[Statedef 40; type: S; physics: S; | |
79 | + anim: 40; ctrl: 0; sprpriority: 1; facep2: 1;] | |
80 | +if Time = 0 { | |
81 | + sysvar(1) := 0; | |
82 | +} | |
83 | +if command = "holdback" { | |
84 | + sysvar(1) := -1; | |
85 | +} else if command = "holdfwd" { | |
86 | + sysvar(1) := 1; | |
87 | +} | |
88 | +if AnimTime = 0 { | |
89 | + if sysvar(1) = 0 { | |
90 | + VelSet{x: const(velocity.jump.neu.x)} | |
91 | + } else if sysvar(1) = 1 { | |
92 | + if prevstateno = 100 { | |
93 | + VelSet{x: const(velocity.runjump.fwd.x)} | |
94 | + } else { | |
95 | + VelSet{x: const(velocity.jump.fwd.x)} | |
96 | + } | |
97 | + } else { | |
98 | + VelSet{x: const(velocity.jump.back.x)} | |
99 | + } | |
100 | + VelSet{y: const(velocity.jump.y)} | |
101 | + ChangeState{value: 50; ctrl: 1} | |
102 | +} | |
103 | + | |
104 | + | |
105 | +[Statedef 45; type: A; physics: N; | |
106 | + ctrl: 0; velset: 0, 0;] | |
107 | +ChangeAnim{value: ifelse(SelfAnimExist(44), 44, 41)} | |
108 | +if Time = 0 { | |
109 | + sysvar(1) := 0; | |
110 | +} | |
111 | +if command = "holdback" { | |
112 | + sysvar(1) := -1; | |
113 | +} else if command = "holdfwd" { | |
114 | + sysvar(1) := 1; | |
115 | +} | |
116 | +if Time = 2 { | |
117 | + if sysvar(1) = 0 { | |
118 | + VelSet{x: const(velocity.airjump.neu.x)} | |
119 | + } else if sysvar(1) = 1 { | |
120 | + VelSet{x: const(velocity.airjump.fwd.x)} | |
121 | + } else { | |
122 | + VelSet{x: const(velocity.airjump.back.x)} | |
123 | + } | |
124 | + VelSet{y: const(velocity.airjump.y)} | |
125 | + ChangeState{value: 50; ctrl: 1} | |
126 | +} | |
127 | + | |
128 | + | |
129 | +[Statedef 50; type: A; physics: A;] | |
130 | +if Time = 0 { | |
131 | + sysvar(1) := 0; | |
132 | + ChangeAnim{value: cond((vel x) = 0, 41, ifelse((vel x) > 0, 42, 43))} | |
133 | +} | |
134 | +if Vel y > Const240p(-2) && SelfAnimExist(anim + 3) && anim = [41, 43] { | |
135 | + ChangeAnim{value: Anim + 3} | |
136 | +} | |
137 | + | |
138 | + | |
139 | +[Statedef 51; type: A; physics: A;] | |
140 | + | |
141 | + | |
142 | +[Statedef 52; type: S; physics: S; | |
143 | + ctrl: 0; anim: 47;] | |
144 | +if Time = 0 { | |
145 | + VelSet{y: 0} | |
146 | + PosSet{y: 0} | |
147 | +} else if Time = 3 { | |
148 | + CtrlSet{value: 1} | |
149 | +} | |
150 | +if MajorVersion = 1 && abs(vel x) < Const(movement.stand.friction.threshold){ | |
151 | + VelSet{x: 0} | |
152 | +} | |
153 | +if AnimTime = 0 { | |
154 | + ChangeState{value: 0; ctrl: 1} | |
155 | +} | |
156 | + | |
157 | + | |
158 | +[Statedef 100; type: S; physics: S; | |
159 | + anim: 100; sprpriority: 1;] | |
160 | +VelSet{x: const(velocity.run.fwd.x)} | |
161 | +AssertSpecial{flag: NoWalk; flag2: NoAutoTurn} | |
162 | +if command != "holdfwd" { | |
163 | + ChangeState{value: 0} | |
164 | +} | |
165 | + | |
166 | + | |
167 | +[Statedef 105; type: A; physics: A; | |
168 | + ctrl: 0; anim: 105; sprpriority: 1;] | |
169 | +if Time = 0 { | |
170 | + VelSet{x: const(velocity.run.back.x); y: const(velocity.run.back.y)} | |
171 | +}else if Time = 2 { | |
172 | + CtrlSet{value: 1} | |
173 | +} | |
174 | +if Vel Y > 0 && Pos Y >= 0 { | |
175 | + ChangeState{value: 106} | |
176 | +} | |
177 | + | |
178 | + | |
179 | +[Statedef 106; type: S; physics: S; | |
180 | + ctrl: 0; anim: 47;] | |
181 | +if MajorVersion = 1 && abs(vel x) < Const(movement.stand.friction.threshold) { | |
182 | + VelSet{x: 0} | |
183 | +} | |
184 | +if Time = 0 { | |
185 | + VelSet{y: 0} | |
186 | + PosSet{y: 0} | |
187 | +} else if Time = 2 { | |
188 | + if MajorVersion = 1 { | |
189 | + MakeDust{pos: 0, 0; spacing: 1} | |
190 | + } else { | |
191 | + MakeDust{pos: -5, -2; spacing: 1} | |
192 | + } | |
193 | +} else if Time = 7 { | |
194 | + ChangeState{value: 0; ctrl: 1} | |
195 | +} | |
196 | + |
@@ -953,6 +953,8 @@ func (be BytecodeExp) run(c *Char) BytecodeValue { | ||
953 | 953 | sys.bcStack.PushI(c.time()) |
954 | 954 | case OC_alive: |
955 | 955 | sys.bcStack.PushB(c.alive()) |
956 | + case OC_ctrl: | |
957 | + sys.bcStack.PushB(c.canCtrl()) | |
956 | 958 | case OC_random: |
957 | 959 | sys.bcStack.PushI(Rand(0, 999)) |
958 | 960 | case OC_roundstate: |
@@ -1019,17 +1021,28 @@ func (be BytecodeExp) run(c *Char) BytecodeValue { | ||
1019 | 1021 | sys.bcStack.PushF(c.bottomEdge()) |
1020 | 1022 | case OC_power: |
1021 | 1023 | sys.bcStack.PushI(c.getPower()) |
1024 | + case OC_roundsexisted: | |
1025 | + sys.bcStack.PushI(c.roundsExisted()) | |
1026 | + case OC_gametime: | |
1027 | + sys.bcStack.PushI(sys.gameTime) | |
1028 | + case OC_hitfall: | |
1029 | + sys.bcStack.PushB(c.ghv.fallf) | |
1022 | 1030 | case OC_ishelper: |
1023 | 1031 | *sys.bcStack.Top() = c.isHelper(*sys.bcStack.Top()) |
1024 | 1032 | case OC_numhelper: |
1025 | 1033 | *sys.bcStack.Top() = c.numHelper(*sys.bcStack.Top()) |
1026 | - case OC_roundsexisted: | |
1027 | - sys.bcStack.PushI(c.roundsExisted()) | |
1028 | 1034 | case OC_teammode: |
1029 | 1035 | sys.bcStack.PushB(sys.tmode[c.playerNo&1] == TeamMode(be[i])) |
1030 | 1036 | i++ |
1031 | - case OC_ctrl: | |
1032 | - sys.bcStack.PushB(c.canCtrl()) | |
1037 | + case OC_statetype: | |
1038 | + sys.bcStack.PushB(c.ss.sb.stateType == StateType(be[i])) | |
1039 | + i++ | |
1040 | + case OC_movetype: | |
1041 | + sys.bcStack.PushB(c.ss.sb.moveType == MoveType(be[i])) | |
1042 | + i++ | |
1043 | + case OC_hitdefattr: | |
1044 | + sys.bcStack.PushB(c.hitDefAttr(*(*int32)(unsafe.Pointer(&be[i])))) | |
1045 | + i += 4 | |
1033 | 1046 | case OC_st_: |
1034 | 1047 | be.run_st(c, &i) |
1035 | 1048 | case OC_const_: |
@@ -1459,6 +1472,13 @@ func (b StateBlock) Run(c *Char, ps []int32) (changeState bool) { | ||
1459 | 1472 | return false |
1460 | 1473 | } |
1461 | 1474 | |
1475 | +type StateExpr BytecodeExp | |
1476 | + | |
1477 | +func (se StateExpr) Run(c *Char, _ []int32) (changeState bool) { | |
1478 | + BytecodeExp(se).run(c) | |
1479 | + return false | |
1480 | +} | |
1481 | + | |
1462 | 1482 | type StateControllerBase []byte |
1463 | 1483 | |
1464 | 1484 | func newStateControllerBase() *StateControllerBase { |
@@ -3964,6 +3984,56 @@ func (sc envColor) Run(c *Char, _ []int32) bool { | ||
3964 | 3984 | return false |
3965 | 3985 | } |
3966 | 3986 | |
3987 | +type displayToClipboard StateControllerBase | |
3988 | + | |
3989 | +const ( | |
3990 | + displayToClipboard_params byte = iota | |
3991 | + displayToClipboard_text | |
3992 | +) | |
3993 | + | |
3994 | +func (sc displayToClipboard) Run(c *Char, _ []int32) bool { | |
3995 | + params := []interface{}{} | |
3996 | + StateControllerBase(sc).run(c, func(id byte, exp []BytecodeExp) bool { | |
3997 | + switch id { | |
3998 | + case displayToClipboard_params: | |
3999 | + for _, e := range exp { | |
4000 | + if bv := e.run(c); bv.t == VT_Float { | |
4001 | + params = append(params, bv.ToF()) | |
4002 | + } else { | |
4003 | + params = append(params, bv.ToI()) | |
4004 | + } | |
4005 | + } | |
4006 | + case displayToClipboard_text: | |
4007 | + sys.clipboardText[c.ss.sb.playerNo] = nil | |
4008 | + sys.appendToClipboard(c.ss.sb.playerNo, int(exp[0].evalI(c)), params...) | |
4009 | + } | |
4010 | + return true | |
4011 | + }) | |
4012 | + return false | |
4013 | +} | |
4014 | + | |
4015 | +type appendToClipboard displayToClipboard | |
4016 | + | |
4017 | +func (sc appendToClipboard) Run(c *Char, _ []int32) bool { | |
4018 | + params := []interface{}{} | |
4019 | + StateControllerBase(sc).run(c, func(id byte, exp []BytecodeExp) bool { | |
4020 | + switch id { | |
4021 | + case displayToClipboard_params: | |
4022 | + for _, e := range exp { | |
4023 | + if bv := e.run(c); bv.t == VT_Float { | |
4024 | + params = append(params, bv.ToF()) | |
4025 | + } else { | |
4026 | + params = append(params, bv.ToI()) | |
4027 | + } | |
4028 | + } | |
4029 | + case displayToClipboard_text: | |
4030 | + sys.appendToClipboard(c.ss.sb.playerNo, int(exp[0].evalI(c)), params...) | |
4031 | + } | |
4032 | + return true | |
4033 | + }) | |
4034 | + return false | |
4035 | +} | |
4036 | + | |
3967 | 4037 | type StateBytecode struct { |
3968 | 4038 | stateType StateType |
3969 | 4039 | moveType MoveType |
@@ -478,6 +478,10 @@ func (hd *HitDef) invalidate(stateType StateType) { | ||
478 | 478 | hd.reversal_attr |= -1 << 31 |
479 | 479 | hd.lhit = false |
480 | 480 | } |
481 | +func (hd *HitDef) testAttr(attr int32) bool { | |
482 | + attr &= hd.attr | |
483 | + return attr&int32(ST_MASK) != 0 && attr&^int32(ST_MASK)&^(-1<<31) != 0 | |
484 | +} | |
481 | 485 | |
482 | 486 | type GetHitVar struct { |
483 | 487 | hitBy [][2]int32 |
@@ -1881,3 +1885,6 @@ func (c *Char) canCtrl() bool { | ||
1881 | 1885 | func (c *Char) win() bool { |
1882 | 1886 | return sys.winTeam == c.playerNo&1 |
1883 | 1887 | } |
1888 | +func (c *Char) hitDefAttr(attr int32) bool { | |
1889 | + return c.ss.sb.moveType == MT_A && c.hitdef.testAttr(attr) | |
1890 | +} |
@@ -30,67 +30,69 @@ type Compiler struct { | ||
30 | 30 | func newCompiler() *Compiler { |
31 | 31 | c := &Compiler{} |
32 | 32 | c.scmap = map[string]scFunc{ |
33 | - "hitby": c.hitBy, | |
34 | - "nothitby": c.notHitBy, | |
35 | - "assertspecial": c.assertSpecial, | |
36 | - "playsnd": c.playSnd, | |
37 | - "changestate": c.changeState, | |
38 | - "selfstate": c.selfState, | |
39 | - "tagin": c.tagIn, | |
40 | - "tagout": c.tagOut, | |
41 | - "destroyself": c.destroySelf, | |
42 | - "changeanim": c.changeAnim, | |
43 | - "changeanim2": c.changeAnim2, | |
44 | - "helper": c.helper, | |
45 | - "ctrlset": c.ctrlSet, | |
46 | - "explod": c.explod, | |
47 | - "modifyexplod": c.modifyExplod, | |
48 | - "gamemakeanim": c.gameMakeAnim, | |
49 | - "posset": c.posSet, | |
50 | - "posadd": c.posAdd, | |
51 | - "velset": c.velSet, | |
52 | - "veladd": c.velAdd, | |
53 | - "velmul": c.velMul, | |
54 | - "palfx": c.palFX, | |
55 | - "allpalfx": c.allPalFX, | |
56 | - "bgpalfx": c.bgPalFX, | |
57 | - "afterimage": c.afterImage, | |
58 | - "afterimagetime": c.afterImageTime, | |
59 | - "hitdef": c.hitDef, | |
60 | - "reversaldef": c.reversalDef, | |
61 | - "projectile": c.projectile, | |
62 | - "width": c.width, | |
63 | - "sprpriority": c.sprPriority, | |
64 | - "varset": c.varSet, | |
65 | - "varadd": c.varAdd, | |
66 | - "parentvarset": c.parentVarSet, | |
67 | - "parentvaradd": c.parentVarAdd, | |
68 | - "turn": c.turn, | |
69 | - "targetfacing": c.targetFacing, | |
70 | - "targetbind": c.targetBind, | |
71 | - "bindtotarget": c.bindToTarget, | |
72 | - "targetlifeadd": c.targetLifeAdd, | |
73 | - "targetstate": c.targetState, | |
74 | - "targetvelset": c.targetVelSet, | |
75 | - "targetveladd": c.targetVelAdd, | |
76 | - "targetpoweradd": c.targetPowerAdd, | |
77 | - "targetdrop": c.targetDrop, | |
78 | - "lifeadd": c.lifeAdd, | |
79 | - "lifeset": c.lifeSet, | |
80 | - "poweradd": c.powerAdd, | |
81 | - "powerset": c.powerSet, | |
82 | - "hitvelset": c.hitVelSet, | |
83 | - "screenbound": c.screenBound, | |
84 | - "posfreeze": c.posFreeze, | |
85 | - "envshake": c.envShake, | |
86 | - "hitoverride": c.hitOverride, | |
87 | - "pause": c.pause, | |
88 | - "superpause": c.superPause, | |
89 | - "trans": c.trans, | |
90 | - "playerpush": c.playerPush, | |
91 | - "statetypeset": c.stateTypeSet, | |
92 | - "angledraw": c.angleDraw, | |
93 | - "envcolor": c.envColor, | |
33 | + "hitby": c.hitBy, | |
34 | + "nothitby": c.notHitBy, | |
35 | + "assertspecial": c.assertSpecial, | |
36 | + "playsnd": c.playSnd, | |
37 | + "changestate": c.changeState, | |
38 | + "selfstate": c.selfState, | |
39 | + "tagin": c.tagIn, | |
40 | + "tagout": c.tagOut, | |
41 | + "destroyself": c.destroySelf, | |
42 | + "changeanim": c.changeAnim, | |
43 | + "changeanim2": c.changeAnim2, | |
44 | + "helper": c.helper, | |
45 | + "ctrlset": c.ctrlSet, | |
46 | + "explod": c.explod, | |
47 | + "modifyexplod": c.modifyExplod, | |
48 | + "gamemakeanim": c.gameMakeAnim, | |
49 | + "posset": c.posSet, | |
50 | + "posadd": c.posAdd, | |
51 | + "velset": c.velSet, | |
52 | + "veladd": c.velAdd, | |
53 | + "velmul": c.velMul, | |
54 | + "palfx": c.palFX, | |
55 | + "allpalfx": c.allPalFX, | |
56 | + "bgpalfx": c.bgPalFX, | |
57 | + "afterimage": c.afterImage, | |
58 | + "afterimagetime": c.afterImageTime, | |
59 | + "hitdef": c.hitDef, | |
60 | + "reversaldef": c.reversalDef, | |
61 | + "projectile": c.projectile, | |
62 | + "width": c.width, | |
63 | + "sprpriority": c.sprPriority, | |
64 | + "varset": c.varSet, | |
65 | + "varadd": c.varAdd, | |
66 | + "parentvarset": c.parentVarSet, | |
67 | + "parentvaradd": c.parentVarAdd, | |
68 | + "turn": c.turn, | |
69 | + "targetfacing": c.targetFacing, | |
70 | + "targetbind": c.targetBind, | |
71 | + "bindtotarget": c.bindToTarget, | |
72 | + "targetlifeadd": c.targetLifeAdd, | |
73 | + "targetstate": c.targetState, | |
74 | + "targetvelset": c.targetVelSet, | |
75 | + "targetveladd": c.targetVelAdd, | |
76 | + "targetpoweradd": c.targetPowerAdd, | |
77 | + "targetdrop": c.targetDrop, | |
78 | + "lifeadd": c.lifeAdd, | |
79 | + "lifeset": c.lifeSet, | |
80 | + "poweradd": c.powerAdd, | |
81 | + "powerset": c.powerSet, | |
82 | + "hitvelset": c.hitVelSet, | |
83 | + "screenbound": c.screenBound, | |
84 | + "posfreeze": c.posFreeze, | |
85 | + "envshake": c.envShake, | |
86 | + "hitoverride": c.hitOverride, | |
87 | + "pause": c.pause, | |
88 | + "superpause": c.superPause, | |
89 | + "trans": c.trans, | |
90 | + "playerpush": c.playerPush, | |
91 | + "statetypeset": c.stateTypeSet, | |
92 | + "angledraw": c.angleDraw, | |
93 | + "envcolor": c.envColor, | |
94 | + "displaytoclipboard": c.displayToClipboard, | |
95 | + "appendtoclipboard": c.appendToClipboard, | |
94 | 96 | } |
95 | 97 | return c |
96 | 98 | } |
@@ -406,6 +408,80 @@ func (c *Compiler) attr(text string, hitdef bool) (int32, error) { | ||
406 | 408 | } |
407 | 409 | return flg, nil |
408 | 410 | } |
411 | +func (c *Compiler) trgAttr(in *string) (int32, error) { | |
412 | + flg := int32(0) | |
413 | + *in = strings.TrimSpace(*in) | |
414 | + i := strings.IndexAny(*in, kuuhaktokigou) | |
415 | + var att string | |
416 | + if i >= 0 { | |
417 | + att = (*in)[:i] | |
418 | + *in = strings.TrimSpace((*in)[i:]) | |
419 | + } else { | |
420 | + att = *in | |
421 | + *in = "" | |
422 | + } | |
423 | + for _, a := range att { | |
424 | + switch a { | |
425 | + case 'S', 's': | |
426 | + flg |= int32(ST_S) | |
427 | + case 'C', 'c': | |
428 | + flg |= int32(ST_C) | |
429 | + case 'A', 'a': | |
430 | + flg |= int32(ST_A) | |
431 | + default: | |
432 | + return 0, Error(att + "が不正な属性値です") | |
433 | + } | |
434 | + } | |
435 | + for len(*in) > 0 && (*in)[0] == ',' { | |
436 | + oldin := *in | |
437 | + *in = strings.TrimSpace((*in)[1:]) | |
438 | + i := strings.IndexAny(*in, kuuhaktokigou) | |
439 | + var att string | |
440 | + if i >= 0 { | |
441 | + att = (*in)[:i] | |
442 | + *in = strings.TrimSpace((*in)[i:]) | |
443 | + } else { | |
444 | + att = *in | |
445 | + *in = "" | |
446 | + } | |
447 | + switch strings.ToLower(att) { | |
448 | + case "na": | |
449 | + flg |= int32(AT_NA) | |
450 | + case "nt": | |
451 | + flg |= int32(AT_NT) | |
452 | + case "np": | |
453 | + flg |= int32(AT_NP) | |
454 | + case "sa": | |
455 | + flg |= int32(AT_SA) | |
456 | + case "st": | |
457 | + flg |= int32(AT_ST) | |
458 | + case "sp": | |
459 | + flg |= int32(AT_SP) | |
460 | + case "ha": | |
461 | + flg |= int32(AT_HA) | |
462 | + case "ht": | |
463 | + flg |= int32(AT_HT) | |
464 | + case "hp": | |
465 | + flg |= int32(AT_HP) | |
466 | + case "aa": | |
467 | + flg |= int32(AT_AA) | |
468 | + case "at": | |
469 | + flg |= int32(AT_AT) | |
470 | + case "ap": | |
471 | + flg |= int32(AT_AP) | |
472 | + case "n": | |
473 | + flg |= int32(AT_NA | AT_NT | AT_NP) | |
474 | + case "s": | |
475 | + flg |= int32(AT_SA | AT_ST | AT_SP) | |
476 | + case "h", "a": | |
477 | + flg |= int32(AT_HA | AT_HT | AT_HP) | |
478 | + default: | |
479 | + *in = oldin | |
480 | + return flg, nil | |
481 | + } | |
482 | + } | |
483 | + return flg, nil | |
484 | +} | |
409 | 485 | func (c *Compiler) kakkohiraku(in *string) error { |
410 | 486 | if c.tokenizer(in) != "(" { |
411 | 487 | return Error(c.token + "の次に'('がありません") |
@@ -657,15 +733,13 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
657 | 733 | c.token = c.tokenizer(in) |
658 | 734 | return bv, nil |
659 | 735 | } |
660 | - if !sys.ignoreMostErrors { | |
661 | - defer func() { c.usiroOp = false }() | |
662 | - } | |
663 | 736 | _var := func(sys, f bool) error { |
664 | 737 | bv1, err := c.oneArg(out, in, rd, false) |
665 | 738 | if err != nil { |
666 | 739 | return err |
667 | 740 | } |
668 | 741 | var oc OpCode |
742 | + c.token = c.tokenizer(in) | |
669 | 743 | set, _else := c.token == ":=", false |
670 | 744 | if !bv1.IsNone() && bv1.ToI() >= 0 { |
671 | 745 | switch [2]bool{sys, f} { |
@@ -751,6 +825,16 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
751 | 825 | } |
752 | 826 | return nil |
753 | 827 | } |
828 | + eqne2 := func(f func(not bool) error) error { | |
829 | + not, err := c.kyuushiki(in) | |
830 | + if err != nil { | |
831 | + return err | |
832 | + } | |
833 | + if err := f(not); err != nil { | |
834 | + return err | |
835 | + } | |
836 | + return nil | |
837 | + } | |
754 | 838 | var be1, be2, be3 BytecodeExp |
755 | 839 | var bv1, bv2, bv3 BytecodeValue |
756 | 840 | var n int32 |
@@ -889,21 +973,13 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
889 | 973 | return bvNone(), err |
890 | 974 | } |
891 | 975 | case "var": |
892 | - if err := _var(false, false); err != nil { | |
893 | - return bvNone(), err | |
894 | - } | |
976 | + return bvNone(), _var(false, false) | |
895 | 977 | case "fvar": |
896 | - if err := _var(false, true); err != nil { | |
897 | - return bvNone(), err | |
898 | - } | |
978 | + return bvNone(), _var(false, true) | |
899 | 979 | case "sysvar": |
900 | - if err := _var(true, false); err != nil { | |
901 | - return bvNone(), err | |
902 | - } | |
980 | + return bvNone(), _var(true, false) | |
903 | 981 | case "sysfvar": |
904 | - if err := _var(true, true); err != nil { | |
905 | - return bvNone(), err | |
906 | - } | |
982 | + return bvNone(), _var(true, true) | |
907 | 983 | case "ifelse", "cond": |
908 | 984 | cond := c.token == "cond" |
909 | 985 | if err := c.kakkohiraku(in); err != nil { |
@@ -971,10 +1047,12 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
971 | 1047 | bv = bv3 |
972 | 1048 | } |
973 | 1049 | } |
974 | - case "time": | |
1050 | + case "time", "statetime": | |
975 | 1051 | out.append(OC_time) |
976 | 1052 | case "alive": |
977 | 1053 | out.append(OC_alive) |
1054 | + case "ctrl": | |
1055 | + out.append(OC_ctrl) | |
978 | 1056 | case "random": |
979 | 1057 | out.append(OC_random) |
980 | 1058 | case "roundstate": |
@@ -1005,8 +1083,10 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
1005 | 1083 | case "animtime": |
1006 | 1084 | out.append(OC_animtime) |
1007 | 1085 | case "animelem": |
1008 | - if _, err = c.kyuushiki(in); err != nil { | |
1086 | + if not, err := c.kyuushiki(in); err != nil { | |
1009 | 1087 | return bvNone(), err |
1088 | + } else if not && !sys.ignoreMostErrors { | |
1089 | + return bvNone(), Error("animelemに != は使えません") | |
1010 | 1090 | } |
1011 | 1091 | if c.token == "-" { |
1012 | 1092 | return bvNone(), Error("マイナスが付くとエラーです") |
@@ -1161,6 +1241,14 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
1161 | 1241 | out.append(OC_bottomedge) |
1162 | 1242 | case "power": |
1163 | 1243 | out.append(OC_power) |
1244 | + case "roundsexisted": | |
1245 | + out.append(OC_roundsexisted) | |
1246 | + case "gametime": | |
1247 | + out.append(OC_gametime) | |
1248 | + case "hitfall": | |
1249 | + out.append(OC_hitfall) | |
1250 | + case "win": | |
1251 | + out.append(OC_ex_, OC_ex_win) | |
1164 | 1252 | case "ishelper": |
1165 | 1253 | if _, err := c.oneArg(out, in, rd, true, BytecodeInt(-1)); err != nil { |
1166 | 1254 | return bvNone(), err |
@@ -1171,10 +1259,11 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
1171 | 1259 | return bvNone(), err |
1172 | 1260 | } |
1173 | 1261 | out.append(OC_numhelper) |
1174 | - case "roundsexisted": | |
1175 | - out.append(OC_roundsexisted) | |
1176 | 1262 | case "teammode": |
1177 | 1263 | if err := eqne(func() error { |
1264 | + if len(c.token) == 0 { | |
1265 | + return Error("teammodeの値が指定されていません") | |
1266 | + } | |
1178 | 1267 | var tm TeamMode |
1179 | 1268 | switch c.token { |
1180 | 1269 | case "single": |
@@ -1191,10 +1280,90 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
1191 | 1280 | }); err != nil { |
1192 | 1281 | return bvNone(), err |
1193 | 1282 | } |
1194 | - case "win": | |
1195 | - out.append(OC_ex_, OC_ex_win) | |
1196 | - case "ctrl": | |
1197 | - out.append(OC_ctrl) | |
1283 | + case "statetype", "p2statetype": | |
1284 | + trname := c.token | |
1285 | + if err := eqne2(func(not bool) error { | |
1286 | + if len(c.token) == 0 { | |
1287 | + return Error(trname + "の値が指定されていません") | |
1288 | + } | |
1289 | + var st StateType | |
1290 | + switch c.token[0] { | |
1291 | + case 's': | |
1292 | + st = ST_S | |
1293 | + case 'c': | |
1294 | + st = ST_C | |
1295 | + case 'a': | |
1296 | + st = ST_A | |
1297 | + case 'l': | |
1298 | + st = ST_L | |
1299 | + default: | |
1300 | + return Error(c.token + "が無効な値です") | |
1301 | + } | |
1302 | + if trname == "p2statetype" { | |
1303 | + out.appendI32Op(OC_p2, 2+Btoi(not)) | |
1304 | + } | |
1305 | + out.append(OC_statetype, OpCode(st)) | |
1306 | + if not { | |
1307 | + out.append(OC_blnot) | |
1308 | + } | |
1309 | + return nil | |
1310 | + }); err != nil { | |
1311 | + return bvNone(), err | |
1312 | + } | |
1313 | + case "movetype", "p2movetype": | |
1314 | + trname := c.token | |
1315 | + if err := eqne2(func(not bool) error { | |
1316 | + if len(c.token) == 0 { | |
1317 | + return Error(trname + "の値が指定されていません") | |
1318 | + } | |
1319 | + var mt MoveType | |
1320 | + switch c.token[0] { | |
1321 | + case 'i': | |
1322 | + mt = MT_I | |
1323 | + case 'a': | |
1324 | + mt = MT_A | |
1325 | + case 'h': | |
1326 | + mt = MT_H | |
1327 | + default: | |
1328 | + return Error(c.token + "が無効な値です") | |
1329 | + } | |
1330 | + if trname == "p2movetype" { | |
1331 | + out.appendI32Op(OC_p2, 2+Btoi(not)) | |
1332 | + } | |
1333 | + out.append(OC_movetype, OpCode(mt)) | |
1334 | + if not { | |
1335 | + out.append(OC_blnot) | |
1336 | + } | |
1337 | + return nil | |
1338 | + }); err != nil { | |
1339 | + return bvNone(), err | |
1340 | + } | |
1341 | + case "hitdefattr": | |
1342 | + hda := func() error { | |
1343 | + if attr, err := c.trgAttr(in); err != nil { | |
1344 | + return err | |
1345 | + } else { | |
1346 | + out.appendI32Op(OC_hitdefattr, attr) | |
1347 | + } | |
1348 | + return nil | |
1349 | + } | |
1350 | + if sys.cgi[c.playerNo].ver[0] == 1 { | |
1351 | + if err := eqne(hda); err != nil { | |
1352 | + return bvNone(), err | |
1353 | + } | |
1354 | + } else { | |
1355 | + if not, err := c.kyuushiki(in); err != nil { | |
1356 | + if sys.ignoreMostErrors { | |
1357 | + out.appendValue(BytecodeBool(false)) | |
1358 | + } else { | |
1359 | + return bvNone(), err | |
1360 | + } | |
1361 | + } else if err := hda(); err != nil { | |
1362 | + return bvNone(), err | |
1363 | + } else if not && !sys.ignoreMostErrors { | |
1364 | + return bvNone(), Error("旧バージョンのためhitdefattrに != は使えません") | |
1365 | + } | |
1366 | + } | |
1198 | 1367 | case "abs": |
1199 | 1368 | if bv, err = c.mathFunc(out, in, rd, OC_abs, out.abs); err != nil { |
1200 | 1369 | return bvNone(), err |
@@ -1356,6 +1525,48 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
1356 | 1525 | if err := c.kakkotojiru(in); err != nil { |
1357 | 1526 | return bvNone(), err |
1358 | 1527 | } |
1528 | + case "const240p": | |
1529 | + if bv, err = c.oneArg(&be1, in, false, false); err != nil { | |
1530 | + return bvNone(), err | |
1531 | + } | |
1532 | + if bv.IsNone() { | |
1533 | + if rd { | |
1534 | + out.append(OC_rdreset) | |
1535 | + } | |
1536 | + out.append(be1...) | |
1537 | + out.appendValue(BytecodeFloat(1)) | |
1538 | + out.append(OC_mul) | |
1539 | + } else { | |
1540 | + out.mul(&bv, BytecodeFloat(1)) | |
1541 | + } | |
1542 | + case "const480p": | |
1543 | + if bv, err = c.oneArg(&be1, in, false, false); err != nil { | |
1544 | + return bvNone(), err | |
1545 | + } | |
1546 | + if bv.IsNone() { | |
1547 | + if rd { | |
1548 | + out.append(OC_rdreset) | |
1549 | + } | |
1550 | + out.append(be1...) | |
1551 | + out.appendValue(BytecodeFloat(0.5)) | |
1552 | + out.append(OC_mul) | |
1553 | + } else { | |
1554 | + out.mul(&bv, BytecodeFloat(0.5)) | |
1555 | + } | |
1556 | + case "const720p": | |
1557 | + if bv, err = c.oneArg(&be1, in, false, false); err != nil { | |
1558 | + return bvNone(), err | |
1559 | + } | |
1560 | + if bv.IsNone() { | |
1561 | + if rd { | |
1562 | + out.append(OC_rdreset) | |
1563 | + } | |
1564 | + out.append(be1...) | |
1565 | + out.appendValue(BytecodeFloat(0.25)) | |
1566 | + out.append(OC_mul) | |
1567 | + } else { | |
1568 | + out.mul(&bv, BytecodeFloat(0.25)) | |
1569 | + } | |
1359 | 1570 | case "const": |
1360 | 1571 | if err := c.kakkohiraku(in); err != nil { |
1361 | 1572 | return bvNone(), err |
@@ -1580,19 +1791,21 @@ func (c *Compiler) expPostNot(out *BytecodeExp, in *string) (BytecodeValue, | ||
1580 | 1791 | if err != nil { |
1581 | 1792 | return bvNone(), err |
1582 | 1793 | } |
1583 | - for c.token == "!" { | |
1584 | - c.usiroOp = true | |
1585 | - if bv.IsNone() { | |
1586 | - out.append(OC_blnot) | |
1587 | - } else { | |
1588 | - out.blnot(&bv) | |
1794 | + if sys.ignoreMostErrors { | |
1795 | + for c.token == "!" { | |
1796 | + c.usiroOp = true | |
1797 | + if bv.IsNone() { | |
1798 | + out.append(OC_blnot) | |
1799 | + } else { | |
1800 | + out.blnot(&bv) | |
1801 | + } | |
1802 | + c.token = c.tokenizer(in) | |
1589 | 1803 | } |
1590 | - c.token = c.tokenizer(in) | |
1591 | 1804 | } |
1592 | 1805 | if len(c.maeOp) == 0 { |
1593 | 1806 | opp := c.isOperator(c.token) |
1594 | 1807 | if opp == 0 { |
1595 | - if !c.usiroOp && c.token == "(" { | |
1808 | + if !sys.ignoreMostErrors || !c.usiroOp && c.token == "(" { | |
1596 | 1809 | return bvNone(), Error("演算子がありません") |
1597 | 1810 | } |
1598 | 1811 | oldtoken, oldin := c.token, *in |
@@ -4842,6 +5055,60 @@ func (c *Compiler) envColor(is IniSection, sc *StateControllerBase, | ||
4842 | 5055 | }) |
4843 | 5056 | return *ret, err |
4844 | 5057 | } |
5058 | +func (c *Compiler) displayToClipboardSub(is IniSection, | |
5059 | + sc *StateControllerBase) error { | |
5060 | + if err := c.stateParam(is, "params", func(data string) error { | |
5061 | + bes, err := c.exprs(data, VT_SFalse, 100000) | |
5062 | + if err != nil { | |
5063 | + return err | |
5064 | + } | |
5065 | + sc.add(displayToClipboard_params, bes) | |
5066 | + return nil | |
5067 | + }); err != nil { | |
5068 | + return err | |
5069 | + } | |
5070 | + b := false | |
5071 | + if err := c.stateParam(is, "text", func(data string) error { | |
5072 | + b = true | |
5073 | + _else := false | |
5074 | + if len(data) >= 2 && data[0] == '"' { | |
5075 | + data = data[1:] | |
5076 | + if i := strings.Index(data, "\""); i >= 0 { | |
5077 | + data = data[:i] | |
5078 | + } else { | |
5079 | + _else = true | |
5080 | + } | |
5081 | + } else { | |
5082 | + _else = true | |
5083 | + } | |
5084 | + if _else { | |
5085 | + return Error("\"で囲まれていません") | |
5086 | + } | |
5087 | + sc.add(displayToClipboard_text, | |
5088 | + sc.iToExp(int32(sys.stringPool[c.playerNo].Add(data)))) | |
5089 | + return nil | |
5090 | + }); err != nil { | |
5091 | + return err | |
5092 | + } | |
5093 | + if !b { | |
5094 | + return Error("textが指定されていません") | |
5095 | + } | |
5096 | + return nil | |
5097 | +} | |
5098 | +func (c *Compiler) displayToClipboard(is IniSection, sc *StateControllerBase, | |
5099 | + _ int8) (StateController, error) { | |
5100 | + ret, err := (*displayToClipboard)(sc), c.stateSec(is, func() error { | |
5101 | + return c.displayToClipboardSub(is, sc) | |
5102 | + }) | |
5103 | + return *ret, err | |
5104 | +} | |
5105 | +func (c *Compiler) appendToClipboard(is IniSection, sc *StateControllerBase, | |
5106 | + _ int8) (StateController, error) { | |
5107 | + ret, err := (*appendToClipboard)(sc), c.stateSec(is, func() error { | |
5108 | + return c.displayToClipboardSub(is, sc) | |
5109 | + }) | |
5110 | + return *ret, err | |
5111 | +} | |
4845 | 5112 | func (c *Compiler) stateCompile(bc *Bytecode, filename, def string) error { |
4846 | 5113 | var str string |
4847 | 5114 | fnz := filename |
@@ -5133,16 +5400,19 @@ func (c *Compiler) readString(line *string) (string, error) { | ||
5133 | 5400 | *line = (*line)[i+1:] |
5134 | 5401 | return s, nil |
5135 | 5402 | } |
5136 | -func (c *Compiler) readSentenceLine(line *string) (s string, err error) { | |
5403 | +func (c *Compiler) readSentenceLine(line *string) (s string, assign bool, | |
5404 | + err error) { | |
5137 | 5405 | c.token = "" |
5138 | 5406 | offset := 0 |
5139 | 5407 | for { |
5140 | 5408 | i := strings.IndexAny((*line)[offset:], ";#\"{}") |
5141 | 5409 | if i < 0 { |
5410 | + assign = assign || strings.Index((*line)[offset:], ":=") >= 0 | |
5142 | 5411 | s, *line = *line, "" |
5143 | 5412 | return |
5144 | 5413 | } |
5145 | 5414 | i += offset |
5415 | + assign = assign || strings.Index((*line)[offset:i], ":=") >= 0 | |
5146 | 5416 | switch (*line)[i] { |
5147 | 5417 | case ';', '{', '}': |
5148 | 5418 | c.token = (*line)[i : i+1] |
@@ -5152,7 +5422,7 @@ func (c *Compiler) readSentenceLine(line *string) (s string, err error) { | ||
5152 | 5422 | case '"': |
5153 | 5423 | tmp := (*line)[i+1:] |
5154 | 5424 | if _, err := c.readString(&tmp); err != nil { |
5155 | - return "", err | |
5425 | + return "", false, err | |
5156 | 5426 | } |
5157 | 5427 | offset = len(*line) - len(tmp) |
5158 | 5428 | continue |
@@ -5161,10 +5431,10 @@ func (c *Compiler) readSentenceLine(line *string) (s string, err error) { | ||
5161 | 5431 | } |
5162 | 5432 | return |
5163 | 5433 | } |
5164 | -func (c *Compiler) readSentence(line *string) (s string, err error) { | |
5165 | - sen, err := c.readSentenceLine(line) | |
5166 | - if err != nil { | |
5167 | - return "", err | |
5434 | +func (c *Compiler) readSentence(line *string) (s string, a bool, err error) { | |
5435 | + | |
5436 | + if s, a, err = c.readSentenceLine(line); err != nil { | |
5437 | + return | |
5168 | 5438 | } |
5169 | 5439 | for c.token == "" { |
5170 | 5440 | var ok bool |
@@ -5172,13 +5442,14 @@ func (c *Compiler) readSentence(line *string) (s string, err error) { | ||
5172 | 5442 | if !ok { |
5173 | 5443 | break |
5174 | 5444 | } |
5175 | - s, err := c.readSentenceLine(line) | |
5176 | - if err != nil { | |
5177 | - return "", err | |
5445 | + if sen, ass, err := c.readSentenceLine(line); err != nil { | |
5446 | + return "", false, err | |
5447 | + } else { | |
5448 | + s += "\n" + sen | |
5449 | + a = a || ass | |
5178 | 5450 | } |
5179 | - sen += "\n" + s | |
5180 | 5451 | } |
5181 | - return strings.TrimSpace(sen), nil | |
5452 | + return strings.TrimSpace(s), a, nil | |
5182 | 5453 | } |
5183 | 5454 | func (c *Compiler) statementEnd(line *string) error { |
5184 | 5455 | c.token = c.tokenizer(line) |
@@ -5201,7 +5472,7 @@ func (c *Compiler) readKeyValue(is IniSection, end string, | ||
5201 | 5472 | if err := c.needToken(":"); err != nil { |
5202 | 5473 | return err |
5203 | 5474 | } |
5204 | - data, err := c.readSentence(line) | |
5475 | + data, _, err := c.readSentence(line) | |
5205 | 5476 | if err != nil { |
5206 | 5477 | return err |
5207 | 5478 | } |
@@ -5214,7 +5485,7 @@ func (c *Compiler) subBlock(line *string, | ||
5214 | 5485 | switch c.token { |
5215 | 5486 | case "{": |
5216 | 5487 | case "if": |
5217 | - expr, err := c.readSentence(line) | |
5488 | + expr, _, err := c.readSentence(line) | |
5218 | 5489 | if err != nil { |
5219 | 5490 | return nil, err |
5220 | 5491 | } |
@@ -5326,7 +5597,35 @@ func (c *Compiler) stateBlock(line *string, bl *StateBlock, root bool) error { | ||
5326 | 5597 | } |
5327 | 5598 | c.scan(line) |
5328 | 5599 | continue |
5600 | + } else { | |
5601 | + otk := c.token | |
5602 | + expr, assign, err := c.readSentence(line) | |
5603 | + if err != nil { | |
5604 | + return err | |
5605 | + } | |
5606 | + expr = otk + " " + expr | |
5607 | + otk = c.token | |
5608 | + if stex, err := c.fullExpression(&expr, VT_SFalse); err != nil { | |
5609 | + return err | |
5610 | + } else { | |
5611 | + bl.ctrls = append(bl.ctrls, StateExpr(stex)) | |
5612 | + } | |
5613 | + c.token = otk | |
5614 | + if err := c.needToken(";"); err != nil { | |
5615 | + return err | |
5616 | + } | |
5617 | + if !assign { | |
5618 | + return Error("値が利用されない式") | |
5619 | + } | |
5620 | + if root { | |
5621 | + if err := c.statementEnd(line); err != nil { | |
5622 | + return err | |
5623 | + } | |
5624 | + } | |
5625 | + c.scan(line) | |
5626 | + continue | |
5329 | 5627 | } |
5628 | + case "varset", "varadd": | |
5330 | 5629 | } |
5331 | 5630 | break |
5332 | 5631 | } |
@@ -139,7 +139,7 @@ func scriptCommonInit(l *lua.LState) { | ||
139 | 139 | return 0 |
140 | 140 | }) |
141 | 141 | luaRegister(l, "setHomeTeam", func(l *lua.LState) int { |
142 | - tn := int32(numArg(l, 1)) | |
142 | + tn := int(numArg(l, 1)) | |
143 | 143 | if tn < 1 || tn > 2 { |
144 | 144 | l.RaiseError("チーム番号(%v)が不正です。", tn) |
145 | 145 | } |
@@ -1,6 +1,7 @@ | ||
1 | 1 | package main |
2 | 2 | |
3 | 3 | import ( |
4 | + "fmt" | |
4 | 5 | "github.com/go-gl/gl/v2.1/gl" |
5 | 6 | "github.com/go-gl/glfw/v3.2/glfw" |
6 | 7 | "github.com/timshannon/go-openal/openal" |
@@ -82,7 +83,8 @@ type System struct { | ||
82 | 83 | keyConfig []*KeyConfig |
83 | 84 | com [MaxSimul * 2]int32 |
84 | 85 | autolevel bool |
85 | - home int32 | |
86 | + home int | |
87 | + gameTime int32 | |
86 | 88 | match int32 |
87 | 89 | inputRemap [MaxSimul * 2]int |
88 | 90 | listenPort string |
@@ -133,6 +135,7 @@ type System struct { | ||
133 | 135 | envcol [3]int32 |
134 | 136 | envcol_time int32 |
135 | 137 | envcol_under bool |
138 | + clipboardText [MaxSimul * 2][]string | |
136 | 139 | } |
137 | 140 | |
138 | 141 | func (s *System) init(w, h int32) *lua.LState { |
@@ -240,6 +243,13 @@ func (s *System) setSF(gsf GlobalSpecialFlag) { | ||
240 | 243 | func (s *System) unsetSF(gsf GlobalSpecialFlag) { |
241 | 244 | s.specialFlag &^= gsf |
242 | 245 | } |
246 | +func (s *System) appendToClipboard(pn, sn int, a ...interface{}) { | |
247 | + spl := s.stringPool[pn].List | |
248 | + if sn >= 0 && sn < len(spl) { | |
249 | + s.clipboardText[pn] = append(s.clipboardText[pn], | |
250 | + strings.Split(fmt.Sprintf(spl[sn], a...), "\n")...) | |
251 | + } | |
252 | +} | |
243 | 253 | |
244 | 254 | type SelectChar struct { |
245 | 255 | def, name string |
@@ -488,7 +498,8 @@ func (l *Loader) loadChar(pn int) int { | ||
488 | 498 | sys.cgi[pn].palno = pal |
489 | 499 | } |
490 | 500 | if sys.cgi[pn].sff == nil { |
491 | - if l.code[pn], l.err = newCompiler().Compile(p.playerNo, cdef); l.err != nil { | |
501 | + if l.code[pn], l.err = | |
502 | + newCompiler().Compile(p.playerNo, cdef); l.err != nil { | |
492 | 503 | sys.chars[pn] = nil |
493 | 504 | return -1 |
494 | 505 | } |