bloodchalice 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []