-
Notifications
You must be signed in to change notification settings - Fork 0
/
game.go
98 lines (88 loc) · 2.34 KB
/
game.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package internal
import (
"fmt"
E "github.com/ionous/sashimi/event"
G "github.com/ionous/sashimi/game"
"github.com/ionous/sashimi/meta"
"github.com/ionous/sashimi/util/ident"
)
type Game struct {
Model meta.Model
RuntimeCore
Queue *ActionQueue
}
func NewGame(core RuntimeCore, m meta.Model) *Game {
g := &Game{
m,
core,
nil,
}
g.Queue = NewActionQueue(g)
return g
}
func (g *Game) newPlay(data *RuntimeAction, hint ident.Id) G.Play {
return &GameEventAdapter{Game: g, data: data, hint: hint}
}
var lastRandom int
func (g *Game) Random(exclusiveMax int) int {
n := g.Rand.Intn(exclusiveMax)
if n == lastRandom {
n = (n + 1) % exclusiveMax
}
lastRandom = n
return n
}
// target: class or instance id
// note: we get dispatch multiple times for each event:
// on the capture, target, and bubble cycles.
func (g *Game) dispatch(evt E.IEvent, target ident.Id) (err error) {
if src, ok := g.Model.GetEvent(evt.Id()); ok {
if ls, ok := src.GetListeners(true); ok {
err = E.Capture(evt, NewGameListeners(g, evt, target, ls))
}
if err == nil {
if ls, ok := src.GetListeners(false); ok {
err = E.Bubble(evt, NewGameListeners(g, evt, target, ls))
}
}
}
return
}
func (g *Game) QueueAction(data *RuntimeAction) {
future := &QueuedAction{data: data}
g.Queue.Enqueue(future)
}
func (g *Game) ProcessActions() error {
return g.Queue.ProcessActions(g)
}
// NewRuntimeAction: captures an action and bunch of nouns.
// TODO: unwind this... possibly now merege this with the go bits....
func (g *Game) NewRuntimeAction(action meta.Action, nouns ...ident.Id,
) (ret *RuntimeAction, err error,
) {
types := action.GetNouns()
switch diff := len(nouns) - len(types); {
case diff < 0:
err = fmt.Errorf("too few nouns specified for '%s', %d", action, diff)
case diff > 0:
err = fmt.Errorf("too many nouns specified for '%s', +%d", action, diff)
default:
objs := make([]meta.Instance, len(types))
for i, class := range types {
noun := nouns[i]
if gobj, ok := g.Model.GetInstance(noun); !ok {
err = InstanceNotFound(noun.String())
break
} else if !g.Model.AreCompatible(gobj.GetParentClass(), class) {
err = fmt.Errorf("type mismatch %v is %v expected %v", noun, gobj.GetParentClass(), class)
break
} else {
objs[i] = gobj
}
}
if err == nil {
ret = NewRuntimeAction(action, objs)
}
}
return ret, err
}