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