eschaton 0.0.2
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/LICENSE.md +21 -0
- data/README.md +25 -0
- data/bin/eschaton +70 -0
- data/lib/eschaton/combatant.rb +177 -0
- data/lib/eschaton/game.rb +198 -0
- data/lib/eschaton/gamemaster.rb +52 -0
- data/lib/eschaton/strategic_targets.rb +48 -0
- data/spec/eschaton/combatant_spec.rb +37 -0
- data/spec/eschaton/game_spec.rb +61 -0
- data/spec/eschaton/strategic_targets_spec.rb +18 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 36c88e36d0464df530240a63f138783a11ab9c05
|
4
|
+
data.tar.gz: 953284e6342cbbd4b7161ef149d0655ab398e4ed
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1c22e4cbb81aba1e6a6fba513729a8e36bc974ac3b4f8b04a7bfaa917c39ff449c9a8f1cb467041428b5f99a1f9f390bca65f5e508f1bfad92168dc54f957539
|
7
|
+
data.tar.gz: 242280e8543ac809f4e3a21d9c0ec6dd7155a037d92ada4e0ffb2f5c68b2b1a792c15f3aa0d5cb0e38a885b5ac12c8f5c4ae7532dadb2964b26170f06914139f
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2014, Sean Parr
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Eschaton for Ruby
|
2
|
+
|
3
|
+
|
4
|
+
An attempt to adapt the game of Eschaton, from David Foster Wallace's [*Infinite Jest*](http://en.wikipedia.org/wiki/Infinite_Jest), into a text-based Ruby game. Definitely a work in progress. Not much to look at now, but I'll update the README when the game gets a little more involved.
|
5
|
+
|
6
|
+
|
7
|
+
To install:
|
8
|
+
|
9
|
+
gem install eschaton
|
10
|
+
|
11
|
+
To play:
|
12
|
+
|
13
|
+
eschaton
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
License
|
19
|
+
----
|
20
|
+
|
21
|
+
MIT
|
22
|
+
|
23
|
+
Copyright (c) 2014, Sean Parr
|
24
|
+
|
25
|
+
Eschaton is provided as-is under the MIT license. For more information see LICENSE.
|
data/bin/eschaton
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/eschaton/game'
|
4
|
+
|
5
|
+
new_game = Eschaton::Game.new
|
6
|
+
|
7
|
+
puts "\n \n \n"
|
8
|
+
|
9
|
+
puts "ESCHATON".center(100, '-')
|
10
|
+
|
11
|
+
puts "\n \n \n "
|
12
|
+
|
13
|
+
puts "c:\\Pink2\\Mathpak\\Endstat...\n "
|
14
|
+
|
15
|
+
3.times do
|
16
|
+
sleep(1)
|
17
|
+
puts "\n...loading...\n"
|
18
|
+
sleep(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
puts "\nEschaton is a thermonuclear warfare game played by the students at the Enfield Tennis Academy in Boston."
|
22
|
+
puts "You will belong to a Combatant nation, between AMNAT, SOVWAR, REDCHI, INDPAK, IRLIBSYR, or SOUTHAF."
|
23
|
+
puts "The point of the game is to lob a tennis ball (thermonuclear warhead) accurately at an opposing combatant's"
|
24
|
+
puts "strategic target, of which there are many, and with their own corresponding point values."
|
25
|
+
puts "Certain strategic targets carry higher point values but due to their scarcity, are harder to hit."
|
26
|
+
puts "A given Eschaton's winning team is simply that Combatant with the most favorable ratio of points for INDDIR -"
|
27
|
+
puts "Infliction of Death, Destruction, and Incapacity of Response - to SUFDDIR - self-evident.\n "
|
28
|
+
|
29
|
+
puts "Got it? (press Enter)\n "
|
30
|
+
|
31
|
+
gets
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
loop do
|
36
|
+
|
37
|
+
puts "\nHow many rounds of Eschaton would we be playing? ('quit' or 'q' to exit)\n "
|
38
|
+
|
39
|
+
answer = gets.chomp
|
40
|
+
|
41
|
+
case answer
|
42
|
+
|
43
|
+
when /^\d+$/
|
44
|
+
|
45
|
+
new_game.control_combatant
|
46
|
+
|
47
|
+
gets
|
48
|
+
|
49
|
+
new_game.play(answer.to_i)
|
50
|
+
|
51
|
+
when 'quit', 'q'
|
52
|
+
puts "\n \n "
|
53
|
+
puts "Thanks for playing ESCHATON".center(80, ' ')
|
54
|
+
puts "\n \n "
|
55
|
+
puts "\"See yourself in your opponents. They will bring you to understand the game.".center(80, ' ')
|
56
|
+
puts "To accept the fact that the Game is about managed fear.".center(80, ' ')
|
57
|
+
puts "That its object is to send from yourself what you hope will not return.\"\n ".center(80, ' ')
|
58
|
+
puts ' - David Foster Wallace'.rjust(80, ' ')
|
59
|
+
puts "\nP.S. Allston Rules!\n "
|
60
|
+
break
|
61
|
+
|
62
|
+
else
|
63
|
+
|
64
|
+
puts "\nError: Please enter a number"
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require_relative 'strategic_targets'
|
2
|
+
|
3
|
+
module Eschaton
|
4
|
+
|
5
|
+
class Combatant
|
6
|
+
attr_accessor :nation, :megatonnage, :inddir, :sufddir, :accuracy, :defcon, :rad_level, :em_immunity, :population, :score
|
7
|
+
|
8
|
+
# megatonnage =
|
9
|
+
# integrally regressed ratio of:
|
10
|
+
# yearly military budget as percentage of yearly GNP
|
11
|
+
# inverse of stratego-tactical expenditures as percentage of yearly military budget
|
12
|
+
# GNP/Military // Military/Nuke ratio
|
13
|
+
|
14
|
+
|
15
|
+
def initialize(nation, megatonnage: 400, defcon: 5, sufddir: 0.0, inddir: 0.0,
|
16
|
+
sacpop: 0, rad_level: 0, em_immunity: true,
|
17
|
+
population: 300_000_000, accuracy: 0, score: 0)
|
18
|
+
|
19
|
+
@nation = nation.to_s.upcase
|
20
|
+
@sufddir = sufddir #suffering of death, destruction, and incapacitation of response
|
21
|
+
@inddir = inddir #infliction of death, destruction, and incapacitation of response
|
22
|
+
@defcon = defcon
|
23
|
+
@sacpop = sacpop # strikes against civilian populations
|
24
|
+
@megatonnage = megatonnage # distrubtion of megatonnage determined by mean-value theorem of integrals
|
25
|
+
@rad_level = rad_level
|
26
|
+
@em_immunity = em_immunity
|
27
|
+
@population = population
|
28
|
+
@accuracy = accuracy
|
29
|
+
@score = score
|
30
|
+
@targets_hit = Hash.new(0)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"#{@nation.ljust(20, '.')} SUFDDIR: #{@sufddir} / INDDIR: #{@inddir} / MEGATONNAGE: #{@megatonnage}\nDEFCON: #{@defcon} / RADIATION: #{@rad_level} / EM-PULSE IMMUNITY: #{@em_immunity} / SURVIVING POPULATION: #{@population}\n "
|
35
|
+
end
|
36
|
+
|
37
|
+
def <=>(other)
|
38
|
+
other.score <=> score
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# statistics
|
43
|
+
|
44
|
+
|
45
|
+
def scoretotal
|
46
|
+
if @sufddir > 0
|
47
|
+
@score = @inddir/@sufddir
|
48
|
+
@score.round(2)
|
49
|
+
else
|
50
|
+
@score = @inddir
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def hit_target(target)
|
55
|
+
@targets_hit[target.name.to_sym] += target.ptvalue
|
56
|
+
end
|
57
|
+
|
58
|
+
def target_stats
|
59
|
+
total_target_points = @targets_hit.values.reduce(0) {|sum, val| sum + val }
|
60
|
+
puts "Total INDDIR from ALL targets: ".upcase + total_target_points.to_s
|
61
|
+
sleep(1)
|
62
|
+
end
|
63
|
+
|
64
|
+
def each_hit_target
|
65
|
+
@targets_hit.each do |name, value|
|
66
|
+
yield Target.new(name, value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
# attacks
|
74
|
+
|
75
|
+
|
76
|
+
def lob(opponent)
|
77
|
+
if @megatonnage > 0
|
78
|
+
@inddir += 30
|
79
|
+
@megatonnage -= 5
|
80
|
+
|
81
|
+
opponent.sufddir += 30
|
82
|
+
if opponent.defcon > 1
|
83
|
+
opponent.defcon -= 1
|
84
|
+
end
|
85
|
+
opponent.rad_level += 20
|
86
|
+
opponent.population -= rand(100_000..200_000)
|
87
|
+
|
88
|
+
@score = self.scoretotal
|
89
|
+
puts "#{@nation} lobs a warhead at #{opponent.nation} (+30 INDDIR)!"
|
90
|
+
else
|
91
|
+
puts "#{@nation}'s megaton supply has been depleted."
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def sacpop(opponent)
|
96
|
+
if @megatonnage > 0
|
97
|
+
@inddir += 100
|
98
|
+
@sacpop += 1
|
99
|
+
@megatonnage -= 5
|
100
|
+
|
101
|
+
opponent.sufddir += 100
|
102
|
+
if opponent.defcon > 2
|
103
|
+
opponent.defcon -= 2
|
104
|
+
else
|
105
|
+
opponent.defcon = 1
|
106
|
+
end
|
107
|
+
opponent.rad_level += 20
|
108
|
+
opponent.population -= rand(100_000..200_000)
|
109
|
+
|
110
|
+
@score = self.scoretotal
|
111
|
+
puts "#{@nation} strikes one of #{opponent.nation}'s civilian populations..."
|
112
|
+
puts self
|
113
|
+
puts ' '
|
114
|
+
else
|
115
|
+
puts "#{@nation}'s megaton supply has been depleted.\ "
|
116
|
+
puts self
|
117
|
+
puts ' '
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def mirv(opponent)
|
122
|
+
if @megatonnage > 350
|
123
|
+
puts "Dear God. #{@nation} launches a neatly tied MIRV jockstrap at #{opponent.nation}..."
|
124
|
+
@inddir += 100
|
125
|
+
@megatonnage -= 350
|
126
|
+
|
127
|
+
opponent.sufddir += 300
|
128
|
+
opponent.defcon = 1
|
129
|
+
opponent.rad_level += 100
|
130
|
+
opponent.population -= rand(100_000_000..200_000_000)
|
131
|
+
8.times do
|
132
|
+
GameMaster.spasex(self, opponent)
|
133
|
+
sleep(1)
|
134
|
+
end
|
135
|
+
|
136
|
+
@score = self.scoretotal
|
137
|
+
puts self
|
138
|
+
puts ' '
|
139
|
+
else
|
140
|
+
puts "#{@nation}'s megaton supply is insufficient for this attack.\n "
|
141
|
+
puts self
|
142
|
+
puts ' '
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
|
151
|
+
# def empulse(opponent)
|
152
|
+
# puts "#{@nation} fires an electro-magnetic pulse at #{opponent.nation}'s comm. systems..."
|
153
|
+
# if opponent.em_immunity == false
|
154
|
+
# opponent.comm_loss
|
155
|
+
# puts "#{opponent.nation}'s comm. systems have been shut down!"
|
156
|
+
# else
|
157
|
+
# puts "#{opponent.nation}'s em-pulse immunity is too high. #{opponent.nation} retains all communications."
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
# # statuses
|
164
|
+
|
165
|
+
# def comm_loss
|
166
|
+
# #loss of next turn
|
167
|
+
# end
|
168
|
+
|
169
|
+
# def incapacitated?
|
170
|
+
# #ratio of SUFDDIR, loss of turns
|
171
|
+
# end
|
172
|
+
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require_relative 'combatant'
|
2
|
+
require_relative 'gamemaster'
|
3
|
+
require_relative 'strategic_targets'
|
4
|
+
|
5
|
+
module Eschaton
|
6
|
+
|
7
|
+
class Game
|
8
|
+
|
9
|
+
# 400 5-megaton warheads total, disbursed
|
10
|
+
|
11
|
+
attr_accessor :combatants, :beanie_status
|
12
|
+
|
13
|
+
def initialize(name: "Eschaton", beanie_status: 'Normal Game Conditions')
|
14
|
+
@beanie_status = beanie_status
|
15
|
+
@combatants = [Combatant.new(:amnat), Combatant.new(:sovwar), Combatant.new(:redchi),
|
16
|
+
Combatant.new(:irlibsyr), Combatant.new(:southaf), Combatant.new(:indpak)]
|
17
|
+
# status can change to 'cessation of hostilities'
|
18
|
+
# and 'utter global crisis'
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
# initializes player control of random Combatant. A bit hacky, yes
|
25
|
+
|
26
|
+
def control_combatant
|
27
|
+
@playercombatant = @combatants.delete_at(rand(@combatants.length))
|
28
|
+
puts "\nFor this game of Eschaton, you've been designated to be represent #{@playercombatant.nation}. (press Enter)\n "
|
29
|
+
@playercombatant.nation.prepend '*'
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
# gameplay
|
43
|
+
|
44
|
+
|
45
|
+
def play(rounds)
|
46
|
+
|
47
|
+
1.upto(rounds) do |r|
|
48
|
+
puts "\nRound #{r}\n "
|
49
|
+
|
50
|
+
puts "Which Combatant will you attack?"
|
51
|
+
puts @combatants.map{|x| x.nation }.sort.join(', ')
|
52
|
+
|
53
|
+
puts ' '
|
54
|
+
|
55
|
+
# This loop cycles through the @combatants array for a match between the user's input
|
56
|
+
# and each Combatant's nation abbreviation. If match found, we store the Combatant in
|
57
|
+
# the @target variable. If no match, we ask user to try again.
|
58
|
+
|
59
|
+
loop do
|
60
|
+
target = gets.chomp.upcase
|
61
|
+
|
62
|
+
puts ' '
|
63
|
+
|
64
|
+
if @combatants.any? { |i| i.nation == target }
|
65
|
+
@target = @combatants.find {|x| x.nation == target }
|
66
|
+
GameMaster.spasex(@playercombatant, @target)
|
67
|
+
sleep(2)
|
68
|
+
break
|
69
|
+
else
|
70
|
+
puts "Please enter the name of a Combatant:"
|
71
|
+
puts @combatants.map{|x| x.nation }.sort.join(', ')
|
72
|
+
puts ' '
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# puts "Enter an nuclear attack sequence:"
|
78
|
+
|
79
|
+
# loop do
|
80
|
+
|
81
|
+
# puts "LOB [Nuclear Attack]"
|
82
|
+
# puts "SACPOP [Strike Against Civilian Population]"
|
83
|
+
# puts "MIRV [Multiple Independent Reetry Vehicle]\n "
|
84
|
+
|
85
|
+
# attack = gets.chomp.upcase
|
86
|
+
|
87
|
+
# puts ' '
|
88
|
+
|
89
|
+
# case attack
|
90
|
+
# when "LOB"
|
91
|
+
# GameMaster.spasex(@playercombatant, @target)
|
92
|
+
# break
|
93
|
+
# when "SACPOP"
|
94
|
+
# @playercombatant.sacpop(@target)
|
95
|
+
# break
|
96
|
+
# when "MIRV"
|
97
|
+
# @playercombatant.mirv(@target)
|
98
|
+
# break
|
99
|
+
# else
|
100
|
+
# puts "Error: Incorrect Attack Sequence"
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
|
104
|
+
# sleep(2)
|
105
|
+
|
106
|
+
@combatants.each do |c|
|
107
|
+
|
108
|
+
# clone the @combatant array without the current Combatant
|
109
|
+
combatantsclone = @combatants.reject { |x| x.nation == c.nation }
|
110
|
+
combatantsclone << @playercombatant # add @playercombatant to array of attackable Combatants
|
111
|
+
|
112
|
+
opp = combatantsclone.sample
|
113
|
+
|
114
|
+
|
115
|
+
GameMaster.spasex(c, opp)
|
116
|
+
|
117
|
+
combatantsclone.reject! { |x| x.nation == @playercombatant.nation} #removes @playercombatant again
|
118
|
+
sleep(2)
|
119
|
+
end
|
120
|
+
|
121
|
+
# if @combatants.all? {|c| c.defcon == 1 }
|
122
|
+
# @beanie_status = 'Utter Global Crisis'
|
123
|
+
# puts "\nEvery Combatant has entered DEFCON 1. Otis P. Lord has donned the Red Beanie. #{@beanie_status.upcase}.\n "
|
124
|
+
# sleep(2)
|
125
|
+
# end
|
126
|
+
|
127
|
+
if @combatants.all? {|c| c.megatonnage == 0}
|
128
|
+
@beanie_status = 'Cessation of Hostilities'
|
129
|
+
puts "\nIt appears the Global supply of Nuclear Weapons has been depleted. Otis P. Lord has donned the White Beanie. #{@beanie_status}.\n "
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
puts "END OF GAME".center(30, ".")
|
134
|
+
puts "\npress Enter to calculate results\n "
|
135
|
+
gets
|
136
|
+
puts "\nEndStat calculating results...\n "
|
137
|
+
sleep(2)
|
138
|
+
3.times do
|
139
|
+
puts "calculating...\n "
|
140
|
+
sleep(1)
|
141
|
+
end
|
142
|
+
puts " "
|
143
|
+
finalstats
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
# statistics
|
158
|
+
|
159
|
+
def print_score(combatant)
|
160
|
+
puts "#{combatant.nation} SCORE".ljust(50, '.') + "#{combatant.score} pts. \n "
|
161
|
+
end
|
162
|
+
|
163
|
+
def finalstats
|
164
|
+
@combatants << @playercombatant
|
165
|
+
accuracy_rankings = @combatants.sort {|a,b| b.accuracy <=> a.accuracy }
|
166
|
+
mvl = accuracy_rankings.first
|
167
|
+
if mvl.accuracy = 1
|
168
|
+
puts "Most Valuable Lobber: #{mvl.nation} with #{mvl.accuracy} direct hit!\n "
|
169
|
+
else
|
170
|
+
puts "Most Valuable Lobber: #{mvl.nation} with #{mvl.accuracy} direct hits!\n "
|
171
|
+
end
|
172
|
+
sleep(1.5)
|
173
|
+
|
174
|
+
@combatants.each {|c| c.scoretotal } # calculates the INDDIR/SUFDDIR ratio for a final score.
|
175
|
+
|
176
|
+
score_rankings = @combatants.sort {|a,b| b.score <=> a.score}
|
177
|
+
puts "Final Rankings:\n"
|
178
|
+
puts " "
|
179
|
+
ranknum = 1
|
180
|
+
score_rankings.each do |c|
|
181
|
+
puts "#{ranknum} #{c.nation}:"
|
182
|
+
puts "Total Infliction of Death, Destruction and Incapacitation of Response(INDDIR): #{c.inddir}"
|
183
|
+
puts "Total Suffering of Death, Destruction and Incapacitation of Response(SUFDDIR): #{c.sufddir}"
|
184
|
+
puts "Direct Hits: #{c.accuracy}"
|
185
|
+
c.each_hit_target do |t|
|
186
|
+
puts "Total INDDIR from striking #{t.name}s: #{t.ptvalue}"
|
187
|
+
end
|
188
|
+
c.target_stats
|
189
|
+
print_score(c)
|
190
|
+
ranknum += 1
|
191
|
+
end
|
192
|
+
puts score_rankings.first.nation + ' wins! (press Enter to continue)'
|
193
|
+
gets
|
194
|
+
@playercombatant.nation[0] = ''
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Eschaton
|
2
|
+
|
3
|
+
module GameMaster
|
4
|
+
|
5
|
+
def self.accuracy
|
6
|
+
rand(1..20)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.spasex(combatant, opponent)
|
10
|
+
lobaccuracy = accuracy
|
11
|
+
|
12
|
+
target = StrategicTargets.random
|
13
|
+
|
14
|
+
case accuracy
|
15
|
+
when 18..20
|
16
|
+
combatant.lob(opponent)
|
17
|
+
combatant.accuracy += 1
|
18
|
+
combatant.inddir += 20
|
19
|
+
puts "#{combatant.nation}'s warhead directly (+20 INDDIR) hits a #{target.name}(+#{target.ptvalue} INDDIR)! Ho-ly CROW!"
|
20
|
+
combatant.hit_target(target)
|
21
|
+
combatant.inddir += target.ptvalue
|
22
|
+
puts combatant
|
23
|
+
when 4..17
|
24
|
+
combatant.lob(opponent)
|
25
|
+
puts "#{combatant.nation}'s warhead hit a #{target.name}(+#{target.ptvalue} INDDIR)!"
|
26
|
+
combatant.hit_target(target)
|
27
|
+
combatant.inddir += target.ptvalue
|
28
|
+
puts combatant
|
29
|
+
else
|
30
|
+
puts "#{combatant.nation} whiffed it!"
|
31
|
+
combatant.megatonnage -= 5
|
32
|
+
puts combatant
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
# def milabbrevs
|
38
|
+
# puts "MILABBREVS(Military Abbreviations)......."
|
39
|
+
# puts "CONFORCON: Conventional Force Concentrations"
|
40
|
+
# puts "INDDIR: Infliction of Death, Destruction and Incapacitation of Response"
|
41
|
+
# puts "MAMA: Major Metropolitan Areas"
|
42
|
+
# puts "MIRV: Multiple Independent Reentry Vehicles"
|
43
|
+
# puts "SACPOP: Strikes Against Civilian Populations"
|
44
|
+
# puts "SPASEX: Spasm Exchanges"
|
45
|
+
# puts "SSTRAC: Sites of Strategic Command"
|
46
|
+
# puts "SUFDDIR: Suffering of Death, Destruction and Incapacitation of Response"
|
47
|
+
# end
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Eschaton
|
2
|
+
|
3
|
+
Target = Struct.new(:name, :ptvalue)
|
4
|
+
|
5
|
+
module StrategicTargets
|
6
|
+
|
7
|
+
|
8
|
+
TARGETS = [
|
9
|
+
Target.new("MAMA", 100),
|
10
|
+
Target.new("CONFORCON", 50),
|
11
|
+
Target.new("SSTRAC", 100),
|
12
|
+
Target.new("submarine", 15),
|
13
|
+
Target.new("airfield", 20),
|
14
|
+
Target.new("bridge", 5),
|
15
|
+
Target.new("satellite facility", 25),
|
16
|
+
Target.new("carrier group", 28),
|
17
|
+
Target.new("power plant", 35),
|
18
|
+
Target.new("rail convergence", 23),
|
19
|
+
Target.new("atomic plant", 45),
|
20
|
+
Target.new("plutonium uranium enrichment plant", 50),
|
21
|
+
Target.new("diffusion plant", 55),
|
22
|
+
Target.new("breeder reactor", 51),
|
23
|
+
Target.new("initiator factory", 38),
|
24
|
+
Target.new("neutron lab", 40),
|
25
|
+
Target.new("tritium reactor", 35),
|
26
|
+
Target.new("heavy water plant", 26),
|
27
|
+
Target.new("semiprivate concern", 20),
|
28
|
+
Target.new("linear accelerator", 30),
|
29
|
+
Target.new("annular fusion lab", 85),
|
30
|
+
Target.new("antimissile base", 40),
|
31
|
+
Target.new("silo cluster", 42),
|
32
|
+
Target.new("b2 squadron", 38)
|
33
|
+
]
|
34
|
+
|
35
|
+
# def self.select(target)
|
36
|
+
# if Targets.any? { |i| i.name == target }
|
37
|
+
# @target = Targets.find {|x| x.name == target }
|
38
|
+
# else
|
39
|
+
# puts "\nPlease Enter the name of a Target:\n "
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
|
43
|
+
def self.random
|
44
|
+
TARGETS.sample
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'eschaton/combatant'
|
2
|
+
|
3
|
+
|
4
|
+
describe Eschaton::Combatant do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@pemulis = Eschaton::Combatant.new('peemster')
|
8
|
+
@hal = Eschaton::Combatant.new('halsadick')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "but so like, has an upcased nation abbreviation" do
|
12
|
+
expect(@hal.nation).to eq('HALSADICK')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has an initial megatonnage" do
|
16
|
+
expect(@hal.megatonnage).to be >= 0
|
17
|
+
end
|
18
|
+
|
19
|
+
it "loses megatonnage when launching an attack" do
|
20
|
+
@pemulis.mirv(@hal)
|
21
|
+
expect(@pemulis.megatonnage).to eq(100)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "has a total score that stems from the ratio of INDDIR and SUFDDIR" do
|
25
|
+
@hal.mirv(@pemulis)
|
26
|
+
@pemulis.sacpop(@hal)
|
27
|
+
expect(@hal.scoretotal).to eq(7)
|
28
|
+
end
|
29
|
+
|
30
|
+
# it "will cause opponent comm loss if successfully launching an EM-Pulse"
|
31
|
+
|
32
|
+
|
33
|
+
# it "should not have DEFCON levels lower than 1"
|
34
|
+
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'eschaton/game'
|
2
|
+
|
3
|
+
describe Eschaton::Game do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@eschaton = Eschaton::Game.new
|
7
|
+
end
|
8
|
+
|
9
|
+
# context "being played" do
|
10
|
+
# before do
|
11
|
+
# @combatant = Eschaton.combatants.sample
|
12
|
+
# end
|
13
|
+
|
14
|
+
# it "critical hit if higher accuracy" do
|
15
|
+
# GameMaster.stub(:accuracy) {19}
|
16
|
+
# @eschaton.play(2)
|
17
|
+
# expect(combatant.inddir).to eq((inddir + 50) * 2)
|
18
|
+
# end
|
19
|
+
|
20
|
+
# it "normal damage if medium accuracy" do
|
21
|
+
# GameMaster.stub(:accuracy) {10}
|
22
|
+
# @eschaton.play(2)
|
23
|
+
# expect(@combatant.inddir).to eq((@inddir + 30) * 2)
|
24
|
+
# end
|
25
|
+
|
26
|
+
# it "misses if a low accuracy" do
|
27
|
+
# GameMaster.stub(:accuracy) {3}
|
28
|
+
# @eschaton.play(2)
|
29
|
+
# expect(@combatant.inddir).to eq(0)
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
|
33
|
+
# context "all Combatants at DEFCON 1" do
|
34
|
+
|
35
|
+
# before do
|
36
|
+
# @eschaton.combatants.map! { |c| c.defcon = 1 }
|
37
|
+
# end
|
38
|
+
|
39
|
+
# it "changes game beanie status to 'UTTER GLOBAL CRISIS'" do
|
40
|
+
# expect(@eschaton.beanie_status).to eq('UTTER GLOBAL CRISIS')
|
41
|
+
# end
|
42
|
+
|
43
|
+
# end
|
44
|
+
|
45
|
+
# it "should have a minimum of 3 rounds"
|
46
|
+
|
47
|
+
# it "should have a maximum of 400 5-megaton warheads to distribute"
|
48
|
+
|
49
|
+
# it "should distribute megatonnage to combatants"
|
50
|
+
|
51
|
+
# it "should have a beanie status to start the game"
|
52
|
+
|
53
|
+
# "eschaton beanie status at 'Cessation of Hostilities'"
|
54
|
+
|
55
|
+
# "eschaton beanie status at 'Utter Global Crisis'"
|
56
|
+
|
57
|
+
# it "should raise all combatants DEFCON levels to 1"
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'eschaton/strategic_targets'
|
2
|
+
|
3
|
+
|
4
|
+
describe Eschaton::Target do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@target = Eschaton::Target.new("MAMA", 50)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has a name attribute" do
|
11
|
+
expect(@target.name).to eql("MAMA")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "has a points attribute" do
|
15
|
+
expect(@target.ptvalue).to eq(50)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eschaton
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Parr
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: |-
|
28
|
+
# Eschaton for Ruby
|
29
|
+
|
30
|
+
|
31
|
+
An attempt to adapt the game of Eschaton, from David Foster Wallace's [*Infinite Jest*](http://en.wikipedia.org/wiki/Infinite_Jest), into a text-based Ruby game. Definitely a work in progress. Not much to look at now, but I'll update the README when the game gets a little more involved.
|
32
|
+
|
33
|
+
|
34
|
+
To install:
|
35
|
+
|
36
|
+
gem install eschaton
|
37
|
+
|
38
|
+
To play:
|
39
|
+
|
40
|
+
eschaton
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
License
|
46
|
+
----
|
47
|
+
|
48
|
+
MIT
|
49
|
+
|
50
|
+
Copyright (c) 2014, Sean Parr
|
51
|
+
|
52
|
+
Eschaton is provided as-is under the MIT license. For more information see LICENSE.
|
53
|
+
email: seancparr@gmail.com
|
54
|
+
executables:
|
55
|
+
- eschaton
|
56
|
+
extensions: []
|
57
|
+
extra_rdoc_files: []
|
58
|
+
files:
|
59
|
+
- LICENSE.md
|
60
|
+
- README.md
|
61
|
+
- bin/eschaton
|
62
|
+
- lib/eschaton/combatant.rb
|
63
|
+
- lib/eschaton/game.rb
|
64
|
+
- lib/eschaton/gamemaster.rb
|
65
|
+
- lib/eschaton/strategic_targets.rb
|
66
|
+
- spec/eschaton/combatant_spec.rb
|
67
|
+
- spec/eschaton/game_spec.rb
|
68
|
+
- spec/eschaton/strategic_targets_spec.rb
|
69
|
+
homepage: https://github.com/rubyruettiger
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.9'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 2.2.1
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: Play text game Eschaton
|
93
|
+
test_files:
|
94
|
+
- spec/eschaton/combatant_spec.rb
|
95
|
+
- spec/eschaton/game_spec.rb
|
96
|
+
- spec/eschaton/strategic_targets_spec.rb
|