Ok this is the actual inital code... need to convert from mongo to sqlite...
This commit is contained in:
parent
8c856ce465
commit
8fa1664bcb
13 changed files with 1168 additions and 0 deletions
166
active_rpg.rb
Normal file
166
active_rpg.rb
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
load "mongo_connect.rb"
|
||||
load "mongo_document_wrapper.rb"
|
||||
load "entity_factory.rb"
|
||||
|
||||
load "rpg_grid.rb"
|
||||
load "rpg_bets.rb"
|
||||
|
||||
class ActiveRpg
|
||||
@grid = nil
|
||||
@mc = nil
|
||||
@ef = nil
|
||||
|
||||
def initialize(grid_size = 10, db="testdb", coll="entities")
|
||||
@mc = MongoConnect.new(db, coll)
|
||||
@ef = EntityFactory.new(@mc)
|
||||
@grid = RpgGrid.new(@mc, grid_size)
|
||||
@bets = RpgBets.new(@mc)
|
||||
end
|
||||
|
||||
# this should only really ever be needed in a simulation run to clear out the DB and reset the indexes
|
||||
def get_mc()
|
||||
return @mc
|
||||
end
|
||||
|
||||
# this is just a placeholder hopefully. need to flesh out how bets are gonna work but gonna
|
||||
# delegate it to the irc bot for now...
|
||||
def get_bets()
|
||||
return @bets
|
||||
end
|
||||
|
||||
# Create and/or load player. Spawn another entity. Move the player.
|
||||
def take_turn(player_name, line)
|
||||
p = find_player(player_name)
|
||||
|
||||
new_loc = @grid.get_move_location(p.get("location"))
|
||||
|
||||
# Update the player doc with new location/exp/line
|
||||
p.set({
|
||||
'exp' => p.get('exp').to_i + 1,
|
||||
'location' => new_loc,
|
||||
'last_line' => line,
|
||||
})
|
||||
|
||||
# Spawn a new Monster
|
||||
spawn_monster(player_name, line)
|
||||
|
||||
# Spawn a potential event
|
||||
spawn_event()
|
||||
|
||||
# Resolve interaction from player movement and grab a string and return it
|
||||
res = resolve_conflict(p, new_loc)
|
||||
|
||||
update_user_boss(player_name, line)
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
def find_player(player_name)
|
||||
found_player = @mc.collection.find({"type" => :player, "name" => player_name}).first
|
||||
|
||||
if found_player == nil then
|
||||
p = @ef.get(:player)
|
||||
|
||||
p.set({
|
||||
"name" => player_name,
|
||||
"exp" => 1,
|
||||
"location" => @grid.find_location()
|
||||
})
|
||||
|
||||
return p
|
||||
else
|
||||
return @ef.build_instance(found_player)
|
||||
end
|
||||
end
|
||||
|
||||
def update_user_boss(player_name, line)
|
||||
found_boss = @mc.collection.find({"type" => :boss, "spawned_by" => player_name}).first
|
||||
|
||||
if found_boss != nil then
|
||||
#level them up by line length...
|
||||
|
||||
b = @ef.build_instance(found_boss)
|
||||
b.set({"exp" => b.get("exp") + line.length})
|
||||
else
|
||||
if rand(1000) > 900 then
|
||||
spawn_boss(player_name, line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def spawn_boss(player_name, line)
|
||||
b = @ef.get(:boss)
|
||||
b.set({
|
||||
"spawned_by" => player_name,
|
||||
"location" => @grid.find_location(),
|
||||
"exp" => line.length,
|
||||
"last_line" => line,
|
||||
})
|
||||
end
|
||||
|
||||
def spawn_monster(player_name, line)
|
||||
m = @ef.get(:monster)
|
||||
m.set({
|
||||
"spawned_by" => player_name,
|
||||
"location" => @grid.find_location(),
|
||||
"line" => line,
|
||||
"exp" => line.length,
|
||||
})
|
||||
end
|
||||
|
||||
def spawn_event()
|
||||
if rand(1000) <= 10 then
|
||||
e = @ef.get(:random_event)
|
||||
e.set({
|
||||
"location" => @grid.find_location(),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def resolve_conflict(player, loc)
|
||||
ents = find_at_location(loc)
|
||||
|
||||
if ents.count > 1 then
|
||||
battle_ents = []
|
||||
|
||||
ents.each do |e|
|
||||
if e.get("name") != player.get("name") then
|
||||
battle_ents.push e
|
||||
end
|
||||
end
|
||||
|
||||
results = []
|
||||
|
||||
# A bit clunky but basically resolve any conflicts with other objects
|
||||
# and nuke any of them that aren't other players
|
||||
battle_ents.each do |b|
|
||||
res = player.resolve(b)
|
||||
|
||||
if res != nil or res != "" then
|
||||
results.push(res)
|
||||
end
|
||||
|
||||
if b.get("type") != :player then
|
||||
b.delete()
|
||||
else
|
||||
new_loc = @grid.find_location()
|
||||
b.set({"location" => new_loc})
|
||||
end
|
||||
end
|
||||
|
||||
return results.join("; ")
|
||||
end
|
||||
end
|
||||
|
||||
def find_at_location(loc)
|
||||
ents = @mc.collection.find({"location" => loc})
|
||||
|
||||
wrapper_docs = []
|
||||
|
||||
ents.each do |e|
|
||||
wrapper_docs.push(@ef.build_instance(e))
|
||||
end
|
||||
|
||||
return wrapper_docs
|
||||
end
|
||||
end
|
||||
91
entities/boss.rb
Normal file
91
entities/boss.rb
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
class Boss < Entity
|
||||
@@bossMods = [
|
||||
"Insanely Violent", "Horiffic and Huge", "Incredibly Monstrous", "World-Threatening",
|
||||
"Disasterously Unhinged", "Literally God-like", "Absurdly Deranged", "Wildly Disastrous",
|
||||
"Potentially Universe Ending", "Unhinged Ancient", "Insatiably Hungry", "Malevolently Cruel",
|
||||
"Practically Omniscient Like Wow You Don't Even Know",
|
||||
]
|
||||
|
||||
@@bossTypes = [
|
||||
"Space Demon", "Literal Star", "Supervillian", "Kitten", "Bob", "Subatomic Particle",
|
||||
"Dental Hygenist", "Creature from Beyond the Stars", "Previously Slumbering Elder Being",
|
||||
"Bag of Snacks that Says it's 20g In Size But Somehow 19g's of it are Just Air???",
|
||||
"Mysterious Button", "English Teacher", "Corrupted Wizard", "Pit Fiend",
|
||||
"King Henry VIII's 9th Wife", "Guy Fieri", "Celestial Being", "Balloon-Shaped Horror",
|
||||
"GREAT Worm", "Planet Smasher", "DragBot Mecha-Queen",
|
||||
]
|
||||
|
||||
@@bossLosses = [
|
||||
"returned from the dimension from which they came", "slumbers under the sea once more",
|
||||
"flees to the stars", "gives up and vanishes without a trace", "runs home to devise a new plan",
|
||||
]
|
||||
|
||||
@@bossWins = [
|
||||
"isn't sure what to do with themselves now, and goes off to plan an easier conflict",
|
||||
"only partially destroys the planet", "deletes a star out there, probably somewhere over the rainbow",
|
||||
"summoned several eldritch beings that quickly passed away in their atmosphere", "eats some cake",
|
||||
]
|
||||
|
||||
@@encounterTypes = [
|
||||
"tangle", "struggle", "wrestle", "argue", "combat", "stare down", "grapple",
|
||||
]
|
||||
|
||||
def get_default_doc()
|
||||
q = {
|
||||
'type' => :boss,
|
||||
'spawned_by' => nil,
|
||||
'location' => nil,
|
||||
'exp' => nil,
|
||||
'last_line' => nil,
|
||||
'name' => @@bossMods.sample + " " + @@bossTypes.sample
|
||||
}
|
||||
|
||||
return q
|
||||
end
|
||||
|
||||
def resolve(p)
|
||||
max_player_attack = p.get('exp')
|
||||
max_xp_gain = (self.get('exp').to_f + 0.25).to_i
|
||||
|
||||
encounter_str = "runs into a Boss, spawned by " +
|
||||
self.get("spawned_by") + " with their wicked incantation of \"" +
|
||||
self.get("last_line") + "\"! Known by legend as the "
|
||||
|
||||
result = p.get("name") + "[" + max_player_attack.to_s + "str] "
|
||||
result = result + encounter_str
|
||||
result = result + self.get("name") + "[" + self.get('exp').to_s + "str] "
|
||||
|
||||
player_attack = 1+rand(max_player_attack)
|
||||
foe_attack = 1+rand(self.get('exp'))
|
||||
|
||||
result = result + "They " + @@encounterTypes.sample + "! "
|
||||
result = result + "[" + player_attack.to_s + "dmg vs " + foe_attack.to_s + "dmg]! "
|
||||
|
||||
if player_attack > foe_attack then
|
||||
xp = 1 + rand(max_xp_gain)
|
||||
result = result + p.get("name") + " wins! "
|
||||
result = result + "The " + self.get('name') + " " + @@bossLosses.sample + "! "
|
||||
result = result + p.get('name') + " earns " + xp.to_s + "xp!"
|
||||
p.gain_exp(xp)
|
||||
elsif player_attack < foe_attack then
|
||||
result = result + "The " + self.get("name") + " wins and " + @@bossWins.sample + "! "
|
||||
|
||||
if self.get("spawned_by") != p.get("name") then
|
||||
raw_spawner = @mc.collection().find({"type" => :player, "name" => self.get("spawned_by")}).first
|
||||
s = Player.new(@mc, raw_spawner)
|
||||
|
||||
xp = 1 + rand(1 + (s.get("exp")*0.05).to_i)
|
||||
|
||||
result = result + self.get("spawned_by") + "'s nefarious plan succeeded! They gain " + xp.to_s + "xp!"
|
||||
s.gain_exp(xp)
|
||||
else
|
||||
result = result + self.get("spawned_by") + " was betrayed by their creation! "
|
||||
result = result + "The shame they feel is immeasurable!"
|
||||
end
|
||||
else
|
||||
result = result + "They tied! They begrudgingly back away from each other."
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
11
entities/entity.rb
Normal file
11
entities/entity.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
load "mongo_document_wrapper.rb"
|
||||
|
||||
class Entity < MongoDocumentWrapper
|
||||
def initialize(mc, doc=nil)
|
||||
super(mc, doc)
|
||||
end
|
||||
|
||||
def resolve(target)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
131
entities/monster.rb
Normal file
131
entities/monster.rb
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
class Monster < Entity
|
||||
@@monsterMods = [
|
||||
"Crafty", "Stinky", "Spooky", "Surprisingly Stout", "Shockingly Petite",
|
||||
"Malevolent", "Loud", "Nudist", "Rude", "Aroused", "Depressed",
|
||||
"Seemingly Friendly but Violent", "Lazy", "Ugly", "Cute Lil'", "Impish", "Ancient",
|
||||
"Ambiguously Gendered", "Idiotic", "Sticky", "Angery", "Dusty ol'", "Big",
|
||||
"Mega", "Itty Bitty", "Vibrant Orange", "Yella-Bellied", "Cowardly", "Brave",
|
||||
"Crusty", "Jankety", "Viral", "Blue-ish", "Moldy", "Musty", "Haunted", "Cursed",
|
||||
"Buttery", "Sexy", "Drunken", "Foreign", "Extremely Sharp", "Shifty", "Smrat",
|
||||
"Sharply Dressed", "Irate", "Psychic", "Emphatic", "Unreasonable",
|
||||
"Dumb as Rocks", "Possessed", "High as Hell", "Annoying", "VERY LOUD",
|
||||
"Oddly Erotic", "Confused", "Arrogant", "Undead", "Frustrated", "Transparent",
|
||||
"Thicc", "Holy", "Unholy", "Filthy", "Slimy", "Contagious", "Fartin'", "Eccentric",
|
||||
"Shartin'", "Eccentric", "Moist", "Ecstatic", "Zooming", "Grim (Up North)",
|
||||
"Flatulent", "Nefarious", "Rotten", "Sacred", "Handsome", "Purdy", "Howling",
|
||||
"Weeping", "Real Handsy", "Underachieving", "Playful", "Bubbly", "Offputting",
|
||||
"Unnerving", "Mysterious", "Creeeepy", "Dirty", "Unfunny", "Inverted", "Inside-Out",
|
||||
"Bleak", "Near-Sighted", "Uncooked", "Burnt", "Frosty", "Corpulent", "Winged",
|
||||
"Mastermind", "Lackey", "Scientific", "Tenured", "Illegal", "[redacted]",
|
||||
"Invisible", "Floating", "Oozing", "smol", "Embarrassing", "Cheeky", "Slanderous",
|
||||
"Perverted", "Super-Fast", "Boring", "Educated", "Wary", "Ribbed", "Bumpy",
|
||||
"Smooth", "Cheeked Up", "Insane", "Faaaaast", "Stoned", "Worthless", "Timid",
|
||||
"Voyeuristic", "Watchful", "Crunchy", "Uncouth", "Brazen", "Regretful", "Practically Dead",
|
||||
"Obviously Unhinged", "Volatile", "Problematic", "Wary", "Gifted", "Abstract",
|
||||
"Disgusting", "Amateur", "Expired", "Fading", "Funky", "Bearded", "Feeble", "Frail",
|
||||
"Crude", "Stringy", "El Fuego", "Paper Crown Wearing", "Majestic", "Beastly", "Number 7",
|
||||
"Onanistic", "Stained", "Lucky", "Priapic", "Phallic", "Professional", "Wild", "Feral",
|
||||
"Electric", "Droopy", "Dripping", "Questionable", "Wandering", "Scousey", "Troubled",
|
||||
"Well-Adjusted", "Innocent", "Creepy", "Clown-Like", "Abrasive", "Arrogant", "1337",
|
||||
"Tastefully Nude", "Wet", "All-Powerful", "Scandelous", "Remarkedly Stupid",
|
||||
]
|
||||
|
||||
@@monsterTypes = [
|
||||
"Goblin", "Orc", "Skeleton", "Skelly", "Bob", "Tim", "Witch", "Demon", "Cricket",
|
||||
"Slime", "Ghost", "Gila Monster", "Sentient Paperclip", "Cthlululu", "Imp",
|
||||
"BUG?!", "Influencer", "Duck", "Alium", "Hippie", "Druid", "Bean", "Woof", "Sheep",
|
||||
"Opossum", "Dwarf", "Lizard Fella", "Sailor", "Spy", "Agent", "ChonKee", "Boar",
|
||||
"Squirrel", "Hobo", "Hairball", "Wizard", "Pupper", "Doggo", "Cat", "Mother",
|
||||
"Karen", "Magister", "Thief", "Leaky Glass", "Dead Battery", "Cow",
|
||||
"Disembodied Foot", "Cloud", "Patch of Grass", "Ginger", "Warrior", "Bride",
|
||||
"Badger", "Parrot", "Mummy", "Raider", "Knight", "Paladin", "Necromancer",
|
||||
"Pixie", "Sprite", "Stranger", "College Student", "Child", "Foreigner", "Creep",
|
||||
"Basement Dweller", "Pile of Clothes", "Box of Sand", "Lady", "Dude", "Nerd",
|
||||
"Luggage", "Spooder", "Pirate", "Scientist", "Professor", "Monkey", "Tree", "Bus",
|
||||
"[redacted]", "Moth", "Perv", "Sanic", "Wolverine", "Rock", "Eggplant", "Stoner",
|
||||
"Honeybee", "Wasp", "Gnome", "Tunnel Dweller", "Truck", "Shrimp Appetizer Platter",
|
||||
"Marine", "Pilot", "Faceless Beard", "Pork Slab", "Denizen", "Archer", "Weirdo Next Door",
|
||||
"Can of Diet Sprite", "Ferret", "Guttersnipe", "Elf", "Horror", "Terror", "Wanderer",
|
||||
"Person Who Works in the Cubicle Next to You", "Bunny Rabbit", "Hamster", "Degu",
|
||||
"Metalhead", "Baking-Soda Volcano", "Canadian", "Moon", "Jazz Musician", "Robot",
|
||||
"AI Program", "Flat Earther", "Entrepreneur", "Social Media Platform", "Man?", "Beast",
|
||||
"American", "Brit", "Hippo", "7", "B-List Celebrity", "Bear", "Childs Drawing",
|
||||
"Anime Character", "Merperson", "Salesperson", "Skellington", "Scallies", "Clown Puppet",
|
||||
"Clown", "Puppet", "n00b", "Spider Shaped Man", "Bat Shaped Man", "Armadillo", "Unshucked Ear of Corn",
|
||||
"Dustmite", "Single Follicle of Hair", "Optimal Pride",
|
||||
]
|
||||
|
||||
@@encounter = [
|
||||
"ran into", "encountered", "crossed paths with", "slammed into", "almost got stepped on by",
|
||||
"crossed paths with", "almost got eaten by", "got into fisticuffs with", "failed to hide from",
|
||||
"hunted down", "picked a fight with", "got caught sleeping by", "drunkenly bumped into",
|
||||
"got bored and starting puching at", "attempted to poach", "tried to collect a trophy from",
|
||||
"got jealous of and attacked", "got lost then found and got punchy with", "had beef to settle with",
|
||||
"was inappropriately touched by", "had a misunderstanding with",
|
||||
"was frustrated and confused by and started fighting",
|
||||
]
|
||||
|
||||
@@getWin = [
|
||||
"is brutally slaughtered", "straight up dies", "explodes into a million tiny pieces", "has been murdered",
|
||||
"collapses into a pile of tears before slowly dying", "should probably be buried soon", "DESTROYED!!!",
|
||||
"is beaten to a bloody pulp", "is permamently damaged", "wonders where things went so wrong and flees",
|
||||
"dies from embarrassment", "ineffectively begs for forgiveness", "was exsanguinated",
|
||||
]
|
||||
|
||||
@@getLoss = [
|
||||
"mysteriously disappears", "vanishes in a puff of smoke", "spits at your feet and flips you the bird",
|
||||
"returns to the dimension from whence they came", "saunters off happily", "gets bored of winning and leaves",
|
||||
"somehow managed to not completely murder you", "runs away cackling", "is quite embarrassed for you",
|
||||
"bows, then turns to walk away",
|
||||
]
|
||||
|
||||
def get_default_doc()
|
||||
return {
|
||||
'type' => :monster,
|
||||
'spawned_by' => nil,
|
||||
'location' => nil,
|
||||
'exp' => nil,
|
||||
'line' => "",
|
||||
'name' => @@monsterMods.sample + " " + @@monsterTypes.sample
|
||||
}
|
||||
end
|
||||
|
||||
def resolve(p)
|
||||
max_xp_gain = self.get('exp')
|
||||
max_player_strength = p.get('last_line').length
|
||||
|
||||
name = self.get("name")
|
||||
|
||||
article = "a"
|
||||
|
||||
if ['A','E','I','O','U', 'a','e','i','o','u'].include?(self.get('name')[0])
|
||||
article = "an"
|
||||
end
|
||||
|
||||
player_attack = 1+rand(max_player_strength)
|
||||
foe_attack = 1+rand(self.get('exp'))
|
||||
|
||||
result = p.get('name') + "[" + max_player_strength.to_s + "str] "
|
||||
|
||||
result = result + @@encounter.sample + " " + article
|
||||
|
||||
result = result + " " + name
|
||||
result = result + "[" + max_xp_gain.to_s + "str]" + "! "
|
||||
result = result + "[" + player_attack.to_s + "dmg vs " + foe_attack.to_s + "dmg] "
|
||||
|
||||
if player_attack > foe_attack then
|
||||
xp_gain = 1 + rand(max_xp_gain)
|
||||
|
||||
result = result + "The " + name + " " + @@getWin.sample + "! "
|
||||
result = result + p.get("name") + " wins and earns " + xp_gain.to_s + "xp! "
|
||||
|
||||
p.gain_exp( xp_gain)
|
||||
elsif player_attack < foe_attack then
|
||||
result = result + "The " + self.get("name") + " wins and " + @@getLoss.sample + "! "
|
||||
else
|
||||
result = result + "They tied! They shake hands and agree to disagree. "
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
76
entities/player.rb
Normal file
76
entities/player.rb
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
class Player < Entity
|
||||
def initialize(mc, doc=nil)
|
||||
super(mc, doc)
|
||||
end
|
||||
|
||||
def get_default_doc()
|
||||
q = {
|
||||
'type' => :player,
|
||||
'name' => nil,
|
||||
'location' => nil,
|
||||
'exp' => 0,
|
||||
'last_line' => nil
|
||||
}
|
||||
|
||||
return q
|
||||
end
|
||||
|
||||
def gain_exp(amount)
|
||||
self.set_exp(self.get('exp') + amount)
|
||||
end
|
||||
|
||||
# be careful with this one. very rare use case when you want
|
||||
# to use this directly from a bot or playground
|
||||
def set_exp(amount)
|
||||
self.set({'exp' => amount})
|
||||
end
|
||||
|
||||
# yeah this needs a WHOLE LOT of cleanup and rethinking....
|
||||
def resolve(foe)
|
||||
result = nil
|
||||
|
||||
# call the resolve method for anything that's not a player.
|
||||
if foe.get('type') != :player then
|
||||
result = foe.resolve(self)
|
||||
|
||||
# Handle player v player here.... can't exactly recall resolve without
|
||||
# recursing forever
|
||||
# most of this should probably be somehow abstracted into Entity...
|
||||
# I'm ok with this for now.
|
||||
else
|
||||
max_player_attack = self.get('exp')
|
||||
max_foe_attack = foe.get('exp')
|
||||
|
||||
player_str = self.get('name')
|
||||
player_str = player_str + "[" + max_player_attack.to_s + "str] "
|
||||
|
||||
result = player_str + "felt the need to fight "
|
||||
|
||||
result = result + foe.get('name')
|
||||
result = result + "[" + max_foe_attack.to_s + "str]" + "! "
|
||||
|
||||
player_attack = 1+rand(max_player_attack)
|
||||
foe_attack = 1+rand(foe.get('exp'))
|
||||
|
||||
result = result + "[" + player_attack.to_s + "dmg vs " + foe_attack.to_s + "dmg]! "
|
||||
|
||||
if player_attack > foe_attack then
|
||||
# Max of 25% of foe exp, minimum of 1. Cannot pass a 0 into rand without
|
||||
# getting a float, so this is a bit cludgy. if rand gets a 1 it always returns
|
||||
# 0 so the floor is effectively 1 :/
|
||||
max_xp_gain = (foe.get('exp').to_f * 0.25).to_i + 1
|
||||
xp = 1 + rand(max_xp_gain)
|
||||
|
||||
result = result + foe.get('name') + " lost! "
|
||||
result = result + self.get('name') + " wins and earns " + xp.to_s + "xp!"
|
||||
gain_exp(xp)
|
||||
elsif player_attack < foe_attack then
|
||||
result = result + foe.get("name") + " wins and saunters away"
|
||||
else
|
||||
result = result + "They tied! They shake hands and agree to disagree and part ways."
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
61
entities/random_event.rb
Normal file
61
entities/random_event.rb
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
class RandomEvent < Entity
|
||||
@@eventTypes = [
|
||||
"ate a real solid kebab", "discovered the secret of magnets", "managed to do almost seven whole pushups in a row",
|
||||
"found a giant cache of fresh beans", "got help from a particularly friendly woodling sprite",
|
||||
"received a kiss from a travelling prince. Or princess. They weren't exactly sure but it felt great",
|
||||
"somehow managed to wake up rested", "finished a Rubix cube without swapping any of the stickers this time",
|
||||
"made a bet with an impish gnome and won", "arm wrestled an ogre and won", "discovered a way to impersonate Guy Fieri",
|
||||
"found an altar adorned with skulls but it turned out that the god being worshiped was just misunderstood and was actually pretty chill",
|
||||
"paid for insurance at the blackjack table and it actually worked", "boiled a pot of water without screwing it up",
|
||||
"finally replied to that text they got from a friend like a week ago but kept putting off responding for no good reason",
|
||||
"made friends with a tree", "got invited to sit at the cool kids table", "found some dusty sacred texts",
|
||||
"chose to be a better person", "digs up dirt on their political opponents", "was gifted a jar of honey from The True Queen Bee",
|
||||
"changed a flat tire for a weary traveller", "won at a game of poker with a tribe of wandering mages",
|
||||
"didn't die, not even a little", "accidentally solved world hunger, at least for a few minutes",
|
||||
"felt at one with the universe before realizing it was just a bit of indigestion. But still, it felt pretty good",
|
||||
"took a big refreshing gulp of ocean water", "replaced the batteries in the smoke detector",
|
||||
"passed the lie detector test (somehow)", "was found innocent on all charges", "brushed their teeth and took a shower",
|
||||
"stood up to the schoolyard bully", "found a penny. Not a particularly lucky one but hey, it's better than nothing",
|
||||
"finally remembered the name of that song that they had half stuck in their head for the past several days",
|
||||
"discovered music", "found the right cable from that big box of cables they keep saved in that one closet for some reason",
|
||||
"artfully evaded a swarm of angry ducks", "fell into a hole but found a big ol' pile of treasure at the bottom",
|
||||
"overheard a joke a friend said but no one else in the group did, repeated it and got good big laughs in return",
|
||||
"found their way out of The Endless Wood", "found a scratch-off lottery ticket and won a couple bucks",
|
||||
"got a haircut", "felt a fleeting moment of happiness", "went to bed early", "comforted a grieving child",
|
||||
"deleted those dozen apps from their phone that they hadn't used in years", "planned a party that people actually showed up for",
|
||||
"caught a lucky fish that whispered eldritch secrets to them", "raised awareness for The Cause", "helped a friend move",
|
||||
"didn't burn down the house", "crafted a not-haunted puppet", "saw their childhood imaginary friend",
|
||||
"discovered a cure for sneezing", "saved the world but it wasn't THAT big of a deal", "donated money to charity",
|
||||
"regretted previous decisions and made amends", "educated the ignorant", "cut loose on the dance floor",
|
||||
"filed the appropriate paperwork to prevent The Great Disintegration just in time", "made a new friend",
|
||||
"finished that TV series their friend recommended a good few months back", "took a hot bath", "won the game",
|
||||
"cracked the code", "found a sheep stuck on its side, and after righting it found a super small secret wishing well",
|
||||
"raked some leaves for the elderly couple next door", "kissed a toad, hallucinated",
|
||||
"saved up the pennies over the years and can now afford that downpayment", "lost a foot but found a fresh new one",
|
||||
"ran into a crowd, who then started chanting and calling them Muad'Dib",
|
||||
]
|
||||
|
||||
def get_default_doc()
|
||||
q = {
|
||||
'type' => :random_event,
|
||||
'location' => nil,
|
||||
'name' => @@eventTypes.sample
|
||||
}
|
||||
|
||||
return q
|
||||
end
|
||||
|
||||
def resolve(p)
|
||||
exp = p.get('exp')
|
||||
|
||||
max_xp_gain = ((exp.to_f * (0.10)).to_i)+1
|
||||
actual_xp_gain = rand(max_xp_gain)+1
|
||||
|
||||
result = p.get('name') + "[" + exp.to_s + "xp] " + self.get('name') + "!"
|
||||
result = result + " They gained " + actual_xp_gain.to_s + "xp!"
|
||||
|
||||
p.gain_exp(actual_xp_gain)
|
||||
|
||||
return result
|
||||
end
|
||||
end
|
||||
50
entity_factory.rb
Normal file
50
entity_factory.rb
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
load "entities/entity.rb"
|
||||
load "entities/player.rb"
|
||||
load "entities/monster.rb"
|
||||
load "entities/boss.rb"
|
||||
load "entities/random_event.rb"
|
||||
|
||||
class EntityFactory
|
||||
@mc = nil
|
||||
|
||||
def initialize(mc)
|
||||
@mc = mc
|
||||
end
|
||||
|
||||
# Convert the symbol into a class. There might be a way to automate this better...
|
||||
# Make sure to load the class if you're adding a new one here.
|
||||
def get_ent_class(type)
|
||||
ent_class = nil
|
||||
|
||||
case type
|
||||
when :player
|
||||
ent_class = Player
|
||||
when :monster
|
||||
ent_class = Monster
|
||||
when :boss
|
||||
ent_class = Boss
|
||||
when :random_event
|
||||
ent_class = RandomEvent
|
||||
end
|
||||
|
||||
return ent_class
|
||||
end
|
||||
|
||||
# get a new entity if doc is nil, otherwise load from that doc
|
||||
def get(type, doc=nil)
|
||||
return get_ent_class(type).new(@mc, doc)
|
||||
end
|
||||
|
||||
# try to load an object instance of an entity based on the doc
|
||||
def build_instance(doc)
|
||||
if doc['type'] != nil then
|
||||
return get_ent_class(doc['type']).new(@mc, doc)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def run_query(filter={})
|
||||
return @mc.collection().find(filter)
|
||||
end
|
||||
end
|
||||
23
mongo_connect.rb
Normal file
23
mongo_connect.rb
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#require 'rubygems' # not necessary for Ruby 1.9
|
||||
require 'mongo'
|
||||
|
||||
Mongo::Logger.logger.level = ::Logger::FATAL
|
||||
|
||||
include Mongo
|
||||
|
||||
class MongoConnect
|
||||
def initialize(dbname, collname)
|
||||
@db = Mongo::Client.new(
|
||||
["127.0.0.1:27017"],
|
||||
:database => dbname)
|
||||
@coll = @db[collname.to_sym]
|
||||
end
|
||||
|
||||
def db()
|
||||
return @db
|
||||
end
|
||||
|
||||
def collection()
|
||||
return @coll
|
||||
end
|
||||
end
|
||||
77
mongo_document_wrapper.rb
Normal file
77
mongo_document_wrapper.rb
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
class MongoDocumentWrapper
|
||||
@mc = nil # MongoConnect instance
|
||||
@doc = nil # MongoDocument instance....
|
||||
@id = nil # BSON ID for the Doc
|
||||
|
||||
def initialize(mc, doc=nil)
|
||||
@mc = mc
|
||||
|
||||
if doc == nil then
|
||||
create()
|
||||
else
|
||||
@id = doc['_id']
|
||||
@doc = doc
|
||||
end
|
||||
end
|
||||
|
||||
def create()
|
||||
@id = BSON::ObjectId.new()
|
||||
|
||||
doc = get_default_doc()
|
||||
doc['_id'] = @id
|
||||
|
||||
@doc = doc
|
||||
|
||||
@mc.collection.insert_one(@doc)
|
||||
end
|
||||
|
||||
def load()
|
||||
@doc = @mc.collection().find({"_id" => @id}).first()
|
||||
end
|
||||
|
||||
# save and grab the ID and doc....
|
||||
def set(params={}, persist=true)
|
||||
@doc.merge!(params)
|
||||
|
||||
if persist == true then
|
||||
persist()
|
||||
end
|
||||
end
|
||||
|
||||
def get(field)
|
||||
return @doc[field]
|
||||
end
|
||||
|
||||
def persist()
|
||||
@mc.collection().update_one({"_id" => @id}, @doc)
|
||||
end
|
||||
|
||||
def delete()
|
||||
if @id == nil then
|
||||
die
|
||||
end
|
||||
|
||||
@mc.collection().delete_one({"_id" => @id})
|
||||
end
|
||||
|
||||
def update(query)
|
||||
@mc.collection().update_one({"_id" => @id}, query)
|
||||
end
|
||||
|
||||
def get_default_doc()
|
||||
puts "Override this in ent class"
|
||||
return {}
|
||||
end
|
||||
|
||||
def self.build_from(mc, doc=nil)
|
||||
if doc == nil then
|
||||
puts "wtf whoops??"
|
||||
else
|
||||
@mc = mc
|
||||
@doc = doc
|
||||
@id = @doc['_id']
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
||||
167
rpg_bets.rb
Normal file
167
rpg_bets.rb
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# I am not happy with most of this.
|
||||
|
||||
class RpgBets < MongoDocumentWrapper
|
||||
@bets = []
|
||||
|
||||
def initialize(mc)
|
||||
doc = mc.collection().find({"type" => :bets}).first
|
||||
|
||||
if doc == nil then
|
||||
@mc = mc
|
||||
self.create()
|
||||
else
|
||||
super(mc, doc)
|
||||
end
|
||||
|
||||
@bets = self.get("bets")
|
||||
end
|
||||
|
||||
# This needs so much cleanup
|
||||
# Call with 2 player names and an amount. Returns a string with the interaction output
|
||||
def place_bet(player, target, amount)
|
||||
# NO SELF BETS!
|
||||
if player == target then
|
||||
return "No self bets " + player + "!"
|
||||
end
|
||||
|
||||
# so this happened in the sim...
|
||||
if amount == 0 then
|
||||
return "Who bets 0?"
|
||||
end
|
||||
|
||||
possible_player = @mc.collection().find({"type" => :player, "name" => player}).first
|
||||
# This should never really happen, but just in case...
|
||||
if possible_player == nil then
|
||||
return "Who the heck are YOU " + player + "??"
|
||||
end
|
||||
|
||||
# Check to see if the target even exists...
|
||||
possible_target = @mc.collection().find({"type" => :player, "name" => target}).first
|
||||
|
||||
if possible_target == nil then
|
||||
return "Who the heck is " + target + "?"
|
||||
end
|
||||
|
||||
# if we get here we know we have both a valid player and target
|
||||
p = Player.new(@mc, possible_player)
|
||||
t = Player.new(@mc, possible_target)
|
||||
|
||||
# Make sure betting/calling player has enough xp to place the bet...
|
||||
if p.get("exp") < amount then
|
||||
return "Sorry " + p.get("name") + " but you only have " + p.get("exp").to_s + "xp to bet with!"
|
||||
end
|
||||
|
||||
bet = get_bet(p.get('name'), t.get('name'), amount)
|
||||
|
||||
response = ""
|
||||
|
||||
# Check the exp on the bet and see if the new amount is greater.
|
||||
# If greater, if it's from the same player who already owns the most
|
||||
# recent bet, do nothing. Otherwise, replace the old exp with the new one
|
||||
# and replace the last bet player with the current.
|
||||
if amount > bet['exp'] then
|
||||
if bet['last_bet'] == p.get('name') then
|
||||
response = "You already have the highest bet of " + bet['exp'].to_s + "xp!"
|
||||
else
|
||||
bet['exp'] = amount
|
||||
bet['last_bet'] = player
|
||||
response = player + " upped the ante to " + amount.to_s + "xp against " + target + "!"
|
||||
end
|
||||
# If amount is less than the current bet, don't return immediately but spit out
|
||||
# a message about how it's not enough
|
||||
elsif amount < bet['exp'] then
|
||||
response = player + " be real, yo. Current bet with " + target + " is at " + t.get('exp').to_s + "xp. "
|
||||
response = response + "Match to fight, or overbid them."
|
||||
# fight? This should prolly be refactored into some function.... it gets busy...
|
||||
else
|
||||
if bet['last_bet'] == player then
|
||||
response = "You have the highest bet already against " + target + " for "
|
||||
response = response + bet['exp'].to_s + "xp! They need to call you on it."
|
||||
else
|
||||
# this whole block needs cleaning. It's gross atm.
|
||||
p_attack = 1 + rand(amount)
|
||||
t_attack = 1 + rand(amount)
|
||||
|
||||
response = player + " and " + target + " fight over " + amount.to_s + "xp! "
|
||||
response = response + "[" + p_attack.to_s + "dmg vs " + t_attack.to_s + "dmg]! "
|
||||
|
||||
winner = loser = nil
|
||||
|
||||
if p_attack > t_attack then
|
||||
winner = p
|
||||
loser = t
|
||||
elsif t_attack > p_attack then
|
||||
winner = t
|
||||
loser = p
|
||||
# If it's a tie, persist the bet back down with no changes and return
|
||||
else
|
||||
@bets.push(bet)
|
||||
self.set({"bets" => @bets})
|
||||
response = "They tied! The crowd goes wild in anticipation! The bet remains unresolved!"
|
||||
return response
|
||||
end
|
||||
|
||||
response = response + winner.get("name") + " wins! They won " + amount.to_s + "xp "
|
||||
response = response + "from " + loser.get("name") + ", who respectfully hands it over! "
|
||||
|
||||
# update the players...
|
||||
winner.gain_exp(amount)
|
||||
loser.gain_exp(-amount)
|
||||
|
||||
if loser.get("exp") <= 0 then
|
||||
response = response + "Holy wow! " + loser.get("name") + " went negative! "
|
||||
response = response + "The Powers That Be resets them to 1xp!"
|
||||
loser.set_exp(1)
|
||||
puts response
|
||||
die
|
||||
end
|
||||
|
||||
return response
|
||||
end
|
||||
end
|
||||
|
||||
@bets.push(bet)
|
||||
self.set({"bets" => @bets})
|
||||
|
||||
return response
|
||||
end
|
||||
|
||||
def get_player_bets(player)
|
||||
found_bets = []
|
||||
|
||||
@bets.each do |b|
|
||||
if b['players'].include?(player) then
|
||||
found_bets.push(b)
|
||||
end
|
||||
end
|
||||
|
||||
return found_bets
|
||||
end
|
||||
|
||||
def get_bet(player, target, amount)
|
||||
found_bet = nil
|
||||
|
||||
@bets.each do |b|
|
||||
if b["players"].include?(player) and b["players"].include?(target) then
|
||||
found_bet = b
|
||||
end
|
||||
end
|
||||
|
||||
# This feels cludgy but deleting an element from inside an iterator (the .each above)
|
||||
# is apparently straight up disallowed in ruby. so need to nuke it here. It will either
|
||||
# resolve and disappear in the place_bet method or be updated and re-inserted there
|
||||
if found_bet != nil then
|
||||
@bets.delete_if{ |b| b["players"].include?(player) and b["players"].include?(target) }
|
||||
return found_bet
|
||||
end
|
||||
|
||||
return {"players" => [player, target], "last_bet" => player, "exp" => amount}
|
||||
end
|
||||
|
||||
def get_default_doc()
|
||||
return {
|
||||
"type" => :bets,
|
||||
"bets" => [],
|
||||
}
|
||||
end
|
||||
end
|
||||
67
rpg_grid.rb
Normal file
67
rpg_grid.rb
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
class RpgGrid
|
||||
@mc = nil
|
||||
@gridSize = nil
|
||||
|
||||
# need the @mc to query occupied locations.
|
||||
def initialize(mc, grid_size=25)
|
||||
@mc = mc
|
||||
@gridSize = grid_size
|
||||
end
|
||||
|
||||
# Finds a place to put either a player or a monster that isn't currently occupied
|
||||
# Players need to spawn in a non-player cell, monsters can replace an existing monster
|
||||
def find_location()
|
||||
loop do
|
||||
x = rand(@gridSize)
|
||||
y = rand(@gridSize)
|
||||
|
||||
loc = [x, y]
|
||||
|
||||
n = @mc.collection().find({'location' => [x, y]})
|
||||
if n.count == 0 then
|
||||
return loc
|
||||
elsif n.first["type"] == :monster then
|
||||
@mc.collection().delete_one({"_id" => n.first["_id"]})
|
||||
return loc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Move the +/- 1 on the x/y with them "bumping" off the walls to find a new position.
|
||||
# Gotta keep em in the grid.
|
||||
def get_move_location(cur_loc=nil)
|
||||
if cur_loc == nil then
|
||||
cur_loc = [0, 0]
|
||||
end
|
||||
|
||||
# get the x/y differences
|
||||
dx = get_move_diff(cur_loc[0])
|
||||
dy = get_move_diff(cur_loc[1])
|
||||
|
||||
# Build a new [x,y] to save to location
|
||||
new_loc = [cur_loc[0] + dx, cur_loc[1] + dy]
|
||||
|
||||
return new_loc
|
||||
end
|
||||
|
||||
# Should keep all chars inside the @gridSize playfield though without getting locked on an edge
|
||||
def get_move_diff(cur_loc)
|
||||
# i should be a num between 0 and 2. If 0 == 0, 1 == 1, 2 == -1. Intuitive right?
|
||||
i = rand(3)
|
||||
d = 0
|
||||
|
||||
if i == 2 then
|
||||
d = -1
|
||||
else
|
||||
d = i
|
||||
end
|
||||
|
||||
if cur_loc == 0 and d == -1 then
|
||||
d = rand(2)
|
||||
elsif cur_loc == @gridSize - 1 and d == 1 then
|
||||
d = rand(2) - 1
|
||||
end
|
||||
|
||||
return d
|
||||
end
|
||||
end
|
||||
127
rpgqui.rb
Normal file
127
rpgqui.rb
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
require 'cinch'
|
||||
|
||||
load "active_rpg.rb"
|
||||
|
||||
def fix_nick(n)
|
||||
return n[0] + "\uFEFF" + n[1,n.length]
|
||||
end
|
||||
|
||||
# Clean up all nicks in the responses
|
||||
def fix_nicks(response, users)
|
||||
fixed_response = response
|
||||
|
||||
users.keys.each do |u|
|
||||
split_response = fixed_response.split(u.nick)
|
||||
fixed_response = split_response.join(fix_nick(u.nick))
|
||||
end
|
||||
|
||||
return fixed_response
|
||||
end
|
||||
|
||||
bot = Cinch::Bot.new do
|
||||
# Set up the data store here...
|
||||
$w = ActiveRpg.new(25, 'libera-rpg_new')
|
||||
|
||||
$output_channel = "#active_rpg"
|
||||
|
||||
$intro_message = "Hi! I'm a bot that runs a passively active RPG game. Please join " +
|
||||
$output_channel + " to track progress"
|
||||
|
||||
configure do |c|
|
||||
c.server = "irc.libera.chat"
|
||||
c.user = "Monqui"
|
||||
c.password = "tbmsn"
|
||||
c.nick = "rpgqui"
|
||||
c.delay_joins = 15
|
||||
c.channels = ["#bakedbeans", "#sconesandcream fatjoints", $output_channel]
|
||||
c.timeouts.connect = 30
|
||||
end
|
||||
|
||||
on :join do |m|
|
||||
if m.channel != $output_channel then
|
||||
m.reply $intro_message + ", or say '!help' for a list of commands!"
|
||||
end
|
||||
end
|
||||
|
||||
on :message, ".bots" do |m|
|
||||
m.reply "rEpOrtInG iN! [ruby] Lmao!"
|
||||
end
|
||||
|
||||
on :message, /^(.*)$/ do |m, line|
|
||||
synchronize(:rpg) do
|
||||
if line[0] != "!" then
|
||||
res = $w.take_turn(m.user.nick, line)
|
||||
if res != "" and res != nil then
|
||||
fixed_response = fix_nicks(res, m.channel.users)
|
||||
self.bot.channel_list.find($output_channel).send(fixed_response)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
on :message, /^!help$/ do |m|
|
||||
response = $intro_message
|
||||
response = response + ", or use the following commands to get more info!\n"
|
||||
response = response + "!rpg - personal user stats; !critters - list entities in the world; "
|
||||
response = response + "!leaderboard - ugly printout of all user stats; "
|
||||
response = response + "!rpgbet - bet against another user for xp! "
|
||||
response = response + "(\"!rpgbet [target_player] [amount]\")"
|
||||
m.reply response
|
||||
end
|
||||
|
||||
on :message, /^!rpg$/ do |m|
|
||||
synchronize(:rpg) do
|
||||
mc = $w.get_mc()
|
||||
|
||||
u = mc.collection.find({"type" => :player, "name" => m.user.nick}).first
|
||||
pet = mc.collection.find({"type" => :boss, "spawned_by" => m.user.nick}).first
|
||||
|
||||
out = m.user.nick + " currently has " + u['exp'].to_s + "xp at " + u['location'].inspect + "! "
|
||||
|
||||
if pet != nil then
|
||||
out = out + "Their pet, the " + pet["name"] + " is chilling out at " + pet['location'].inspect + " "
|
||||
out = out + "with " + pet["exp"].to_s + " points of power!"
|
||||
end
|
||||
|
||||
m.reply out
|
||||
end
|
||||
end
|
||||
|
||||
on :message, /^!critters$/ do |m|
|
||||
synchronize(:rpg) do
|
||||
mc = $w.get_mc()
|
||||
out = "Critters crittering around: " + mc.collection().find({"type" => :monster}).count.to_s
|
||||
out = out + "\n"
|
||||
out = out + "Bosses bossing around: " + mc.collection().find({"type" => :boss}).count.to_s
|
||||
out = out + "\n"
|
||||
out = out + "Events eventing around: " + mc.collection().find({"type" => :random_event}).count.to_s
|
||||
m.reply out
|
||||
end
|
||||
end
|
||||
|
||||
on :message, /^!leaderboard$/ do |m|
|
||||
synchronize(:rpg) do
|
||||
mc = $w.get_mc()
|
||||
users = mc.collection.find({"type" => "player"})
|
||||
|
||||
sorted = users.to_a.sort_by{|i| i['exp']}
|
||||
sorted.reverse!
|
||||
|
||||
out_str = ""
|
||||
|
||||
sorted.each do |i|
|
||||
out_str = out_str + fix_nick(i['name']) + i['location'].inspect + ": " + i['exp'].to_s + '; '
|
||||
end
|
||||
|
||||
m.reply(out_str)
|
||||
end
|
||||
end
|
||||
|
||||
on :message, /^!rpgbet (\S*) (\d*)$/ do |m, target, amount|
|
||||
bets = $w.get_bets()
|
||||
# m.reply m.user.nick + " wants to post up a bet of " + amount.to_s + " against " + target
|
||||
m.reply bets.place_bet(m.user.nick, target, amount.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
bot.start
|
||||
121
testground.rb
Normal file
121
testground.rb
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
# This is a very bodged together wrapper that lets you spin up an
|
||||
# instance of ActiveRpg in its own little sandbox. Randomly generates
|
||||
# lots of potential turns/players/monsters/bets/whatevers
|
||||
|
||||
load "active_rpg.rb"
|
||||
|
||||
#configgy bits
|
||||
collection_name = "testground"
|
||||
grid_size = 25
|
||||
player_num = 20
|
||||
turns = 1000
|
||||
max_damage = 100
|
||||
|
||||
$ar = nil # ActigeRpg instance
|
||||
$bets = nil
|
||||
|
||||
# call this if you want to drop all of the DB.
|
||||
def reset_all()
|
||||
$ar.get_mc().collection.drop()
|
||||
$ar.get_mc().collection().indexes.create_one(_id: 1)
|
||||
end
|
||||
|
||||
# generates a line of given length.
|
||||
def get_line(len)
|
||||
line = Array.new(1+rand(len), ".").join
|
||||
end
|
||||
|
||||
# I want to find a way to make it a bit more dynamic in
|
||||
# adding bets here.... More variations
|
||||
def place_bet(player, target)
|
||||
chance = rand(1000)
|
||||
|
||||
if chance <= 2 then
|
||||
amount = 1+rand(10)
|
||||
puts $bets.place_bet(player, target, amount)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# start of simulator code
|
||||
|
||||
puts "Starting run in collection " + collection_name + ", " + grid_size.to_s + " grid."
|
||||
puts player_num.to_s + " players, " + turns.to_s + " turns, " + max_damage.to_s + " max damage."
|
||||
|
||||
puts "Creating ActiveRpg"
|
||||
$ar = ActiveRpg.new(grid_size, collection_name)
|
||||
|
||||
puts "Grabbing bets..."
|
||||
$bets = $ar.get_bets()
|
||||
|
||||
puts "Dropping and building index on the collection"
|
||||
reset_all()
|
||||
|
||||
players = []
|
||||
|
||||
puts "Creating players..."
|
||||
for x in 1..player_num do
|
||||
# this should be the basis of aw.take_turn()...
|
||||
players.push(name = (0...8).map { (65 + rand(26)).chr }.join)
|
||||
end
|
||||
|
||||
puts players.inspect
|
||||
|
||||
puts "Starting turns..."
|
||||
for t in 1..turns do
|
||||
players.each do |p|
|
||||
res = $ar.take_turn(p, get_line(max_damage))
|
||||
if res.to_s != "" then
|
||||
puts res
|
||||
end
|
||||
|
||||
place_bet(p, players.sample)
|
||||
end
|
||||
end
|
||||
|
||||
# end of simluation code. Below prints out a summary of it.
|
||||
|
||||
puts "FINISHED!\n\n"
|
||||
print "SUMMARY for " + collection_name + ", grid=" + grid_size.to_s + ". "
|
||||
print player_num.to_s + " players, " + turns.to_s + " turns, " + max_damage.to_s + " max damage!"
|
||||
puts
|
||||
|
||||
final_players = $ar.get_mc().collection().find({"type" => :player})
|
||||
puts "Players: " + final_players.count.to_s
|
||||
final_players.each do |p|
|
||||
puts p['name'] + ": " + p['location'].inspect + "; " + p['exp'].to_s + "xp; last_line: " + p['last_line']
|
||||
end
|
||||
|
||||
puts
|
||||
|
||||
final_monsters = $ar.get_mc().collection().find({"type" => :monster})
|
||||
puts "Monsters: " + final_monsters.count.to_s
|
||||
|
||||
puts
|
||||
|
||||
final_bosses = $ar.get_mc().collection().find({"type" => :boss})
|
||||
puts "Bosses: " + final_bosses.count.to_s
|
||||
final_bosses.each do |b|
|
||||
puts b['name'] + ": " + b['location'].inspect + "; " + b['exp'].to_s + "xp; " + b['last_line'] + "; " + b['spawned_by']
|
||||
end
|
||||
|
||||
puts
|
||||
|
||||
final_events = $ar.get_mc().collection().find({"type" => :random_event})
|
||||
puts "Events: " + final_events.count.to_s
|
||||
final_events.each do |e|
|
||||
puts e['name'] + ": " + e['location'].inspect
|
||||
end
|
||||
|
||||
puts
|
||||
open_bets = 0
|
||||
raw_bets = []
|
||||
|
||||
final_players.each do |p|
|
||||
player_bets = $bets.get_player_bets(p['name'])
|
||||
open_bets = open_bets + player_bets.count
|
||||
raw_bets.push(player_bets)
|
||||
end
|
||||
|
||||
puts raw_bets.inspect
|
||||
puts "Open bets: " + open_bets.to_s
|
||||
Loading…
Add table
Add a link
Reference in a new issue