gingham 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f42bcf5cc471a76f91e679bdcc2d499e53af33d3
4
+ data.tar.gz: 6adc747300171b376782a7ea2cef200ac8bd5052
5
+ SHA512:
6
+ metadata.gz: 92e86f127788c578e927d55330cf7be3fc0231f2227e98d3fa280655e8eb4abeca8246024acd00220392cf4ac84b5484ddf3f526828261a6daaa3ab8ce58bfc1
7
+ data.tar.gz: 3606fae484fd25c9621cc3ce5ead90193e48e10914a97d5850550e5cdd481789206026bb12b7cf319072c1ba23d9e5f95195da23baab403ac7551728f088b0a7
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea
11
+ /vendor
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.4
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gingham.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Cignoir
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # Gingham
2
+
3
+ [![Build Status](https://travis-ci.org/cignoir/gingham.svg?branch=master)](https://travis-ci.org/cignoir/gingham)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'gingham'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install gingham
20
+
21
+ ## Usage
22
+
23
+ W.I.P
24
+
25
+ ## Development
26
+
27
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
28
+
29
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
30
+
31
+ ## Contributing
32
+
33
+ Bug reports and pull requests are welcome on GitHub at https://github.com/cignoir/gingham. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
34
+
35
+
36
+ ## License
37
+
38
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gingham"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/gingham.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gingham/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gingham"
8
+ spec.version = Gingham::VERSION
9
+ spec.authors = ["cignoir"]
10
+ spec.email = ["cignoir@gmail.com"]
11
+
12
+ spec.summary = %q{Implementation of original pathfinding algorythm based on 3d grids.}
13
+ spec.description = %q{R.I.P. StruGarden}
14
+ spec.homepage = "https://github.com/cignoir/gingham"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "activesupport", '~> 0'
23
+ spec.add_development_dependency "bundler", '~> 0'
24
+ spec.add_development_dependency "rake", '~> 0'
25
+ spec.add_development_dependency "rspec", '~> 0'
26
+ end
@@ -0,0 +1,19 @@
1
+ module Gingham
2
+ class Actor
3
+ attr_accessor :waypoint, :weight
4
+ attr_accessor :move_steps
5
+ attr_accessor :team_id
6
+ attr_accessor :move_status
7
+
8
+ def initialize(waypoint, weight = 100, team_id = 0)
9
+ @waypoint = waypoint
10
+ @weight = weight
11
+ @team_id = team_id
12
+ @move_status = Gingham::MoveStatus::DEFAULT
13
+ end
14
+
15
+ def move_end?
16
+ @move_status == Gingham::MoveStatus::FINISHED || @move_status == Gingham::MoveStatus::STOPPED
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ module Gingham
2
+ class Cell
3
+ attr_accessor :x, :y, :z, :is_occupied, :is_ground
4
+
5
+ def initialize(x = 0, y = 0, z = 0)
6
+ @x, @y, @z = x.to_i, y.to_i, z.to_i
7
+ @is_occupied = false
8
+ @is_ground = false
9
+ end
10
+
11
+ def ==(other)
12
+ other.is_a?(Gingham::Cell) && @x == other.x && @y == other.y && @z == other.z
13
+ end
14
+
15
+ #FIXME
16
+ def occupied?
17
+ @is_occupied
18
+ end
19
+
20
+ def passable?
21
+ !@is_occupied
22
+ end
23
+
24
+ def sky?
25
+ !@is_ground
26
+ end
27
+
28
+ def ground?
29
+ @is_ground
30
+ end
31
+
32
+ def to_s
33
+ "(#{x},#{y},#{z})"
34
+ end
35
+
36
+ def inspect
37
+ "(#{x},#{y},#{z})"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ module Gingham
2
+ module Direction
3
+ # D1 = 1
4
+ D2 = 2
5
+ # D3 = 3
6
+ D4 = 4
7
+ # D5 = 5
8
+ D6 = 6
9
+ # D7 = 7
10
+ D8 = 8
11
+ # D9 = 9
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ module Gingham
2
+ class MoveFrame
3
+ attr_accessor :index, :actors
4
+
5
+ def initialize(index, actors)
6
+ @index = index
7
+ # deep_copy actors
8
+ @actors = Marshal.load Marshal.dump(actors)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,66 @@
1
+ module Gingham
2
+ class MoveSimulator
3
+ class << self
4
+ def next_step(current_step_index, actors)
5
+ actors.each do |actor|
6
+ actor.move_status = Gingham::MoveStatus::FINISHED unless actor.move_steps[current_step_index + 1]
7
+ end
8
+
9
+ grouped = actors.reject{ |actor| actor.move_end? }.group_by{ |actor| actor.move_steps[current_step_index + 1].cell }
10
+ grouped.each do |goal, group|
11
+ if actors.map{ |a| a.waypoint.cell }.include? goal
12
+ # ゴール地点に誰かいる場合
13
+ # 方向転換の場合、ゴール地点に自分自身がいることになることに注意
14
+ winner = actors.select{ |a| a.waypoint.cell == goal }.first
15
+ losers = group.reject{ |actor| actor.object_id == winner.object_id }
16
+ all_in_goal = [winner, losers].flatten.compact
17
+ else
18
+ # ゴール地点に誰もいない場合
19
+ max_weight = group.map(&:weight).max
20
+ winner = group.select{ |actor| actor.weight == max_weight }.sample
21
+ winner.waypoint = winner.move_steps[current_step_index + 1]
22
+ winner.move_status = Gingham::MoveStatus::DEFAULT
23
+ losers = group.reject{ |actor| actor.object_id == winner.object_id }
24
+ all_in_goal = [winner, losers].flatten.compact
25
+ end
26
+
27
+ if all_in_goal.map(&:team_id).uniq.size == 1
28
+ # 全員同じチームの場合
29
+ losers.each do |loser|
30
+ loser.move_status = Gingham::MoveStatus::STAY
31
+ # 足踏みステップを挿入
32
+ loser.move_steps = loser.move_steps.insert(current_step_index, loser.move_steps[current_step_index])
33
+ end
34
+ else
35
+ # 敵チームを含んでいる場合
36
+ winner.move_steps = winner.move_steps[0..(current_step_index + 1)]
37
+ winner.move_status = Gingham::MoveStatus::STOPPED
38
+ losers.each do |loser|
39
+ loser.move_status = Gingham::MoveStatus::STOPPED
40
+ loser.move_steps = loser.move_steps[0..current_step_index] # 以降のmove_stepsを削除
41
+ end
42
+ end
43
+ end
44
+ actors
45
+ end
46
+
47
+ def record(actors)
48
+ all_moved = actors.select(&:move_end?).size == actors.size
49
+ all_stayed = actors.reject(&:move_end?).map(&:move_status).uniq.first == Gingham::MoveStatus::STAY
50
+
51
+ index = 0
52
+ records = [MoveFrame.new(index, actors)]
53
+ until all_moved || all_stayed
54
+ actors = self.next_step(index, actors)
55
+ index += 1
56
+ records << MoveFrame.new(index, actors)
57
+
58
+ all_moved = actors.select(&:move_end?).size == actors.size
59
+ all_stayed = actors.reject(&:move_end?).map(&:move_status).uniq.first == Gingham::MoveStatus::STAY
60
+ end
61
+
62
+ records
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,8 @@
1
+ module Gingham
2
+ module MoveStatus
3
+ DEFAULT = 0
4
+ STAY = 1
5
+ STOPPED = 2
6
+ FINISHED = 3
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module Gingham
2
+ class Naterua
3
+ attr_accessor :turn
4
+ attr_accessor :step_index
5
+ end
6
+ end
@@ -0,0 +1,203 @@
1
+ module Gingham
2
+ class PathFinder
3
+ class << self
4
+ def find_move_path(space, from, to, cost_limit = 999)
5
+ raise ArgumentError unless space && space.is_a?(Gingham::Space)
6
+ raise ArgumentError unless from && from.is_a?(Gingham::Waypoint) && to && to.is_a?(Gingham::Waypoint)
7
+
8
+ open_list = [from]
9
+ return open_list if from.cell == to.cell
10
+ close_list = []
11
+ loop_limit = 0
12
+
13
+ while open_list.size > 0 && loop_limit < 1000 do
14
+ current_wp = open_list.first
15
+ close_list << current_wp
16
+ open_list = open_list.drop 1
17
+
18
+ adjacent_waypoints = Gingham::PathFinder.find_adjacent_waypoints(space, current_wp)
19
+ adjacent_waypoints.each do |wp|
20
+ if wp.sum_cost < cost_limit
21
+ open_list << wp unless close_list.include? wp
22
+ end
23
+ end
24
+ loop_limit += 1
25
+ end
26
+
27
+ shortest_chains = [from]
28
+ end_points = close_list.select{ |closed| closed.cell == to.cell }
29
+
30
+ unless end_points.size.zero?
31
+ shortest_cost = 999
32
+ end_points.each do |end_wp|
33
+ if end_wp.sum_cost < shortest_cost
34
+ shortest_cost = end_wp.sum_cost
35
+ shortest_chains = end_wp.chains
36
+ end
37
+ end
38
+ end
39
+ shortest_chains
40
+ end
41
+
42
+ def find_skill_path(space, from, to, max_height = 10)
43
+ path = [from]
44
+ last_wp = path.last
45
+ should_move_y = from.direction == Gingham::Direction::D8 || from.direction == Gingham::Direction::D2
46
+
47
+ loop_limit = 0
48
+ while last_wp.cell.x != to.cell.x || last_wp.cell.y != to.cell.y
49
+ loop_limit += 1
50
+ break if loop_limit > 30
51
+
52
+ if should_move_y && last_wp.cell.y != to.cell.y
53
+ if last_wp.cell.y < to.cell.y
54
+ if last_wp.cell.y + 1 != space.depth
55
+ height = space.height_at(last_wp.cell.x, last_wp.cell.y + 1)
56
+ cell = space.cells[last_wp.cell.x][last_wp.cell.y + 1][height]
57
+ break unless cell.passable?
58
+
59
+ if last_wp.direction == 8
60
+ break if cell.z > max_height
61
+ wp = Gingham::Waypoint.new(cell, 8, last_wp)
62
+ path << wp
63
+ last_wp = wp
64
+ else
65
+ tmp = Gingham::Waypoint.new(last_wp.cell, 8, last_wp)
66
+ path << tmp
67
+ break if cell.z > max_height
68
+ tmp = Gingham::Waypoint.new(cell, 8, tmp)
69
+ path << tmp
70
+ last_wp = tmp
71
+ end
72
+ end
73
+ elsif last_wp.cell.y > to.cell.y
74
+ if last_wp.cell.y - 1 >= 0
75
+ height = space.height_at(last_wp.cell.x, last_wp.cell.y - 1)
76
+ cell = space.cells[last_wp.cell.x][last_wp.cell.y - 1][height]
77
+ break unless cell.passable?
78
+
79
+ if last_wp.direction == 2
80
+ break if cell.z > max_height
81
+ wp = Gingham::Waypoint.new(cell, 2, last_wp)
82
+ path << wp
83
+ last_wp = wp
84
+ else
85
+ tmp = Gingham::Waypoint.new(last_wp.cell, 2, last_wp)
86
+ path << tmp
87
+ break if cell.z > max_height
88
+ tmp = Gingham::Waypoint.new(cell, 2, tmp)
89
+ path << tmp
90
+ last_wp = tmp
91
+ end
92
+ end
93
+ end
94
+ should_move_y = false
95
+ next
96
+ else
97
+ should_move_y = false
98
+ end
99
+
100
+ if !should_move_y && last_wp.cell.x != to.cell.x
101
+ if last_wp.cell.x < to.cell.x
102
+ if last_wp.cell.x + 1 != space.width
103
+ height = space.height_at(last_wp.cell.x + 1, last_wp.cell.y)
104
+ cell = space.cells[last_wp.cell.x + 1][last_wp.cell.y][height]
105
+ break unless cell.passable?
106
+
107
+ if last_wp.direction == 6
108
+ break if cell.z > max_height
109
+ wp = Gingham::Waypoint.new(cell, 6, last_wp)
110
+ path << wp
111
+ last_wp = wp
112
+ else
113
+ tmp = Gingham::Waypoint.new(last_wp.cell, 6, last_wp)
114
+ path << tmp
115
+ break if cell.z > max_height
116
+ tmp = Gingham::Waypoint.new(cell, 6, tmp)
117
+ path << tmp
118
+ last_wp = tmp
119
+ end
120
+ end
121
+ elsif last_wp.cell.x > to.cell.x
122
+ if last_wp.cell.x - 1 >= 0
123
+ height = space.height_at(last_wp.cell.x - 1, last_wp.cell.y)
124
+ cell = space.cells[last_wp.cell.x - 1][last_wp.cell.y][height]
125
+ break unless cell.passable?
126
+
127
+ if last_wp.direction == 4
128
+ break if cell.z > max_height
129
+ wp = Gingham::Waypoint.new(cell, 4, last_wp)
130
+ path << wp
131
+ last_wp = wp
132
+ else
133
+ tmp = Gingham::Waypoint.new(last_wp.cell, 4, last_wp)
134
+ path << tmp
135
+ break if cell.z > max_height
136
+ tmp = Gingham::Waypoint.new(cell, 4, tmp)
137
+ path << tmp
138
+ last_wp = tmp
139
+ end
140
+ end
141
+ end
142
+ should_move_y = true
143
+ next
144
+ else
145
+ should_move_y = true
146
+ end
147
+ end
148
+
149
+ path.compact
150
+ end
151
+ end
152
+
153
+ def self.find_adjacent_waypoints(space, wp)
154
+ raise unless space && space.is_a?(Gingham::Space)
155
+ raise unless wp && wp.is_a?(Gingham::Waypoint)
156
+
157
+ adjacent_list = []
158
+ adjacent_cells = Gingham::PathFinder.find_adjacent_cells(space, wp.cell)
159
+ adjacent_cells.each do |cell|
160
+ move_direction = Gingham::Waypoint.detect_direction(wp, cell)
161
+ parent = wp
162
+ if move_direction != wp.direction
163
+ turn_wp = Gingham::Waypoint.new(wp.cell, move_direction, wp)
164
+ parent = turn_wp
165
+ end
166
+ move_to = Gingham::Waypoint.new(cell, move_direction, parent)
167
+ adjacent_list << move_to
168
+ end
169
+ adjacent_list
170
+ end
171
+
172
+ def self.find_adjacent_cells(space, cell)
173
+ raise unless space && space.is_a?(Gingham::Space)
174
+ raise unless cell && cell.is_a?(Gingham::Cell)
175
+
176
+ adjacent_list = []
177
+ w, d, h = space.width, space.depth, space.height
178
+ x, y, z = cell.x, cell.y, cell.z
179
+
180
+ if x + 1 < w
181
+ target_cell = space.cells[x + 1][y][z]
182
+ adjacent_list << target_cell unless target_cell && target_cell.occupied?
183
+ end
184
+
185
+ if x - 1 >= 0
186
+ target_cell = space.cells[x - 1][y][z]
187
+ adjacent_list << target_cell unless target_cell && target_cell.occupied?
188
+ end
189
+
190
+ if y + 1 < d
191
+ target_cell = space.cells[x][y + 1][z]
192
+ adjacent_list << target_cell unless target_cell && target_cell.occupied?
193
+ end
194
+
195
+ if y - 1 >= 0
196
+ target_cell = space.cells[x][y - 1][z]
197
+ adjacent_list << target_cell unless target_cell && target_cell.occupied?
198
+ end
199
+
200
+ adjacent_list
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,9 @@
1
+ module Gingham
2
+ class Position
3
+ attr_accessor :x, :y, :z
4
+
5
+ def initialize(x, y, z)
6
+ @x, @y, @z = x, y, z
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,75 @@
1
+ module Gingham
2
+ class Space
3
+ attr_accessor :width, :height, :depth, :cells
4
+
5
+ def initialize(width = 0, depth = 0, height = 0)
6
+ @width = width
7
+ @depth = depth
8
+ @height = height
9
+ @cells = Array.new(width){ |x| Array.new(depth){ |y| Array.new(height){ |z| Cell.new(x, y, z) } } }
10
+ end
11
+
12
+ # 指定した座標の高さを取得
13
+ def height_at(x, y)
14
+ return nil unless @cells[x][y]
15
+
16
+ ground_cells = @cells[x][y].select{ |cell| cell.ground? }
17
+ return 0 if ground_cells.blank?
18
+
19
+ z_list = ground_cells.map(&:z)
20
+ return 0 if z_list.blank?
21
+
22
+ [0, z_list.max].max
23
+ end
24
+
25
+ # 指定した座標の地表のセルを取得
26
+ def ground_at(x, y)
27
+ z = height_at(x, y)
28
+ is_illegal = z.nil? || x < 0 || y < 0 || z < 0 || x >= self.width || y >= self.depth || z >= self.height
29
+ is_illegal ? nil : cells[x][y][z]
30
+ end
31
+
32
+ # 中心セルを基準にtargetのセルを回転した位置のセルを取得
33
+ def rotate_right(center, target)
34
+ target ? ground_at(center.x + (target.y - center.y), center.y - (target.x - center.x)) : nil
35
+ end
36
+ def rotate_left(center, target)
37
+ target ? ground_at(center.x - (target.y - center.y), center.y + (target.x - center.x)) : nil
38
+ end
39
+ def rotate_reverse(center, target)
40
+ target ? ground_at(center.x - (target.x - center.x), center.y - (target.y - center.y)) : nil
41
+ end
42
+
43
+ def build_range_cell(waypoint, query)
44
+ x = waypoint.cell.x
45
+ y = waypoint.cell.y
46
+ query.to_s.split('').map(&:to_i).each do |n|
47
+ case n
48
+ when 8 then y += 1
49
+ when 2 then y -= 1
50
+ when 6 then x += 1
51
+ when 4 then x -= 1
52
+ end
53
+ end
54
+
55
+ target = self.ground_at(x, y)
56
+ result = case waypoint.direction
57
+ when Gingham::Direction::D2 then rotate_reverse(waypoint.cell, target)
58
+ when Gingham::Direction::D6 then rotate_right(waypoint.cell, target)
59
+ when Gingham::Direction::D4 then rotate_left(waypoint.cell, target)
60
+ else target
61
+ end
62
+
63
+ (result.nil? || result.occupied?) ? nil : result
64
+ end
65
+
66
+ def build_all_range_cells(waypoint, query_list)
67
+ result = []
68
+ query_list.each do |query|
69
+ range_cell = build_range_cell(waypoint, query)
70
+ result << range_cell unless range_cell.nil?
71
+ end
72
+ result.uniq
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,5 @@
1
+ module Gingham
2
+ class TimeLine
3
+ attr_accessor :move_records, :action_records
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Gingham
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,105 @@
1
+ module Gingham
2
+ class Waypoint
3
+ attr_accessor :cell, :direction, :parent, :cost, :sum_cost, :chains
4
+
5
+ class << self
6
+ def detect_direction(from, target_cell)
7
+ raise if from.nil? || from.cell.nil? || from.direction.nil? || target_cell.nil?
8
+ raise unless from.cell.is_a?(Gingham::Cell) && target_cell.is_a?(Gingham::Cell)
9
+
10
+ diff_x = target_cell.x - from.cell.x
11
+ diff_y = target_cell.y - from.cell.y
12
+
13
+ direction = from.direction
14
+ direction = Gingham::Direction::D6 if diff_x > 0
15
+ direction = Gingham::Direction::D4 if diff_x < 0
16
+ direction = Gingham::Direction::D8 if diff_y > 0
17
+ direction = Gingham::Direction::D2 if diff_y < 0
18
+ direction
19
+ end
20
+ end
21
+
22
+ def initialize(cell = Cell.new, direction = Gingham::Direction::D8, parent = nil)
23
+ @cell = cell
24
+ @direction = direction
25
+ @parent = parent
26
+
27
+ update
28
+ end
29
+
30
+ def calc_cost
31
+ return 0 unless @parent
32
+
33
+ is_same_cell = @parent.cell == @cell
34
+ turn_cost = case @parent.direction
35
+ when Gingham::Direction::D8
36
+ case @direction
37
+ when Gingham::Direction::D8 then is_same_cell ? 5 : 0
38
+ when Gingham::Direction::D2 then 10
39
+ else 5
40
+ end
41
+ when Gingham::Direction::D2
42
+ case @direction
43
+ when Gingham::Direction::D2 then is_same_cell ? 5 : 0
44
+ when Gingham::Direction::D8 then 10
45
+ else 5
46
+ end
47
+ when Gingham::Direction::D6
48
+ case @direction
49
+ when Gingham::Direction::D6 then is_same_cell ? 5 : 0
50
+ when Gingham::Direction::D4 then 10
51
+ else 5
52
+ end
53
+ when Gingham::Direction::D4
54
+ case @direction
55
+ when Gingham::Direction::D4 then is_same_cell ? 5 : 0
56
+ when Gingham::Direction::D6 then 10
57
+ else 5
58
+ end
59
+ else 0
60
+ end
61
+ is_same_cell ? turn_cost : 10 + turn_cost
62
+ end
63
+
64
+ def pick_parents
65
+ result = []
66
+ result << @parent.chains if @parent
67
+ result << self
68
+ result.flatten.compact
69
+ end
70
+
71
+ def update
72
+ if @parent.nil?
73
+ @cost, @sum_cost = 0, 0
74
+ @chains = [self]
75
+ else
76
+ @cost = calc_cost
77
+ @chains = pick_parents
78
+ @sum_cost = @chains.map(&:cost).inject(:+)
79
+ end
80
+ self
81
+ end
82
+
83
+ def turning?
84
+ @parent ? @parent.cell == @cell : false
85
+ end
86
+
87
+ def moving?
88
+ @parent ? @parent.cell != @cell : false
89
+ end
90
+
91
+ def ==(other)
92
+ other.is_a?(Gingham::Waypoint) && @cell == other.cell && @direction == other.direction# && @cost == other.cost && @sum_cost == other.sum_cost
93
+ end
94
+
95
+ def to_s
96
+ base = "#{@cell}/#{@direction}" + ":#{@cost}/#{@sum_cost}"
97
+ @parent ? "#{@parent.cell}/#{@parent.direction}->" + base : base
98
+ end
99
+
100
+ def inspect
101
+ base = "#{@cell}/#{@direction}" + ":#{@cost}/#{@sum_cost}"
102
+ @parent ? "#{@parent.cell}/#{@parent.direction}->" + base : base
103
+ end
104
+ end
105
+ end
data/lib/gingham.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'active_support/dependencies'
2
+
3
+ module Gingham
4
+ # Utility
5
+ autoload :VERSION, 'gingham/version'
6
+ autoload :PathFinder, 'gingham/path_finder'
7
+ autoload :MoveSimulator, 'gingham/move_simulator'
8
+ autoload :ActionSimulator, 'gingham/action_simulator'
9
+ autoload :MoveStatus, 'gingham/move_status'
10
+
11
+ # World
12
+ autoload :Naterua, 'gingham/naterua' # GameMaster
13
+ autoload :Space, 'gingham/space'
14
+ autoload :Cell, 'gingham/cell'
15
+ autoload :Position, 'gingham/position'
16
+ autoload :Direction, 'gingham/direction'
17
+ autoload :Waypoint, 'gingham/waypoint'
18
+
19
+ # Objects
20
+ autoload :Actor, 'gingham/actor'
21
+
22
+ # Timeline
23
+ autoload :TimeLine, 'gingham/time_line'
24
+ autoload :MoveFrame, 'gingham/move_frame'
25
+ autoload :ActionFrame, 'gingham/action_frame'
26
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gingham
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - cignoir
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-04-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: R.I.P. StruGarden
70
+ email:
71
+ - cignoir@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - gingham.gemspec
86
+ - lib/gingham.rb
87
+ - lib/gingham/actor.rb
88
+ - lib/gingham/cell.rb
89
+ - lib/gingham/direction.rb
90
+ - lib/gingham/move_frame.rb
91
+ - lib/gingham/move_simulator.rb
92
+ - lib/gingham/move_status.rb
93
+ - lib/gingham/naterua.rb
94
+ - lib/gingham/path_finder.rb
95
+ - lib/gingham/position.rb
96
+ - lib/gingham/space.rb
97
+ - lib/gingham/time_line.rb
98
+ - lib/gingham/version.rb
99
+ - lib/gingham/waypoint.rb
100
+ homepage: https://github.com/cignoir/gingham
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.5.1
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: Implementation of original pathfinding algorythm based on 3d grids.
124
+ test_files: []