From 71d431f601f2b9bf5266b5c68519febd454f4cf0 Mon Sep 17 00:00:00 2001
From: Paolo Capriotti
Date: Fri, 26 Jun 2009 10:57:02 +0200
Subject: [PATCH] Merge games and plugins.
Games are now loaded by the common plugin system.
---
lib/ext/loader.rb | 1 +
lib/games/chess/main.rb | 42 -------------
lib/games/games.rb | 133 ++++++++++++++---------------------------
lib/games/shogi/main.rb | 24 --------
lib/kaya.rb | 4 +-
lib/mainwindow.rb | 11 +++-
lib/plugins/background.rb | 2 -
lib/plugins/celtic/celtic.rb | 2 +-
lib/plugins/fantasy/fantasy.rb | 2 +-
lib/plugins/games/chess.rb | 17 +++++-
lib/plugins/games/shogi.rb | 14 +++--
lib/plugins/plugin.rb | 8 +++
lib/plugins/shadow.rb | 2 -
lib/plugins/shogi/shogi.rb | 2 +-
test/games/chess/test_pgn.rb | 2 +-
15 files changed, 93 insertions(+), 173 deletions(-)
delete mode 100644 lib/games/chess/main.rb
rewrite lib/games/games.rb (81%)
delete mode 100644 lib/games/shogi/main.rb
diff --git a/lib/ext/loader.rb b/lib/ext/loader.rb
index a9415c2..e60683c 100644
--- a/lib/ext/loader.rb
+++ b/lib/ext/loader.rb
@@ -8,6 +8,7 @@ end
$ext = $qApp.findChild(Qt::Object, "kaya extensions") if $qApp
fake = unless $ext
# install fake implementations of the extension functions
+ warn "Creating fake extension library"
$ext = Qt::Object.new
class << $ext
def exp_blur(img, radius)
diff --git a/lib/games/chess/main.rb b/lib/games/chess/main.rb
deleted file mode 100644
index 77f0e11..0000000
--- a/lib/games/chess/main.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require 'games/games'
-require 'games/chess/state'
-require 'games/chess/move'
-require 'games/chess/board'
-require 'games/chess/policy'
-require 'games/chess/animator'
-require 'games/chess/validator'
-require 'games/chess/serializer'
-require 'games/chess/pgn'
-
-module Chess
-
-Game.add :chess do
- Game.new :size => Point.new(8, 8),
- :policy => Policy.new(Move),
- :state_component => State,
- :state => lambda { state_component.new(board.new, move, piece) },
- :board_component => Board,
- :board => lambda { board_component.new(size) },
- :move => Move,
- :animator => Animator,
- :validator => Validator,
- :piece => Piece,
- :players => [:white, :black],
- :types => [:pawn, :knight, :bishop, :rook, :queen, :king],
- :serializer => lambda {|rep|
- Serializer.new(rep, validator, move, piece) },
- :keywords => %w(chess),
-
- :game_writer_component => PGN,
- :game_writer => lambda {
- game_writer_component.new(serializer.new(:compact),
- state) },
- :game_reader => lambda { game_writer.new },
- :game_extensions => %w(pgn)
-end
-
-Game.add :chess5x5, [:chess] do |chess|
- chess.extend(:size => Point.new(5, 5))
-end
-
-end
diff --git a/lib/games/games.rb b/lib/games/games.rb
dissimilarity index 81%
index 84bedba..03e4ec5 100644
--- a/lib/games/games.rb
+++ b/lib/games/games.rb
@@ -1,87 +1,46 @@
-require 'factory'
-
-class Game
- GAMES = { }
- LOADING = { }
- LoadableGame = Struct.new(:deps, :defn)
-
- def self.load_all(directory = nil)
- directory ||= File.dirname(__FILE__)
- Dir[File.join(directory, '*')].each do |f|
- if File.directory?(f)
- main = File.join(f, 'main.rb')
- load main if File.exist?(main)
- end
- end
-
- # register games
- LOADING.each do |name, game|
- register_game(name, game)
- end
- end
-
- def self.dummy
- # dummy is chess for the moment
- get(:chess)
- end
-
- def self.get(name)
- GAMES[name]
- end
-
- def self.add(name, deps = [], &defn)
- if Game.get(name) or LOADING[name]
- raise "The game #{name} is already defined"
- end
- LOADING[name] = LoadableGame.new(deps, defn)
- end
-
- def self.each(&blk)
- GAMES.each(&blk)
- end
-
- def extend(fields)
- clone.tap do |x|
- x.add_fields(fields)
- end
- end
-
- def initialize(fields)
- add_fields(fields)
- end
-
- protected
-
- def add_fields(fields)
- fields.each do |field, value|
- case value
- when Proc
- f_method = "__#{field}"
- metaclass_eval do
- define_method(field) { Factory.new {|*args| send(f_method, *args) } }
- define_method(f_method, value)
- end
- else
- metaclass_eval do
- define_method(field) { value }
- end
- end
- end
- end
-
- private
-
- def self.register_game(name, game)
- unless Game.get(name)
- deps = game.deps.map do |dep|
- Game.get(dep) || begin
- lgame = LOADING[dep] or
- raise "Invalid dependency #{dep} for game #{name}"
- register_game(dep, lgame)
- end
- end
- GAMES[name] = game.defn[*deps]
- end
- end
-end
-
+require 'factory'
+require 'plugins/loader'
+
+class Game
+ GAMES = { }
+ LOADER = PluginLoader.new
+
+ def self.load_all(directory = nil)
+ klasses = { }
+ LOADER.get_all_matching(:game).each do |game|
+ klasses[game.data(:id)] = game
+ end
+
+ klasses.values.each {|klass| register_game(klasses, klass) }
+ end
+
+ def self.dummy
+ # dummy is chess for the moment
+ get(:chess)
+ end
+
+ def self.get(name)
+ GAMES[name]
+ end
+
+ def self.each(&blk)
+ GAMES.each(&blk)
+ end
+
+ private
+
+ def self.register_game(klasses, klass)
+ unless Game.get(klass.data(:id))
+ (klass.data(:depends) || []).each do |dep|
+ depklass = klasses[dep] or
+ raise "Invalid dependency #{dep} for game #{klass.plugin_name}"
+ register_game(klasses, depklass)
+ klass.instance_eval do
+ define_method(dep) { Game.get(dep) }
+ end
+ end
+ GAMES[klass.data(:id)] = klass.new
+ end
+ end
+end
+
diff --git a/lib/games/shogi/main.rb b/lib/games/shogi/main.rb
deleted file mode 100644
index e75914f..0000000
--- a/lib/games/shogi/main.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'games/shogi/state'
-require 'games/shogi/pool'
-require 'games/shogi/move'
-require 'games/shogi/validator'
-require 'games/shogi/policy'
-
-module Shogi
-
-Game.add :shogi, [:chess] do |chess|
- Game.new :size => Point.new(9, 9),
- :state => lambda { State.new(board.new, pool, move, piece) },
- :board => lambda { chess.board_component.new size },
- :pool => Pool,
- :policy => Policy.new(Move, Validator),
- :move => Move,
- :animator => chess.animator,
- :validator => Validator,
- :piece => chess.piece,
- :keywords => %w(shogi),
- :players => [:black, :white],
- :types => [:pawn, :lance, :horse, :silver, :gold, :bishop, :rook, :king]
-end
-
-end
\ No newline at end of file
diff --git a/lib/kaya.rb b/lib/kaya.rb
index f0ea6fa..e1db3e8 100644
--- a/lib/kaya.rb
+++ b/lib/kaya.rb
@@ -17,7 +17,9 @@ if $0 == __FILE__
:contributors => [[KDE.ki18n("Jani Huhtanen"), KDE.ki18n('Gaussian blur code')]],
:bug_tracker => 'http://github.com/pcapriotti/kaya/issues',
:options => [['+[game]', KDE.ki18n('Initial game')]])
-
+
+ require 'ext/loader'
+
args = KDE::CmdLineArgs.parsed_args
game = if args.count > 0
name = args.arg(0)
diff --git a/lib/mainwindow.rb b/lib/mainwindow.rb
index 3ef1963..3f3dd60 100644
--- a/lib/mainwindow.rb
+++ b/lib/mainwindow.rb
@@ -150,7 +150,7 @@ private
game.respond_to?(:game_extensions) and
game.game_extensions.include?(ext)
end.map do |_, game|
- [game, game.game_reader.new]
+ [game, game.game_reader]
end
if readers.empty?
@@ -181,6 +181,7 @@ private
unless history
warn "Could not load file #{url.path}"
+ return
end
# create game
@@ -209,7 +210,11 @@ private
def save_game_as
match = @controller.match
if match
- pattern = match.game.game_extensions.map{|ext| "*.#{ext}"}.join(' ')
+ pattern = if match.game.respond_to?(:game_extensions)
+ match.game.game_extensions.map{|ext| "*.#{ext}"}.join(' ')
+ else
+ '*.*'
+ end
url = KDE::FileDialog.get_save_url(
KDE::Url.new, pattern, self, KDE.i18n("Save game"))
match.url = write_game(url)
@@ -231,7 +236,7 @@ private
match = @controller.match
if match
url ||= match.url
- writer = match.game.game_writer.new
+ writer = match.game.game_writer
info = match.info
info[:players] = info[:players].inject({}) do |res, pl|
res[pl.color] = pl.name
diff --git a/lib/plugins/background.rb b/lib/plugins/background.rb
index 4b2c0db..fef786b 100644
--- a/lib/plugins/background.rb
+++ b/lib/plugins/background.rb
@@ -1,5 +1,3 @@
-require 'ext/loader'
-
module Background
HALO_DELTA = 0.1
def halo(size, color)
diff --git a/lib/plugins/celtic/celtic.rb b/lib/plugins/celtic/celtic.rb
index d663de1..c29b949 100644
--- a/lib/plugins/celtic/celtic.rb
+++ b/lib/plugins/celtic/celtic.rb
@@ -3,7 +3,7 @@ require 'plugins/svg_theme'
class CelticTheme < SvgTheme
include Plugin
- plugin :name => 'Celtic',
+ plugin :name => 'Celtic Pieces',
:interface => :pieces,
:keywords => %w(chess)
diff --git a/lib/plugins/fantasy/fantasy.rb b/lib/plugins/fantasy/fantasy.rb
index 06fb2be..f914e9d 100644
--- a/lib/plugins/fantasy/fantasy.rb
+++ b/lib/plugins/fantasy/fantasy.rb
@@ -3,7 +3,7 @@ require 'plugins/svg_theme'
class FantasyTheme < SvgTheme
include Plugin
- plugin :name => 'Fantasy',
+ plugin :name => 'Fantasy Pieces',
:interface => :pieces,
:keywords => %w(chess)
diff --git a/lib/plugins/games/chess.rb b/lib/plugins/games/chess.rb
index 821aacf..8e18fc0 100644
--- a/lib/plugins/games/chess.rb
+++ b/lib/plugins/games/chess.rb
@@ -9,7 +9,9 @@ require 'games/chess/serializer'
require 'games/chess/pgn'
require 'plugins/plugin'
-class ChessGame
+module Chess
+
+class Game
include Plugin
plugin :name => 'Chess',
@@ -34,7 +36,7 @@ class ChessGame
@piece = Piece
@players = [:white, :black]
@types = [:pawn, :knight,:bishop, :rook, :queen, :king]
- @serializer = lambda {|rep|
+ @serializer = Factory.new(Serializer) {|rep|
Serializer.new(rep, validator, move, piece) }
@keywords = %w(chess)
@@ -47,13 +49,22 @@ class ChessGame
end
end
-class Chess5x5Game < ChessGame
+end
+
+module Chess5x5
+
+class Game < Chess::Game
plugin :name => 'Chess 5x5',
:id => :chess5x5,
:interface => :game,
:keywords => %w(chess)
def initialize
+ super
@size = Point.new(5, 5)
+ @game_extensions = []
end
+
+end
+
end
diff --git a/lib/plugins/games/shogi.rb b/lib/plugins/games/shogi.rb
index 97a19e3..9f264c3 100644
--- a/lib/plugins/games/shogi.rb
+++ b/lib/plugins/games/shogi.rb
@@ -5,7 +5,9 @@ require 'games/shogi/validator'
require 'games/shogi/policy'
require 'plugins/plugin'
-class ShogiGame
+module Shogi
+
+class Game
include Plugin
plugin :name => 'Shogi',
@@ -16,17 +18,17 @@ class ShogiGame
attr_reader :size, :state, :board, :pool,
:policy, :move, :animator, :validator,
- :piece, :keywords, :players, :types, :actions
+ :piece, :players, :types, :actions
def initialize
@size = Point.new(9, 9)
@state = Factory.new { State.new(board.new, pool, move, piece) }
- @board = Factory.new { deps[:chess].board.component.new size }
+ @board = Factory.new { chess.board.component.new size }
@pool = Pool
- @piece = deps[:chess].piece
+ @piece = chess.piece
@move = Move
@validator = Validator
- @animator = deps[:chess].animator
+ @animator = chess.animator
@policy = Policy.new(move, validator)
@players = [:white, :black]
@@ -34,3 +36,5 @@ class ShogiGame
:gold, :bishop, :rook, :king]
end
end
+
+end
\ No newline at end of file
diff --git a/lib/plugins/plugin.rb b/lib/plugins/plugin.rb
index 7ff7d5a..be382a0 100644
--- a/lib/plugins/plugin.rb
+++ b/lib/plugins/plugin.rb
@@ -25,7 +25,15 @@ module Plugin
def implements?(iface)
@plugin_data[:interface] == iface
end
+
+ def data(key)
+ @plugin_data[key]
+ end
end
extend ModuleMethods
+
+ def keywords
+ self.class.data(:keywords)
+ end
end
diff --git a/lib/plugins/shadow.rb b/lib/plugins/shadow.rb
index 960a4cb..ec1452b 100644
--- a/lib/plugins/shadow.rb
+++ b/lib/plugins/shadow.rb
@@ -1,5 +1,3 @@
-require 'ext/loader'
-
module Shadower
ShadowData = Struct.new(:radius, :color, :grow, :offset)
DEFAULT_SHADOW_DATA =
diff --git a/lib/plugins/shogi/shogi.rb b/lib/plugins/shogi/shogi.rb
index 6a14430..cf70ff9 100644
--- a/lib/plugins/shogi/shogi.rb
+++ b/lib/plugins/shogi/shogi.rb
@@ -64,7 +64,7 @@ class ShogiTheme
:lance => 0.83,
:pawn => 0.8 }
- plugin :name => 'Shogi',
+ plugin :name => 'Shogi Pieces',
:interface => :pieces,
:keywords => %w(shogi)
diff --git a/test/games/chess/test_pgn.rb b/test/games/chess/test_pgn.rb
index 67d7b72..59bf0fc 100644
--- a/test/games/chess/test_pgn.rb
+++ b/test/games/chess/test_pgn.rb
@@ -74,7 +74,7 @@ Kc7 42.Kxd5 Rd8+ 43.Rd6 Rf8 44.Ra6 Rf5+ 45.Kc4 Rxf4+
@state = @game.state.new
@state.setup
@history = History.new(@state)
- @pgn = @game.game_writer.new
+ @pgn = @game.game_writer
end
def test_pgn_black_wins
--
2.11.4.GIT