Euler
09-14-2015, 10:16 AM
I am trying to learn RUBY because I haven't programmed since BASIC on my VIC-20. (Ok I lie. I had a Commodore 64 too)
I made this script to keep sigils up because the one in the repo kept blowing my nerves and popping my muscles. I think it is ok, but I would like feedback, even unkind feedback. Also, I feel like it makes me lag, but I may be imagining this.
The idea is that I made an array for sigils. The array consists of sigils[counter number, sigil number, stamina cost, mana cost]
the loop looks at the counter number and checks if that sigil of up. if it isn't then it checks for available stamina and mana and casts. Then the counter moves up one and the array is changed to the next sigil. etc.
ok, open fire on the code:
sigil=[1, 9714, 30, 0]
loop do
if checkstamina >=50 && checkmana <= sigil[3]
fput "sigil of power"
elsif sigil[0]==1; sigil=[1, 9714, 30, 0]
elsif sigil[0]==2; sigil=[2, 9705, 3, 3]
elsif sigil[0]==3; sigil=[3, 9707, 5, 5]
elsif sigil[0]==4; sigil=[4, 9708, 5, 5]
elsif sigil[0]==5; sigil=[5, 9710, 10, 5]
elsif sigil[0]==6; sigil=[6, 9711, 5, 5]
elsif sigil[0]==7; sigil=[7, 9715, 10, 10]
elsif sigil[0]==8; sigil=[8, 9708, 15, 10]
elsif sigil[0]==9; sigil=[9, 9713, 15, 10]
elsif sigil[0]=10; sigil=[1, 9714, 30, 0]
end
if !Spell[sigil[1]].active? && checkstamina >= sigil[2] && checkmana >= sigil[3]
Spell[sigil[1]].cast
end
sigil[0] +=1
end
Gnomad
09-14-2015, 11:17 AM
Most of this is available through Lich's built-in Spell support already, and Ruby is pretty darn awesome too, so you're really reinventing the wheel here.
Ruby has some very useful methods built-in to all of its objects: .inspect (to see what it has) and .methods (to see what it can do). Note that Ruby will give you a bunch of methods automatically, so feel free to ignore any weird-looking ones.
So:
;exec echo Spell[9714].inspect
--- Lich: exec2 active.
[exec2: #<Games::Gemstone::Spell:0x145a9448 @num=9714, @name="Sigil of Concentration", @type="bonus", @no_incant=false, @availability="self-cast", @bonus={}, @msgup="As you concentrate on your sigil, you feel more attuned to the flows of mana\\.", @msgdn="Your heightened attunement to the flows of mana begins to fade\\.", @stance=false, @channel=false, @cost={"stamina"=>{"self"=>"30"}}, @duration={"self"=>{:duration=>"10", :stackable=>false, :refreshable=>false, :multicastable=>false, :max_duration=>250.0}}, @real_time=false, @persist_on_death=false, @cast_proc="dothistimeout 'sigil of concentration', 3, /^As you concentrate on your sigil, you feel more attuned to the flows of mana\\.$|^Your muscles ache much too badly to even think about attempting this maneuver\\.$|^The power from your sigil dissipates into the air\\.$/", @timestamp=2015-09-14 10:45:27 -0400, @timeleft=0, @active=false, @circle="97">]
Let's break that down into individual lines:
<Games::Gemstone::Spell:0x145a9448
@num=9714,
@name="Sigil of Concentration",
@type="bonus",
@no_incant=false,
@availability="self-cast",
@bonus={},
@msgup="As you concentrate on your sigil, you feel more attuned to the flows of mana\\.",
@msgdn="Your heightened attunement to the flows of mana begins to fade\\.",
@stance=false,
@channel=false,
@cost={"stamina"=>{"self"=>"30"}},
@duration={"self"=>{:duration=>"10", :stackable=>false, :refreshable=>false, :multicastable=>false, :max_duration=>250.0}},
@real_time=false,
@persist_on_death=false,
@cast_proc="dothistimeout 'sigil of concentration', 3, /^As you concentrate on your sigil, you feel more attuned to the flows of mana\\.$|^Your muscles ache much too badly to even think about attempting this maneuver\\.$|^The power from your sigil dissipates into the air\\.$/",
@timestamp=2015-09-14 10:45:27 -0400,
@timeleft=0,
@active=false,
@circle="97">
Similarly:
;exec echo Spell[9714].methods
--- Lich: exec2 active.
[exec2: [:num, :name, :timestamp, :msgup, :msgdn, :circle, :active, :type, :cast_proc, :real_time, :persist_on_death, :availability, :no_incant, :stance, :stance=, :channel, :channel=, :time_per_formula, :time_per, :timeleft=, :timeleft, :minsleft, :secsleft, :active=, :active?, :stackable?, :refreshable?, :multicastable?, :known?, :available?, :to_s, :max_duration, :putup, :putdown, :remaining, :affordable?, :cast, :_bonus, :_cost, :method_missing, :circle_name, :clear_on_death, :duration, :cost, :manaCost, :spiritCost, :staminaCost, :boltAS, :physicalAS, :boltDS, :physicalDS, :elementalCS, :mentalCS, :spiritCS, :sorcererCS, :elementalTD, :mentalTD, :spiritTD, :sorcererTD, :castProc, :stacks, :command, :circlename, :selfonly, :dclone, :waitrt?, :waitcastrt?, :lichnet_get_spells, :ubWoundsFullDis, :ubWoundsChangeDis, :ubWoundsMash, :spam, :unspam, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]]
I'm not going to itemize each of these, but :active?, :affordable?, and :cast are the big ones. (Note that Ruby, as a convention but not by requirement, uses ? at the end of Boolean methods.)
So you can change that last bit to:
if !Spell[sigil[1]].active? && Spell[sigil[1]].affordable?
Spell[sigil[1]].cast
end
Good? Good.
Ruby also supports native enumerators, which are awesome. If you give it an array (or lots of other collections), it can go through one-by-one without you needing to write heavy loops. So make an array of all the sigils you want.
sigils = [9714, 9705, 9707, 9708, 9710, 9711, 9715, 9708, 9713, 9714]
Then iterate through it in a block demarcated by {}. The variable between the pipes sigil holds the current object from your array sigils.
sigils = [9714, 9705, 9707, 9708, 9710, 9711, 9715, 9708, 9713, 9714]
sigils.each { |sigil|
if !Spell[sigil].active? && Spell[sigil].affordable?
Spell[sigil].cast
end
}
Cool? Cool.
You can also write the whole thing on one line, if you're into that sort of thing. I don't find it as good for learning, but that'll let you write this as an alias in Lich.
[9714, 9705, 9707, 9708, 9710, 9711, 9715, 9708, 9713, 9714].each { |sigil| Spell[sigil].cast if !Spell[sigil].active? && Spell[sigil].affordable? }
PS: I'm a little out of it this morning, so other coders: if I f'ed any of this up, please correct.
edit: Realized I didn't make it loop, and didn't include Sigil of Power usage. Still, it's a start.
Gnomad
09-14-2015, 11:11 PM
You can see them by loading up Lich.rbw and searching for the method name. They're not amazingly instructive, but I'll go through one.
Let's take a look at .affordable?
def affordable?(options={})
# fixme: deal with them dirty bards!
release_options = options.dup
release_options[:multicast] = nil
if (self.mana_cost(options) > 0) and ( !checkmana(self.mana_cost(options)) or (Spell[515].active? and !checkmana(self.mana_cost(options) + [self.mana_cost(release_options)/4, 1].max)) )
false
elsif (self.stamina_cost(options) > 0) and (Spell[9699].active? or not checkstamina(self.stamina_cost(options)))
false
elsif (self.spirit_cost(options) > 0) and not checkspirit(self.spirit_cost(options) + 1 + [ 9912, 9913, 9914, 9916, 9916, 9916 ].delete_if { |num| !Spell[num].active? }.length)
false
else
true
end
end
options = {} makes the parameter options optional, with a default value of an empty hash.
release_options duplicates the options passed to the function and then sets its :mulitcast entry to nil, because multicast doesn't come into play when releasing spells, only when casting. No reason to think of 120 costing as costing 40 mana when you're just releasing it anyway. (If it wasn't duplicated, then changing release_options would also change the original options.)
By the way, :words_that_start_with_colons in Ruby are symbols. They're essentially slimmer and less versatile string literals. You generally use them internally. Tillmen could have used "multicast" throughout his instead of :multicast, but he'd have gotten a bunch of unnecessary overhead. Google if you want, but I would save that for later.
# is the comment character.
This method exists in the Spell class. If you're calling .affordable?, you've almost definitely made a Spell object and given it a spell number already, probably just by doing Spell[9714].affordable? Every instance of the word self just refers to the current spell object.
So now we run through the 3 cases that the spell might not be affordable: mana, stamina, and spirit. All of the spell's data have been loaded into its object already (see .inspect) from another file, spell-list.xml.
First it checks for each whether the spell actually costs mana/stamina/spirit. These are listed first because if the first half of the and statement evaluates false, then Ruby won't bother checking the rest of it. Short-circuit evaluation is important. Read up on it if you need to.
Then, it runs through each of the cases where you might not be able to afford it. 515 is rapid fire, so if you can't afford to release it after casting, you can't afford it. 9699 is the spell number for having blown your muscles. The 99XX are all the CoL spirit signs that could wear off, so their costs are added in if they're active or you'd get a big surprise in a few minutes.
If all of those pass, then you'll return true, and the spell is affordable. If not, you'll return false.
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.