1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2011-2013 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Provides basic game logic utilities using buckets to coordinate and
18 # optimize actions on game turn ends. Supports both action at each
19 # end of turn as well as actions on some end of turns.
21 # Allows for fast support of a large number of entities with rare actions,
22 # such as a forest with many individual trees.
25 # Something acting on the game
26 class Turnable[G
: Game]
27 fun do_turn
(turn
: GameTurn[G
]) is abstract
30 # Something acting on the game from time to time
31 class Bucketable[G
: Game]
33 private var act_at
: Int = 0
36 # Optiomized organization of `Bucketable` instances
37 class Buckets[G
: Game]
39 type BUCKET: HashSet[Bucketable[G
]]
41 private var buckets
: Array[BUCKET]
43 private var next_bucket
: nullable BUCKET = null
44 private var current_bucket_key
: Int = -1
49 buckets
= new Array[BUCKET].with_capacity
(n_buckets
)
51 for b
in [0 .. n_buckets
[do
52 buckets
[b
] = new HashSet[Bucketable[G
]]
56 fun add_at
(e
: Bucketable[G
], at_tick
: Int)
58 var at_key
= key_for_tick
(at_tick
)
60 if at_key
== current_bucket_key
then
61 next_bucket
.as(not null).add
(e
)
63 buckets
[at_key
].add
(e
)
69 private fun key_for_tick
(at_tick
: Int): Int
71 return at_tick
% buckets
.length
74 redef fun do_turn
(turn
: GameTurn[G
])
76 current_bucket_key
= key_for_tick
(turn
.tick
)
77 var current_bucket
= buckets
[current_bucket_key
]
79 next_bucket
= new HashSet[Bucketable[G
]]
81 for e
in current_bucket
do
82 if e
.act_at
== turn
.tick
then
84 else if e
.act_at
> turn
.tick
and
85 key_for_tick
(e
.act_at
) == current_bucket_key
87 next_bucket
.as(not null).add
(e
)
91 buckets
[current_bucket_key
] = next_bucket
.as(not null)
97 fun apply
( game
: ThinGame ) is abstract
100 # Event raised at the first turn
105 # Game logic on the client
107 var tick
: Int protected writable = 0
110 # Game turn on the client
111 class ThinGameTurn[G
: ThinGame]
112 var tick
: Int protected writable = 0
114 var events
: List[GameEvent] protected writable = new List[GameEvent]
116 init (t
: Int) do tick
= t
119 # Game turn on the full logic
120 class GameTurn[G
: Game]
121 super ThinGameTurn[G
]
130 fun act_next
(e
: Bucketable[G
])
132 game
.buckets
.add_at
(e
, tick
+ 1)
135 fun act_in
(e
: Bucketable[G
], t
: Int)
137 game
.buckets
.add_at
(e
, tick
+ t
)
140 fun add_event
( event
: GameEvent )
152 var buckets
: Buckets[G
] = new Buckets[G
]
154 # Last turn executed in this game
155 # Can be used to consult the latest events (by the display for example),
156 # but cannot be used to add new Events.
157 var last_turn
: nullable ThinGameTurn[G
] = null
161 fun do_turn
: GameTurn[G
]
163 var turn
= new GameTurn[G
](self)
166 buckets
.do_turn
(turn
)
176 fun do_pre_turn
(turn
: GameTurn[G
]) do end
177 fun do_post_turn
(turn
: GameTurn[G
]) do end