bloodchalice 1.0.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.
data/assets/world/map1 ADDED
@@ -0,0 +1,15 @@
1
+ #####################################################################################
2
+ # C 1 2 # P #
3
+ # # ##### P #
4
+ # 3 4 P ####### #
5
+ ############ # P P# #
6
+ # #### # # P #
7
+ # ##### ###### ## ## #
8
+ # ########### ### #
9
+ # ## ### #
10
+ # ## Z ############## P #
11
+ # ## ##### K # # P # P #
12
+ # P ## ##### # #
13
+ # P P # #
14
+ # # ##### # # # P #
15
+ #####################################################################################
data/bin/bloodchalice ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/bloodchalice'
3
+
4
+ BloodChalice::Application.run
@@ -0,0 +1,16 @@
1
+ require 'io/console'
2
+ require 'pathname'
3
+ require 'highline/import'
4
+
5
+ require_relative 'bloodchalice/event_deck'
6
+ require_relative 'bloodchalice/tile'
7
+ require_relative 'bloodchalice/movable'
8
+ require_relative 'bloodchalice/ai'
9
+ require_relative 'bloodchalice/map'
10
+ require_relative 'bloodchalice/bloodchalice'
11
+ require_relative 'bloodchalice/game'
12
+ require_relative 'bloodchalice/player'
13
+ require_relative 'bloodchalice/zombie'
14
+ require_relative 'bloodchalice/peasant'
15
+ require_relative 'bloodchalice/knight'
16
+ require_relative 'bloodchalice/chalice'
@@ -0,0 +1,39 @@
1
+ ########
2
+ # This is a very basic IA just for testing.
3
+ ########
4
+
5
+ class BloodChalice
6
+ module ArtificialIntelligence
7
+ def think()
8
+ self.speed.times { move(Movable::DIRECTIONS.keys.sample) }
9
+ end
10
+
11
+ def reacts_to(tile)
12
+ if tile.wall?
13
+ return :stop
14
+ elsif tile.empty?
15
+ return :move
16
+ end
17
+ end
18
+
19
+ def die()
20
+ @game.remove_npc(self)
21
+ @map.set_tile @position, Tile.new(@position, ' ')
22
+ end
23
+
24
+ def bited()
25
+ @blood -= 1
26
+ if @blood <= 0
27
+ die()
28
+ end
29
+ end
30
+
31
+ def hit(damage)
32
+ @life -= damage
33
+ if @life <= 0
34
+ die()
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ class BloodChalice
2
+
3
+ ASSETS_FOLDER = Pathname.new(__FILE__).dirname + '../../' + 'assets'
4
+
5
+ class Application
6
+ def self.run
7
+ say('Welcome to Blood Chalice')
8
+ number_of_players = ask("How many players are going to play?").to_i
9
+
10
+ game = Game.new(number_of_players: number_of_players)
11
+ while not game.end_of_game?
12
+ game.next_turn
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ class BloodChalice
2
+ class Chalice
3
+ include BloodChalice::Movable
4
+ include BloodChalice::TileValues
5
+
6
+ attr_accessor :position, :life, :blood, :map, :value
7
+
8
+ def initialize(options = {})
9
+ @position = options[:position]
10
+ @map = options[:map]
11
+ @life = 400
12
+ @blood = 0
13
+ @value = 'C'
14
+ end
15
+
16
+ def to_s
17
+ @value.to_s
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ class BloodChalice
2
+ class EventDeck
3
+ CARDS = [:new_zombie, :new_knight, :new_peasant]
4
+
5
+ attr_accessor :game, :map
6
+
7
+ def initialize(game)
8
+ @game = game
9
+ @map = game.map
10
+ end
11
+
12
+ def take_a_card()
13
+ modify_world(get_card())
14
+ end
15
+
16
+ def get_card()
17
+ CARDS.sample
18
+ end
19
+
20
+ def modify_world(card)
21
+ empty_tiles = @map.map.flatten.select { |t| t.empty?}
22
+ case card
23
+ when :new_zombie
24
+ puts "New zombie!"
25
+ tile = empty_tiles.sample
26
+ @map.set_tile(tile.position, Zombie.new(map: @map, position: tile.position, game: @game))
27
+ when :new_knight
28
+ puts "New Knight!"
29
+ tile = empty_tiles.sample
30
+ @map.set_tile(tile.position, Knight.new(map: @map, position: tile.position, game: @game))
31
+ when :new_peasant
32
+ puts "New Peasant!"
33
+ tile = empty_tiles.sample
34
+ @map.set_tile(tile.position, Peasant.new(map: @map, position: tile.position, game: @game))
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,133 @@
1
+ class BloodChalice
2
+ class Game
3
+ include HighLine::SystemExtensions
4
+
5
+ attr_accessor :map, :number_of_players, :players, :turn, :chalice, :non_playable_characters, :event_deck
6
+
7
+ END_OF_THE_WORLD = 400
8
+
9
+ def initialize(options = {})
10
+ @non_playable_characters = []
11
+ @map = Map.new('map1')
12
+ @number_of_players = options[:number_of_players]
13
+ @players = generate_players(map)
14
+ generate_npc(map)
15
+ @turn = 1
16
+ @event_deck = EventDeck.new(self)
17
+ end
18
+
19
+ def next_turn()
20
+ event_deck.take_a_card
21
+ players.each do |player|
22
+ player.reset_moves
23
+ while player.moves?
24
+ show_interface(player)
25
+ ask_next_action(player)
26
+ end
27
+ show_interface(player)
28
+ ask "Next Player: hit enter"
29
+ end
30
+
31
+ @non_playable_characters.each &:reset_moves
32
+ @non_playable_characters.each &:think
33
+
34
+ @turn += 1
35
+ end
36
+
37
+ def ask_next_action(player)
38
+ say "A Move to the West"
39
+ say "D Move to the East"
40
+ say "W Move to the North"
41
+ say "S Move to the South"
42
+ say "Q Quit"
43
+
44
+ print 'Your order: '
45
+ action = get_character.chr.upcase
46
+
47
+ case action.strip
48
+ when 'W'
49
+ player.move(:north)
50
+ when 'D'
51
+ player.move(:east)
52
+ when 'S'
53
+ player.move(:south)
54
+ when 'A'
55
+ player.move(:west)
56
+ when 'Q'
57
+ exit()
58
+ end
59
+ end
60
+
61
+ def end_of_game?()
62
+ (@turn == END_OF_THE_WORLD) or all_players_dead? or @chalice.blood >= 50
63
+ end
64
+
65
+ def all_players_dead?
66
+ @players.all? {|p| p.dead?}
67
+ end
68
+
69
+ def generate_players(number_of_players)
70
+ 1.upto(number_of_players) { |i| @players << Player.new(number: i, map: @map) }
71
+ end
72
+
73
+ def show_interface(player)
74
+ system('clear')
75
+ say "It is the turn of Player #{player.number} and there are #{END_OF_THE_WORLD - @turn} turns until dawn."
76
+ say "The Blood Chalice has #{@chalice.blood} of 50 blood units"
77
+ show_map
78
+ say "You have #{player.moves}/#{Player::SPEED} moves left, #{player.blood} blood stored and #{player.life}/#{Player::MAX_LIFE} HP"
79
+ say 'What are your orders, my Liege?'
80
+ end
81
+
82
+ def show_map()
83
+ say @map.to_s
84
+ end
85
+
86
+ def active_player?(tile)
87
+ tile.value.to_i <= @number_of_players
88
+ end
89
+
90
+ def remove_npc(npc)
91
+ @non_playable_characters.delete(npc)
92
+ end
93
+
94
+ def generate_npc(map)
95
+ map.map.each_with_index do |line, y|
96
+ line.each_with_index do |tile, x|
97
+ if tile.peasant?
98
+ peasant = Peasant.new(map: map, position: [y, x], game: self)
99
+ @non_playable_characters << peasant
100
+ map.set_tile [y, x], peasant
101
+ elsif tile.zombie?
102
+ zombie = Zombie.new(map: map, position: [y, x], game: self)
103
+ @non_playable_characters << zombie
104
+ map.set_tile [y, x], zombie
105
+ elsif tile.knight?
106
+ knight = Knight.new(map: map, position: [y, x], game: self)
107
+ @non_playable_characters << knight
108
+ map.set_tile [y, x], knight
109
+ elsif tile.chalice?
110
+ @chalice = Chalice.new(map: map, position: [y, x], game: self)
111
+ map.set_tile [y, x], @chalice
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ def generate_players(map)
118
+ players = []
119
+
120
+ map.map.each_with_index do |line, y|
121
+ line.each_with_index do |tile, x|
122
+ if tile.player? && active_player?(tile)
123
+ players << map[y][x] = Player.new(map: map, position: [y, x], number: tile.value, game: self)
124
+ elsif tile.player?
125
+ map.set_tile [y, x], Tile.new([y, x], ' ')
126
+ end
127
+ end
128
+ end
129
+ players
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,44 @@
1
+ class BloodChalice
2
+ class Knight
3
+ include BloodChalice::Movable
4
+ include BloodChalice::TileValues
5
+ include BloodChalice::ArtificialIntelligence
6
+
7
+ attr_accessor :position, :life, :blood, :map, :value, :speed, :game
8
+
9
+ MAX_LIFE = 5
10
+ SPEED = 3
11
+ ATTACK = 1
12
+ VISION = 6
13
+ MAXBLOOD = 1
14
+
15
+ def initialize(options = {})
16
+ @position = options[:position]
17
+ @map = options[:map]
18
+ @game = options[:game]
19
+ @life = MAX_LIFE
20
+ @blood = MAXBLOOD
21
+ @value = 'K'
22
+ @speed = SPEED
23
+ end
24
+
25
+ def reacts_to(tile)
26
+ if tile.wall?
27
+ return :stop
28
+ elsif tile.empty?
29
+ return :move
30
+ elsif tile.player?
31
+ tile.hit(ATTACK)
32
+ return :fight
33
+ elsif tile.zombie?
34
+ tile.hit(ATTACK)
35
+ return :fight
36
+ end
37
+ end
38
+
39
+ def to_s
40
+ @value.to_s
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ class BloodChalice
2
+ class Map
3
+ attr_accessor :map, :number_of_players
4
+
5
+ def initialize(path)
6
+ @map = load_map(path)
7
+ end
8
+
9
+ def value(position)
10
+ @map[position[0]][position[1]]
11
+ end
12
+
13
+ def set_tile(position, value)
14
+ @map[position[0]][position[1]] = value
15
+ end
16
+
17
+ def to_s
18
+ result = ''
19
+ @map.each do |line|
20
+ line.each { |tile| result += tile.to_s }
21
+ result += "\n"
22
+ end
23
+ result
24
+ end
25
+
26
+ def[](value)
27
+ @map[value]
28
+ end
29
+
30
+ private
31
+
32
+ def load_map(path)
33
+ filename = ASSETS_FOLDER + "world/#{path}"
34
+
35
+ map = File.readlines(filename).each_with_index.map do |line, y|
36
+ line.strip.split(//).each_with_index.map do |tile, x|
37
+ Tile.new([y, x], tile)
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,56 @@
1
+ class BloodChalice
2
+ module Movable
3
+ DIRECTIONS = {north: [-1, 0], east: [0, 1], south: [1, 0], west: [0, -1] }
4
+
5
+ def move(direction)
6
+ case direction
7
+ when :north
8
+ reactions sum_positions(@position, DIRECTIONS[:north])
9
+ when :south
10
+ reactions sum_positions(@position, DIRECTIONS[:south])
11
+ when :east
12
+ reactions sum_positions(@position, DIRECTIONS[:east])
13
+ when :west
14
+ reactions sum_positions(@position, DIRECTIONS[:west])
15
+ end
16
+ end
17
+
18
+ def reactions(position)
19
+ case reacts_to(@map.value(position))
20
+ when :move
21
+ move!(position)
22
+ when :fight
23
+ @moves = 0
24
+ end
25
+ end
26
+
27
+ def hit(damage)
28
+ @life -= damage
29
+ if @life <= 0
30
+ die()
31
+ end
32
+ end
33
+
34
+ def reset_moves
35
+ @moves = self.speed
36
+ end
37
+
38
+ def move!(position)
39
+ @map.set_tile(@position, Tile.new(@position, ' '))
40
+ @position = position
41
+ @moves -= 1
42
+ @map.set_tile(position, self)
43
+ end
44
+
45
+ def moves?
46
+ self.moves > 0
47
+ end
48
+
49
+ private
50
+
51
+ def sum_positions(pos1, pos2)
52
+ [pos1[0] + pos2[0], pos1[1] + pos2[1]]
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,29 @@
1
+ class BloodChalice
2
+ class Peasant
3
+ include BloodChalice::Movable
4
+ include BloodChalice::TileValues
5
+ include BloodChalice::ArtificialIntelligence
6
+
7
+ attr_accessor :position, :life, :blood, :map, :value, :speed, :game
8
+
9
+ MAX_LIFE = 2
10
+ SPEED = 2
11
+ ATTACK = 0
12
+ VISION = 6
13
+ MAXBLOOD = 3
14
+
15
+ def initialize(options = {})
16
+ @position = options[:position]
17
+ @map = options[:map]
18
+ @game = options[:game]
19
+ @life = MAX_LIFE
20
+ @blood = MAXBLOOD
21
+ @value = 'P'
22
+ @speed = SPEED
23
+ end
24
+
25
+ def to_s
26
+ @value.to_s
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,68 @@
1
+ class BloodChalice
2
+ class Player
3
+ include BloodChalice::Movable
4
+ include BloodChalice::TileValues
5
+
6
+ attr_accessor :position, :life, :blood, :number, :map, :moves, :value, :speed, :game
7
+
8
+ MAX_LIFE = 100
9
+ SPEED = 7
10
+ ATTACK = 3
11
+ VISION = 10
12
+
13
+ def initialize(options = {})
14
+ @position = options[:position]
15
+ @value = @number = options[:number]
16
+ @map = options[:map]
17
+ @game = options[:game]
18
+ @life = MAX_LIFE
19
+ @moves = SPEED
20
+ @blood = 0
21
+ @speed = SPEED
22
+ end
23
+
24
+ def reacts_to(tile)
25
+ if tile.wall?
26
+ return :stop
27
+ elsif tile.player?
28
+ return :stop
29
+ elsif tile.peasant?
30
+ bite(tile)
31
+ return :fight
32
+ elsif tile.zombie?
33
+ fight(tile)
34
+ return :fight
35
+ elsif tile.knight?
36
+ fight(tile)
37
+ return :fight
38
+ elsif tile.chalice?
39
+ pour_blood(tile)
40
+ elsif tile.empty?
41
+ return :move
42
+ end
43
+ end
44
+
45
+ def pour_blood(chalice)
46
+ chalice.blood += @blood
47
+ @blood = 0
48
+ end
49
+
50
+ def fight(enemy)
51
+ enemy.hit(ATTACK)
52
+ end
53
+
54
+ def bite(human)
55
+ human.bited
56
+ @blood += 1
57
+ end
58
+
59
+ def dead?
60
+ life < 1
61
+ end
62
+
63
+ def to_s
64
+ @number.to_s
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,46 @@
1
+ class BloodChalice
2
+ module TileValues
3
+ def wall?
4
+ @value == '#'
5
+ end
6
+
7
+ def player?
8
+ @value.to_i > 0
9
+ end
10
+
11
+ def empty?
12
+ @value == ' '
13
+ end
14
+
15
+ def peasant?
16
+ @value == 'P'
17
+ end
18
+
19
+ def zombie?
20
+ @value == 'Z'
21
+ end
22
+
23
+ def knight?
24
+ @value == 'K'
25
+ end
26
+
27
+ def chalice?
28
+ @value == 'C'
29
+ end
30
+ end
31
+
32
+ class Tile
33
+ include BloodChalice::TileValues
34
+ attr_accessor :value, :position
35
+
36
+ def initialize(position, value )
37
+ @value = value
38
+ @position = position
39
+ end
40
+
41
+ def to_s
42
+ @value.to_s
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ class BloodChalice
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,44 @@
1
+ class BloodChalice
2
+ class Zombie
3
+ include BloodChalice::Movable
4
+ include BloodChalice::TileValues
5
+ include BloodChalice::ArtificialIntelligence
6
+
7
+ attr_accessor :position, :life, :blood, :map, :value, :speed, :game
8
+
9
+ MAX_LIFE = 2
10
+ SPEED = 2
11
+ ATTACK = 1
12
+ VISION = 5
13
+ MAXBLOOD = 0
14
+
15
+ def initialize(options = {})
16
+ @position = options[:position]
17
+ @map = options[:map]
18
+ @game = options[:game]
19
+ @life = MAX_LIFE
20
+ @blood = MAXBLOOD
21
+ @value = 'Z'
22
+ @speed = SPEED
23
+ end
24
+
25
+ def reacts_to(tile)
26
+ if tile.wall?
27
+ return :stop
28
+ elsif tile.empty?
29
+ return :move
30
+ elsif tile.player? or tile.knight?
31
+ tile.hit(ATTACK)
32
+ return :fight
33
+ elsif tile.peasant? # Will be changed
34
+ tile.hit(ATTACK)
35
+ return :fight
36
+ end
37
+ end
38
+
39
+ def to_s
40
+ @value.to_s
41
+ end
42
+
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bloodchalice
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gonzalo Rodriguez-Baltanas Diaz
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-13 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: You and your friends will be vampires. Each turn you will be able to
15
+ move, fight, drink blood and transfer blood to the chalice.
16
+ email: siotopo@gmail.com
17
+ executables:
18
+ - bloodchalice
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/bloodchalice/ai.rb
23
+ - lib/bloodchalice/bloodchalice.rb
24
+ - lib/bloodchalice/chalice.rb
25
+ - lib/bloodchalice/event_deck.rb
26
+ - lib/bloodchalice/game.rb
27
+ - lib/bloodchalice/knight.rb
28
+ - lib/bloodchalice/map.rb
29
+ - lib/bloodchalice/movable.rb
30
+ - lib/bloodchalice/peasant.rb
31
+ - lib/bloodchalice/player.rb
32
+ - lib/bloodchalice/tile.rb
33
+ - lib/bloodchalice/version.rb
34
+ - lib/bloodchalice/zombie.rb
35
+ - lib/bloodchalice.rb
36
+ - bin/bloodchalice
37
+ - assets/world/map1
38
+ homepage: https://github.com/Nerian/s9-e1
39
+ licenses: []
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 1.8.10
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: A cooperative roleplaying videogame
62
+ test_files: []