ruby-stones 0.0.5
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 +7 -0
- data/bin/stones +23 -0
- data/lib/extensions/array.rb +5 -0
- data/lib/stones.rb +10 -0
- data/lib/stones/board.rb +78 -0
- data/lib/stones/board/with_head.rb +27 -0
- data/lib/stones/board/with_stones.rb +24 -0
- data/lib/stones/color.rb +25 -0
- data/lib/stones/direction.rb +25 -0
- data/lib/stones/execution_context.rb +11 -0
- data/lib/stones/gbb.rb +14 -0
- data/lib/stones/gbb/gbb_reader.rb +52 -0
- data/lib/stones/gbb/gbb_writer.rb +37 -0
- data/lib/stones/program.rb +48 -0
- data/lib/stones/version.rb +3 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5e91e5b19b7e1af7d13c7d8188306f6d61ccfa11
|
4
|
+
data.tar.gz: af406f7c45f5acd829b2693d8e9413d8b08cf3aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 846d8f203ad7d55bf298883aabe507462f9c7002dd00d0b7f6ff90e884724ee655f79cfe4f65242bb2e00e7e78149b3360421bbdcf80f7c34f58d0b02efe01e9
|
7
|
+
data.tar.gz: 22edef2eac5e62bc4d6fd7ec3fd8224488b32e5322ed4561e8e6599ef982271e137de161127a925ebb195c88595e9aaadf664441fea72a12a5d66bb4b28edfaf
|
data/bin/stones
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if ARGV.size != 3
|
4
|
+
puts 'Not enough arguments. Must pass program file, input board file and output board file'
|
5
|
+
exit 1
|
6
|
+
end
|
7
|
+
|
8
|
+
program = File.read ARGV[0]
|
9
|
+
input_gbb = File.read ARGV[1]
|
10
|
+
output_gbb_file = ARGV[2]
|
11
|
+
|
12
|
+
require 'stones'
|
13
|
+
|
14
|
+
Main = Class.new
|
15
|
+
Main.class_eval do
|
16
|
+
include Stones::Program
|
17
|
+
eval program
|
18
|
+
end
|
19
|
+
|
20
|
+
context = Stones::ExecutionContext.new
|
21
|
+
context.board = Stones::Gbb.read input_gbb
|
22
|
+
context.run Main
|
23
|
+
File.write output_gbb_file, Stones::Gbb.write(context.board)
|
data/lib/stones.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Stones
|
2
|
+
end
|
3
|
+
|
4
|
+
require_relative 'stones/direction'
|
5
|
+
require_relative 'stones/color'
|
6
|
+
require_relative 'stones/board'
|
7
|
+
require_relative 'stones/execution_context'
|
8
|
+
require_relative 'stones/program'
|
9
|
+
require_relative 'stones/gbb'
|
10
|
+
require_relative 'stones/version'
|
data/lib/stones/board.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative './board/with_head'
|
2
|
+
require_relative './board/with_stones'
|
3
|
+
|
4
|
+
module Stones
|
5
|
+
class OutOfBoardError < RuntimeError
|
6
|
+
end
|
7
|
+
|
8
|
+
class Board
|
9
|
+
include WithHead
|
10
|
+
include WithStones
|
11
|
+
|
12
|
+
attr_reader :cells, :head_position
|
13
|
+
|
14
|
+
def initialize(cells, position)
|
15
|
+
@cells = cells
|
16
|
+
@head_position = position
|
17
|
+
end
|
18
|
+
|
19
|
+
def size
|
20
|
+
[cells[0].size, cells.size]
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other)
|
24
|
+
self.class == other.class &&
|
25
|
+
self.cells == other.cells &&
|
26
|
+
self.head_position == other.head_position
|
27
|
+
end
|
28
|
+
|
29
|
+
def hash
|
30
|
+
self.cells.hash ^ self.head_position.hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.empty(x, y, position=[0, 0])
|
34
|
+
self.new(empty_cells(x, y), position)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.from(cells, position=[0, 0])
|
38
|
+
self.new(cells.map { |row| row.map { |cell| empty_cell.merge(cell) } }, position)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def each_cell
|
44
|
+
(0..(size[0]-1)).each do |x|
|
45
|
+
(0..(size[1]-1)).each do |y|
|
46
|
+
yield cell_at([x, y]), x, y
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def cell_at(position)
|
52
|
+
raise OutOfBoardError unless within_bounds? position
|
53
|
+
cells[-(position[1]+1)][position[0]]
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_cell(position, cell)
|
57
|
+
cell_at(position).merge! cell
|
58
|
+
end
|
59
|
+
|
60
|
+
def within_bounds?(position)
|
61
|
+
(x, y) = size
|
62
|
+
position[0] >= 0 && position[1] >= 0 &&
|
63
|
+
position[0] < x && position[1] < y
|
64
|
+
end
|
65
|
+
|
66
|
+
def head_cell
|
67
|
+
cell_at(head_position)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.empty_cell
|
71
|
+
{red: 0, black: 0, green: 0, blue: 0}
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.empty_cells(x, y)
|
75
|
+
(1..y).map { (1..x).map { empty_cell } }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Stones
|
2
|
+
module WithHead
|
3
|
+
def can_move?(direction)
|
4
|
+
within_bounds? next_position(direction)
|
5
|
+
end
|
6
|
+
|
7
|
+
def move!(direction)
|
8
|
+
move_to! next_position(direction)
|
9
|
+
end
|
10
|
+
|
11
|
+
def move_to_edge!(direction)
|
12
|
+
move!(direction) while can_move?(direction)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def move_to!(position)
|
18
|
+
raise OutOfBoardError unless within_bounds? position
|
19
|
+
@head_position = position
|
20
|
+
end
|
21
|
+
|
22
|
+
def next_position(direction)
|
23
|
+
direction.call(*@head_position)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Stones
|
2
|
+
module WithStones
|
3
|
+
def push!(color, amount=1)
|
4
|
+
head_cell[color] += amount
|
5
|
+
end
|
6
|
+
|
7
|
+
def pop!(color)
|
8
|
+
raise "#{color} Underflow" if head_cell[color] == 0
|
9
|
+
head_cell[color] -= 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear!
|
13
|
+
@cells = self.class.empty_cells(*size)
|
14
|
+
end
|
15
|
+
|
16
|
+
def count(color)
|
17
|
+
head_cell[color]
|
18
|
+
end
|
19
|
+
|
20
|
+
def exist?(color)
|
21
|
+
count(color) > 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/stones/color.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Stones
|
2
|
+
module Color
|
3
|
+
def red
|
4
|
+
:red
|
5
|
+
end
|
6
|
+
|
7
|
+
def blue
|
8
|
+
:blue
|
9
|
+
end
|
10
|
+
|
11
|
+
def green
|
12
|
+
:green
|
13
|
+
end
|
14
|
+
|
15
|
+
def black
|
16
|
+
:black
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all
|
20
|
+
[red, green, black, blue]
|
21
|
+
end
|
22
|
+
|
23
|
+
module_function :red, :blue, :green, :black
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Stones
|
2
|
+
module Direction
|
3
|
+
def east
|
4
|
+
@east ||= -> (x, y) { [x+1, y] }
|
5
|
+
end
|
6
|
+
|
7
|
+
def west
|
8
|
+
@west ||= -> (x, y) { [x-1, y] }
|
9
|
+
end
|
10
|
+
|
11
|
+
def north
|
12
|
+
@north ||= -> (x, y) { [x, y+1] }
|
13
|
+
end
|
14
|
+
|
15
|
+
def south
|
16
|
+
@south ||= -> (x, y) { [x, y-1] }
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all
|
20
|
+
[east, west, south, north]
|
21
|
+
end
|
22
|
+
|
23
|
+
module_function :north, :south, :east, :west
|
24
|
+
end
|
25
|
+
end
|
data/lib/stones/gbb.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative '../../extensions/array.rb'
|
2
|
+
|
3
|
+
|
4
|
+
class MatchData
|
5
|
+
def to_position
|
6
|
+
[self[1].to_i, self[2].to_i]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module Stones
|
11
|
+
class GbbReader
|
12
|
+
COLORS = {'Azul' => :blue, 'Negro' => :black, 'Rojo' => :red, 'Verde' => :green}
|
13
|
+
|
14
|
+
def from_string(gbb_string)
|
15
|
+
board = nil
|
16
|
+
|
17
|
+
lines = gbb_string.lines.reject { |it| it.start_with? 'GBB', '%%' }
|
18
|
+
|
19
|
+
/size (\d+) (\d+)/.match(lines[0]) { |match| board = Board.empty(match[1].to_i, match[2].to_i) }
|
20
|
+
/head (\d+) (\d+)/.match(lines.last) { |match| board.send :move_to!, match.to_position }
|
21
|
+
|
22
|
+
lines.drop(1).init.each do |cell_line|
|
23
|
+
position = get_position_from cell_line
|
24
|
+
cell = create_cell_from cell_line
|
25
|
+
|
26
|
+
board.send :set_cell, position, cell
|
27
|
+
end
|
28
|
+
|
29
|
+
board
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def get_position_from(cell_line)
|
35
|
+
/cell (\d+) (\d+)/.match(cell_line).to_position
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_cell_from(cell_line)
|
39
|
+
cell = {}
|
40
|
+
|
41
|
+
cell_line.scan(/(Azul|Negro|Rojo|Verde) (\d+)/) do |match|
|
42
|
+
cell[to_color(match[0])] = match[1].to_i
|
43
|
+
end
|
44
|
+
|
45
|
+
cell
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_color(gbb_color_string)
|
49
|
+
COLORS[gbb_color_string]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Stones
|
2
|
+
module GbbWriter
|
3
|
+
def self.write(board)
|
4
|
+
"GBB/1.0\n" +
|
5
|
+
"size #{board.size[0]} #{board.size[1]}\n" +
|
6
|
+
"#{write_cells board}" +
|
7
|
+
"head #{board.head_position[0]} #{board.head_position[1]}"
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def self.write_cells(board)
|
13
|
+
cells_gbb = ''
|
14
|
+
|
15
|
+
board.send :each_cell do |cell, x, y|
|
16
|
+
cell = cell.select { |color, count| count > 0 }
|
17
|
+
next if cell.empty?
|
18
|
+
cells_gbb << "cell #{x} #{y} #{write_colors cell}\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
cells_gbb
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.write_colors(cell)
|
25
|
+
cell.map { |color, count| "#{to_gbb_color color} #{count}" }.join(' ')
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.to_gbb_color(color)
|
29
|
+
case color
|
30
|
+
when :red then 'Rojo'
|
31
|
+
when :green then 'Verde'
|
32
|
+
when :black then 'Negro'
|
33
|
+
when :blue then 'Azul'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Stones
|
2
|
+
module Program
|
3
|
+
attr_accessor :board
|
4
|
+
|
5
|
+
include Stones::Color
|
6
|
+
include Stones::Direction
|
7
|
+
|
8
|
+
def move!(direction)
|
9
|
+
board.move!(direction)
|
10
|
+
end
|
11
|
+
|
12
|
+
def move_to_edge!(direction)
|
13
|
+
board.move_to_edge!
|
14
|
+
end
|
15
|
+
|
16
|
+
def can_move?(direction)
|
17
|
+
board.can_move?(direction)
|
18
|
+
end
|
19
|
+
|
20
|
+
def push!(color)
|
21
|
+
board.push!(color)
|
22
|
+
end
|
23
|
+
|
24
|
+
def pop!(color)
|
25
|
+
board.pop!(color)
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear!
|
29
|
+
board.clear!
|
30
|
+
end
|
31
|
+
|
32
|
+
def count(color)
|
33
|
+
board.count(color)
|
34
|
+
end
|
35
|
+
|
36
|
+
def exist?(color)
|
37
|
+
board.exists?(color)
|
38
|
+
end
|
39
|
+
|
40
|
+
def colors
|
41
|
+
Color.all
|
42
|
+
end
|
43
|
+
|
44
|
+
def directions
|
45
|
+
Direction.all
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-stones
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Federico Aloi
|
8
|
+
- Franco Bulgarelli
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-06-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.7'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.7'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '10.0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '10.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: codeclimate-test-reporter
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
description: Write Gobstones program within Ruby
|
71
|
+
email:
|
72
|
+
- federico.aloi@gmail.com
|
73
|
+
- flbulgarelli@yahoo.com.ar
|
74
|
+
executables:
|
75
|
+
- stones
|
76
|
+
extensions: []
|
77
|
+
extra_rdoc_files: []
|
78
|
+
files:
|
79
|
+
- bin/stones
|
80
|
+
- lib/extensions/array.rb
|
81
|
+
- lib/stones.rb
|
82
|
+
- lib/stones/board.rb
|
83
|
+
- lib/stones/board/with_head.rb
|
84
|
+
- lib/stones/board/with_stones.rb
|
85
|
+
- lib/stones/color.rb
|
86
|
+
- lib/stones/direction.rb
|
87
|
+
- lib/stones/execution_context.rb
|
88
|
+
- lib/stones/gbb.rb
|
89
|
+
- lib/stones/gbb/gbb_reader.rb
|
90
|
+
- lib/stones/gbb/gbb_writer.rb
|
91
|
+
- lib/stones/program.rb
|
92
|
+
- lib/stones/version.rb
|
93
|
+
homepage: https://github.com/uqbar-project/ruby-stones
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 2.2.0
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: Pure ruby library that implements a Gobstones-like board and dsl
|
117
|
+
test_files: []
|