gemwarrior 0.15.10 → 0.15.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/gemwarrior +146 -146
- data/gemwarrior.gemspec +3 -1
- data/lib/gemwarrior/arena.rb +81 -81
- data/lib/gemwarrior/battle.rb +690 -690
- data/lib/gemwarrior/evaluator.rb +836 -836
- data/lib/gemwarrior/game.rb +191 -191
- data/lib/gemwarrior/game_assets.rb +100 -100
- data/lib/gemwarrior/game_options.rb +15 -15
- data/lib/gemwarrior/inventory.rb +243 -243
- data/lib/gemwarrior/repl.rb +705 -705
- data/lib/gemwarrior/version.rb +6 -6
- metadata +6 -6
data/lib/gemwarrior/evaluator.rb
CHANGED
@@ -1,836 +1,836 @@
|
|
1
|
-
# lib/gemwarrior/evaluator.rb
|
2
|
-
# Evaluates prompt input
|
3
|
-
|
4
|
-
require_relative 'arena'
|
5
|
-
require_relative 'game_assets'
|
6
|
-
require_relative 'game_options'
|
7
|
-
|
8
|
-
module Gemwarrior
|
9
|
-
class Evaluator
|
10
|
-
# CONSTANTS
|
11
|
-
PROGRAM_NAME = 'Gem Warrior'
|
12
|
-
QUIT_MESSAGE = 'Thanks for playing the game. Until next time...'
|
13
|
-
RESUME_MESSAGE = 'Back to adventuring!'
|
14
|
-
|
15
|
-
GO_PARAMS = 'Options: north, east, south, west'
|
16
|
-
CHANGE_PARAMS = 'Options: name'
|
17
|
-
DEBUG_LIST_PARAMS = 'Options: players, creatures, items, locations, monsters, weapons, armor'
|
18
|
-
DEBUG_STAT_PARAMS = 'Options: hp_cur, atk_lo, atk_hi, experience, rox, strength, dexterity, defense, inventory'
|
19
|
-
|
20
|
-
ERROR_COMMAND_INVALID = 'That is not something the game yet understands.'
|
21
|
-
ERROR_LOOK_AT_PARAM_MISSING = 'You cannot just "look at". You gotta choose something to look at.'
|
22
|
-
ERROR_TALK_PARAM_INVALID = 'Are you talking to yourself? That person is not here.'
|
23
|
-
ERROR_TALK_PARAM_UNTALKABLE = 'That cannnot be conversed with.'
|
24
|
-
ERROR_TALK_TO_PARAM_MISSING = 'You cannot just "talk to". You gotta choose someone to talk to.'
|
25
|
-
ERROR_GO_PARAM_MISSING = 'Just wander aimlessly? A direction would be nice.'
|
26
|
-
ERROR_GO_PARAM_INVALID = 'Something tells you that is not a way to go.'
|
27
|
-
ERROR_DIRECTION_PARAM_INVALID = 'You cannot go to that place.'
|
28
|
-
ERROR_ATTACK_PARAM_MISSING = 'You cannot just "attack". You gotta choose something to attack.'
|
29
|
-
ERROR_ATTACK_PARAM_INVALID = 'That monster does not exist here or can\'t be attacked.'
|
30
|
-
ERROR_BREAKTHRU_PARAM_MISSING = 'You cannot just "breakthru". You gotta specify a location name.'
|
31
|
-
ERROR_BREAKTHRU_PARAM_INVALID = 'You cannot breakthru to that place.'
|
32
|
-
ERROR_BREAKTHRU_INEXPERIENCED = 'You are not experienced enough to perform that feat.'
|
33
|
-
ERROR_TAKE_PARAM_MISSING = 'You cannot just "take". You gotta choose something to take.'
|
34
|
-
ERROR_USE_PARAM_MISSING = 'You cannot just "use". You gotta choose something to use.'
|
35
|
-
ERROR_USE_PARAM_INVALID = 'You cannot use that, as it does not exist here or in your inventory.'
|
36
|
-
ERROR_USE_PARAM_UNUSEABLE = 'That is not useable.'
|
37
|
-
ERROR_DROP_PARAM_MISSING = 'You cannot just "drop". You gotta choose something to drop.'
|
38
|
-
ERROR_EQUIP_PARAM_MISSING = 'You cannot just "equip". You gotta choose something to equip.'
|
39
|
-
ERROR_UNEQUIP_PARAM_MISSING = 'You cannot just "unequip". You gotta choose something to unequip.'
|
40
|
-
ERROR_CHANGE_PARAM_MISSING = 'You cannot just "change". You gotta choose something to change.'
|
41
|
-
ERROR_CHANGE_PARAM_INVALID = 'You cannot change that...yet.'
|
42
|
-
ERROR_LIST_PARAM_MISSING = 'You cannot just "list". You gotta choose something to list.'
|
43
|
-
ERROR_LIST_PARAM_INVALID = 'You cannot list that...yet.'
|
44
|
-
ERROR_DEBUG_STAT_PARAM_MISSING = 'You cannot just "change stats". You gotta choose a stat to change.'
|
45
|
-
ERROR_DEBUG_STAT_PARAM_INVALID = 'You cannot change that stat...yet.'
|
46
|
-
ERROR_DEBUG_STAT_INV_PARAM_INVALID = 'You cannot add that to your inventory...yet.'
|
47
|
-
ERROR_DEBUG_GLOBAL_VAR_INVALID = 'That global variable does not exist.'
|
48
|
-
ERROR_DEBUG_TELEPORT_PARAMS_MISSING = 'You cannot just "teleport". You gotta specify an x AND y coordinate, at least.'
|
49
|
-
ERROR_DEBUG_TELEPORT_PARAMS_NEEDED = 'You cannot just "teleport" to an x coordinate without a y coordinate.'
|
50
|
-
ERROR_DEBUG_TELEPORT_PARAMS_INVALID = 'You cannot teleport there...yet.'
|
51
|
-
|
52
|
-
attr_accessor :world,
|
53
|
-
:commands,
|
54
|
-
:aliases,
|
55
|
-
:extras,
|
56
|
-
:cmd_descriptions,
|
57
|
-
:devcommands,
|
58
|
-
:devaliases,
|
59
|
-
:devextras,
|
60
|
-
:devcmd_descriptions
|
61
|
-
|
62
|
-
def initialize(world)
|
63
|
-
self.world = world
|
64
|
-
|
65
|
-
self.devcommands = %w(god beast constants list vars map stat global teleport spawn levelbump restfight)
|
66
|
-
self.devaliases = %w(gd bs cn ls vs m st gl tp sp lb rf)
|
67
|
-
self.devextras = %w()
|
68
|
-
self.devcmd_descriptions = [
|
69
|
-
'Toggle god mode (i.e. invincible)',
|
70
|
-
'Toggle beast mode (i.e. super strength)',
|
71
|
-
'List all GameAssets',
|
72
|
-
'List all instances of a specific entity type',
|
73
|
-
'List all the variables in the world',
|
74
|
-
'Show a map of the world',
|
75
|
-
'Change player stat',
|
76
|
-
'Change world global variable',
|
77
|
-
'Teleport to coordinates (5 0 0) or name (\'Home\')',
|
78
|
-
'Spawn random monster',
|
79
|
-
'Bump your character up *n* levels',
|
80
|
-
'Rest, but ensure battle for testing'
|
81
|
-
]
|
82
|
-
|
83
|
-
self.commands = %w(character look rest take talk inventory use open drop equip unequip go north east south west attack breakthru change version checkupdate help quit quit!)
|
84
|
-
self.aliases = %w(c l r t tk i u o d eq ue g n e s w a br ch v cu h q qq)
|
85
|
-
self.extras = %w(exit exit! x xx fight f ? ?? ???)
|
86
|
-
self.cmd_descriptions = [
|
87
|
-
'Display character information',
|
88
|
-
'Look around your current location',
|
89
|
-
'Take a load off and regain HP',
|
90
|
-
'Take item',
|
91
|
-
'Talk to person',
|
92
|
-
'Look in your inventory',
|
93
|
-
'Use item (in inventory or environment)',
|
94
|
-
'Open item (in inventory or environment)',
|
95
|
-
'Drop item',
|
96
|
-
'Equip item',
|
97
|
-
'Unequip item',
|
98
|
-
'Go in a direction',
|
99
|
-
'Go north (shortcut)',
|
100
|
-
'Go east (shortcut)',
|
101
|
-
'Go south (shortcut)',
|
102
|
-
'Go west (shortcut)',
|
103
|
-
'Attack a monster (also fight)',
|
104
|
-
'Teleport to a location (if you are experienced enough)',
|
105
|
-
'Change attribute',
|
106
|
-
'Display game version',
|
107
|
-
'Check for newer game releases',
|
108
|
-
'This help menu (also ?)',
|
109
|
-
'Quit w/ confirmation (also exit/x)',
|
110
|
-
'Quit w/o confirmation (also exit!/xx)'
|
111
|
-
]
|
112
|
-
end
|
113
|
-
|
114
|
-
def parse(input)
|
115
|
-
case input
|
116
|
-
# Ctrl-D or empty command
|
117
|
-
when nil, ''
|
118
|
-
return
|
119
|
-
# real command
|
120
|
-
else
|
121
|
-
return ERROR_COMMAND_INVALID.colorize(:red) unless input_valid?(input)
|
122
|
-
end
|
123
|
-
|
124
|
-
tokens = input.split
|
125
|
-
command = tokens.first.downcase
|
126
|
-
param1 = tokens[1]
|
127
|
-
param2 = tokens[2]
|
128
|
-
param3 = tokens[3]
|
129
|
-
|
130
|
-
# helpful
|
131
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
132
|
-
|
133
|
-
# dev commands
|
134
|
-
if GameOptions.data['debug_mode']
|
135
|
-
case command
|
136
|
-
when 'god', 'gd'
|
137
|
-
GameOptions.data['god_mode'] = !GameOptions.data['god_mode']
|
138
|
-
return "God mode set to #{GameOptions.data['god_mode']}"
|
139
|
-
when 'beast', 'bs'
|
140
|
-
GameOptions.data['beast_mode'] = !GameOptions.data['beast_mode']
|
141
|
-
return "Beast mode set to #{GameOptions.data['beast_mode']}"
|
142
|
-
when 'constants', 'cn'
|
143
|
-
puts 'GameCreatures'.colorize(:yellow)
|
144
|
-
puts GameCreatures.data
|
145
|
-
STDIN.getc
|
146
|
-
puts 'GameMonsters'.colorize(:yellow)
|
147
|
-
puts GameMonsters.data
|
148
|
-
STDIN.getc
|
149
|
-
puts 'GamePeople'.colorize(:yellow)
|
150
|
-
puts GamePeople.data
|
151
|
-
STDIN.getc
|
152
|
-
puts 'GameItems'.colorize(:yellow)
|
153
|
-
puts GameItems.data
|
154
|
-
STDIN.getc
|
155
|
-
puts 'GameArmor'.colorize(:yellow)
|
156
|
-
puts GameArmor.data
|
157
|
-
STDIN.getc
|
158
|
-
puts 'GameWeapons'.colorize(:yellow)
|
159
|
-
puts GameWeapons.data
|
160
|
-
when 'vars', 'vs'
|
161
|
-
if param1
|
162
|
-
world.print_vars(param1)
|
163
|
-
else
|
164
|
-
world.print_vars
|
165
|
-
end
|
166
|
-
when 'list', 'ls'
|
167
|
-
if param1.nil?
|
168
|
-
puts ERROR_LIST_PARAM_MISSING
|
169
|
-
return DEBUG_LIST_PARAMS
|
170
|
-
else
|
171
|
-
return world.list(param1, param2)
|
172
|
-
end
|
173
|
-
when 'map', 'm'
|
174
|
-
world.print_map(param1)
|
175
|
-
when 'stat', 'st'
|
176
|
-
if param1.nil?
|
177
|
-
puts ERROR_DEBUG_STAT_PARAM_MISSING
|
178
|
-
return DEBUG_STAT_PARAMS
|
179
|
-
else
|
180
|
-
case param1
|
181
|
-
when 'hp_cur', 'hp'
|
182
|
-
unless param2.nil?
|
183
|
-
param2 = param2.to_i
|
184
|
-
if param2.is_a? Numeric
|
185
|
-
if param2 > 0
|
186
|
-
world.player.hp_cur = param2
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
when 'atk_lo'
|
191
|
-
unless param2.nil?
|
192
|
-
param2 = param2.to_i
|
193
|
-
if param2.is_a? Numeric
|
194
|
-
if param2 >= 0
|
195
|
-
world.player.atk_lo = param2
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
when 'atk_hi'
|
200
|
-
unless param2.nil?
|
201
|
-
param2 = param2.to_i
|
202
|
-
if param2.is_a? Numeric
|
203
|
-
if param2 >= 0
|
204
|
-
world.player.atk_hi = param2
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
when 'strength', 'str', 'st'
|
209
|
-
unless param2.nil?
|
210
|
-
param2 = param2.to_i
|
211
|
-
if param2.is_a? Numeric
|
212
|
-
if param2 >= 0
|
213
|
-
world.player.atk_lo = param2
|
214
|
-
world.player.atk_hi = param2
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
when 'dexterity', 'dex'
|
219
|
-
unless param2.nil?
|
220
|
-
param2 = param2.to_i
|
221
|
-
if param2.is_a? Numeric
|
222
|
-
if param2 >= 0
|
223
|
-
world.player.dexterity = param2
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
when 'defense', 'def'
|
228
|
-
unless param2.nil?
|
229
|
-
param2 = param2.to_i
|
230
|
-
if param2.is_a? Numeric
|
231
|
-
if param2 >= 0
|
232
|
-
world.player.defense = param2
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
when 'rox', 'r', '$'
|
237
|
-
unless param2.nil?
|
238
|
-
param2 = param2.to_i
|
239
|
-
if param2.is_a? Numeric
|
240
|
-
if param2 >= 0
|
241
|
-
world.player.rox = param2
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
when 'experience', 'xp'
|
246
|
-
unless param2.nil?
|
247
|
-
param2 = param2.to_i
|
248
|
-
if param2.is_a? Numeric
|
249
|
-
if param2 >= 0
|
250
|
-
world.player.xp = param2
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
when 'inventory', 'inv'
|
255
|
-
unless param2.nil?
|
256
|
-
begin
|
257
|
-
item_const_name = Gemwarrior.const_get(Formatting.upstyle(param2, no_space: true))
|
258
|
-
item = item_const_name.new
|
259
|
-
world.player.inventory.items.push(item)
|
260
|
-
return "#{item.name.colorize(:yellow)} added to player inventory."
|
261
|
-
rescue
|
262
|
-
return ERROR_DEBUG_STAT_INV_PARAM_INVALID
|
263
|
-
end
|
264
|
-
end
|
265
|
-
else
|
266
|
-
return ERROR_DEBUG_STAT_PARAM_INVALID
|
267
|
-
end
|
268
|
-
end
|
269
|
-
when 'global', 'gl'
|
270
|
-
if param1.nil?
|
271
|
-
return world.instance_variables.join(', ')
|
272
|
-
elsif world.instance_variable_get("@#{param1}").nil?
|
273
|
-
return ERROR_DEBUG_GLOBAL_VAR_INVALID
|
274
|
-
elsif param2.nil?
|
275
|
-
return world.instance_variable_get("@#{param1}").to_s
|
276
|
-
else
|
277
|
-
val = false
|
278
|
-
val = param2.eql?('true') ? true : val
|
279
|
-
|
280
|
-
world.instance_variable_set("@#{param1}", val)
|
281
|
-
return "Instance variable #{param1} has been set to #{val}."
|
282
|
-
end
|
283
|
-
when 'spawn', 'sp'
|
284
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
285
|
-
player_cur_location.populate_monsters(GameMonsters.data, true, param1)
|
286
|
-
return world.describe(player_cur_location)
|
287
|
-
when 'teleport', 'tp'
|
288
|
-
if param1.nil?
|
289
|
-
return ERROR_DEBUG_TELEPORT_PARAMS_MISSING
|
290
|
-
else
|
291
|
-
if (param1.to_i.to_s == param1)
|
292
|
-
# we got at least an x coordinate
|
293
|
-
if (param2.to_i.to_s == param2)
|
294
|
-
# we got a y coordinate, too
|
295
|
-
x_coord = param1.to_i
|
296
|
-
y_coord = param2.to_i
|
297
|
-
# grab the z coordinate, if present, otherwise default to current level
|
298
|
-
z_coord = param3.to_i.to_s == param3 ? param3.to_i : world.player.cur_coords[:z]
|
299
|
-
|
300
|
-
# check to make sure new location exists
|
301
|
-
if world.location_by_coords(x: x_coord, y: y_coord, z: z_coord)
|
302
|
-
world.player.cur_coords = { x: x_coord, y: y_coord, z: z_coord }
|
303
|
-
else
|
304
|
-
return ERROR_DEBUG_TELEPORT_PARAMS_INVALID
|
305
|
-
end
|
306
|
-
else
|
307
|
-
# we only got an x coordinate
|
308
|
-
return ERROR_DEBUG_TELEPORT_PARAMS_NEEDED
|
309
|
-
end
|
310
|
-
else
|
311
|
-
# we got a place name instead, potentially
|
312
|
-
place_to_match = tokens[1..tokens.length].join(' ').downcase
|
313
|
-
locations = []
|
314
|
-
world.locations.each do |l|
|
315
|
-
locations << l.name.downcase
|
316
|
-
end
|
317
|
-
if locations.include?(place_to_match)
|
318
|
-
world.player.cur_coords = world.location_coords_by_name(place_to_match)
|
319
|
-
else
|
320
|
-
return ERROR_DEBUG_TELEPORT_PARAMS_INVALID
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
# stats
|
325
|
-
world.player.movements_made += 1
|
326
|
-
|
327
|
-
Animation.run(phrase: '** TELEPORT! **', speed: :insane)
|
328
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
329
|
-
return world.describe(player_cur_location)
|
330
|
-
end
|
331
|
-
when 'levelbump', 'lb'
|
332
|
-
new_level = param1.nil? ? 1 : param1.to_i
|
333
|
-
world.player.update_stats(reason: :level_bump, value: new_level)
|
334
|
-
when 'restfight', 'rf'
|
335
|
-
result = world.player.rest(world, 0, true)
|
336
|
-
|
337
|
-
if result.eql?('death')
|
338
|
-
player_death_resurrection
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
# normal commands
|
344
|
-
case command
|
345
|
-
when 'character', 'c'
|
346
|
-
# bypass puts so it prints out with newlines properly
|
347
|
-
print world.player.check_self
|
348
|
-
when 'inventory', 'i'
|
349
|
-
if param1
|
350
|
-
world.player.inventory.describe_item(param1)
|
351
|
-
else
|
352
|
-
world.player.list_inventory
|
353
|
-
end
|
354
|
-
when 'look', 'l'
|
355
|
-
if param1
|
356
|
-
# convert 'look at' to 'look'
|
357
|
-
if param1.eql?('at')
|
358
|
-
if param2
|
359
|
-
param1 = param2
|
360
|
-
else
|
361
|
-
return ERROR_LOOK_AT_PARAM_MISSING
|
362
|
-
end
|
363
|
-
end
|
364
|
-
world.describe_entity(player_cur_location, param1)
|
365
|
-
else
|
366
|
-
world.describe(player_cur_location)
|
367
|
-
end
|
368
|
-
when 'rest', 'r'
|
369
|
-
tent_uses = 0
|
370
|
-
player_inventory = world.player.inventory
|
371
|
-
|
372
|
-
if player_inventory.contains_item?('tent')
|
373
|
-
player_inventory.items.each do |i|
|
374
|
-
if i.name.eql?('tent')
|
375
|
-
if i.number_of_uses > 0
|
376
|
-
result = i.use(world)
|
377
|
-
tent_uses = i.number_of_uses
|
378
|
-
i.number_of_uses -= 1
|
379
|
-
|
380
|
-
puts ">> tent can be used when resting #{i.number_of_uses} more time(s)."
|
381
|
-
end
|
382
|
-
end
|
383
|
-
end
|
384
|
-
elsif player_cur_location.contains_item?('tent')
|
385
|
-
player_cur_location.items.each do |i|
|
386
|
-
if i.name.eql?('tent')
|
387
|
-
if i.number_of_uses > 0
|
388
|
-
result = i.use(world)
|
389
|
-
tent_uses = i.number_of_uses
|
390
|
-
i.number_of_uses -= 1
|
391
|
-
|
392
|
-
puts ">> tent can be used when resting #{i.number_of_uses} more time(s)."
|
393
|
-
end
|
394
|
-
end
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
result = world.player.rest(world, tent_uses)
|
399
|
-
|
400
|
-
if result.eql?('death')
|
401
|
-
player_death_resurrection
|
402
|
-
else
|
403
|
-
result
|
404
|
-
end
|
405
|
-
when 'take', 't'
|
406
|
-
if param1.nil?
|
407
|
-
ERROR_TAKE_PARAM_MISSING
|
408
|
-
else
|
409
|
-
world.player.inventory.add_item(param1, player_cur_location, world.player)
|
410
|
-
end
|
411
|
-
when 'talk', 'tk'
|
412
|
-
if param1.nil?
|
413
|
-
return ERROR_TALK_TO_PARAM_MISSING
|
414
|
-
elsif param1.eql?('to')
|
415
|
-
if param2
|
416
|
-
param1 = param2
|
417
|
-
else
|
418
|
-
return ERROR_TALK_TO_PARAM_MISSING
|
419
|
-
end
|
420
|
-
end
|
421
|
-
|
422
|
-
talkable_name = param1
|
423
|
-
|
424
|
-
player_inventory = world.player.inventory
|
425
|
-
|
426
|
-
if player_inventory.contains_item?(talkable_name)
|
427
|
-
player_inventory.items.each do |person|
|
428
|
-
if person.name.eql?(talkable_name)
|
429
|
-
if person.talkable
|
430
|
-
return self.parse("use #{talkable_name}")
|
431
|
-
else
|
432
|
-
return ERROR_TALK_PARAM_UNTALKABLE
|
433
|
-
end
|
434
|
-
end
|
435
|
-
end
|
436
|
-
elsif player_cur_location.contains_item?(talkable_name)
|
437
|
-
player_cur_location.items.each do |person|
|
438
|
-
if person.name.eql?(talkable_name)
|
439
|
-
if person.talkable
|
440
|
-
return self.parse("use #{talkable_name}")
|
441
|
-
else
|
442
|
-
return ERROR_TALK_PARAM_UNTALKABLE
|
443
|
-
end
|
444
|
-
end
|
445
|
-
end
|
446
|
-
elsif player_cur_location.has_monster?(talkable_name)
|
447
|
-
player_cur_location.monsters_abounding.each do |monster|
|
448
|
-
if monster.name.eql?(talkable_name)
|
449
|
-
if monster.talkable
|
450
|
-
return self.parse("use #{talkable_name}")
|
451
|
-
else
|
452
|
-
return ERROR_TALK_PARAM_UNTALKABLE
|
453
|
-
end
|
454
|
-
end
|
455
|
-
end
|
456
|
-
elsif player_cur_location.has_boss?(talkable_name)
|
457
|
-
player_cur_location.bosses_abounding.each do |boss|
|
458
|
-
if boss.name.eql?(talkable_name)
|
459
|
-
if boss.talkable
|
460
|
-
return self.parse("use #{talkable_name}")
|
461
|
-
else
|
462
|
-
return ERROR_TALK_PARAM_UNTALKABLE
|
463
|
-
end
|
464
|
-
end
|
465
|
-
end
|
466
|
-
end
|
467
|
-
when 'use', 'u', 'open', 'o'
|
468
|
-
if param1.nil?
|
469
|
-
ERROR_USE_PARAM_MISSING
|
470
|
-
else
|
471
|
-
item_name = param1
|
472
|
-
result = nil
|
473
|
-
|
474
|
-
player_inventory = world.player.inventory
|
475
|
-
|
476
|
-
if player_inventory.contains_item?(item_name)
|
477
|
-
player_inventory.items.each do |i|
|
478
|
-
if i.name.eql?(item_name)
|
479
|
-
if i.useable
|
480
|
-
if !i.number_of_uses.nil?
|
481
|
-
if i.number_of_uses > 0
|
482
|
-
result = i.use(world)
|
483
|
-
i.number_of_uses -= 1
|
484
|
-
puts ">> #{i.name} can be used #{i.number_of_uses} more time(s)."
|
485
|
-
break
|
486
|
-
else
|
487
|
-
return ">> #{i.name} cannot be used anymore."
|
488
|
-
end
|
489
|
-
elsif i.consumable
|
490
|
-
result = i.use(world)
|
491
|
-
world.player.inventory.remove_item(i.name)
|
492
|
-
break
|
493
|
-
else
|
494
|
-
result = i.use(world)
|
495
|
-
break
|
496
|
-
end
|
497
|
-
else
|
498
|
-
return ERROR_USE_PARAM_UNUSEABLE
|
499
|
-
end
|
500
|
-
end
|
501
|
-
end
|
502
|
-
elsif player_cur_location.contains_item?(item_name)
|
503
|
-
player_cur_location.items.each do |i|
|
504
|
-
if i.name.eql?(item_name)
|
505
|
-
if i.useable
|
506
|
-
if !i.number_of_uses.nil?
|
507
|
-
if i.number_of_uses > 0
|
508
|
-
result = i.use(world)
|
509
|
-
i.number_of_uses -= 1
|
510
|
-
puts ">> #{i.name} can be used #{i.number_of_uses} more time(s)."
|
511
|
-
break
|
512
|
-
else
|
513
|
-
return ">> #{i.name} cannot be used anymore."
|
514
|
-
end
|
515
|
-
elsif i.consumable
|
516
|
-
result = i.use(world)
|
517
|
-
location.remove_item(i.name)
|
518
|
-
break
|
519
|
-
else
|
520
|
-
result = i.use(world)
|
521
|
-
break
|
522
|
-
end
|
523
|
-
else
|
524
|
-
return ERROR_USE_PARAM_UNUSEABLE
|
525
|
-
end
|
526
|
-
end
|
527
|
-
end
|
528
|
-
elsif player_cur_location.has_monster?(item_name)
|
529
|
-
player_cur_location.monsters_abounding.each do |i|
|
530
|
-
if i.name.eql?(item_name)
|
531
|
-
return i.use(world)
|
532
|
-
end
|
533
|
-
end
|
534
|
-
elsif player_cur_location.has_boss?(item_name)
|
535
|
-
player_cur_location.bosses_abounding.each do |i|
|
536
|
-
if i.name.eql?(item_name)
|
537
|
-
return i.use(world)
|
538
|
-
end
|
539
|
-
end
|
540
|
-
end
|
541
|
-
|
542
|
-
if result.nil?
|
543
|
-
ERROR_USE_PARAM_INVALID
|
544
|
-
else
|
545
|
-
case result[:type]
|
546
|
-
when 'move'
|
547
|
-
world.player.cur_coords = world.location_coords_by_name(result[:data])
|
548
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
549
|
-
world.describe(player_cur_location)
|
550
|
-
when 'move_dangerous'
|
551
|
-
dmg = rand(0..2)
|
552
|
-
puts ">> You lose #{dmg} hit point(s)." if dmg > 0
|
553
|
-
world.player.take_damage(dmg)
|
554
|
-
|
555
|
-
world.player.cur_coords = world.location_coords_by_name(result[:data])
|
556
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
557
|
-
world.describe(player_cur_location)
|
558
|
-
when 'dmg'
|
559
|
-
result = world.player.take_damage(result[:data])
|
560
|
-
|
561
|
-
if result.eql?('death')
|
562
|
-
player_death_resurrection
|
563
|
-
end
|
564
|
-
when 'rest', 'health'
|
565
|
-
world.player.heal_damage(result[:data])
|
566
|
-
return
|
567
|
-
when 'xp'
|
568
|
-
world.player.update_stats(reason: :xp, value: result[:data])
|
569
|
-
return
|
570
|
-
when 'tent'
|
571
|
-
world.player.rest(world, result[:data])
|
572
|
-
when 'action'
|
573
|
-
case result[:data]
|
574
|
-
when 'map'
|
575
|
-
world.print_map(world.player.cur_coords[:z])
|
576
|
-
end
|
577
|
-
when 'arena'
|
578
|
-
arena = Arena.new(world: world, player: world.player)
|
579
|
-
result = arena.start
|
580
|
-
|
581
|
-
if result.eql?('death')
|
582
|
-
player_death_resurrection
|
583
|
-
end
|
584
|
-
when 'item'
|
585
|
-
player_cur_location.add_item(result[:data])
|
586
|
-
return
|
587
|
-
when 'purchase'
|
588
|
-
result[:data].each do |i|
|
589
|
-
world.player.inventory.items.push(i)
|
590
|
-
end
|
591
|
-
return
|
592
|
-
else
|
593
|
-
return
|
594
|
-
end
|
595
|
-
end
|
596
|
-
end
|
597
|
-
when 'drop', 'd'
|
598
|
-
if param1.nil?
|
599
|
-
ERROR_DROP_PARAM_MISSING
|
600
|
-
else
|
601
|
-
world.player.inventory.drop_item(param1, player_cur_location)
|
602
|
-
end
|
603
|
-
when 'equip', 'eq'
|
604
|
-
if param1.nil?
|
605
|
-
ERROR_EQUIP_PARAM_MISSING
|
606
|
-
else
|
607
|
-
world.player.inventory.equip_item(param1)
|
608
|
-
end
|
609
|
-
when 'unequip', 'ue'
|
610
|
-
if param1.nil?
|
611
|
-
ERROR_UNEQUIP_PARAM_MISSING
|
612
|
-
else
|
613
|
-
world.player.inventory.unequip_item(param1)
|
614
|
-
end
|
615
|
-
when 'go', 'g'
|
616
|
-
if param1.nil?
|
617
|
-
puts ERROR_GO_PARAM_MISSING
|
618
|
-
GO_PARAMS
|
619
|
-
else
|
620
|
-
direction = param1
|
621
|
-
try_to_move_player(direction)
|
622
|
-
end
|
623
|
-
when 'n'
|
624
|
-
if param1
|
625
|
-
ERROR_DIRECTION_PARAM_INVALID
|
626
|
-
else
|
627
|
-
try_to_move_player('north')
|
628
|
-
end
|
629
|
-
when 'e'
|
630
|
-
if param1
|
631
|
-
ERROR_DIRECTION_PARAM_INVALID
|
632
|
-
else
|
633
|
-
try_to_move_player('east')
|
634
|
-
end
|
635
|
-
when 's'
|
636
|
-
if param1
|
637
|
-
ERROR_DIRECTION_PARAM_INVALID
|
638
|
-
else
|
639
|
-
try_to_move_player('south')
|
640
|
-
end
|
641
|
-
when 'w'
|
642
|
-
if param1
|
643
|
-
ERROR_DIRECTION_PARAM_INVALID
|
644
|
-
else
|
645
|
-
try_to_move_player('west')
|
646
|
-
end
|
647
|
-
when 'attack', 'a', 'fight', 'f'
|
648
|
-
if param1.nil?
|
649
|
-
if GameOptions.data['fight_completion']
|
650
|
-
if player_cur_location.has_any_monsters?
|
651
|
-
monster_param = player_cur_location.monsters_abounding[0].name
|
652
|
-
self.parse("attack #{monster_param}")
|
653
|
-
else
|
654
|
-
ERROR_ATTACK_PARAM_INVALID
|
655
|
-
end
|
656
|
-
else
|
657
|
-
ERROR_ATTACK_PARAM_MISSING
|
658
|
-
end
|
659
|
-
else
|
660
|
-
monster_name = param1
|
661
|
-
if world.has_monster_to_attack?(monster_name)
|
662
|
-
monster = player_cur_location.monster_by_name(monster_name)
|
663
|
-
result = world.player.attack(world, monster, param2)
|
664
|
-
|
665
|
-
if result.eql?('death')
|
666
|
-
return player_death_resurrection
|
667
|
-
elsif result.eql?('exit')
|
668
|
-
return 'exit'
|
669
|
-
end
|
670
|
-
|
671
|
-
unless result.nil?
|
672
|
-
case result[:type]
|
673
|
-
when 'message'
|
674
|
-
result[:data]
|
675
|
-
when 'move'
|
676
|
-
world.player.cur_coords = world.location_coords_by_name(result[:data])
|
677
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
678
|
-
world.describe(player_cur_location)
|
679
|
-
end
|
680
|
-
end
|
681
|
-
else
|
682
|
-
ERROR_ATTACK_PARAM_INVALID
|
683
|
-
end
|
684
|
-
end
|
685
|
-
when 'breakthru', 'br'
|
686
|
-
if world.player.special_abilities.include?(:breakthru)
|
687
|
-
if param1.nil?
|
688
|
-
return ERROR_BREAKTHRU_PARAM_MISSING
|
689
|
-
else
|
690
|
-
place_to_match = tokens[1..tokens.length].join(' ').downcase
|
691
|
-
locations = []
|
692
|
-
world.locations.each do |l|
|
693
|
-
locations << l.name.downcase
|
694
|
-
end
|
695
|
-
if locations.include?(place_to_match)
|
696
|
-
world.player.cur_coords = world.location_coords_by_name(place_to_match)
|
697
|
-
else
|
698
|
-
return ERROR_BREAKTHRU_PARAM_INVALID
|
699
|
-
end
|
700
|
-
end
|
701
|
-
|
702
|
-
# stats
|
703
|
-
world.player.movements_made += 1
|
704
|
-
|
705
|
-
Animation.run(phrase: '** BREAK THROUGH! **')
|
706
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
707
|
-
return world.describe(player_cur_location)
|
708
|
-
else
|
709
|
-
ERROR_BREAKTHRU_INEXPERIENCED
|
710
|
-
end
|
711
|
-
when 'change', 'ch'
|
712
|
-
if param1.nil?
|
713
|
-
puts ERROR_CHANGE_PARAM_MISSING
|
714
|
-
CHANGE_PARAMS
|
715
|
-
else
|
716
|
-
case param1
|
717
|
-
when 'name'
|
718
|
-
world.player.modify_name
|
719
|
-
else
|
720
|
-
ERROR_CHANGE_PARAM_INVALID
|
721
|
-
end
|
722
|
-
end
|
723
|
-
when 'help', 'h', '?', '??', '???'
|
724
|
-
list_commands
|
725
|
-
when 'version', 'v'
|
726
|
-
Gemwarrior::VERSION
|
727
|
-
when 'checkupdate', 'cu'
|
728
|
-
'checkupdate'
|
729
|
-
when 'quit', 'exit', 'q', 'x'
|
730
|
-
print 'You sure you want to quit? (y/n) '
|
731
|
-
answer = gets.chomp.downcase
|
732
|
-
|
733
|
-
case answer
|
734
|
-
when 'y', 'yes'
|
735
|
-
puts QUIT_MESSAGE.colorize(:yellow)
|
736
|
-
return 'exit'
|
737
|
-
else
|
738
|
-
puts RESUME_MESSAGE.colorize(:green)
|
739
|
-
end
|
740
|
-
when 'quit!', 'exit!', 'qq', 'xx'
|
741
|
-
puts QUIT_MESSAGE.colorize(:yellow)
|
742
|
-
return 'exit'
|
743
|
-
else
|
744
|
-
return
|
745
|
-
end
|
746
|
-
end
|
747
|
-
|
748
|
-
private
|
749
|
-
|
750
|
-
def try_to_move_player(direction)
|
751
|
-
if world.can_move?(direction)
|
752
|
-
world.player.go(world, direction)
|
753
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
754
|
-
player_cur_location.checked_for_monsters = false
|
755
|
-
|
756
|
-
if player_cur_location.name.include?('pain_quarry')
|
757
|
-
if player_cur_location.has_boss?('garynetty')
|
758
|
-
roll = rand(0..100) + world.player.dexterity
|
759
|
-
roll_display = roll < 25 ? "#{roll}".colorize(:red) : "#{roll}".colorize(:green)
|
760
|
-
puts "[Pain Quarry Garynetty Roll: #{roll_display}]" if GameOptions.data['debug_mode']
|
761
|
-
if roll < 25
|
762
|
-
self.parse("attack garynetty is_ambush")
|
763
|
-
else
|
764
|
-
puts 'You nearly got attacked by a vicious Garynetty! Be careful, your next move might not be as lucky.'.colorize(:yellow)
|
765
|
-
end
|
766
|
-
end
|
767
|
-
end
|
768
|
-
|
769
|
-
world.describe(player_cur_location)
|
770
|
-
else
|
771
|
-
return ERROR_GO_PARAM_INVALID.colorize(:red)
|
772
|
-
end
|
773
|
-
end
|
774
|
-
|
775
|
-
def player_death_resurrection
|
776
|
-
Audio.play_synth(:player_resurrection)
|
777
|
-
|
778
|
-
puts 'Somehow, though, your adventure does not end here!'.colorize(:yellow)
|
779
|
-
puts 'Instead, you are whisked back home via some magical force.'.colorize(:yellow)
|
780
|
-
puts 'A bit worse for the weary and somewhat poorer, but you are ALIVE!'.colorize(:yellow)
|
781
|
-
puts
|
782
|
-
|
783
|
-
world.player.hp_cur = 1
|
784
|
-
world.player.rox -= (world.player.rox * 0.1).to_i
|
785
|
-
if world.player.rox < 0
|
786
|
-
world.player.rox = 0
|
787
|
-
end
|
788
|
-
world.player.cur_coords = world.location_coords_by_name('Home')
|
789
|
-
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
790
|
-
world.describe(player_cur_location)
|
791
|
-
world.player.deaths += 1
|
792
|
-
return
|
793
|
-
end
|
794
|
-
|
795
|
-
def list_commands
|
796
|
-
i = 0
|
797
|
-
Hr.print('=')
|
798
|
-
puts ' COMMAND | ALIAS | DESCRIPTION '
|
799
|
-
Hr.print('=')
|
800
|
-
commands.each do |cmd|
|
801
|
-
puts " #{cmd.ljust(11)} | #{aliases[i].ljust(5)} | #{cmd_descriptions[i]}"
|
802
|
-
i += 1
|
803
|
-
end
|
804
|
-
Hr.print('=')
|
805
|
-
|
806
|
-
if GameOptions.data['debug_mode']
|
807
|
-
puts ' DEBUG COMMANDS'
|
808
|
-
Hr.print('=')
|
809
|
-
i = 0
|
810
|
-
devcommands.each do |cmd|
|
811
|
-
puts " #{cmd.ljust(11)} | #{devaliases[i].ljust(5)} | #{devcmd_descriptions[i]}"
|
812
|
-
i += 1
|
813
|
-
end
|
814
|
-
Hr.print('=')
|
815
|
-
end
|
816
|
-
end
|
817
|
-
|
818
|
-
def input_valid?(input)
|
819
|
-
tokens = input.split
|
820
|
-
command = tokens[0]
|
821
|
-
commands_and_aliases = commands | aliases | extras
|
822
|
-
|
823
|
-
if GameOptions.data['debug_mode']
|
824
|
-
commands_and_aliases = commands_and_aliases | devcommands | devaliases | devextras
|
825
|
-
end
|
826
|
-
|
827
|
-
if commands_and_aliases.include?(command.downcase)
|
828
|
-
if tokens.size.between?(1, 4)
|
829
|
-
return true
|
830
|
-
end
|
831
|
-
elsif tokens.empty?
|
832
|
-
return true
|
833
|
-
end
|
834
|
-
end
|
835
|
-
end
|
836
|
-
end
|
1
|
+
# lib/gemwarrior/evaluator.rb
|
2
|
+
# Evaluates prompt input
|
3
|
+
|
4
|
+
require_relative 'arena'
|
5
|
+
require_relative 'game_assets'
|
6
|
+
require_relative 'game_options'
|
7
|
+
|
8
|
+
module Gemwarrior
|
9
|
+
class Evaluator
|
10
|
+
# CONSTANTS
|
11
|
+
PROGRAM_NAME = 'Gem Warrior'
|
12
|
+
QUIT_MESSAGE = 'Thanks for playing the game. Until next time...'
|
13
|
+
RESUME_MESSAGE = 'Back to adventuring!'
|
14
|
+
|
15
|
+
GO_PARAMS = 'Options: north, east, south, west'
|
16
|
+
CHANGE_PARAMS = 'Options: name'
|
17
|
+
DEBUG_LIST_PARAMS = 'Options: players, creatures, items, locations, monsters, weapons, armor'
|
18
|
+
DEBUG_STAT_PARAMS = 'Options: hp_cur, atk_lo, atk_hi, experience, rox, strength, dexterity, defense, inventory'
|
19
|
+
|
20
|
+
ERROR_COMMAND_INVALID = 'That is not something the game yet understands.'
|
21
|
+
ERROR_LOOK_AT_PARAM_MISSING = 'You cannot just "look at". You gotta choose something to look at.'
|
22
|
+
ERROR_TALK_PARAM_INVALID = 'Are you talking to yourself? That person is not here.'
|
23
|
+
ERROR_TALK_PARAM_UNTALKABLE = 'That cannnot be conversed with.'
|
24
|
+
ERROR_TALK_TO_PARAM_MISSING = 'You cannot just "talk to". You gotta choose someone to talk to.'
|
25
|
+
ERROR_GO_PARAM_MISSING = 'Just wander aimlessly? A direction would be nice.'
|
26
|
+
ERROR_GO_PARAM_INVALID = 'Something tells you that is not a way to go.'
|
27
|
+
ERROR_DIRECTION_PARAM_INVALID = 'You cannot go to that place.'
|
28
|
+
ERROR_ATTACK_PARAM_MISSING = 'You cannot just "attack". You gotta choose something to attack.'
|
29
|
+
ERROR_ATTACK_PARAM_INVALID = 'That monster does not exist here or can\'t be attacked.'
|
30
|
+
ERROR_BREAKTHRU_PARAM_MISSING = 'You cannot just "breakthru". You gotta specify a location name.'
|
31
|
+
ERROR_BREAKTHRU_PARAM_INVALID = 'You cannot breakthru to that place.'
|
32
|
+
ERROR_BREAKTHRU_INEXPERIENCED = 'You are not experienced enough to perform that feat.'
|
33
|
+
ERROR_TAKE_PARAM_MISSING = 'You cannot just "take". You gotta choose something to take.'
|
34
|
+
ERROR_USE_PARAM_MISSING = 'You cannot just "use". You gotta choose something to use.'
|
35
|
+
ERROR_USE_PARAM_INVALID = 'You cannot use that, as it does not exist here or in your inventory.'
|
36
|
+
ERROR_USE_PARAM_UNUSEABLE = 'That is not useable.'
|
37
|
+
ERROR_DROP_PARAM_MISSING = 'You cannot just "drop". You gotta choose something to drop.'
|
38
|
+
ERROR_EQUIP_PARAM_MISSING = 'You cannot just "equip". You gotta choose something to equip.'
|
39
|
+
ERROR_UNEQUIP_PARAM_MISSING = 'You cannot just "unequip". You gotta choose something to unequip.'
|
40
|
+
ERROR_CHANGE_PARAM_MISSING = 'You cannot just "change". You gotta choose something to change.'
|
41
|
+
ERROR_CHANGE_PARAM_INVALID = 'You cannot change that...yet.'
|
42
|
+
ERROR_LIST_PARAM_MISSING = 'You cannot just "list". You gotta choose something to list.'
|
43
|
+
ERROR_LIST_PARAM_INVALID = 'You cannot list that...yet.'
|
44
|
+
ERROR_DEBUG_STAT_PARAM_MISSING = 'You cannot just "change stats". You gotta choose a stat to change.'
|
45
|
+
ERROR_DEBUG_STAT_PARAM_INVALID = 'You cannot change that stat...yet.'
|
46
|
+
ERROR_DEBUG_STAT_INV_PARAM_INVALID = 'You cannot add that to your inventory...yet.'
|
47
|
+
ERROR_DEBUG_GLOBAL_VAR_INVALID = 'That global variable does not exist.'
|
48
|
+
ERROR_DEBUG_TELEPORT_PARAMS_MISSING = 'You cannot just "teleport". You gotta specify an x AND y coordinate, at least.'
|
49
|
+
ERROR_DEBUG_TELEPORT_PARAMS_NEEDED = 'You cannot just "teleport" to an x coordinate without a y coordinate.'
|
50
|
+
ERROR_DEBUG_TELEPORT_PARAMS_INVALID = 'You cannot teleport there...yet.'
|
51
|
+
|
52
|
+
attr_accessor :world,
|
53
|
+
:commands,
|
54
|
+
:aliases,
|
55
|
+
:extras,
|
56
|
+
:cmd_descriptions,
|
57
|
+
:devcommands,
|
58
|
+
:devaliases,
|
59
|
+
:devextras,
|
60
|
+
:devcmd_descriptions
|
61
|
+
|
62
|
+
def initialize(world)
|
63
|
+
self.world = world
|
64
|
+
|
65
|
+
self.devcommands = %w(god beast constants list vars map stat global teleport spawn levelbump restfight)
|
66
|
+
self.devaliases = %w(gd bs cn ls vs m st gl tp sp lb rf)
|
67
|
+
self.devextras = %w()
|
68
|
+
self.devcmd_descriptions = [
|
69
|
+
'Toggle god mode (i.e. invincible)',
|
70
|
+
'Toggle beast mode (i.e. super strength)',
|
71
|
+
'List all GameAssets',
|
72
|
+
'List all instances of a specific entity type',
|
73
|
+
'List all the variables in the world',
|
74
|
+
'Show a map of the world',
|
75
|
+
'Change player stat',
|
76
|
+
'Change world global variable',
|
77
|
+
'Teleport to coordinates (5 0 0) or name (\'Home\')',
|
78
|
+
'Spawn random monster',
|
79
|
+
'Bump your character up *n* levels',
|
80
|
+
'Rest, but ensure battle for testing'
|
81
|
+
]
|
82
|
+
|
83
|
+
self.commands = %w(character look rest take talk inventory use open drop equip unequip go north east south west attack breakthru change version checkupdate help quit quit!)
|
84
|
+
self.aliases = %w(c l r t tk i u o d eq ue g n e s w a br ch v cu h q qq)
|
85
|
+
self.extras = %w(exit exit! x xx fight f ? ?? ???)
|
86
|
+
self.cmd_descriptions = [
|
87
|
+
'Display character information',
|
88
|
+
'Look around your current location',
|
89
|
+
'Take a load off and regain HP',
|
90
|
+
'Take item',
|
91
|
+
'Talk to person',
|
92
|
+
'Look in your inventory',
|
93
|
+
'Use item (in inventory or environment)',
|
94
|
+
'Open item (in inventory or environment)',
|
95
|
+
'Drop item',
|
96
|
+
'Equip item',
|
97
|
+
'Unequip item',
|
98
|
+
'Go in a direction',
|
99
|
+
'Go north (shortcut)',
|
100
|
+
'Go east (shortcut)',
|
101
|
+
'Go south (shortcut)',
|
102
|
+
'Go west (shortcut)',
|
103
|
+
'Attack a monster (also fight)',
|
104
|
+
'Teleport to a location (if you are experienced enough)',
|
105
|
+
'Change attribute',
|
106
|
+
'Display game version',
|
107
|
+
'Check for newer game releases',
|
108
|
+
'This help menu (also ?)',
|
109
|
+
'Quit w/ confirmation (also exit/x)',
|
110
|
+
'Quit w/o confirmation (also exit!/xx)'
|
111
|
+
]
|
112
|
+
end
|
113
|
+
|
114
|
+
def parse(input)
|
115
|
+
case input
|
116
|
+
# Ctrl-D or empty command
|
117
|
+
when nil, ''
|
118
|
+
return
|
119
|
+
# real command
|
120
|
+
else
|
121
|
+
return ERROR_COMMAND_INVALID.colorize(:red) unless input_valid?(input)
|
122
|
+
end
|
123
|
+
|
124
|
+
tokens = input.split
|
125
|
+
command = tokens.first.downcase
|
126
|
+
param1 = tokens[1]
|
127
|
+
param2 = tokens[2]
|
128
|
+
param3 = tokens[3]
|
129
|
+
|
130
|
+
# helpful
|
131
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
132
|
+
|
133
|
+
# dev commands
|
134
|
+
if GameOptions.data['debug_mode']
|
135
|
+
case command
|
136
|
+
when 'god', 'gd'
|
137
|
+
GameOptions.data['god_mode'] = !GameOptions.data['god_mode']
|
138
|
+
return "God mode set to #{GameOptions.data['god_mode']}"
|
139
|
+
when 'beast', 'bs'
|
140
|
+
GameOptions.data['beast_mode'] = !GameOptions.data['beast_mode']
|
141
|
+
return "Beast mode set to #{GameOptions.data['beast_mode']}"
|
142
|
+
when 'constants', 'cn'
|
143
|
+
puts 'GameCreatures'.colorize(:yellow)
|
144
|
+
puts GameCreatures.data
|
145
|
+
STDIN.getc
|
146
|
+
puts 'GameMonsters'.colorize(:yellow)
|
147
|
+
puts GameMonsters.data
|
148
|
+
STDIN.getc
|
149
|
+
puts 'GamePeople'.colorize(:yellow)
|
150
|
+
puts GamePeople.data
|
151
|
+
STDIN.getc
|
152
|
+
puts 'GameItems'.colorize(:yellow)
|
153
|
+
puts GameItems.data
|
154
|
+
STDIN.getc
|
155
|
+
puts 'GameArmor'.colorize(:yellow)
|
156
|
+
puts GameArmor.data
|
157
|
+
STDIN.getc
|
158
|
+
puts 'GameWeapons'.colorize(:yellow)
|
159
|
+
puts GameWeapons.data
|
160
|
+
when 'vars', 'vs'
|
161
|
+
if param1
|
162
|
+
world.print_vars(param1)
|
163
|
+
else
|
164
|
+
world.print_vars
|
165
|
+
end
|
166
|
+
when 'list', 'ls'
|
167
|
+
if param1.nil?
|
168
|
+
puts ERROR_LIST_PARAM_MISSING
|
169
|
+
return DEBUG_LIST_PARAMS
|
170
|
+
else
|
171
|
+
return world.list(param1, param2)
|
172
|
+
end
|
173
|
+
when 'map', 'm'
|
174
|
+
world.print_map(param1)
|
175
|
+
when 'stat', 'st'
|
176
|
+
if param1.nil?
|
177
|
+
puts ERROR_DEBUG_STAT_PARAM_MISSING
|
178
|
+
return DEBUG_STAT_PARAMS
|
179
|
+
else
|
180
|
+
case param1
|
181
|
+
when 'hp_cur', 'hp'
|
182
|
+
unless param2.nil?
|
183
|
+
param2 = param2.to_i
|
184
|
+
if param2.is_a? Numeric
|
185
|
+
if param2 > 0
|
186
|
+
world.player.hp_cur = param2
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
when 'atk_lo'
|
191
|
+
unless param2.nil?
|
192
|
+
param2 = param2.to_i
|
193
|
+
if param2.is_a? Numeric
|
194
|
+
if param2 >= 0
|
195
|
+
world.player.atk_lo = param2
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
when 'atk_hi'
|
200
|
+
unless param2.nil?
|
201
|
+
param2 = param2.to_i
|
202
|
+
if param2.is_a? Numeric
|
203
|
+
if param2 >= 0
|
204
|
+
world.player.atk_hi = param2
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
when 'strength', 'str', 'st'
|
209
|
+
unless param2.nil?
|
210
|
+
param2 = param2.to_i
|
211
|
+
if param2.is_a? Numeric
|
212
|
+
if param2 >= 0
|
213
|
+
world.player.atk_lo = param2
|
214
|
+
world.player.atk_hi = param2
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
when 'dexterity', 'dex'
|
219
|
+
unless param2.nil?
|
220
|
+
param2 = param2.to_i
|
221
|
+
if param2.is_a? Numeric
|
222
|
+
if param2 >= 0
|
223
|
+
world.player.dexterity = param2
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
when 'defense', 'def'
|
228
|
+
unless param2.nil?
|
229
|
+
param2 = param2.to_i
|
230
|
+
if param2.is_a? Numeric
|
231
|
+
if param2 >= 0
|
232
|
+
world.player.defense = param2
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
when 'rox', 'r', '$'
|
237
|
+
unless param2.nil?
|
238
|
+
param2 = param2.to_i
|
239
|
+
if param2.is_a? Numeric
|
240
|
+
if param2 >= 0
|
241
|
+
world.player.rox = param2
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
when 'experience', 'xp'
|
246
|
+
unless param2.nil?
|
247
|
+
param2 = param2.to_i
|
248
|
+
if param2.is_a? Numeric
|
249
|
+
if param2 >= 0
|
250
|
+
world.player.xp = param2
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
when 'inventory', 'inv'
|
255
|
+
unless param2.nil?
|
256
|
+
begin
|
257
|
+
item_const_name = Gemwarrior.const_get(Formatting.upstyle(param2, no_space: true))
|
258
|
+
item = item_const_name.new
|
259
|
+
world.player.inventory.items.push(item)
|
260
|
+
return "#{item.name.colorize(:yellow)} added to player inventory."
|
261
|
+
rescue
|
262
|
+
return ERROR_DEBUG_STAT_INV_PARAM_INVALID
|
263
|
+
end
|
264
|
+
end
|
265
|
+
else
|
266
|
+
return ERROR_DEBUG_STAT_PARAM_INVALID
|
267
|
+
end
|
268
|
+
end
|
269
|
+
when 'global', 'gl'
|
270
|
+
if param1.nil?
|
271
|
+
return world.instance_variables.join(', ')
|
272
|
+
elsif world.instance_variable_get("@#{param1}").nil?
|
273
|
+
return ERROR_DEBUG_GLOBAL_VAR_INVALID
|
274
|
+
elsif param2.nil?
|
275
|
+
return world.instance_variable_get("@#{param1}").to_s
|
276
|
+
else
|
277
|
+
val = false
|
278
|
+
val = param2.eql?('true') ? true : val
|
279
|
+
|
280
|
+
world.instance_variable_set("@#{param1}", val)
|
281
|
+
return "Instance variable #{param1} has been set to #{val}."
|
282
|
+
end
|
283
|
+
when 'spawn', 'sp'
|
284
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
285
|
+
player_cur_location.populate_monsters(GameMonsters.data, true, param1)
|
286
|
+
return world.describe(player_cur_location)
|
287
|
+
when 'teleport', 'tp'
|
288
|
+
if param1.nil?
|
289
|
+
return ERROR_DEBUG_TELEPORT_PARAMS_MISSING
|
290
|
+
else
|
291
|
+
if (param1.to_i.to_s == param1)
|
292
|
+
# we got at least an x coordinate
|
293
|
+
if (param2.to_i.to_s == param2)
|
294
|
+
# we got a y coordinate, too
|
295
|
+
x_coord = param1.to_i
|
296
|
+
y_coord = param2.to_i
|
297
|
+
# grab the z coordinate, if present, otherwise default to current level
|
298
|
+
z_coord = param3.to_i.to_s == param3 ? param3.to_i : world.player.cur_coords[:z]
|
299
|
+
|
300
|
+
# check to make sure new location exists
|
301
|
+
if world.location_by_coords(x: x_coord, y: y_coord, z: z_coord)
|
302
|
+
world.player.cur_coords = { x: x_coord, y: y_coord, z: z_coord }
|
303
|
+
else
|
304
|
+
return ERROR_DEBUG_TELEPORT_PARAMS_INVALID
|
305
|
+
end
|
306
|
+
else
|
307
|
+
# we only got an x coordinate
|
308
|
+
return ERROR_DEBUG_TELEPORT_PARAMS_NEEDED
|
309
|
+
end
|
310
|
+
else
|
311
|
+
# we got a place name instead, potentially
|
312
|
+
place_to_match = tokens[1..tokens.length].join(' ').downcase
|
313
|
+
locations = []
|
314
|
+
world.locations.each do |l|
|
315
|
+
locations << l.name.downcase
|
316
|
+
end
|
317
|
+
if locations.include?(place_to_match)
|
318
|
+
world.player.cur_coords = world.location_coords_by_name(place_to_match)
|
319
|
+
else
|
320
|
+
return ERROR_DEBUG_TELEPORT_PARAMS_INVALID
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
# stats
|
325
|
+
world.player.movements_made += 1
|
326
|
+
|
327
|
+
Animation.run(phrase: '** TELEPORT! **', speed: :insane)
|
328
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
329
|
+
return world.describe(player_cur_location)
|
330
|
+
end
|
331
|
+
when 'levelbump', 'lb'
|
332
|
+
new_level = param1.nil? ? 1 : param1.to_i
|
333
|
+
world.player.update_stats(reason: :level_bump, value: new_level)
|
334
|
+
when 'restfight', 'rf'
|
335
|
+
result = world.player.rest(world, 0, true)
|
336
|
+
|
337
|
+
if result.eql?('death')
|
338
|
+
player_death_resurrection
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
# normal commands
|
344
|
+
case command
|
345
|
+
when 'character', 'c'
|
346
|
+
# bypass puts so it prints out with newlines properly
|
347
|
+
print world.player.check_self
|
348
|
+
when 'inventory', 'i'
|
349
|
+
if param1
|
350
|
+
world.player.inventory.describe_item(param1)
|
351
|
+
else
|
352
|
+
world.player.list_inventory
|
353
|
+
end
|
354
|
+
when 'look', 'l'
|
355
|
+
if param1
|
356
|
+
# convert 'look at' to 'look'
|
357
|
+
if param1.eql?('at')
|
358
|
+
if param2
|
359
|
+
param1 = param2
|
360
|
+
else
|
361
|
+
return ERROR_LOOK_AT_PARAM_MISSING
|
362
|
+
end
|
363
|
+
end
|
364
|
+
world.describe_entity(player_cur_location, param1)
|
365
|
+
else
|
366
|
+
world.describe(player_cur_location)
|
367
|
+
end
|
368
|
+
when 'rest', 'r'
|
369
|
+
tent_uses = 0
|
370
|
+
player_inventory = world.player.inventory
|
371
|
+
|
372
|
+
if player_inventory.contains_item?('tent')
|
373
|
+
player_inventory.items.each do |i|
|
374
|
+
if i.name.eql?('tent')
|
375
|
+
if i.number_of_uses > 0
|
376
|
+
result = i.use(world)
|
377
|
+
tent_uses = i.number_of_uses
|
378
|
+
i.number_of_uses -= 1
|
379
|
+
|
380
|
+
puts ">> tent can be used when resting #{i.number_of_uses} more time(s)."
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
elsif player_cur_location.contains_item?('tent')
|
385
|
+
player_cur_location.items.each do |i|
|
386
|
+
if i.name.eql?('tent')
|
387
|
+
if i.number_of_uses > 0
|
388
|
+
result = i.use(world)
|
389
|
+
tent_uses = i.number_of_uses
|
390
|
+
i.number_of_uses -= 1
|
391
|
+
|
392
|
+
puts ">> tent can be used when resting #{i.number_of_uses} more time(s)."
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
result = world.player.rest(world, tent_uses)
|
399
|
+
|
400
|
+
if result.eql?('death')
|
401
|
+
player_death_resurrection
|
402
|
+
else
|
403
|
+
result
|
404
|
+
end
|
405
|
+
when 'take', 't'
|
406
|
+
if param1.nil?
|
407
|
+
ERROR_TAKE_PARAM_MISSING
|
408
|
+
else
|
409
|
+
world.player.inventory.add_item(param1, player_cur_location, world.player)
|
410
|
+
end
|
411
|
+
when 'talk', 'tk'
|
412
|
+
if param1.nil?
|
413
|
+
return ERROR_TALK_TO_PARAM_MISSING
|
414
|
+
elsif param1.eql?('to')
|
415
|
+
if param2
|
416
|
+
param1 = param2
|
417
|
+
else
|
418
|
+
return ERROR_TALK_TO_PARAM_MISSING
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
talkable_name = param1
|
423
|
+
|
424
|
+
player_inventory = world.player.inventory
|
425
|
+
|
426
|
+
if player_inventory.contains_item?(talkable_name)
|
427
|
+
player_inventory.items.each do |person|
|
428
|
+
if person.name.eql?(talkable_name)
|
429
|
+
if person.talkable
|
430
|
+
return self.parse("use #{talkable_name}")
|
431
|
+
else
|
432
|
+
return ERROR_TALK_PARAM_UNTALKABLE
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
elsif player_cur_location.contains_item?(talkable_name)
|
437
|
+
player_cur_location.items.each do |person|
|
438
|
+
if person.name.eql?(talkable_name)
|
439
|
+
if person.talkable
|
440
|
+
return self.parse("use #{talkable_name}")
|
441
|
+
else
|
442
|
+
return ERROR_TALK_PARAM_UNTALKABLE
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
elsif player_cur_location.has_monster?(talkable_name)
|
447
|
+
player_cur_location.monsters_abounding.each do |monster|
|
448
|
+
if monster.name.eql?(talkable_name)
|
449
|
+
if monster.talkable
|
450
|
+
return self.parse("use #{talkable_name}")
|
451
|
+
else
|
452
|
+
return ERROR_TALK_PARAM_UNTALKABLE
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
elsif player_cur_location.has_boss?(talkable_name)
|
457
|
+
player_cur_location.bosses_abounding.each do |boss|
|
458
|
+
if boss.name.eql?(talkable_name)
|
459
|
+
if boss.talkable
|
460
|
+
return self.parse("use #{talkable_name}")
|
461
|
+
else
|
462
|
+
return ERROR_TALK_PARAM_UNTALKABLE
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
when 'use', 'u', 'open', 'o'
|
468
|
+
if param1.nil?
|
469
|
+
ERROR_USE_PARAM_MISSING
|
470
|
+
else
|
471
|
+
item_name = param1
|
472
|
+
result = nil
|
473
|
+
|
474
|
+
player_inventory = world.player.inventory
|
475
|
+
|
476
|
+
if player_inventory.contains_item?(item_name)
|
477
|
+
player_inventory.items.each do |i|
|
478
|
+
if i.name.eql?(item_name)
|
479
|
+
if i.useable
|
480
|
+
if !i.number_of_uses.nil?
|
481
|
+
if i.number_of_uses > 0
|
482
|
+
result = i.use(world)
|
483
|
+
i.number_of_uses -= 1
|
484
|
+
puts ">> #{i.name} can be used #{i.number_of_uses} more time(s)."
|
485
|
+
break
|
486
|
+
else
|
487
|
+
return ">> #{i.name} cannot be used anymore."
|
488
|
+
end
|
489
|
+
elsif i.consumable
|
490
|
+
result = i.use(world)
|
491
|
+
world.player.inventory.remove_item(i.name)
|
492
|
+
break
|
493
|
+
else
|
494
|
+
result = i.use(world)
|
495
|
+
break
|
496
|
+
end
|
497
|
+
else
|
498
|
+
return ERROR_USE_PARAM_UNUSEABLE
|
499
|
+
end
|
500
|
+
end
|
501
|
+
end
|
502
|
+
elsif player_cur_location.contains_item?(item_name)
|
503
|
+
player_cur_location.items.each do |i|
|
504
|
+
if i.name.eql?(item_name)
|
505
|
+
if i.useable
|
506
|
+
if !i.number_of_uses.nil?
|
507
|
+
if i.number_of_uses > 0
|
508
|
+
result = i.use(world)
|
509
|
+
i.number_of_uses -= 1
|
510
|
+
puts ">> #{i.name} can be used #{i.number_of_uses} more time(s)."
|
511
|
+
break
|
512
|
+
else
|
513
|
+
return ">> #{i.name} cannot be used anymore."
|
514
|
+
end
|
515
|
+
elsif i.consumable
|
516
|
+
result = i.use(world)
|
517
|
+
location.remove_item(i.name)
|
518
|
+
break
|
519
|
+
else
|
520
|
+
result = i.use(world)
|
521
|
+
break
|
522
|
+
end
|
523
|
+
else
|
524
|
+
return ERROR_USE_PARAM_UNUSEABLE
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|
528
|
+
elsif player_cur_location.has_monster?(item_name)
|
529
|
+
player_cur_location.monsters_abounding.each do |i|
|
530
|
+
if i.name.eql?(item_name)
|
531
|
+
return i.use(world)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
elsif player_cur_location.has_boss?(item_name)
|
535
|
+
player_cur_location.bosses_abounding.each do |i|
|
536
|
+
if i.name.eql?(item_name)
|
537
|
+
return i.use(world)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
if result.nil?
|
543
|
+
ERROR_USE_PARAM_INVALID
|
544
|
+
else
|
545
|
+
case result[:type]
|
546
|
+
when 'move'
|
547
|
+
world.player.cur_coords = world.location_coords_by_name(result[:data])
|
548
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
549
|
+
world.describe(player_cur_location)
|
550
|
+
when 'move_dangerous'
|
551
|
+
dmg = rand(0..2)
|
552
|
+
puts ">> You lose #{dmg} hit point(s)." if dmg > 0
|
553
|
+
world.player.take_damage(dmg)
|
554
|
+
|
555
|
+
world.player.cur_coords = world.location_coords_by_name(result[:data])
|
556
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
557
|
+
world.describe(player_cur_location)
|
558
|
+
when 'dmg'
|
559
|
+
result = world.player.take_damage(result[:data])
|
560
|
+
|
561
|
+
if result.eql?('death')
|
562
|
+
player_death_resurrection
|
563
|
+
end
|
564
|
+
when 'rest', 'health'
|
565
|
+
world.player.heal_damage(result[:data])
|
566
|
+
return
|
567
|
+
when 'xp'
|
568
|
+
world.player.update_stats(reason: :xp, value: result[:data])
|
569
|
+
return
|
570
|
+
when 'tent'
|
571
|
+
world.player.rest(world, result[:data])
|
572
|
+
when 'action'
|
573
|
+
case result[:data]
|
574
|
+
when 'map'
|
575
|
+
world.print_map(world.player.cur_coords[:z])
|
576
|
+
end
|
577
|
+
when 'arena'
|
578
|
+
arena = Arena.new(world: world, player: world.player)
|
579
|
+
result = arena.start
|
580
|
+
|
581
|
+
if result.eql?('death')
|
582
|
+
player_death_resurrection
|
583
|
+
end
|
584
|
+
when 'item'
|
585
|
+
player_cur_location.add_item(result[:data])
|
586
|
+
return
|
587
|
+
when 'purchase'
|
588
|
+
result[:data].each do |i|
|
589
|
+
world.player.inventory.items.push(i)
|
590
|
+
end
|
591
|
+
return
|
592
|
+
else
|
593
|
+
return
|
594
|
+
end
|
595
|
+
end
|
596
|
+
end
|
597
|
+
when 'drop', 'd'
|
598
|
+
if param1.nil?
|
599
|
+
ERROR_DROP_PARAM_MISSING
|
600
|
+
else
|
601
|
+
world.player.inventory.drop_item(param1, player_cur_location)
|
602
|
+
end
|
603
|
+
when 'equip', 'eq'
|
604
|
+
if param1.nil?
|
605
|
+
ERROR_EQUIP_PARAM_MISSING
|
606
|
+
else
|
607
|
+
world.player.inventory.equip_item(param1)
|
608
|
+
end
|
609
|
+
when 'unequip', 'ue'
|
610
|
+
if param1.nil?
|
611
|
+
ERROR_UNEQUIP_PARAM_MISSING
|
612
|
+
else
|
613
|
+
world.player.inventory.unequip_item(param1)
|
614
|
+
end
|
615
|
+
when 'go', 'g'
|
616
|
+
if param1.nil?
|
617
|
+
puts ERROR_GO_PARAM_MISSING
|
618
|
+
GO_PARAMS
|
619
|
+
else
|
620
|
+
direction = param1
|
621
|
+
try_to_move_player(direction)
|
622
|
+
end
|
623
|
+
when 'n'
|
624
|
+
if param1
|
625
|
+
ERROR_DIRECTION_PARAM_INVALID
|
626
|
+
else
|
627
|
+
try_to_move_player('north')
|
628
|
+
end
|
629
|
+
when 'e'
|
630
|
+
if param1
|
631
|
+
ERROR_DIRECTION_PARAM_INVALID
|
632
|
+
else
|
633
|
+
try_to_move_player('east')
|
634
|
+
end
|
635
|
+
when 's'
|
636
|
+
if param1
|
637
|
+
ERROR_DIRECTION_PARAM_INVALID
|
638
|
+
else
|
639
|
+
try_to_move_player('south')
|
640
|
+
end
|
641
|
+
when 'w'
|
642
|
+
if param1
|
643
|
+
ERROR_DIRECTION_PARAM_INVALID
|
644
|
+
else
|
645
|
+
try_to_move_player('west')
|
646
|
+
end
|
647
|
+
when 'attack', 'a', 'fight', 'f'
|
648
|
+
if param1.nil?
|
649
|
+
if GameOptions.data['fight_completion']
|
650
|
+
if player_cur_location.has_any_monsters?
|
651
|
+
monster_param = player_cur_location.monsters_abounding[0].name
|
652
|
+
self.parse("attack #{monster_param}")
|
653
|
+
else
|
654
|
+
ERROR_ATTACK_PARAM_INVALID
|
655
|
+
end
|
656
|
+
else
|
657
|
+
ERROR_ATTACK_PARAM_MISSING
|
658
|
+
end
|
659
|
+
else
|
660
|
+
monster_name = param1
|
661
|
+
if world.has_monster_to_attack?(monster_name)
|
662
|
+
monster = player_cur_location.monster_by_name(monster_name)
|
663
|
+
result = world.player.attack(world, monster, param2)
|
664
|
+
|
665
|
+
if result.eql?('death')
|
666
|
+
return player_death_resurrection
|
667
|
+
elsif result.eql?('exit')
|
668
|
+
return 'exit'
|
669
|
+
end
|
670
|
+
|
671
|
+
unless result.nil?
|
672
|
+
case result[:type]
|
673
|
+
when 'message'
|
674
|
+
result[:data]
|
675
|
+
when 'move'
|
676
|
+
world.player.cur_coords = world.location_coords_by_name(result[:data])
|
677
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
678
|
+
world.describe(player_cur_location)
|
679
|
+
end
|
680
|
+
end
|
681
|
+
else
|
682
|
+
ERROR_ATTACK_PARAM_INVALID
|
683
|
+
end
|
684
|
+
end
|
685
|
+
when 'breakthru', 'br'
|
686
|
+
if world.player.special_abilities.include?(:breakthru)
|
687
|
+
if param1.nil?
|
688
|
+
return ERROR_BREAKTHRU_PARAM_MISSING
|
689
|
+
else
|
690
|
+
place_to_match = tokens[1..tokens.length].join(' ').downcase
|
691
|
+
locations = []
|
692
|
+
world.locations.each do |l|
|
693
|
+
locations << l.name.downcase
|
694
|
+
end
|
695
|
+
if locations.include?(place_to_match)
|
696
|
+
world.player.cur_coords = world.location_coords_by_name(place_to_match)
|
697
|
+
else
|
698
|
+
return ERROR_BREAKTHRU_PARAM_INVALID
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
# stats
|
703
|
+
world.player.movements_made += 1
|
704
|
+
|
705
|
+
Animation.run(phrase: '** BREAK THROUGH! **')
|
706
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
707
|
+
return world.describe(player_cur_location)
|
708
|
+
else
|
709
|
+
ERROR_BREAKTHRU_INEXPERIENCED
|
710
|
+
end
|
711
|
+
when 'change', 'ch'
|
712
|
+
if param1.nil?
|
713
|
+
puts ERROR_CHANGE_PARAM_MISSING
|
714
|
+
CHANGE_PARAMS
|
715
|
+
else
|
716
|
+
case param1
|
717
|
+
when 'name'
|
718
|
+
world.player.modify_name
|
719
|
+
else
|
720
|
+
ERROR_CHANGE_PARAM_INVALID
|
721
|
+
end
|
722
|
+
end
|
723
|
+
when 'help', 'h', '?', '??', '???'
|
724
|
+
list_commands
|
725
|
+
when 'version', 'v'
|
726
|
+
Gemwarrior::VERSION
|
727
|
+
when 'checkupdate', 'cu'
|
728
|
+
'checkupdate'
|
729
|
+
when 'quit', 'exit', 'q', 'x'
|
730
|
+
print 'You sure you want to quit? (y/n) '
|
731
|
+
answer = gets.chomp.downcase
|
732
|
+
|
733
|
+
case answer
|
734
|
+
when 'y', 'yes'
|
735
|
+
puts QUIT_MESSAGE.colorize(:yellow)
|
736
|
+
return 'exit'
|
737
|
+
else
|
738
|
+
puts RESUME_MESSAGE.colorize(:green)
|
739
|
+
end
|
740
|
+
when 'quit!', 'exit!', 'qq', 'xx'
|
741
|
+
puts QUIT_MESSAGE.colorize(:yellow)
|
742
|
+
return 'exit'
|
743
|
+
else
|
744
|
+
return
|
745
|
+
end
|
746
|
+
end
|
747
|
+
|
748
|
+
private
|
749
|
+
|
750
|
+
def try_to_move_player(direction)
|
751
|
+
if world.can_move?(direction)
|
752
|
+
world.player.go(world, direction)
|
753
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
754
|
+
player_cur_location.checked_for_monsters = false
|
755
|
+
|
756
|
+
if player_cur_location.name.include?('pain_quarry')
|
757
|
+
if player_cur_location.has_boss?('garynetty')
|
758
|
+
roll = rand(0..100) + world.player.dexterity
|
759
|
+
roll_display = roll < 25 ? "#{roll}".colorize(:red) : "#{roll}".colorize(:green)
|
760
|
+
puts "[Pain Quarry Garynetty Roll: #{roll_display}]" if GameOptions.data['debug_mode']
|
761
|
+
if roll < 25
|
762
|
+
self.parse("attack garynetty is_ambush")
|
763
|
+
else
|
764
|
+
puts 'You nearly got attacked by a vicious Garynetty! Be careful, your next move might not be as lucky.'.colorize(:yellow)
|
765
|
+
end
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
world.describe(player_cur_location)
|
770
|
+
else
|
771
|
+
return ERROR_GO_PARAM_INVALID.colorize(:red)
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
775
|
+
def player_death_resurrection
|
776
|
+
Audio.play_synth(:player_resurrection)
|
777
|
+
|
778
|
+
puts 'Somehow, though, your adventure does not end here!'.colorize(:yellow)
|
779
|
+
puts 'Instead, you are whisked back home via some magical force.'.colorize(:yellow)
|
780
|
+
puts 'A bit worse for the weary and somewhat poorer, but you are ALIVE!'.colorize(:yellow)
|
781
|
+
puts
|
782
|
+
|
783
|
+
world.player.hp_cur = 1
|
784
|
+
world.player.rox -= (world.player.rox * 0.1).to_i
|
785
|
+
if world.player.rox < 0
|
786
|
+
world.player.rox = 0
|
787
|
+
end
|
788
|
+
world.player.cur_coords = world.location_coords_by_name('Home')
|
789
|
+
player_cur_location = world.location_by_coords(world.player.cur_coords)
|
790
|
+
world.describe(player_cur_location)
|
791
|
+
world.player.deaths += 1
|
792
|
+
return
|
793
|
+
end
|
794
|
+
|
795
|
+
def list_commands
|
796
|
+
i = 0
|
797
|
+
Hr.print('=')
|
798
|
+
puts ' COMMAND | ALIAS | DESCRIPTION '
|
799
|
+
Hr.print('=')
|
800
|
+
commands.each do |cmd|
|
801
|
+
puts " #{cmd.ljust(11)} | #{aliases[i].ljust(5)} | #{cmd_descriptions[i]}"
|
802
|
+
i += 1
|
803
|
+
end
|
804
|
+
Hr.print('=')
|
805
|
+
|
806
|
+
if GameOptions.data['debug_mode']
|
807
|
+
puts ' DEBUG COMMANDS'
|
808
|
+
Hr.print('=')
|
809
|
+
i = 0
|
810
|
+
devcommands.each do |cmd|
|
811
|
+
puts " #{cmd.ljust(11)} | #{devaliases[i].ljust(5)} | #{devcmd_descriptions[i]}"
|
812
|
+
i += 1
|
813
|
+
end
|
814
|
+
Hr.print('=')
|
815
|
+
end
|
816
|
+
end
|
817
|
+
|
818
|
+
def input_valid?(input)
|
819
|
+
tokens = input.split
|
820
|
+
command = tokens[0]
|
821
|
+
commands_and_aliases = commands | aliases | extras
|
822
|
+
|
823
|
+
if GameOptions.data['debug_mode']
|
824
|
+
commands_and_aliases = commands_and_aliases | devcommands | devaliases | devextras
|
825
|
+
end
|
826
|
+
|
827
|
+
if commands_and_aliases.include?(command.downcase)
|
828
|
+
if tokens.size.between?(1, 4)
|
829
|
+
return true
|
830
|
+
end
|
831
|
+
elsif tokens.empty?
|
832
|
+
return true
|
833
|
+
end
|
834
|
+
end
|
835
|
+
end
|
836
|
+
end
|