Skip to content

Instantly share code, notes, and snippets.

@chamun
Last active October 2, 2015 22:09
Show Gist options
  • Save chamun/8285614c4aacfed58e55 to your computer and use it in GitHub Desktop.
Save chamun/8285614c4aacfed58e55 to your computer and use it in GitHub Desktop.
A simple implementation of a Jokenpo server
# Author: Rodrigo Chamun
# How to run:
# Server: ruby jokenpo.rb
# Players: $ nc server_address 6666 - 2>/dev/null
require 'socket'
require 'forwardable'
class Move
attr_accessor :player, :verb
def initialize(player, verb, inferior_move)
@player = player
@verb = verb
@inferior_move = inferior_move
end
def >(move)
move.class == @inferior_move
end
def win_sentence(loser)
"#{self.class} #{verb} #{loser.class}. #{player} wins!"
end
end
class Rock < Move
def initialize(player)
super(player, 'smashes', Scissors)
end
end
class Scissors < Move
def initialize(player)
super(player, 'cuts', Paper)
end
end
class Paper < Move
def initialize(player)
super(player, 'wraps', Rock)
end
end
class Hulk < Move
def initialize(player)
super(player, 'smashes', nil)
end
def >(move)
move.class != Hulk
end
def win_sentence(loser)
"Hulk smashes! #{player} wins."
end
end
class Broadcast
def initialize(*connections)
@connections = connections
end
def puts(message, *ignore)
@connections.each do |c|
c.puts message unless ignore.include?(c)
end
end
def new_line
puts("\n")
end
def <<(item)
@connections << item
end
end
class Player
extend Forwardable
def_delegators :@socket, :puts
attr_accessor :name
def initialize(name, socket)
@name = name
@socket = socket
end
def get_move
Object.const_get(@socket.gets.chomp.capitalize).new(name)
end
end
class Game
def self.start
Game.new.start
end
def initialize
@broadcast = Broadcast.new(STDOUT)
connection = TCPServer.new 6666
@broadcast.puts 'Waiting for Player 1'
@p1 = Player.new('Player 1', connection.accept)
puts_welcome_message(@p1)
@broadcast << @p1
@broadcast.puts 'Waiting for Player 2 to connect'
@p2 = Player.new('Player 2', connection.accept)
puts_welcome_message(@p2)
@broadcast << @p2
end
def start
loop do
m1 = get_player_move(@p1)
m2 = get_player_move(@p2)
begin
winner, loser = eval_moves(m1, m2)
@broadcast.puts winner.win_sentence(loser)
rescue
@broadcast.puts "Both played #{m1.class}. It's a draw!"
end
@broadcast.new_line
end
rescue Interrupt
@broadcast.puts "Server shut down."
end
private
def get_player_move(player)
@broadcast.puts("Waiting for #{player.name} to play.", player)
begin
player.puts('You move!')
move = player.get_move
rescue NameError
player.puts("You can't play that!")
end while move.nil?
move
end
def eval_moves(m1, m2)
return [m1, m2] if m1 > m2
return [m2, m1] if m2 > m1
raise 'draw'
end
def puts_welcome_message(player)
player.puts "Welcome to Jokenpo! You are #{player.name}"
player.puts 'Valid moves are: rock, paper and scissors'
end
end
Game.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment