Class: D3MPQ::ModCode::Stack

Inherits:
Object
  • Object
show all
Defined in:
lib/d3_mpq/mod_code.rb

Overview

Pseudo-Stack to compute min/max of current ModCode

Defined Under Namespace

Classes: StackValue

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Stack

Returns a new instance of Stack.



63
64
65
66
67
68
69
# File 'lib/d3_mpq/mod_code.rb', line 63

def initialize(data)
  @stack  = []
  @trace  = []
  @data   = *data
  @value  = nil
  parse
end

Instance Attribute Details

#traceObject (readonly)

Returns the value of attribute trace.



61
62
63
# File 'lib/d3_mpq/mod_code.rb', line 61

def trace
  @trace
end

#valueObject (readonly)

Returns the value of attribute value.



61
62
63
# File 'lib/d3_mpq/mod_code.rb', line 61

def value
  @value
end

Instance Method Details

#countObject



91
92
93
# File 'lib/d3_mpq/mod_code.rb', line 91

def count
  @stack.length
end

#empty?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/d3_mpq/mod_code.rb', line 95

def empty?
  count == 0
end

#inspectObject



159
160
161
# File 'lib/d3_mpq/mod_code.rb', line 159

def inspect
  { :value => @value, :trace => @trace}
end

#maxObject



75
76
77
# File 'lib/d3_mpq/mod_code.rb', line 75

def max
  @value ? @value.max : nil
end

#minObject



71
72
73
# File 'lib/d3_mpq/mod_code.rb', line 71

def min
  @value ? @value.min : nil
end

#op(&blk) ⇒ Object

Perform OP-Code



149
150
151
152
153
154
155
156
157
# File 'lib/d3_mpq/mod_code.rb', line 149

def op(&blk)
  b = pop
  a = pop

  formula, min, max = blk.call(a, b)

  push(StackValue.random(min, max || min))
  @trace << formula
end

#parseObject

Lets go



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/d3_mpq/mod_code.rb', line 100

def parse
  return @value if @value
  return nil if @data.empty?

  next_op = true
  @data.each_with_index do |dword, index|
    next_op = true and next unless next_op

    case dword.bytes.first
    when 0x00
      # return the value at the top of the stack
      raise "Return found, but Stack not empty!" if @data[index+1]
      @value = pop
      return @value
    when 0x01
      # call the function of the next op-code (just pass here)
    when 0x03
      # rand1(A,B); pop 2 numbers and push a random value between A and A+B
      op { |a, b| ["rand", a, a + b] }
    when 0x04
      # rand2(A,B); pop 2 numbers and push a random value between A and B
      op { |a, b| ["rand2", a, b] }
    when 0x06
      # push the next DWord onto the stack
      v = @data[index+1].unpack('F').first
      push(StackValue.new(v))
      @trace << "#{v}"
      next_op = false
    when 0x0B
      # add(A,B); pop 2 numbers and push the sum
      op { |a, b| ["add", (a + b)] }
    when 0x0C
      # sub(A,B); pop 2 numbers and push the difference
      op { |a, b| ["sub", (a - b)] }
    when 0x0D
      # mul(A,B); pop 2 numbers and push the product
      op { |a, b| ["mul", (a * b)] }
    when 0x0E
      # div(A,B); pop 2 numbers and push the quotient
      op { |a, b| ["div", (a / b)] }
    else
      raise "OP-Code not found: #{op} | #{@data.inspect}"
    end
  end

  raise "No return found: #{@data.inspect}"
end

#peekObject



87
88
89
# File 'lib/d3_mpq/mod_code.rb', line 87

def peek
  @stack.last
end

#popObject



83
84
85
# File 'lib/d3_mpq/mod_code.rb', line 83

def pop
  @stack.pop
end

#push(item) ⇒ Object



79
80
81
# File 'lib/d3_mpq/mod_code.rb', line 79

def push(item)
  @stack.push item
end