Class: Gameworks::Game
- Inherits:
-
Object
- Object
- Gameworks::Game
- Defined in:
- lib/gameworks/game.rb,
lib/gameworks/game_snapshot.rb
Defined Under Namespace
Classes: Snapshot
Constant Summary collapse
- TURN_TIME_LIMIT =
30
- DEFAULT_DELAY =
0.3
- STATE_INITIATING =
'initiating'
- STATE_IN_PLAY =
'in play'
- STATE_COMPLETED =
'completed'
Instance Attribute Summary collapse
-
#delay_time ⇒ Object
readonly
Returns the value of attribute delay_time.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#moves ⇒ Object
readonly
Returns the value of attribute moves.
-
#notifier ⇒ Object
readonly
Returns the value of attribute notifier.
-
#players ⇒ Object
readonly
Returns the value of attribute players.
-
#state ⇒ Object
readonly
Returns the value of attribute state.
Instance Method Summary collapse
- #active_players ⇒ Object
- #add_move(payload, player) ⇒ Object
- #add_player(payload = {}) ⇒ Object
- #as_json(for_player = nil) ⇒ Object
- #build_move(payload, player) ⇒ Object
- #delta(snapshot, for_player = nil) ⇒ Object
- #disqualify(player) ⇒ Object
- #end_game ⇒ Object
- #full? ⇒ Boolean
- #generate_uuid ⇒ Object
- #ignore_disqualified_players ⇒ Object
- #init_game ⇒ Object
-
#initialize(payload = {}) ⇒ Game
constructor
A new instance of Game.
- #move_legal?(move, player) ⇒ Boolean
- #player_changed?(player, snapshot, for_player = nil) ⇒ Boolean
- #player_class ⇒ Object
- #player_for_token(token) ⇒ Object
- #process_move(move, player) ⇒ Object
- #register_observer(cb) ⇒ Object
- #signal_turns ⇒ Object
- #snapshot ⇒ Object
- #snapshot_class ⇒ Object
- #snapshot_for_observer(token) ⇒ Object
- #start_if_ready ⇒ Object
- #to_json(for_player = nil) ⇒ Object
- #update_observers(end_game = false) ⇒ Object
- #waiting_on_moves? ⇒ Boolean
Constructor Details
#initialize(payload = {}) ⇒ Game
Returns a new instance of Game.
17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/gameworks/game.rb', line 17 def initialize(payload={}) @notifier = Notifier.new @players = [] @state = STATE_INITIATING @delay_time = payload['delay_time'] || DEFAULT_DELAY @turns = {} @observers = {} @fuses = {} @id = generate_uuid.split('-').first @moves = {} end |
Instance Attribute Details
#delay_time ⇒ Object (readonly)
Returns the value of attribute delay_time.
15 16 17 |
# File 'lib/gameworks/game.rb', line 15 def delay_time @delay_time end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
15 16 17 |
# File 'lib/gameworks/game.rb', line 15 def id @id end |
#moves ⇒ Object (readonly)
Returns the value of attribute moves.
15 16 17 |
# File 'lib/gameworks/game.rb', line 15 def moves @moves end |
#notifier ⇒ Object (readonly)
Returns the value of attribute notifier.
15 16 17 |
# File 'lib/gameworks/game.rb', line 15 def notifier @notifier end |
#players ⇒ Object (readonly)
Returns the value of attribute players.
15 16 17 |
# File 'lib/gameworks/game.rb', line 15 def players @players end |
#state ⇒ Object (readonly)
Returns the value of attribute state.
15 16 17 |
# File 'lib/gameworks/game.rb', line 15 def state @state end |
Instance Method Details
#active_players ⇒ Object
99 100 101 |
# File 'lib/gameworks/game.rb', line 99 def active_players raise NotImplementedError end |
#add_move(payload, player) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/gameworks/game.rb', line 124 def add_move(payload, player) @fuses[player].abort move, error = build_move(payload, player) return false, error unless move legal, error = move_legal?(move, player) return false, error unless legal moves[player] = move process_move(move, player) ignore_disqualified_players update_observers true end |
#add_player(payload = {}) ⇒ Object
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/gameworks/game.rb', line 79 def add_player(payload={}) return false if full? player = player_class.new(payload) return false unless player.valid? @players << player update_observers player end |
#as_json(for_player = nil) ⇒ Object
183 184 185 186 187 |
# File 'lib/gameworks/game.rb', line 183 def as_json(for_player=nil) { :id => id, :players => @players.map{ |player| player.as_json(for_player) }, :state => @state } end |
#build_move(payload, player) ⇒ Object
141 142 143 |
# File 'lib/gameworks/game.rb', line 141 def build_move(payload, player) raise NotImplementedError end |
#delta(snapshot, for_player = nil) ⇒ Object
57 58 59 60 61 |
# File 'lib/gameworks/game.rb', line 57 def delta(snapshot, for_player=nil) { :id => id, :players => @players.select{ |p| player_changed?(p, snapshot, for_player) }.map{ |p| p.as_json(for_player) }, :state => @state } end |
#disqualify(player) ⇒ Object
157 158 159 160 161 162 163 164 165 166 |
# File 'lib/gameworks/game.rb', line 157 def disqualify(player) player.disqualify! update_observers if @players.select { |p| !p.disqualified? }.size < 2 end_game elsif !waiting_on_moves? signal_turns end # else do nothing; waiting for other players end |
#end_game ⇒ Object
168 169 170 171 172 173 |
# File 'lib/gameworks/game.rb', line 168 def end_game @state = STATE_COMPLETED @fuses.values.each(&:abort) update_observers(true) @players.each{ |p| p.signal_turn(nil) } end |
#full? ⇒ Boolean
63 64 65 |
# File 'lib/gameworks/game.rb', line 63 def full? raise NotImplementedError end |
#generate_uuid ⇒ Object
95 96 97 |
# File 'lib/gameworks/game.rb', line 95 def generate_uuid SecureRandom.uuid end |
#ignore_disqualified_players ⇒ Object
103 104 105 |
# File 'lib/gameworks/game.rb', line 103 def ignore_disqualified_players @players.rotate! while @players.first.disqualified? end |
#init_game ⇒ Object
90 91 92 93 |
# File 'lib/gameworks/game.rb', line 90 def init_game @players.shuffle! @state = STATE_IN_PLAY end |
#move_legal?(move, player) ⇒ Boolean
145 146 147 |
# File 'lib/gameworks/game.rb', line 145 def move_legal?(move, player) raise NotImplementedError end |
#player_changed?(player, snapshot, for_player = nil) ⇒ Boolean
53 54 55 |
# File 'lib/gameworks/game.rb', line 53 def player_changed?(player, snapshot, for_player=nil) player.score != snapshot.player_scores[player] end |
#player_class ⇒ Object
67 68 69 |
# File 'lib/gameworks/game.rb', line 67 def player_class Gameworks::Player end |
#player_for_token(token) ⇒ Object
120 121 122 |
# File 'lib/gameworks/game.rb', line 120 def player_for_token(token) @turns.delete(token) end |
#process_move(move, player) ⇒ Object
149 150 151 |
# File 'lib/gameworks/game.rb', line 149 def process_move(move, player) raise NotImplementedError end |
#register_observer(cb) ⇒ Object
29 30 31 32 33 |
# File 'lib/gameworks/game.rb', line 29 def register_observer(cb) token = generate_uuid @observers[token] = [self.snapshot, cb] token end |
#signal_turns ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/gameworks/game.rb', line 107 def signal_turns moves.clear active_players.each do |player| token = generate_uuid @turns[token] = player # This may no longer be necessary, since we abort the players' fuses # when they submit turns in #add_move. @fuses[player].abort if @fuses[player] @fuses[player] = Gameworks::Fuse.new(TURN_TIME_LIMIT) { disqualify(player) } player.signal_turn(token) end end |
#snapshot ⇒ Object
179 180 181 |
# File 'lib/gameworks/game.rb', line 179 def snapshot snapshot_class.new(self) end |
#snapshot_class ⇒ Object
175 176 177 |
# File 'lib/gameworks/game.rb', line 175 def snapshot_class Gameworks::Game::Snapshot end |
#snapshot_for_observer(token) ⇒ Object
44 45 46 47 48 49 50 51 |
# File 'lib/gameworks/game.rb', line 44 def snapshot_for_observer(token) snapshot = nil if @observers.has_key?(token) snapshot, cb = @observers[token] @observers[token][0] = self.snapshot end snapshot end |
#start_if_ready ⇒ Object
71 72 73 74 75 76 77 |
# File 'lib/gameworks/game.rb', line 71 def start_if_ready if full? init_game signal_turns update_observers end end |
#to_json(for_player = nil) ⇒ Object
189 190 191 |
# File 'lib/gameworks/game.rb', line 189 def to_json(for_player=nil) as_json(for_player).to_json end |
#update_observers(end_game = false) ⇒ Object
35 36 37 38 39 40 41 42 |
# File 'lib/gameworks/game.rb', line 35 def update_observers(end_game = false) @observers.each do |token, (_, cb)| snapshot = snapshot_for_observer(token) cb.call(delta(snapshot).to_json) cb.succeed if end_game end notifier.push(self, to_json) end |
#waiting_on_moves? ⇒ Boolean
153 154 155 |
# File 'lib/gameworks/game.rb', line 153 def waiting_on_moves? (active_players - moves.keys).any? end |