Class: Dat::Game

Inherits:
Object
  • Object
show all
Defined in:
lib/dat/game.rb

Direct Known Subclasses

LogGame

Constant Summary collapse

START_WORD =
'DAT'
MIN_PLAYERS =
2

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(logger, opt = {}) ⇒ Game

Returns a new instance of Game.



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
# File 'lib/dat/game.rb', line 19

def initialize(logger, opt={})
  @logger = logger
  printable_opt = opt.clone
  printable_opt[:players] = printable_opt[:players].map(&:to_s)
  @logger.log("game = Dat::LogGame.new(#{printable_opt})", true)

  if !opt[:players] || opt[:players].size < MIN_PLAYERS
    raise InvalidGame, "Not enough players in the game."
  else
    num_players = opt[:players].size
  end

  # Mix of player jids and bot objects
  @players = {}
  @player_order = opt[:players]
  opt[:players].each_with_index do |p, i|
    @players[p] = i
  end

  @dict = opt[:dict] || Dict.new
  @logic = Dat::Logic.new(@dict, opt)
  @min_size = @logic.min_size

  @last = opt[:start_word] || START_WORD
  @last.upcase!
  @played = [@last]
  @used = {@last => true}

  @start = Time.now
  @times = []

  @bot_moves = []
end

Instance Attribute Details

#dictObject (readonly)

Returns the value of attribute dict.



16
17
18
# File 'lib/dat/game.rb', line 16

def dict
  @dict
end

#lastObject (readonly)

Returns the value of attribute last.



16
17
18
# File 'lib/dat/game.rb', line 16

def last
  @last
end

#logicObject (readonly)

Returns the value of attribute logic.



16
17
18
# File 'lib/dat/game.rb', line 16

def logic
  @logic
end

#min_sizeObject (readonly)

Returns the value of attribute min_size.



16
17
18
# File 'lib/dat/game.rb', line 16

def min_size
  @min_size
end

#playedObject (readonly) Also known as: history

Returns the value of attribute played.



16
17
18
# File 'lib/dat/game.rb', line 16

def played
  @played
end

#usedObject (readonly)

Returns the value of attribute used.



16
17
18
# File 'lib/dat/game.rb', line 16

def used
  @used
end

#wonObject (readonly)

Returns the value of attribute won.



16
17
18
# File 'lib/dat/game.rb', line 16

def won
  @won
end

Instance Method Details

#display(num, time = false) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/dat/game.rb', line 86

def display(num, time=false)
  items = (num == :all ? @played : @played.last(num))
  size = items.size
  result = []
  items.each_with_index do |item, i|
    if time && i != 0
      result << "#{item} (#{@times[i-1]})"
    else
      result << "#{item}"
    end
    result << " -> " if i != size-1
  end
  result << " -> ???" if !@won
  result.join
end

#forfeit(player) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/dat/game.rb', line 53

def forfeit(player)
  @logger.log("game.forfeit(\"#{player}\")", true)

  idx = @players[player]
  @players.delete player
  @player_order[idx] = nil
  @player_order.compact!

  if @players.size == 1
    @won = @player_order[0]
  end

  msg = "Player #{idx+1} (#{player}) has forfeited."
  msg << " Player #{@players[@won]+1} (#{@won}) wins.\nOne word you could have played is '#{@logic.perturb(@last, @used)[0]}'." if @won
  msg
end

#next_move!(r = []) ⇒ Object



102
103
104
105
106
107
108
109
# File 'lib/dat/game.rb', line 102

def next_move!(r=[])
  next_player = whos_turn
  if next_player.respond_to?(:move)
    r << next_player.move
    next_move!(r) if !@won
  end
  r.join("\n")
end

#play(player, word) ⇒ Object

Raises:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/dat/game.rb', line 111

def play(player, word)
  @logger.log("game.play(\"#{player}\", \"#{word}\")", true)

  expected_player = whos_turn
  raise InvalidMove, "#{player} is not a valid player." if !@players[player]
  raise InvalidMove, "Cannot play out of turn. It is player #{@players[expected_player]}'s (#{expected_player}) move." if player != expected_player
  raise InvalidMove, "The game has already been won by #{@won}." if @won

  if word.size >= @min_size && @dict[word] && !@used[word] && @logic.leven(word, @last) == 1
    t = Time.now
    @times << ("%.1f" % (t-@start))
    @start = t
    @last = word
    @played << word
    @used[word] = true
    @dict[word].relatives.map { |r| @used[r.get] = true }

    if @logic.perturb(@last, @used).empty?
      @won = player
      raise WinningMove, "Player #{@players[@won]+1} (#{@won}) wins."
    end
  else
    if !@dict[word]
      raise InvalidMove, "'#{word}' is not a word."
    elsif word.size < @min_size
      raise InvalidMove, "'#{word}' is shorter than the minimum #{@min_size} characters."
    elsif @used[word]
      raise InvalidMove, "'#{word}' (or one of its relatives) has already been played."
    else
      raise InvalidMove, "'#{word}' must be within one edit distance of '#{@last}'"
    end
  end
end

#timeObject



70
71
72
# File 'lib/dat/game.rb', line 70

def time
  Time.now - @start
end

#to_sObject



82
83
84
# File 'lib/dat/game.rb', line 82

def to_s
  display(:all)
end

#turnObject



74
75
76
# File 'lib/dat/game.rb', line 74

def turn
  @played.size
end

#whos_turnObject



78
79
80
# File 'lib/dat/game.rb', line 78

def whos_turn
  @player_order[turn % @players.size]
end