upwords 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +83 -30
- data/exe/upwords +1 -1
- data/lib/upwords.rb +8 -4
- data/lib/upwords/board.rb +4 -12
- data/lib/upwords/cursor.rb +4 -4
- data/lib/upwords/game.rb +70 -232
- data/lib/upwords/move.rb +45 -30
- data/lib/upwords/move_manager.rb +11 -3
- data/lib/upwords/player.rb +55 -48
- data/lib/upwords/shape.rb +11 -2
- data/lib/upwords/ui.rb +360 -0
- data/lib/upwords/version.rb +1 -1
- data/lib/upwords/word.rb +10 -9
- metadata +3 -3
- data/lib/upwords/graphics.rb +0 -149
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c9bd9e51484e62844a28edd893d75677898ca58
|
4
|
+
data.tar.gz: a6d853e3009e62f02d20b0bca25ea295d7e15e62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d9708d7e8b1910c0662defce90876449ec30f459ad1caf210e4e95dc0f89fa391c2a9e9c4fa54caf6f527d0f7b85c75ad85b2abce0bfb7e585f90033f43c48f
|
7
|
+
data.tar.gz: 696b89a6feaf45026c0a7b94046d93c6eb03063c1f01a3d7b9d2ae8b3e7e6431a374c9f49f8656d6ddd34ebf3f986c442a251b70ad2eba943100ba929e4ab4ce
|
data/README.md
CHANGED
@@ -1,4 +1,38 @@
|
|
1
|
-
#
|
1
|
+
# Upwords - The Quick Stacking Word Game
|
2
|
+
|
3
|
+
## Getting Started
|
4
|
+
|
5
|
+
1. Install Upwords at the command prompt if you haven't yet:
|
6
|
+
|
7
|
+
$ gem install upwords
|
8
|
+
|
9
|
+
2. At the command prompt, start a new Upwords game:
|
10
|
+
|
11
|
+
$ upwords
|
12
|
+
|
13
|
+
3. Select the number of players:
|
14
|
+
|
15
|
+
How many players will play? (1-4)
|
16
|
+
3
|
17
|
+
|
18
|
+
4. Name each player and select if they are humans or computers:
|
19
|
+
|
20
|
+
What is Player 1's name? (Press enter to submit...)
|
21
|
+
Bob
|
22
|
+
Is Bob a computer? (y/n)
|
23
|
+
n
|
24
|
+
|
25
|
+
What is Player 2's name? (Press enter to submit...)
|
26
|
+
Nina
|
27
|
+
Is Nina a computer? (y/n)
|
28
|
+
n
|
29
|
+
|
30
|
+
What is Player 3's name? (Press enter to submit...)
|
31
|
+
Jack
|
32
|
+
Is Jack a computer? (y/n)
|
33
|
+
y
|
34
|
+
|
35
|
+
## Rules
|
2
36
|
|
3
37
|
Rules taken from: http://www.hasbro.com/common/instruct/04312.pdf
|
4
38
|
|
@@ -14,17 +48,11 @@ You score points for each letter in your word and every letter tile under
|
|
14
48
|
each letter of your word.Letters can be stacked five tiles high so your score
|
15
49
|
can really add up fast. Build words, stack letters, score high and have fun!
|
16
50
|
|
17
|
-
##
|
51
|
+
## Objective
|
18
52
|
|
19
53
|
Build words to score the most points.
|
20
54
|
|
21
|
-
##
|
22
|
-
|
23
|
-
Plastic gameboard 100 plastic letter tiles 4 plastic tile racks
|
24
|
-
|
25
|
-
4 rubber feet label sheet
|
26
|
-
|
27
|
-
## LETTER DISTRIBUTION
|
55
|
+
## Letter Distribution
|
28
56
|
|
29
57
|
| Letters | Amount |
|
30
58
|
| ------------- | --------- |
|
@@ -37,7 +65,7 @@ Plastic gameboard 100 plastic letter tiles 4 plastic tile racks
|
|
37
65
|
| A I O | 7 of each |
|
38
66
|
| E | 8 of each |
|
39
67
|
|
40
|
-
##
|
68
|
+
## Setup
|
41
69
|
|
42
70
|
- Turn all of the tiles letter-side down and mix them up to create a draw pile.
|
43
71
|
- Each player takes a rack.
|
@@ -46,7 +74,7 @@ Plastic gameboard 100 plastic letter tiles 4 plastic tile racks
|
|
46
74
|
word. See Rule 8 on page 5 for more information. Use the dictionary
|
47
75
|
to settle challenges only.
|
48
76
|
|
49
|
-
##
|
77
|
+
## Gameplay
|
50
78
|
|
51
79
|
### 1. Deciding Who Goes First
|
52
80
|
|
@@ -68,7 +96,7 @@ let your opponents see 1 your letters.
|
|
68
96
|
Whoever plays first must form a word of two letters or more that covers at least
|
69
97
|
one of the four game squares in the center of the gameboard.
|
70
98
|
|
71
|
-
### 4.
|
99
|
+
### 4. Basic Turn
|
72
100
|
|
73
101
|
On your turn, play one or more letter tiles, either to form a new word that connects to
|
74
102
|
a word already on the board, or to change a word already on the board to a different word.
|
@@ -79,7 +107,7 @@ the ones you played.
|
|
79
107
|
**IMPORTANT:** A word is legal and can be used in the game if it is in the dictionary and
|
80
108
|
it does not fall into any of the categories of illegal words listed in Rule 7 on page 5.
|
81
109
|
|
82
|
-
### 5.
|
110
|
+
### 5. How To Form Words
|
83
111
|
|
84
112
|
Figures 2 through 7 show a sequence of plays. Arrows point out the word or words
|
85
113
|
formed on each play. Point scores are given for each example. See Rule 6 on page
|
@@ -92,15 +120,40 @@ Build across using the letter "E" in DEAR to form the word NET as shown in Figur
|
|
92
120
|
The word ON is also formed reading down.You score points for all of the words
|
93
121
|
formed during your turn.
|
94
122
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
123
|
+
+----+----+----+----+----+----+
|
124
|
+
| | | | | | |
|
125
|
+
+----+----+----+----+----+----+
|
126
|
+
| | M | O | O |{D} | |
|
127
|
+
+----+---1+---1+---1+---1+----+
|
128
|
+
| | | | |{E} | |
|
129
|
+
+----+----+----+----+---1+----+
|
130
|
+
| | | | |{A} | |
|
131
|
+
+----+----+----+----+---1+----+
|
132
|
+
| | | | |{R} | |
|
133
|
+
+----+----+----+----+---1+----+
|
134
|
+
| | | | | | |
|
135
|
+
+----+----+----+----+----+----+
|
136
|
+
|
137
|
+
*Figure 2 - Score: 8 Points*
|
138
|
+
|
139
|
+
+----+----+----+----+----+----+
|
140
|
+
| | | | | | |
|
141
|
+
+----+----+----+----+----+----+
|
142
|
+
| | M | O |{O} | D | |
|
143
|
+
+----+---1+---1+---1+---1+----+
|
144
|
+
| | | |{N} |{E} |{T} |
|
145
|
+
+----+----+----+---1+---1+---1+
|
146
|
+
| | | | | A | |
|
147
|
+
+----+----+----+----+---1+----+
|
148
|
+
| | | | | R | |
|
149
|
+
+----+----+----+----+---1+----+
|
150
|
+
| | | | | | |
|
151
|
+
+----+----+----+----+----+----+
|
152
|
+
|
153
|
+
*Figure 3 - Score: 10 Points*
|
154
|
+
|
155
|
+
|
156
|
+
**NOTE:** Any letter in your word that is adjacent to another letter or letters on
|
104
157
|
the board must form a word. For example, in Figure 3, the letter "N" in NET is adjacent to
|
105
158
|
the letter "O" in MOOD, which forms the word ON.
|
106
159
|
|
@@ -147,7 +200,7 @@ makes it plural as shown in Figure 7. You score points for both words.
|
|
147
200
|
|
148
201
|
[FIGURE 7 | Score: 16 Points]
|
149
202
|
|
150
|
-
### 6.
|
203
|
+
### 6. How To Score Words
|
151
204
|
|
152
205
|
- You score 2 points per letter tile for any word formed with all letters
|
153
206
|
only one tile high (no letter in the word is stacked on top of another
|
@@ -178,7 +231,7 @@ makes it plural as shown in Figure 7. You score points for both words.
|
|
178
231
|
- At the end of the game, 5 points are subtracted from your score for
|
179
232
|
each letter tile you cannot play.
|
180
233
|
|
181
|
-
### 7.
|
234
|
+
### 7. Illegal Words
|
182
235
|
|
183
236
|
Any word that falls into any category listed below, is an illegal
|
184
237
|
word and cannot be used in the game:
|
@@ -190,7 +243,7 @@ word and cannot be used in the game:
|
|
190
243
|
- Foreign words are illegal unless they appear in the dictionary.
|
191
244
|
- Words that are only one letter long are illegal. *(Note: Not Standard)*
|
192
245
|
|
193
|
-
### 8.
|
246
|
+
### 8. Challenging A Word
|
194
247
|
|
195
248
|
You can challenge an opponent's word if you think it's misspelled or
|
196
249
|
an illegal word. The word must be challenged before another word is
|
@@ -198,13 +251,13 @@ played. Use a dictionary to decide if the challenged word is legal or
|
|
198
251
|
illegal. lf the challenged word is illegal, the player who played it removes
|
199
252
|
the letter tiles from the board and either plays another word or passes.
|
200
253
|
|
201
|
-
### 9.
|
254
|
+
### 9. Passing
|
202
255
|
|
203
256
|
You may pass your turn at any time during the game. Sometimes it is to
|
204
257
|
your advantage to pass, especially toward the end of the game, to allow
|
205
258
|
a better scoring opportunity to open up for you.
|
206
259
|
|
207
|
-
### 10.
|
260
|
+
### 10. Exchanging Your Letters
|
208
261
|
|
209
262
|
On your turn, you may exchange one of your letter tiles for a new one.
|
210
263
|
Just turn the tile you want to exchange letter-side down and draw a
|
@@ -214,7 +267,7 @@ it is a good strategy to give up a turn in order to exchange a letter. For
|
|
214
267
|
example, you may want to exchange a "J" or a "Z" if you draw them late
|
215
268
|
in the game.
|
216
269
|
|
217
|
-
### 11.
|
270
|
+
### 11. How To End The Game
|
218
271
|
|
219
272
|
The game is over as soon as any of the following situations occur:
|
220
273
|
- When one player uses all of his or her letter tiles, and no tiles remain in
|
@@ -227,11 +280,11 @@ The game is over as soon as any of the following situations occur:
|
|
227
280
|
When the game is over, total each player's final score. Subtract 5 points
|
228
281
|
from a player's score for each letter tile he/she has not played.
|
229
282
|
|
230
|
-
###
|
283
|
+
### How To Win
|
231
284
|
|
232
285
|
The player who scores the most points wins.
|
233
286
|
|
234
|
-
###
|
287
|
+
### Solo Play Rules
|
235
288
|
|
236
289
|
Follow setup and gameplay rules as explained above. Make words, one at
|
237
290
|
a time, and score points for every word you make. **NOTE:** During the game,
|
data/exe/upwords
CHANGED
data/lib/upwords.rb
CHANGED
@@ -7,17 +7,17 @@ require 'upwords/board'
|
|
7
7
|
require 'upwords/letter_bank'
|
8
8
|
require 'upwords/letter_rack'
|
9
9
|
require 'upwords/dictionary'
|
10
|
+
require 'upwords/word'
|
10
11
|
|
11
12
|
require 'upwords/shape'
|
12
13
|
require 'upwords/move'
|
13
|
-
require 'upwords/move_manager'
|
14
14
|
|
15
15
|
require 'upwords/cursor'
|
16
|
-
|
17
|
-
require 'upwords/word'
|
18
16
|
require 'upwords/player'
|
19
|
-
|
17
|
+
|
18
|
+
require 'upwords/move_manager'
|
20
19
|
require 'upwords/game'
|
20
|
+
require 'upwords/ui'
|
21
21
|
|
22
22
|
module Upwords
|
23
23
|
# Raised when player makes an illegal move
|
@@ -42,6 +42,10 @@ module Upwords
|
|
42
42
|
DELETE = 127
|
43
43
|
ENTER = 10
|
44
44
|
|
45
|
+
# Curses Color Constants
|
46
|
+
RED = 1
|
47
|
+
YELLOW = 2
|
48
|
+
|
45
49
|
# Official Scrabble Player Dictionary file
|
46
50
|
OSPD_FILE = File.join(File.dirname(__FILE__), "../data/ospd.txt")
|
47
51
|
|
data/lib/upwords/board.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Upwords
|
2
2
|
class Board
|
3
3
|
|
4
|
-
attr_accessor :max_height, :size
|
4
|
+
attr_accessor :max_height, :min_word_length, :size
|
5
5
|
|
6
6
|
# creates a 10 x 10 board
|
7
7
|
def initialize(size=10, max_height=5)
|
@@ -10,6 +10,7 @@ module Upwords
|
|
10
10
|
else
|
11
11
|
@size = size
|
12
12
|
@max_height = max_height
|
13
|
+
@min_word_length = 2
|
13
14
|
@grid = Hash.new do |h, (row, col)|
|
14
15
|
if row < 0 || col < 0 || num_rows <= row || num_columns <= col
|
15
16
|
raise IllegalMove, "#{row}, #{col} is out of bounds!"
|
@@ -28,11 +29,6 @@ module Upwords
|
|
28
29
|
@grid.key?([row, col]) && stack_height(row, col) > 0
|
29
30
|
end
|
30
31
|
|
31
|
-
# maximum letters than can be stacked in one space
|
32
|
-
def min_word_length
|
33
|
-
2
|
34
|
-
end
|
35
|
-
|
36
32
|
def num_rows
|
37
33
|
@size
|
38
34
|
end
|
@@ -70,6 +66,7 @@ module Upwords
|
|
70
66
|
else
|
71
67
|
return true
|
72
68
|
end
|
69
|
+
|
73
70
|
return false
|
74
71
|
end
|
75
72
|
|
@@ -84,13 +81,8 @@ module Upwords
|
|
84
81
|
@grid[[row, col]].pop
|
85
82
|
end
|
86
83
|
|
87
|
-
# show top letter in board space
|
88
84
|
def top_letter(row, col)
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
def get_letter(row, col, depth=1)
|
93
|
-
@grid[[row, col]][-depth]
|
85
|
+
@grid[[row, col]].last
|
94
86
|
end
|
95
87
|
|
96
88
|
def word_positions
|
data/lib/upwords/cursor.rb
CHANGED
@@ -6,9 +6,9 @@ module Upwords
|
|
6
6
|
@max_y = max_y
|
7
7
|
@max_x = max_x
|
8
8
|
|
9
|
-
#
|
10
|
-
@y = init_y
|
11
|
-
@x = init_x
|
9
|
+
# HACK: Force init_y, init_x to be in bounds
|
10
|
+
@y = init_y % @max_y
|
11
|
+
@x = init_x % @max_x
|
12
12
|
end
|
13
13
|
|
14
14
|
def up
|
@@ -32,7 +32,7 @@ module Upwords
|
|
32
32
|
@x = (x + dx) % @max_x
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def pos
|
36
36
|
[y, x]
|
37
37
|
end
|
38
38
|
end
|
data/lib/upwords/game.rb
CHANGED
@@ -2,19 +2,15 @@ module Upwords
|
|
2
2
|
class Game
|
3
3
|
attr_reader :board, :cursor, :players
|
4
4
|
|
5
|
-
def initialize(
|
5
|
+
def initialize(max_players = 4)
|
6
6
|
@max_players = max_players
|
7
|
-
@display_on = display_on
|
8
7
|
@board = Board.new(10, 5)
|
9
8
|
@letter_bank = LetterBank.new(ALL_LETTERS.dup)
|
10
|
-
@cursor = Cursor.new(@board.num_rows,
|
11
|
-
@board.num_columns,
|
12
|
-
*@board.middle_square[0])
|
9
|
+
@cursor = Cursor.new(@board.num_rows, @board.num_columns, *@board.middle_square[0])
|
13
10
|
@dict = Dictionary.import(OSPD_FILE)
|
14
11
|
@moves = MoveManager.new(@board, @dict)
|
15
12
|
@players = []
|
16
|
-
@running =
|
17
|
-
@submitted = false
|
13
|
+
@running = true
|
18
14
|
end
|
19
15
|
|
20
16
|
# =========================================
|
@@ -33,80 +29,39 @@ module Upwords
|
|
33
29
|
player_count = @players.size
|
34
30
|
end
|
35
31
|
|
36
|
-
def add_player(name = nil, cpu = false)
|
37
|
-
if player_count >= max_players
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@players << Player.new(name, rack_capacity=7, cpu)
|
44
|
-
end
|
45
|
-
@players.each {|p| p.refill_rack(@letter_bank) }
|
32
|
+
def add_player(name = nil, letter_capacity = 7, cpu = false)
|
33
|
+
raise ArgumentError, "No more players can join" if player_count >= max_players
|
34
|
+
|
35
|
+
# Automatically name player if no name is provided
|
36
|
+
name = "Player #{player_count + 1}" if name.nil? || name.length == 0
|
37
|
+
|
38
|
+
@players << Player.new(name, letter_capacity, cpu)
|
46
39
|
end
|
47
40
|
|
48
|
-
def
|
49
|
-
|
50
|
-
num_players = 0
|
51
|
-
|
52
|
-
# Select how many players will be in the game
|
53
|
-
# TODO: Add a command-line flag to allow players to skip this step
|
54
|
-
until (1..@max_players).include?(num_players) do
|
55
|
-
print "How many players will play? (1-#{@max_players})\n"
|
56
|
-
num_players = gets.chomp.to_i
|
57
|
-
print "\n"
|
58
|
-
if !(1..@max_players).include?(num_players)
|
59
|
-
print "Invalid selection: #{num_players}\n\n"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Name each player and choose if they are humans or computers
|
64
|
-
# TODO: Add a command-line flag to set this
|
65
|
-
(1..num_players).each do |idx|
|
66
|
-
print "What is Player #{idx}'s name?\n"
|
67
|
-
name = gets.chomp
|
68
|
-
print "Is Player #{idx} or a computer? (y/n)\n"
|
69
|
-
cpu = gets.chomp
|
70
|
-
add_player(name, cpu.upcase == "Y")
|
71
|
-
print "\n"
|
72
|
-
end
|
41
|
+
def all_refill_racks
|
42
|
+
@players.each {|p| p.refill_rack(@letter_bank) }
|
73
43
|
end
|
74
44
|
|
75
45
|
# =========================================
|
76
|
-
#
|
46
|
+
# Move Manager Methods
|
77
47
|
# =========================================
|
78
|
-
|
79
|
-
def init_window
|
80
|
-
Curses.noecho
|
81
|
-
Curses.curs_set(0)
|
82
|
-
Curses.init_screen
|
83
|
-
# Curses.start_color
|
84
|
-
|
85
|
-
@win = Graphics.new(self)
|
86
|
-
@win.keypad(true)
|
87
|
-
end
|
88
48
|
|
89
|
-
def
|
90
|
-
@
|
91
|
-
end
|
92
|
-
|
93
|
-
def refresh_graphics
|
94
|
-
if display_on? && running?
|
95
|
-
@win.refresh
|
96
|
-
end
|
49
|
+
def play_letter(letter, y = @cursor.y, x = @cursor.x)
|
50
|
+
@moves.add(current_player, modify_letter_input(letter), y, x)
|
97
51
|
end
|
98
52
|
|
99
|
-
def
|
100
|
-
|
101
|
-
@win.message = msg
|
102
|
-
refresh_graphics
|
103
|
-
end
|
53
|
+
def undo_last
|
54
|
+
@moves.undo_last(current_player)
|
104
55
|
end
|
105
56
|
|
106
|
-
def
|
107
|
-
|
57
|
+
def pending_position?(row, col)
|
58
|
+
@moves.include?(row, col)
|
108
59
|
end
|
109
60
|
|
61
|
+
# =========================================
|
62
|
+
# Output messages that rely on MoveManager
|
63
|
+
# =========================================
|
64
|
+
|
110
65
|
def standard_message
|
111
66
|
"#{current_player.name}'s pending words: #{pending_result}"
|
112
67
|
end
|
@@ -116,7 +71,7 @@ module Upwords
|
|
116
71
|
|
117
72
|
unless new_words.empty?
|
118
73
|
new_words.map do |w|
|
119
|
-
"#{w} (#{w.score})"
|
74
|
+
"#{w} (#{w.score})".upcase
|
120
75
|
end.join(", ") + " (Total = #{@moves.pending_score(current_player)})"
|
121
76
|
end
|
122
77
|
end
|
@@ -129,196 +84,79 @@ module Upwords
|
|
129
84
|
@running
|
130
85
|
end
|
131
86
|
|
132
|
-
def
|
133
|
-
@
|
134
|
-
|
135
|
-
|
136
|
-
add_players
|
137
|
-
|
138
|
-
# Start graphics
|
139
|
-
init_window if @display_on
|
140
|
-
clear_message
|
141
|
-
|
142
|
-
# Start main loop
|
143
|
-
while running? do
|
144
|
-
begin
|
145
|
-
# ------ CPU MOVE --------
|
146
|
-
if current_player.cpu?
|
147
|
-
update_message "#{current_player.name} is thinking..."
|
148
|
-
cpu_move = current_player.cpu_move(@board, @dict, 50, 10)
|
149
|
-
|
150
|
-
if !cpu_move.nil?
|
151
|
-
cpu_move.each do |posn, letter|
|
152
|
-
@moves.add(current_player, letter, *posn)
|
153
|
-
end
|
154
|
-
submit_moves(need_confirm=false)
|
155
|
-
else
|
156
|
-
skip_turn(need_confirm=false)
|
157
|
-
end
|
158
|
-
else
|
159
|
-
read_input(@win.getch)
|
160
|
-
end
|
161
|
-
|
162
|
-
if @submitted
|
163
|
-
# TODO: remove magic string from last move message
|
164
|
-
if @players.all? {|p| p.last_turn == "skipped turn"} || @letter_bank.empty? && current_player.rack_empty?
|
165
|
-
game_over
|
166
|
-
@running = false
|
167
|
-
else
|
168
|
-
next_turn
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
refresh_graphics
|
173
|
-
|
174
|
-
rescue IllegalMove => exception
|
175
|
-
update_message "#{exception.message} (press any key to continue...)"
|
176
|
-
@win.getch if display_on?
|
177
|
-
clear_message
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
end
|
182
|
-
|
183
|
-
def read_input(key)
|
184
|
-
case key
|
185
|
-
when 'Q'
|
186
|
-
exit_game
|
187
|
-
when SPACE
|
188
|
-
toggle_rack_visibility
|
189
|
-
when DELETE
|
190
|
-
undo_moves
|
191
|
-
when ENTER
|
87
|
+
def cpu_move
|
88
|
+
move = current_player.cpu_move(@board, @dict, batch_size=50, min_score=10)
|
89
|
+
if !move.nil?
|
90
|
+
move.each { |pos, letter| play_letter(letter, *pos) }
|
192
91
|
submit_moves
|
193
|
-
|
194
|
-
@cursor.up
|
195
|
-
when Curses::KEY_DOWN
|
196
|
-
@cursor.down
|
197
|
-
when Curses::KEY_LEFT
|
198
|
-
@cursor.left
|
199
|
-
when Curses::KEY_RIGHT
|
200
|
-
@cursor.right
|
201
|
-
when '+'
|
202
|
-
swap_letter
|
203
|
-
when '-'
|
92
|
+
else
|
204
93
|
skip_turn
|
205
|
-
when /[[:alpha:]]/
|
206
|
-
@moves.add(current_player, modify_letter_input(key), @cursor.y, @cursor.x)
|
207
|
-
clear_message
|
208
94
|
end
|
209
95
|
end
|
210
96
|
|
211
|
-
def next_turn
|
212
|
-
@players.rotate!
|
213
|
-
@win.hide_rack if display_on?
|
214
|
-
clear_message
|
215
|
-
@submitted = false
|
216
|
-
end
|
217
|
-
|
218
|
-
# =========================================
|
219
|
-
# Methods Related to Key Inputs
|
220
|
-
# =========================================
|
221
|
-
|
222
|
-
# Capitalize letters, and convert 'Q' and 'q' to 'Qu'
|
223
|
-
def modify_letter_input(letter)
|
224
|
-
if letter =~ /[Qq]/
|
225
|
-
'Qu'
|
226
|
-
else
|
227
|
-
letter.capitalize
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
def confirm_action?(question_text)
|
232
|
-
if display_on?
|
233
|
-
update_message "#{question_text} (y/n)"
|
234
|
-
inp = @win.getch
|
235
|
-
clear_message
|
236
|
-
inp == 'y' || inp == 'Y'
|
237
|
-
else
|
238
|
-
true # Never ask for confirm if the display_on is off
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
97
|
# =========================================
|
243
98
|
# Game Procedures Bound to some Key Input
|
244
99
|
# =========================================
|
245
100
|
|
246
|
-
def
|
247
|
-
@moves.
|
248
|
-
|
101
|
+
def submit_moves
|
102
|
+
@moves.submit(current_player)
|
103
|
+
current_player.refill_rack(@letter_bank)
|
104
|
+
current_player.last_turn = "played word" # TODO: remove magic string from last move message
|
105
|
+
next_turn
|
249
106
|
end
|
250
107
|
|
251
|
-
def
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
# TODO: remove magic string from last move message
|
259
|
-
current_player.last_turn = "played word"
|
260
|
-
end
|
108
|
+
def swap_letter(letter)
|
109
|
+
letter = modify_letter_input(letter)
|
110
|
+
@moves.undo_all(current_player)
|
111
|
+
current_player.swap_letter(letter, @letter_bank)
|
112
|
+
current_player.last_turn = "swapped letter" # TODO: remove magic string from last move message
|
113
|
+
next_turn
|
261
114
|
end
|
262
115
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
if letter =~ /[[:alpha:]]/
|
269
|
-
letter = modify_letter_input(letter)
|
270
|
-
if !need_confirm || (confirm_action? "Swap '#{letter}' for another?")
|
271
|
-
@moves.undo_all(current_player)
|
272
|
-
current_player.swap_letter(letter, @letter_bank)
|
273
|
-
@submitted = true
|
274
|
-
|
275
|
-
# TODO: remove magic string from last move message
|
276
|
-
current_player.last_turn = "swapped letter"
|
277
|
-
end
|
278
|
-
end
|
116
|
+
def skip_turn
|
117
|
+
@moves.undo_all(current_player)
|
118
|
+
current_player.last_turn = "skipped turn" # TODO: remove magic string from last move message
|
119
|
+
next_turn
|
279
120
|
end
|
280
121
|
|
281
|
-
def
|
282
|
-
|
283
|
-
|
284
|
-
@submitted = true
|
122
|
+
def exit_game
|
123
|
+
@running = false
|
124
|
+
end
|
285
125
|
|
286
|
-
|
287
|
-
|
288
|
-
|
126
|
+
# =================
|
127
|
+
# Game over methods
|
128
|
+
# =================
|
129
|
+
|
130
|
+
def game_over?
|
131
|
+
@players.all? {|p| p.last_turn == "skipped turn"} || (@letter_bank.empty? && current_player.rack_empty?)
|
289
132
|
end
|
290
133
|
|
291
|
-
def
|
292
|
-
|
293
|
-
@running = false
|
294
|
-
@win.close if display_on?
|
295
|
-
end
|
134
|
+
def get_top_score
|
135
|
+
@players.map {|p| p.score}.max
|
296
136
|
end
|
297
137
|
|
298
|
-
def
|
299
|
-
@
|
138
|
+
def get_winners
|
139
|
+
@players.select{|p| p.score == get_top_score}.map{|p| p.name}
|
300
140
|
end
|
301
141
|
|
302
|
-
|
303
|
-
update_message "The game is over. Press any key to continue to see who won..."
|
304
|
-
@win.getch if display_on?
|
142
|
+
private
|
305
143
|
|
306
|
-
|
307
|
-
|
308
|
-
|
144
|
+
def next_turn
|
145
|
+
if game_over?
|
146
|
+
# Subtract 5 points for each tile remaining
|
147
|
+
@players.each { |p| p.score -= p.letters.size * 5 }
|
148
|
+
else
|
149
|
+
@players.rotate!
|
309
150
|
end
|
151
|
+
end
|
310
152
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
update_message "And the winner is... #{winners[0]} with #{top_score} points!"
|
153
|
+
# Capitalize letters, and convert 'Q' and 'q' to 'Qu'
|
154
|
+
def modify_letter_input(letter)
|
155
|
+
if letter =~ /[Qq]/
|
156
|
+
'Qu'
|
316
157
|
else
|
317
|
-
|
158
|
+
letter.capitalize
|
318
159
|
end
|
319
|
-
|
320
|
-
@win.getch if display_on?
|
321
|
-
exit_game(need_confirm=false)
|
322
160
|
end
|
323
161
|
|
324
162
|
end
|