lib: move some examples/* into specific subdirectories of their lib
[nit.git] / lib / bucketed_game.nit
index 40f4753..45a439c 100644 (file)
@@ -30,7 +30,13 @@ end
 # Something acting on the game from time to time
 class Bucketable[G: Game]
        super Turnable[G]
-       private var act_at: Int = 0
+       private var act_at: nullable Int = null
+
+       # Cancel the previously registered acting turn
+       #
+       # Once called, `self.do_turn` will not be invoked until `GameTurn::act_next`
+       # or `GameTurn::act_in` are called again.
+       fun cancel_act do act_at = null
 end
 
 # Optiomized organization of `Bucketable` instances
@@ -38,7 +44,7 @@ class Buckets[G: Game]
        super Turnable[G]
        type BUCKET: HashSet[Bucketable[G]]
 
-       private var buckets: Array[BUCKET]
+       private var buckets: Array[BUCKET] is noinit
 
        private var next_bucket: nullable BUCKET = null
        private var current_bucket_key: Int = -1
@@ -76,24 +82,29 @@ class Buckets[G: Game]
                current_bucket_key = key_for_tick(turn.tick)
                var current_bucket = buckets[current_bucket_key]
 
-               next_bucket = new HashSet[Bucketable[G]]
+               var next_bucket = new HashSet[Bucketable[G]]
 
                for e in current_bucket do
-                       if e.act_at == turn.tick then
-                               e.do_turn(turn)
-                       else if e.act_at > turn.tick and
-                               key_for_tick(e.act_at) == current_bucket_key
-                       then
-                               next_bucket.as(not null).add(e)
+                       var act_at = e.act_at
+                       if act_at != null then
+                               if turn.tick == act_at then
+                                       e.do_turn(turn)
+                               else if act_at > turn.tick and
+                                       key_for_tick(act_at) == current_bucket_key
+                               then
+                                       next_bucket.add(e)
+                               end
                        end
                end
 
-               buckets[current_bucket_key] = next_bucket.as(not null)
+               self.next_bucket = next_bucket
+               buckets[current_bucket_key] = next_bucket
        end
 end
 
 # Game related event
-class GameEvent
+interface GameEvent
+       fun apply( game : ThinGame ) is abstract
 end
 
 # Event raised at the first turn
@@ -103,14 +114,14 @@ end
 
 # Game logic on the client
 class ThinGame
-       var tick: Int protected writable = 0
+       var tick: Int = 0 is protected writable
 end
 
 # Game turn on the client
 class ThinGameTurn[G: ThinGame]
-       var tick: Int protected writable = 0
+       var tick: Int = 0 is protected writable
 
-       var events: List[GameEvent] protected writable = new List[GameEvent]
+       var events: List[GameEvent] = new List[GameEvent] is protected writable
 
        init (t: Int) do tick = t
 end
@@ -135,6 +146,12 @@ class GameTurn[G: Game]
        do
                game.buckets.add_at(e, tick + t)
        end
+
+       fun add_event( event : GameEvent )
+       do
+               event.apply( game )
+               events.add( event )
+       end
 end
 
 # Full game logic
@@ -144,6 +161,11 @@ class Game
 
        var buckets: Buckets[G] = new Buckets[G]
 
+       # Last turn executed in this game
+       # Can be used to consult the latest events (by the display for example),
+       # but cannot be used to add new Events.
+       var last_turn: nullable ThinGameTurn[G] = null
+
        init do end
 
        fun do_turn: GameTurn[G]
@@ -154,6 +176,8 @@ class Game
                buckets.do_turn(turn)
                do_post_turn(turn)
 
+               last_turn = turn
+
                tick += 1
 
                return turn