lomic 0.0.1

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Gilbert B Garza
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,22 @@
1
+ LICENSE
2
+ Manifest
3
+ README.rdoc
4
+ Rakefile
5
+ TODO
6
+ examples/nomic_initial_rules.rb
7
+ examples/priority.rb
8
+ examples/simple.rb
9
+ features/event_engine.feature
10
+ features/resource.feature
11
+ features/step_definitions/steps.rb
12
+ features/support/env.rb
13
+ features/var_init.feature
14
+ lib/lomic.rb
15
+ lib/lomic/Event.rb
16
+ lib/lomic/EventEngine.rb
17
+ lib/lomic/GameState.rb
18
+ lib/lomic/Lomic.rb
19
+ lib/lomic/LomicParser.rb
20
+ lib/lomic/Rule.rb
21
+ lomic.gemspec
22
+ parse.rb
data/README.rdoc ADDED
@@ -0,0 +1,55 @@
1
+ = Lomic
2
+
3
+ Lomic is a Domain Specific Language (DSL) intended to be used for Pomic, a programming version of the game Nomic.
4
+
5
+ == What does Lomic look like?
6
+
7
+ Lomic is designed to be expressive in declaring rules for the game Nomic:
8
+
9
+ class Globals < Lomic
10
+ var :players => []
11
+ var :currentPlayer
12
+ end
13
+
14
+ class Player < Lomic
15
+ resource :hp => 15 # resources have a max and min value
16
+ end
17
+
18
+ rule 101 do |g| # g refers to globals
19
+ ### The game begins with 4 players.
20
+ ### Each player is assigned a unique number.
21
+ event "game:start" do
22
+ Player.new_var :number => 0
23
+ 4.times do |i|
24
+ p = Player.new
25
+ p.number = i
26
+ g.players.push(p)
27
+ end
28
+ end
29
+ end
30
+
31
+ rule 102 do |g|
32
+ ### At the beginning of each player's turn,
33
+ ### that player takes 3 damage
34
+ event "turn:start" do
35
+ currentPlayer.hp -= 3
36
+ end
37
+ end
38
+
39
+ == Getting Started
40
+
41
+ Download the source and run an example:
42
+
43
+ $ git clone git://github.com/mindeavor/Lomic.git
44
+ $ cd Lomic
45
+ $ ruby parse.rb examples/simple.rb
46
+
47
+ Check out the `examples/` folder to see what Lomic is supposed to look like, and `parse.rb` to see how to use Lomic (in its current, underdeveloped state)
48
+
49
+ == Contributing
50
+
51
+ Lomic is currently in the concept and development stage. To discuss contributing, syntax, goals, or implementation, join us at #lomic on irc.freenode, or email me at gilbertbgarza aT gmail
52
+
53
+ == Copyright
54
+
55
+ Copyright (c) 2010 Gilbert B Garza. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,65 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "lomic"
8
+ gem.summary = %Q{A Ruby DSL for the game Nomic}
9
+ gem.description = %Q{Lomic is a Domain Specific Language (DSL) intended to be used for Pomic, a programming version of the game Nomic.}
10
+ gem.email = "gilbertbgarza@gmail.com"
11
+ gem.homepage = "http://github.com/mindeavor/lomic"
12
+ gem.authors = ["Gilbert B Garza"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_development_dependency "cucumber", ">= 0.8.0"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ begin
45
+ require 'cucumber/rake/task'
46
+ Cucumber::Rake::Task.new(:features)
47
+
48
+ task :features => :check_dependencies
49
+ rescue LoadError
50
+ task :features do
51
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
52
+ end
53
+ end
54
+
55
+ task :default => :test
56
+
57
+ require 'rake/rdoctask'
58
+ Rake::RDocTask.new do |rdoc|
59
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
60
+
61
+ rdoc.rdoc_dir = 'rdoc'
62
+ rdoc.title = "lomic #{version}"
63
+ rdoc.rdoc_files.include('README*')
64
+ rdoc.rdoc_files.include('lib/**/*.rb')
65
+ end
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ * Network communication via send and listen
2
+ * Rule source code reloading to support rule changing
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 1
5
+ :build:
@@ -0,0 +1,184 @@
1
+ class Player < Lomic
2
+ var :number
3
+ end
4
+
5
+ # global data: all lomic functions search exclusively in this class for global variables
6
+ class Globals < Lomic
7
+ var :currentRule # Rule is a built-in class type
8
+ var :ruleChangeType => ""
9
+
10
+ var :players => []
11
+ var :currentPlayer
12
+
13
+ var :num => 99
14
+
15
+ var :turnCounter => 0, :ruleCounter => 301
16
+
17
+ var :playersVoted => Set.new
18
+ var :votesUnanimous => false # since this is a boolean, it's accessed with: votesUnanimous?
19
+ end
20
+
21
+ # Rules
22
+
23
+ # Rules recieve events in the order of their priority *for that event* (standard is 5)
24
+ # If two rules have the same priority, the lowest rule number goes first
25
+
26
+ # A failed cond will cause the rule to ignore the event
27
+ # A failed assert will cause the rule to kill the event entirely and
28
+ # set the next event to "assert:fail" with failed_event containing
29
+ # the name of the failed event
30
+
31
+ # Both cond and assert failures will cause the rule to stop executing.
32
+
33
+ rule 102 do |g|
34
+ ### Initially the rules in the 100's are immutable and rules in
35
+ ### the 200's are mutable. Rules subsequently enacted or transmuted
36
+ ### (that is, changed from immutable to mutable or vice versa) may be
37
+ ### immutable or mutable regardless of their numbers, and rules in the
38
+ ### Initial Set may be transmuted regardless of their numbers
39
+ event "game:start" do
40
+ # create a new accessible variable in the Rule class initialized to false
41
+ Rule.new_var :immutable => false
42
+ # rules is a reserved global array
43
+ g.rules.each do |r|
44
+ r.immutable = true if r.number >= 100 and r.number < 200
45
+ end
46
+ end
47
+
48
+ event "rule:change", :priority => 1 do
49
+ cond g.ruleChangeType == "transmute"
50
+ assert g.currentRule.immutable == false
51
+ end
52
+ end
53
+
54
+ rule 103 do |g|
55
+ ### A rule change is any of the following:
56
+ ### (1) the enactment, repeal, or amendment of a mutable rule;
57
+ ### (2) the enactment, repeal, or amendment of an amendment of a mutable rule;
58
+ ### or (3) the transmutation of an immutable rule into a mutable rule or vice versa.
59
+ event "rule:change" do
60
+ assert g.ruleChangeType.isEither ["repeal","amendment","transmute"]
61
+ end
62
+ end
63
+
64
+ rule 104 do |g|
65
+ ### All rule-changes proposed in the proper way shall be voted on.
66
+ event "rule:change" do
67
+ set_next "players:vote"
68
+ end
69
+
70
+ ### They will be adopted if and only if they receive the required number of votes.
71
+ event "rule:voted" do
72
+ set_next "vote:unanimous?"
73
+ end
74
+ end
75
+
76
+ rule 105 do |g|
77
+ ### Every player is an eligible voter.
78
+ event "game:start" do
79
+ Player.new_var 'voter' => true
80
+ Player.new_var 'votedYes' => false
81
+ end
82
+
83
+ ### Every eligible voter must participate in every vote on rule-changes.
84
+ event "players:vote" do
85
+ # This will send JSON data over the network to the external manager
86
+ # that is managing this instance of Lomic
87
+ send "request:votes"
88
+ # This will listen for a message from the external manager and treat it an event
89
+ listen "player:vote"
90
+ end
91
+
92
+ event "player:vote" do
93
+ # start listening before the assertions in case one of them fails
94
+ # listening, like next_event, takes place after the code block is done executing
95
+ listen "player:vote"
96
+
97
+ assert g.currentPlayer.voter? == true
98
+ assert g.playersVoted.include? currentPlayer == false
99
+ playersVoted.add(currentPlayer)
100
+
101
+ allVoted = true
102
+ g.players.each do |p|
103
+ allVoted = false if p.voter? and g.playersVoted.include? p == false
104
+ end
105
+
106
+ if allVoted
107
+ listen :cancel # necessary because listening has higher priority over next_event
108
+ set_next "rule:voted"
109
+ end
110
+ end
111
+ end
112
+
113
+ rule 108 do |g|
114
+ ### Each proposed rule-change shall be given a number for reference.
115
+ ### The numbers shall begin with 301, and each rule-change proposed
116
+ ### in the proper way shall receive the next successive integer,
117
+ ### whether or not the proposal is adopted.
118
+ event "rule:passed" do
119
+ # store global data
120
+ # modify source code for rule currentRule.number
121
+ # reload source code
122
+ # reload global data
123
+ # set_next "rule:complete" on load
124
+ end
125
+ end
126
+
127
+ rule 201 do |g|
128
+ ### Players shall alternate in clockwise order, taking one whole turn apiece.
129
+ ### Turns may not be skipped or passed, and parts of turns may not be omitted.
130
+ ### All players begin with zero points.
131
+ event "game:start" do
132
+ Player.new_var 'points', 0
133
+ g.turnCounter = 0
134
+ g.currentPlayer = players[0]
135
+ set_next "turn:start"
136
+ end
137
+
138
+ event "turn:end" do
139
+ g.turnCounter += 1
140
+ g.currentPlayer = g.players[g.turnCounter % g.players.size]
141
+ set_next "turn:start"
142
+ end
143
+ end
144
+
145
+ rule 202 do |g|
146
+ ### One turn consists of two parts in this order:
147
+ ### (1) proposing one rule-change and having it voted on, and
148
+ event "turn:start" do
149
+ # prompt external manager for action
150
+ send :event => "request:action", :player => g.currentPlayer.number
151
+ g.ruleChangeType = listen "response:action"
152
+
153
+ set_next "rule:change"
154
+ end
155
+
156
+ ### (2) throwing one die once and adding the number of points on its face to one's score.
157
+ event "rule:complete" do
158
+ set_next "player:dice roll"
159
+ end
160
+
161
+ event "player:dice roll" do
162
+ g.currentPlayer.points += ran(6)
163
+ end
164
+ end
165
+
166
+ rule 203 do |g|
167
+ ### A rule-change is adopted if and only if the vote is unanimous among the eligible voters.
168
+ event "vote:unanimous?" do
169
+ g.votesUnanimous = true
170
+ g.votedPlayers.each { |p| g.votesUnanimous = false if p.votedYes? == false }
171
+ assert g.votesUnanimous?
172
+ end
173
+ end
174
+
175
+ rule 208 do |g|
176
+ ### The winner is the first player to achieve 100 (positive) points.
177
+ event "player:dice roll", :priority => 1 do
178
+ if g.currentPlayer.points >= 100
179
+ set_next "player:win by points"
180
+ else
181
+ set_next "turn:end"
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,35 @@
1
+ class Globals < Lomic
2
+ var :number => 100
3
+ end
4
+
5
+ rule 101 do |g| # g refers to globals
6
+ event "game:start" do
7
+ puts '[Example: priority.rb]'
8
+ g.number = 99
9
+ set_next "route:right"
10
+ end
11
+
12
+ # A lower priority number means it runs closer to the end.
13
+ # The default priority is 5, thus this event block
14
+ # runs last, having the last effect on set_next and g.number
15
+ event "game:start", :priority => 1 do
16
+ g.number = 77
17
+ set_next "route:left"
18
+ end
19
+
20
+ event "game:start" do
21
+ g.number = 55
22
+ set_next "route:right"
23
+ end
24
+
25
+ event "route:left" do
26
+ puts "The number is: #{g.number}"
27
+ puts "You went left!"
28
+ end
29
+
30
+ event "route:right" do
31
+ puts "The number is: #{g.number}"
32
+ puts "You went right!"
33
+ end
34
+ end
35
+
@@ -0,0 +1,15 @@
1
+ class Globals < Lomic
2
+ var :didiwin => 'No...'
3
+ end
4
+
5
+ rule 101 do |g| # g refers to globals
6
+ event "game:start" do
7
+ puts '[Example: simple.rb]'
8
+ g.didiwin = 'Yes!'
9
+ set_next "game:test1"
10
+ end
11
+
12
+ event "game:test1" do
13
+ puts "Did I win? #{g.didiwin}"
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ Feature: resources in class declarations
2
+ In order to remove boiler plate code
3
+ Resources auto generate convenience methods
4
+ Geared towards game resources
5
+ Such as hit points and energy
6
+
7
+ Scenario: Declaring a resource should generate additional variables
8
+ Given the Lomic inherited class MyClass
9
+ And the resource declaration HP with value 17
10
+ When I create a new MyClass object named foo
11
+ Then the result of foo.HP should be 17
12
+ And the result of foo.HPmax should be 17
13
+ And the result of foo.HPmin should be 0
14
+
15
+ Scenario: A resources should automatically be kept within its defined limits
16
+ Given the Lomic inherited class MyClass
17
+ And the resource declaration HP with value 17
18
+ And the resource declaration MP with value 5
19
+ When I create a new MyClass object named foo
20
+ And I add 33 to foo.HP
21
+ And I subtract 99 from foo.MP
22
+ Then the result of foo.HP should be 17
23
+ And the result of foo.MP should be 0
24
+
25
+ Scenario: Resource limits can be explicitly defined
26
+ Given the Lomic inherited class MyClass
27
+ And the resource declaration EXP with value [0,15,0]
28
+ And the resource declaration STR with value [1,5]
29
+ And the resource declaration HP with value [17]
30
+ When I create a new MyClass object named foo
31
+ Then the results of each <var> should be <val>:
32
+ | var | val |
33
+ | foo.EXP | 0 |
34
+ | foo.EXPmin | 0 |
35
+ | foo.EXPmax | 15 |
36
+ | foo.STR | 5 |
37
+ | foo.STRmin | 1 |
38
+ | foo.STRmax | 5 |
39
+ | foo.HP | 17 |
40
+ | foo.HPmin | 0 |
41
+ | foo.HPmax | 17 |
@@ -0,0 +1,39 @@
1
+ Given /^the Lomic inherited class (\w*)/ do |klass|
2
+ eval "class #{klass} < Lomic\nend"
3
+ @class = Kernel.const_get(klass)
4
+ end
5
+
6
+ When /^I create a new (\w*) object named (\w*)/ do |klass,obj_name|
7
+ eval "$#{obj_name} = #{klass}.new"
8
+ end
9
+
10
+ Then /^the result of (\w+)\.(\w+) should be (\w+)/ do |obj_name,var_name,result|
11
+ result == (eval "$#{obj_name}.#{var_name}")
12
+ end
13
+
14
+ Then /^the results of each <var> should be <val>/ do |table|
15
+ @alltrue = true
16
+ table.hashes.each do |h|
17
+ @alltrue = @alltrue and h[:val] == (eval "$#{h[:var]}")
18
+ end
19
+ @alltrue
20
+ end
21
+
22
+ ### general variables
23
+
24
+ When /^I (add|subtract) (\d+) (?:to|from) (.*)/ do |type,amt,var|
25
+ op = (type=='add') ? '+' : '-'
26
+ eval "$#{var} #{op}= #{amt}"
27
+ end
28
+
29
+ ### var declaration
30
+
31
+ Given /^the following var declarations:/ do |vars|
32
+ vars.hashes.each { |h| @class.class_eval h[:var_decl] }
33
+ end
34
+
35
+ ### resources
36
+
37
+ Given /^the resource declaration (\w+) with value (\[.*\]|\d+)/ do |name,val|
38
+ @class.class_eval "resource :#{name} => #{val}"
39
+ end
@@ -0,0 +1,2 @@
1
+ lomic_file = File.join(File.dirname(__FILE__), *%w[.. .. lib Lomic.rb])
2
+ require lomic_file
@@ -0,0 +1,14 @@
1
+ Feature: variable declaration and initialization on new objects
2
+ In order to keep variable declarations consistent
3
+ With other Lomic features
4
+ Such as resources
5
+
6
+ Scenario: Use of var after new object initializes
7
+ Given the Lomic inherited class MyClass
8
+ And the following var declarations:
9
+ | var_decl |
10
+ | var :example => 9 |
11
+ | var :another => 3 |
12
+ When I create a new MyClass object named foo
13
+ Then the result of foo.example should be 9
14
+ And the result of foo.another should be 3
data/lib/Lomic.rb ADDED
@@ -0,0 +1,16 @@
1
+ $:.push File.expand_path(File.dirname(__FILE__) + '/lib')
2
+ require 'lomic/Event'
3
+ require 'lomic/EventEngine'
4
+ require 'lomic/GameState'
5
+ require 'lomic/Lomic'
6
+ require 'lomic/Rule'
7
+ require 'lomic/LomicParser'
8
+
9
+ module Lomic
10
+ VERSION = '0.0.1'
11
+
12
+ def self.parse(filename, start_event="game:start")
13
+ gstate = LomicParser.load_source(filename)
14
+ gstate.emit start_event
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ module Lomic
2
+
3
+ class Event
4
+ attr_accessor :name, :priority, :rule_number
5
+ attr_accessor :block
6
+
7
+ def initialize(attrs)
8
+ attrs.each {|key,val| instance_variable_set "@#{key}", val }
9
+ end
10
+ end
11
+
12
+ end # module
@@ -0,0 +1,78 @@
1
+ module Lomic
2
+
3
+ class EventEngine
4
+
5
+ def initialize
6
+ @stack = []
7
+ @counter = 0 # the number of event code blocks executed
8
+ end
9
+
10
+ def run(event_name, rules)
11
+ add_sort_events rules
12
+ @next_event = event_name
13
+
14
+ begin
15
+ event_name = @next_event
16
+ @next_event = nil
17
+ for event in @events[event_name]
18
+ # event code blocks can set @next_event through set_next
19
+ instance_eval &event.block
20
+ end
21
+ end while @next_event.nil? == false
22
+ end
23
+
24
+ def set_next(event_name)
25
+ @next_event = event_name
26
+ end
27
+
28
+ def next_event
29
+ @next_event
30
+ end
31
+
32
+ def counter
33
+ @counter
34
+ end
35
+
36
+ private
37
+
38
+ def add_sort_events(rules)
39
+ # "event_name" => [Event]
40
+ @events = {}
41
+ rules.each do |r|
42
+ r.event_bag.each do |name, event_arr|
43
+ for e in event_arr do
44
+ if @events[name].nil?
45
+ @events[name] = [e]
46
+ next
47
+ end
48
+ # insert into sorted spot
49
+ arr = @events[name]
50
+ i = 0
51
+ arr.each do |arr_e|
52
+ if e.priority > arr_e.priority
53
+ arr.insert(i,e)
54
+ break
55
+ elsif i == arr.size-1
56
+ arr.insert(i+1,e)
57
+ break
58
+ end
59
+ i += 1
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ def push(event)
67
+ # pushes a state onto the stack
68
+ state = {
69
+ :event_name => event.name,
70
+ :priority => event.priority,
71
+ :rule_number => event.rule_number
72
+ }
73
+ @stack.push(state)
74
+ end
75
+
76
+ end
77
+
78
+ end # module
@@ -0,0 +1,35 @@
1
+ module Lomic
2
+
3
+ require 'Set'
4
+
5
+ class GameState
6
+ def initialize
7
+ super
8
+ @globals
9
+ @rules = []
10
+ @em = EventEngine.new
11
+ end
12
+
13
+ def globals
14
+ @globals
15
+ end
16
+
17
+ def globals=(globals_obj)
18
+ return if @globals.nil? == false
19
+ @globals = globals_obj
20
+ klass = @globals.class
21
+
22
+ klass.new_var :rules => []
23
+ @globals.rules = @rules
24
+ end
25
+
26
+ def addRule(rule)
27
+ @rules.push(rule)
28
+ end
29
+
30
+ def emit(event_name)
31
+ @em.run(event_name,@globals.rules)
32
+ end
33
+ end
34
+
35
+ end # module
@@ -0,0 +1,104 @@
1
+ module Lomic
2
+
3
+ ### This class helps clean up in-game class definitions
4
+ class Lomic
5
+ class << self
6
+ public :define_method, :remove_method
7
+ end
8
+
9
+ def self.var(symbols)
10
+ if symbols.instance_of? Symbol
11
+ self.new_var({symbols.to_sym => nil})
12
+ else
13
+ symbols.each { |name,init_val|
14
+ self.new_var(name => init_val)
15
+ }
16
+ end
17
+ end
18
+
19
+ def self.new_var(symbol)
20
+ name = symbol.keys[0]
21
+ init_val = symbol[name]
22
+
23
+ self.define_method name do
24
+ getter = "@#{name}"
25
+ getter += '?' if init_val.instance_of? TrueClass or init_val.instance_of? FalseClass
26
+ val = instance_variable_get getter
27
+
28
+ if val.nil? and @init_used[name].nil?
29
+ inits = self.class.class_eval "@@__#{className}_inits__"
30
+ val = inits[name]
31
+ instance_variable_set("@#{name}", val)
32
+ @init_used[name] = true
33
+ end
34
+
35
+ return val
36
+ end
37
+
38
+ self.define_method "#{name}=" do |new_val|
39
+ instance_variable_set("@#{name}", new_val)
40
+ @init_used[name] = true
41
+ end
42
+
43
+ class_eval "@@__#{self.className}_inits__ ||= {}"
44
+ inits = class_eval "@@__#{self.className}_inits__"
45
+ inits[name] = init_val
46
+ end
47
+
48
+ def self.resource(symbols)
49
+ symbols.each { |name,init_val|
50
+ self.new_resource(name => init_val)
51
+ }
52
+ end
53
+
54
+ def self.new_resource(symbol)
55
+ name = symbol.keys[0]
56
+ init_val = symbol[name]
57
+
58
+ if init_val.instance_of? Array
59
+ min,max,init = case init_val.size
60
+ when 1 then [0,init_val[0],init_val[0]]
61
+ when 2 then [init_val[0],init_val[1],init_val[1]]
62
+ else [init_val[0],init_val[1],init_val[2]]
63
+ end
64
+ else
65
+ min,max,init = [0,init_val,init_val]
66
+ end
67
+ self.new_var(name => init)
68
+ self.new_var("#{name}min" => min)
69
+ self.new_var("#{name}max" => max)
70
+
71
+ # redefine the set method to enforce resource limits
72
+ self.remove_method "#{name}="
73
+ self.define_method "#{name}=" do |new_val|
74
+ min = instance_variable_get "@#{name}min"
75
+ max = instance_variable_get "@#{name}max"
76
+ new_val = new_val < min ? min : (new_val > max ? max : new_val)
77
+
78
+ instance_variable_set("@#{name}", new_val)
79
+ end
80
+ end
81
+
82
+ def initialize
83
+ @init_used = {}
84
+ inits = self.class.class_eval "@@__#{className}_inits__"
85
+ inits.each do |var,val|
86
+ instance_variable_set "@#{var}", val
87
+ @init_used[var] = true
88
+ end
89
+ end
90
+
91
+ def self.className
92
+ if self.name.include? '::'
93
+ self.name.split('::')[1]
94
+ else
95
+ self.name
96
+ end
97
+ end
98
+
99
+ def className
100
+ self.class.className
101
+ end
102
+ end
103
+
104
+ end # module
@@ -0,0 +1,43 @@
1
+ module Lomic
2
+
3
+ class LomicParser
4
+
5
+ def initialize
6
+ # points to the Rule that is currently being parsed
7
+ @currentRule = nil
8
+ # The entire state of the game
9
+ @state = GameState.new
10
+ @first_rule = true
11
+ end
12
+
13
+ def rule(number)
14
+ # TODO: ensure number is int
15
+ @currentRule = Rule.new(number)
16
+ if @first_rule
17
+ @state.globals = instance_eval 'Globals.new'
18
+ @first_rule = false
19
+ end
20
+
21
+ yield @state.globals
22
+ ensure
23
+ @state.addRule(@currentRule)
24
+ @currentRule = nil
25
+ end
26
+
27
+ def event(event_name, options={}, &block)
28
+ @currentRule.event(event_name, options, &block)
29
+ end
30
+
31
+ def gamestate
32
+ @state
33
+ end
34
+
35
+ def self.load_source(filename)
36
+ dsl = new
37
+ dsl.instance_eval(File.read(filename),filename)
38
+ # dsl.gamestate.globals = (dsl.instance_eval 'Globals.new')
39
+ dsl.gamestate
40
+ end
41
+ end
42
+
43
+ end # module
data/lib/lomic/Rule.rb ADDED
@@ -0,0 +1,44 @@
1
+ module Lomic
2
+
3
+ class Rule < Lomic
4
+ def initialize(number)
5
+ @number = number
6
+ @event_bag = {} # "event_name" => [Event]
7
+ end
8
+
9
+
10
+ def event(event_name, options={}, &block)
11
+ options[:priority] ||= 5
12
+ options[:name] = event_name
13
+ options[:block] = block
14
+
15
+ event = Event.new(options)
16
+ if @event_bag[event_name].nil?
17
+ @event_bag[event_name] = [event]
18
+ else
19
+ # insert into sorted spot
20
+ arr = @event_bag[event_name]
21
+ i = 0
22
+ arr.each do |e|
23
+ if event.priority > e.priority
24
+ arr.insert(i,event)
25
+ break
26
+ elsif i == arr.size-1
27
+ arr.insert(i+1,event)
28
+ break
29
+ end
30
+ i += 1
31
+ end
32
+ end
33
+ end
34
+
35
+ def event_bag
36
+ @event_bag
37
+ end
38
+
39
+ def inspect
40
+ "Rule #{@number}: #{@event_bag.inspect}"
41
+ end
42
+ end
43
+
44
+ end # module
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lomic
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Gilbert B Garza
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-12 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: thoughtbot-shoulda
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: cucumber
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 63
44
+ segments:
45
+ - 0
46
+ - 8
47
+ - 0
48
+ version: 0.8.0
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: Lomic is a Domain Specific Language (DSL) intended to be used for Pomic, a programming version of the game Nomic.
52
+ email: gilbertbgarza@gmail.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - LICENSE
59
+ - README.rdoc
60
+ - TODO
61
+ files:
62
+ - LICENSE
63
+ - Manifest
64
+ - README.rdoc
65
+ - Rakefile
66
+ - TODO
67
+ - VERSION.yml
68
+ - examples/nomic_initial_rules.rb
69
+ - examples/priority.rb
70
+ - examples/simple.rb
71
+ - features/resource.feature
72
+ - features/step_definitions/steps.rb
73
+ - features/support/env.rb
74
+ - features/var_init.feature
75
+ - lib/Lomic.rb
76
+ - lib/lomic/Event.rb
77
+ - lib/lomic/EventEngine.rb
78
+ - lib/lomic/GameState.rb
79
+ - lib/lomic/Lomic.rb
80
+ - lib/lomic/LomicParser.rb
81
+ - lib/lomic/Rule.rb
82
+ has_rdoc: true
83
+ homepage: http://github.com/mindeavor/lomic
84
+ licenses: []
85
+
86
+ post_install_message:
87
+ rdoc_options:
88
+ - --charset=UTF-8
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: 3
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ requirements: []
110
+
111
+ rubyforge_project:
112
+ rubygems_version: 1.3.7
113
+ signing_key:
114
+ specification_version: 3
115
+ summary: A Ruby DSL for the game Nomic
116
+ test_files:
117
+ - examples/nomic_initial_rules.rb
118
+ - examples/priority.rb
119
+ - examples/simple.rb