smagacor 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +340 -0
- data/ChangeLog +111 -0
- data/README +48 -0
- data/Rakefile +255 -0
- data/TODO +19 -0
- data/VERSION +1 -0
- data/bin/smagacor +23 -0
- data/data/smagacor/smagacor.png +0 -0
- data/data/smagacor/tictactoe/game.info +7 -0
- data/data/smagacor/tictactoe/o.png +0 -0
- data/data/smagacor/tictactoe/tictactoe.png +0 -0
- data/data/smagacor/tictactoe/tictactoe.rb +300 -0
- data/data/smagacor/tictactoe/x.png +0 -0
- data/install.rb +21 -0
- data/lib/smagacor/controller.rb +129 -0
- data/lib/smagacor/smagacor-ui.rb +230 -0
- data/setup.rb +1331 -0
- data/test/games/tictactoe/game.info +7 -0
- data/test/runtests.rb +2 -0
- data/test/smagacor/tc_controller.rb +48 -0
- metadata +69 -0
data/Rakefile
ADDED
@@ -0,0 +1,255 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
#
|
3
|
+
# $Id$
|
4
|
+
#
|
5
|
+
# smagacor - a collection of small games in ruby
|
6
|
+
# Copyright (C) 2004 Thomas Leitner
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
9
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
10
|
+
# License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
13
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
17
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
|
+
#
|
19
|
+
|
20
|
+
|
21
|
+
begin
|
22
|
+
require 'rubygems'
|
23
|
+
require 'rake/gempackagetask'
|
24
|
+
rescue Exception
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'rake/clean'
|
29
|
+
require 'rake/packagetask'
|
30
|
+
require 'rake/rdoctask'
|
31
|
+
require 'rake/testtask'
|
32
|
+
|
33
|
+
# General actions ##############################################################
|
34
|
+
|
35
|
+
$:.push "lib"
|
36
|
+
require 'smagacor/controller'
|
37
|
+
|
38
|
+
PKG_NAME = "smagacor"
|
39
|
+
PKG_VERSION = Smagacor::VERSION.join( '.' )
|
40
|
+
PKG_FULLNAME = PKG_NAME + "-" + PKG_VERSION
|
41
|
+
PKG_SUMMARY = "A collection of small games in ruby"
|
42
|
+
PKG_DESCRIPTION = "Smagacor is a collection of some small games,
|
43
|
+
like TicTacToe and Pong. Adding new games should not be to hard,
|
44
|
+
as Smagacor provides some useful classes for games."
|
45
|
+
|
46
|
+
|
47
|
+
SRC_RB = FileList['lib/**/*.rb', 'bin/**/*', 'data/**/*.rb']
|
48
|
+
|
49
|
+
|
50
|
+
# The default task is run if rake is given no explicit arguments.
|
51
|
+
|
52
|
+
desc "Default Task"
|
53
|
+
task :default => :version
|
54
|
+
|
55
|
+
|
56
|
+
# End user tasks ################################################################
|
57
|
+
|
58
|
+
desc "Prepares for installation"
|
59
|
+
task :prepare do
|
60
|
+
ruby "setup.rb config"
|
61
|
+
ruby "setup.rb setup"
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
desc "Installs the package #{PKG_NAME}"
|
66
|
+
task :install => [:prepare] do
|
67
|
+
ruby "setup.rb install"
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
task :clean do
|
72
|
+
ruby "setup.rb clean"
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
CLOBBER << "doc/output" << FileList['texput.*'].to_a
|
77
|
+
desc "Builds the documentation (needs webgen installed)"
|
78
|
+
task :doc => [:rdoc, :gen_version] do
|
79
|
+
chdir "doc" do
|
80
|
+
sh "webgen -V 3"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
rd = Rake::RDocTask.new do |rdoc|
|
85
|
+
rdoc.rdoc_dir = 'doc/output/rdoc'
|
86
|
+
rdoc.title = PKG_NAME
|
87
|
+
rdoc.options << '--line-numbers' << '--inline-source' << '-m README'
|
88
|
+
rdoc.rdoc_files.include( 'README' )
|
89
|
+
rdoc.rdoc_files.include( SRC_RB )
|
90
|
+
end
|
91
|
+
|
92
|
+
task 'test' do |t|
|
93
|
+
ruby "-Ilib -Itest test/runtests.rb"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Developer tasks ##############################################################
|
97
|
+
|
98
|
+
PKG_FILES = FileList.new( [
|
99
|
+
'setup.rb',
|
100
|
+
'install.rb',
|
101
|
+
'TODO',
|
102
|
+
'COPYING',
|
103
|
+
'README',
|
104
|
+
'Rakefile',
|
105
|
+
'ChangeLog',
|
106
|
+
'VERSION',
|
107
|
+
'bin/**/*',
|
108
|
+
'lib/**/*',
|
109
|
+
'doc/**/*',
|
110
|
+
'test/**/*',
|
111
|
+
'data/**/*'
|
112
|
+
]) do |fl|
|
113
|
+
fl.exclude( /\bsvn\b/ )
|
114
|
+
fl.exclude( 'doc/output' )
|
115
|
+
end
|
116
|
+
|
117
|
+
task :package => [:gen_files] do
|
118
|
+
chdir 'pkg' do
|
119
|
+
sh "rpaadmin packport #{PKG_NAME}-#{PKG_VERSION}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
task :gen_changelog do
|
124
|
+
sh "svn log -r HEAD:1 -v > ChangeLog"
|
125
|
+
end
|
126
|
+
|
127
|
+
task :gen_version do
|
128
|
+
puts "Generating VERSION file"
|
129
|
+
File.open( 'VERSION', 'w+' ) do |file| file.write( PKG_VERSION + "\n" ) end
|
130
|
+
end
|
131
|
+
|
132
|
+
task :gen_installrb do
|
133
|
+
puts "Generating install.rb file"
|
134
|
+
File.open( 'install.rb', 'w+' ) do |file|
|
135
|
+
file.write "
|
136
|
+
require 'rpa/install'
|
137
|
+
|
138
|
+
class Install_#{PKG_NAME} < RPA::Install::FullInstaller
|
139
|
+
name '#{PKG_NAME}'
|
140
|
+
version '#{PKG_VERSION}-1'
|
141
|
+
classification Application
|
142
|
+
build do
|
143
|
+
installdocs %w[COPYING ChangeLog TODO]
|
144
|
+
installdocs 'docs'
|
145
|
+
installrdoc %w[README] + Dir['lib/**/*.rb']
|
146
|
+
installdata
|
147
|
+
end
|
148
|
+
description <<-EOF
|
149
|
+
#{PKG_SUMMARY}
|
150
|
+
|
151
|
+
#{PKG_DESCRIPTION}
|
152
|
+
EOF
|
153
|
+
end
|
154
|
+
"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
task :gen_files => [:gen_changelog, :gen_version, :gen_installrb]
|
159
|
+
CLOBBER << "ChangeLog" << "VERSION" << "install.rb"
|
160
|
+
|
161
|
+
Rake::PackageTask.new( PKG_NAME, PKG_VERSION ) do |p|
|
162
|
+
p.need_tar = true
|
163
|
+
p.need_zip = true
|
164
|
+
p.package_files = PKG_FILES
|
165
|
+
end
|
166
|
+
|
167
|
+
if defined? Gem
|
168
|
+
spec = Gem::Specification.new do |s|
|
169
|
+
|
170
|
+
#### Basic information
|
171
|
+
|
172
|
+
s.name = PKG_NAME
|
173
|
+
s.version = PKG_VERSION
|
174
|
+
s.summary = PKG_SUMMARY
|
175
|
+
s.description = PKG_DESCRIPTION
|
176
|
+
|
177
|
+
#### Dependencies, requirements and files
|
178
|
+
|
179
|
+
s.files = PKG_FILES.to_a
|
180
|
+
|
181
|
+
s.autorequire = nil
|
182
|
+
s.executables = [ 'smagacor']
|
183
|
+
s.default_executable = 'smagacor'
|
184
|
+
|
185
|
+
#### Documentation
|
186
|
+
|
187
|
+
s.has_rdoc = true
|
188
|
+
s.extra_rdoc_files = rd.rdoc_files.reject do |fn| fn =~ /\.rb$/ end.to_a
|
189
|
+
s.rdoc_options = ['--line-numbers', '-m README']
|
190
|
+
|
191
|
+
#### Author and project details
|
192
|
+
|
193
|
+
s.author = "Thomas Leitner"
|
194
|
+
s.email = "t_leitner@gmx.at"
|
195
|
+
s.homepage = "smagacor.rubyforge.org"
|
196
|
+
s.rubyforge_project = "smagacor"
|
197
|
+
end
|
198
|
+
|
199
|
+
Rake::GemPackageTask.new( spec ) do |pkg|
|
200
|
+
pkg.need_zip = true
|
201
|
+
pkg.need_tar = true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
=begin
|
206
|
+
desc "Creates a tag in the repository"
|
207
|
+
task :tag do
|
208
|
+
repositoryPath = File.dirname( $1 ) if `svn info` =~ /^URL: (.*)$/
|
209
|
+
fail "Tag already created in repository " if /#{PKG_FULLNAME}/ =~ `svn ls #{repositoryPath}/versions`
|
210
|
+
sh "svn cp -m 'Created version #{PKG_FULLNAME}' #{repositoryPath}/trunk/#{PKG_NAME} #{repositoryPath}/versions/#{PKG_FULLNAME}"
|
211
|
+
end
|
212
|
+
=end
|
213
|
+
|
214
|
+
desc "Upload documentation to homepage"
|
215
|
+
task :uploaddoc => [:doc] do
|
216
|
+
Dir.chdir('doc/output')
|
217
|
+
sh "scp -r * gettalong@rubyforge.org:/var/www/gforge-projects/#{PKG_NAME}/"
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
# Misc tasks ###################################################################
|
222
|
+
|
223
|
+
|
224
|
+
def count_lines( filename )
|
225
|
+
lines = 0
|
226
|
+
codelines = 0
|
227
|
+
open( filename ) do |f|
|
228
|
+
f.each do |line|
|
229
|
+
lines += 1
|
230
|
+
next if line =~ /^\s*$/
|
231
|
+
next if line =~ /^\s*#/
|
232
|
+
codelines += 1
|
233
|
+
end
|
234
|
+
end
|
235
|
+
[lines, codelines]
|
236
|
+
end
|
237
|
+
|
238
|
+
|
239
|
+
def show_line( msg, lines, loc )
|
240
|
+
printf "%6s %6s %s\n", lines.to_s, loc.to_s, msg
|
241
|
+
end
|
242
|
+
|
243
|
+
desc "Show statistics"
|
244
|
+
task :statistics do
|
245
|
+
total_lines = 0
|
246
|
+
total_code = 0
|
247
|
+
show_line( "File Name", "Lines", "LOC" )
|
248
|
+
SRC_RB.each do |fn|
|
249
|
+
lines, codelines = count_lines fn
|
250
|
+
show_line( fn, lines, codelines )
|
251
|
+
total_lines += lines
|
252
|
+
total_code += codelines
|
253
|
+
end
|
254
|
+
show_line( "Total", total_lines, total_code )
|
255
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
---- CURRENT ----
|
2
|
+
|
3
|
+
* help -> help for current game
|
4
|
+
* make splitter not moveable
|
5
|
+
* make splitter hideable
|
6
|
+
* implement Pong
|
7
|
+
* implement UNDO mechanism
|
8
|
+
* implement State saver
|
9
|
+
* TicTacToe AI opponent (on base of mini-max, nega-max,...)
|
10
|
+
* complete tests
|
11
|
+
|
12
|
+
---- FUTURE ----
|
13
|
+
|
14
|
+
* implement Sokoban
|
15
|
+
|
16
|
+
---- DONE ----
|
17
|
+
|
18
|
+
* BUG: log window should stay behind main window
|
19
|
+
* BUG: rake install broken on windows
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/smagacor
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
#
|
4
|
+
# $Id$
|
5
|
+
#
|
6
|
+
# smagacor - a collection of small games in ruby
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'smagacor/smagacor-ui'
|
22
|
+
|
23
|
+
Smagacor::SmagacorUI.new.start
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,300 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
#
|
4
|
+
# $Id: tictactoe.rb 190 2005-02-02 19:26:25Z thomas $
|
5
|
+
#
|
6
|
+
# smagacor - a collection of small games in ruby
|
7
|
+
# Copyright (C) 2004 Thomas Leitner
|
8
|
+
#
|
9
|
+
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU
|
10
|
+
# General Public License as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
14
|
+
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15
|
+
# General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License along with this program; if not,
|
18
|
+
# write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
require 'observer'
|
23
|
+
|
24
|
+
module Smagacor
|
25
|
+
|
26
|
+
# TicTacToe for Smagacor
|
27
|
+
module TicTacToe
|
28
|
+
|
29
|
+
# Base player class
|
30
|
+
class Player
|
31
|
+
|
32
|
+
# Defines whether the player can currently make a move. Default is +false+.
|
33
|
+
attr_accessor :can_move
|
34
|
+
|
35
|
+
# Return a new player.
|
36
|
+
def initialize
|
37
|
+
@can_move = false
|
38
|
+
end
|
39
|
+
|
40
|
+
# Invoked by the game engine to get the move.
|
41
|
+
def move() end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# Human player. Provides the interface for a human to play TicTacToe.
|
47
|
+
class HumanPlayer < Player
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
super
|
51
|
+
@field = -1
|
52
|
+
end
|
53
|
+
|
54
|
+
# See Player#move
|
55
|
+
def move
|
56
|
+
self.can_move = false
|
57
|
+
@field
|
58
|
+
end
|
59
|
+
|
60
|
+
# Set the +field+ which is returned by the next #move. <tt>can_move</tt> is set to +true+ so
|
61
|
+
# that the game engine knows the this player has chosen a field.
|
62
|
+
def set_field( field )
|
63
|
+
@field = field
|
64
|
+
self.can_move = true
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# AI computer player. Not yet implemented!
|
71
|
+
class ComputerPlayer < Player
|
72
|
+
|
73
|
+
def move
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# The TicTacToe board.
|
80
|
+
class Board < String
|
81
|
+
|
82
|
+
# Defines the empty field.
|
83
|
+
FIELD_EMPTY = ?-
|
84
|
+
|
85
|
+
def initialize( size )
|
86
|
+
super( FIELD_EMPTY.chr * size )
|
87
|
+
end
|
88
|
+
|
89
|
+
# Redefined each so that the methods from Enumerable work correctly.
|
90
|
+
def each( &block )
|
91
|
+
each_byte( &block )
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Game engine for TicTacToe. Knows how to correctly play TicTacToe.
|
98
|
+
class TicTacToe
|
99
|
+
|
100
|
+
include Observable
|
101
|
+
|
102
|
+
# The board on which is played.
|
103
|
+
attr_accessor :board
|
104
|
+
|
105
|
+
# Create a new TicTacToe game with the given +players+.
|
106
|
+
def initialize( players )
|
107
|
+
@players = players
|
108
|
+
@board = Board.new( 9 )
|
109
|
+
end
|
110
|
+
|
111
|
+
# Return the current player if the game has been initialized.
|
112
|
+
def cur_player
|
113
|
+
@players[@cur_player] if @cur_player < 2
|
114
|
+
end
|
115
|
+
|
116
|
+
# Initialize the game state.
|
117
|
+
def init
|
118
|
+
@board = Board.new( 9 )
|
119
|
+
@cur_player = 0
|
120
|
+
end
|
121
|
+
|
122
|
+
# Play one (or more) round(s) of a TicTacToe game. When the current player can make a move
|
123
|
+
# (Player#can_move), his move is verified and the board changed. Then it is the turn of the
|
124
|
+
# other player. As long as the current player can make a move (and the game is not finished),
|
125
|
+
# the method runs. When the current player cannot make a move, the method exists and it has to
|
126
|
+
# be called again, when the current player can make his move.
|
127
|
+
def play_round
|
128
|
+
while @players[@cur_player].can_move && !game_finished?
|
129
|
+
logger.info { "Current board: #{@board}" }
|
130
|
+
logger.info { "Current player: #{cur_player}" }
|
131
|
+
field = @players[@cur_player].move
|
132
|
+
logger.info { "Field selected: #{field}" }
|
133
|
+
if @board[field] == Board::FIELD_EMPTY
|
134
|
+
@board[field] = @cur_player.to_s
|
135
|
+
@cur_player = 1 - @cur_player
|
136
|
+
changed
|
137
|
+
notify_observers( :move )
|
138
|
+
end
|
139
|
+
end
|
140
|
+
if game_finished?
|
141
|
+
logger.info { " Game finished" }
|
142
|
+
changed
|
143
|
+
notify_observers( :finished, player_won )
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
# True if the board is full.
|
150
|
+
def board_full?
|
151
|
+
@board.all? {|i| i != Board::FIELD_EMPTY}
|
152
|
+
end
|
153
|
+
|
154
|
+
# Win situations.
|
155
|
+
WIN_SITUATIONS = [[0,1,2], [3,4,5], [6,7,8], [0,3,6],
|
156
|
+
[1,4,7], [2,5,8], [0,4,8], [2,4,6]]
|
157
|
+
|
158
|
+
# True if the game is over
|
159
|
+
def game_finished?
|
160
|
+
board_full? || player_won?( ?0 ) || player_won?( ?1 )
|
161
|
+
end
|
162
|
+
|
163
|
+
# Return the number of the player who has won.
|
164
|
+
#
|
165
|
+
# Returns
|
166
|
+
# 0:: player 1
|
167
|
+
# 1:: player 2
|
168
|
+
# 2:: draw
|
169
|
+
# -1:: game not finished yet
|
170
|
+
def player_won
|
171
|
+
( player_won?( ?0 ) ? 0 : ( player_won?( ?1 ) ? 1 : ( board_full? ? 2 : -1 ) ) )
|
172
|
+
end
|
173
|
+
|
174
|
+
# Check if +player+ has won the game.
|
175
|
+
def player_won?( player )
|
176
|
+
WIN_SITUATIONS.each {|a,b,c| return true if @board[a] == player && @board[b] == player && @board[c] == player }
|
177
|
+
return false
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
# Widget for TicTacToe.
|
184
|
+
class TicTacToeUI < FXHorizontalFrame
|
185
|
+
|
186
|
+
attr_reader :gameinfo
|
187
|
+
|
188
|
+
def initialize( p, gameinfo )
|
189
|
+
super( p )
|
190
|
+
@gameinfo = gameinfo
|
191
|
+
|
192
|
+
@canvas = FXCanvas.new( self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y )
|
193
|
+
@canvas.connect( SEL_PAINT, method( :onPaint ) )
|
194
|
+
@canvas.connect( SEL_LEFTBUTTONRELEASE, method( :onCanvasClick ) )
|
195
|
+
FXVerticalSeparator.new( self )
|
196
|
+
options = FXVerticalFrame.new( self, LAYOUT_FILL_Y )
|
197
|
+
|
198
|
+
p = Proc.new do |name|
|
199
|
+
FXLabel.new( options, name )
|
200
|
+
box = FXComboBox.new( options, 20, 2, nil, 0, COMBOBOX_NORMAL|COMBOBOX_STATIC|FRAME_SUNKEN )
|
201
|
+
box.appendItem( 'Human', HumanPlayer )
|
202
|
+
box.appendItem( 'Computer', ComputerPlayer )
|
203
|
+
box
|
204
|
+
end
|
205
|
+
@player1 = p.call( 'Player 1' )
|
206
|
+
@player2 = p.call( 'Player 2' )
|
207
|
+
|
208
|
+
FXButton.new( options, "Start Game", nil, nil, 0, LAYOUT_FILL_X|BUTTON_NORMAL ).connect( SEL_COMMAND, method( :onStartGame ) )
|
209
|
+
|
210
|
+
@xicon = File.join( gameinfo.directory, 'x.png' )
|
211
|
+
@oicon = File.join( gameinfo.directory, 'o.png' )
|
212
|
+
end
|
213
|
+
|
214
|
+
def create
|
215
|
+
super
|
216
|
+
end
|
217
|
+
|
218
|
+
def onCanvasClick( sender, sel, event )
|
219
|
+
if !@game.nil? && @game.cur_player.respond_to?( :set_field )
|
220
|
+
width, padding = get_lengths
|
221
|
+
pos = Proc.new do |point|
|
222
|
+
case point
|
223
|
+
when 0..(padding + width/3): 0
|
224
|
+
when (padding + width/3)..(padding + width*2/3): 1
|
225
|
+
else 2
|
226
|
+
end
|
227
|
+
end
|
228
|
+
@game.cur_player.set_field( pos[event.click_x] + pos[event.click_y]*3 )
|
229
|
+
@game.play_round
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def onStartGame( sender, sel, event )
|
234
|
+
p = [@player1.getItemData( @player1.currentItem ).new, @player2.getItemData( @player2.currentItem ).new ]
|
235
|
+
@canvas.update
|
236
|
+
@game = TicTacToe.new( p)
|
237
|
+
@game.add_observer( self )
|
238
|
+
@game.init
|
239
|
+
@game.play_round
|
240
|
+
end
|
241
|
+
|
242
|
+
def update( reason, winner=nil )
|
243
|
+
case reason
|
244
|
+
when :move: @canvas.update
|
245
|
+
when :finished
|
246
|
+
msg = (winner < 2 ? "Player #{winner+1}" : "Nobody" ) + " has won!"
|
247
|
+
FXMessageBox.information( self, MBOX_OK, "Result", msg )
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def onPaint( sender, sel, event )
|
252
|
+
FXDCWindow.new( sender, event ) do |dc|
|
253
|
+
dc.foreground = FXColor::White
|
254
|
+
dc.fillRectangle( 0, 0, sender.width, sender.height )
|
255
|
+
paintPlayArea( dc )
|
256
|
+
paintCurGame( dc )
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
private
|
261
|
+
|
262
|
+
def get_lengths
|
263
|
+
width = (@canvas.width > @canvas.height ? @canvas.height : @canvas.width )
|
264
|
+
[(width * 0.8).to_i, (width * 0.1).to_i]
|
265
|
+
end
|
266
|
+
|
267
|
+
def paintPlayArea( dc )
|
268
|
+
width, padding = get_lengths
|
269
|
+
dc.foreground = FXColor::Black
|
270
|
+
dc.lineWidth = 10
|
271
|
+
dc.lineCap = CAP_ROUND
|
272
|
+
dc.drawLine( padding + width/3, padding, padding + width/3, padding + width )
|
273
|
+
dc.drawLine( padding + width*2/3, padding, padding + width*2/3, padding + width )
|
274
|
+
dc.drawLine( padding, padding + width/3, padding + width, padding + width/3 )
|
275
|
+
dc.drawLine( padding, padding + width*2/3, padding + width, padding + width*2/3 )
|
276
|
+
end
|
277
|
+
|
278
|
+
def paintCurGame( dc )
|
279
|
+
unless @game.nil?
|
280
|
+
width, padding = get_lengths
|
281
|
+
size = width/5
|
282
|
+
padding = padding + (width/3 - size)/2
|
283
|
+
@game.board.each_with_index do |item, index|
|
284
|
+
case item
|
285
|
+
when ?0
|
286
|
+
dc.foreground = FXColor::Red
|
287
|
+
dc.drawRectangle( padding + width/3 * (index % 3), padding + width/3 * (index / 3), size, size )
|
288
|
+
when ?1
|
289
|
+
dc.foreground = FXColor::Green
|
290
|
+
dc.drawCircle( padding + size/2 + width/3 * (index % 3), padding + size/2 + width/3 * (index / 3), size/2 )
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
Binary file
|
data/install.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
require 'rpa/install'
|
3
|
+
|
4
|
+
class Install_smagacor < RPA::Install::FullInstaller
|
5
|
+
name 'smagacor'
|
6
|
+
version '0.0.1-1'
|
7
|
+
classification Application
|
8
|
+
build do
|
9
|
+
installdocs %w[COPYING ChangeLog TODO]
|
10
|
+
installdocs 'docs'
|
11
|
+
installrdoc %w[README] + Dir['lib/**/*.rb']
|
12
|
+
installdata
|
13
|
+
end
|
14
|
+
description <<-EOF
|
15
|
+
A collection of small games in ruby
|
16
|
+
|
17
|
+
Smagacor is a collection of some small games,
|
18
|
+
like TicTacToe and Pong. Adding new games should not be to hard,
|
19
|
+
as Smagacor provides some useful classes for games.
|
20
|
+
EOF
|
21
|
+
end
|