were_wolf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2bddf36a281f5189a36ae1c65dede53c43f567de
4
+ data.tar.gz: d0dae2add604f028fd24ef2fe791a677588f848f
5
+ SHA512:
6
+ metadata.gz: 6c2a9ef75b7441395bdb853dd2c3053bf125cb34fcc783ab8801b4844e5723ce9dbf97e60e5cf8e01cd86aefee9f43c03f6b0daaae2ed14edab63ce08144c4d3
7
+ data.tar.gz: cb47b1a687f2ebc9c06dff229f33ad5411bcbacda845f753449143d00ee19754b2c7cd400a28b103112e13bb69357b18ca2091f66c32dd0799356b6c4b038137
data/.gitignore ADDED
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ # Gemfile.lock
31
+ # .ruby-version
32
+ # .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in were_wolf.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 CodeAstra
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.
22
+
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # WereWolf
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/were_wolf`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'were_wolf'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install were_wolf
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/CodeAstra/were_wolf.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "were_wolf"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,102 @@
1
+ require_relative 'player/player_collection'
2
+
3
+ # game = Game.new(3, 9)
4
+ # game.simulate
5
+ class Game
6
+ DRAW = 0
7
+ WOLF = 1
8
+ VILLAGER = 2
9
+
10
+ def initialize(no_of_wolves, no_of_villagers)
11
+ @players = PlayerCollection.new(no_of_wolves, no_of_villagers)
12
+ end
13
+
14
+ def run
15
+ until over?
16
+ night_mode
17
+ day_mode unless over?
18
+ end
19
+
20
+ return DRAW if @draw
21
+
22
+ return villagers_alive.empty? ? WOLF : VILLAGER
23
+ end
24
+
25
+ private
26
+ def over?
27
+ villagers_alive.empty? || wolves_alive.empty?
28
+ end
29
+
30
+ def night_mode
31
+ # Cop identifies a person
32
+ cop = @players.cop
33
+ cop.identify_a_player(@players) if cop
34
+ # Doctor chooses to save a person
35
+ doctor = @players.doctor
36
+ saved_person = doctor.choose_a_player_to_save(@players)
37
+ # Wolves kill a villager
38
+ wolves_victim = villagers_alive.sample
39
+ # Rogue kills a players once in the entire game
40
+ rogue = @players.rogue
41
+ rogues_victim = rogue.choose_victim(@players) if rogue
42
+
43
+ # Don't kill the person if the doctor saved the person
44
+ @players.kill(wolves_victim) unless wolves_victim == saved_person
45
+ # Don't kill the person again, if the wolves have already killed the person
46
+ @players.kill(rogues_victim) unless (rogues_victim == saved_person) || (rogues_victim == wolves_victim)
47
+ end
48
+
49
+ def day_mode
50
+ victim = run_voting
51
+ if victim == DRAW
52
+ @draw = true
53
+ else
54
+ @players.kill(victim)
55
+ end
56
+ end
57
+
58
+ def run_voting
59
+ if (villagers_count == 1 && wolves_count == 1)
60
+ return DRAW
61
+ end
62
+
63
+ votes = Hash.new(0)
64
+
65
+ players_alive.each do |player|
66
+ accused = player.accuse(@players)
67
+ votes[accused] += 1
68
+ end
69
+
70
+ max_votes = votes.values.max
71
+ winners = []
72
+ votes.keys.each do |player|
73
+ winners.push(player) if votes[player] == max_votes
74
+ end
75
+
76
+ if winners.count == 1
77
+ return winners.first
78
+ else
79
+ return run_voting
80
+ end
81
+ end
82
+
83
+ def villagers_alive
84
+ @players.alive_villagers
85
+ end
86
+
87
+ def villagers_count
88
+ villagers_alive.count
89
+ end
90
+
91
+ def wolves_alive
92
+ @players.alive_wolves
93
+ end
94
+
95
+ def wolves_count
96
+ wolves_alive.count
97
+ end
98
+
99
+ def players_alive
100
+ @players.alive_players
101
+ end
102
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'game'
2
+
3
+ class GameSimulator
4
+ def initialize(no_of_wolves, no_of_villagers, no_of_runs)
5
+ @no_of_wolves = no_of_wolves
6
+ @no_of_villagers = no_of_villagers
7
+ @no_of_runs = no_of_runs
8
+ end
9
+
10
+ def simulate
11
+ wins = Hash.new(0)
12
+ @no_of_runs.times do
13
+ wins[Game.new(@no_of_wolves, @no_of_villagers).run] += 1
14
+ end
15
+
16
+ return wins
17
+ end
18
+ end
@@ -0,0 +1,48 @@
1
+ require_relative 'game'
2
+ require_relative 'game_simulator'
3
+
4
+ class GameSuggestor
5
+ def initialize(num_of_players, no_of_runs)
6
+ @players_count = num_of_players
7
+ @no_of_runs = no_of_runs
8
+ end
9
+
10
+ def run
11
+ # Preferred Wolves Win Percentage
12
+ pref_wolves_prob = 70
13
+ wolves_count = 1
14
+ absolute_diff = 1000
15
+ best_wins = {}
16
+
17
+ while true
18
+ wins = GameSimulator.new(wolves_count, @players_count - wolves_count, @no_of_runs).simulate
19
+ percent_wolves_win = (100.0*wins[Game::WOLF]/@no_of_runs)
20
+ new_diff = (pref_wolves_prob - percent_wolves_win).abs
21
+ if new_diff < absolute_diff
22
+ absolute_diff = new_diff
23
+ best_wins = wins
24
+ wolves_count += 1
25
+ else
26
+ return result(wolves_count - 1, best_wins)
27
+ end
28
+ end
29
+ end
30
+ private
31
+ def result(wolves_count, best_wins)
32
+ players = {}
33
+ players['wolves'] = wolves_count
34
+ players['cops'] = 1
35
+ players['doctors'] = 1 if @players_count - wolves_count > 1
36
+ players['rogues'] = 1 if @players_count - wolves_count > 2
37
+ players['villagers'] = (@players_count - wolves_count - 3) if @players_count - wolves_count > 3
38
+
39
+ probabilities = {}
40
+ probabilities['wolves_win'] = (100.0*(best_wins[Game::WOLF] || 0)/@no_of_runs)
41
+ probabilities['villagers_win'] = (100.0*(best_wins[Game::VILLAGER] || 0)/@no_of_runs)
42
+ probabilities['draws'] = (100.0*(best_wins[Game::DRAW] || 0)/@no_of_runs)
43
+
44
+ hsh = {players: players, probabilities: probabilities}
45
+
46
+ return hsh
47
+ end
48
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'wolf'
2
+
3
+ class Cop < Villager
4
+ def initialize
5
+ super
6
+ forget_all
7
+ end
8
+
9
+ def identify_a_player(players)
10
+ identified_player = (players.alive_players - @identified_wolves - @identified_villagers - [self]).sample
11
+ if identified_player.is_a?(Wolf)
12
+ @identified_wolves.push(identified_player)
13
+ else
14
+ @identified_villagers.push(identified_player)
15
+ end
16
+ end
17
+
18
+ def accuse(players)
19
+ if @identified_wolves.any?
20
+ return @identified_wolves.sample
21
+ else
22
+ return (players.alive_players - [self] - @identified_villagers).sample
23
+ end
24
+ end
25
+
26
+ def forget_all
27
+ @identified_wolves = []
28
+ @identified_villagers = []
29
+ end
30
+
31
+ def forget(player)
32
+ if player.is_a?(Wolf)
33
+ @identified_wolves.delete(player)
34
+ else
35
+ @identified_villagers.delete(player)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ class Doctor < Villager
2
+ def choose_a_player_to_save(players)
3
+ # Assumption: Doctor saves him/her self 50% of the times
4
+ if rand < 0.5
5
+ return self
6
+ else
7
+ return players.alive_players.sample
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,2 @@
1
+ class Player
2
+ end
@@ -0,0 +1,87 @@
1
+ require_relative 'wolf'
2
+ require_relative 'villager'
3
+ require_relative 'cop'
4
+ require_relative 'doctor'
5
+ require_relative 'rogue'
6
+
7
+ class PlayerCollection
8
+ def initialize(no_of_wolves, no_of_villagers)
9
+ @players = []
10
+ @wolves = []
11
+ @villagers = []
12
+ no_of_wolves.times do
13
+ wolf = Wolf.new
14
+ @wolves.push(wolf)
15
+ @players.push(wolf)
16
+ end
17
+ @villagers = []
18
+ (1..no_of_villagers).each do |i|
19
+ if i == 1
20
+ villager = Cop.new
21
+ @cop = villager
22
+ elsif i == 2
23
+ villager = Doctor.new
24
+ @doctor = villager
25
+ elsif i == 3
26
+ villager = Rogue.new
27
+ @rogue = villager
28
+ else
29
+ villager = Villager.new
30
+ end
31
+ @villagers.push(villager)
32
+ @players.push(villager)
33
+ end
34
+ end
35
+
36
+ def alive_villagers
37
+ @villagers
38
+ end
39
+
40
+ def alive_wolves
41
+ @wolves
42
+ end
43
+
44
+ def alive_players
45
+ @players
46
+ end
47
+
48
+ def kill(player)
49
+ if player.is_a?(Wolf)
50
+ collection = @wolves
51
+ promote_rogue_to_wolf
52
+ else
53
+ @cop = nil if player.is_a?(Cop)
54
+ @rogue = nil if player.is_a?(Rogue)
55
+ collection = @villagers
56
+ end
57
+ collection.delete(player)
58
+ @players.delete(player)
59
+ @cop.forget(player) if @cop
60
+ end
61
+
62
+ def cop
63
+ @cop
64
+ end
65
+
66
+ def doctor
67
+ @doctor
68
+ end
69
+
70
+ def rogue
71
+ @rogue
72
+ end
73
+
74
+ private
75
+ def promote_rogue_to_wolf
76
+ return if @wolves.count > 0
77
+
78
+ if @rogue
79
+ kill(@rogue)
80
+ new_wolf = Wolf.new
81
+ @wolves.push(new_wolf)
82
+ @players.push(new_wolf)
83
+ end
84
+
85
+ @cop.forget_all!
86
+ end
87
+ end
@@ -0,0 +1,19 @@
1
+ class Rogue < Villager
2
+ def initialize
3
+ super
4
+ @killing_power_used = false
5
+ end
6
+
7
+ def choose_victim(players)
8
+ return nil if @killing_power_used
9
+
10
+ if (rand < (1.0/(players.alive_wolves.count + 1)))
11
+ # Choose a victim
12
+ @killing_power_used = true
13
+ return (players.alive_players - [self]).sample
14
+ else
15
+ # Save the power for a later round
16
+ return nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'player'
2
+
3
+ class Villager < Player
4
+ def accuse(players)
5
+ (players.alive_players - [self]).sample
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'player'
2
+
3
+ class Wolf < Player
4
+ def accuse(players)
5
+ players.alive_villagers.sample
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module WereWolf
2
+ VERSION = "0.1.0"
3
+ end
data/lib/were_wolf.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'were_wolf/version'
2
+ require 'were_wolf/game'
3
+ require 'were_wolf/game_simulator'
4
+ require 'were_wolf/game_suggestor'
5
+
6
+ module WereWolf
7
+ class << self
8
+ # Return:
9
+ # => 0 if the game is draw
10
+ # => 1 if wolves win
11
+ # => 2 if villagers win
12
+ def run(wolves_count, villagers_count)
13
+ game = Game.new(wolves_count, villagers_count)
14
+ return game.run
15
+ end
16
+
17
+ # Returns a hash with the following keys and value pairs:
18
+ # => 0, <no of draws>
19
+ # => 1, <no of tiems wolves won>
20
+ # => 2, <no of tiems vilalgers won>
21
+ def simulate(wolves_count, villagers_count, runs_count = 100)
22
+ simulator = GameSimulator.new(wolves_count, villagers_count, runs_count)
23
+ return simulator.simulate
24
+ end
25
+
26
+ def suggest(players_count, runs_count = 100)
27
+ suggestor = GameSuggestor.new(players_count, runs_count)
28
+ return suggestor.run
29
+ end
30
+ end
31
+ end
data/were_wolf.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'were_wolf/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "were_wolf"
8
+ spec.version = WereWolf::VERSION
9
+ spec.authors = ["BV Satyaram"]
10
+ spec.email = ["bvsatyaram@gmail.com"]
11
+
12
+ spec.summary = "WereWolf Game helper"
13
+ spec.description = "Provide us the number of players, we suggest the config for the game"
14
+ spec.homepage = "http://www.codeastra.com"
15
+
16
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
17
+ # delete this section to allow pushing this gem to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
22
+ end
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.10"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: were_wolf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - BV Satyaram
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Provide us the number of players, we suggest the config for the game
42
+ email:
43
+ - bvsatyaram@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE
51
+ - README.md
52
+ - Rakefile
53
+ - bin/console
54
+ - bin/setup
55
+ - lib/were_wolf.rb
56
+ - lib/were_wolf/game.rb
57
+ - lib/were_wolf/game_simulator.rb
58
+ - lib/were_wolf/game_suggestor.rb
59
+ - lib/were_wolf/player/cop.rb
60
+ - lib/were_wolf/player/doctor.rb
61
+ - lib/were_wolf/player/player.rb
62
+ - lib/were_wolf/player/player_collection.rb
63
+ - lib/were_wolf/player/rogue.rb
64
+ - lib/were_wolf/player/villager.rb
65
+ - lib/were_wolf/player/wolf.rb
66
+ - lib/were_wolf/version.rb
67
+ - were_wolf.gemspec
68
+ homepage: http://www.codeastra.com
69
+ licenses: []
70
+ metadata:
71
+ allowed_push_host: https://rubygems.org
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.4.8
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: WereWolf Game helper
92
+ test_files: []