gridlock.app-1.10/0000755000175000000000000000000010342227611013025 5ustar gurkanrootgridlock.app-1.10/main.m0000644000175000000000000000340110342202543014122 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import #import "AutoplayController.h" static int doAutoplay() { id pool = [[NSAutoreleasePool alloc] init]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; int result = ([defaults objectForKey:@"AutoplayGame"]!=nil); [pool release]; return result; } int main(int argc, const char *argv[]) { srandom(time(NULL)); if (doAutoplay()) { id pool = [[NSAutoreleasePool alloc] init]; AutoplayController *apController = [[AutoplayController alloc] init]; [apController run]; [apController release]; [pool release]; return 0; } else { return NSApplicationMain(argc, argv); } } gridlock.app-1.10/PC.project0000644000175000000000000001265410342222007014721 0ustar gurkanroot{ APPCLASS = NSApplication; APPKIT = "GNUSTEP-GUI"; APPLICATIONICON = Gridlock.tiff; APP_DOCUMENT_BASED = NO; BUILDTOOL = "/usr/bin/make"; CLASS_FILES = ( main.m, AbstractLineGame.m, AppController.m, AtaxxAI.m, AtaxxGame.m, AtaxxViewDelegate.m, BoardView.m, BreakthroughAI.m, CocoaAdditions.m, ConnectFourAI.m, ConnectFourGame.m, DCHypergrid.m, DCHypergridPosition.m, DCHypergridPositionEnumerator.m, Game.m, GameController.m, GenericAI.m, GlassBeadGame.m, GlassBeadViewDelegate.m, GomokuAI.m, GomokuGame.m, ImageStore.m, MyWindow.m, PlayerTurnIndicatorView.m, Preferences.m, PrefsWindowController.m, ReversiAI.m, ReversiGame.m, CheckersAI.m, CheckersGame.m, CheckersViewDelegate.m, GridlockGameState.m, GameConfiguration.m, GameHistory.m, ClientController.m, ServerController.m, RendezvousUtils.m, NetConnection.m, EDIPSocket.m, EDSocket.m, EDTCPSocket.m, functions.m, "NSFileHandle+Extensions.m", "NSObject+Extensions.m", LifeAI.m, LifeGame.m, AutoplayController.m, GravityAI.m, GravityGame.m, GravityViewDelegate.m, ZoneshAI.m, ZoneshGame.m, ZoneshViewDelegate.m, CatsAndDogsAI.m, CatsAndDogsGame.m, QuadWrangleGame.m, CatsAndDogsViewDelegate.m, HexapawnAI.m, HexapawnGame.m, MorayEelsGame.m, AnyDirectionUntilBlockedMoveRule.m, AtomicAI.m, AtomicGame.m, AtomicViewDelegate.m, BombardmentAI.m, BombardmentGame.m, DaggerAI.m, DaggerGame.m, FissionAI.m, FissionGame.m, FiveFieldKonoAI.m, FiveFieldKonoGame.m, OrthokonGame.m, PhotonicAttackGame.m, ReactorGame.m, ReactorViewDelegate.m, TourneyAI.m, TourneyGame.m, WallGameViewDelegate.m, AmbivalenceGame.m, SabotageAI.m, FusionGame.m, SabotageGame.m, SabotageViewDelegate.m, ThinkAheadAI.m, ThinkAheadGame.m, ThinkAheadViewDelegate.m, TongaGame.m, DominionGame.m, FiancoAI.m, FiancoGame.m ); COMPILEROPTIONS = ""; CPPOPTIONS = ""; CREATION_DATE = ""; DOCU_FILES = ( README.GNUstep, readme.html ); FOUNDATION = "GNUSTEP-BASE"; FRAMEWORKS = ( ); HEADER_FILES = ( AbstractLineGame.h, AppController.h, AtaxxAI.h, AtaxxGame.h, AtaxxViewDelegate.h, BoardView.h, BreakthroughAI.h, CocoaAdditions.h, ConnectFourAI.h, ConnectFourGame.h, DCHypergrid.h, DCHypergridPosition.h, DCHypergridPositionEnumerator.h, Game.h, GameController.h, GenericAI.h, GlassBeadGame.h, GlassBeadViewDelegate.h, GomokuAI.h, GomokuGame.h, ImageStore.h, MyWindow.h, PlayerTurnIndicatorView.h, Preferences.h, PrefsWindowController.h, ReversiAI.h, ReversiGame.h, AccessorMacros.h, CheckersAI.h, CheckersGame.h, CheckersViewDelegate.h, GridlockGameState.h, GameConfiguration.h, GameHistory.h, ClientController.h, ServerController.h, RendezvousUtils.h, NetConnection.h, EDIPSocket.h, EDSocket.h, EDTCPSocket.h, functions.h, EDCommonDefines.h, osdep.h, "NSFileHandle+Extensions.h", "NSObject+Extensions.h", LifeAI.h, LifeGame.h, AutoplayController.h, GravityAI.h, GravityGame.h, GravityViewDelegate.h, ZoneshAI.h, ZoneshGame.h, ZoneshViewDelegate.h, CatsAndDogsAI.h, CatsAndDogsGame.h, QuadWrangleGame.h, CatsAndDogsViewDelegate.h, HexapawnAI.h, HexapawnGame.h, MorayEelsGame.h, AnyDirectionUntilBlockedMoveRule.h, AtomicAI.h, AtomicGame.h, AtomicViewDelegate.h, BombardmentAI.h, BombardmentGame.h, DaggerAI.h, DaggerGame.h, FissionAI.h, FissionGame.h, FiveFieldKonoAI.h, FiveFieldKonoGame.h, OrthokonGame.h, PhotonicAttackGame.h, ReactorGame.h, ReactorViewDelegate.h, TourneyAI.h, TourneyGame.h, WallGameViewDelegate.h, AmbivalenceGame.h, SabotageAI.h, FusionGame.h, SabotageGame.h, SabotageViewDelegate.h, ThinkAheadAI.h, ThinkAheadGame.h, ThinkAheadViewDelegate.h, TongaGame.h, DominionGame.h, FiancoAI.h, FiancoGame.h ); IMAGES = ( aqua.tiff, blue.tiff, graphite.tiff, green.tiff, purple.tiff, red.tiff, wall.tiff, yellow.tiff, Gridlock.tiff ); INSTALLDIR = "$(GNUSTEP_LOCAL_ROOT)/"; INTERFACES = ( PrefsWindow.gorm, GameWindow.gorm, Gridlock.gorm, ServerWindow.gorm, ClientWindow.gorm ); LANGUAGE = English; LAST_EDITING = "2005-11-26 21:11:47 -0600"; LIBRARIES = ( "gnustep-base", "gnustep-gui" ); LINKEROPTIONS = ""; LOCALIZED_RESOURCES = ( ); MAININTERFACE = Gridlock.gorm; MAKEFILEDIR = "$(GNUSTEP_SYSTEM_ROOT)/Makefiles"; OBJC_COMPILEROPTIONS = ""; OTHER_FILES = ( ); OTHER_RESOURCES = ( "Info-gnustep.plist", Games.plist, PieceImages.plist, Localizable.strings ); OTHER_SOURCES = ( hypergrid.c ); PC_WINDOWS = { ProjectBuild = "168 130 543 407 0 0 960 768 "; ProjectWindow = "224 35 726 686 0 0 960 768 "; ShowToolbar = YES; }; PRINCIPAL_CLASS = NSApplication; PROJECT_AUTHORS = ( ); PROJECT_COPYRIGHT = "No license specified!"; PROJECT_COPYRIGHT_DESC = "Released under ..."; PROJECT_CREATOR = ""; PROJECT_DESCRIPTION = "No description avaliable!"; PROJECT_DOCUMENTTYPES = ( ); PROJECT_GROUP = "No description avaliable!"; PROJECT_MAINTAINER = ""; PROJECT_NAME = Gridlock; PROJECT_RELEASE = 1; PROJECT_SOURCE = "%{gs_name}-%{gs_version}.tar.gz"; PROJECT_SUMMARY = "No summary avaliable!"; PROJECT_TYPE = Application; PROJECT_URL = ""; PROJECT_VERSION = 1.0; SEARCH_HEADER_DIRS = ( ); SEARCH_LIB_DIRS = ( ); SUBPROJECTS = ( ); SUPPORTING_FILES = ( GNUmakefile.preamble, GNUmakefile, GNUmakefile.postamble ); USER_LANGUAGES = ( English ); }gridlock.app-1.10/Gridlock.pcproj0000644000175000000000000001101110027001365015770 0ustar gurkanroot{ APPCLASS = NSApplication; APPKIT = "GNUSTEP-GUI"; APPLICATIONICON = Gridlock.tiff; BUILDTOOL = "/usr/bin/make"; CLASS_FILES = ( main.m, AbstractLineGame.m, AppController.m, AtaxxAI.m, AtaxxGame.m, AtaxxViewDelegate.m, BoardView.m, BreakthroughAI.m, CocoaAdditions.m, ConnectFourAI.m, ConnectFourGame.m, DCHypergrid.m, DCHypergridPosition.m, DCHypergridPositionEnumerator.m, Game.m, GameController.m, GenericAI.m, GlassBeadGame.m, GlassBeadViewDelegate.m, GomokuAI.m, GomokuGame.m, ImageStore.m, MyWindow.m, PlayerTurnIndicatorView.m, Preferences.m, PrefsWindowController.m, ReversiAI.m, ReversiGame.m, CheckersAI.m, CheckersGame.m, CheckersViewDelegate.m, GridlockGameState.m, GameConfiguration.m, GameHistory.m, ClientController.m, ServerController.m, RendezvousUtils.m, NetConnection.m, EDIPSocket.m, EDSocket.m, EDTCPSocket.m, functions.m, "NSFileHandle+Extensions.m", "NSObject+Extensions.m", LifeAI.m, LifeGame.m, AutoplayController.m, GravityAI.m, GravityGame.m, GravityViewDelegate.m, ZoneshAI.m, ZoneshGame.m, ZoneshViewDelegate.m, CatsAndDogsAI.m, CatsAndDogsGame.m, QuadWrangleGame.m, CatsAndDogsViewDelegate.m, HexapawnAI.m, HexapawnGame.m, MorayEelsGame.m, AnyDirectionUntilBlockedMoveRule.m, AtomicAI.m, AtomicGame.m, AtomicViewDelegate.m, BombardmentAI.m, BombardmentGame.m, DaggerAI.m, DaggerGame.m, FissionAI.m, FissionGame.m, FiveFieldKonoAI.m, FiveFieldKonoGame.m, OrthokonGame.m, PhotonicAttackGame.m, ReactorGame.m, ReactorViewDelegate.m, TourneyAI.m, TourneyGame.m, WallGameViewDelegate.m ); COMPILEROPTIONS = ""; CREATION_DATE = ""; DOCU_FILES = ( README.GNUstep, readme.html ); FOUNDATION = "GNUSTEP-BASE"; FRAMEWORKS = ( ); HEADER_FILES = ( AbstractLineGame.h, AppController.h, AtaxxAI.h, AtaxxGame.h, AtaxxViewDelegate.h, BoardView.h, BreakthroughAI.h, CocoaAdditions.h, ConnectFourAI.h, ConnectFourGame.h, DCHypergrid.h, DCHypergridPosition.h, DCHypergridPositionEnumerator.h, Game.h, GameController.h, GenericAI.h, GlassBeadGame.h, GlassBeadViewDelegate.h, GomokuAI.h, GomokuGame.h, ImageStore.h, MyWindow.h, PlayerTurnIndicatorView.h, Preferences.h, PrefsWindowController.h, ReversiAI.h, ReversiGame.h, AccessorMacros.h, CheckersAI.h, CheckersGame.h, CheckersViewDelegate.h, GridlockGameState.h, GameConfiguration.h, GameHistory.h, ClientController.h, ServerController.h, RendezvousUtils.h, NetConnection.h, EDIPSocket.h, EDSocket.h, EDTCPSocket.h, functions.h, EDCommonDefines.h, osdep.h, "NSFileHandle+Extensions.h", "NSObject+Extensions.h", LifeAI.h, LifeGame.h, AutoplayController.h, GravityAI.h, GravityGame.h, GravityViewDelegate.h, ZoneshAI.h, ZoneshGame.h, ZoneshViewDelegate.h, CatsAndDogsAI.h, CatsAndDogsGame.h, QuadWrangleGame.h, CatsAndDogsViewDelegate.h, HexapawnAI.h, HexapawnGame.h, MorayEelsGame.h, AnyDirectionUntilBlockedMoveRule.h, AtomicAI.h, AtomicGame.h, AtomicViewDelegate.h, BombardmentAI.h, BombardmentGame.h, DaggerAI.h, DaggerGame.h, FissionAI.h, FissionGame.h, FiveFieldKonoAI.h, FiveFieldKonoGame.h, OrthokonGame.h, PhotonicAttackGame.h, ReactorGame.h, ReactorViewDelegate.h, TourneyAI.h, TourneyGame.h, WallGameViewDelegate.h ); IMAGES = ( aqua.tiff, blue.tiff, graphite.tiff, green.tiff, purple.tiff, red.tiff, wall.tiff, yellow.tiff, Gridlock.tiff ); INSTALLDIR = "$(GNUSTEP_LOCAL_ROOT)/"; INTERFACES = ( PrefsWindow.gorm, GameWindow.gorm, Gridlock.gorm, ServerWindow.gorm, ClientWindow.gorm ); LANGUAGE = English; LAST_EDITING = ""; LIBRARIES = ( "gnustep-base", "gnustep-gui" ); LINKEROPTIONS = ""; MAININTERFACE = Gridlock.gorm; MAKEFILEDIR = "$(GNUSTEP_SYSTEM_ROOT)/Makefiles"; OTHER_FILES = ( ); OTHER_RESOURCES = ( GridlockInfo.plist, Games.plist, PieceImages.plist, Localizable.strings ); OTHER_SOURCES = ( hypergrid.c ); PRINCIPAL_CLASS = main.m; PROJECT_BUILDER = PCGormProj; PROJECT_COPYRIGHT = "No license specified!"; PROJECT_CREATOR = ""; PROJECT_DESCRIPTION = "No description avaliable!"; PROJECT_GROUP = "No description avaliable!"; PROJECT_MAINTAINER = ""; PROJECT_NAME = Gridlock; PROJECT_RELEASE = 1; PROJECT_SOURCE = "%{gs_name}-%{gs_version}.tar.gz"; PROJECT_SUMMARY = "No summary avaliable!"; PROJECT_TYPE = PCGormProject; PROJECT_VERSION = 1.0; SUBPROJECTS = ( ); SUPPORTING_FILES = ( GNUmakefile.preamble, GNUmakefile, GNUmakefile.postamble ); }gridlock.app-1.10/Gridlock.pcproj.backup0000644000175000000000000001101110027001175017233 0ustar gurkanroot{ APPCLASS = NSApplication; APPKIT = "GNUSTEP-GUI"; APPLICATIONICON = Gridlock.tiff; BUILDTOOL = "/usr/bin/make"; CLASS_FILES = ( main.m, AbstractLineGame.m, AppController.m, AtaxxAI.m, AtaxxGame.m, AtaxxViewDelegate.m, BoardView.m, BreakthroughAI.m, CocoaAdditions.m, ConnectFourAI.m, ConnectFourGame.m, DCHypergrid.m, DCHypergridPosition.m, DCHypergridPositionEnumerator.m, Game.m, GameController.m, GenericAI.m, GlassBeadGame.m, GlassBeadViewDelegate.m, GomokuAI.m, GomokuGame.m, ImageStore.m, MyWindow.m, PlayerTurnIndicatorView.m, Preferences.m, PrefsWindowController.m, ReversiAI.m, ReversiGame.m, CheckersAI.m, CheckersGame.m, CheckersViewDelegate.m, GridlockGameState.m, GameConfiguration.m, GameHistory.m, ClientController.m, ServerController.m, RendezvousUtils.m, NetConnection.m, EDIPSocket.m, EDSocket.m, EDTCPSocket.m, functions.m, "NSFileHandle+Extensions.m", "NSObject+Extensions.m", LifeAI.m, LifeGame.m, AutoplayController.m, GravityAI.m, GravityGame.m, GravityViewDelegate.m, ZoneshAI.m, ZoneshGame.m, ZoneshViewDelegate.m, CatsAndDogsAI.m, CatsAndDogsGame.m, QuadWrangleGame.m, CatsAndDogsViewDelegate.m, HexapawnAI.m, HexapawnGame.m, MorayEelsGame.m, AnyDirectionUntilBlockedMoveRule.m, AtomicAI.m, AtomicGame.m, AtomicViewDelegate.m, BombardmentAI.m, BombardmentGame.m, DaggerAI.m, DaggerGame.m, FissionAI.m, FissionGame.m, FiveFieldKonoAI.m, FiveFieldKonoGame.m, OrthokonGame.m, PhotonicAttackGame.m, ReactorGame.m, ReactorViewDelegate.m, TourneyAI.m, TourneyGame.m, WallGameViewDelegate.m ); COMPILEROPTIONS = ""; CREATION_DATE = ""; DOCU_FILES = ( README.GNUstep, readme.html ); FOUNDATION = "GNUSTEP-BASE"; FRAMEWORKS = ( ); HEADER_FILES = ( AbstractLineGame.h, AppController.h, AtaxxAI.h, AtaxxGame.h, AtaxxViewDelegate.h, BoardView.h, BreakthroughAI.h, CocoaAdditions.h, ConnectFourAI.h, ConnectFourGame.h, DCHypergrid.h, DCHypergridPosition.h, DCHypergridPositionEnumerator.h, Game.h, GameController.h, GenericAI.h, GlassBeadGame.h, GlassBeadViewDelegate.h, GomokuAI.h, GomokuGame.h, ImageStore.h, MyWindow.h, PlayerTurnIndicatorView.h, Preferences.h, PrefsWindowController.h, ReversiAI.h, ReversiGame.h, AccessorMacros.h, CheckersAI.h, CheckersGame.h, CheckersViewDelegate.h, GridlockGameState.h, GameConfiguration.h, GameHistory.h, ClientController.h, ServerController.h, RendezvousUtils.h, NetConnection.h, EDIPSocket.h, EDSocket.h, EDTCPSocket.h, functions.h, EDCommonDefines.h, osdep.h, "NSFileHandle+Extensions.h", "NSObject+Extensions.h", LifeAI.h, LifeGame.h, AutoplayController.h, GravityAI.h, GravityGame.h, GravityViewDelegate.h, ZoneshAI.h, ZoneshGame.h, ZoneshViewDelegate.h, CatsAndDogsAI.h, CatsAndDogsGame.h, QuadWrangleGame.h, CatsAndDogsViewDelegate.h, HexapawnAI.h, HexapawnGame.h, MorayEelsGame.h, AnyDirectionUntilBlockedMoveRule.h, AtomicAI.h, AtomicGame.h, AtomicViewDelegate.h, BombardmentAI.h, BombardmentGame.h, DaggerAI.h, DaggerGame.h, FissionAI.h, FissionGame.h, FiveFieldKonoAI.h, FiveFieldKonoGame.h, OrthokonGame.h, PhotonicAttackGame.h, ReactorGame.h, ReactorViewDelegate.h, TourneyAI.h, TourneyGame.h, WallGameViewDelegate.h ); IMAGES = ( aqua.tiff, blue.tiff, graphite.tiff, green.tiff, purple.tiff, red.tiff, wall.tiff, yellow.tiff, Gridlock.tiff ); INSTALLDIR = "$(GNUSTEP_LOCAL_ROOT)/"; INTERFACES = ( PrefsWindow.gorm, GameWindow.gorm, Gridlock.gorm, ServerWindow.gorm, ClientWindow.gorm ); LANGUAGE = English; LAST_EDITING = ""; LIBRARIES = ( "gnustep-base", "gnustep-gui" ); LINKEROPTIONS = ""; MAININTERFACE = Gridlock.gorm; MAKEFILEDIR = "$(GNUSTEP_SYSTEM_ROOT)/Makefiles"; OTHER_FILES = ( ); OTHER_RESOURCES = ( GridlockInfo.plist, Games.plist, PieceImages.plist, Localizable.strings ); OTHER_SOURCES = ( hypergrid.c ); PRINCIPAL_CLASS = main.m; PROJECT_BUILDER = PCGormProj; PROJECT_COPYRIGHT = "No license specified!"; PROJECT_CREATOR = ""; PROJECT_DESCRIPTION = "No description avaliable!"; PROJECT_GROUP = "No description avaliable!"; PROJECT_MAINTAINER = ""; PROJECT_NAME = Gridlock; PROJECT_RELEASE = 1; PROJECT_SOURCE = "%{gs_name}-%{gs_version}.tar.gz"; PROJECT_SUMMARY = "No summary avaliable!"; PROJECT_TYPE = PCGormProject; PROJECT_VERSION = 1.0; SUBPROJECTS = ( ); SUPPORTING_FILES = ( GNUmakefile.preamble, GNUmakefile, GNUmakefile.postamble ); }gridlock.app-1.10/PC.project.backup0000644000175000000000000001243410342221573016170 0ustar gurkanroot{ APPCLASS = NSApplication; APPKIT = "GNUSTEP-GUI"; APPLICATIONICON = Gridlock.tiff; APP_DOCUMENT_BASED = NO; BUILDTOOL = "/usr/bin/make"; CLASS_FILES = ( main.m, AbstractLineGame.m, AppController.m, AtaxxAI.m, AtaxxGame.m, AtaxxViewDelegate.m, BoardView.m, BreakthroughAI.m, CocoaAdditions.m, ConnectFourAI.m, ConnectFourGame.m, DCHypergrid.m, DCHypergridPosition.m, DCHypergridPositionEnumerator.m, Game.m, GameController.m, GenericAI.m, GlassBeadGame.m, GlassBeadViewDelegate.m, GomokuAI.m, GomokuGame.m, ImageStore.m, MyWindow.m, PlayerTurnIndicatorView.m, Preferences.m, PrefsWindowController.m, ReversiAI.m, ReversiGame.m, CheckersAI.m, CheckersGame.m, CheckersViewDelegate.m, GridlockGameState.m, GameConfiguration.m, GameHistory.m, ClientController.m, ServerController.m, RendezvousUtils.m, NetConnection.m, EDIPSocket.m, EDSocket.m, EDTCPSocket.m, functions.m, "NSFileHandle+Extensions.m", "NSObject+Extensions.m", LifeAI.m, LifeGame.m, AutoplayController.m, GravityAI.m, GravityGame.m, GravityViewDelegate.m, ZoneshAI.m, ZoneshGame.m, ZoneshViewDelegate.m, CatsAndDogsAI.m, CatsAndDogsGame.m, QuadWrangleGame.m, CatsAndDogsViewDelegate.m, HexapawnAI.m, HexapawnGame.m, MorayEelsGame.m, AnyDirectionUntilBlockedMoveRule.m, AtomicAI.m, AtomicGame.m, AtomicViewDelegate.m, BombardmentAI.m, BombardmentGame.m, DaggerAI.m, DaggerGame.m, FissionAI.m, FissionGame.m, FiveFieldKonoAI.m, FiveFieldKonoGame.m, OrthokonGame.m, PhotonicAttackGame.m, ReactorGame.m, ReactorViewDelegate.m, TourneyAI.m, TourneyGame.m, WallGameViewDelegate.m, AmbivalenceGame.m, SabotageAI.m, FusionGame.m, SabotageGame.m, SabotageViewDelegate.m, ThinkAheadAI.m, ThinkAheadGame.m, ThinkAheadViewDelegate.m, TongaGame.m, DominionGame.m, FiancoAI.m, FiancoGame.m ); COMPILEROPTIONS = ""; CPPOPTIONS = ""; CREATION_DATE = ""; DOCU_FILES = ( README.GNUstep, readme.html ); FOUNDATION = "GNUSTEP-BASE"; FRAMEWORKS = ( ); HEADER_FILES = ( AbstractLineGame.h, AppController.h, AtaxxAI.h, AtaxxGame.h, AtaxxViewDelegate.h, BoardView.h, BreakthroughAI.h, CocoaAdditions.h, ConnectFourAI.h, ConnectFourGame.h, DCHypergrid.h, DCHypergridPosition.h, DCHypergridPositionEnumerator.h, Game.h, GameController.h, GenericAI.h, GlassBeadGame.h, GlassBeadViewDelegate.h, GomokuAI.h, GomokuGame.h, ImageStore.h, MyWindow.h, PlayerTurnIndicatorView.h, Preferences.h, PrefsWindowController.h, ReversiAI.h, ReversiGame.h, AccessorMacros.h, CheckersAI.h, CheckersGame.h, CheckersViewDelegate.h, GridlockGameState.h, GameConfiguration.h, GameHistory.h, ClientController.h, ServerController.h, RendezvousUtils.h, NetConnection.h, EDIPSocket.h, EDSocket.h, EDTCPSocket.h, functions.h, EDCommonDefines.h, osdep.h, "NSFileHandle+Extensions.h", "NSObject+Extensions.h", LifeAI.h, LifeGame.h, AutoplayController.h, GravityAI.h, GravityGame.h, GravityViewDelegate.h, ZoneshAI.h, ZoneshGame.h, ZoneshViewDelegate.h, CatsAndDogsAI.h, CatsAndDogsGame.h, QuadWrangleGame.h, CatsAndDogsViewDelegate.h, HexapawnAI.h, HexapawnGame.h, MorayEelsGame.h, AnyDirectionUntilBlockedMoveRule.h, AtomicAI.h, AtomicGame.h, AtomicViewDelegate.h, BombardmentAI.h, BombardmentGame.h, DaggerAI.h, DaggerGame.h, FissionAI.h, FissionGame.h, FiveFieldKonoAI.h, FiveFieldKonoGame.h, OrthokonGame.h, PhotonicAttackGame.h, ReactorGame.h, ReactorViewDelegate.h, TourneyAI.h, TourneyGame.h, WallGameViewDelegate.h, AmbivalenceGame.h, SabotageAI.h, FusionGame.h, SabotageGame.h, SabotageViewDelegate.h, ThinkAheadAI.h, ThinkAheadGame.h, ThinkAheadViewDelegate.h, TongaGame.h, DominionGame.h, FiancoAI.h, FiancoGame.h ); IMAGES = ( aqua.tiff, blue.tiff, graphite.tiff, green.tiff, purple.tiff, red.tiff, wall.tiff, yellow.tiff, Gridlock.tiff ); INSTALLDIR = "$(GNUSTEP_LOCAL_ROOT)/"; INTERFACES = ( PrefsWindow.gorm, GameWindow.gorm, Gridlock.gorm, ServerWindow.gorm, ClientWindow.gorm ); LANGUAGE = English; LAST_EDITING = "2005-11-26 21:09:47 -0600"; LIBRARIES = ( "gnustep-base", "gnustep-gui" ); LINKEROPTIONS = ""; LOCALIZED_RESOURCES = ( ); MAININTERFACE = Gridlock.gorm; MAKEFILEDIR = "$(GNUSTEP_SYSTEM_ROOT)/Makefiles"; OBJC_COMPILEROPTIONS = ""; OTHER_FILES = ( ); OTHER_RESOURCES = ( "Info-gnustep.plist", Games.plist, PieceImages.plist, Localizable.strings ); OTHER_SOURCES = ( hypergrid.c ); PRINCIPAL_CLASS = NSApplication; PROJECT_AUTHORS = ( ); PROJECT_COPYRIGHT = "No license specified!"; PROJECT_COPYRIGHT_DESC = "Released under ..."; PROJECT_CREATOR = ""; PROJECT_DESCRIPTION = "No description avaliable!"; PROJECT_DOCUMENTTYPES = ( ); PROJECT_GROUP = "No description avaliable!"; PROJECT_MAINTAINER = ""; PROJECT_NAME = Gridlock; PROJECT_RELEASE = 1; PROJECT_SOURCE = "%{gs_name}-%{gs_version}.tar.gz"; PROJECT_SUMMARY = "No summary avaliable!"; PROJECT_TYPE = Application; PROJECT_URL = ""; PROJECT_VERSION = 1.0; SEARCH_HEADER_DIRS = ( ); SEARCH_LIB_DIRS = ( ); SUBPROJECTS = ( ); SUPPORTING_FILES = ( GNUmakefile.preamble, GNUmakefile, GNUmakefile.postamble ); USER_LANGUAGES = ( English ); }gridlock.app-1.10/MyWindow.h0000644000175000000000000000231310342202555014752 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import @interface MyWindow : NSWindow { NSView *boardView; } @end gridlock.app-1.10/GNUmakefile0000644000175000000000000001066610342221763015112 0ustar gurkanroot# # GNUmakefile - Generated by ProjectCenter # include $(GNUSTEP_MAKEFILES)/common.make # # Application # VERSION = 1 PACKAGE_NAME = Gridlock APP_NAME = Gridlock Gridlock_APPLICATION_ICON = Gridlock.tiff GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_LOCAL_ROOT)/ # # Resource files # Gridlock_RESOURCE_FILES = \ Resources/PrefsWindow.gorm \ Resources/GameWindow.gorm \ Resources/Gridlock.gorm \ Resources/ServerWindow.gorm \ Resources/ClientWindow.gorm\ Resources/aqua.tiff \ Resources/blue.tiff \ Resources/graphite.tiff \ Resources/green.tiff \ Resources/purple.tiff \ Resources/red.tiff \ Resources/wall.tiff \ Resources/yellow.tiff \ Resources/Gridlock.tiff\ Resources/Info-gnustep.plist \ Resources/Games.plist \ Resources/PieceImages.plist \ Resources/Localizable.strings\ Resources/README.GNUstep \ Resources/readme.html # # Header files # Gridlock_HEADER_FILES = \ AbstractLineGame.h \ AppController.h \ AtaxxAI.h \ AtaxxGame.h \ AtaxxViewDelegate.h \ BoardView.h \ BreakthroughAI.h \ CocoaAdditions.h \ ConnectFourAI.h \ ConnectFourGame.h \ DCHypergrid.h \ DCHypergridPosition.h \ DCHypergridPositionEnumerator.h \ Game.h \ GameController.h \ GenericAI.h \ GlassBeadGame.h \ GlassBeadViewDelegate.h \ GomokuAI.h \ GomokuGame.h \ ImageStore.h \ MyWindow.h \ PlayerTurnIndicatorView.h \ Preferences.h \ PrefsWindowController.h \ ReversiAI.h \ ReversiGame.h \ AccessorMacros.h \ CheckersAI.h \ CheckersGame.h \ CheckersViewDelegate.h \ GridlockGameState.h \ GameConfiguration.h \ GameHistory.h \ ClientController.h \ ServerController.h \ RendezvousUtils.h \ NetConnection.h \ EDIPSocket.h \ EDSocket.h \ EDTCPSocket.h \ functions.h \ EDCommonDefines.h \ osdep.h \ NSFileHandle+Extensions.h \ NSObject+Extensions.h \ LifeAI.h \ LifeGame.h \ AutoplayController.h \ GravityAI.h \ GravityGame.h \ GravityViewDelegate.h \ ZoneshAI.h \ ZoneshGame.h \ ZoneshViewDelegate.h \ CatsAndDogsAI.h \ CatsAndDogsGame.h \ QuadWrangleGame.h \ CatsAndDogsViewDelegate.h \ HexapawnAI.h \ HexapawnGame.h \ MorayEelsGame.h \ AnyDirectionUntilBlockedMoveRule.h \ AtomicAI.h \ AtomicGame.h \ AtomicViewDelegate.h \ BombardmentAI.h \ BombardmentGame.h \ DaggerAI.h \ DaggerGame.h \ FissionAI.h \ FissionGame.h \ FiveFieldKonoAI.h \ FiveFieldKonoGame.h \ OrthokonGame.h \ PhotonicAttackGame.h \ ReactorGame.h \ ReactorViewDelegate.h \ TourneyAI.h \ TourneyGame.h \ WallGameViewDelegate.h \ AmbivalenceGame.h \ SabotageAI.h \ FusionGame.h \ SabotageGame.h \ SabotageViewDelegate.h \ ThinkAheadAI.h \ ThinkAheadGame.h \ ThinkAheadViewDelegate.h \ TongaGame.h \ DominionGame.h \ FiancoAI.h \ FiancoGame.h # # Class files # Gridlock_OBJC_FILES = \ main.m \ AbstractLineGame.m \ AppController.m \ AtaxxAI.m \ AtaxxGame.m \ AtaxxViewDelegate.m \ BoardView.m \ BreakthroughAI.m \ CocoaAdditions.m \ ConnectFourAI.m \ ConnectFourGame.m \ DCHypergrid.m \ DCHypergridPosition.m \ DCHypergridPositionEnumerator.m \ Game.m \ GameController.m \ GenericAI.m \ GlassBeadGame.m \ GlassBeadViewDelegate.m \ GomokuAI.m \ GomokuGame.m \ ImageStore.m \ MyWindow.m \ PlayerTurnIndicatorView.m \ Preferences.m \ PrefsWindowController.m \ ReversiAI.m \ ReversiGame.m \ CheckersAI.m \ CheckersGame.m \ CheckersViewDelegate.m \ GridlockGameState.m \ GameConfiguration.m \ GameHistory.m \ ClientController.m \ ServerController.m \ RendezvousUtils.m \ NetConnection.m \ EDIPSocket.m \ EDSocket.m \ EDTCPSocket.m \ functions.m \ NSFileHandle+Extensions.m \ NSObject+Extensions.m \ LifeAI.m \ LifeGame.m \ AutoplayController.m \ GravityAI.m \ GravityGame.m \ GravityViewDelegate.m \ ZoneshAI.m \ ZoneshGame.m \ ZoneshViewDelegate.m \ CatsAndDogsAI.m \ CatsAndDogsGame.m \ QuadWrangleGame.m \ CatsAndDogsViewDelegate.m \ HexapawnAI.m \ HexapawnGame.m \ MorayEelsGame.m \ AnyDirectionUntilBlockedMoveRule.m \ AtomicAI.m \ AtomicGame.m \ AtomicViewDelegate.m \ BombardmentAI.m \ BombardmentGame.m \ DaggerAI.m \ DaggerGame.m \ FissionAI.m \ FissionGame.m \ FiveFieldKonoAI.m \ FiveFieldKonoGame.m \ OrthokonGame.m \ PhotonicAttackGame.m \ ReactorGame.m \ ReactorViewDelegate.m \ TourneyAI.m \ TourneyGame.m \ WallGameViewDelegate.m \ AmbivalenceGame.m \ SabotageAI.m \ FusionGame.m \ SabotageGame.m \ SabotageViewDelegate.m \ ThinkAheadAI.m \ ThinkAheadGame.m \ ThinkAheadViewDelegate.m \ TongaGame.m \ DominionGame.m \ FiancoAI.m \ FiancoGame.m # # C files # Gridlock_C_FILES = \ hypergrid.c Gridlock_OBJC_FILES += # # Makefiles # -include GNUmakefile.preamble include $(GNUSTEP_MAKEFILES)/aggregate.make include $(GNUSTEP_MAKEFILES)/application.make -include GNUmakefile.postamble gridlock.app-1.10/DiagonalsGame.m0000644000175000000000000000663610342202541015704 0ustar gurkanroot// // DiagonalsGame.m // Gridlock // // Created by Brian on Sat Jul 10 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "DiagonalsGame.h" @implementation DiagonalsGame idAccessor(preparedMove, setPreparedMove) -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; p1Score = p2Score = 0; [self setPreparedMove:nil]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self setPreparedMove:[positions lastObject]]; return YES; } -(NSArray *)positionsOfAllChangingCells { return [[self preparedMove] arrayWithSelf_]; } -(int)futureValueAtPosition:(DCHypergridPosition *)pos { if ([pos isEqual:[self preparedMove]]) return [self currentPlayerNumber]; else return [self valueAtPosition:pos]; } -(int)scoreForDiagonalFromPosition:(id)pos northEast:(BOOL)ne { int score = 1; // count position moved to BOOL longerThan1 = NO; // corners don't count int pnum = [self valueAtPosition:pos]; // go forward diagonally until we hit the edge or an empty cell int r = [pos row]; int c = [pos column]; int dc = ne ? 1 : -1; while ([self isValidRow:r+1 column:c+dc]) { int val = [self valueAtRow:r+1 column:c+dc]; if (val==0) return 0; // not a full diagonal if (val==pnum) score++; longerThan1 = YES; r++; c+=dc; } // repeat in opposite direction r = [pos row]; c = [pos column]; while ([self isValidRow:r-1 column:c-dc]) { int val = [self valueAtRow:r-1 column:c-dc]; if (val==0) return 0; // not a full diagonal if (val==pnum) score++; longerThan1 = YES; r--; c-=dc; } return (longerThan1) ? score : 0; } -(int)scoreForDiagonalsFromPosition:(id)pos { return [self scoreForDiagonalFromPosition:pos northEast:YES] + [self scoreForDiagonalFromPosition:pos northEast:NO]; } -(void)updateFromPreparedMove { id pos = [self preparedMove]; [super updateFromPreparedMove]; // check for completed diagonals int score = [self scoreForDiagonalsFromPosition:pos]; if ([self currentPlayerNumber]==1) { p1Score += score; } else { p2Score += score; } } -(NSArray *)allValidMoveSequences { return [[[self grid] allPositionsWithValue:0] valuesByObjectsPerformingSelector:@selector(arrayWithSelf_)]; } -(BOOL)showScores { return YES; } -(int)scoreForPlayer:(int)pnum { return (pnum==1) ? p1Score : p2Score; } -(BOOL)isGameOver { return !([[self grid] hasCellWithValue:0]); } // these methods deal with the score ivars (since they can't be derived from the state of the board) -(Game *)copy { DiagonalsGame *newGame = (DiagonalsGame *)[super copy]; newGame->p1Score = p1Score; newGame->p2Score = p2Score; return newGame; } -(void)copyValuesToGame:(DiagonalsGame *)newGame { [super copyValuesToGame:newGame]; newGame->p1Score = p1Score; newGame->p2Score = p2Score; } -(id)propertyList { id plist = [super propertyList]; // assume mutable? [plist setObject:[[NSNumber numberWithInt:p1Score] stringValue] forKey:@"p1Score"]; [plist setObject:[[NSNumber numberWithInt:p2Score] stringValue] forKey:@"p2Score"]; return plist; } -(void)updateFromPropertyList:(id)plist { [super updateFromPropertyList:plist]; p1Score = [[plist objectForKey:@"p1Score"] intValue]; p2Score = [[plist objectForKey:@"p2Score"] intValue]; } @end gridlock.app-1.10/AbstractLineGame.m0000644000175000000000000001716410342202540016353 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "AbstractLineGame.h" @implementation AbstractLineGame -(int)winningLength { return -1; } -(id)init { if (self = [super init]) { _cachedThreatDicts = [[NSMutableDictionary alloc] init]; } return self; } idAccessor(preparedMove, setPreparedMove) -(void)dealloc { [_cachedThreatDicts release]; [self setPreparedMove:nil]; [super dealloc]; } -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; [_cachedThreatDicts removeAllObjects]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self setPreparedMove:[positions lastObject]]; return YES; } -(NSArray *)positionsOfAllChangingCells { return [[self preparedMove] arrayWithSelf_]; } -(int)futureValueAtPosition:(DCHypergridPosition *)pos { if ([pos isEqual:[self preparedMove]]) return [self currentPlayerNumber]; else return [self valueAtPosition:pos]; } -(void)didMakeMove:(NSArray *)positions { [super didMakeMove:positions]; [self setPreparedMove:nil]; [_cachedThreatDicts removeAllObjects]; } -(BOOL)isGameOver { if ([self hasPlayerWon:1] || [self hasPlayerWon:2]) return YES; else { // game is over if all cells are filled return ![[self grid] hasCellWithValue:0]; } } -(BOOL)hasPlayerWon:(int)pnum { NSArray *threats = [self threatsForPlayer:pnum]; NSEnumerator *te = [threats objectEnumerator]; NSDictionary *threat; while (threat=[te nextObject]) { int length = [[threat objectForKey:@"length"] intValue]; if (length>=[self winningLength]) return YES; } return NO; } -(int)winningPlayer { int pcount = [self numberOfPlayers]; int i; for(i=1; i<=pcount; i++) { if ([self hasPlayerWon:i]) return i; } return 0; } -(NSArray *)positionsOfWinningPieces { int wpnum = [self winningPlayer]; if (wpnum>=1 && wpnum<=[self numberOfPlayers]) { NSArray *threats = [self threatsForPlayer:wpnum]; NSEnumerator *te = [threats objectEnumerator]; NSDictionary *threat; while (threat=[te nextObject]) { int length = [[threat objectForKey:@"length"] intValue]; if (length>=[self winningLength]) { NSMutableArray *positions = [NSMutableArray array]; int i=0; DCHypergridPosition *pos = [threat objectForKey:@"position"]; DCHypergridPosition *dir = [threat objectForKey:@"direction"]; while (i<[self winningLength]) { [positions addObject:pos]; pos = [pos positionByAddingPosition:dir]; i++; } return positions; } } } return nil; } /** Returns an array of NSDictionary objects, each of which describes a threat line. The keys and values of each dictionary are as follows: "position" - DCHypergridPosition, starting position of the threat line "direction" - DCHypergridPosition, direction of the threat line relative to position "length" - number of cells in the threat line "openBefore" - number of empty cells "behind" the threat line (relative to direction) "openAfter" - number of empty cells in front of the threat line */ -(NSArray *)threatsForPlayer:(int)pnum { NSNumber *num = [NSNumber numberWithInt:pnum]; NSArray *result = [_cachedThreatDicts objectForKey:num]; if (!result) { [_cachedThreatDicts setObject:(result=[self _threatsForPlayer:pnum]) forKey:num]; } return result; } -(NSArray *)_threatsForPlayer:(int)pnum { NSMutableArray *threats = [NSMutableArray array]; NSEnumerator *ge = [grid positionEnumerator]; DCHypergridPosition *pos; while (pos=[ge nextObject]) { // does the player own this cell? if ([self valueAtPosition:pos]==pnum) { // only look in the "forward" directions int deltas[8] = {0,1, 1,-1, 1,0, 1,1}; int i; for(i=0; i<4; i++) { int dr = deltas[2*i]; int dc = deltas[2*i+1]; if ([pos row]+dr<[self numberOfRows] && [pos column]+dc>=0 && [pos column]+dc<[self numberOfColumns]) { id diff = [DCHypergridPosition positionWithRow:dr column:dc]; // make sure the player does not own the cell going backwards id temppos = [pos positionBySubtractingPosition:diff]; int backval = -1; if (![grid isValidPosition:temppos] || (backval=[self valueAtPosition:temppos])!=pnum) { int backopen = 0; int fwdopen = 0; int length = 1; BOOL done = NO; // walk forward, incrementing length while we keep hitting cells we own, then fwdopen BOOL threatFinished = NO; temppos=[pos positionByAddingPosition:diff]; while (!done) { if ([grid isValidPosition:temppos]) { int value = [grid valueAtPosition:temppos]; if (!threatFinished) { if (value==pnum) ++length; else threatFinished = YES; } if (threatFinished) { if (value==pnum || value==0) ++fwdopen; else done = YES; } } else done = YES; if (!done) temppos = [temppos positionByAddingPosition:diff]; } // walk backward, incrementing backopen done = 0; temppos = [pos positionBySubtractingPosition:diff]; while (!done) { if ([grid isValidPosition:temppos]) { int value = [grid valueAtPosition:temppos]; if (value==pnum || value==0) ++backopen; else done = YES; } else done = YES; if (!done) temppos = [temppos positionBySubtractingPosition:diff]; } // create threat dictionary { int totallen = length+backopen+fwdopen; // can't be a winning threat unless totallen>=winningLength if (length>1 && totallen>=[self winningLength]) { NSMutableDictionary *threatDict = [NSMutableDictionary dictionary]; [threatDict setObject:pos forKey:@"position"]; [threatDict setObject:diff forKey:@"direction"]; [threatDict setObject:[NSNumber numberWithInt:length] forKey:@"length"]; [threatDict setObject:[NSNumber numberWithInt:fwdopen] forKey:@"openAfter"]; [threatDict setObject:[NSNumber numberWithInt:backopen] forKey:@"openBefore"]; [threats addObject:threatDict]; } } } } } } } return threats; } @end gridlock.app-1.10/AppController.m0000644000175000000000000001013410342202541015761 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "AppController.h" #import "DCHypergrid.h" #import "GameController.h" #import "PrefsWindowController.h" #import "ClientController.h" #import "ServerController.h" /* static void test2() { DCHypergrid *grid = [[[DCHypergrid alloc] initWithRows:8 columns:8] autorelease]; DCHypergridPosition *pos1 = [DCHypergridPosition positionWithRow:2 column:3]; DCHypergridPosition *pos2 = [DCHypergridPosition positionWithRow:4 column:5]; DCHypergridPosition *pos3 = [DCHypergridPosition positionWithRow:2 column:3]; DCHypergridPosition *pos4 = [DCHypergridPosition positionWithRow:4 column:5]; NSArray *array1 = [NSArray arrayWithObjects:pos1,pos2,nil]; NSArray *array2 = [NSArray arrayWithObjects:pos3,pos4,nil]; NSArray *array3 = [NSArray arrayWithObjects:pos1,pos3,pos3,nil]; NSLog(@"%d %d %d %d %d %d", [pos1 hash], [pos2 hash], [pos3 hash], [pos4 hash], [array1 hash], [array3 hash]); NSLog(@"%d %d %d", [pos1 isEqual:pos3], [array1 isEqual:array2], [array1 isEqual:array3]); { NSData *gdata = [NSArchiver archivedDataWithRootObject:grid]; DCHypergrid *gridcopy = [NSUnarchiver unarchiveObjectWithData:gdata]; NSLog(@"%d %d", [grid numberOfDimensions], [gridcopy numberOfDimensions]); } } */ @implementation AppController -(void)applicationDidFinishLaunching:(NSNotification *)note { } idAccessor(gameController, setGameController) -(void)awakeFromNib { [self setGameController:[[[GameController alloc] init] autorelease]]; [NSBundle loadNibNamed:@"GameWindow" owner:[self gameController]]; } -(void)showPreferences:(id)sender { if (!prefsController) { prefsController = [[PrefsWindowController alloc] init]; [NSBundle loadNibNamed:@"PrefsWindow" owner:prefsController]; } [prefsController showWindow]; } -(void)joinGame:(id)sender { if (!clientController) { clientController = [[ClientController alloc] init]; [NSBundle loadNibNamed:@"ClientWindow" owner:clientController]; } [clientController showWindow]; } -(void)hostGame:(id)sender { if (!serverController) { serverController = [[ServerController alloc] init]; [NSBundle loadNibNamed:@"ServerWindow" owner:serverController]; } [serverController showWindow]; } // testing methods /* -(void)runTest { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int i; for(i=0; i<10000; i++) { //[self testGrid]; if (i%100==0) { [pool release]; pool = [[NSAutoreleasePool alloc] init]; NSLog(@"%d", i); } } [pool release]; } -(void)testGrid { DCHypergrid *grid; int dim[] = {8,8,8}; int coordints[] = {2,4,5}; NSArray *neighbors; DCHypergridPosition *coords; grid = [[[DCHypergrid alloc] initWithNumberOfDimensions:2 sizes:dim] autorelease]; coords = [[[DCHypergridPosition alloc] initWithSize:2 data:coordints] autorelease]; neighbors = [grid neighborsOfPosition:coords distance:2]; NSLog(@"neighbors:%@", neighbors); //[coords debug]; //NSLog(@"%d", [neighbors count]); //for(i=0; i<[neighbors count]; i++) { // [[neighbors objectAtIndex:i] debug]; //} } */ @end gridlock.app-1.10/AtaxxAI.m0000644000175000000000000001346710342202541014510 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "AtaxxAI.h" #import "AtaxxGame.h" /* AtaxxAI uses a custom enumerator to only generate moves as they are required. This gives a substantial performance improvement when used with alpha-beta searching, because when a node gets pruned we save time by not computing all of its moves. AtaxxAIGoodMoveEnumerator cycles through all the pieces owned by the current player twice; first looking for non-jump moves and then looking for jumps. It keeps track of where it left off searching in its index and boolean ivars. */ @interface AtaxxAIGoodMoveEnumerator : NSEnumerator { Game *game; NSMutableArray *startPositions; NSMutableSet *nonJumpEndPositions; int movesReturned; // these ivars store where we are in the process of searching for moves int startPositionIndex; // which position we're starting from int neighborIndex; // index of the neighbor (possible ending position) of the start position BOOL checkingNonjumps; // true if we're looking for normal moves BOOL checkingJumps; // true if we're looking for jumps } @end @implementation AtaxxAIGoodMoveEnumerator -(id)initWithGame:(Game *)g { if (self=[super init]) { game = [g retain]; // get start positions, and randomize so that if the utilities are equal the same move won't always be made { NSEnumerator *pe = [[game grid] enumeratorForPositionsWithValue:[game currentPlayerNumber]]; id pos; startPositions = [[NSMutableArray alloc] init]; while (pos=[pe nextObject]) { [startPositions addObject:pos]; } [startPositions randomizeObjects_]; nonJumpEndPositions = [[NSMutableSet alloc] init]; checkingNonjumps = YES; } } return self; } /** Advances the ivars to point at the next move to check. */ -(void)incrementIndexes { neighborIndex++; if (checkingNonjumps){ if (neighborIndex==9) { // done with the current starting position (up to 9 cells distance 1 away) neighborIndex = 0; startPositionIndex++; if (startPositionIndex>=[startPositions count]) { // done with all non-jumps checkingJumps = YES; checkingNonjumps = NO; startPositionIndex = 0; } } } else if (neighborIndex==25) { // done with the current starting position (up to 25 cells distance 2 away) neighborIndex = 0; startPositionIndex++; if (startPositionIndex>=[startPositions count]) { // done with all jumps checkingJumps = NO; } } } /** Get the next valid move, ignoring duplicate non-jump moves to the same destination, and jumps to a destination where a non-jump is available. */ -(id)nextObject { // test at indices, then increment while (checkingNonjumps) { id startpos = [startPositions objectAtIndex:startPositionIndex]; // neighborIndex goes from 0 to 8, because there are (up to) 9 cells within 1 of the start position int r = [startpos row] - 1 + neighborIndex/3; int c = [startpos column] - 1 + neighborIndex%3; if ([game isValidRow:r column:c]) { id endpos = [DCHypergridPosition positionWithRow:r column:c]; if ([game valueAtRow:r column:c]==0 && ![nonJumpEndPositions containsObject:endpos]) { // good move [nonJumpEndPositions addObject:endpos]; [self incrementIndexes]; ++movesReturned; return [endpos arrayWithSelf_]; //return [NSArray arrayWithObjects:startpos,endpos,nil]; } } [self incrementIndexes]; } while (checkingJumps) { id startpos = [startPositions objectAtIndex:startPositionIndex]; // neighborIndex goes from 0 to 24, because there are (up to) 25 cells within 2 of the start position int dr = -2 + neighborIndex/5; int dc = -2 + neighborIndex%5; // we don't want to check neighbors that aren't actually jumps if (dr==2 || dr==-2 || dc==2 || dc==-2) { int r = [startpos row] + dr; int c = [startpos column] + dc; if ([game isValidRow:r column:c]) { id endpos = [DCHypergridPosition positionWithRow:r column:c]; if ([game valueAtRow:r column:c]==0 && ![nonJumpEndPositions containsObject:endpos]) { // good move [self incrementIndexes]; ++movesReturned; return [NSArray arrayWithObjects:startpos,endpos,nil]; } } } [self incrementIndexes]; } // we're done checking all jumps and nonjumps. If we didn't find anything, return a pass if (movesReturned==0) { ++movesReturned; return [NSArray array]; } return nil; } -(void)dealloc { [game release]; [startPositions release]; [nonJumpEndPositions release]; [super dealloc]; } @end @implementation AtaxxAI -(NSEnumerator *)enumeratorForMovesToConsiderForGame:(Game *)game { return [[[AtaxxAIGoodMoveEnumerator alloc] initWithGame:game] autorelease]; } @end gridlock.app-1.10/AtaxxGame.m0000644000175000000000000001215610342202541015062 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "AtaxxGame.h" @implementation AtaxxGame -(void)reset { [super reset]; [self createGridFromConfiguration]; // handle random walls if ([[self configurationInfo] objectForKey:@"randomWalls"]) { int nwalls = [[[[self configurationInfo] objectForKey:@"randomWalls"] objectForKey:@"count"] intValue]; NSString *symmetry = [[[self configurationInfo] objectForKey:@"randomWalls"] objectForKey:@"symmetry"]; int n=0; while (n1 ? [positions objectAtIndex:0] : nil; DCHypergridPosition *pos1 = [positions lastObject]; // if this is a jump, remove the starting cell if (pos0 && (abs([pos1 row]-[pos0 row])>1 || abs([pos1 column]-[pos0 column])>1)) { [[self futureGrid] setValue:0 atPosition:pos0]; } // the destination cell is always filled [[self futureGrid] setValue:pnum atPosition:pos1]; // change all neighbors of the destination { int r = [pos1 row]; int c = [pos1 column]; int dr; for(dr=-1; dr<=1; dr++) { if (r+dr>=0 && r+dr<[self numberOfRows]) { int dc; for(dc=-1; dc<=1; dc++) { if (c+dc>=0 && c+dc<[self numberOfColumns]) { if (oppnum==[self valueAtRow:r+dr column:c+dc]) { [[self futureGrid] setValue:pnum atRow:r+dr column:c+dc]; } } } } } } return YES; } } -(BOOL)isGameOver { // game is over if all cells are filled, or if either player has no cells // therefore, game is not over if and only if grid contains at least 1 cell with each of 0,1,2. return (![grid hasCellWithValue:0] || ![grid hasCellWithValue:1] || ![grid hasCellWithValue:2]); } -(NSArray *)allValidMoveSequences { NSMutableArray *sequences = [NSMutableArray array]; NSEnumerator *posEnum = [[self grid] enumeratorForPositionsWithValue:[self currentPlayerNumber]]; id position; while (position=[posEnum nextObject]) { NSArray *neighbors = [grid neighborsOfPosition:position distance:2]; NSEnumerator *nenum = [neighbors objectEnumerator]; id npos; while (npos=[nenum nextObject]) { if ([self valueAtPosition:npos]==0) { [sequences addObject:[NSArray arrayWithObjects:position,npos,nil]]; } } } if ([sequences count]==0) [sequences addObject:[NSArray array]]; return sequences; } -(BOOL)showScores { return YES; } -(NSString *)descriptionForMove:(NSArray *)move { // If it's a normal move (not a jump), the start position doesn't matter, so only show the second // This also keeps the display consistent because of AtaxxAI optimizations that sometimes return // only the final position. if ([move count]==2) { id pos0 = [move objectAtIndex:0]; id pos1 = [move objectAtIndex:1]; if (abs([pos0 row]-[pos1 row])<=1 && abs([pos0 column]-[pos1 column])<=1) { return [super descriptionForMove:[pos1 arrayWithSelf_]]; } } return [super descriptionForMove:move]; } @end gridlock.app-1.10/AtaxxViewDelegate.m0000644000175000000000000000303607735511406016572 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "AtaxxViewDelegate.h" #import #import "ImageStore.h" @implementation AtaxxViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game { if (value==-1) { NSImage *wallImage = [[ImageStore defaultStore] bitmapImageWithName:@"wall.tiff" size:rect.size]; [wallImage compositeToPoint:rect.origin operation:NSCompositeSourceOver]; return YES; } return NO; } @end gridlock.app-1.10/BoardView.m0000644000175000000000000003501510342202541015064 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "BoardView.h" #import "Preferences.h" #import "CocoaAdditions.h" #import "ImageStore.h" static inline int max(int a, int b) { return (a>b) ? a : b; } @implementation BoardView -(id)init { if (self=[super init]) { animationFrames = 6; inAnimation = NO; pieceImages = [[NSMutableDictionary alloc] init]; } return self; } -(void)awakeFromNib { [self updateColors:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateColors:) name:@"PlayerColorsChangedNotification" object:nil]; // we need to know when our window closes so we can stop the timers, otherwise nasty stuff happens [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowClosed:) name:NSWindowWillCloseNotification object:[self window]]; [self addTrackingRect:[self bounds] owner:self userData:nil assumeInside:NO]; [[self window] setAcceptsMouseMovedEvents:YES]; } -(void)dealloc { //NSLog(@"BoardView dealloc"); [flashingPositions release]; [pieceImages release]; [animationTimer invalidate]; [flashTimer invalidate]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; } // timers retain their targets, so when our window is closed we need to invalidate them -(void)windowClosed:(NSNotification *)note { if ([self window]==[note object]) { [animationTimer invalidate]; animationTimer = nil; [flashTimer invalidate]; flashTimer = nil; } } idAccessor(gameHistory, setGameHistory) idAccessor(lastMouseOverPosition, setLastMouseOverPosition) idAccessor(animatingPositions, setAnimatingPositions) -(Game *)game { return [[self gameHistory] currentGame]; } -(NSRect)updateRectForPositions:(NSArray *)positions { NSEnumerator *pe = [positions objectEnumerator]; id pos; NSRect updateRect = NSMakeRect(0,0,0,0); while (pos=[pe nextObject]) { updateRect = NSUnionRect(updateRect, [self rectForGridPosition:pos]); } if (!NSIsEmptyRect(updateRect)) { float yoff = [self cellHeight]/2; float xoff = [self cellWidth]/2; updateRect.origin.x -= xoff; updateRect.origin.y -= yoff; updateRect.size.width += 2*xoff; updateRect.size.height += 2*yoff; } return updateRect; } -(NSArray *)highlightedPositions { return highlightedPositions; } -(void)setHighlightedPositions:(NSArray *)positions { if (![[self highlightedPositions] isEqual:positions]) { // compute intersection of old and new highlighted positions to minimize drawing NSMutableArray *updatePositions = [NSMutableArray array]; if (highlightedPositions) [updatePositions addObjectsFromArray:highlightedPositions]; if (positions) [updatePositions addObjectsFromArray:positions]; [highlightedPositions autorelease]; highlightedPositions = [positions retain]; [self setNeedsDisplayInRect:[self updateRectForPositions:updatePositions]]; } } // assigned via nib connection, target is not retained -(id )eventTarget { return eventTarget; } -(void)setEventTarget:(id )obj { eventTarget = obj; } // delegate *is* retained -(id )delegate { return delegate; } -(void)setDelegate:(id)value { [delegate autorelease]; delegate = [value retain]; } -(void)drawHighlightedPositions:(NSArray *)positions { NSEnumerator *pe = [positions objectEnumerator]; id pos; while (pos=[pe nextObject]) { NSRect cellRect = [self rectForGridPosition:pos]; NSBezierPath *path = [NSBezierPath bezierPathWithRect:cellRect]; [path setLineWidth:3.0]; [[[Preferences sharedInstance] highlightColorForPlayerNumber:[[self game] currentPlayerNumber]] set]; [path stroke]; } } - (void)drawRect:(NSRect)aRect { if ([self game]) { int r, c; int maxr = [[self game] numberOfRows]; int maxc = [[self game] numberOfColumns]; for(r=0; r0) { NSImage *image = [[ImageStore defaultStore] pieceImageForPlayer:value withSize:rect.size]; [image compositeToPoint:rect.origin operation:NSCompositeSourceOver]; } } // indicate if value changed if ([self shouldDrawPreviousMoveIndicatorForPosition:pos]) { NSRect changeRect = NSInsetRect(rect, 4*rect.size.width/9, 4*rect.size.height/9); [[NSColor blackColor] set]; [[NSBezierPath bezierPathWithOvalInRect:changeRect] fill]; } } -(NSImage *)cellImageForValue:(int)value atPosition:(id)pos withSize:(NSSize)size { NSImage *image = [[[NSImage alloc] initWithSize:size] autorelease]; NSRect imageRect = NSMakeRect(0,0,size.width,size.height); [image lockFocus]; [self drawCellWithValue:value atPosition:pos inRect:imageRect]; [image unlockFocus]; return image; } -(BOOL)isPositionFlashing:(id)pos { return (flashTimer!=nil && flashState==YES && [[self flashingPositions] containsObject:pos]); } -(void)drawCellAtPosition:(DCHypergridPosition *)pos { NSRect cellFrameRect = [self rectForGridPosition:pos]; NSRect cellRect = cellFrameRect; int cellvalue = 0; int nextvalue = 0; // inset cellRect so it fits inside cellFrameRect ++cellRect.origin.x; ++cellRect.origin.y; cellRect.size.width -= 2; cellRect.size.height -= 2; if ([self isPositionFlashing:pos]) { [self drawCellWithValue:0 atPosition:pos inRect:cellRect]; } else { cellvalue = nextvalue = [[self game] valueAtPosition:pos]; if (inAnimation) { if ([[Preferences sharedInstance] animateCapturedPieces]==NO || [immediateChangePositions containsObject:pos]) { // draw future value immediately cellvalue = nextvalue = [[self game] futureValueAtPosition:pos]; } else if ([[self animatingPositions] containsObject:pos]) { nextvalue = [[self game] futureValueAtPosition:pos]; } } if (inAnimation && cellvalue!=nextvalue) { // draw cell in transition float frac = ((float)animationFrameCounter)/animationFrames; NSImage *fromImage = [self cellImageForValue:cellvalue atPosition:pos withSize:cellRect.size]; NSImage *toImage = [self cellImageForValue:nextvalue atPosition:pos withSize:cellRect.size]; [fromImage compositeToPoint:cellRect.origin operation:NSCompositeSourceOver]; [toImage dissolveToPoint:cellRect.origin fraction:frac]; } else { // draw static cell [self drawCellWithValue:cellvalue atPosition:pos inRect:cellRect]; } } // draw the frame last so it always goes on top [[NSColor blackColor] set]; [NSBezierPath strokeRect:cellFrameRect]; } -(DCHypergridPosition *)positionForEvent:(NSEvent *)event { NSRect bounds = [self bounds]; NSPoint pointInWindow = [event locationInWindow]; NSPoint pointInView = [self convertPoint:pointInWindow fromView:nil]; int c = (pointInView.x-bounds.origin.x)/([self cellWidth]); int r = (pointInView.y-bounds.origin.y)/([self cellHeight]); return [DCHypergridPosition positionWithRow:r column:c]; } -(void)mouseDown:(NSEvent *)event { DCHypergridPosition *position = [self positionForEvent:event]; if ([[self game] isPositionValid:position]) { [[self eventTarget] boardView:self clickedAtPosition:position]; [self setLastMouseOverPosition:nil]; } } -(void)mouseEntered:(NSEvent *)event { //NSLog(@"mouseEntered"); [[self window] makeFirstResponder:self]; } -(void)mouseExited:(NSEvent *)event { //NSLog(@"mouseExited"); [[self eventTarget] boardView:self mouseMovedOverPosition:nil]; [self setLastMouseOverPosition:nil]; } -(void)mouseMoved:(NSEvent *)event { DCHypergridPosition *position = [self positionForEvent:event]; if ([[self game] isPositionValid:position] && ![position isEqual:[self lastMouseOverPosition]]) { [[self eventTarget] boardView:self mouseMovedOverPosition:position]; [self setLastMouseOverPosition:position]; } } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)becomeFirstResponder { [[self window] setAcceptsMouseMovedEvents: YES]; return YES; } - (BOOL)resignFirstResponder { [[self window] setAcceptsMouseMovedEvents: NO]; return YES; } // animation support -(id)animationCallbackObject { return animationCallbackObject; } -(void)setAnimationCallbackObject:(id)obj { [animationCallbackObject release]; animationCallbackObject = [obj retain]; } -(void)animationTimerFired:(NSTimer *)timer { NSRect updateRect = [self updateRectForPositions:[self animatingPositions]]; if (timer!=animationTimer) return; ++animationFrameCounter; //NSLog(@"animationTimerFired:%d %d",animationFrameCounter, animationFrames); if (animationFrameCounter>=animationFrames || ![[self animatingPositions] count]) { //NSLog(@"Animation done"); inAnimation = NO; [animationTimer invalidate]; animationTimer = nil; [self finishMove]; } // compute minimal rectangle to redraw [self setNeedsDisplayInRect:updateRect]; } -(void)finishMove { [[self eventTarget] boardView:self finishedMoveAnimation:animationCallbackObject]; [self setAnimationCallbackObject:nil]; [self setAnimatingPositions:nil]; [immediateChangePositions release]; immediateChangePositions = nil; [self setLastMouseOverPosition:nil]; } -(void)beginMoveAnimationForPositions:(NSArray *)animPositions immediatelyChangingPositions:(NSArray *)immdtPositions callbackObject:(id)obj { BOOL disableAnimation = NO; [self setAnimationCallbackObject:obj]; [self setAnimatingPositions:animPositions]; [immediateChangePositions release]; immediateChangePositions = [[immdtPositions arrayByIntersectingArray_:animPositions] retain]; inAnimation = YES; animationFrameCounter = 0; animationFrames = 6; // abort if game doesn't support animation disableAnimation = ([[self delegate] respondsToSelector:@selector(disableAnimation)] && [[self delegate] disableAnimation]); if (!disableAnimation && [[self animatingPositions] count]>[immediateChangePositions count]) { animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSEventTrackingRunLoopMode]; } else { inAnimation = NO; [self finishMove]; } [self setNeedsDisplay:YES]; } -(NSArray *)flashingPositions { return flashingPositions; } -(void)setFlashingPositions:(NSArray *)positions { if ([positions count]) { [flashingPositions release]; flashingPositions = [positions retain]; if (!flashTimer) { flashState = NO; flashTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(flashTimerFired:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:flashTimer forMode:NSEventTrackingRunLoopMode]; } } else { [flashingPositions release]; flashingPositions = nil; [flashTimer invalidate]; flashTimer = nil; } } -(void)flashTimerFired:(NSTimer *)timer { if (timer!=flashTimer) return; flashState = !flashState; [self setNeedsDisplayInRect:[self updateRectForPositions:[self flashingPositions]]]; } @end gridlock.app-1.10/BreakthroughAI.m0000644000175000000000000002635110342202541016044 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* There is no "BreakthroughGame" class because the rules can be handled by HexapawnGame */ #import "BreakthroughAI.h" #import "DCHypergridPosition.h" @implementation BreakthroughAI -(int)rowIncrementForPlayer:(int)pnum { return (pnum==1) ? 1 : -1; } -(int)piecesSupportingPostion:(id)pos forPlayer:(int)pnum inGame:(Game *)game { // look behind left and right int count=0; int dr = [self rowIncrementForPlayer:pnum]; int r = [pos row]-dr; if (r>=0 && r<[game numberOfRows]) { int c1= [pos column]+1; int c2= [pos column]-1; if (c1>=0 && c1<[game numberOfColumns] && [game valueAtRow:r column:c1]==pnum) count++; if (c2>=0 && c2<[game numberOfColumns] && [game valueAtRow:r column:c2]==pnum) count++; } return count; } /** Returns the number of opposing pieces in the "light cone" of the given position; that is, pieces which fall within a 45 degree angle (column difference<=row difference). Any pieces outside this cone cannot affect the piece at the given position. */ -(int)numberOfOpposingPiecesRelevantToPosition:(id)pos forPlayer:(int)pnum inGame:(Game *)game { int count = 0; int oppval = [game playerNumberMovingAfterPlayer:pnum]; int dr = [self rowIncrementForPlayer:pnum]; int r,c; int maxr = [game numberOfRows]; int maxc = [game numberOfColumns]; int maxoffc = 0; for(r=[pos row]+dr; r>=0 && r=0 && c3) { int oppval = [game playerNumberMovingAfterPlayer:pnum]; int dr = [self rowIncrementForPlayer:pnum]; int r,c; int maxr = [game numberOfRows]; int maxc = [game numberOfColumns]; int maxoffc = 0; int count = 0; // 2 points for same column, 1 for diagonal, 2 otherwise //int leftCount = 0; //int rightCount = 0; for(r=[pos row]+dr; r>=0 && r=0 && c=[pos column]) rightCount += defvalue; if (c<=[pos column]) leftCount += defvalue; */ // optimization since no side counts if (count>=bonuscount) return 0; } } } /* // penalize for not having 3 points left or right (disabled, see above) if (leftCount<=sidelimit && [pos column]>0) count-=1; if (rightCount<=sidelimit && [pos column]<[game numberOfColumns]-1) count-=1; if (count<0) count=0; */ if (count>=bonuscount) return 0; else return bonuses[count]; } else return 0; } -(int)playerControllingPosition:(id)pos inGame:(Game *)game { // check each of the four cells that can capture this position int p1threats = [self piecesSupportingPostion:pos forPlayer:1 inGame:game]; int p2threats = [self piecesSupportingPostion:pos forPlayer:2 inGame:game]; // if threats are equal, it's controlled by whoever has a piece there if (p1threats>p2threats) return 1; else if (p2threats>p1threats) return 2; else return [game valueAtPosition:pos]; } -(float)controlFactorForPosition:(id)pos forPlayer:(int)pnum inGame:(Game *)game { int oppnum = [game playerNumberMovingAfterPlayer:pnum]; float control = 0; int value = [game valueAtPosition:pos]; //int relativeRow = (pnum==1) ? [pos row] : [game numberOfRows]-1-[pos row]; if (value==pnum) control++; else if (value==oppnum) control--; control += [self piecesSupportingPostion:pos forPlayer:pnum inGame:game]; control -= [self piecesSupportingPostion:pos forPlayer:oppnum inGame:game]; // "tie" on an occupied cell goes to the current player if (value!=0 && control==0) { control = ([game currentPlayerNumber]==pnum) ? 1 : -1; } if (control>1) control=1; if (control<-1) control = -1; control *= (1+[self positionalBonusForPosition:pos forPlayer:pnum inGame:game]); return control; /* if (control>0 && relativeRow>3) { int p = [self numberOfOpposingPiecesRelevantToPosition:pos forPlayer:pnum inGame:game]; if (p==0) control*=3.0; else if (p==1) control*=2.0; else if (p==2) control*=1.5; */ // assign bonus for neighboring cells // actually it looks like this causes gaps /* if (relativeRow>4) { int neighbors = 0; NSEnumerator *ne = [[[game grid] neighborsOfPosition:pos distance:1] objectEnumerator]; id npos; while (npos=[ne nextObject]) { if ([game valueAtPosition:npos]==pnum) neighbors++; } control *= 1+(0.05*neighbors); } } */ } -(NSArray *)_emptyCellsToCheckFromPosition:(id)pos forPlayer:(int)pnum inGame:(Game *)game { int dr = [self rowIncrementForPlayer:pnum]; int c = [pos column]; int r = [pos row]; int maxc = [game numberOfColumns]; int maxr = [game numberOfRows]; NSMutableArray *array = [NSMutableArray array]; // check (r+dr,c-1),(r+dr,c),(r+dr,c+1) if (r+dr>=0 && r+dr0) [array addObject:[DCHypergridPosition positionWithRow:r+dr column:c-1]]; [array addObject:[DCHypergridPosition positionWithRow:r+dr column:c]]; if (c0) { //[emptyCellThreats addObjectsFromArray:[self _emptyCellsToCheckFromPosition:pos forPlayer:pnum inGame:game]]; utility += weight*control; utility += pieceWeight; } // any credit for pieces that are outnumbered? } /* // this doesn't seem to help if (emptyMultiplier>0) { pe = [emptyCellThreats objectEnumerator]; while (pos=[pe nextObject]) { int index = (pnum==1) ? [pos row] : [game numberOfRows]-1-[pos row]; int weight = index[(cpnum==pnum) ? myturnweights : oppturnweights]; int control = [self controlFactorForPosition:pos forPlayer:pnum inGame:game]; if (control>0) { utility += weight*control*emptyMultiplier; } } } */ return (int)utility; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { return [self _threatWeightForGame:game player:pnum] - [self _threatWeightForGame:game player:[game playerNumberMovingAfterPlayer:pnum]]; } // for some reason, a depth of 2 is actually worse than 1. // not in this class, but it takes way too long to do 3-2-1 evaluation -(int)searchDepthForLevel:(int)d { if (use311) return (d%2==0) ? d-1 : d; else return d; } -(NSArray *)movesToConsiderForGame:(Game *)game { // if we can win, win // otherwise stop opponent if he's about to win int pnum = [game currentPlayerNumber]; int oppnum = [game nextPlayerNumber]; int dr = [self rowIncrementForPlayer:pnum]; int lastrow = (pnum==1) ? [game numberOfRows]-1 : 0; int nextlastrow = lastrow - dr; int firstrow = (pnum==1) ? 0 : [game numberOfRows]-1; int secondrow = firstrow+dr; int maxc = [game numberOfColumns]; int c; NSMutableArray *blockmoves = nil; // scan our next to last row for win for(c=0; c0 && [game valueAtRow:firstrow column:c-1]==pnum) { id move = [NSArray arrayWithObjects:[DCHypergridPosition positionWithRow:firstrow column:c-1], [DCHypergridPosition positionWithRow:secondrow column:c], nil]; if (!blockmoves) blockmoves = [NSMutableArray array]; [blockmoves addObject:move]; } if (cc2) ? NSOrderedDescending : NSOrderedAscending; } @implementation NSObject (DCArchivingAdditions) -(NSData *)archivedData_ { return [NSArchiver archivedDataWithRootObject:self]; } +(id)objectWithArchivedData_:(NSData *)data { return [NSUnarchiver unarchiveObjectWithData:data]; } @end @implementation NSUserDefaults (DCArchivingAdditions) -(id)archivedObjectForKey:(id)key { return [NSUnarchiver unarchiveObjectWithData:[self objectForKey:key]]; } -(void)setArchivedObject:(id)obj forKey:(id)key { [self setObject:[obj archivedData_] forKey:key]; } @end @implementation NSArray (DCMiscAdditions) -(id)objectWithValue:(id)searchValue forSelector:(SEL)selector withArgument:(id)arg { NSEnumerator *e = [self objectEnumerator]; id obj; while (obj=[e nextObject]) { id value = [obj performSelector:selector withObject:arg]; if (value==nil && searchValue==nil) return obj; if ([value isEqual:searchValue]) return obj; } return nil; } -(NSArray *)arrayByIntersectingArray_:(NSArray *)array { NSEnumerator *e = [self objectEnumerator]; NSMutableArray *intersection = [NSMutableArray array]; id obj; while (obj=[e nextObject]) { if ([array containsObject:obj]) { [intersection addObject:obj]; } } return intersection; } -(NSArray *)arrayByRemovingObjectsFromArray_:(NSArray *)array { NSMutableArray *result = [NSMutableArray array]; NSEnumerator *e = [self objectEnumerator]; id obj; while (obj=[e nextObject]) { if (![array containsObject:obj]) { [result addObject:obj]; } } return result; } -(NSArray *)valuesByObjectsPerformingSelector:(SEL)sel { NSMutableArray *result = [NSMutableArray array]; NSEnumerator *e = [self objectEnumerator]; id obj; while (obj=[e nextObject]) { [result addObject:[obj performSelector:sel]]; } return result; } -(NSArray *)valuesByObjectsPerformingSelector:(SEL)sel withObject_:(id)arg { NSMutableArray *result = [NSMutableArray array]; NSEnumerator *e = [self objectEnumerator]; id obj; while (obj=[e nextObject]) { [result addObject:[obj performSelector:sel withObject:arg]]; } return result; } -(NSArray *)arrayWithPrefix_:(NSArray *)prefix { if ([prefix count]==0) return NO; NSEnumerator *e = [self objectEnumerator]; id obj; while (obj=[e nextObject]) { if ([obj isKindOfClass:[NSArray class]]) { if ([prefix count]<[obj count] && [prefix isEqual:[obj subarrayWithRange:NSMakeRange(0,[prefix count])]]) { return obj; } } } return nil; } -(NSArray *)arrayWithObjectsInRandomOrder_ { NSMutableArray *array = [NSMutableArray arrayWithArray:self]; [array randomizeObjects_]; return array; } -(NSArray *)sortedArrayUsingKey_:(NSString *)key { return [self sortedArrayUsingFunction:keyCompareFunc context:key]; } -(NSArray *)sortedArrayByCount_ { return [self sortedArrayUsingFunction:countCompareFunc context:NULL]; } @end @implementation NSMutableArray (DCMiscAdditions) -(void)randomizeObjects_ { int count = [self count]; int i; for(i=0; i0) [self exchangeObjectAtIndex:i withObjectAtIndex:i+incr]; } } -(void)sortArrayUsingKey_:(NSString *)key { [self sortUsingFunction:keyCompareFunc context:key]; } -(void)sortArrayByCount_ { [self sortUsingFunction:countCompareFunc context:NULL]; } @end @implementation NSPopUpButton (DCAppKitAdditions) -(void)setItemTitles:(NSArray *)titles representedObjects_:(NSArray *)objects { int i,len=[titles count]; [self removeAllItems]; for(i=0; i0 && [[threat objectForKey:@"openAfter"] intValue]>0); if (length>=[game winningLength]) length=[game winningLength]; total += weights[2*length + openings]; } return total; } @end gridlock.app-1.10/ConnectFourGame.m0000644000175000000000000000322710342202541016221 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ConnectFourGame.h" static int WIN_LENGTH = 4; @implementation ConnectFourGame -(int)winningLength { return WIN_LENGTH; } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:0]; id pos; while (pos=[pe nextObject]) { // valid position if it's on the bottom or the row directly beneath it is not empty if ([pos row]==0 || [self valueAtRow:[pos row]-1 column:[pos column]]!=0) { [moves addObject:[pos arrayWithSelf_]]; } } return moves; } @end gridlock.app-1.10/DCHypergrid.m0000644000175000000000000002360510342207042015351 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "DCHypergrid.h" #import "DCHypergridPositionEnumerator.h" #import "CocoaAdditions.h" @implementation DCHypergrid -(id)initWithNumberOfDimensions:(int)numdim sizes:(int *)sizes { self = [super init]; if (self) { _cgrid = hypergrid_create(numdim, sizes); } return self; } -(id)initWithCHypergrid:(hypergrid *)gridptr { self = [super init]; if (self) { _cgrid = hypergrid_copy(gridptr); } return self; } -(id)copy { return [[DCHypergrid alloc] initWithCHypergrid:_cgrid]; } -(void)copyValuesToGrid:(DCHypergrid *)gridCopy { memcpy([gridCopy cHypergrid]->grid_data, [self cHypergrid]->grid_data, [self numberOfCells]*sizeof(gridvalue_t)); } -(int)numberOfDimensions { return _cgrid->num_dimensions; } -(int)numberOfCells { return _cgrid->num_cells; } -(gridvalue_t)valueAtPosition:(DCHypergridPosition *)coords { // optimization for 2 dimensions, used in Gridlock to optimize game evaluations if (_cgrid->num_dimensions==2) { int index = coords->_data[0]*_cgrid->dimension_sizes[1] + coords->_data[1]; return _cgrid->grid_data[index]; } return hypergrid_get_value(_cgrid, [coords cArray]); } -(gridvalue_t)valueAtCoordinateArray:(int *)array { // optimization for 2 dimensions, used in Gridlock to optimize game evaluations if (_cgrid->num_dimensions==2) { int index = array[0]*_cgrid->dimension_sizes[1] + array[1]; return _cgrid->grid_data[index]; } return hypergrid_get_value(_cgrid, array); } -(id)setValue:(gridvalue_t)value atPosition:(DCHypergridPosition *)coords { hypergrid_set_value(_cgrid, [coords cArray], value); return self; } -(id)setValue:(gridvalue_t)value atCoordinateArray:(int *)array { hypergrid_set_value(_cgrid, array, value); return self; } -(void)setValue:(gridvalue_t)value atPositions:(NSArray *)positions { int i; for(i=[positions count]-1; i>=0; i--) { id pos = [positions objectAtIndex:i]; hypergrid_set_value(_cgrid, [pos cArray], value); } } -(BOOL)isValidPosition:(DCHypergridPosition *)position { return hypergrid_coords_isvalid(_cgrid, [position cArray]); } -(BOOL)isValidCoordinateArray:(int *)array { return hypergrid_coords_isvalid(_cgrid, array); } -(int)sizeOfDimension:(int)dim { return hypergrid_dimension_size(_cgrid, dim); } -(int)nonzeroNeighborsOfPosition:(DCHypergridPosition *)coords { return hypergrid_neighbor_count(_cgrid, [coords cArray], 0, 0, 1); } -(int)nonzeroNeighborsOfPosition:(DCHypergridPosition *)coords wrapping:(BOOL)wrap { return hypergrid_neighbor_count(_cgrid, [coords cArray], 0, 0, wrap); } -(int)numberOfNeighborsOfPosition:(DCHypergridPosition *)pos withValue:(int)value { return hypergrid_neighbor_count(_cgrid, [pos cArray], 1, value, 0); } -(int)numberOfCellsWithValue:(int)value { return hypergrid_value_count(_cgrid, value); } -(BOOL)hasCellWithValue:(int)value { return (hypergrid_value_exists(_cgrid, value)!=0); } -(BOOL)isEqualToHypergrid:(DCHypergrid *)cmp { return hypergrid_equal([self cHypergrid], [cmp cHypergrid]); } -(NSArray *)neighborsOfPosition:(DCHypergridPosition *)coords distance:(int)dist { NSMutableArray *array; int dim = [self numberOfDimensions]; if (dim==2) { int dr, dc; int r=[coords row], c=[coords column]; // max neighbors = (2*dist+1)^2 = 4d^2+4d+1 = 4d(d+1)+1 array = [NSMutableArray arrayWithCapacity:4*dist*(dist+1)+1]; for(dr=-dist; dr<=dist; dr++) { int newr = r+dr; for(dc=-dist; dc<=dist; dc++) { int newc = c+dc; if ([self isValidRow:newr column:newc]) { [array addObject:[DCHypergridPosition positionWithRow:newr column:newc]]; } } } } else { int **neighborlist; int count; int i; array = [NSMutableArray array]; neighborlist = hypergrid_neighbors([self cHypergrid], [coords cArray], dist, &count); for(i=0; inum_dimensions, sizeof(int)); DCHypergridPosition *position = nil; if (hypergrid_get_value(_cgrid, _coords)==value) { position = [DCHypergridPosition positionWithSize:_cgrid->num_dimensions data:_coords]; } while (!position && hypergrid_coords_increment(_cgrid, _coords)) { if (hypergrid_get_value(_cgrid, _coords)==value) { position = [DCHypergridPosition positionWithSize:_cgrid->num_dimensions data:_coords]; } } free(_coords); return position; } -(NSArray *)allPositionsWithValue:(int)value { return [[self enumeratorForPositionsWithValue:value] allObjects]; } -(void)addPositionsToGroup:(NSMutableSet *)group withValue:(int)pnum startingFromPosition:(id)pos onlyOrthoganal:(BOOL)ortho { // this only works for 2d grids currently static int orthoDeltas[] = {+1,0, -1,0, 0,+1, 0,-1}; static int diagDeltas[] = {+1,+1, +1,0, +1,-1, 0,+1, 0,-1, -1,+1, -1,0, -1,-1}; [group addObject:pos]; int *deltas = (ortho) ? orthoDeltas : diagDeltas; int numd = (ortho) ? 4 : 8; int r=[pos row], c=[pos column]; int i; for(i=0; i #include #include "hypergrid.h" #include "string.h" static DCHypergridPosition **_cachedPositions = NULL; static int CACHE_MIN = -25; static int CACHE_MAX = +25; static int CACHE_SIZE = 50; // private subclasses used for cached positions to avoid retains and releases @interface DCArrayWithCachedPosition : NSArray { id position; } @end @implementation DCArrayWithCachedPosition -(id)initWithPosition:(id)pos { self = [super init]; position = pos; return self; } // this initializer is needed for GNUstep #ifdef GNUSTEP -(id)initWithObjects:(id *)objects count:(unsigned)count { // GNUstep calls this from -[NSArray init] with arguments of nil and 0 if (count==0) return self; else [NSException raise:@"IndexOutOfBounds" format:@"%@: count (%d) must be 0 for %@", NSStringFromSelector(_cmd), index, NSStringFromClass([self class])]; return nil; } #endif -(unsigned)count { return 1; } -(id)objectAtIndex:(unsigned)index { if (index==0) return position; else [NSException raise:@"IndexOutOfBounds" format:@"%@: index (%d) must be 0 for %@", NSStringFromSelector(_cmd), index, NSStringFromClass([self class])]; return nil; } -(id)retain { return self; } -(void)release { return; } -(id)autorelease { return self; } @end @interface DCCachedHypergridPosition : DCHypergridPosition { NSArray *array; } @end @implementation DCCachedHypergridPosition : DCHypergridPosition -(id)retain { return self; } -(void)release { return; } -(id)autorelease { return self; } -(NSArray *)arrayWithSelf_ { if (!array) { array = [[DCArrayWithCachedPosition alloc] initWithPosition:self]; } return array; } @end @implementation DCHypergridPosition -(id)initWithSize:(int)cap { _numberOfDimensions = cap; _data = (int *)calloc(cap, sizeof(int)); return self; } -(id)initWithSize:(int)cap data:(int *)values { _numberOfDimensions = cap; _data = (int *)calloc(cap, sizeof(int)); memcpy(_data, values, cap*(sizeof(int))); return self; } -(id)initWithRow:(int)r column:(int)c { int values[] = {r,c}; return [self initWithSize:2 data:values]; } +(void)_fillCache { if (!_cachedPositions) { int r,c; int index=0; int numCachedPositions = CACHE_SIZE*CACHE_SIZE; _cachedPositions = (DCHypergridPosition **)malloc(numCachedPositions*sizeof(DCHypergridPosition *)); for(r=0; r=CACHE_MIN && values[0]=CACHE_MIN && values[1]=CACHE_MIN && r=CACHE_MIN && cv1) return NSOrderedAscending; if (v21) { int i; [configurationPopup removeAllItems]; [configurationPopup setEnabled:YES]; for(i=0; i<[variationDisplayNames count]; i++) { [configurationPopup addItemWithTitle:[variationDisplayNames objectAtIndex:i]]; [[configurationPopup lastItem] setRepresentedObject:[variationNames objectAtIndex:i]]; } [configurationPopup selectItemWithTitle:[[self gameConfiguration] variationDisplayName]]; } else { [configurationPopup removeAllItems]; [configurationPopup addItemWithTitle:NSLocalizedString(@"NoVariationsTitle", nil)]; [configurationPopup setEnabled:NO]; } } -(void)gameStateChanged { [self clearMovePositions]; [self updateScores]; [boardView setHighlightedPositions:nil]; [boardView setFlashingPositions:nil]; [boardView setNeedsDisplay:YES]; [self cancelPendingAIMoves]; if ([[self game] isGameOver]) { [self doGameOver]; } else { [statusField setStringValue:@""]; if ([self shouldMakeAIMove]) { [self makeAIMove]; } else { [passButton setEnabled:[[self game] isPassValid]]; } } [moveRecordTable reloadData]; } -(BOOL)hasStartedMove { return ([[self movePositions] count]>0); } -(NSArray *)movePositions { return movePositions; } -(void)appendMovePosition:(id)position { [movePositions addObject:position]; } -(void)setMovePositions:(NSMutableArray *)positions { [movePositions autorelease]; movePositions = [positions retain]; } -(void)removeLastPositionFromMove { [movePositions removeLastObject]; } -(void)clearMovePositions { [movePositions removeAllObjects]; } -(void)updateScores { int pnum = [[self game] currentPlayerNumber]; if ([[self game] showScores]) { [player1ScoreField setIntValue:[[self game] scoreForPlayer:1]]; [player2ScoreField setIntValue:[[self game] scoreForPlayer:2]]; } [player1TurnView setVisible:(pnum==1)]; [player2TurnView setVisible:(pnum==2)]; } -(void)doGameOver { int wpnum = [[self game] winningPlayer]; if (wpnum==0) { NSString *msg = [[NSBundle mainBundle] localizedStringForKey:@"TieMessage" value:@"Tie" table:nil]; [statusField setStringValue:msg]; } else { NSString *msg = [[NSBundle mainBundle] localizedStringForKey:@"WinMessage" value:@"Player %d wins" table:nil]; [statusField setStringValue:[NSString stringWithFormat:msg,wpnum]]; } [boardView setFlashingPositions:[[self game] positionsOfWinningPieces]]; [passButton setEnabled:NO]; //NSLog(@"Game Over: %d %d", [game scoreForPlayer:1], [game scoreForPlayer:2]); [playerWins replaceObjectAtIndex:wpnum withObject:[NSNumber numberWithInt:1+[[playerWins objectAtIndex:wpnum] intValue]]]; [p1Wins setIntValue:[[playerWins objectAtIndex:1] intValue]]; [p2Wins setIntValue:[[playerWins objectAtIndex:2] intValue]]; /* if (FASTPLAY) { NSLog(@"Total record: %@", [playerWins componentsJoinedByString:@","]); if ([playerAIs count]==[[self game] numberOfPlayers]) { [self restartGame]; } } */ } -(void)doMoveSequence:(NSArray *)positions { // notify network players if this move wasn't received from the network //NSLog(@"Current player=%d", [[self game] currentPlayerNumber]); if (nil==[[self gameState] netConnectionForPlayer:[[self game] currentPlayerNumber]]) { [self sendMoveToNetworkPlayers:positions]; } [[self game] prepareMoveSequence:positions]; inAnimation = YES; { NSArray *positionsNotAnimating = [[Preferences sharedInstance] animateCapturedPieces] ? positions : [[self game] positionsOfAllChangingCells]; [boardView setHighlightedPositions:nil]; [boardView beginMoveAnimationForPositions:[[self game] positionsOfAllChangingCells] immediatelyChangingPositions:positionsNotAnimating callbackObject:positions]; } } -(BOOL)isWaitingForHumanMove { return (![[self game] isGameOver] && !inAnimation && [[self gameState] isCurrentPlayerHuman]); } -(void)boardView:(BoardView *)view clickedAtPosition:(DCHypergridPosition *)position { if (boardView && boardView==view && [self isWaitingForHumanMove]) { int row = [position row]; int col = [position column]; if (row>=0 && row<[[self game] numberOfRows] && col>=0 && col<[[self game] numberOfColumns]) { id position = [DCHypergridPosition positionWithRow:row column:col]; //NSLog(@"Got click at row:%d col:%d", row, col); [self appendMovePosition:position]; if ([[self game] isCompleteMoveSequenceValid:[self movePositions]]) { // FIXME: if the sequence is also a valid partial move, we should require confirmation //NSLog(@"Executing move"); [self doMoveSequence:[self movePositions]]; } else if ([[self game] isPartialMoveSequenceValid:[self movePositions]]) { // do nothing, keep added position //NSLog(@"Added to move sequence"); } else { // not a valid move, but check if it's a valid move or start by itself NSMutableArray *newArray = [NSMutableArray arrayWithObject:position]; [self removeLastPositionFromMove]; if ([[self game] isPartialMoveSequenceValid:newArray]) { //NSLog(@"Started new move"); [self setMovePositions:newArray]; } else { // we don't want to execute it if it's a complete move [self clearMovePositions]; } [boardView setHighlightedPositions:[[[self movePositions] copy] autorelease]]; } } } } -(void)recordAndExecuteMove:(NSArray *)move { [[self gameHistory] recordAndExecuteMove:move]; } -(NSArray *)humanPlayerNumbers { NSMutableArray *humanNumbers = [NSMutableArray array]; int i; for(i=0; i<[[self game] numberOfPlayers]; i++) { if ([[self gameState] isPlayerHuman:i+1]) { [humanNumbers addObject:[NSNumber numberWithInt:i+1]]; } } return humanNumbers; } -(void)undoMove:(id)sender { if ([[self gameHistory] undoMovesUntilPlayerNumberInArray:[self humanPlayerNumbers]]) { [self gameStateChanged]; } else { NSBeep(); } } -(void)redoMove:(id)sender { if ([[self gameHistory] redoMovesUntilPlayerNumberInArray:[self humanPlayerNumbers]]) { [self gameStateChanged]; } else { NSBeep(); } } -(BOOL)validateMenuItem:(NSMenuItem *)item { // don't allow undo/redo in network games, and make sure the game state is undo/redoable // GNUstep selectors can't be compared with == NSString *selName = NSStringFromSelector([item action]); if ([@"undoMove:" isEqualToString:selName]) { if ([self isInNetworkGame]) return NO; return [[self gameHistory] canUndoMovesUntilPlayerNumberInArray:[self humanPlayerNumbers]]; } if ([@"redoMove:" isEqualToString:selName]) { if ([self isInNetworkGame]) return NO; return [[self gameHistory] canRedoMovesUntilPlayerNumberInArray:[self humanPlayerNumbers]]; } if ([@"openDocument:" isEqualToString:selName]) { if ([self isInNetworkGame]) return NO; } return YES; } -(void)boardView:(BoardView *)view finishedMoveAnimation:(id)callbackObject { // callback object is positions in the move NSArray *moveToExecute = callbackObject; [self recordAndExecuteMove:moveToExecute]; inAnimation = NO; [self gameStateChanged]; } -(void)boardView:(BoardView *)view mouseMovedOverPosition:(DCHypergridPosition *)position { //NSLog(@"Mouse moved at row:%d col:%d", [position row], [position column]); if ([self isWaitingForHumanMove]) { if (position) { NSArray *moves = [[self movePositions] arrayByAddingObject:position]; if ([[self game] isCompleteMoveSequenceValid:moves] || [[self game] isPartialMoveSequenceValid:moves]) { [boardView setHighlightedPositions:moves]; } else { [boardView setHighlightedPositions:[[[self movePositions] copy] autorelease]]; } } else { // mouse moved outside board [boardView setHighlightedPositions:[[[self movePositions] copy] autorelease]]; } } } -(BOOL)shouldMakeAIMove { if (0==[[[self gameState] aiNameForPlayer:[[self game] currentPlayerNumber]] length]) return NO; if ([[self game] isGameOver]) return NO; return YES; } -(void)cancelPendingAIMoves { /* create a unique move ID that we want the results for, so if multiple responses come back (which can happen if the user switches AIs while in mid-move, we only accept one of them. */ aiMoveID = (aiMoveID+1)%(1<<14); } -(id)idForPendingAIMove { return [NSNumber numberWithInt:aiMoveID]; } -(void)makeAIMove { [self cancelPendingAIMoves]; // We need a delay here, or else if the AI thread comes back really fast (as it will for low search levels), // the main event loop will never get a chance to process user input so menus and buttons won't respond. [self performSelector:@selector(detachAIThread) withObject:nil afterDelay:0.01 inModes:[NSArray arrayWithObjects:NSDefaultRunLoopMode, NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode, nil]]; } -(void)detachAIThread { [NSThread detachNewThreadSelector:@selector(makeAIMoveInThread:) toTarget:self withObject:[self idForPendingAIMove]]; } -(void)makeAIMoveInThread:(id)moveIDForThread { id pool = [[NSAutoreleasePool alloc] init]; [[[NSThread currentThread] threadDictionary] setObject:moveIDForThread forKey:@"moveID"]; [[self gameState] makeAIMove]; [pool release]; } -(void)aiComputedMoveInfoMainThread:(NSArray *)params { if ([self isWaitingForHumanMove]) { NSLog(@"Got move from AI but controller is human, ignoring move"); return; } else { id threadMoveID = [params objectAtIndex:1]; // we don't need a threadsafe accessor for moveID because it's only ever read and written from the main thread if (![threadMoveID isEqual:[self idForPendingAIMove]]) { NSLog(@"Got wrong move ID from worker thread (%@, expected %@), ignoring move", threadMoveID, [self idForPendingAIMove]); return; } else { NSNotification *notification = [params objectAtIndex:0]; //GenericAI *ai = [notification object]; NSDictionary *moveInfo = [notification userInfo]; //NSLog(@"Received best move:%@ in thread:%@", move, [NSThread currentThread]); NSArray *move = [moveInfo objectForKey:@"move"]; int positionsEvaluated = [[moveInfo objectForKey:@"positionsEvaluated"] intValue]; double moveTime = [[moveInfo objectForKey:@"time"] doubleValue]; [self doMoveSequence:move]; [aiNumMovesEvaluatedField setIntValue:positionsEvaluated]; [aiTimeField setDoubleValue:moveTime]; [aiMovesPerSecondField setIntValue:(int)(positionsEvaluated/moveTime)]; } } } -(void)aiComputedMoveInfo:(NSNotification *)notification { [self performSelectorOnMainThread:@selector(aiComputedMoveInfoMainThread:) withObject:[NSArray arrayWithObjects:notification,[[[NSThread currentThread] threadDictionary] objectForKey:@"moveID"], nil] waitUntilDone:NO]; } -(void)buildPlayerPopups { NSArray *aiTypes = [[self gameState] availableAINames]; NSArray *aiDisplayNames = [[self gameState] availableAIDisplayNames]; NSArray *popups = [NSArray arrayWithObjects:player1TypePopup,player2TypePopup,nil]; NSEnumerator *pe = [popups objectEnumerator]; NSPopUpButton *popup; int pnum = 1; while (popup=[pe nextObject]) { int i; // representedObjects of popup items are the non-localized names of the AIs ("" for human) [popup removeAllItems]; [popup addItemWithTitle:[[NSBundle mainBundle] localizedStringForKey:@"HumanPlayer" value:@"Human" table:nil]]; [[popup lastItem] setRepresentedObject:@""]; for(i=0; i<[aiDisplayNames count]; i++) { [popup addItemWithTitle:[[[NSBundle mainBundle] localizedStringForKey:@"ComputerPlayerPrefix" value:@"Human" table:nil] stringByAppendingString:[aiDisplayNames objectAtIndex:i]]]; [[popup lastItem] setRepresentedObject:[aiTypes objectAtIndex:i]]; } [popup selectItemWithRepresentedObject_:[[self gameState] aiNameForPlayer:pnum]]; // check for network if (nil!=[[self gameState] netConnectionForPlayer:pnum]) { [popup addItemWithTitle:[[NSBundle mainBundle] localizedStringForKey:@"NetworkPlayer" value:@"Network" table:nil]]; [popup selectItemAtIndex:[popup numberOfItems]-1]; } // FIXME: hide menu if only item is "Human" ++pnum; } } -(BOOL)allowRestart { if ([[self game] isGameOver] || [[self game] moveCount]==0) { return YES; } else { // game is in progress, show confirmation dialog NSString *title = NSLocalizedString(@"RestartTitle", nil); NSString *okLabel = NSLocalizedString(@"RestartOK", nil); NSString *cancelLabel = NSLocalizedString(@"RestartCancel", nil); NSString *msgText = NSLocalizedString(@"RestartMessage", nil); int result = NSRunAlertPanel(title, msgText, okLabel, cancelLabel, nil); return (result==NSAlertDefaultReturn); } } -(BOOL)confirmNetworkDisconnect { NSString *title = NSLocalizedString(@"DisconnectTitle", nil); NSString *okLabel = NSLocalizedString(@"DisconnectOK", nil); NSString *cancelLabel = NSLocalizedString(@"DisconnectCancel", nil); NSString *msgText = NSLocalizedString(@"DisconnectMessage", nil); int result = NSRunAlertPanel(title, msgText, okLabel, cancelLabel, nil); return (result==NSAlertDefaultReturn); } -(IBAction)playerTypeUpdated:(id)sender { int pnum = [sender tag]; NSString *aiName = [[sender selectedItem] representedObject]; // if in network game, changing player type will disconnect if (![self isInNetworkGame] || [self confirmNetworkDisconnect]) { [self dropAllNetConnections]; [[self gameState] setAIName:aiName forPlayer:pnum]; if ([self shouldMakeAIMove]) { [self makeAIMove]; } } [self buildPlayerPopups]; } -(IBAction)configurationSelectedFromPopup:(id)sender { if ([self allowRestart]) { NSString *varname = [[sender selectedItem] representedObject]; GameConfiguration *newConfig = [[[GameConfiguration alloc] initWithName:[self gameName] variation:varname] autorelease]; [self restartGameWithConfiguration:newConfig]; [self sendRestartToNetworkPlayers]; } else { [sender selectItemWithTitle:[self gameVariationDisplayName]]; } } -(IBAction)gameSelectedFromPopup:(id)sender { if ([self allowRestart]) { NSString *gameName = [[sender selectedItem] representedObject]; GameConfiguration *newConfig = [[[GameConfiguration alloc] initWithName:gameName variation:nil] autorelease]; [self restartGameWithConfiguration:newConfig]; [self sendRestartToNetworkPlayers]; } else { [sender selectItemWithTitle:[self gameName]]; } } -(IBAction)passButtonClicked:(id)sender { if ([[self game] isCompleteMoveSequenceValid:nil]) { //NSLog(@"Executing move"); [self doMoveSequence:nil]; } } -(IBAction)restartGame:(id)sender { if ([self allowRestart]) { [[self gameConfiguration] createNewInitialGame]; [self restartGame]; [self sendRestartToNetworkPlayers]; } } -(void)restartSheetEnded:(NSWindow *)window returnCode:(int)code contextInfo:(void *)unused { if (code==NSAlertDefaultReturn) { [self restartGame]; } } -(void)windowWillClose:(NSNotification *)note { // clear any previous delayed invocations because they retain their targets [self cancelPendingAIMoves]; [self autorelease]; // terminate app [[NSApplication sharedApplication] performSelector:@selector(terminate:) withObject:nil afterDelay:0.01]; } -(NSSize)windowWillResize:(NSWindow *)win toSize:(NSSize)newSize { if (newSize.width > newSize.height+widthDelta) { return NSMakeSize(newSize.height+widthDelta, newSize.height); } else { return NSMakeSize(newSize.width, newSize.width-widthDelta); } } // recorded move table view data source methods -(int)numberOfRowsInTableView:(NSTableView *)table { return [[self gameHistory] numberOfMoves]/2; } -(id)tableView:(NSTableView *)table objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row { int col = [[tableColumn identifier] intValue]; int index = [[table tableColumns] count]*row + col - 1; NSArray *move = [[self gameHistory] moveWithNumber:index]; return (move) ? [[self game] descriptionForMove:move] : @""; } -(void)tableView:(NSTableView *)table willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(int)row { int col = [[tableColumn identifier] intValue]; int index = [[table tableColumns] count]*row + col - 1; if (index>=[[self gameHistory] currentMoveNumber]) { [cell setTextColor:[NSColor redColor]]; } else { [cell setTextColor:[NSColor blackColor]]; } } -(BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex { return NO; } ////////////////////////////////////////////////////////////////////////////////// // loading and saving games -(id)propertyList { NSMutableDictionary *plist = [NSMutableDictionary dictionary]; [plist setObject:[[self gameHistory] propertyList] forKey:@"history"]; { NSMutableDictionary *aiDict = [NSMutableDictionary dictionary]; int i; for(i=1; i<=[[self game] numberOfPlayers]; i++) { NSString *aiName = [[self gameState] aiNameForPlayer:i]; if ([aiName length]>0) { [aiDict setObject:aiName forKey:[[NSNumber numberWithInt:i] stringValue]]; } } [plist setObject:aiDict forKey:@"AIs"]; } return plist; } -(void)updateFromPropertyList:(id)plist { GameHistory *newHistory = [[[GameHistory alloc] initFromPropertyList:[plist objectForKey:@"history"]] autorelease]; if (newHistory) { // update AIs in Preferences, they will be created in restartGame... NSDictionary *aiDict = [plist objectForKey:@"AIs"]; int i; for(i=1; i<=[[newHistory currentGame] numberOfPlayers]; i++) { NSString *aiName = [aiDict objectForKey:[NSString stringWithFormat:@"%d",i]]; if (!aiName) aiName = @""; [[Preferences sharedInstance] setAIType:aiName forGame:[[newHistory gameConfiguration] gameName] player:i]; } [self restartGameWithHistory:newHistory]; } else { NSLog(@"Failed to load game"); } } -(IBAction)saveDocument:(id)sender { NSSavePanel *panel = [NSSavePanel savePanel]; // GNUstep doesn't like sheets (it implements the methods but the return code isn't set) #ifdef GNUSTEP if ([panel runModal]==NSFileHandlingPanelOKButton) { [self saveGameToURL:[panel URL]]; } #else [panel beginSheetForDirectory:nil file:nil modalForWindow:window modalDelegate:self didEndSelector:@selector(savePanelEnded:returnCode:contextInfo:) contextInfo:nil]; #endif } -(void)saveGameToURL:(NSURL *)url { id plist = [self propertyList]; if ([plist writeToURL:url atomically:YES]==NO) { NSLog(@"Error saving game to:%@", url); [self performSelector:@selector(showSaveFailedPanelForURL:) withObject:url afterDelay:0.0]; } } -(void)showSaveFailedPanelForURL:(NSURL *)url { NSRunAlertPanel(NSLocalizedString(@"SaveFailedTitle", nil), NSLocalizedString(@"SaveFailedMessage", nil), nil, nil, nil); } -(void)savePanelEnded:(NSSavePanel *)panel returnCode:(int)code contextInfo:(void *)info { if (code==NSOKButton) { [self saveGameToURL:[panel URL]]; } } -(IBAction)openDocument:(id)sender { if ([self isInNetworkGame]) { NSBeep(); } else { NSOpenPanel *panel = [NSOpenPanel openPanel]; // GNUstep doesn't like sheets (it implements the methods but the return code isn't set) #ifdef GNUSTEP if ([panel runModalForTypes:nil]==NSOKButton) { [self loadGameFromURL:[panel URL]]; } #else [panel beginSheetForDirectory:nil file:nil modalForWindow:window modalDelegate:self didEndSelector:@selector(openPanelEnded:returnCode:contextInfo:) contextInfo:nil]; #endif } } -(void)loadGameFromURL:(NSURL *)url { id plist; NS_DURING plist = [[NSString stringWithContentsOfURL:url] propertyList]; NS_HANDLER plist = nil; NS_ENDHANDLER if (plist) { [self updateFromPropertyList:plist]; } else { NSLog(@"Can't restore saved game from:%@", url); [self performSelector:@selector(showLoadFailedPanelForURL:) withObject:url afterDelay:0.0]; } } -(void)showLoadFailedPanelForURL:(NSURL *)url { NSRunAlertPanel(NSLocalizedString(@"LoadFailedTitle", nil), NSLocalizedString(@"LoadFailedMessage", nil), nil, nil, nil); } -(void)openPanelEnded:(NSSavePanel *)panel returnCode:(int)code contextInfo:(void *)info { if (code==NSOKButton) { [self loadGameFromURL:[panel URL]]; } } ///////////////////////////////////////////////////////////////////////////////////// // network support -(BOOL)isInNetworkGame { return [[[self gameState] allNetConnections] count]>0; } -(void)gotNetworkConnection:(NSNotification *)notification { id playerNum = [[notification userInfo] objectForKey:@"playerNumber"]; NetConnection *connection = [[notification userInfo] objectForKey:@"connection"]; GameConfiguration *config = [[notification userInfo] objectForKey:@"configuration"]; if (playerNum && connection && config) { NSLog(@"Got remote connection, restarting"); [self restartGameWithConfiguration:config]; // update player menus [[self gameState] makeAllPlayersHuman]; [[self gameState] setNetConnection:connection forPlayer:[playerNum intValue]]; [self buildPlayerPopups]; [self updateNetworkStatus]; [self showNetworkDrawer:nil]; } } -(void)sendPropertyListToNetworkPlayers:(id)plist { [[[self gameState] allNetConnections] makeObjectsPerformSelector:@selector(transmitPropertyList:) withObject:plist]; } -(void)updateNetworkStatus { NSArray *connections = [[self gameState] allNetConnections]; if ([connections count]>0) { // for now assume only one id conn = [connections objectAtIndex:0]; [networkStatusField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"NetworkStatusConnected", nil), [conn remoteIPAddress]]]; [disconnectButton setEnabled:YES]; [chatMessageField setEnabled:YES]; } else { [networkStatusField setStringValue:NSLocalizedString(@"NetworkStatusNotConnected", nil)]; [disconnectButton setEnabled:NO]; [chatMessageField setEnabled:NO]; } } -(void)dropAllNetConnections { [[[self gameState] allNetConnections] makeObjectsPerformSelector:@selector(sendDisconnect)]; } -(IBAction)disconnectButtonClicked:(id)sender { if ([self isInNetworkGame] && [self confirmNetworkDisconnect]) { [self dropAllNetConnections]; } } -(void)dropNetConnectionForPlayer:(NSNumber *)pnum { [[[self gameState] netConnectionForPlayer:[pnum intValue]] setIsDisconnected:YES]; [[self gameState] setNetConnection:nil forPlayer:[pnum intValue]]; [self buildPlayerPopups]; // this won't work if >2 players [self updateNetworkStatus]; } -(void)receivedPropertyListFromNetwork:(NSNotification *)notification { int pnum = [[self gameState] playerNumberForNetConnection:[notification object]]; if (pnum>0) { NSDictionary *plist = [[notification userInfo] objectForKey:@"plist"]; //NSLog(@"Read plist from network:%@", [plist description]); // check for disconnect or error if ([plist objectForKey:@"disconnect"]) { NSLog(@"Received disconnect"); // we want to keep the connection around until the next run loop, otherwise // there are timing problems where the NetConnection can get data notifications // just after it's dealloced. [self performSelector:@selector(dropNetConnectionForPlayer:) withObject:[NSNumber numberWithInt:pnum] afterDelay:0.0]; } else if ([plist objectForKey:@"error"]) { NSLog(@"Received error:%@", [plist objectForKey:@"error"]); [self performSelector:@selector(dropNetConnectionForPlayer:) withObject:[NSNumber numberWithInt:pnum] afterDelay:0.0]; } else if ([plist objectForKey:@"chat"]) { NSString *msg = [plist objectForKey:@"chat"]; //NSLog(@"Received chat message:%@", msg); [chatTranscriptArea appendText:[NSString stringWithFormat:@"%@: %@\n", [[notification object] remoteUsername], msg] scrollToEnd_:YES]; } else if ([plist objectForKey:@"restart"]) { // TODO: ask for verification GameConfiguration *config = [self gameConfiguration]; NSDictionary *configPlist = [plist objectForKey:@"configuration"]; if (configPlist) { config = [[[GameConfiguration alloc] initFromPropertyList:configPlist] autorelease]; } [self restartGameWithConfiguration:config]; [chatTranscriptArea appendText:[NSLocalizedString(@"GameRestartedMessage",nil) stringByAppendingString:@"\n"] scrollToEnd_:YES]; } else if ([plist objectForKey:@"start"]) { // do nothing, this is the start request, handled in ClientController } else { NSArray *moveStrings = [plist objectForKey:@"move"]; id gamePlist = [plist objectForKey:@"game"]; //NSLog(@"Got move from network:%@", [moveStrings description]); if (moveStrings && gamePlist) { // make sure it's the right turn if (pnum!=[[self game] currentPlayerNumber]) { NSLog(@"Move for player %d received when player %d's turn", pnum, [[self game] currentPlayerNumber]); [self performSelector:@selector(dropNetConnectionForPlayer:) withObject:[NSNumber numberWithInt:pnum] afterDelay:0.0]; } else { // validate move NSArray *move = [DCHypergridPosition positionArrayFromPropertyListValueArray:moveStrings]; Game *gameCopy = [[[self game] copy] autorelease]; if ([gameCopy isCompleteMoveSequenceValid:move] && [gameCopy makeMoveSequence:move]) { // move is valid, make sure the resulting state matches Game *gameFromClient = [[[[self gameConfiguration] initialGame] copy] autorelease]; [gameFromClient updateFromPropertyList:gamePlist]; if ([[gameCopy grid] isEqualToHypergrid:[gameFromClient grid]]) { // good move, execute [self doMoveSequence:move]; } else { NSLog(@"Inconsistency in game state from client"); [self performSelector:@selector(dropNetConnectionForPlayer:) withObject:[NSNumber numberWithInt:pnum] afterDelay:0.0]; } } else { NSLog(@"Received invalid move from client:%@", [move description]); [self performSelector:@selector(dropNetConnectionForPlayer:) withObject:[NSNumber numberWithInt:pnum] afterDelay:0.0]; } } } else { NSLog(@"Received unrecognized message:%@", [plist description]); } } } } -(IBAction)sendChatMessage:(id)sender { if ([[chatMessageField stringValue] length]>0 && [[[self gameState] allNetConnections] count]>0) { NSMutableDictionary *chatDict = [NSMutableDictionary dictionary]; [chatDict setObject:[chatMessageField stringValue] forKey:@"chat"]; [self sendPropertyListToNetworkPlayers:chatDict]; [chatTranscriptArea appendText:[NSString stringWithFormat:@"%@: %@\n", [[Preferences sharedInstance] networkUsername], [chatMessageField stringValue]] scrollToEnd_:YES]; } [chatMessageField setStringValue:@""]; } -(void)sendMoveToNetworkPlayers:(NSArray *)move { if ([[self gameState] hasNetConnections]) { Game *gameCopy = [[[self game] copy] autorelease]; NSMutableDictionary *movePlist = [NSMutableDictionary dictionary]; NSEnumerator *ne = [[[self gameState] allNetConnections] objectEnumerator]; id conn; [gameCopy makeMoveSequence:move]; [movePlist setObject:[move valuesByObjectsPerformingSelector:@selector(propertyListValue)] forKey:@"move"]; //NSLog(@"move array:%@", move); [movePlist setObject:[gameCopy propertyList] forKey:@"game"]; while (conn=[ne nextObject]) { //NSLog(@"Writing plist to network:%@", [movePlist description]); [conn transmitPropertyList:movePlist]; } } } -(void)sendRestartToNetworkPlayers { NSMutableDictionary *restartDict = [NSMutableDictionary dictionary]; [restartDict setObject:@"1" forKey:@"restart"]; [restartDict setObject:[[self gameConfiguration] propertyList] forKey:@"configuration"]; [self sendPropertyListToNetworkPlayers:restartDict]; } -(void)networkConnectionTerminated:(NSNotification *)notification { int pnum = [[self gameState] playerNumberForNetConnection:[notification object]]; if (pnum>0) { [self dropNetConnectionForPlayer:[NSNumber numberWithInt:pnum]]; } } ///////////////////////////////////////////////////////////////////////////////// /* These methods operate on both the drawer and window ivars. One of each will be nil (window ivar is not set in OS X, drawer is not set in GNUstep), messages to them will be ignored. */ -(IBAction)toggleStatisticsDrawer:(id)sender { [statisticsDrawer toggle:self]; [statisticsWindow makeKeyAndOrderFront:nil]; } -(IBAction)showStatisticsDrawer:(id)sender { [statisticsDrawer open]; [statisticsWindow makeKeyAndOrderFront:nil]; } -(IBAction)toggleNetworkDrawer:(id)sender { [networkDrawer toggle:self]; [networkWindow makeKeyAndOrderFront:nil]; } -(IBAction)showNetworkDrawer:(id)sender { [networkDrawer open]; [networkWindow makeKeyAndOrderFront:nil]; } -(void)drawerDidOpen:(NSNotification *)notification { if ([notification object]==statisticsDrawer) { [[NSUserDefaults standardUserDefaults] setInteger:1 forKey:@"StatsVisible"]; } } -(void)drawerDidClose:(NSNotification *)notification { if ([notification object]==statisticsDrawer) { [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"StatsVisible"]; } } @end gridlock.app-1.10/Game.m0000644000175000000000000002335310342202542014056 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "Game.h" static NSArray *gEmptyArray = nil; static NSArray* emptyArray() { if (!gEmptyArray) { gEmptyArray = [[NSArray alloc] init]; } return gEmptyArray; } @implementation Game idAccessor(grid, setGrid) idAccessor(futureGrid, setFutureGrid) idAccessor(configurationInfo, setConfigurationInfo) -(Game *)copy { Game *newGame = nil; if (newGame = [[[self class] alloc] init]) { newGame->grid = [grid copy]; newGame->playerNumber = playerNumber; [newGame setConfigurationInfo:[self configurationInfo]]; newGame->moveCount = moveCount; } return newGame; } -(void)copyValuesToGame:(Game *)newGame { [grid copyValuesToGrid:newGame->grid]; newGame->playerNumber = playerNumber; [newGame setConfigurationInfo:[self configurationInfo]]; newGame->moveCount = moveCount; } -(void)dealloc { [grid release]; [futureGrid release]; [configurationInfo release]; [super dealloc]; } -(void)reset { playerNumber = 1; moveCount = 0; } -(void)createGridFromConfiguration { [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; [self setGridValuesFromArray:[[self configurationInfo] objectForKey:@"positions"]]; } // number of rows and columns are cached to avoid method calls -(int)numberOfRows { if (_nrows>0) return _nrows; return (_nrows=[grid numberOfRows]); } -(int)numberOfColumns { if (_ncols>0) return _ncols; return (_ncols=[grid numberOfColumns]); } -(int)moveCount { return moveCount; } -(int)valueAtPosition:(DCHypergridPosition *)pos { return [grid valueAtPosition:pos]; } -(int)valueAtRow:(int)r column:(int)c { return [grid valueAtRow:r column:c]; } -(void)setValue:(int)value atPosition:(DCHypergridPosition *)pos { [grid setValue:value atPosition:pos]; } -(void)setValue:(int)value atRow:(int)r column:(int)c { [grid setValue:value atRow:r column:c]; } -(BOOL)isPositionValid:(DCHypergridPosition *)pos { int row = [pos row]; int col = [pos column]; return (row>=0 && col>=0 && row<[self numberOfRows] && col<[self numberOfColumns]); } -(BOOL)isValidRow:(int)row column:(int)col { return (row>=0 && col>=0 && row<[self numberOfRows] && col<[self numberOfColumns]); } -(void)resetFutureGrid { if ([self futureGrid]==nil) { [self setFutureGrid:[[[self grid] copy] autorelease]]; } else { [[self grid] copyValuesToGrid:[self futureGrid]]; } } -(void)updateFromPreparedMove { if ([self futureGrid]) { [[self futureGrid] copyValuesToGrid:[self grid]]; } else { NSEnumerator *cenum; DCHypergridPosition *pos; cenum = [[self positionsOfAllChangingCells] objectEnumerator]; while (pos=[cenum nextObject]) { //NSLog(@"updating: %d %d %d", [pos row], [pos column], [self futureValueAtPosition:pos]); [self setValue:[self futureValueAtPosition:pos] atPosition:pos]; } } } -(int)futureValueAtPosition:(DCHypergridPosition *)pos { return [[self futureGrid] valueAtPosition:pos]; } -(NSArray *)positionsOfAllChangingCells { NSMutableArray *array = [NSMutableArray array]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; DCHypergrid *grid1 = [self grid]; DCHypergrid *grid2 = [self futureGrid]; while (pos=[pe nextObject]) { if ([grid1 valueAtPosition:pos]!=[grid2 valueAtPosition:pos]) { [array addObject:pos]; } } return array; } -(BOOL)makeMoveSequence:(NSArray *)positions { if (![self prepareMoveSequence:positions]) return NO; else { [self updateFromPreparedMove]; [self didMakeMove:positions]; return YES; } } -(void)didMakeMove:(NSArray *)positions { ++moveCount; [self incrementPlayerNumber]; } -(BOOL)preparePass { return [self prepareMoveSequence:emptyArray()]; } -(BOOL)pass { return [self makeMoveSequence:emptyArray()]; } -(BOOL)isPassValid { return [self isCompleteMoveSequenceValid:emptyArray()]; } -(NSArray *)allValidMoveSequences { [NSException raise:@"SubclassMustImplementMethod" format:@"Class %d must implement -allValidMoveSequences", NSStringFromClass([self class])]; return nil; } -(NSArray *)inferredValidMoveSequences { NSMutableArray *validSequences = [NSMutableArray array]; NSMutableArray *partialSequences = [NSMutableArray array]; // partialSequences is a stack holding in-progress move arrays [partialSequences addObject:[NSMutableArray array]]; while ([partialSequences count]>0) { NSMutableArray *sequence = [partialSequences lastObject]; NSEnumerator *posEnum = [[self grid] positionEnumerator]; id position; [partialSequences removeLastObject]; // add each cell to the partial sequence while(position=[posEnum nextObject]) { NSMutableArray *possibleSequence = [NSMutableArray arrayWithArray:sequence]; [possibleSequence addObject:position]; // If this forms a complete sequence, add to the return array. // If it forms a valid sequence, push it back on the stack. if ([self isCompleteMoveSequenceValid:possibleSequence]) { [validSequences addObject:possibleSequence]; } if ([self isPartialMoveSequenceValid:possibleSequence]) { [partialSequences addObject:possibleSequence]; } } } return validSequences; } -(BOOL)isPartialMoveSequenceValid:(NSArray *)positions { return ([positions count]>0 && [[self allValidMoveSequences] arrayWithPrefix_:positions]!=nil); } -(BOOL)isCompleteMoveSequenceValid:(NSArray *)positions { if (!positions) positions = [NSArray array]; return [[self allValidMoveSequences] containsObject:positions]; } -(int)currentPlayerNumber { return playerNumber; } -(void)setCurrentPlayerNumber:(int)value { playerNumber = value; } -(void)incrementPlayerNumber { [self setCurrentPlayerNumber:[self nextPlayerNumber]]; } -(int)playerNumberMovingAfterPlayer:(int)pnum { return (pnum==[self numberOfPlayers]) ? 1 : pnum+1; } -(int)nextPlayerNumber { return [self playerNumberMovingAfterPlayer:[self currentPlayerNumber]]; } -(int)scoreForPlayer:(int)pnum { return [grid numberOfCellsWithValue:pnum]; } -(BOOL)showScores { return NO; } -(int)winningPlayer { int pcount = [self numberOfPlayers]; int i; int highscore = [self scoreForPlayer:1]; int winner = 1; BOOL tie = NO; for(i=2; i<=pcount; i++) { int score = [self scoreForPlayer:i]; if (score>highscore) { highscore = score; winner = i; tie = NO; } else if (score==highscore) tie = YES; } return (tie) ? 0 : winner; } -(NSArray *)positionsOfWinningPieces { return nil; } -(int)numberOfPlayers { return 2; } -(void)setGridValuesFromArray:(NSArray *)array { NSEnumerator *ae = [array objectEnumerator]; id pv; while (pv=[ae nextObject]) { [[self grid] setValue:[[pv objectAtIndex:2] intValue] atRow:[[pv objectAtIndex:0] intValue] column:[[pv objectAtIndex:1] intValue]]; } } -(void)fillFirstRows:(int)numRows { int r, c; for(c=0; c<[self numberOfColumns]; c++) { for(r=0; rsourceArray = array; enumerator->lock = theLock; return enumerator; } -(id)nextObject { id obj = nil; [lock lock]; if ([sourceArray count]>0) { obj = [sourceArray lastObject]; [sourceArray removeLastObject]; } [lock unlock]; return obj; } @end @implementation GenericAI -(id)init { if (self=[super init]) { //NSLog(@"Creating AI:%@", NSStringFromClass([self class])); threadLock = [[NSLock alloc] init]; bestThreadMoves = [[NSMutableArray alloc] init]; } return self; } -(void)dealloc { [threadLock release]; [bestThreadMoves release]; [super dealloc]; } idAccessor(name, setName) idAccessor(threadLock, setThreadLock) idAccessor(bestThreadMoves, setBestThreadMoves) intAccessor(depth, setDepth) intAccessor(useThreads, setUseThreads) // alpha-beta algorithm adapted from http://www.seanet.com/~brucemo/topics/alphabeta.htm -(NSArray *)alphaBetaMoveForGame:(Game *)game depth:(int)d alpha:(int)alpha beta:(int)beta candidateMoves:(NSEnumerator *)moveenum positionsEvaluated:(int *)numEvaluated utility:(int *)utility { int nextUtility; if (!moveenum) moveenum = [self enumeratorForMovesToConsiderForGame:game]; NSArray *move, *nextMove, *bestMove=nil; Game *gameCopy = nil; int movenum=0; NSAssert2(alpha=beta(%d)", alpha, beta); while ((alpha=beta) { nextUtility = beta; } if (bestMove==nil || nextUtility>alpha) { bestMove = move; } if (nextUtility>alpha) alpha=nextUtility; if (numEvaluated) ++(*numEvaluated); [pool release]; } [gameCopy release]; *utility = alpha; if (alpha>=beta) { //NSLog(@"Exceeded beta at depth %d", d); } return bestMove; } -(int)searchDepthForGame:(Game *)game { return depth; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { return ([game scoreForPlayer:pnum] - [game scoreForPlayer:[game nextPlayerNumber]]); } -(NSArray *)movesToConsiderForGame:(Game *)game { return [game allValidMoveSequences]; } -(NSEnumerator *)enumeratorForMovesToConsiderForGame:(Game *)game { return [[[self movesToConsiderForGame:game] arrayWithObjectsInRandomOrder_] objectEnumerator]; } +(double)normalizedRatioOf:(double)u1 to:(double)u2 maxRatio:(double)maxr { // Look at the ratio of my vs. opponent's utility. This will encourage exchanges when we're ahead and // avoid them when we're behind. double logratio = 0.0; if (u1<=0) return -1; if (u2<=0) return +1; else { logratio = log(u1/u2); if (logratio<-maxr) return -1; if (logratio>maxr) return +1; } return logratio/maxr; } ////////////////////////////////// thread support ////////////////////////////// -(int)threadsToUse { if ([self useThreads]) { int nthreads = [[NSUserDefaults standardUserDefaults] integerForKey:@"CPUPlayerThreads"]; if (nthreads<1) { // use MPProcessors() on Mac OS X, default to 1 on GNUstep until I find a portable way #ifdef GNUSTEP nthreads = 1; #else nthreads = MPProcessors(); #endif } return nthreads; } else return 1; } -(NSDictionary *)_bestMoveInfoForGame:(Game *)game candidateMoves:(NSArray *)moves spawningThreads:(int)nthreads { NSTimeInterval t1 = [NSDate timeIntervalSinceReferenceDate]; NSTimeInterval t2; // each worker thread gets a lock whose condition it sets to 1 when it finishes NSMutableArray *locks = [NSMutableArray array]; NSMutableArray *randomMoves = [[[moves arrayWithObjectsInRandomOrder_] mutableCopy] autorelease]; int nmoves = [moves count]; int i; if (nthreads>nmoves) nthreads = nmoves; for(i=0; i0) { if (bestMove==nil) bestMove = [NSArray array]; [moveInfo setObject:bestMove forKey:@"move"]; [moveInfo setObject:[NSNumber numberWithInt:positionsEvaluated] forKey:@"positionsEvaluated"]; [moveInfo setObject:[NSNumber numberWithInt:utility] forKey:@"utility"]; [self _recordBestMoveFoundInThread:moveInfo]; if (DEBUG) { NSLog(@"Finished processing in thread:%@", [NSThread currentThread]); } } else { if (DEBUG) NSLog(@"No moves available to process in thread:%@", [NSThread currentThread]); } [lock unlockWithCondition:1]; [pool release]; } //////////////////////////////// end thread support ///////////////////////////// -(NSDictionary *)bestMoveInfoForGame:(Game *)game { int nthreads = [self threadsToUse]; NSDictionary *moveInfo; if (nthreads<=1) { NSTimeInterval t1 = [NSDate timeIntervalSinceReferenceDate]; NSTimeInterval t2; int positionsEvaluated=0; NSMutableDictionary *detailInfo = [NSMutableDictionary dictionary]; NSArray *bestMove = nil; int d = [self searchDepthForGame:game]; int utility; bestMove = [self alphaBetaMoveForGame:game depth:d alpha:LOSE_UTILITY-d beta:WIN_UTILITY+d candidateMoves:nil positionsEvaluated:&positionsEvaluated utility:&utility]; if (bestMove==nil) bestMove = [NSArray array]; [detailInfo setObject:bestMove forKey:@"move"]; [detailInfo setObject:[NSNumber numberWithInt:positionsEvaluated] forKey:@"positionsEvaluated"]; [detailInfo setObject:[NSNumber numberWithInt:utility] forKey:@"utility"]; t2 = [NSDate timeIntervalSinceReferenceDate]; [detailInfo setObject:[NSNumber numberWithDouble:t2-t1] forKey:@"time"]; moveInfo = detailInfo; } else { NSArray *candidateMoves = [self movesToConsiderForGame:game]; moveInfo = [self _bestMoveInfoForGame:game candidateMoves:candidateMoves spawningThreads:nthreads]; } if (DEBUG) { NSLog(@"AI done, time=%@ sec, utility=%@", [moveInfo objectForKey:@"time"], [moveInfo objectForKey:@"utility"]); } return moveInfo; } -(void)computeBestMoveForGame:(Game *)game { Game *gamecopy = [[game copy] autorelease]; NSMutableDictionary *moveInfo = [[self bestMoveInfoForGame:gamecopy] mutableCopy]; [moveInfo setObject:game forKey:@"game"]; //NSLog(@"Computed best move:%@ in thread:%@", move, [NSThread currentThread]); [[NSNotificationCenter defaultCenter] postNotificationName:@"AIComputedBestMoveNotification" object:self userInfo:moveInfo]; } @end gridlock.app-1.10/GlassBeadGame.m0000644000175000000000000000712410342202542015622 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GlassBeadGame.h" /** Cells with actual pieces have values corresponding to player numbers (+1 and +2). Cells which don't have pieces but are controlled by a player have the negative of the player numbers (-1 and -2). */ @implementation GlassBeadGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { DCHypergridPosition *pos = [positions lastObject]; NSArray *neighbors = [[self grid] neighborsOfPosition:pos distance:1]; NSEnumerator *me = [neighbors objectEnumerator]; DCHypergridPosition *mpos; int pnum = [self currentPlayerNumber]; int oppnum = [self nextPlayerNumber]; [self resetFutureGrid]; [[self futureGrid] setValue:pnum atPosition:pos]; // check each neighbor of this move for changes while (mpos=[me nextObject]) { // only check cells that don't have pieces on them if ([self valueAtPosition:mpos]<=0 && ![mpos isEqual:pos]) { // count current neighbors (of each neighbor to the proposed move) for each players' pieces int mycount = 0; int oppcount = 0; int dr, dc; for(dr=-1; dr<=1; dr++) { int r = [mpos row]+dr; if (r>=0 && r<[self numberOfRows]) { for(dc=-1; dc<=1; dc++) { int c = [mpos column]+dc; if (c>=0 && c<[self numberOfColumns]) { int value = [self valueAtRow:r column:c]; if (value==pnum) ++mycount; else if (value==oppnum) ++oppcount; } } } } if (mycount==oppcount) { // empty cell will become owned by current player [[self futureGrid] setValue:-pnum atPosition:mpos]; } else if (mycount+1==oppcount) { // cell owned by opponent will become empty [[self futureGrid] setValue:0 atPosition:mpos]; } } } return YES; } -(int)scoreForPlayer:(int)pnum { // sum of # of pieces and # of controlled cells return [[self grid] numberOfCellsWithValue:pnum] + [[self grid] numberOfCellsWithValue:0-pnum]; } -(BOOL)isGameOver { // game over when all cells are filled or controlled return (![[self grid] hasCellWithValue:0]); } -(NSArray *)allValidMoveSequences { return [[[self grid] allPositionsWithValue:0] valuesByObjectsPerformingSelector:@selector(arrayWithSelf_)]; } -(BOOL)showScores { return YES; } @end gridlock.app-1.10/GlassBeadViewDelegate.m0000644000175000000000000000316610342202542017320 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GlassBeadViewDelegate.h" #import "Preferences.h" #import #import "ImageStore.h" @implementation GlassBeadViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game { if (abs(value)>0) { NSColor *playerColor = [[Preferences sharedInstance] highlightColorForPlayerNumber:abs(value)]; [[playerColor blendedColorWithFraction:0.75 ofColor:[NSColor whiteColor]] set]; NSRectFill(rect); } return NO; } -(BOOL)disableAnimation { return YES; } @end gridlock.app-1.10/GomokuAI.m0000644000175000000000000001156210342202542014657 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GomokuAI.h" @implementation GomokuAI -(NSArray *)movesToConsiderForGame:(Game *)g { GomokuGame *game = g; NSArray *myThreats = [game threatsForPlayer:[game currentPlayerNumber]]; //NSArray *oppThreats = [game threatsForPlayer:[game nextPlayerNumber]]; //NSArray *combinedThreats = [myThreats arrayByAddingObjectsFromArray:oppThreats]; NSEnumerator *te; NSDictionary *threat; // win or block // (as below, only look for our own wins, otherwise we might block opponent when we could win with XX-XX) for(te=[myThreats objectEnumerator]; threat=[te nextObject]; ) { int tlen = [[threat objectForKey:@"length"] intValue]; if (tlen==[game winningLength]-1) { DCHypergridPosition *pos = [threat objectForKey:@"position"]; DCHypergridPosition *dir = [threat objectForKey:@"direction"]; pos = [pos positionBySubtractingPosition:dir]; if ([game isPositionValid:pos] && [game valueAtPosition:pos]==0) { return [NSArray arrayWithObject:[pos arrayWithSelf_]]; } // try other direction pos = [DCHypergridPosition positionWithRow:[pos row]+[game winningLength]*[dir row] column:[pos column]+[game winningLength]*[dir column]]; if ([game isPositionValid:pos] && [game valueAtPosition:pos]==0) { return [NSArray arrayWithObject:[pos arrayWithSelf_]]; } } } // look for threat of length n-2 open on both ends; make winning move or block // unfortunately this misses critical moves like winning or blocking with XX-XX /* for(te=[combinedThreats objectEnumerator]; threat=[te nextObject]; ) { int tlen = [[threat objectForKey:@"length"] intValue]; if (tlen==[game winningLength]-2) { int fwdlen = [[threat objectForKey:@"openAfter"] intValue]; int backlen = [[threat objectForKey:@"openBefore"] intValue]; if (fwdlen>=1 && backlen>=1 && (fwdlen>1 || backlen>1)) { NSMutableArray *array = [NSMutableArray array]; DCHypergridPosition *pos = [threat objectForKey:@"position"]; DCHypergridPosition *dir = [threat objectForKey:@"direction"]; if (fwdlen>1) { id fwdpos = [DCHypergridPosition positionWithRow:[pos row]+([game winningLength]-2)*[dir row] column:[pos column]+([game winningLength]-2)*[dir column]]; [array addObject:[NSArray arrayWithObject:fwdpos]]; } if (backlen>1) { id backpos = [pos positionBySubtractingPosition:dir]; [array addObject:[NSArray arrayWithObject:backpos]]; } if ([array count]) return array; } } } */ return [super movesToConsiderForGame:g]; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { return [self threatWeightForGame:(GomokuGame *)game player:pnum] - [self threatWeightForGame:(GomokuGame *)game player:[game playerNumberMovingAfterPlayer:pnum]]; } -(int)threatWeightForGame:(GomokuGame *)game player:(int)pnum { static int nextPlayerWeights[] = {0,0, 1,5, 10,50, 100,500, 1000,50000, 9999999,9999999}; static int currentPlayerWeights[] = {0,0, 1,5, 10,50, 500,2500, 999999,999999, 9999999,9999999}; int *weights = (pnum==[game currentPlayerNumber]) ? currentPlayerWeights : nextPlayerWeights; NSArray *threats = [game threatsForPlayer:pnum]; NSEnumerator *te = [threats objectEnumerator]; NSDictionary *threat; int total = 0; while (threat=[te nextObject]) { int length = [[threat objectForKey:@"length"] intValue]; // openings is 1 if both ends are open int openings = ([[threat objectForKey:@"openBefore"] intValue]>0 && [[threat objectForKey:@"openAfter"] intValue]>0); if (length>=[game winningLength]) length=[game winningLength]; total += weights[2*length + openings]; } return total; } @end gridlock.app-1.10/GomokuGame.m0000644000175000000000000000255210342202542015236 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GomokuGame.h" static int WIN_LENGTH = 5; @implementation GomokuGame -(int)winningLength { return WIN_LENGTH; } -(NSArray *)allValidMoveSequences { return [[[self grid] allPositionsWithValue:0] valuesByObjectsPerformingSelector:@selector(arrayWithSelf_)]; } @end gridlock.app-1.10/ImageStore.m0000644000175000000000000000756310342202542015251 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ImageStore.h" #import "Preferences.h" static ImageStore *_sharedInstance; @implementation ImageStore +(ImageStore *)defaultStore { if (!_sharedInstance) { _sharedInstance = [[self alloc] init]; } return _sharedInstance; } -(id)init { self = [super init]; colorImageCache = [[NSMutableDictionary alloc] init]; bitmapImageCache = [[NSMutableDictionary alloc] init]; return self; } -(void)dealloc { [colorImageCache release]; [bitmapImageCache release]; [super dealloc]; } -(NSImage *)bitmapImageWithName:(NSString *)name size:(NSSize)size { // bitmapImageCache is indexed by name and size NSString *sizekey = NSStringFromSize(size); NSMutableDictionary *sizeDict = [bitmapImageCache objectForKey:name]; NSImage *image = nil; if (!sizeDict) { [bitmapImageCache setObject:(sizeDict=[NSMutableDictionary dictionary]) forKey:name]; } image = [sizeDict objectForKey:sizekey]; if (!image) { NSImage *bitmapImage = [NSImage imageNamed:name]; image = [[[NSImage alloc] initWithSize:size] autorelease]; [image lockFocus]; [[bitmapImage bestRepresentationForDevice:nil] drawInRect:NSMakeRect(0,0,size.width,size.height)]; [image unlockFocus]; // inelegant way of preventing cache from growing without bound if ([sizeDict count]>10) { [sizeDict removeAllObjects]; } [sizeDict setObject:image forKey:sizekey]; } return image; } -(NSImage *)solidPieceImageWithColor:(NSColor *)color size:(NSSize)size { NSString *sizekey = NSStringFromSize(size); NSMutableDictionary *sizeDict = [colorImageCache objectForKey:color]; NSImage *image = nil; if (!sizeDict) { // inelegant way of preventing cache from growing without bound if ([colorImageCache count]>10) { [colorImageCache removeAllObjects]; } [colorImageCache setObject:(sizeDict=[NSMutableDictionary dictionary]) forKey:color]; } image = [sizeDict objectForKey:sizekey]; if (!image) { image = [[[NSImage alloc] initWithSize:size] autorelease]; [image lockFocus]; [color set]; [[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(1,1,size.width-2,size.height-2)] fill]; [image unlockFocus]; // inelegant way of preventing cache from growing without bound if ([sizeDict count]>10) { [sizeDict removeAllObjects]; } [sizeDict setObject:image forKey:sizekey]; } return image; } -(NSImage *)pieceImageForPlayer:(int)pnum withSize:(NSSize)size { if ([[Preferences sharedInstance] useBitmapPieces]) { return [self bitmapImageWithName:[[Preferences sharedInstance] imageNameForPlayerNumber:pnum] size:size]; } else { return [self solidPieceImageWithColor:[[Preferences sharedInstance] pieceColorForPlayerNumber:pnum] size:size]; } } @end gridlock.app-1.10/MyWindow.m0000644000175000000000000000352510342202542014761 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "MyWindow.h" /** For some reason, after the BoardView is resized, clicks with a height greater than the original height of the BoardView don't get sent to it. This NSWindow subclass overrides -mouseDown to dispatch clicks to the BoardView if the click falls within it. */ @implementation MyWindow -(void)awakeFromNib { NSEnumerator *ve = [[[self contentView] subviews] objectEnumerator]; id view; while (!boardView && (view=[ve nextObject])) { if ([NSStringFromClass([view class]) isEqualToString:@"BoardView"]) { boardView = view; } } } -(void)mouseDown:(NSEvent *)event { if (boardView && [boardView hitTest:[event locationInWindow]]==boardView) { [boardView mouseDown:event]; } else { [super mouseDown:event]; } } @end gridlock.app-1.10/PlayerTurnIndicatorView.m0000644000175000000000000000470710342202543020005 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "PlayerTurnIndicatorView.h" #import "ImageStore.h" @implementation PlayerTurnIndicatorView -(void)awakeFromNib { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePieces) name:@"PlayerColorsChangedNotification" object:nil]; } -(void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; } -(int)playerNumber { return playerNumber; } -(void)setPlayerNumber:(int)pnum { if (playerNumber!=pnum) { playerNumber = pnum; [self setNeedsDisplay:YES]; } } -(BOOL)visible { return visible; } -(void)setVisible:(BOOL)value { if ((value && !visible) || (!value && visible)) { visible = value; [self setNeedsDisplay:YES]; } } -(void)drawRect:(NSRect)theRect { NSRect rect = [self bounds]; NSImage *image = nil; [[NSColor clearColor] set]; [NSBezierPath fillRect:rect]; if (![self visible]) { rect = NSInsetRect(rect, rect.size.width/5, rect.size.height/5); } image = [[ImageStore defaultStore] pieceImageForPlayer:[self playerNumber] withSize:rect.size]; [image dissolveToPoint:rect.origin fraction:([self visible] ? 1.0 : 0.5)]; } -(void)updatePieces { [self setNeedsDisplay:YES]; } @end gridlock.app-1.10/Preferences.m0000644000175000000000000001437010342202543015446 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "Preferences.h" #import "CocoaAdditions.h" static NSDictionary* defaultPreferences() { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:[[NSColor redColor] archivedData_] forKey:@"player1PieceColor"]; [dict setObject:[[NSColor blueColor] archivedData_] forKey:@"player2PieceColor"]; [dict setObject:[[NSColor redColor] archivedData_] forKey:@"player1HighlightColor"]; [dict setObject:[[NSColor blueColor] archivedData_] forKey:@"player2HighlightColor"]; [dict setObject:@"red.tiff" forKey:@"player1ImageName"]; [dict setObject:@"blue.tiff" forKey:@"player2ImageName"]; // these values are strings because GNUstep doesn't seem to work with NSNumbers [dict setObject:@"1" forKey:@"animateCapturedPieces"]; [dict setObject:@"1" forKey:@"useBitmapPieces"]; return dict; } static Preferences *_instance; @implementation Preferences -(id)init { self = [super init]; [[NSUserDefaults standardUserDefaults] registerDefaults:defaultPreferences()]; return self; } +(Preferences *)sharedInstance { if (!_instance) { _instance = [[self alloc] init]; } return _instance; } -(NSColor *)player1PieceColor { return [[NSUserDefaults standardUserDefaults] archivedObjectForKey:@"player1PieceColor"]; } -(void)setPlayer1PieceColor:(NSColor *)value { [[NSUserDefaults standardUserDefaults] setArchivedObject:value forKey:@"player1PieceColor"]; } -(NSColor *)player2PieceColor { return [[NSUserDefaults standardUserDefaults] archivedObjectForKey:@"player2PieceColor"]; } -(void)setPlayer2PieceColor:(NSColor *)value { [[NSUserDefaults standardUserDefaults] setArchivedObject:value forKey:@"player2PieceColor"]; } -(NSColor *)pieceColorForPlayerNumber:(int)pnum { return [self valueForKey:[NSString stringWithFormat:@"player%dPieceColor",pnum]]; } -(NSColor *)player1HighlightColor { return [[NSUserDefaults standardUserDefaults] archivedObjectForKey:@"player1HighlightColor"]; } -(void)setPlayer1HighlightColor:(NSColor *)value { [[NSUserDefaults standardUserDefaults] setArchivedObject:value forKey:@"player1HighlightColor"]; } -(NSColor *)player2HighlightColor { return [[NSUserDefaults standardUserDefaults] archivedObjectForKey:@"player2HighlightColor"]; } -(void)setPlayer2HighlightColor:(NSColor *)value { [[NSUserDefaults standardUserDefaults] setArchivedObject:value forKey:@"player2HighlightColor"]; } -(NSColor *)highlightColorForPlayerNumber:(int)pnum { return [self valueForKey:[NSString stringWithFormat:@"player%dHighlightColor",pnum]]; } -(NSString *)player1ImageName { return [[NSUserDefaults standardUserDefaults] objectForKey:@"player1ImageName"]; } -(void)setPlayer1ImageName:(NSString *)value { [[NSUserDefaults standardUserDefaults] setObject:value forKey:@"player1ImageName"]; } -(NSString *)player2ImageName { return [[NSUserDefaults standardUserDefaults] objectForKey:@"player2ImageName"]; } -(void)setPlayer2ImageName:(NSString *)value { [[NSUserDefaults standardUserDefaults] setObject:value forKey:@"player2ImageName"]; } -(NSString *)imageNameForPlayerNumber:(int)pnum { if (pnum>0) return [self valueForKey:[NSString stringWithFormat:@"player%dImageName",pnum]]; else return @"None"; } -(BOOL)useBitmapPieces { return [[NSUserDefaults standardUserDefaults] integerForKey:@"useBitmapPieces"]; } -(void)setUseBitmapPieces:(BOOL)value { [[NSUserDefaults standardUserDefaults] setInteger:value forKey:@"useBitmapPieces"]; } -(BOOL)animateCapturedPieces { return [[NSUserDefaults standardUserDefaults] integerForKey:@"animateCapturedPieces"]; } -(void)setAnimateCapturedPieces:(BOOL)value { [[NSUserDefaults standardUserDefaults] setInteger:value forKey:@"animateCapturedPieces"]; } -(NSString *)initialGame { return [[NSUserDefaults standardUserDefaults] objectForKey:@"initialGame"]; } -(void)setInitialGame:(NSString *)game { [[NSUserDefaults standardUserDefaults] setObject:game forKey:@"initialGame"]; } -(NSString *)networkUsername { NSString *name = [[NSUserDefaults standardUserDefaults] objectForKey:@"networkUsername"]; if (!name) name = NSUserName(); return name; } -(void)setNetworkUsername:(NSString *)name { [[NSUserDefaults standardUserDefaults] setObject:name forKey:@"networkUsername"]; } -(NSString *)configurationForGame:(NSString *)game { NSString *key = [NSString stringWithFormat:@"config.%@",game]; return [[NSUserDefaults standardUserDefaults] objectForKey:key]; } -(void)setConfiguration:(NSString *)cfg forGame:(NSString *)game { NSString *key = [NSString stringWithFormat:@"config.%@",game]; if (cfg) [[NSUserDefaults standardUserDefaults] setObject:cfg forKey:key]; else [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; } // nil->unassigned, @""->human -(NSString *)aiTypeForGame:(NSString *)game player:(int)player { NSString *key = [NSString stringWithFormat:@"ai.%@.%d",game,player]; return [[NSUserDefaults standardUserDefaults] objectForKey:key]; } -(void)setAIType:(NSString *)aiType forGame:(NSString *)game player:(int)player { NSString *key = [NSString stringWithFormat:@"ai.%@.%d",game,player]; if (aiType==nil) [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; else [[NSUserDefaults standardUserDefaults] setObject:aiType forKey:key]; } @end gridlock.app-1.10/PrefsWindowController.m0000644000175000000000000001273710342202543017525 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "PrefsWindowController.h" #import "Preferences.h" @implementation PrefsWindowController -(void)buildImagePopups { NSArray *popups = [NSArray arrayWithObjects:player1ImagePopup,player2ImagePopup,nil]; NSEnumerator *pe = [popups objectEnumerator]; id popup; while (popup=[pe nextObject]) { NSEnumerator *de = [imageDefinitions objectEnumerator]; id imageDef; [popup removeAllItems]; while (imageDef=[de nextObject]) { [popup addItemWithTitle:[imageDef objectForKey:@"name"]]; [[popup lastItem] setRepresentedObject:imageDef]; } } } -(void)awakeFromNib { radioGroup = [[NSArray alloc] initWithObjects:imageRadioButton,colorRadioButton,nil]; imageDefinitions = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"PieceImages" ofType:@"plist"]]; [self buildImagePopups]; } -(void)dealloc { [radioGroup release]; [imageDefinitions release]; [super dealloc]; } -(void)showWindow { [window makeKeyAndOrderFront:self]; [self updateFromPreferences]; } - (IBAction)cancel:(id)sender { [window orderOut:self]; } -(NSColor *)highlightColorForDictionary:(NSDictionary *)dict { id value = [dict objectForKey:@"highlight"]; if ([value isKindOfClass:[NSString class]]) { return [[NSColor class] performSelector:NSSelectorFromString(value)]; } else if ([value isKindOfClass:[NSDictionary class]]) { float red = [[value objectForKey:@"red"] floatValue]; float green = [[value objectForKey:@"green"] floatValue]; float blue = [[value objectForKey:@"blue"] floatValue]; return [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:1.0]; } return nil; } - (IBAction)applyPreferences:(id)sender { [[Preferences sharedInstance] setPlayer1PieceColor:[player1ColorWell color]]; [[Preferences sharedInstance] setPlayer2PieceColor:[player2ColorWell color]]; [[Preferences sharedInstance] setPlayer1ImageName:[[[player1ImagePopup selectedItem] representedObject] objectForKey:@"file"]]; [[Preferences sharedInstance] setPlayer2ImageName:[[[player2ImagePopup selectedItem] representedObject] objectForKey:@"file"]]; [[Preferences sharedInstance] setAnimateCapturedPieces:([animateCheckbox state]==NSOnState)]; [[Preferences sharedInstance] setUseBitmapPieces:([imageRadioButton state]==NSOnState)]; // use either selected colors or colors defined in plist for highlight colors if ([[Preferences sharedInstance] useBitmapPieces]) { [[Preferences sharedInstance] setPlayer1HighlightColor:[self highlightColorForDictionary:[[player1ImagePopup selectedItem] representedObject]]]; [[Preferences sharedInstance] setPlayer2HighlightColor:[self highlightColorForDictionary:[[player2ImagePopup selectedItem] representedObject]]]; } else { [[Preferences sharedInstance] setPlayer1HighlightColor:[player1ColorWell color]]; [[Preferences sharedInstance] setPlayer2HighlightColor:[player2ColorWell color]]; } [[NSNotificationCenter defaultCenter] postNotificationName:@"PlayerColorsChangedNotification" object:nil]; } -(IBAction)savePreferences:(id)sender { [self applyPreferences:sender]; [window orderOut:self]; } -(NSString *)imageTitleForFilename:(NSString *)file { NSEnumerator *de = [imageDefinitions objectEnumerator]; id def; while (def=[de nextObject]) { if ([file isEqualToString:[def objectForKey:@"file"]]) { return [def objectForKey:@"name"]; } } return nil; } -(void)updateFromPreferences { [player1ColorWell setColor:[[Preferences sharedInstance] player1PieceColor]]; [player2ColorWell setColor:[[Preferences sharedInstance] player2PieceColor]]; [player2ImagePopup selectItemWithTitle:[self imageTitleForFilename:[[Preferences sharedInstance] player2ImageName]]]; [player1ImagePopup selectItemWithTitle:[self imageTitleForFilename:[[Preferences sharedInstance] player1ImageName]]]; [animateCheckbox setState:([[Preferences sharedInstance] animateCapturedPieces] ? NSOnState: NSOffState)]; [imageRadioButton setState:([[Preferences sharedInstance] useBitmapPieces] ? NSOnState : NSOffState)]; [colorRadioButton setState:([[Preferences sharedInstance] useBitmapPieces] ? NSOffState : NSOnState)]; } -(IBAction)radioButtonSelected:(id)sender { NSEnumerator *re = [radioGroup objectEnumerator]; id button; while (button=[re nextObject]) { [button setState:((button==sender) ? NSOnState : NSOffState)]; } } @end gridlock.app-1.10/ReversiAI.m0000644000175000000000000000614410342202543015036 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ReversiAI.h" #import "ReversiGame.h" @implementation ReversiAI -(id)init { self = [super init]; // assign default weights // Reversi strategy says not to grab edges early, but an edgeWeight of 0 loses to 2. edgeWeight = 2.0f; cornerWeight = 8.0f; return self; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { // count cells by middle, edges, and corners int mymiddle=0, myedges=0, mycorners=0, oppmiddle=0, oppedges=0, oppcorners=0; int maxr = [game numberOfRows]-1; int maxc = [game numberOfColumns]-1; int oppnum = [game playerNumberMovingAfterPlayer:pnum]; int mytotal = [[game grid] numberOfCellsWithValue:pnum]; int opptotal = [[game grid] numberOfCellsWithValue:oppnum]; int filledcells = mytotal + opptotal; // value of -1 indicates unplayable "wall" cell, currently not used int totalcells = [[game grid] numberOfCells] - [[game grid] numberOfCellsWithValue:-1]; int r,c; for(r=0; r<=maxr; r++) { for(c=0; c<=maxc; c++) { int isRowEdge = (r==0 || r==maxr); int isColEdge = (c==0 || c==maxc); if (isRowEdge || isColEdge) { // if owned by a player, increment appropriate counter int value = [game valueAtRow:r column:c]; if (value==pnum) { if (isRowEdge && isColEdge) mycorners++; else myedges++; } else if (value>0) { if (isRowEdge && isColEdge) oppcorners++; else oppedges++; } } } } mymiddle = mytotal-myedges-mycorners; oppmiddle = opptotal-oppedges-oppcorners; { // factors decay by the ratio of how many cells in the board are filled float factor = 1.0 - ((float)filledcells)/totalcells; float scale = 100.0f; float middlew = scale; float edgew = scale*(1 + factor*edgeWeight); float cornerw = scale*(1 + factor*cornerWeight); int mypoints = (int)(middlew*mymiddle + edgew*myedges + cornerw*mycorners); int opppoints = (int)(middlew*oppmiddle + edgew*oppedges + cornerw*oppcorners); return mypoints-opppoints; } } @end gridlock.app-1.10/ReversiGame.m0000644000175000000000000001161610342202543015416 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ReversiGame.h" static NSArray *EMPTY_ARRAY; static int ROW_DIRECTIONS[] = {+1,+1,+1, 0, 0,-1,-1,-1}; static int COL_DIRECTIONS[] = {+1, 0,-1,+1,-1,+1, 0,-1}; @implementation ReversiGame +(void)load { EMPTY_ARRAY = [[NSArray alloc] init]; } -(void)reset { [super reset]; [self createGridFromConfiguration]; } // "private" methods // precondition: pos is currently empty -(int)numberOfPositionsCapturedByMoveAtPosition:(id)pos movingByRow:(int)dr column:(int)dc forPlayer:(int)pnum { int myCellValue = pnum; int oppCellValue = [self playerNumberMovingAfterPlayer:pnum]; int r = [pos row]+dr; int c = [pos column]+dc; int count = 0; int good = 0; // set to true if we hit one of our cells int bad = 0; // set to true if we hit a empty or barrier cell // using grid ivar is >10% faster while (!bad && !good && [grid isValidRow:r column:c]) { int value = [grid valueAtRow:r column:c]; if (value==myCellValue) { good = 1; } else if (value==oppCellValue) { count++; } else { bad = 1; } r+=dr; c+=dc; } return (good && !bad) ? count : 0; } -(NSArray *)positionsCapturedByMoveAtPosition:(DCHypergridPosition *)pos forPlayer:(int)pnum { NSMutableArray *array = nil; int i; for(i=0; i<8; i++) { int count = [self numberOfPositionsCapturedByMoveAtPosition:pos movingByRow:ROW_DIRECTIONS[i] column:COL_DIRECTIONS[i] forPlayer:pnum]; if (count>0) { int j; if (!array) array = [NSMutableArray array]; for(j=1; j<=count; j++) { [array addObject:[DCHypergridPosition positionWithRow:([pos row]+j*ROW_DIRECTIONS[i]) column:([pos column]+j*COL_DIRECTIONS[i])]]; } } } return (array ? array : EMPTY_ARRAY); } -(BOOL)areAnyPositionsCapturedByMoveAtPosition:(DCHypergridPosition *)pos forPlayer:(int)pnum { int i; for(i=0; i<8; i++) { int nump = [self numberOfPositionsCapturedByMoveAtPosition:pos movingByRow:ROW_DIRECTIONS[i] column:COL_DIRECTIONS[i] forPlayer:pnum]; if (nump>0) return YES; } return NO; } // end private methods -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:0]; id pos; while (pos=[pe nextObject]) { if ([[self positionsCapturedByMoveAtPosition:pos forPlayer:pnum] count]>0) { [moves addObject:[pos arrayWithSelf_]]; } } if ([moves count]==0) [moves addObject:[NSArray array]]; return moves; } -(BOOL)prepareMoveSequence:(NSArray *)positions { int pnum = [self currentPlayerNumber]; [self resetFutureGrid]; if ([positions count]==0) return YES; if ([positions count]!=1) return NO; else { id pos = [positions lastObject]; NSArray *capturedPositions = [self positionsCapturedByMoveAtPosition:pos forPlayer:pnum]; if ([capturedPositions count]>0) { [[self futureGrid] setValue:pnum atPosition:pos]; [[self futureGrid] setValue:pnum atPositions:capturedPositions]; return YES; } else return NO; } } -(BOOL)isGameOver { // see if either player can move NSEnumerator *pe = [grid positionEnumerator]; id pos; int maxp = [self numberOfPlayers]; while (pos=[pe nextObject]) { if ([grid valueAtPosition:pos]==0) { int p; for(p=1; p<=maxp; p++) { if ([self areAnyPositionsCapturedByMoveAtPosition:pos forPlayer:p]) return NO; } } } return YES; } -(BOOL)showScores { return YES; } @end gridlock.app-1.10/AbstractLineGame.h0000644000175000000000000000261410342202553016344 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface AbstractLineGame : Game { id preparedMove; NSMutableDictionary *_cachedThreatDicts; } -(int)winningLength; -(NSArray *)threatsForPlayer:(int)pnum; // internal methods -(NSArray *)_threatsForPlayer:(int)pnum; -(BOOL)hasPlayerWon:(int)pnum; @end gridlock.app-1.10/AccessorMacros.h0000644000175000000000000000504410342202553016106 0ustar gurkanroot/* Taken from Marcel Weiher's MPWFoundation framework. */ //--- This file expands the accessor macros #define newBool(x) (x ? [[NSNumber numberWithBool:x] retain] : nil) #define newInt(x) [[NSNumber numberWithInt:x] retain] #define newChar(x) [[NSNumber numberWithChar:x] retain] #define makeBool(x) (x ? [NSNumber numberWithBool:x] : nil) #define makeInt(x) [NSNumber numberWithInt:x] #define makeChar(x) [NSNumber numberWithChar:x] #define toInt(x) [x intValue] #define toBool(x) [x boolValue] #define toString(x) [x stringValue] #define ASSIGN_ID(var,value)\ {\ id tempValue=(value);\ if ( tempValue!=var) { \ if ( tempValue!=(id)self ) \ [tempValue retain]; \ if ( var && var!=(id)self) \ [var release]; \ var = tempValue; \ } \ }\ #define setAccessor( var,setVar ) \ -(void)setVar:newVar { \ ASSIGN_ID(var,newVar)\ } \ #define readAccessor( var )\ -var { return var; } #define relayReadAccessor( var, delegate ) \ -var\ {\ if ( var ) {\ return var;\ } else {\ return [delegate var];\ }\ }\ #define idAccessor( var, setVar ) \ readAccessor( var )\ setAccessor(var,setVar ) #define relayAccessor( var, setVar, delegate )\ relayReadAccessor( var , delegate )\ setAccessor( var, setVar ) #define idAccessor_h( var,setVar ) -(void)setVar:newVar; \ -var; #define scalarAccessor( scalarType, var, setVar ) \ -(void)setVar:(scalarType)newVar { var=newVar; } \ -(scalarType)var { return var; } #define scalarAccessor_h( scalarType, var, setVar ) \ -(void)setVar:(scalarType)newVar; \ -(scalarType)var; #define intAccessor( var, setVar ) scalarAccessor( int, var, setVar ) #define intAccessor_h( var, setVar ) scalarAccessor_h( int, var, setVar ) #define floatAccessor(var,setVar ) scalarAccessor( float, var, setVar ) #define floatAccessor_h(var,setVar ) scalarAccessor_h( float, var, setVar ) #define boolAccessor(var,setVar ) scalarAccessor( BOOL, var, setVar ) #define boolAccessor_h(var,setVar ) scalarAccessor_h( BOOL, var, setVar ) //--- compatibility: //#define accessor idAccessor //#define accessor_h idAccessor_h //---- RETAIN/RELEASE Macros for GNUStep compatibility #ifndef RETAIN #define RETAIN(x) ([(x) retain]) #endif #ifndef RELEASE #define RELEASE(x) ([(x) release]) #endif #ifndef AUTORELEASE #define AUTORELEASE(x) ([(x) autorelease]) #endif #ifndef DESTROY #define DESTROY(x) ([(x) release]) #endif #ifndef ASSIGN #define ASSIGN(var,value) ASSIGN_ID(var,value) #endif #ifndef ASSIGNCOPY #define ASSIGNCOPY(var,value) ASSIGN(var,[(value) copy]) #endif gridlock.app-1.10/AppController.h0000644000175000000000000000256710342202553015772 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import #import "BoardView.h" #import "AccessorMacros.h" @interface AppController : NSObject { id prefsController; id clientController; id serverController; id gameController; } idAccessor_h(gameController, setGameController) @end gridlock.app-1.10/AtaxxAI.h0000644000175000000000000000226410342202553014477 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface AtaxxAI : GenericAI { } @end gridlock.app-1.10/AtaxxGame.h0000644000175000000000000000225310342202553015055 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface AtaxxGame : Game { } @end gridlock.app-1.10/AtaxxViewDelegate.h0000644000175000000000000000242107735511413016560 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import @interface AtaxxViewDelegate : NSObject { } -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game; @end gridlock.app-1.10/BoardView.h0000644000175000000000000000644010342202554015063 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import #import "GameHistory.h" #import "AccessorMacros.h" @class BoardView; @protocol BoardViewTarget -(void)boardView:(BoardView *)view clickedAtPosition:(DCHypergridPosition *)pos; -(void)boardView:(BoardView *)view finishedMoveAnimation:(id)callbackObject; -(void)boardView:(BoardView *)view mouseMovedOverPosition:(DCHypergridPosition *)pos; @end @protocol BoardViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect; -(BOOL)disableAnimation; -(BOOL)drawCellAnimatingFromValue:(int)val1 toValue:(int)val2 fraction:(float)frac inRect:(NSRect)rect; -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(Game *)game; @end @interface BoardView : NSView { GameHistory *gameHistory; int moveStartRow; int moveStartColumn; id eventTarget; BOOL inAnimation; int animationFrames; int animationFrameCounter; NSTimer *animationTimer; DCHypergridPosition *lastMouseOverPosition; NSArray *highlightedPositions; // to control flashing of winning pieces NSTimer *flashTimer; NSArray *flashingPositions; BOOL flashState; NSArray *immediateChangePositions; NSArray *animatingPositions; id animationCallbackObject; NSMutableDictionary *pieceImages; id delegate; } idAccessor_h(gameHistory, setGameHistory) idAccessor_h(highlightedPositions, setHighlightedPositions) idAccessor_h(lastMouseOverPosition, setLastMouseOverPosition) idAccessor_h(animatingPositions, setAnimatingPositions) -(Game *)game; -(id )eventTarget; -(void)setEventTarget:(id )obj; -(id )delegate; -(void)setDelegate:(id)delegate; -(float)cellWidth; -(float)cellHeight; -(void)beginMoveAnimationForPositions:(NSArray *)animPositions immediatelyChangingPositions:(NSArray *)immdtPositions callbackObject:(id)obj; -(void)updateColors:(id)sender; -(NSRect)rectForGridPosition:(DCHypergridPosition *)pos; -(void)drawCellAtPosition:(DCHypergridPosition *)position; -(void)finishMove; -(NSArray *)flashingPositions; -(void)setFlashingPositions:(NSArray *)positions; -(BOOL)isPositionFlashing:(id)pos; @end gridlock.app-1.10/BreakthroughAI.h0000644000175000000000000000247510342202554016044 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface BreakthroughAI : GenericAI { int pieceWeight; int use311; float emptyMultiplier; float nextMoveMultiplier; int useAltWeights; float minCellValue; } @end gridlock.app-1.10/CocoaAdditions.h0000644000175000000000000000522110342202554016060 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import @interface NSObject (DCArchivingAdditions) -(NSData *)archivedData_; +(id)objectWithArchivedData_:(NSData *)data; @end @interface NSUserDefaults (DCArchivingAdditions) -(id)archivedObjectForKey:(id)key; -(void)setArchivedObject:(id)obj forKey:(id)key; @end @interface NSArray (DCMiscAdditions) -(id)objectWithValue:(id)searchValue forSelector:(SEL)selector withArgument:(id)arg; -(NSArray *)arrayByIntersectingArray_:(NSArray *)array; -(NSArray *)arrayByRemovingObjectsFromArray_:(NSArray *)array; -(NSArray *)valuesByObjectsPerformingSelector:(SEL)sel; -(NSArray *)valuesByObjectsPerformingSelector:(SEL)sel withObject_:(id)arg; -(NSArray *)arrayWithPrefix_:(NSArray *)prefix; -(NSArray *)arrayWithObjectsInRandomOrder_; -(NSArray *)sortedArrayUsingKey_:(NSString *)key; -(NSArray *)sortedArrayByCount_; @end @interface NSMutableArray (DCMiscAdditions) -(void)randomizeObjects_; -(void)sortArrayUsingKey_:(NSString *)key; -(void)sortArrayByCount_; @end @interface NSPopUpButton (DCAppKitAdditions) -(void)setItemTitles:(NSArray *)titles representedObjects_:(NSArray *)objects; -(BOOL)selectItemWithRepresentedObject_:(id)obj; @end @interface NSTextView (DCAppKitAdditions) -(void)appendText:(NSString *)text scrollToEnd_:(BOOL)scroll; @end /** Resolution independence support. Only available in Tiger, so return the default value of 1.0 if -userSpaceScaleFactor isn't available. */ @interface NSWindow (DCAppKitAdditions) -(float)userSpaceScaleFactor_; @end @interface NSObject (DCMiscAdditions) -(NSArray *)arrayWithSelf_; @end gridlock.app-1.10/ConnectFourAI.h0000644000175000000000000000243310342202554015636 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" #import "ConnectFourGame.h" @interface ConnectFourAI : GenericAI { } -(int)threatWeightForGame:(ConnectFourGame *)game player:(int)pnum; @end gridlock.app-1.10/ConnectFourGame.h0000644000175000000000000000231110342202554016211 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AbstractLineGame.h" @interface ConnectFourGame : AbstractLineGame { } @end gridlock.app-1.10/DCHypergrid.h0000644000175000000000000000602110342202554015340 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "hypergrid.h" #import "DCHypergridPosition.h" @interface DCHypergrid : NSObject { hypergrid *_cgrid; } -(id)initWithNumberOfDimensions:(int)numdim sizes:(int *)sizes; -(id)initWithCHypergrid:(hypergrid *)gridptr; -(id)copy; -(void)copyValuesToGrid:(DCHypergrid *)gridCopy; -(int)numberOfDimensions; -(int)numberOfCells; -(gridvalue_t)valueAtPosition:(DCHypergridPosition *)coords; -(gridvalue_t)valueAtCoordinateArray:(int *)array; -(BOOL)isValidPosition:(DCHypergridPosition *)position; -(BOOL)isValidCoordinateArray:(int *)array; -(BOOL)isValidRow:(int)r column:(int)c; -(id)setValue:(gridvalue_t)value atPosition:(DCHypergridPosition *)coords; -(id)setValue:(gridvalue_t)value atCoordinateArray:(int *)array; -(void)setValue:(gridvalue_t)value atPositions:(NSArray *)positions; -(int)sizeOfDimension:(int)dim; -(int)nonzeroNeighborsOfPosition:(DCHypergridPosition *)coords; -(int)nonzeroNeighborsOfPosition:(DCHypergridPosition *)coords wrapping:(BOOL)wrap; -(int)numberOfNeighborsOfPosition:(DCHypergridPosition *)pos withValue:(int)value; -(int)numberOfCellsWithValue:(int)value; -(BOOL)hasCellWithValue:(int)value; -(BOOL)isEqualToHypergrid:(DCHypergrid *)cmp; -(NSArray *)neighborsOfPosition:(DCHypergridPosition *)coords distance:(int)dist; -(NSEnumerator *)positionEnumerator; -(NSEnumerator *)enumeratorForPositionsWithValue:(int)value; -(DCHypergridPosition *)positionWithValue:(int)value; -(NSArray *)allPositionsWithValue:(int)value; -(NSArray *)connectedGroupsWithValue:(int)value onlyOrthoganal:(BOOL)ortho; -(hypergrid *)cHypergrid; -(id)propertyList; -(id)initFromPropertyList:(id)plist; // convenience methods for 2d grids...put these in a separate category? -(id)initWithRows:(int)r columns:(int)c; +(id)gridWithRows:(int)r columns:(int)c; -(int)valueAtRow:(int)r column:(int)c; -(void)setValue:(int)value atRow:(int)r column:(int)c; -(int)numberOfRows; -(int)numberOfColumns; -(void)dealloc; @end gridlock.app-1.10/DCHypergridPositionEnumerator.h0000644000175000000000000000307010342202554021130 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "DCHypergrid.h" @interface DCHypergridPositionEnumerator : NSEnumerator { DCHypergrid *_grid; int *_coords; int _dimensions; hypergrid *_hypergrid; //IMP positionCreateMethod; //Class positionClass; } -(id)initWithHypergrid:(DCHypergrid *)grid; @end @interface DCHypergridPositionEnumeratorForValue : DCHypergridPositionEnumerator { int targetValue; } -(id)initWithHypergrid:(DCHypergrid *)grid targetValue:(int)value; @end gridlock.app-1.10/DCHypergridPosition.h0000644000175000000000000000372110342202554017071 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import @interface DCHypergridPosition : NSObject { @public int *_data; int _numberOfDimensions; } -(id)initWithSize:(int)cap; -(id)initWithSize:(int)cap data:(int *)values; -(id)initWithRow:(int)r column:(int)c; +(DCHypergridPosition *)positionWithSize:(int)size data:(int *)values; +(DCHypergridPosition *)positionWithRow:(int)r column:(int)c; -(DCHypergridPosition *)positionByAddingPosition:(DCHypergridPosition *)pos; -(DCHypergridPosition *)positionBySubtractingPosition:(DCHypergridPosition *)pos; -(int)compare:(DCHypergridPosition *)pos; -(int)numberOfDimensions; -(int)valueAtIndex:(int)index; -(int)row; -(int)column; -(int *)cArray; -(void)dealloc; -(id)propertyListValue; +(DCHypergridPosition *)positionWithPropertyListValue:(id)value; +(NSArray *)positionArrayFromPropertyListValueArray:(NSArray *)values; -(void)debug; @end gridlock.app-1.10/GameController.h0000644000175000000000000000776710342202555016134 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import #import "GameHistory.h" #import "BoardView.h" #import "PlayerTurnIndicatorView.h" #import "GridlockGameState.h" #import "AccessorMacros.h" @interface GameController : NSObject { // controls in the main window IBOutlet id boardView; IBOutlet id player1ScoreField; IBOutlet id player2ScoreField; IBOutlet id window; IBOutlet id player1TypePopup; IBOutlet id player2TypePopup; IBOutlet id gamePopup; IBOutlet id configurationPopup; IBOutlet id player1LabelField; IBOutlet id player2LabelField; IBOutlet PlayerTurnIndicatorView *player1TurnView; IBOutlet PlayerTurnIndicatorView *player2TurnView; IBOutlet id statusField; IBOutlet id passButton; // Mac OS X will set the drawer ivar, GNUstep will set the window IBOutlet id statisticsDrawer; IBOutlet id statisticsWindow; // controls in the statistics window or drawer IBOutlet id p1Wins; IBOutlet id p2Wins; IBOutlet id aiTimeField; IBOutlet id aiNumMovesEvaluatedField; IBOutlet id aiMovesPerSecondField; IBOutlet id utilityField; IBOutlet id moveRecordTable; // Mac OS X will set the drawer ivar, GNUstep will set the window IBOutlet id networkWindow; IBOutlet id networkDrawer; // controls in the chat window or drawer IBOutlet id chatMessageField; IBOutlet id chatTranscriptArea; IBOutlet id networkStatusField; IBOutlet id disconnectButton; NSArray *availableGames; GridlockGameState *gameState; NSMutableArray *movePositions; BOOL inAnimation; NSMutableArray *playerWins; float widthDelta; int aiMoveID; } idAccessor_h(gameState, setGameState) -(Game *)game; -(NSArray *)movePositions; -(void)setMovePositions:(NSMutableArray *)pos; -(void)appendMovePosition:(id)position; -(void)removeLastPositionFromMove; -(void)clearMovePositions; -(void)updateScores; -(void)boardView:(BoardView *)view clickedAtPosition:(DCHypergridPosition *)pos; -(void)boardView:(BoardView *)view finishedMoveAnimation:(id)callbackObject; -(IBAction)playerTypeUpdated:(id)sender; -(IBAction)configurationSelectedFromPopup:(id)sender; -(IBAction)restartGame:(id)sender; -(IBAction)sendChatMessage:(id)sender; -(IBAction)showNetworkDrawer:(id)sender; -(IBAction)showStatisticsDrawer:(id)sender; -(IBAction)toggleNetworkDrawer:(id)sender; -(IBAction)toggleStatisticsDrawer:(id)sender; -(void)restartGame; -(void)restartGameWithConfiguration:(GameConfiguration *)config; -(BOOL)isWaitingForHumanMove; -(BOOL)isInNetworkGame; // private methods -(void)buildConfigurationPopup; -(void)buildGamePopup; -(void)buildPlayerPopups; -(BOOL)shouldMakeAIMove; -(void)makeAIMove; -(void)cancelPendingAIMoves; -(void)updateNetworkStatus; -(void)gameStateChanged; -(void)doGameOver; -(void)sendMoveToNetworkPlayers:(NSArray *)move; -(void)dropAllNetConnections; -(void)sendRestartToNetworkPlayers; @end gridlock.app-1.10/Game.h0000644000175000000000000003042610342202554014053 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "DCHypergrid.h" #import "AccessorMacros.h" #import "CocoaAdditions.h" @interface Game : NSObject { DCHypergrid *grid; DCHypergrid *futureGrid; int playerNumber; NSDictionary *configurationInfo; int moveCount; int _nrows; int _ncols; } /** Returns true if the given position exists in the game. Subclasses should not need to override. */ -(BOOL)isPositionValid:(DCHypergridPosition *)pos; -(BOOL)isValidRow:(int)row column:(int)col; /** Returns a deep copy of the game, duplicating all state. The default implementation creates a new object of the receiver's class and copies the grid and playerNumber ivars. Subclasses should override if they need to copy additional state, in which case they should also call the superclass implementation. The returned object has a retain count of 1 and should be released by the caller when needed. */ -(Game *)copy; /** Makes the given game a copy of the receiver, by copying all necessary information. The given game can be assumed to have a grid with the same dimensions as the receiver. The default implementation copies the grid values and ivars defined in this class. Superclasses should override to copy additional state if needed. */ -(void)copyValuesToGame:(Game *)newGame; /** Resets the game to its beginning state. Subclasses which override must call the superclass implementation. */ -(void)reset; /** Creates a grid with dimensions and initial positions from the "rows", "cols", and "positions" keys in the game's configurationInfo dictionary. Normally called by subclasses in their -reset methods. */ -(void)createGridFromConfiguration; /** Returns the number of rows in the game board. Default implementation returns [[self grid] numberOfRows]. Subclasses should not override unless they don't use the grid ivar. */ -(int)numberOfRows; /** Returns the number of columns in the game board. Default implementation returns [[self grid] numberOfColumns]. Subclasses should not override unless they don't use the grid ivar. */ -(int)numberOfColumns; /** Returns the DCHypergrid object that the game uses. Default implementation returns the grid ivar; subclasses should not normally need to override. */ idAccessor_h(grid, setGrid) /** Returns the number of moves made in the game. Subclasses should not need to override. */ -(int)moveCount; // accessors for configuration dictionary. The dictionary must not be modified after it is assigned. -(NSDictionary *)configurationInfo; -(void)setConfigurationInfo:(NSDictionary *)value; /** Returns YES if the given array contains positions representing the beginning of a legal move. It should return NO if the array represents a complete move to which no more positions can be added (in which case -isCompleteMoveSequenceValid: would return YES). Should return NO if the the argument is empty or nil. The default implementation examines the moves returned by -allValidMoveSequences. Subclasses *must* override if they implement -allValidMoveSequences in terms of -inferredValidMoveSequences to avoid an infinite loop. */ -(BOOL)isPartialMoveSequenceValid:(NSArray *)positions; /** Returns YES if the given array contains positions represents a complete legal move. It is possible for both -isPartialMoveSequenceValid: and -isCompleteMoveSequenceValid: to return YES for the same array; for example if (A,B) and (A,B,C) are legal moves then both methods should return YES when given an argument of (A,B). If the argument is empty or nil, should return true if a pass is legal. The default implementation examines the moves returned by -allValidMoveSequences. Subclasses *must* override if they implement -allValidMoveSequences in terms of -inferredValidMoveSequences to avoid an infinite loop. */ -(BOOL)isCompleteMoveSequenceValid:(NSArray *)positions; /** Returns YES if a pass is a valid move. Implemented by calling -isCompleteMoveSequenceValid: with a nil argument. Subclasses should not need to override. */ -(BOOL)isPassValid; /** Must be implemented by subclasses. Called when the given move is being considered or about to be made. This method should update internal state so that -positionsOfAllChangingCells and -futureValueAtPosition: return correct values for the given move. Normally a subclass will do this by setting values in the futureGrid ivar (after first calling -resetFutureGrid). If a subclass doesn't use futureGrid, it must override -positionsOfAllChangingCells and -futureValueAtPosition: . The move must be valid; if it is not the results are undefined. */ -(BOOL)prepareMoveSequence:(NSArray *)positions; /** Provides access to the grid which holds the values which the game would have if the move specified in -prepareMoveSequence: were to be executed. Subclasses should update this grid in their implementations of -prepareMoveSequence: . */ -(DCHypergrid *)futureGrid; -(void)setFutureGrid:(DCHypergrid *)value; /** Creates futureGrid if it hasn't been initialized, setting it to a grid equal to the grid ivar. Subclasses will normally call this method at the beginning of -prepareMoveSequence: */ -(void)resetFutureGrid; /** Updates the state of the game by executing the move given in the last call to -prepareMoveSequence: The default implementation copies the values stored by the futureGrid ivar if it is non-nil. If futureGrid is nil, it calls -positionsOfAllChangingCells to get the positions to be updated, and calls -futureValueAtPosition: for each of those positions. Subclasses do not need to override. */ -(void)updateFromPreparedMove; /** Returns all cells which would change state if the move previously specified by a call to -prepareMoveSequence: were to be executed. The default implemenation determines the changed positions by inspecting the futureGrid ivar. Subclasses should override if they don't use futureGrid. */ -(NSArray *)positionsOfAllChangingCells; /** Called when a pass is being considered or about to be made. Implemented by calling -prepareMoveSequence: with a nil argument. Subclasses should not need to override. */ -(BOOL)preparePass; /** Executes the move, updates the present state of the game, and returns YES. The default implementation calls -prepareMoveSequence:, uses -futureValueAtPosition: to update the game state, and calls -moveFinised. Subclasses do not need to override, but can for optimization. The move must be valid; if it is not the results are undefined. */ -(BOOL)makeMoveSequence:(NSArray *)positions; /** Called to execute a pass. Implemented by calling -makeMoveSequence: with a nil argument. Subclasses should not need to override. */ -(BOOL)pass; /** Called when a move has just been made. The default implementation increments the move count and player number, subclasses which override should call the superclass implementation. */ -(void)didMakeMove:(NSArray *)positions; /** Returns the value of the cell at the given position. Default implementation forwards the call to the grid ivar. */ -(int)valueAtPosition:(DCHypergridPosition *)pos; -(int)valueAtRow:(int)r column:(int)c; /** Sets the value of the cell at the given position. Default implementation forwards the call to the grid ivar. */ -(void)setValue:(int)value atPosition:(DCHypergridPosition *)pos; -(void)setValue:(int)value atRow:(int)r column:(int)c; /** Helper method to set the values of multiple cells listed in the given array. The elements of the array must be arrays of 3 objects, all of which respond to -intValue, giving the row, column, and value in that order. Generally this method is used when setting a starting position read from a configuration file (see Games.plist). */ -(void)setGridValuesFromArray:(NSArray *)array; /** Helper method to initialize a game by setting the values of cells in the "first" rows (row 0 and up for player 1, highest numbered row and down for player 2). */ -(void)fillFirstRows:(int)numRows; /** Returns the value that the cell at the given position would have if the move previously specified by a call to -prepareMoveSequence: were to be executed. The default implementation looks in the futureGrid ivar for the future value. Subclasses should override if they don't use futureGrid. */ -(int)futureValueAtPosition:(DCHypergridPosition *)pos; /** Returns the number of players in the game. The default implementation returns 2. */ -(int)numberOfPlayers; /** Must be implemented by subclasses. Returns the number (1-based) of the player whose turn it is. */ -(int)currentPlayerNumber; -(void)setCurrentPlayerNumber:(int)value; /** Returns the player number (1-based) who will move after the given player number. The default implementation returns 1+([self currentPlayerNumber]%[self numberOfPlayers]). */ -(int)playerNumberMovingAfterPlayer:(int)pnum; /** Returns the number (1-based) of the player whose turn it will next be. The default implementation returns [self playerNumberMovingAfterPlayer:[self currentPlayerNumber]]. */ -(int)nextPlayerNumber; /** Sets the player number to the next player. Subclasses should not need to override. */ -(void)incrementPlayerNumber; /** Returns YES if player scores should be shown. The default implentation returns NO. */ -(BOOL)showScores; /** Returns a game-specific score for the given player. The default implementation returns the number of cells with value equal to the player number. */ -(int)scoreForPlayer:(int)pnum; /** Returns the number of the player who has won, or 0 if there is no winner. Should only be called if the game is over (-isGameOver returns YES). The default implementation returns the player with the highest score as determined by -scoreForPlayer:. */ -(int)winningPlayer; /** Returns an array of positions which contain the "winning" pieces. The default implementation returns nil, subclasses should override if applicable (e.g. Connect Four and Gomoku). */ -(NSArray *)positionsOfWinningPieces; /** Must be implemented by subclasses. Returns YES if the game is over, NO if not. */ -(BOOL)isGameOver; /** Must be implemented by subclasses. Returns an array containing all legal move sequences for the current player. Subclasses may implement this method by calling -inferredValidMoveSequences (see below), but if they do, they *must* override -isPartialMoveSequenceValid: and -isCompleteMoveSequenceValid:, since the default implementations of those methods call -allValidMoveSequences, and -inferredValidMoveSequences calls them. */ -(NSArray *)allValidMoveSequences; /** Returns an array containing all legal move sequences for the current player. Used by AI classes. Uses -isPartialMoveSequenceValid: and -isCompleteMoveSequenceValid: to build all possible sequences of valid moves. This method should only ever be called by subclasses as a means of implementing allValidMoveSequences. If this is done, the subclass *must* override -isPartialMoveSequenceValid: and -isCompleteMoveSequenceValid: to avoid infinite recursion. */ -(NSArray *)inferredValidMoveSequences; /** Returns a human-readable description of the given move sequence. The default implementation labels columns as letters starting with 'a', rows as numbers starting with 1, and returns a string like "c4-d5". */ -(NSString *)descriptionForMove:(NSArray *)move; -(DCHypergridPosition *)randomPosition; -(void)fillRandomEmptyCellsWithValue:(int)value count:(int)count; -(id)propertyList; -(void)updateFromPropertyList:(id)plist; @end gridlock.app-1.10/GenericAI.h0000644000175000000000000000427710342202555014776 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" #import "AccessorMacros.h" @interface GenericAI : NSObject { int depth; NSString *name; int useThreads; NSLock *threadLock; NSMutableArray *bestThreadMoves; int dispatchedThreadsCount; NSTimeInterval threadCalcStartTime; } idAccessor_h(name, setName) intAccessor_h(depth, setDepth) intAccessor_h(useThreads, setUseThreads) -(NSArray *)movesToConsiderForGame:(Game *)game; -(NSDictionary *)bestMoveInfoForGame:(Game *)game; -(void)computeBestMoveForGame:(Game *)game; -(int)searchDepthForGame:(Game *)game; -(NSEnumerator *)enumeratorForMovesToConsiderForGame:(Game *)game; /** Returns an integer representing the "value" of the current position for the given player. The default implementation returns the score for the current player minus the score of the next player. Subclasses should override to increase accuracy. */ -(int)relativeUtilityForGame:(Game *)game player:(int)pnum; /** Maps the ratio of the two given utilities to a number between -1 and +1. */ +(double)normalizedRatioOf:(double)u1 to:(double)u2 maxRatio:(double)maxr; @end gridlock.app-1.10/GlassBeadGame.h0000644000175000000000000000225710342202555015623 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface GlassBeadGame : Game { } @end gridlock.app-1.10/GlassBeadViewDelegate.h0000644000175000000000000000246010342202555017313 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import @interface GlassBeadViewDelegate : NSObject { } -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game; -(BOOL)disableAnimation; @end gridlock.app-1.10/GomokuAI.h0000644000175000000000000000241410342202555014652 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" #import "GomokuGame.h" @interface GomokuAI : GenericAI { } -(int)threatWeightForGame:(GomokuGame *)game player:(int)pnum; @end gridlock.app-1.10/GomokuGame.h0000644000175000000000000000230510342202555015231 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AbstractLineGame.h" @interface GomokuGame : AbstractLineGame { } @end gridlock.app-1.10/hypergrid.h0000644000175000000000000001004310342202556015172 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ typedef unsigned int gridvalue_t; typedef struct hypergrid { int num_dimensions; int *dimension_sizes; int num_cells; gridvalue_t *grid_data; } hypergrid; /** Creates a hypergrid with the given number of dimensions and dimension lengths */ hypergrid* hypergrid_create(int dim, int *sizes); /** Copies an existing hypergrid */ hypergrid* hypergrid_copy(hypergrid *srcgrid); /** Deallocates a hypergrid */ void hypergrid_free(hypergrid *gridptr); /** Creates an coords that can be used to access the hypergrid's elements */ int* hypergrid_coords_create(hypergrid *gridptr); /** Deallocates a hypergrid coords */ void hypergrid_coords_free(int *coords); /** Returns true if the given coords is valid for the given hypergrid (i.e. all components are less than the size of the hypergrid's corresponding dimension) */ int hypergrid_coords_isvalid(hypergrid *gridptr, int *coords); /** Increments the coords for the given hypergrid, returns true if successful, 0 if not (i.e. if the coords is at the maximum possible position). If the coords is invalid the results are undefined. */ int hypergrid_coords_increment(hypergrid *gridptr, int *coords); /** Gets the value at the given coords */ gridvalue_t hypergrid_get_value(hypergrid *gridptr, int *coords); /** Sets the value at the given coords */ void hypergrid_set_value(hypergrid *gridptr, int *coords, gridvalue_t value); /** Returns the size of the given dimension */ int hypergrid_dimension_size(hypergrid *gridptr, int dim); /** Returns the number of neighbors of the given coords which have non-zero values. */ /* cmpequal: true to count cells equal to cmpval, false to count cells not equal */ /* wrap: true to wrap around edges of grid */ int hypergrid_neighbor_count(hypergrid *gridptr, int *coords, int cmpequal, gridvalue_t cmpval, int wrap); /** Returns the number of cells in the entire grid with value equal to cmpval */ int hypergrid_value_count(hypergrid *gridptr, int cmpval); /** Returns true if any cells have a value equal to cmpval */ int hypergrid_value_exists(hypergrid *gridptr, int cmpval); /** Returns true if the two hypergrids have equal dimension sizes */ int hypergrid_equal_dimensions(hypergrid *gridptr1, hypergrid *gridptr2); /** Returns true if the two hypergrids have equal dimensions and contents */ int hypergrid_equal(hypergrid *gridptr1, hypergrid *gridptr2); void* hypergrid_archive(hypergrid *gridptr, int *size); hypergrid* hypergrid_unarchive(void *data); int** hypergrid_neighbors(hypergrid *gridptr, int *centercoords, int distance, int *count); void hypergrid_coords_list_free(int **list, int count); /** Adds the components of two arrays and returns a new array. The caller must free the returned array. */ int* array_add(int *arr1, int *arr2, int count); /** Subtracts the components of two arrays and returns a new array. The caller must free the returned array. */ int* array_subtract(int *arr1, int *arr2, int count); // debugging... void hypergrid_debug_coords(hypergrid *gridptr, int *coords); gridlock.app-1.10/ImageStore.h0000644000175000000000000000277010342202555015243 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import @interface ImageStore : NSObject { NSMutableDictionary *colorImageCache; NSMutableDictionary *bitmapImageCache; } +(ImageStore *)defaultStore; -(NSImage *)bitmapImageWithName:(NSString *)name size:(NSSize)size; -(NSImage *)solidPieceImageWithColor:(NSColor *)color size:(NSSize)size; -(NSImage *)pieceImageForPlayer:(int)pnum withSize:(NSSize)size; @end gridlock.app-1.10/CheckersAI.m0000644000175000000000000000357310342202541015147 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "CheckersAI.h" #import "CheckersGame.h" @implementation CheckersAI -(id)init { self = [super init]; regWeight = 1; kingWeight = 2; return self; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { CheckersGame *cgame = game; int myutility = 0; int opputility = 0; int oppnum = [cgame playerNumberMovingAfterPlayer:pnum]; int total = 0; myutility = regWeight*[cgame numberOfRegularPiecesForPlayer:pnum] + kingWeight*[cgame numberOfKingsForPlayer:pnum]; opputility = regWeight*[cgame numberOfRegularPiecesForPlayer:oppnum] + kingWeight*[cgame numberOfKingsForPlayer:oppnum]; total = (myutility-opputility)*1000; total += (int)(1000.0*[[self class] normalizedRatioOf:myutility to:opputility maxRatio:2.0]); return total; } @end gridlock.app-1.10/Preferences.h0000644000175000000000000000465710342202555015453 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import @interface Preferences : NSObject { } +(Preferences *)sharedInstance; -(NSColor *)player1PieceColor; -(void)setPlayer1PieceColor:(NSColor *)value; -(NSColor *)player2PieceColor; -(void)setPlayer2PieceColor:(NSColor *)value; -(NSColor *)pieceColorForPlayerNumber:(int)pnum; -(NSColor *)player1HighlightColor; -(void)setPlayer1HighlightColor:(NSColor *)value; -(NSColor *)player2HighlightColor; -(void)setPlayer2HighlightColor:(NSColor *)value; -(NSColor *)highlightColorForPlayerNumber:(int)pnum; -(NSColor *)pieceColorForPlayerNumber:(int)pnum; -(NSString *)player1ImageName; -(void)setPlayer1ImageName:(NSString *)value; -(NSString *)player2ImageName; -(void)setPlayer2ImageName:(NSString *)value; -(NSString *)imageNameForPlayerNumber:(int)pnum; -(BOOL)useBitmapPieces; -(void)setUseBitmapPieces:(BOOL)value; -(BOOL)animateCapturedPieces; -(void)setAnimateCapturedPieces:(BOOL)value; -(NSString *)initialGame; -(void)setInitialGame:(NSString *)game; -(NSString *)configurationForGame:(NSString *)game; -(void)setConfiguration:(NSString *)cfg forGame:(NSString *)game; -(NSString *)aiTypeForGame:(NSString *)game player:(int)player; -(void)setAIType:(NSString *)aiType forGame:(NSString *)game player:(int)player; -(NSString *)networkUsername; -(void)setNetworkUsername:(NSString *)name; @end gridlock.app-1.10/PlayerTurnIndicatorView.h0000644000175000000000000000247710342202555020005 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import @interface PlayerTurnIndicatorView : NSView { int playerNumber; BOOL visible; } -(int)playerNumber; -(void)setPlayerNumber:(int)pnum; -(void)setVisible:(BOOL)value; @end gridlock.app-1.10/PrefsWindowController.h0000644000175000000000000000333210342202555017512 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import @interface PrefsWindowController : NSObject { IBOutlet id animateCheckbox; IBOutlet id player1ColorWell; IBOutlet id player2ColorWell; IBOutlet id player1ImagePopup; IBOutlet id player2ImagePopup; IBOutlet id imageRadioButton; IBOutlet id colorRadioButton; IBOutlet id window; NSArray *radioGroup; NSArray *imageDefinitions; } -(void)showWindow; -(IBAction)cancel:(id)sender; -(IBAction)savePreferences:(id)sender; -(IBAction)applyPreferences:(id)sender; -(IBAction)radioButtonSelected:(id)sender; -(void)updateFromPreferences; @end gridlock.app-1.10/ReversiAI.h0000644000175000000000000000233710342202555015034 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface ReversiAI : GenericAI { float edgeWeight; float cornerWeight; } @end gridlock.app-1.10/ReversiGame.h0000644000175000000000000000225510342202555015413 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface ReversiGame : Game { } @end gridlock.app-1.10/GNUmakefile.preamble0000644000175000000000000000077410342221763016677 0ustar gurkanroot# # GNUmakefile.preamble - Generated by ProjectCenter # # Additional flags to pass to the preprocessor ADDITIONAL_CPPFLAGS += # Additional flags to pass to Objective C compiler ADDITIONAL_OBJCFLAGS += # Additional flags to pass to C compiler ADDITIONAL_CFLAGS += # Additional flags to pass to the linker ADDITIONAL_LDFLAGS += # Additional include directories the compiler should search ADDITIONAL_INCLUDE_DIRS += # Additional library directories the linker should search ADDITIONAL_LIB_DIRS += gridlock.app-1.10/hypergrid.c0000644000175000000000000003132607720007015015173 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "hypergrid.h" #include #include #include hypergrid* hypergrid_create(int dim, int *sizes) { hypergrid *gridptr = malloc(sizeof(hypergrid)); int i; int totalcells = 1; gridptr->num_dimensions = dim; gridptr->dimension_sizes = malloc(dim*sizeof(int)); for(i=0; idimension_sizes[i] = sizes[i]; totalcells *= sizes[i]; } gridptr->num_cells = totalcells; gridptr->grid_data = calloc(totalcells, sizeof(gridvalue_t)); return gridptr; } hypergrid* hypergrid_copy(hypergrid *srcgrid) { hypergrid *copy = hypergrid_create(srcgrid->num_dimensions, srcgrid->dimension_sizes); memcpy(copy->grid_data, srcgrid->grid_data, srcgrid->num_cells*sizeof(gridvalue_t)); return copy; } void hypergrid_free(hypergrid *gridptr) { free(gridptr->dimension_sizes); free(gridptr->grid_data); free(gridptr); } int* hypergrid_coords_create(hypergrid *gridptr) { int *array = calloc(gridptr->num_dimensions, sizeof(int)); return array; } int* hypergrid_coords_copy(int *coords, int len) { int *array = malloc(len*sizeof(int)); memcpy(array, coords, len*sizeof(int)); return array; } void hypergrid_coords_free(int *coords) { free(coords); } int hypergrid_coords_isvalid(hypergrid *gridptr, int *coords) { int dim = gridptr->num_dimensions; int i; for(i=0; i=gridptr->dimension_sizes[i]) return 0; } return 1; } int hypergrid_coords_increment(hypergrid *gridptr, int *coords) { /* indices are in pseudo-big-endian order, so start incrementing from the last position */ int ndim = gridptr->num_dimensions; int cdim = ndim; while (cdim--) { ++coords[cdim]; if (coords[cdim]dimension_sizes[cdim]) { /* no overflow, we're done */ return 1; } else { /* "carry" to next position */ coords[cdim] = 0; } } /* either coords was the "last" one in the hypergrid or it was invalid */ return 0; } /* "private" method to get the coords into the hypergrid's big 1-d array */ int _compute_coords_index(hypergrid *gridptr, int *coords) { int acc = 0; int placevalue = 1; int i=gridptr->num_dimensions; while (i--) { /* coords[0] is "most" significant, coords[num_dimensions-1] is least */ acc += (coords[i]*placevalue); placevalue *= gridptr->dimension_sizes[i]; } return acc; } gridvalue_t hypergrid_get_value(hypergrid *gridptr, int *coords) { int index = _compute_coords_index(gridptr, coords); return gridptr->grid_data[index]; } void hypergrid_set_value(hypergrid *gridptr, int *coords, gridvalue_t value) { int index = _compute_coords_index(gridptr, coords); gridptr->grid_data[index] = value; } int hypergrid_dimension_size(hypergrid *gridptr, int dim) { return gridptr->dimension_sizes[dim]; } /* "private" method used by hypergrid_neighbor_count */ int _count_neighbors(hypergrid *gridptr, int cmpequal, gridvalue_t cmpval, int baseindex, int dimnum, int placevalue, int wrap) { int next_placevalue = placevalue*gridptr->dimension_sizes[dimnum]; int coord = baseindex / next_placevalue; int newindex; int count = 0; if (dimnum>0) { /* do three recursions corresponding to offsetting coordinate by -1, 0, +1 */ int nextdim = dimnum-1; /* check 0 */ newindex = baseindex; count += _count_neighbors(gridptr, cmpequal, cmpval, newindex, nextdim, next_placevalue, wrap); /* check -1 */ newindex = baseindex-placevalue; /* if it wraps and the wrap flag is set, adjust index and check */ if (newindex<0 || (newindex/next_placevalue!=coord)) { if (wrap) { newindex += next_placevalue; count += _count_neighbors(gridptr, cmpequal, cmpval, newindex, nextdim, next_placevalue, wrap); } } else { /* in range, always check */ count += _count_neighbors(gridptr, cmpequal, cmpval, newindex, nextdim, next_placevalue, wrap); } /* check +1 */ newindex = baseindex+placevalue; /* if it wraps and the wrap flag is set, adjust index and check */ if ((newindex/next_placevalue!=coord)) { if (wrap) { newindex -= next_placevalue; count += _count_neighbors(gridptr, cmpequal, cmpval, newindex, nextdim, next_placevalue, wrap); } } else { /* in range, always check */ count += _count_neighbors(gridptr, cmpequal, cmpval, newindex, nextdim, next_placevalue, wrap); } return count; } else { /* if we've hit dimension 0, return value directly */ /* check 0 */ gridvalue_t *griddata = gridptr->grid_data; newindex = baseindex; if ((cmpequal && griddata[newindex]==cmpval) || (!cmpequal && griddata[newindex]!=cmpval)) ++count; /* check -1 */ newindex = baseindex-placevalue; /* if it wraps and the wrap flag is set, adjust index and check */ if (newindex<0 || (newindex/next_placevalue!=coord)) { if (wrap) { newindex += next_placevalue; if ((cmpequal && griddata[newindex]==cmpval) || (!cmpequal && griddata[newindex]!=cmpval)) ++count; } } else { /* in range, always check */ if ((cmpequal && griddata[newindex]==cmpval) || (!cmpequal && griddata[newindex]!=cmpval)) ++count; } /* check +1 */ newindex = baseindex+placevalue; /* if it wraps and the wrap flag is set, adjust index and check */ if ((newindex/next_placevalue!=coord)) { if (wrap) { newindex -= next_placevalue; if ((cmpequal && griddata[newindex]==cmpval) || (!cmpequal && griddata[newindex]!=cmpval)) ++count; } } else { /* in range, always check */ if ((cmpequal && griddata[newindex]==cmpval) || (!cmpequal && griddata[newindex]!=cmpval)) ++count; } return count; } } /* cmpequal: true to count cells equal to cmpval, false to count cells not equal */ /* wrap: true to wrap around edges of grid */ int hypergrid_neighbor_count(hypergrid *gridptr, int *coords, int cmpequal, gridvalue_t cmpval, int wrap) { int index = _compute_coords_index(gridptr, coords); int count = _count_neighbors(gridptr, cmpequal, cmpval, index, gridptr->num_dimensions-1, 1, wrap); /* we may have just counted the center itself */ if ((cmpequal && gridptr->grid_data[index]==cmpval) || (!cmpequal && gridptr->grid_data[index]!=cmpval)) { --count; } return count; } /** Returns the number of cells in the entire grid with value equal to cmpval */ int hypergrid_value_count(hypergrid *gridptr, int cmpval) { gridvalue_t *values = gridptr->grid_data; int ncells = gridptr->num_cells; int count=0; int i; for(i=0; igrid_data; int ncells = gridptr->num_cells; int i; for(i=0; inum_dimensions; return ( (nd==gridptr2->num_dimensions) && (memcmp(gridptr1->dimension_sizes, gridptr2->dimension_sizes, nd*sizeof(int))==0) ); } /* Returns true if the two hypergrids have equal dimensions and identical values */ int hypergrid_equal(hypergrid *gridptr1, hypergrid *gridptr2) { if (!hypergrid_equal_dimensions(gridptr1, gridptr2)) return 0; else { int nc = gridptr1->num_cells; return ( (nc==gridptr2->num_cells) && (memcmp(gridptr1->grid_data, gridptr2->grid_data, nc*sizeof(gridvalue_t))==0) ); } } /* Returns an array of coordinates containing all neighbors of the given coordinate within the specified distance. The number of neighbors is returned in the count reference parameter. The returned array must be disposed of by calling hypergrid_coords_list_free. */ int** hypergrid_neighbors(hypergrid *gridptr, int *centercoords, int distance, int *count) { /* Extremely inefficient algorith: create a dummy hypergrid whose coordinates represent offsets from the given center coordinate. */ int dim = gridptr->num_dimensions; int *sizes = malloc(dim*sizeof(int)); int mag = 2*distance+1; hypergrid *offsetgrid; int *offsetcoords; int *testcoords = hypergrid_coords_create(gridptr); int i; int done = 0; int **holdingarray; int **retarray; /* create dummy grid */ for(i=0; inum_cells*sizeof(int *)); *count = 0; /* iterate over offset grid */ offsetcoords = hypergrid_coords_create(offsetgrid); while (!done) { /* compute this potential neighbor by applying offset vector */ for(i=0; inum_cells) { retarray = malloc(*count * sizeof(int *)); for(i=0; i<*count; i++) { retarray[i] = holdingarray[i]; } free(holdingarray); } else { /* filled exactly, no need to copy */ retarray = holdingarray; } hypergrid_free(offsetgrid); hypergrid_coords_free(testcoords); hypergrid_coords_free(offsetcoords); return retarray; } void hypergrid_coords_list_free(int **list, int count) { int i; for(i=0; inum_dimensions*sizeof(gridptr->dimension_sizes[0]); int valsize = gridptr->num_cells*sizeof(gridptr->grid_data[0]); *size = sizeof(gridptr->num_dimensions)+dimsize+sizeof(gridptr->num_cells)+valsize; data = malloc(*size); ptr = data; memmove(ptr, &gridptr->num_dimensions, sizeof(gridptr->num_dimensions)); ptr += sizeof(gridptr->num_dimensions); memmove(ptr, &gridptr->num_cells, sizeof(gridptr->num_cells)); ptr += sizeof(gridptr->num_cells); memmove(ptr, gridptr->dimension_sizes, dimsize); ptr += dimsize; memmove(ptr, gridptr->grid_data, valsize); ptr += valsize; return data; } hypergrid* hypergrid_unarchive(void *data) { hypergrid *gridptr = malloc(sizeof(hypergrid)); void *ptr = data; int dimsize, valsize; memmove(&gridptr->num_dimensions, ptr, sizeof(gridptr->num_dimensions)); ptr += sizeof(gridptr->num_dimensions); memmove(&gridptr->num_cells, ptr, sizeof(gridptr->num_cells)); ptr += sizeof(gridptr->num_cells); gridptr->dimension_sizes = malloc(dimsize = gridptr->num_dimensions*sizeof(int)); gridptr->grid_data = malloc(valsize = gridptr->num_cells*sizeof(gridvalue_t)); memmove(gridptr->dimension_sizes, ptr, dimsize); ptr += dimsize; memmove(gridptr->grid_data, ptr, valsize); ptr += valsize; return gridptr; } void hypergrid_debug_coords(hypergrid *gridptr,int *coords) { int i; printf("["); for(i=0; inum_dimensions; i++) { printf("%4d", coords[i]); } printf("]\n"); } gridlock.app-1.10/README.GNUstep0000644000175000000000000000506410342227626015244 0ustar gurkanrootGridlock.app Version 1.10 This file describes how to build and run Gridlock on GNUstep. See the readme.html file for information on how to play. Differences from the Mac OS X version are noted below. In order to compile and run Gridlock, you must have the GNUstep core libraries installed. You can download GNUstep from http://www.gnustep.org. Gridlock was built with gcc 3.3 against the CVS snapshot of GNUstep as of November 26 2005. Earlier or later versions may or may not work correctly. Building -------- You can build Gridlock either from the command line or using ProjectCenter. To build from the command line, make sure you have executed the GNUstep configuration script in (GNUstep root)/System/Makefiles/GNUstep.sh for sh or bash, or (GNUstep root)/System/Makefiles/GNUstep.sh for csh. Once this is done, run: make To build from ProjectCenter, open the PC.pcproj project file, and build from the Build panel. If the build succeeds, it should create the Gridlock.app GNUstep application. Running ------- To run from a command line, execute: openapp Gridlock.app You can also run the application from GWorkspace by double-clicking it. Known Issues ------------ The GNUstep version of Gridlock is built from the same source code as version 1.10 for Mac OS X. Network play between GNUstep and Mac OS X machines should work, and games saved on one platform should be readable on the other. The GNUstep version has the following limitations: - The Mac OS X version detects the number of processors and creates one thread per processor to determine the best move for computer players. The GNUstep version cannot automatically detect the number of processors. To use multiple threads for computing moves, you can set the "CPUPlayerThreads" default to a value greater than 0. (For example, "defaults write Gridlock CPUPlayerThreads 2"). - Resizing the game window does not constrain the game board to maintaining equal width and height, as it does in Mac OS X. - Animations of captured pieces may be slower than they should, due to issues with view redrawing and offscreen images. - Statistics and chat/network information are shown in separate windows rather than in drawers. Also, the statistics window does not display the record of moves that appears in Mac OS X. - Rendezvous support is not available. Feedback -------- The GNUstep port of Gridlock is not well tested. I have built and run it only on an Athlon machine running Debian 3.0 (kernel 2.4.18). Please let me know if it does not work on your system. Email me at brian@dozingcatsoftware.com with any bugs, comments, or suggestions. gridlock.app-1.10/AmbivalenceGame.m0000644000175000000000000000365310342202540016204 0ustar gurkanroot// // AmbivalanceGame.m // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "AmbivalenceGame.h" @implementation AmbivalenceGame -(void)reset { [super reset]; [super createGridFromConfiguration]; } -(NSArray *)allValidMoveSequences { return [[[self grid] allPositionsWithValue:0] valuesByObjectsPerformingSelector:@selector(arrayWithSelf_)]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { if ([positions count]!=1) return NO; [self resetFutureGrid]; id pos = [positions lastObject]; int r = [pos row]; int c = [pos column]; int pnum = [self currentPlayerNumber]; int oppnum = [self nextPlayerNumber]; [[self futureGrid] setValue:pnum atPosition:pos]; int dr,dc; for(dr=-1; dr<=+1; dr++) { for(dc=-1; dc<=+1; dc++) { if (dr!=0 || dc!=0) { if ([self isValidRow:r+dr column:c+dc] && [self valueAtRow:r+dr column:c+dc]==oppnum) { // check for "intrusion" capture, coming in between two opponents kills them both // then check for "custodian" capture, trapping an enemy between two allies kills it if ([self isValidRow:r-dr column:c-dc] && [self valueAtRow:r-dr column:c-dc]==oppnum) { // actually these will get set twice when we check the opposite direction, but that's ok [[self futureGrid] setValue:-1 atPosition:[DCHypergridPosition positionWithRow:r+dr column:c+dc]]; [[self futureGrid] setValue:-1 atPosition:[DCHypergridPosition positionWithRow:r-dr column:c-dc]]; } else if ([self isValidRow:r+2*dr column:c+2*dc] && [self valueAtRow:r+2*dr column:c+2*dc]==pnum) { [[self futureGrid] setValue:-1 atPosition:[DCHypergridPosition positionWithRow:r+dr column:c+dc]]; } } } } } return YES; } -(BOOL)isGameOver { return !([[self grid] hasCellWithValue:0]); } -(BOOL)showScores { return YES; } @end gridlock.app-1.10/DominionGame.m0000644000175000000000000000352110342202542015546 0ustar gurkanroot// // DominionGame.m // Gridlock // // Created by Brian on 9/23/04. // Copyright 2004 __MyCompanyName__. All rights reserved. // #import "DominionGame.h" static int ROW_DIRECTIONS[] = {+1,+1,+1, 0, 0,-1,-1,-1}; static int COL_DIRECTIONS[] = {+1, 0,-1,+1,-1,+1, 0,-1}; @implementation DominionGame -(int)numberOfPositionsCapturedByMoveAtPosition:(id)pos movingByRow:(int)dr column:(int)dc forPlayer:(int)pnum { int myCellValue = pnum; int oppCellValue = [self playerNumberMovingAfterPlayer:pnum]; int r = [pos row]+dr; int c = [pos column]+dc; int count = 0; int good = 0; // set to true if we hit one of our cells int bad = 0; // set to true if we hit a empty or barrier cell // using grid ivar is >10% faster while (!bad && !good && [grid isValidRow:r column:c]) { int value = [grid valueAtRow:r column:c]; if (value==myCellValue) { good = 1; } else if (value==oppCellValue) { count++; } else { bad = 1; } r+=dr; c+=dc; } return (good && !bad) ? count : 0; } -(BOOL)prepareMoveSequence:(NSArray *)positions { int pnum = [self currentPlayerNumber]; id pos = [positions lastObject]; int i; // superclass does Ataxx captures [super prepareMoveSequence:positions]; // then do Reversi captures for(i=0; i<8; i++) { int count = [self numberOfPositionsCapturedByMoveAtPosition:pos movingByRow:ROW_DIRECTIONS[i] column:COL_DIRECTIONS[i] forPlayer:pnum]; int j; for(j=1; j<=count; j++) { [[self futureGrid] setValue:pnum atRow:[pos row]+j*ROW_DIRECTIONS[i] column:[pos column]+j*COL_DIRECTIONS[i]]; } } return YES; } @end gridlock.app-1.10/FusionGame.m0000644000175000000000000000474210342202542015243 0ustar gurkanroot// // FusionGame.m // Gridlock // // Created by Brian on 11/24/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "FusionGame.h" @implementation FusionGame -(void)reset { [super reset]; [self createGridFromConfiguration]; [self fillRandomEmptyCellsWithValue:-1 count:[[[self configurationInfo] objectForKey:@"protons"] intValue]]; } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:-1]; id pos; while (pos=[pe nextObject]) { int r0 = [pos row]; int c0 = [pos column]; int dr, dc; for(dr=-1; dr<=+1; dr++) { for(dc=-1; dc<=+1; dc++) { if (dc==0 && dr==0) continue; // try moves along this direction until we hit an edge or another piece BOOL done = NO; int dist = 0; while (!done) { dist++; int r1 = r0+dist*dr; int c1 = c0+dist*dc; if (![self isValidRow:r1 column:c1] || 0!=[self valueAtRow:r1 column:c1]) { done = YES; } else { // valid move if there's an "atom" adjacent to the destination BOOL valid = NO; int dr2, dc2; for(dr2=-1; dr2<=+1 && !valid; dr2++) { for(dc2=-1; dc2<=+1 && !valid; dc2++) { if ([self isValidRow:r1+dr2 column:c1+dc2] && [self valueAtRow:r1+dr2 column:c1+dc2]>0) { valid = YES; } } } if (valid) [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r1 column:c1], nil]]; } } } } } return moves; } -(BOOL)prepareMoveSequence:(NSArray *)positions { int pnum = [self currentPlayerNumber]; id pos0 = [positions objectAtIndex:0]; id pos1 = [positions objectAtIndex:1]; NSArray *neighbors = [[self grid] neighborsOfPosition:pos1 distance:1]; NSEnumerator *ne = [neighbors objectEnumerator]; id npos; [self resetFutureGrid]; // convert all neighbors to current player while (npos=[ne nextObject]) { if ([self valueAtPosition:npos]!=0) { [[self futureGrid] setValue:pnum atPosition:npos]; } } // force start and destination to correct values [[self futureGrid] setValue:0 atPosition:pos0]; [[self futureGrid] setValue:pnum atPosition:pos1]; return YES; } -(BOOL)isGameOver { return ![[self grid] hasCellWithValue:-1]; } -(BOOL)showScores { return YES; } @end gridlock.app-1.10/FiancoAI.m0000644000175000000000000000306610342202542014615 0ustar gurkanroot// // FiancoAI.m // Gridlock // // Created by Brian on Thu Mar 11 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "FiancoAI.h" @implementation FiancoAI -(int)utilityForGame:(Game *)game player:(int)pnum { int maxr = [game numberOfRows]; int baserow = (pnum==1) ? 0 : maxr-1; int dr = (pnum==1) ? 1 : -1; int utility = 0; int maxUnblockedDist = 0; NSEnumerator *ce = [[game grid] enumeratorForPositionsWithValue:pnum]; id pos; while (pos=[ce nextObject]) { int dist = abs([pos row]-baserow); utility += 100+dist*dist; if (dist>maxUnblockedDist && dist>maxr-4) { // check for unblocked path to end int oppnum = [game playerNumberMovingAfterPlayer:pnum]; int r0 = [pos row]; int c0 = [pos column]; BOOL unblocked = YES; int d; for(d=1; dist+d<=maxr && unblocked; d++) { int r = r0+d*dr; int dc; int crange = ([game currentPlayerNumber]==pnum) ? d-1 : d; for(dc=-crange; dc<=crange && unblocked; dc++) { int c = c0+dc; if ([game isValidRow:r column:c] && oppnum==[game valueAtRow:r column:c]) unblocked = NO; } } if (unblocked) { maxUnblockedDist = dist; //NSLog(@"Found unblocked piece at %@ with distance %d", pos, dist); } } } return utility+10000*maxUnblockedDist; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { return [self utilityForGame:game player:pnum] - [self utilityForGame:game player:[game playerNumberMovingAfterPlayer:pnum]]; } @end gridlock.app-1.10/FiancoGame.m0000644000175000000000000000600210342202542015166 0ustar gurkanroot// // FiancoGame.m // Gridlock // // Created by Brian on Sun Mar 07 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "FiancoGame.h" @implementation FiancoGame -(void)reset { [super reset]; [self createGridFromConfiguration]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { id pos0 = [positions objectAtIndex:0]; id pos1 = [positions objectAtIndex:1]; [self resetFutureGrid]; [[self futureGrid] setValue:0 atPosition:pos0]; [[self futureGrid] setValue:[self valueAtPosition:pos0] atPosition:pos1]; // remove jumped piece if applicable if (abs([pos0 row]-[pos1 row])>1) { [[self futureGrid] setValue:0 atRow:([pos0 row]+[pos1 row])/2 column:([pos0 column]+[pos1 column])/2]; } return YES; } -(void)appendJumpsFromPosition:(DCHypergridPosition *)pos forPlayer:(int)pnum intoArray:(NSMutableArray *)moves { int r = [pos row]; int c = [pos column]; int dr = (pnum==1) ? 1 : -1; int dc; for(dc=-1; dc<=+1; dc+=2) { if ([self isValidRow:r+2*dr column:c+2*dc]) { // must jump over enemy and into empty square int jval = [self valueAtRow:r+dr column:c+dc]; if (jval>0 && jval!=pnum && [self valueAtRow:r+2*dr column:c+2*dc]==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+2*dr column:c+2*dc], nil]]; } } } } -(void)appendNonjumpsFromPosition:(DCHypergridPosition *)pos forPlayer:(int)pnum intoArray:(NSMutableArray *)moves { int r = [pos row]; int c = [pos column]; int dr = (pnum==1) ? 1 : -1; // check left, right, forward if ([self isValidRow:r column:c-1] && [self valueAtRow:r column:c-1]==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r column:c-1], nil]]; } if ([self isValidRow:r column:c+1] && [self valueAtRow:r column:c+1]==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r column:c+1], nil]]; } if ([self isValidRow:r+dr column:c] && [self valueAtRow:r+dr column:c]==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+dr column:c], nil]]; } } -(NSArray *)allValidMoveSequences { NSMutableArray *jumps = [NSMutableArray array]; NSMutableArray *nonjumps = [NSMutableArray array]; int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:pnum]; id pos; while (pos=[pe nextObject]) { [self appendJumpsFromPosition:pos forPlayer:pnum intoArray:jumps]; if ([jumps count]==0) { [self appendNonjumpsFromPosition:pos forPlayer:pnum intoArray:nonjumps]; } } return ([jumps count]>0) ? jumps : nonjumps; } -(int)playerAtLastRow { int c; int maxr = [self numberOfRows]-1; for(c=[self numberOfColumns]-1; c>=0; c--) { if ([self valueAtRow:0 column:c]==2) return 2; if ([self valueAtRow:maxr column:c]==1) return 1; } return 0; } -(BOOL)isGameOver { return [self playerAtLastRow]>0; } -(int)winningPlayer { return [self playerAtLastRow]; } @end gridlock.app-1.10/CatsAndDogsAI.m0000644000175000000000000000262310342202541015545 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "CatsAndDogsAI.h" @implementation CatsAndDogsAI -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { // compare number of empty cells where only one player can move return [[game grid] numberOfCellsWithValue:0-pnum] - [[game grid] numberOfCellsWithValue:0-[game nextPlayerNumber]]; } @end gridlock.app-1.10/DiagonalsGame.h0000644000175000000000000000044210342202554015670 0ustar gurkanroot// // DiagonalsGame.h // Gridlock // // Created by Brian on Sat Jul 10 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "Game.h" @interface DiagonalsGame : Game { id preparedMove; int p1Score; int p2Score; } @end gridlock.app-1.10/CheckersGame.m0000644000175000000000000002612310342202541015523 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "CheckersGame.h" static NSArray* _averagesOfPositionsWithPosition(NSArray *positions, DCHypergridPosition *basepos) { if ([positions count]==0) return nil; else { int r = [basepos row]; int c = [basepos column]; NSMutableArray *array = [NSMutableArray array]; NSEnumerator *pe = [positions objectEnumerator]; id pos; while (pos=[pe nextObject]) { [array addObject:[DCHypergridPosition positionWithRow:(r+[pos row])/2 column:(c+[pos column])/2]]; } return array; } } @implementation CheckersGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; { int rows = [self numberOfRows]; int cols = [self numberOfColumns]; int r,c; // set alternate cells, leaving the two middle rows empty for(r=0; r0) return NO; if ([[self validJumpsForPlayer:pnum fromPosition:pos isKing:king startPosition:pos] count]>0) return NO; } } return YES; } -(int)winningPlayer { return [self nextPlayerNumber]; } -(void)_insertValidJumpsForPlayer:(int)pnum fromPosition:(DCHypergridPosition *)pos isKing:(BOOL)king ignoringJumpedPositions:(NSArray *)previousJumpedPositions startingPositions:(NSArray *)partialMove intoMoveArray:(NSMutableArray *)moves { // get available jumps NSArray *jumps = [self validJumpsForPlayer:pnum fromPosition:pos isKing:king startPosition:[partialMove objectAtIndex:0]]; NSArray *jumpedPositions = _averagesOfPositionsWithPosition(jumps, pos); int i; BOOL foundJump = NO; for(i=0; i<[jumps count]; i++) { if (![previousJumpedPositions containsObject:[jumpedPositions objectAtIndex:i]]) { foundJump = YES; // keep going... [self _insertValidJumpsForPlayer:pnum fromPosition:[jumps objectAtIndex:i] isKing:king ignoringJumpedPositions:[previousJumpedPositions arrayByAddingObject:[jumpedPositions objectAtIndex:i]] startingPositions:[partialMove arrayByAddingObject:[jumps objectAtIndex:i]] intoMoveArray:moves]; } } if (!foundJump) { if ([partialMove count]>=2) { [moves addObject:partialMove]; } } } -(NSArray *)allValidMoveSequences { NSMutableArray *jumps = [NSMutableArray array]; NSMutableArray *nonjumps = [NSMutableArray array]; int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { if (pnum==[self ownerOfPosition:pos]) { BOOL king = [self isKingAtPosition:pos]; // process jumps [self _insertValidJumpsForPlayer:pnum fromPosition:pos isKing:king ignoringJumpedPositions:[NSArray array] startingPositions:[pos arrayWithSelf_] intoMoveArray:jumps]; // process nonjumps if no jumps found if ([jumps count]==0) { NSArray *nonJumpPositions = [self validSingleMovesForPlayer:pnum fromPosition:pos isKing:king]; NSEnumerator *nje = [nonJumpPositions objectEnumerator]; id pos2; while (pos2=[nje nextObject]) { [nonjumps addObject:[NSArray arrayWithObjects:pos, pos2, nil]]; } } } } return ([jumps count]>0) ? jumps : nonjumps; } @end gridlock.app-1.10/FiancoAI.h0000644000175000000000000000036210342202554014607 0ustar gurkanroot// // FiancoAI.h // Gridlock // // Created by Brian on Thu Mar 11 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "GenericAI.h" @interface FiancoAI : GenericAI { } @end gridlock.app-1.10/SabotageAI.m0000644000175000000000000000245710342202543015147 0ustar gurkanroot// // SabotageAI.m // Gridlock // // Created by Brian on 3/28/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "SabotageAI.h" #import "SabotageGame.h" @implementation SabotageAI -(int)utilityForCarrierAtPosition:(id)pos forPlayer:(int)pnum inGame:(SabotageGame *)game { int baseCarrierWeight = 20; static int carrierDistanceWeights[] = {999,20,16,12,8,5,4,3,2,1}; static int numDistanceWeights = 9; id goalpos = [game goalPositionForPlayer:pnum]; int dist = abs([goalpos row]-[pos row])+abs([goalpos column]-[pos column]); if (dist>numDistanceWeights) return baseCarrierWeight; else return baseCarrierWeight+carrierDistanceWeights[dist]; } -(int)relativeUtilityForGame:(SabotageGame *)game player:(int)pnum { int pieceWeight = 10; int oppnum = [game nextPlayerNumber]; int utility = pieceWeight*([[game grid] numberOfCellsWithValue:pnum]-[[game grid] numberOfCellsWithValue:oppnum]); id myCarrierPos = [[game grid] positionWithValue:-pnum]; if (myCarrierPos) utility += [self utilityForCarrierAtPosition:myCarrierPos forPlayer:pnum inGame:game]; else { id oppCarrierPos = [[game grid] positionWithValue:-oppnum]; if (oppCarrierPos) utility -= [self utilityForCarrierAtPosition:oppCarrierPos forPlayer:oppnum inGame:game]; } return utility; } @end gridlock.app-1.10/CheckersViewDelegate.m0000644000175000000000000000547210342202541017223 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "CheckersViewDelegate.h" #import "ImageStore.h" @implementation CheckersViewDelegate idAccessor(alternatingCellColor, setAlternatingCellColor) -(void)dealloc { [self setAlternatingCellColor:nil]; [super dealloc]; } -(void)setAlternateCellColorComponents:(NSString *)str { NSArray *components = [str componentsSeparatedByString:@" "]; [self setAlternatingCellColor:[NSColor colorWithCalibratedRed:[[components objectAtIndex:0] floatValue] green:[[components objectAtIndex:1] floatValue] blue:[[components objectAtIndex:2] floatValue] alpha:1.0]]; } -(void)drawKingForPlayer:(int)pnum inRect:(NSRect)rect { // for kings, draw 2 slightly smaller pieces NSImage *image; float offw = rect.size.width/8; float offh = rect.size.height/8; NSRect smallRect = rect; smallRect.size.width -= offw; smallRect.size.height -= offh; image = [[ImageStore defaultStore] pieceImageForPlayer:pnum withSize:smallRect.size]; [image compositeToPoint:smallRect.origin operation:NSCompositeSourceOver]; smallRect.origin.x += offw; smallRect.origin.y += offh; [image compositeToPoint:smallRect.origin operation:NSCompositeSourceOver]; } // delegate method to draw kings and cells that are always empty -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game { if ((row+col)%2==1 && [self alternatingCellColor]!=nil) { [[self alternatingCellColor] set]; NSRectFill(rect); return YES; } if (value<0 && value>=-2) { [self drawKingForPlayer:-value inRect:rect]; return YES; } return NO; } @end gridlock.app-1.10/CheckersAI.h0000644000175000000000000000233110342202554015135 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface CheckersAI : GenericAI { int regWeight; int kingWeight; } @end gridlock.app-1.10/CheckersGame.h0000644000175000000000000000255710342202554015527 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface CheckersGame : Game { } -(int)ownerOfPosition:(DCHypergridPosition *)pos; -(BOOL)isKingAtPosition:(DCHypergridPosition *)pos; -(int)numberOfRegularPiecesForPlayer:(int)pnum; -(int)numberOfKingsForPlayer:(int)pnum; @end gridlock.app-1.10/CheckersViewDelegate.h0000644000175000000000000000252410342202554017215 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AccessorMacros.h" @interface CheckersViewDelegate : NSObject { NSColor *alternatingCellColor; } idAccessor_h(alternatingCellColor, setAlternatingCellColor) -(void)setAlternatingCellColorComponents:(NSString *)str; @end gridlock.app-1.10/InfoPlist.strings0000644000175000000000000000103007561656770016366 0ustar gurkanrootþÿ/* Localized versions of Info.plist keys */ CFBundleName = "Gridlock"; CFBundleShortVersionString = "Gridlock version 1.3"; CFBundleGetInfoString = "Gridlock version 1.3, Copyright 2002 Brian Nenninger."; NSHumanReadableCopyright = "Copyright 2002 Brian Nenninger"; gridlock.app-1.10/AutoplayController.m0000644000175000000000000001453210342202541017045 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "AutoplayController.h" #import "GameConfiguration.h" #import "GameHistory.h" @implementation AutoplayController -(id)init { if (self=[super init]) { moveStatistics = [[NSMutableDictionary alloc] init]; playerWins = [[NSMutableDictionary alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(aiComputedMoveInfo:) name:@"AIComputedBestMoveNotification" object:nil]; } return self; } -(void)dealloc { [gameState release]; [moveStatistics release]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; } idAccessor(gameState, setGameState) -(GridlockGameState *)createGameState { NSString *gameName = [[NSUserDefaults standardUserDefaults] objectForKey:@"AutoplayGame"]; NSString *variationName = [[NSUserDefaults standardUserDefaults] objectForKey:@"AutoplayVariation"]; GameConfiguration *config = [[[GameConfiguration alloc] initWithName:gameName variation:variationName] autorelease]; GameHistory *history = [[[GameHistory alloc] initWithGameConfiguration:config] autorelease]; GridlockGameState *state = [[[GridlockGameState alloc] init] autorelease]; [state setGameHistory:history]; [state setAIName:[[NSUserDefaults standardUserDefaults] objectForKey:@"AutoplayAI1"] forPlayer:1]; [state setAIName:[[NSUserDefaults standardUserDefaults] objectForKey:@"AutoplayAI2"] forPlayer:2]; return state; } -(void)incrementWinsForPlayer:(int)pnum { id key = [NSNumber numberWithInt:pnum]; int prevWins = [[playerWins objectForKey:key] intValue]; [playerWins setObject:[NSNumber numberWithInt:prevWins+1] forKey:key]; } // compute the average moves per second, which is not the total moves divided by total time -(void)recordStatistics:(NSDictionary *)statsDict forPlayer:(int)pnum { id key = [NSNumber numberWithInt:pnum]; int numMoves = [[statsDict objectForKey:@"positionsEvaluated"] intValue]; double moveTime = [[statsDict objectForKey:@"time"] doubleValue]; double movesPerSecond = ((double)numMoves)/moveTime; NSMutableDictionary *playerStats = [moveStatistics objectForKey:key]; if (!playerStats) { [moveStatistics setObject:playerStats=[NSMutableDictionary dictionary] forKey:key]; [playerStats setObject:[NSNumber numberWithInt:0] forKey:@"numberOfMoves"]; [playerStats setObject:[NSNumber numberWithDouble:0.0] forKey:@"totalMovesPerSecond"]; } [playerStats setObject:[NSNumber numberWithInt:1+[[playerStats objectForKey:@"numberOfMoves"] intValue]] forKey:@"numberOfMoves"]; [playerStats setObject:[NSNumber numberWithDouble:movesPerSecond+[[playerStats objectForKey:@"totalMovesPerSecond"] doubleValue]] forKey:@"totalMovesPerSecond"]; } -(double)averageMovesPerSecondForPlayer:(int)pnum { id key = [NSNumber numberWithInt:pnum]; NSMutableDictionary *playerStats = [moveStatistics objectForKey:key]; int moves = [[playerStats objectForKey:@"numberOfMoves"] intValue]; double totalMPS = [[playerStats objectForKey:@"totalMovesPerSecond"] doubleValue]; return (moves>0) ? totalMPS/moves : 0; } -(void)run { int iters = [[NSUserDefaults standardUserDefaults] integerForKey:@"AutoplayRounds"]; int i; NSString *saveDir = [[NSUserDefaults standardUserDefaults] objectForKey:@"AutoplaySaveDirectory"]; int maxmoves = [[NSUserDefaults standardUserDefaults] integerForKey:@"AutoplayMaxMoves"]; if (maxmoves==0) maxmoves = 500; for(i=0; i0 && [[threat objectForKey:@"openAfter"] intValue]>0); if (length>=[game winningLength]) length=[game winningLength]; total += weights[2*length + openings]; } return total; } @end gridlock.app-1.10/ClientController.h0000644000175000000000000000514110342202554016460 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AccessorMacros.h" #import "NetConnection.h" #import "GameConfiguration.h" @interface ClientController : NSObject { IBOutlet id chatField; IBOutlet id connectionStatusField; IBOutlet id gameInfoField; IBOutlet id hostField; IBOutlet id hostnameCheckbox; IBOutlet id usernameField; IBOutlet id passwordField; IBOutlet id portField; IBOutlet id rendezvousCheckbox; IBOutlet id rendezvousHostsPopup; IBOutlet id windowSizerField; IBOutlet id window; BOOL isWindowExpanded; float windowHeightDelta; NSSize windowDisconnectedSize; NSSize windowConnectedSize; NSFileHandle *socket; NetConnection *netConnection; GameConfiguration *gameConfiguration; id rendezvousBrowser; NSMutableArray *rendezvousServers; int connectionIDCounter; int waitingForConnectionID; } idAccessor_h(socket, setSocket) idAccessor_h(netConnection, setNetConnection) idAccessor_h(gameConfiguration, setGameConfiguration) idAccessor_h(rendezvousBrowser, setRendezvousBrowser) - (IBAction)connect:(id)sender; - (IBAction)connectMethodChanged:(id)sender; - (IBAction)disconnect:(id)sender; - (IBAction)rendezvousHostSelected:(id)sender; - (IBAction)startGame:(id)sender; - (IBAction)updateUsername:(id)sender; -(void)showWindow; -(void)setWindowExpanded:(BOOL)exp display:(BOOL)disp; // private methods -(void)setUseRendezvousServer:(BOOL)value; -(void)setRendezvousEnabled:(BOOL)value; -(void)setupRendezvousDiscovery; -(void)sendConnectMessage; @end gridlock.app-1.10/EDCommonDefines.h0000644000175000000000000001257210342202554016143 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDCommonDefines.h created by erik on Fri 28-Mar-1997 // @(#)$Id: EDCommonDefines.h,v 2.0 2002/08/16 18:12:43 erik Exp $ // // Copyright (c) 1997-2000 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __EDCommonDefines_h_INCLUDE #define __EDCommonDefines_h_INCLUDE // Defines to handle extern declarations on different platforms /*" Ignore this stuff. It is needed thanks to Microsoft's great DLL implementation. "*/ #if defined(__MACH__) #ifdef __cplusplus // This isnt extern "C" because the compiler will not allow this if it has // seen an extern "Objective-C" # define EDCOMMON_EXTERN extern #else # define EDCOMMON_EXTERN extern #endif #elif defined(WIN32) #ifdef _BUILDING_EDCOMMON_DLL # define EDCOMMON_DLL_GOOP __declspec(dllexport) #else # define EDCOMMON_DLL_GOOP __declspec(dllimport) #endif #ifdef __cplusplus # define EDCOMMON_EXTERN extern "C" EDCOMMON_DLL_GOOP #else # define EDCOMMON_EXTERN EDCOMMON_DLL_GOOP extern #endif #else #ifdef __cplusplus # define EDCOMMON_EXTERN extern "C" #else # define EDCOMMON_EXTERN extern #endif #endif /*" Use this if you want to say neither YES nor NO... "*/ #define UNKNOWN 2 /*" A shortcut to get the default notification center "*/ #define DNC [NSNotificationCenter defaultCenter] /*" A shortcut to get the standard user defaults "*/ #define DEFAULTS [NSUserDefaults standardUserDefaults] /*" A shortcut to instantiate a CalendarDate object containing the current time and date "*/ #define NOW [NSCalendarDate calendarDate] // A really useful data type typedef unsigned char byte; // A macro to do asserted casts /*" Don't call this directly. "*/ static __inline__ id EDCast(id object, Class aClass, SEL cmd, id self, const char *file, int line) { if((object != nil) && ([object isKindOfClass:aClass] == NO)) [[NSAssertionHandler currentHandler] handleFailureInMethod:cmd object:self file:[NSString stringWithCString:file] lineNumber:line description:@"cast failure; cannot cast instance of %@ to %@", NSStringFromClass([object class]), NSStringFromClass(aClass)]; return object; } /*" Use this to cast an object pointer to a specific class, eg. !{myString = CAST([array lastObject], NSString)}, asserting that the object really is an instance of the class or one of its subclasses. Raises if the assertion fails."*/ #define CAST(ID, CLASSNAME) \ ((CLASSNAME *)EDCast(ID, [CLASSNAME class], _cmd, self, __FILE__, __LINE__)) /*" A global variable that determines the output generated by the log macros. "*/ EDCOMMON_EXTERN unsigned int EDLogMask; // Macros to conditionally print messages. This looks scary and is in fact a // bad C hack. It is done because this is the only way to prevent the arguments // from even being created if no output would be made anyway. If this would // be implemented as a function and called like, say, // EDLog1(4, @"array = %@", [array description]) // then a poentially large description of the array would be created just // to be discarded if the log mask does not include the area in question. // On the downside, variable argument lists don't work and hence the number of // parameters must be given with the macro name. /*" Function pointer to the function used by the log macros. #NSLog by default. Note that the function does not have to be able to deal with variable arg lists; it is always called with excatly on string argument."*/ EDCOMMON_EXTERN void (*_EDLogFunction)(NSString *); /*" Don't call this directly. "*/ #define EDLogBody(area, format, arg1, arg2, arg3, arg4) \ do { \ if(EDLogMask & area) \ (*_EDLogFunction)([NSString stringWithFormat:format, arg1, arg2, arg3, arg4]); \ } while(0) /*" Log text with format %f and arguments %argN with the logmask specified in %{l}. If !{l & EDLogMask !== 0} the output is supressed and in this case none of the strings are needed. This means that you can pass !{[myObject description]} and the method is only invoked if the output is required."*/ #define EDLog(l, f) EDLogBody((l), (f), 0, 0, 0, 0) #define EDLog1(l, f, arg1) EDLogBody((l), (f), arg1, 0, 0, 0) #define EDLog2(l, f, arg1, arg2) EDLogBody((l), (f), arg1, arg2, 0, 0) #define EDLog3(l, f, arg1, arg2, arg3) EDLogBody((l), (f), arg1, arg2, arg3, 0) #define EDLog4(l, f, arg1, arg2, arg3, arg4) EDLogBody((l), (f), arg1, arg2, arg3, arg4) #endif /* __EDCommonDefines_h_INCLUDE */ gridlock.app-1.10/EDIPSocket.h0000644000175000000000000000522310342202554015071 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDIPSocket.h created by erik // @(#)$Id: EDIPSocket.h,v 2.0 2002/08/16 18:12:47 erik Exp $ // // Copyright (c) 1997-2001 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __EDIPSocket_h_INCLUDE #define __EDIPSocket_h_INCLUDE #import "EDCommonDefines.h" #import "EDSocket.h" struct _EDIPSFlags { unsigned int listening:1; unsigned int connectState:2; unsigned int userAbort:1; }; @interface EDIPSocket : EDSocket { struct _EDIPSFlags flags; /*" All instance variables are private. "*/ } /*" Setting socket options "*/ - (void)setAllowsTransmittingBroadcastMessages:(BOOL)flag; - (void)setAllowsAddressReuse:(BOOL)flag; #ifdef __APPLE__ - (void)setAllowsPortReuse:(BOOL)flag; #endif - (void)setSendTimeout:(NSTimeInterval)aTimeoutVal; - (void)setReceiveTimeout:(NSTimeInterval)aTimeoutVal; /*" Set local endpoint "*/ - (void)setLocalPort:(unsigned short)port; - (void)setLocalPort:(unsigned short)port andAddress:(NSString *)addressString; // If you are looking for info on addresses/ports, check methods in NSFileHandle+NetExt /*" Set remote endpoint "*/ - (void)connectToHost:(NSHost *)host port:(unsigned short)port; - (void)connectToAddress:(NSString *)addressString port:(unsigned short)port; /*" Status "*/ - (BOOL)isConnected; @end /*" Name of an exception which occurs when the connection to a remote port fails due to a timeout. "*/ EDCOMMON_EXTERN NSString *EDSocketTemporaryConnectionFailureException; /*" Name of an exception which occurs when the connection to a remote port is refused. "*/ EDCOMMON_EXTERN NSString *EDSocketConnectionRefusedException; #endif /* __EDIPSocket_h_INCLUDE */ gridlock.app-1.10/EDObjcRuntime.h0000644000175000000000000000554410342202554015637 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDObjcRuntime.h created by znek on Mon 18-Mar-2002 // @(#)$Id: EDObjcRuntime.h,v 2.1 2003/01/25 22:33:43 erik Exp $ // // Copyright (c) 1997-2002 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __EDObjcRuntime_h_INCLUDE #define __EDObjcRuntime_h_INCLUDE #ifndef GNU_RUNTIME /* NeXT RUNTIME */ #import #import #import #import /*" Portable runtime functions. Should be used instead of the corresponding NeXT or GNUStep runtime functions. "*/ #define EDObjcMsgSend(obj, sel) objc_msgSend((obj), (sel)) #define EDObjcMsgSend1(obj, sel, obj1) objc_msgSend((obj), (sel), (obj1)) #define EDObjcMsgSend2(obj, sel, obj1, obj2) objc_msgSend((obj), (sel), (obj1), (obj2)) #define EDObjcMsgSend3(obj, sel, obj1, obj2, obj3) objc_msgSend((obj), (sel), (obj1), (obj2), (obj3)) /*" Defines for runtime types and functions. Should be used instead of the corresponding NeXT and GNUStep runtime functions. (First set is for NeXT, second set for GNU runtimes.)"*/ #define EDObjcMethodInfo Method #define EDObjcClassGetInstanceMethod class_getInstanceMethod #define EDObjcClassGetClassMethod class_getClassMethod #else /* GNU_RUNTIME */ #import #import #define EDObjcMsgSend(obj, sel) objc_msg_lookup((obj), (sel))((obj), (sel)) #define EDObjcMsgSend1(obj, sel, obj1) objc_msg_lookup((obj), (sel))((obj), (sel), (obj1)) #define EDObjcMsgSend2(obj, sel, obj1, obj2) objc_msg_lookup((obj), (sel))((obj), (sel), (obj1), (obj2)) #define EDObjcMsgSend3(obj, sel, obj1, obj2, obj3) objc_msg_lookup((obj), (sel))((obj), (sel), (obj1), (obj2), (obj3)) #define EDObjcMethodInfo Method_t #define EDObjcClassGetInstanceMethod class_get_instance_method #define EDObjcClassGetClassMethod class_get_class_method #endif #endif /* __EDObjcRuntime_h_INCLUDE */ gridlock.app-1.10/EDSocket.h0000644000175000000000000000354310342202554014643 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDSocket.h created by erik // @(#)$Id: EDSocket.h,v 2.0 2002/08/16 18:12:48 erik Exp $ // // Copyright (c) 1997-2000 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __EDSocket_h_INCLUDE #define __EDSocket_h_INCLUDE #import @interface EDSocket : NSFileHandle { NSFileHandle *realHandle; /*" All instance variables are private. "*/ } /*" Describing socket classes "*/ + (int)protocolFamily; + (int)socketType; + (int)socketProtocol; /*" Creating new sockets "*/ + (id)socket; - (id)init; - (id)initWithFileHandle:(NSFileHandle *)aFileHandle; /*" Setting socket options "*/ - (void)setSocketOption:(int)anOption level:(int)aLevel value:(int)value; - (void)setSocketOption:(int)anOption level:(int)aLevel timeValue:(NSTimeInterval)timeout; @end #endif /* __EDSocket_h_INCLUDE */ gridlock.app-1.10/EDTCPSocket.h0000644000175000000000000000323010342202554015203 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDTCPSocket.h created by erik // @(#)$Id: EDTCPSocket.h,v 2.0 2002/08/16 18:12:48 erik Exp $ // // Copyright (c) 1997-2001 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __EDTCPSocket_h_INCLUDE #define __EDTCPSocket_h_INCLUDE #import "EDIPSocket.h" @interface EDTCPSocket : EDIPSocket { } /*" Setting socket options "*/ - (void)setSendsDataImmediately:(BOOL)flag; /*" Server sockets "*/ - (void)startListening; - (void)startListeningOnLocalPort:(unsigned short)aPort; - (void)startListeningOnLocalPort:(unsigned short)aPort andAddress:(NSString *)addressString; @end #endif /* __EDTCPSocket_h_INCLUDE */ gridlock.app-1.10/GameConfiguration.h0000644000175000000000000000412510342202555016601 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface GameConfiguration : NSObject { NSString *gameName; NSString *variationName; Game *initialGame; } -(id)initWithName:(NSString *)name variation:(NSString *)variation; /* +(GameConfiguration *)configurationWithDisplayName:(NSString *)name variationDisplayName:(NSString *)variation; */ +(GameConfiguration *)configurationFromDefaults; -(void)saveToDefaults; -(NSString *)gameName; -(NSString *)variationName; -(NSString *)gameDisplayName; -(NSString *)variationDisplayName; idAccessor_h(initialGame, setInitialGame) -(void)createNewInitialGame; -(Game *)gameInStartingPosition; -(id)aiWithName:(NSString *)aiName; -(id)viewDelegate; +(NSArray *)allGameDisplayNames; +(NSArray *)allGameNames; -(NSArray *)allVariationDisplayNames; -(NSArray *)allVariationNames; // FIXME: handle all AI state in this class -(NSArray *)allAINames; -(NSArray *)allAIDisplayNames; -(id)propertyList; -(id)initFromPropertyList:(id)plist; @end gridlock.app-1.10/GameHistory.h0000644000175000000000000000403010342202555015426 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #include "AccessorMacros.h" #import "GameConfiguration.h" @interface GameHistory : NSObject { NSMutableArray *gameStates; int stateIndex; id gameConfiguration; } -(id)initWithGameConfiguration:(GameConfiguration *)game; -(Game *)currentGame; -(Game *)initialGame; -(void)recordAndExecuteMove:(NSArray *)move; -(BOOL)undoMove; -(BOOL)canUndoMove; -(BOOL)undoMovesUntilPlayerNumberInArray:(NSArray *)pnums; -(BOOL)canUndoMovesUntilPlayerNumberInArray:(NSArray *)pnums; -(BOOL)redoMove; -(BOOL)canRedoMove; -(BOOL)redoMovesUntilPlayerNumberInArray:(NSArray *)pnums; -(BOOL)canRedoMovesUntilPlayerNumberInArray:(NSArray *)pnums; -(id)propertyList; -(id)initFromPropertyList:(id)plist; -(int)numberOfMoves; -(int)currentMoveNumber; -(NSArray *)moveWithNumber:(int)movenum; -(Game *)gameWithNumber:(int)movenum; -(Game *)previousGame; -(NSArray *)previousMove; idAccessor_h(gameConfiguration, setGameConfiguration) @end gridlock.app-1.10/GridlockGameState.h0000644000175000000000000000406410342202555016533 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GameHistory.h" #import "NetConnection.h" #import "GenericAI.h" @interface GridlockGameState : NSObject { GameHistory *gameHistory; NSMutableDictionary *aiPlayers; NSMutableDictionary *networkPlayers; } -(GameHistory *)gameHistory; -(void)setGameHistory:(GameHistory *)value; -(GameConfiguration *)gameConfiguration; -(Game *)currentGame; -(int)currentPlayerNumber; -(BOOL)isPlayerHuman:(int)pnum; -(BOOL)isCurrentPlayerHuman; -(NSArray *)availableAINames; -(NSArray *)availableAIDisplayNames; -(NSString *)aiNameForPlayer:(int)pnum; -(void)setAIName:(NSString *)aiName forPlayer:(int)pnum; -(void)setNetConnection:(NetConnection *)conn forPlayer:(int)pnum; -(void)makePlayerHuman:(int)pnum; -(void)makeAllPlayersHuman; -(int)playerNumberForNetConnection:(NetConnection *)conn; -(NetConnection *)netConnectionForPlayer:(int)pnum; -(BOOL)hasNetConnections; -(NSArray *)allNetConnections; -(void)makeAIMove; -(id)propertyList; @end gridlock.app-1.10/LifeAI.h0000644000175000000000000000226310342202555014272 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface LifeAI : GenericAI { } @end gridlock.app-1.10/LifeGame.h0000644000175000000000000000225210342202555014650 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface LifeGame : Game { } @end gridlock.app-1.10/NSFileHandle+Extensions.h0000644000175000000000000000362110342202555017567 0ustar gurkanroot//--------------------------------------------------------------------------------------- // NSFileHandle+NetExt.h created by erik // @(#)$Id: NSFileHandle+Extensions.h,v 2.0 2002/08/16 18:12:48 erik Exp $ // // Copyright (c) 1997 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __NSFileHandle_NetExt_h_INCLUDE #define __NSFileHandle_NetExt_h_INCLUDE #import // documentation in .m file @interface NSFileHandle(EDExtensions) /*" Endpoints for socket handles "*/ - (unsigned short)localPort; - (NSString *)localAddress; - (unsigned short)remotePort; - (NSString *)remoteAddress; - (NSHost *)remoteHost; /*" Shutdown "*/ - (void)shutdown; - (void)shutdownInput; - (void)shutdownOutput; /*" Non-blocking reads on sockets "*/ - (NSData *)availableDataNonBlocking; - (NSData *)readDataToEndOfFileNonBlocking; - (NSData *)readDataOfLengthNonBlocking:(unsigned int)length; @end #endif /* __NSFileHandle_NetExt_h_INCLUDE */ gridlock.app-1.10/NSObject+Extensions.h0000644000175000000000000000430510342202555017002 0ustar gurkanroot//--------------------------------------------------------------------------------------- // NSObject+Extensions.h created by erik on Sun 06-Sep-1998 // @(#)$Id: NSObject+Extensions.h,v 2.2 2003/01/25 22:33:49 erik Exp $ // // Copyright (c) 1998-2000 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __NSObject_Extensions_h_INCLUDE #define __NSObject_Extensions_h_INCLUDE #import /*" Various common extensions to #NSObject. "*/ @interface NSObject(EDExtensions) /*" Developer notes "*/ - (volatile void)methodIsAbstract:(SEL)selector; - (void)methodIsObsolete:(SEL)selector; - (void)methodIsObsolete:(SEL)selector hint:(NSString *)hint; /*" Class hierarchy "*/ + (NSArray *)subclasses; /*" Mapping an array "*/ - (NSArray *)mapArray:(NSArray *)anArray withSelector:(SEL)aSelector; /*" Repeatedly performing a selector "*/ - (void)performSelector:(SEL)selector withObjects:(NSArray *)objectList; - (void)performSelector:(SEL)selector withObjectsEnumeratedBy:(NSEnumerator *)enumerator; @end IMP EDGetFirstUnusedIMPForSelector(Class aClass, SEL aSelector, BOOL isClassMethod); BOOL EDClassIsSuperclassOfClass(Class aClass, Class subClass); NSArray *EDSubclassesOfClass(Class aClass); #endif /* __NSObject_Extensions_h_INCLUDE */ gridlock.app-1.10/NetConnection.h0000644000175000000000000000324710342202555015752 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AccessorMacros.h" @interface NetConnection : NSObject { NSFileHandle *socket; NSString *remoteUsername; NSMutableData *buffer; int incomingPlistLength; BOOL isDisconnected; BOOL isDeallocating; } idAccessor_h(socket, setSocket) boolAccessor_h(isDisconnected, setIsDisconnected) boolAccessor_h(isDeallocating, setIsDeallocating) idAccessor_h(remoteUsername, setRemoteUsername) +(NetConnection *)connectionWithSocket:(NSFileHandle *)socket; -(NSString *)remoteIPAddress; -(void)transmitPropertyList:(id)plist; -(void)sendDisconnect; @end gridlock.app-1.10/RendezvousUtils.h0000644000175000000000000000250510342202555016365 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import Class nsNetServiceClass_(); Class nsNetServiceBrowserClass_(); BOOL isRendezvousAvailable_(); void getHostAndPortForNetService_(id service, NSString **hostname, int *port); NSString *rendezvousIdentifier_(); gridlock.app-1.10/ServerController.h0000644000175000000000000000427010342202556016514 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AccessorMacros.h" #import "NetConnection.h" #import "GameConfiguration.h" @interface ServerController : NSObject { IBOutlet id chatField; IBOutlet id clientStatusField; IBOutlet id connectionStatusField; IBOutlet id gamePopup; IBOutlet id passwordField; IBOutlet id portField; IBOutlet id variationPopup; IBOutlet id windowSizerField; IBOutlet id window; IBOutlet id usernameField; BOOL isWindowExpanded; float windowHeightDelta; NSFileHandle *serverSocket; NetConnection *netConnection; GameConfiguration *gameConfiguration; id rendezvousService; } idAccessor_h(netConnection, setNetConnection) idAccessor_h(gameConfiguration, setGameConfiguration) idAccessor_h(rendezvousService, setRendezvousService) -(IBAction)abortHosting:(id)sender; -(IBAction)beginHosting:(id)sender; -(IBAction)startGame:(id)sender; -(IBAction)gameSelectedFromPopup:(id)sender; -(IBAction)updateUsername:(id)sender; // private methods -(void)buildGamePopup; -(void)showWindow; -(void)setWindowExpanded:(BOOL)expanded display:(BOOL)display; @end gridlock.app-1.10/functions.h0000644000175000000000000000330510342202556015210 0ustar gurkanroot//--------------------------------------------------------------------------------------- // functions.h created by erik // @(#)$Id: functions.h,v 2.0 2002/08/16 18:12:49 erik Exp $ // // Copyright (c) 1997-2000 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __functions_h_INCLUDE #define __functions_h_INCLUDE #import "osdep.h" /*" Takes an IP address in the POSIX structure and returns an #NSString with the address in the typical dotted number representation. "*/ NSString *EDStringFromInAddr(struct in_addr address); /*" Takes an #NSString with an IP address in the typical dotted number representation and returns the address in the POSIX structure. "*/ struct in_addr EDInAddrFromString(NSString *string); #endif /* __functions_h_INCLUDE */ gridlock.app-1.10/osdep.h0000644000175000000000000001370710342202556014321 0ustar gurkanroot//--------------------------------------------------------------------------------------- // osdep.h created by erik on Wed 28-Jan-1998 // @(#)$Id: osdep.h,v 2.2 2002/08/28 22:09:58 znek Exp $ // // Copyright (c) 1998-1999 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #ifndef __osdep_h_INCLUDE #define __osdep_h_INCLUDE // This file contains stuff that isn't necessarily portable between operating systems. #if defined(sun) //--------------------------------------------------------------------------------------- // Solaris //--------------------------------------------------------------------------------------- #import // UINT_MAX in Solaris 2.8 //#import // UINT_MAX in Solaris < 2.8 #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import // for MAXINT, MAXDOUBLE, etc #import #import #import #import #ifdef __cplusplus extern "C" { #endif extern int res_init(void); extern int gethostname(char *name, int namelen); #ifdef __cplusplus } #endif #import // These are defined in a really funky place in Solaris. #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif // The Solaris man page for errno says that it is thread safe. Dunno how that could be. Either they are refering to perror() and the other functions in the same page, or the -mt thread in the Solaris compiler can do something magic. #import #define ED_ERRNO errno #import #elif WINNT //--------------------------------------------------------------------------------------- // Windows (Yellow Box) //--------------------------------------------------------------------------------------- #import #import #import #import // WinSock has these defined, but puts an #if 0 around them. #define ETIMEDOUT WSAETIMEDOUT #define ECONNREFUSED WSAECONNREFUSED #define ENETDOWN WSAENETDOWN #define ENETUNREACH WSAENETUNREACH #define EHOSTDOWN WSAEHOSTDOWN #define EHOSTUNREACH WSAEHOSTUNREACH // Don't find these anywhere in NT. #define MAXHOSTNAMELEN (256) #define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) #define IN_MULTICAST(i) IN_CLASSD(i) // Misc #define random() rand() #define srandom(seed) srand(seed) #undef alloca // On NT, errno is defined to be '(*_errno())' and presumably this function is thread safe. #import #define ED_ERRNO errno #elif defined(__APPLE__) //--------------------------------------------------------------------------------------- // MacOS X //--------------------------------------------------------------------------------------- #ifdef EDCOMMON_OSXBUILD #define ED_ERRNO errno #import #import #ifndef MAC_OS_X_VERSION_10_2 #import #endif #import #import #import #import #import #import #import #import #import #import #import #else #import #import #import #import #import #import #import #import #import #import #import #import #import #import // For MIN() #import #define ED_ERRNO cthread_errno() #endif #elif defined(__FreeBSD__) //--------------------------------------------------------------------------------------- // FreeBSD //--------------------------------------------------------------------------------------- #define ED_ERRNO errno #import #import #import #import #import #import #import #import #import #import #import #import #import #import #elif defined(linux) //--------------------------------------------------------------------------------------- // Linux //--------------------------------------------------------------------------------------- #define ED_ERRNO errno #import #import #import #import #import #import #import #import #import #import #import #import #else //--------------------------------------------------------------------------------------- // Unknown system //--------------------------------------------------------------------------------------- #error Unknown system! #endif #endif /* __osdep_h_INCLUDE */ gridlock.app-1.10/GravityGame.m0000644000175000000000000000437010342202542015422 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GravityGame.h" static int WIN_LENGTH = 4; @implementation GravityGame -(int)winningLength { return WIN_LENGTH; } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:0]; id pos; while (pos=[pe nextObject]) { BOOL good = NO; int r = [pos row]; int c = [pos column]; int boardSize = [self numberOfRows]; // assuming square board // edges are always legal if (r==0 || c==0 || r==boardSize-1 || c==boardSize-1) good = YES; else { // find the edge or corner closest to the position int dr=0, dc=0; int mid = boardSize/2; int rdiff = (r #import "GenericAI.h" @interface CatsAndDogsAI : GenericAI { } @end gridlock.app-1.10/ClientController.m0000644000175000000000000003067410342202541016472 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ClientController.h" #import "EDTCPSocket.h" #import "Preferences.h" #import "RendezvousUtils.h" @implementation ClientController idAccessor(socket, setSocket) idAccessor(netConnection, setNetConnection) idAccessor(rendezvousBrowser, setRendezvousBrowser) -(id)init { [super init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readPropertyList:) name:@"NetConnectionReadPropertyListNotification" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gotNetworkConnection:) name:@"NetConnectionEstablishedNotification" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkConnectionTerminated:) name:@"NetConnectionTerminatedNotification" object:nil]; rendezvousServers = [[NSMutableArray alloc] init]; return self; } -(void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self setSocket:nil]; [self setNetConnection:nil]; [rendezvousServers release]; [super dealloc]; } idAccessor(gameConfiguration, setGameConfiguration) -(void)awakeFromNib { isWindowExpanded = YES; windowHeightDelta = [windowSizerField frame].origin.y * [window userSpaceScaleFactor_]; [self setUseRendezvousServer:NO]; [self setRendezvousEnabled:NO]; [rendezvousHostsPopup removeAllItems]; // kick off rendezvous discovery... [self setupRendezvousDiscovery]; [connectionStatusField setStringValue:@"Not connected"]; [usernameField setStringValue:[[Preferences sharedInstance] networkUsername]]; [self showWindow]; } -(void)showWindow { [self setWindowExpanded:NO display:NO]; [connectionStatusField setStringValue:@""]; [windowSizerField setStringValue:@""]; [window makeKeyAndOrderFront:nil]; } -(void)setupRendezvousDiscovery { if (isRendezvousAvailable_()) { id browser = [[[nsNetServiceBrowserClass_() alloc] init] autorelease]; [self setRendezvousBrowser:browser]; [browser setDelegate:self]; [browser searchForServicesOfType:@"_gridlock._tcp" inDomain:@""]; } } -(void)setUseRendezvousServer:(BOOL)value { [rendezvousCheckbox setState:(value) ? NSOnState : NSOffState]; [hostnameCheckbox setState:(!value) ? NSOnState : NSOffState]; } -(BOOL)useRendezvousServer { return [rendezvousCheckbox state]==NSOnState; } -(void)setRendezvousEnabled:(BOOL)value { [rendezvousCheckbox setEnabled:value]; [rendezvousHostsPopup setEnabled:value]; if (!value) { [self setUseRendezvousServer:NO]; } } -(void)setWindowExpanded:(BOOL)isExp display:(BOOL)disp { if (isExp && !isWindowExpanded) { // expand NSRect frame = [window frame]; [window setFrame:NSMakeRect(frame.origin.x, frame.origin.y-windowHeightDelta, frame.size.width, frame.size.height+windowHeightDelta) display:disp animate:YES]; } else if (!isExp && isWindowExpanded) { // collapse NSRect frame = [window frame]; [window setFrame:NSMakeRect(frame.origin.x, frame.origin.y+windowHeightDelta, frame.size.width, frame.size.height-windowHeightDelta) display:disp animate:YES]; } isWindowExpanded = isExp; } -(BOOL)hasExistingConnection { // not very nice... return ([[[[[NSApp delegate] gameController] gameState] allNetConnections] count]>0); } -(int)nextConnectionID { return ++connectionIDCounter; } -(NSFileHandle *)connectToHostname:(NSString *)hostname port:(int)port { EDTCPSocket *sock = [EDTCPSocket socket]; NS_DURING [sock connectToHost:[NSHost hostWithName:hostname] port:port]; NSLog(@"Got connection"); NS_HANDLER sock = nil; NS_ENDHANDLER return sock; } -(void)connectInNewThread:(NSDictionary *)dict { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSMutableDictionary *resultDict = [NSMutableDictionary dictionary]; NSFileHandle *sock = [self connectToHostname:[dict objectForKey:@"hostname"] port:[[dict objectForKey:@"port"] intValue]]; [resultDict setObject:[dict objectForKey:@"connectionID"] forKey:@"connectionID"]; if (sock) [resultDict setObject:sock forKey:@"socket"]; [self performSelectorOnMainThread:@selector(connectionCallback:) withObject:resultDict waitUntilDone:YES]; [pool release]; } -(void)connectionCallback:(NSDictionary *)resultDict { // ignore if we weren't waiting for this connection or if we already have one if ([[resultDict objectForKey:@"connectionID"] intValue]!=waitingForConnectionID) return; if ([self hasExistingConnection]) return; if ([resultDict objectForKey:@"socket"]) { [self setSocket:[resultDict objectForKey:@"socket"]]; [self setNetConnection:[NetConnection connectionWithSocket:[self socket]]]; [self sendConnectMessage]; } else { [self setSocket:nil]; [self setNetConnection:nil]; [connectionStatusField setStringValue:@"Unable to connect"]; } } -(void)cancelConnect:(id)sender { if (waitingForConnectionID>0) { waitingForConnectionID = 0; [connectionStatusField setStringValue:@"Connect cancelled"]; } } - (IBAction)connect:(id)sender { NSString *hostname = nil; int port = 0; [self updateUsername:nil]; if ([self hasExistingConnection]) { [connectionStatusField setStringValue:@"Already connected"]; return; } if ([rendezvousCheckbox state]==NSOnState) { id rendezvousService = [[rendezvousHostsPopup selectedItem] representedObject]; getHostAndPortForNetService_(rendezvousService, &hostname, &port); NSLog(@"Using server info from Rendezvous: %@:%d", hostname, port); } else { hostname = [hostField stringValue]; port = [portField intValue]; } if ([hostname length] && port) { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:hostname forKey:@"hostname"]; [dict setObject:[NSNumber numberWithInt:port] forKey:@"port"]; [dict setObject:[NSNumber numberWithInt:(waitingForConnectionID=[self nextConnectionID])] forKey:@"connectionID"]; [connectionStatusField setStringValue:@"Connecting..."]; [NSThread detachNewThreadSelector:@selector(connectInNewThread:) toTarget:self withObject:dict]; } } - (IBAction)connectMethodChanged:(id)sender { if (sender==rendezvousCheckbox) { [hostnameCheckbox setState:NSOffState]; } else { [rendezvousCheckbox setState:NSOffState]; } } - (IBAction)disconnect:(id)sender { [[self socket] closeFile]; [self setSocket:nil]; [self setNetConnection:nil]; [connectionStatusField setStringValue:@"Not connected"]; //[self setWindowExpanded:NO display:YES]; } - (IBAction)rendezvousHostSelected:(id)sender { } -(void)sendConnectMessage { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:@"" forKey:@"connect"]; if ([passwordField stringValue]) [dict setObject:[passwordField stringValue] forKey:@"password"]; [dict setObject:[[Preferences sharedInstance] networkUsername] forKey:@"username"]; [netConnection transmitPropertyList:dict]; } - (IBAction)startGame:(id)sender { NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: [self gameConfiguration], @"configuration", [self netConnection], @"connection", [NSNumber numberWithInt:1], @"playerNumber", nil]; [[NSNotificationCenter defaultCenter] postNotificationName:@"NetConnectionEstablishedNotification" object:self userInfo:dict]; } -(void)readPropertyList:(NSNotification *)notification { if ([self netConnection]==[notification object]) { id plist = [[notification userInfo] objectForKey:@"plist"]; if ([plist objectForKey:@"start"]) { id configPlist = [plist objectForKey:@"configuration"]; NSString *username = [plist objectForKey:@"username"]; [[self netConnection] setRemoteUsername:username]; [self setGameConfiguration:[[[GameConfiguration alloc] initFromPropertyList:configPlist] autorelease]]; if ([self gameConfiguration]) { [self startGame:nil]; } else { [self disconnect:nil]; [connectionStatusField setStringValue:@"Connection Error"]; } } else if ([plist objectForKey:@"refused"]) { [self setSocket:nil]; [connectionStatusField setStringValue:@"Connection refused"]; //[self setWindowExpanded:NO display:YES]; } } } -(IBAction)updateUsername:(id)sender { [[Preferences sharedInstance] setNetworkUsername:[usernameField stringValue]]; } // called when a connection is established (could be from connecting by this window or from server) -(void)gotNetworkConnection:(NSNotification *)notification { [self setSocket:nil]; [self setNetConnection:nil]; [window orderOut:nil]; waitingForConnectionID = 0; } -(void)networkConnectionTerminated:(NSNotification *)notification { } -(void)windowWillClose:(NSNotification *)notification { if (window==[notification object]) { [self cancelConnect:nil]; } } // Rendezvous delegate methods -(void)netServiceBrowserWillSearch:(id)browser { } -(void)netServiceBrowser:(id)browser didFindService:(id)service moreComing:(BOOL)moreComing { [service setDelegate:self]; [service resolve]; if (!moreComing) { } } -(void)netServiceBrowser:(id)browser didRemoveService:(id)service moreComing:(BOOL)moreComing { int index = [rendezvousHostsPopup indexOfItemWithRepresentedObject:service]; [rendezvousServers removeObject:service]; if (index>=0) [rendezvousHostsPopup removeItemAtIndex:index]; if ([rendezvousHostsPopup numberOfItems]==0) { [self setRendezvousEnabled:NO]; } } -(void)netServiceBrowserDidStopSearch:(id)browser { } -(NSString *)displayNameForNetServiceName:(NSString *)serviceName { // the name should have 4 fields separated by ':' NSArray *fields = [serviceName componentsSeparatedByString:@":"]; if ([fields count]<4) return nil; else { NSString *game = [fields objectAtIndex:0]; NSString *variation = [fields objectAtIndex:1]; NSString *username = [fields objectAtIndex:2]; NSString *rendezvousID = [fields objectAtIndex:3]; if ([game length]==0 || [username length]==0 || [rendezvousID length]==0) return nil; // if rendezvousID is the same as ours, it's our own server and we don't want to show it if ([rendezvousID isEqual:rendezvousIdentifier_()]) return nil; if ([variation length]>0) { return [NSString stringWithFormat:@"%@ (%@) - %@", game, variation, username]; } else { return [NSString stringWithFormat:@"%@ - %@", game, username]; } } } -(void)netServiceDidResolveAddress:(id)service { NSString *displayName = [self displayNameForNetServiceName:[service name]]; NSString *ipaddr = nil; int port = 0; getHostAndPortForNetService_(service, &ipaddr, &port); NSLog(@"Resolved service address:%@ port:%d", ipaddr, port); if (displayName) { [rendezvousServers addObject:service]; [rendezvousHostsPopup addItemWithTitle:displayName]; [[rendezvousHostsPopup lastItem] setRepresentedObject:service]; [self setRendezvousEnabled:YES]; } } @end gridlock.app-1.10/EDIPSocket.m0000644000175000000000000003452610342202542015103 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDIPSocket.m created by erik // @(#)$Id: EDIPSocket.m,v 2.1 2002/09/01 19:24:26 erik Exp $ // // Copyright (c) 1997-2001 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #import #import "osdep.h" #import "functions.h" #import "NSFileHandle+Extensions.h" #import "EDIPSocket.h" @interface EDIPSocket(PrivateAPI) - (void)_connectToAddress:(NSString *)hostAddress port:(unsigned short)port hostDescription:(NSString *)hostDesc; @end #ifdef WIN32 #define EDSOCKETHANDLE ((int)[self nativeHandle]) #else #define EDSOCKETHANDLE [self fileDescriptor] #endif #define EDSOCK_HOSTDESCFORADDR NSLocalizedString(@"with the address %@", "Description for a host in error messages when the connection was attempted to a specific IP address. Hope this is localisable because it assumes a specific context, e.g. 'the computer _with_the_address_127.0.0.1_ refused...'") #define EDSOCK_ECONNREFUSED NSLocalizedString(@"The computer %@ refused connection on port %d.", "Message for ECONNREFUSED returned from connect.") #define EDSOCK_ETIMEDOUT NSLocalizedString(@"Timeout when connecting to the computer %@.", "Message for ETIMEDOUT returned from connect.") #define EDSOCK_ENETDOWN NSLocalizedString(@"Attempt to connect to a the computer %@ failed because the computer's network is down.", "Message for ENETDOWN returned from connect.") #define EDSOCK_ENETUNREACH NSLocalizedString(@"Attempt to connect to the computer %@ failed because the computer's network cannot be reached.", "Message for ENETUNREACH returned from connect.") #define EDSOCK_EHOSTDOWN NSLocalizedString(@"Attempt to connect to the computer %@ failed because it is currently inactive.", "Message for EHOSTDOWN returned from connect.") #define EDSOCK_EHOSTUNREACH NSLocalizedString(@"Attempt to connect to the computer %@ failed because no route to it is avaiable.", "Message for EHOSTUNREACH returned from connect.") #define EDSOCK_EOTHER NSLocalizedString(@"Attempt to connect to %@ on port %d failed due to an unexpected error: %s", "Generic message for errors returned from connect.") //--------------------------------------------------------------------------------------- @implementation EDIPSocket //--------------------------------------------------------------------------------------- /*" This class provides methods for basic IP funtionality: binding to a port, connecting to an address, setting popular socket options, etc. It is not meant to be instantiated, though. This is left to its two sublasses #EDTCPSocket and #EDUDPSocket. Note that some (IP) socket related functionality is implemented in a category on NSFileHandle. "*/ NSString *EDSocketTemporaryConnectionFailureException = @"EDSocketTemporaryConnectionFailureException"; NSString *EDSocketConnectionRefusedException = @"EDSocketConnectionRefusedException"; //--------------------------------------------------------------------------------------- // CLASS ATTRIBUTES //--------------------------------------------------------------------------------------- + (int)protocolFamily { return PF_INET; } //--------------------------------------------------------------------------------------- // INIT & DEAlLOC //--------------------------------------------------------------------------------------- - (void)dealloc { if(flags.connectState > 0) [self closeFile]; [super dealloc]; } //--------------------------------------------------------------------------------------- // OPTIONS & PARAMETERS //--------------------------------------------------------------------------------------- /*" Controls whether broadcast messages are allowed. This corresponds to !{SO_BROADCAST}. "*/ - (void)setAllowsTransmittingBroadcastMessages:(BOOL)flag { [self setSocketOption:SO_BROADCAST level:SOL_SOCKET value:flag]; } /*" Controls how quickly an address/port combination can be re-used. With this option set a socket can be connected to a port that is still in !{TIME_WAIT} state which is useful if your server has been shut down, and then restarted right away while sockets are still active on its port. You should be aware that if any unexpected data comes in, it may confuse your server, but while this is possible, it is not likely. This corresponds to !{SO_REUSEADDR}. "*/ - (void)setAllowsAddressReuse:(BOOL)flag { [self setSocketOption:SO_REUSEADDR level:SOL_SOCKET value:flag]; } /*" Controls whether the address/port combination can be shared by multiple sockets. Note that all sockets sharing the address/port must have this option set for it to work. This corresponds !{SO_REUSEPORT} and is currently only implemented on Apple platforms even though other BSD and BSD-derived systems should support it. Note that for multicast addresses this is considered synonymous to !{SO_REUSEADDR} ("TCP/IP Illustrated, Volume 2", p. 731.) So, for portability of multicasting applications you should use #{setAllowsAddressReuse:} instead. "*/ #ifdef __APPLE__ - (void)setAllowsPortReuse:(BOOL)flag { [self setSocketOption:SO_REUSEPORT level:SOL_SOCKET value:flag]; } #endif /*" Sets the timeout for send (write) operations to aTimeoutVal. This corresponds to !{SO_SNDTIMEO}. "*/ - (void)setSendTimeout:(NSTimeInterval)aTimeoutVal { [self setSocketOption:SO_SNDTIMEO level:SOL_SOCKET timeValue:aTimeoutVal]; } /*" Sets the timeout for receive (read) operations to aTimeoutVal. This corresponds to !{SO_RCVTIMEO}. "*/ - (void)setReceiveTimeout:(NSTimeInterval)aTimeoutVal { [self setSocketOption:SO_RCVTIMEO level:SOL_SOCKET timeValue:aTimeoutVal]; } // The next method is for compatibility only - (void)setLocalPortNumber:(unsigned short)port { static int setLocalPortNumberDidLog = 0; if(setLocalPortNumberDidLog == 0) { setLocalPortNumberDidLog = 1; NSLog(@"** method -setLocalPortNumber: in class EDIPSocket is obsolete. Please use -setLocalPort:"); } [self setLocalPort:port]; } /*" Binds the local endpoint of the socket to %aPort on all local IP addresses (interfaces). "*/ - (void)setLocalPort:(unsigned short)aPort { struct in_addr anyAddress; anyAddress.s_addr = htonl(INADDR_ANY); [self setLocalPort:aPort andAddress:EDStringFromInAddr(anyAddress)]; } /*" Binds the local endpoint of the socket to %aPort on the local IP address described by %addressString; the latter being in the "typical" dotted numerical notation. "*/ - (void)setLocalPort:(unsigned short)aPort andAddress:(NSString *)addressString { struct sockaddr_in socketAddress; memset(&socketAddress, 0, sizeof(struct sockaddr_in)); socketAddress.sin_family = AF_INET; socketAddress.sin_addr = EDInAddrFromString(addressString); socketAddress.sin_port = htons(aPort); if(bind(EDSOCKETHANDLE, (struct sockaddr *)&socketAddress, sizeof(socketAddress)) == -1) [NSException raise:NSFileHandleOperationException format:@"Binding of socket to port %d failed: %s", (int)aPort, strerror(ED_ERRNO)]; } //--------------------------------------------------------------------------------------- // CONNECTION SETUP AND SHUTDOWN //--------------------------------------------------------------------------------------- /*" Attempts to connect the remote endpoint of the socket to port on host. "*/ - (void)connectToHost:(NSHost *)host port:(unsigned short)port { NSException *firstTemporaryException = nil; NSEnumerator *hostAddressEnumerator; NSString *hostAddress, *hostDesc; BOOL sawV4Address; NSAssert(flags.connectState == 0, @"already connected"); sawV4Address = NO; hostAddressEnumerator = [[host addresses] objectEnumerator]; while((flags.connectState == 0) && (hostAddress = [hostAddressEnumerator nextObject])) { if([hostAddress rangeOfString:@":"].length > 0) continue; // can't deal with IPv6 addresses yet sawV4Address = YES; NS_DURING hostDesc = [NSString stringWithFormat:@"%@ (%@)", [host name], hostAddress]; [self _connectToAddress:hostAddress port:port hostDescription:hostDesc]; NS_HANDLER if(([[localException name] isEqualToString:EDSocketConnectionRefusedException] == NO) && ([[localException name] isEqualToString:EDSocketTemporaryConnectionFailureException] == NO)) [localException raise]; if(firstTemporaryException == nil) firstTemporaryException = [[localException retain] autorelease]; NS_ENDHANDLER } if(sawV4Address == NO) [NSException raise:NSInvalidArgumentException format:@"Host %@ has no IPv4 address.", host]; if(flags.connectState == 0) [firstTemporaryException raise]; } /*" Attempts to connect the remote endpoint of the socket to port on the host with the IP address described by %addressString; the latter being in the "typical" dotted numerical notation. "*/ - (void)connectToAddress:(NSString *)addressString port:(unsigned short)port { [self _connectToAddress:addressString port:port hostDescription:[NSString stringWithFormat:EDSOCK_HOSTDESCFORADDR, addressString]]; } - (void)_connectToAddress:(NSString *)hostAddress port:(unsigned short)port hostDescription:(NSString *)hostDesc { struct sockaddr_in socketAddress; struct timeval timeout; // fd_set write_fds; //fd_set read_fds; //int result; int origFlags = fcntl(EDSOCKETHANDLE, F_GETFL, 0); timeout.tv_sec = 5; timeout.tv_usec = 0; //if (fcntl(EDSOCKETHANDLE, F_SETFL, O_NONBLOCK)<0) [NSException raise:NSFileHandleOperationException format:EDSOCK_EOTHER, hostDesc, port, strerror(ED_ERRNO)]; NSAssert(flags.connectState == 0, @"already connected"); memset(&socketAddress, 0, sizeof(struct sockaddr_in)); socketAddress.sin_family = AF_INET; socketAddress.sin_addr = EDInAddrFromString(hostAddress); socketAddress.sin_port = htons(port); if(connect(EDSOCKETHANDLE, (struct sockaddr *)&socketAddress, sizeof(socketAddress)) < 0) { switch(ED_ERRNO) { case ECONNREFUSED: [NSException raise:EDSocketConnectionRefusedException format:EDSOCK_ECONNREFUSED, hostDesc, port]; break; case ETIMEDOUT: [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_ETIMEDOUT, hostDesc, port]; break; case ENETDOWN: [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_ENETDOWN, hostDesc, port]; break; case ENETUNREACH: [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_ENETUNREACH, hostDesc, port]; break; case EHOSTDOWN: [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_EHOSTDOWN, hostDesc, port]; break; case EHOSTUNREACH: [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_EHOSTUNREACH, hostDesc, port]; break; case EINPROGRESS: // select on the socket with a 5 second timeout FD_ZERO(&write_fds); FD_SET(EDSOCKETHANDLE, &write_fds); switch (select(getdtablesize(), NULL, &write_fds, NULL, &timeout)) { /* if (ED_ERRNO!=EINTR) { [NSException raise:NSFileHandleOperationException format:EDSOCK_EOTHER, hostDesc, port, strerror(ED_ERRNO)]; } */ case 0: [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_ETIMEDOUT, hostDesc, port]; break; case -1: [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_ETIMEDOUT, hostDesc, port]; default: NSLog(@"Connection is writeable"); flags.connectState = 3; fcntl(EDSOCKETHANDLE, F_SETFL, origFlags); return; } /* if (result<=0) [NSException raise:EDSocketTemporaryConnectionFailureException format:EDSOCK_ETIMEDOUT, hostDesc, port]; break; */ default: [NSException raise:NSFileHandleOperationException format:EDSOCK_EOTHER, hostDesc, port, strerror(ED_ERRNO)]; break; } } fcntl(EDSOCKETHANDLE, F_SETFL, origFlags); flags.connectState = 3; } /*" Returns YES if the socket allows communication, either in both directions or only sending or receiving; the latter resulting from #shutdownInput or #shutdownOutput invocations. (These are implemented in a category on #NSFileHandle.) It only returns NO if the socket is completely disconnected. "*/ - (BOOL)isConnected { return (flags.connectState > 0); } // Semantics for connectState: // 0 - disconnected // 1 - only receives allowed // 2 - only sends allowed // 3 - fully connected - (void)shutdown { [super shutdown]; flags.connectState = 0; } - (void)shutdownInput { [super shutdownOutput]; flags.connectState &= ~1; } - (void)shutdownOutput { [super shutdownOutput]; flags.connectState &= ~2; } - (void)closeFile { if(flags.connectState > 0) { shutdown(EDSOCKETHANDLE, flags.connectState - 1); flags.connectState = 0; } [super closeFile]; } //--------------------------------------------------------------------------------------- @end //--------------------------------------------------------------------------------------- gridlock.app-1.10/EDSocket.m0000644000175000000000000002647110342202542014652 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDSocket.m created by erik // @(#)$Id: EDSocket.m,v 2.0 2002/08/16 18:12:48 erik Exp $ // // Copyright (c) 1997-2000 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #import #import "NSObject+Extensions.h" #import "osdep.h" #import "EDSocket.h" @interface EDSocket(PrivateAPI) - (void)_realHandleNotification:(NSNotification *)notification; @end #ifdef WIN32 #define EDSOCKETHANDLE ((int)[self nativeHandle]) #else #define EDSOCKETHANDLE [self fileDescriptor] #endif //--------------------------------------------------------------------------------------- @implementation EDSocket //--------------------------------------------------------------------------------------- /*" This class and its subclasses provide an object-oriented interface for socket programming. #EDSocket inherits from #NSFileHandle and acts as a common base class. This is a fairly natural choice as a socket is really a special file handle and NSFileHandle actually contains some useful methods to deal with socket functionality, #acceptConnectionInBackgroundAndNotify for example. However, NSFileHandle does not provide a means to create and connect sockets. The interesting part is that NSFileHandle (in Apple's implementation) is a class cluster and all the caveats of subclassing such a thing apply. Hence, most of the code in EDSocket is dealing with general infrastructure. At the moment there is only on subclass, namely #EDIPSocket representing the protocol family !{inet}. There are, however, a lot of other families that you might want to support; Unix domain sockets or Appletalk for example. Note that some socket related functionality is implemented in a category on NSFileHandle. "*/ //--------------------------------------------------------------------------------------- // CLASS ATTRIBUTES //--------------------------------------------------------------------------------------- /*" Must be overriden to return the protocol family for the socket class; for example !{PF_INET} for IP sockets. "*/ + (int)protocolFamily { [self methodIsAbstract:_cmd]; return NSNotFound; // keep compiler happy } /*" Must be overriden to return the protocol for the socket class; for example !{IPPROTO_TCP} for TCP sockets. "*/ + (int)socketProtocol { [self methodIsAbstract:_cmd]; return NSNotFound; // keep compiler happy } /*" Must be overriden to return the type for the socket class; for example !{SOCK_STREAM} for TCP sockets. "*/ + (int)socketType { [self methodIsAbstract:_cmd]; return NSNotFound; // keep compiler happy } //--------------------------------------------------------------------------------------- // CONSTRUCTORS //--------------------------------------------------------------------------------------- /*" Creates and returns a socket. Of course, subclasses inherit this method which means a TCP socket can be created as !{[EDTCPSocket socket]}. "*/ + (id)socket { return [[[self alloc] init] autorelease]; } //--------------------------------------------------------------------------------------- // INITIALIZATION & DEALLOC //--------------------------------------------------------------------------------------- /*" Initialises a newly allocated socket by creating a POSIX socket with the protocol family, protocol and type as defined by the corresponding class methods. "*/ - (id)init { int socketDesc; self = [super init]; if((socketDesc = socket([isa protocolFamily], [isa socketType], [isa socketProtocol])) < 0) { [self release]; [NSException raise:NSFileHandleOperationException format:@"Failed to create a socket: %s", strerror(ED_ERRNO)]; } #ifdef WIN32 realHandle = [[NSFileHandle allocWithZone:[self zone]] initWithNativeHandle:(HANDLE)socketDesc closeOnDealloc:YES]; #else realHandle = [[NSFileHandle allocWithZone:[self zone]] initWithFileDescriptor:socketDesc closeOnDealloc:YES]; #endif [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_realHandleNotification:) name:nil object:realHandle]; return self; } /*" Initialises a newly allocated socket by wrapping %aFileHandle. The file handle's file descriptor must represent a socket. "*/ - (id)initWithFileHandle:(NSFileHandle *)aFileHandle { self = [super init]; realHandle = [aFileHandle retain]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_realHandleNotification:) name:nil object:realHandle]; return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; // to be sure [realHandle release]; [super dealloc]; } //--------------------------------------------------------------------------------------- // SOCKET OPTIONS //--------------------------------------------------------------------------------------- /*" Sets the socket option described by %anOption on protocol level %aLevel to %value. You should not call this method directly but use the "appropriatly" named methods in subclasses, e.g. #{setAllowsAddressReuse:} or #{setSendsDataImmediately:}. "*/ - (void)setSocketOption:(int)anOption level:(int)aLevel value:(int)value { if(setsockopt(EDSOCKETHANDLE, aLevel, anOption, (char *)&value, sizeof(value)) == -1) [NSException raise:NSFileHandleOperationException format:@"Failed to set option %d on socket: %s", anOption, strerror(ED_ERRNO)]; } /*" Sets the socket option described by %anOption on protocol level %aLevel to %timeout. You should not call this method directly but use the "appropriatly" named methods in subclasses, e.g. #{setSendTimeout:}. "*/ - (void)setSocketOption:(int)anOption level:(int)aLevel timeValue:(NSTimeInterval)timeout { struct timeval _timeout; _timeout.tv_sec = (int)timeout; _timeout.tv_usec = (int) ((timeout - floor(timeout)) * (double)1000000); if(setsockopt(EDSOCKETHANDLE, aLevel, anOption, (struct timeval *)&_timeout, sizeof(_timeout)) == -1) [NSException raise:NSFileHandleOperationException format:@"Failed to set option %d on socket: %s", anOption, strerror(ED_ERRNO)]; } //--------------------------------------------------------------------------------------- // OVERRIDES //--------------------------------------------------------------------------------------- - (NSData *)availableData { return [realHandle availableData]; } - (NSData *)readDataToEndOfFile { return [realHandle readDataToEndOfFile]; } - (NSData *)readDataOfLength:(unsigned int)length { return [realHandle readDataOfLength:length]; } - (void)writeData:(NSData *)data { [realHandle writeData:data]; } - (unsigned long long)offsetInFile { [NSException raise:NSInternalInconsistencyException format:@"-[%@ %@]: Operation not allowed on sockets.", NSStringFromClass(isa), NSStringFromSelector(_cmd)]; return 0;// keep Compiler happy } - (unsigned long long)seekToEndOfFile { return [realHandle seekToEndOfFile]; } - (void)seekToFileOffset:(unsigned long long)offset { return [realHandle seekToFileOffset:offset]; } - (void)truncateFileAtOffset:(unsigned long long)offset { [realHandle truncateFileAtOffset:offset]; } - (void)synchronizeFile { return [realHandle synchronizeFile]; } - (void)closeFile { [realHandle closeFile]; } - (int)fileDescriptor { return [realHandle fileDescriptor]; } #ifdef WIN32 - (void *)nativeHandle { return [realHandle nativeHandle]; } #endif #ifdef GNUSTEP // The GNUstep implementation differs from Apple's implementation in several respects. // Most notably the NSFileHandle class in GNUstep is an abstract class as opposed to Apple's // implementation which contains most of the code. The following methods are known to // be implemented in Apple's NSFileHandle but NOT in GNUstep's NSFileHandle. We // thus have to forward these methods to GNUstep's realHandle. - (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray *)modes { [realHandle acceptConnectionInBackgroundAndNotifyForModes:(NSArray *)modes]; } - (void)acceptConnectionInBackgroundAndNotify { [realHandle acceptConnectionInBackgroundAndNotify]; } - (void)readInBackgroundAndNotifyForModes:(NSArray *)modes { [realHandle readInBackgroundAndNotifyForModes:(NSArray *)modes]; } - (void)readInBackgroundAndNotify { [realHandle readInBackgroundAndNotify]; } - (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray *)modes { [realHandle readToEndOfFileInBackgroundAndNotifyForModes:(NSArray *)modes]; } - (void)readToEndOfFileInBackgroundAndNotify { [realHandle readToEndOfFileInBackgroundAndNotify]; } - (void)waitForDataInBackgroundAndNotifyForModes:(NSArray *)modes { [realHandle waitForDataInBackgroundAndNotifyForModes:(NSArray *)modes]; } - (void)waitForDataInBackgroundAndNotify { [realHandle waitForDataInBackgroundAndNotify]; } #endif //--------------------------------------------------------------------------------------- // FORWARDS // We know that certain messages declared in our super class are, in fact, not // implemented in it. Hence, we don't need to override them and can use the // forwarding mechanism. //--------------------------------------------------------------------------------------- - (void)forwardInvocation:(NSInvocation *)invocation { if([realHandle respondsToSelector:[invocation selector]]) [invocation invokeWithTarget:realHandle]; else [self doesNotRecognizeSelector:[invocation selector]]; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature *s; if((s = [super methodSignatureForSelector:aSelector]) != nil) return s; return [realHandle methodSignatureForSelector:aSelector]; } - (BOOL)respondsToSelector:(SEL)aSelector { if([super respondsToSelector:aSelector] == YES) return YES; return [realHandle respondsToSelector:aSelector]; } //--------------------------------------------------------------------------------------- // NOTIFICATION RESENDING //--------------------------------------------------------------------------------------- - (void)_realHandleNotification:(NSNotification *)notification { [[NSNotificationCenter defaultCenter] postNotificationName:[notification name] object:self userInfo:[notification userInfo]]; } //--------------------------------------------------------------------------------------- @end //--------------------------------------------------------------------------------------- gridlock.app-1.10/EDTCPSocket.m0000644000175000000000000001273110342202542015213 0ustar gurkanroot//--------------------------------------------------------------------------------------- // EDTCPSocket.m created by erik // @(#)$Id: EDTCPSocket.m,v 2.0 2002/08/16 18:12:48 erik Exp $ // // Copyright (c) 1997-2001 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #import #import "osdep.h" #import "EDTCPSocket.h" #ifdef WIN32 #define EDSOCKETHANDLE ((int)[self nativeHandle]) #else #define EDSOCKETHANDLE [self fileDescriptor] #endif //--------------------------------------------------------------------------------------- @implementation EDTCPSocket //--------------------------------------------------------------------------------------- /*" This class implementes TCP sockets and some methods specific to such sockets. Most of the commonly used functionality is in its superclasses #EDIPSocket and #NSFileHandle as well as in the NSFileHandle category defined in this framework. The following code example shows how to set up a client socket, and connect it to Apple's web server: !{ EDTCPSocket *socket; socket = [EDTCPSocket socket]; [socket connectToHost:[NSHost hostWithName:hostname] port:80] } The following code example shows how to set up a server socket, listening on the standard web port on all interfaces of this host. If we are debugging it sets the "re-use address" option so that we don't have to wait to set up the socket after restarting our application: !{ EDTCPSocket *socket; socket = [EDTCPSocket socket]; \#if DEBUG [socket setAllowsAddressReuse:YES]; \#endif [socket startListeningOnLocalPort:80]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(newClientNotification:) name:NSFileHandleConnectionAcceptedNotification object:socket]; [socket acceptConnectionInBackgroundAndNotify]; } Note that, generally, working with #EDStreams is a better choice than working directly with sockets. "*/ //--------------------------------------------------------------------------------------- // CLASS ATTRIBUTES //--------------------------------------------------------------------------------------- + (int)socketProtocol { return IPPROTO_TCP; } + (int)socketType { return SOCK_STREAM; } //--------------------------------------------------------------------------------------- // OPTIONS & PARAMETERS //--------------------------------------------------------------------------------------- /*" Controls wether data written to the socket is sent immediatly or whether the operating system should try to accumulate some data before sending a packet to reduce overhead. This is commonly known as Nagle's algorithm (RFC 896) and corresponds to TCP_NODELAY. "*/ - (void)setSendsDataImmediately:(BOOL)flag { [self setSocketOption:TCP_NODELAY level:IPPROTO_TCP value:flag]; } //--------------------------------------------------------------------------------------- // LISTENING //--------------------------------------------------------------------------------------- /*" Starts listening for incoming connections. This requires that a local port has been set before. Note that #acceptConnectionInBackgroundAndNotify must be called afterwards so that incoming connections are handled. "*/ - (void)startListening { if(listen(EDSOCKETHANDLE, 5) == -1) // backlog length of 5 is maximum [NSException raise:NSFileHandleOperationException format:@"Unable start listening on local port: %s", strerror(ED_ERRNO)]; flags.listening = YES; } /*" Starts listening for incoming connections on aPort on all local IP addresses (interfaces). Note that #acceptConnectionInBackgroundAndNotify must be called afterwards so that incoming connections are handled. "*/ - (void)startListeningOnLocalPort:(unsigned short)aPort { [self setLocalPort:aPort]; [self startListening]; } /*" Starts listening for incoming connections on the aPort on the specified local address; the latter being in the "typical" dotted numerical notation. Note that #acceptConnectionInBackgroundAndNotify must be called afterwards so that incoming connections are handled. "*/ - (void)startListeningOnLocalPort:(unsigned short)aPort andAddress:(NSString *)addressString { [self setLocalPort:aPort andAddress:addressString]; [self startListening]; } //--------------------------------------------------------------------------------------- @end //--------------------------------------------------------------------------------------- gridlock.app-1.10/GameConfiguration.m0000644000175000000000000001752610342202542016613 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GameConfiguration.h" #import "GenericAI.h" #import "Preferences.h" static NSArray *gGameList = nil; @implementation NSDictionary(GameConfiguration_DisplayName) -(NSString *)displayName_ { NSString *result = [self objectForKey:@"displayName"]; if (result) return result; return [self objectForKey:@"name"]; } @end @implementation GameConfiguration +(NSArray *)gameList { if (!gGameList) { gGameList = [[[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Games" ofType:@"plist"]] sortedArrayUsingKey_:@"name"] retain]; } return gGameList; } +(NSDictionary *)dictionaryForGameWithName:(NSString *)name { return [[self gameList] objectWithValue:name forSelector:@selector(objectForKey:) withArgument:@"name"]; } -(NSDictionary *)gameDictionary { return [[self class] dictionaryForGameWithName:[self gameName]]; } -(NSDictionary *)dictionaryForVariation { NSArray *variations = [[self gameDictionary] objectForKey:@"variations"]; return [variations objectWithValue:[self variationName] forSelector:@selector(objectForKey:) withArgument:@"name"]; } idAccessor(initialGame, setInitialGame) -(id)initWithName:(NSString *)name variation:(NSString *)variation { NSArray *varNames; self = [super init]; gameName = [name copy]; varNames = [self allVariationNames]; if (!variation) { // look for default variation = [[Preferences sharedInstance] configurationForGame:gameName]; } if (![varNames containsObject:variation]) { variation = nil; } if (!variation) { // if not specified and no default, or if nonexistent, use first if ([varNames count]>0) variation = [varNames objectAtIndex:0]; } variationName = [variation copy]; [self createNewInitialGame]; return self; } /* +(GameConfiguration *)configurationWithDisplayName:(NSString *)name variationDisplayName:(NSString *)variation { } */ +(GameConfiguration *)configurationFromDefaults { NSString *initialGameName = [[Preferences sharedInstance] initialGame]; NSDictionary *gameDict; NSString *varname = nil; if (!initialGameName) initialGameName = [[[self gameList] objectAtIndex:0] objectForKey:@"name"]; gameDict = [self dictionaryForGameWithName:initialGameName]; if (!gameDict) { // invalid game name, default to first initialGameName = [[[self gameList] objectAtIndex:0] objectForKey:@"name"]; gameDict = [self dictionaryForGameWithName:initialGameName]; } // see if game has variations, if so read from prefs or default to first if ([[gameDict objectForKey:@"variations"] count]>0) { varname = [[Preferences sharedInstance] configurationForGame:initialGameName]; if (nil==varname || ![[[gameDict objectForKey:@"variations"] valuesByObjectsPerformingSelector:@selector(objectForKey:) withObject_:@"name"] containsObject:varname]) { // variation missing or invalid, use first varname = [[[gameDict objectForKey:@"variations"] objectAtIndex:0] objectForKey:@"name"]; } } return [[[self alloc] initWithName:initialGameName variation:varname] autorelease]; } -(void)saveToDefaults { [[Preferences sharedInstance] setInitialGame:[self gameName]]; [[Preferences sharedInstance] setConfiguration:[self variationName] forGame:[self gameName]]; } -(void)dealloc { [gameName release]; [variationName release]; [self setInitialGame:nil]; [super dealloc]; } -(NSString *)gameName { return gameName; } -(NSString *)variationName { return variationName; } // FIXME -(NSString *)gameDisplayName { return gameName; } -(NSString *)variationDisplayName { return variationName; } -(Class)gameClass { NSString *className = [[self gameDictionary] objectForKey:@"class"]; return NSClassFromString(className); } -(Game *)gameInStartingPosition { Game *game = [[[[self gameClass] alloc] init] autorelease]; [game setConfigurationInfo:[[self dictionaryForVariation] objectForKey:@"params"]]; [game reset]; return game; } -(void)createNewInitialGame { [self setInitialGame:[self gameInStartingPosition]]; } -(id)aiWithName:(NSString *)aiName { NSDictionary *dict = [[[self gameDictionary] objectForKey:@"aiTypes"] objectWithValue:aiName forSelector:@selector(objectForKey:) withArgument:@"name"]; NSString *aiClassName = [dict objectForKey:@"class"]; NSDictionary *aiParams = [dict objectForKey:@"params"]; GenericAI *ai = (aiClassName) ? [[[NSClassFromString(aiClassName) alloc] init] autorelease] : nil; if (aiParams) { [ai takeValuesFromDictionary:aiParams]; [ai setName:aiName]; } return ai; } -(id)viewDelegate { NSString *className = [[self gameDictionary] objectForKey:@"viewDelegate"]; if (className) { id delegate = [[[NSClassFromString(className) alloc] init] autorelease]; if ([[self gameDictionary] objectForKey:@"viewDelegateParams"]) { [delegate takeValuesFromDictionary:[[self gameDictionary] objectForKey:@"viewDelegateParams"]]; } return delegate; } return nil; } +(NSArray *)allGameDisplayNames { return [[self gameList] valuesByObjectsPerformingSelector:@selector(displayName_)]; } +(NSArray *)allGameNames { return [[self gameList] valuesByObjectsPerformingSelector:@selector(objectForKey:) withObject_:@"name"]; } -(NSArray *)allVariationDisplayNames { NSArray *variations = [[self gameDictionary] objectForKey:@"variations"]; return [variations valuesByObjectsPerformingSelector:@selector(displayName_)]; } -(NSArray *)allVariationNames { NSArray *variations = [[self gameDictionary] objectForKey:@"variations"]; return [variations valuesByObjectsPerformingSelector:@selector(objectForKey:) withObject_:@"name"]; } -(NSArray *)allAINames { NSArray *aiTypes = [[self gameDictionary] objectForKey:@"aiTypes"]; return [aiTypes valuesByObjectsPerformingSelector:@selector(objectForKey:) withObject_:@"name"]; } -(NSArray *)allAIDisplayNames { NSArray *aiTypes = [[self gameDictionary] objectForKey:@"aiTypes"]; return [aiTypes valuesByObjectsPerformingSelector:@selector(displayName_)]; } -(id)propertyList { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:[self gameName] forKey:@"game"]; if ([self variationName]) [dict setObject:[self variationName] forKey:@"variation"]; if ([self initialGame]) [dict setObject:[[self initialGame] propertyList] forKey:@"initialGame"]; return dict; } -(id)initFromPropertyList:(id)plist { [self initWithName:[plist objectForKey:@"game"] variation:[plist objectForKey:@"variation"]]; if ([plist objectForKey:@"initialGame"]) [[self initialGame] updateFromPropertyList:[plist objectForKey:@"initialGame"]]; return self; } @end gridlock.app-1.10/GameHistory.m0000644000175000000000000001602510342202542015436 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GameHistory.h" #import "CocoaAdditions.h" @implementation GameHistory -(id)init { [super init]; gameStates = [[NSMutableArray alloc] init]; stateIndex = 0; return self; } -(id)initWithGameConfiguration:(GameConfiguration *)gameConfig { if ([self init]) { NSMutableDictionary *firstState = [NSMutableDictionary dictionary]; [self setGameConfiguration:gameConfig]; [firstState setObject:[gameConfig initialGame] forKey:@"game"]; [gameStates addObject:firstState]; } return self; } -(void)dealloc { [gameStates release]; [super dealloc]; } idAccessor(gameConfiguration, setGameConfiguration) -(Game *)currentGame { return [[gameStates objectAtIndex:stateIndex] objectForKey:@"game"]; } -(Game *)initialGame { return [[gameStates objectAtIndex:0] objectForKey:@"game"]; } -(void)recordAndExecuteMove:(NSArray *)move { Game *newGame = [[[self currentGame] copy] autorelease]; // remove all states past recordedStateIndex while (stateIndex+1<[gameStates count]) { [gameStates removeLastObject]; } // add the move to the last state // use an empty array instead of nil if (move==nil) move = [NSArray array]; [[gameStates lastObject] setObject:[move copy] forKey:@"move"]; // execute the move [newGame makeMoveSequence:move]; // add the new game state and advance index to point to it [gameStates addObject:[NSMutableDictionary dictionaryWithObject:newGame forKey:@"game"]]; ++stateIndex; // send notification? } -(int)_previousStateIndexWithPlayerNumberInArray:(NSArray *)pnums { int index = stateIndex; while (index>0) { Game *previousGame = [[gameStates objectAtIndex:--index] objectForKey:@"game"]; if ([pnums containsObject:[NSNumber numberWithInt:[previousGame currentPlayerNumber]]]) { return index; } } return -1; } -(int)_nextStateIndexWithPlayerNumberInArray:(NSArray *)pnums { int index = stateIndex; int max = [gameStates count]-1; while (index0) { --stateIndex; return YES; } return NO; } -(BOOL)canUndoMove { return (stateIndex>0); } -(BOOL)undoMovesUntilPlayerNumberInArray:(NSArray *)pnums { int index = [self _previousStateIndexWithPlayerNumberInArray:pnums]; if (index>=0) { stateIndex = index; return YES; } return NO; } -(BOOL)canUndoMovesUntilPlayerNumberInArray:(NSArray *)pnums { return ([self _previousStateIndexWithPlayerNumberInArray:pnums]>=0); } -(BOOL)redoMove { if (stateIndex<[gameStates count]-1) { ++stateIndex; return YES; } return NO; } -(BOOL)canRedoMove { return (stateIndex<[gameStates count]-1); } -(BOOL)redoMovesUntilPlayerNumberInArray:(NSArray *)pnums { int index = [self _nextStateIndexWithPlayerNumberInArray:pnums]; if (index>0) { stateIndex = index; return YES; } return NO; } -(BOOL)canRedoMovesUntilPlayerNumberInArray:(NSArray *)pnums { return ([self _nextStateIndexWithPlayerNumberInArray:pnums]>0); } -(int)numberOfMoves { return [gameStates count]; } -(int)currentMoveNumber { return stateIndex; } -(NSArray *)moveWithNumber:(int)movenum { if (movenum>=0 && movenum<[gameStates count]) { return [[gameStates objectAtIndex:movenum] objectForKey:@"move"]; } return nil; } -(Game *)gameWithNumber:(int)movenum { if (movenum>=0 && movenum<[gameStates count]) { return [[gameStates objectAtIndex:movenum] objectForKey:@"game"]; } return nil; } -(Game *)previousGame { if (stateIndex==0) return nil; return [[gameStates objectAtIndex:stateIndex-1] objectForKey:@"game"]; } -(NSArray *)previousMove { if (stateIndex==0) return nil; return [[gameStates objectAtIndex:stateIndex-1] objectForKey:@"move"]; } -(id)propertyList { NSMutableDictionary *plist = [NSMutableDictionary dictionary]; [plist setObject:[[self gameConfiguration] propertyList] forKey:@"configuration"]; [plist setObject:[[NSNumber numberWithInt:[self currentMoveNumber]] stringValue] forKey:@"moveNumber"]; { NSMutableArray *states = [NSMutableArray array]; NSEnumerator *se = [gameStates objectEnumerator]; NSDictionary *state; while (state=[se nextObject]) { NSMutableDictionary *stateDict = [NSMutableDictionary dictionary]; if ([state objectForKey:@"game"]) { [stateDict setObject:[[state objectForKey:@"game"] propertyList] forKey:@"game"]; } if ([state objectForKey:@"move"]) { // moves are NSArrays of DCHypergridPositions NSArray *moveDescArray = [[state objectForKey:@"move"] valuesByObjectsPerformingSelector:@selector(propertyListValue)]; [stateDict setObject:moveDescArray forKey:@"move"]; } [states addObject:stateDict]; } [plist setObject:states forKey:@"states"]; } return plist; } -(id)initFromPropertyList:(id)plist { if ([self init]) { stateIndex = [[plist objectForKey:@"moveNumber"] intValue]; [self setGameConfiguration:[[[GameConfiguration alloc] initFromPropertyList:[plist objectForKey:@"configuration"]] autorelease]]; { NSEnumerator *se = [[plist objectForKey:@"states"] objectEnumerator]; NSDictionary *archivedState; while (archivedState=[se nextObject]) { NSMutableDictionary *state = [NSMutableDictionary dictionary]; if ([archivedState objectForKey:@"game"]) { Game *game = [[self gameConfiguration] gameInStartingPosition]; [game updateFromPropertyList:[archivedState objectForKey:@"game"]]; [state setObject:game forKey:@"game"]; } if ([archivedState objectForKey:@"move"]) { NSArray *movePositions = [DCHypergridPosition positionArrayFromPropertyListValueArray:[archivedState objectForKey:@"move"]]; [state setObject:movePositions forKey:@"move"]; } [gameStates addObject:state]; } } } return self; } @end gridlock.app-1.10/GridlockGameState.m0000644000175000000000000001523010342202542016531 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GridlockGameState.h" #import "Preferences.h" @implementation GridlockGameState -(id)init { [super init]; aiPlayers = [[NSMutableDictionary alloc] init]; networkPlayers = [[NSMutableDictionary alloc] init]; return self; } -(void)dealloc { [aiPlayers release]; aiPlayers = nil; [networkPlayers release]; networkPlayers = nil; [super dealloc]; } -(NSArray *)aiNamesForCurrentGame:(BOOL)firstTime requireHuman:(BOOL)requireHuman { NSString *gameName = [[self gameConfiguration] gameName]; // read AI types from preferences NSString *player1AIType = [[Preferences sharedInstance] aiTypeForGame:gameName player:1]; NSString *player2AIType = [[Preferences sharedInstance] aiTypeForGame:gameName player:2]; if (firstTime) { // if both unset, we will default to the first AI type available for player 2 NSArray *aiTypes = [[self gameConfiguration] allAINames]; if (player1AIType==nil && player2AIType==nil && [aiTypes count]>0) { player2AIType = [aiTypes objectAtIndex:0]; } } if (firstTime || requireHuman) { // if both set, revert player 1 to human (so we don't start out computer vs computer) if ([player1AIType length]>0 && [player2AIType length]>0) { player1AIType = @""; } } if (!player1AIType) player1AIType = @""; if (!player2AIType) player2AIType = @""; return [NSArray arrayWithObjects:player1AIType, player2AIType, nil]; } // called when game is switched to update AIs from NSUserDefaults -(void)updateAIsForNewGame:(BOOL)firstTime requireHuman:(BOOL)requireHuman { NSArray *aiNames = [self aiNamesForCurrentGame:firstTime requireHuman:requireHuman]; int i; for(i=0; i<[aiNames count]; i++) { [self setAIName:[aiNames objectAtIndex:i] forPlayer:i+1]; } } -(GameHistory *)gameHistory { return gameHistory; } -(void)setGameHistory:(GameHistory *)newHistory { if (newHistory!=gameHistory) { BOOL isSameGame = [[[newHistory gameConfiguration] gameName] isEqual:[[gameHistory gameConfiguration] gameName]]; id temp = gameHistory; gameHistory = [newHistory retain]; // twiddle the AIs for the first game (if we're not playing a network game) if (![self hasNetConnections]) [self updateAIsForNewGame:(temp==nil) requireHuman:!isSameGame]; [temp release]; } } -(GameConfiguration *)gameConfiguration { return [[self gameHistory] gameConfiguration]; } -(Game *)currentGame { return [[self gameHistory] currentGame]; } -(int)currentPlayerNumber { return [[self currentGame] currentPlayerNumber]; } -(BOOL)isPlayerHuman:(int)pnum { id key = [NSNumber numberWithInt:pnum]; return (nil==[aiPlayers objectForKey:key] && nil==[networkPlayers objectForKey:key]); } -(BOOL)isCurrentPlayerHuman { return [self isPlayerHuman:[self currentPlayerNumber]]; } -(NSArray *)availableAINames { return [[self gameConfiguration] allAINames]; } -(NSArray *)availableAIDisplayNames { return [[self gameConfiguration] allAIDisplayNames]; } -(NSString *)aiNameForPlayer:(int)pnum { NSString *name = [[aiPlayers objectForKey:[NSNumber numberWithInt:pnum]] name]; return (name ? name : @""); } -(void)setAIName:(NSString *)aiName forPlayer:(int)pnum { id key = [NSNumber numberWithInt:pnum]; [aiPlayers removeObjectForKey:key]; [networkPlayers removeObjectForKey:key]; if ([aiName length]>0) { GenericAI *ai = [[self gameConfiguration] aiWithName:aiName]; if (ai) { [aiPlayers setObject:ai forKey:key]; } } [[Preferences sharedInstance] setAIType:(aiName ? aiName : @"") forGame:[[self gameConfiguration] gameName] player:pnum]; } -(void)makeAIMove { GenericAI *ai = [aiPlayers objectForKey:[NSNumber numberWithInt:[self currentPlayerNumber]]]; // this move may be executing in a worker thread. If so, we need to protect the AI and game objects because they may be released // by the main thread, for example if the player is switched to human while the AI is still thinking. Game *game = [self currentGame]; [[ai retain] autorelease]; [[game retain] autorelease]; [ai computeBestMoveForGame:game]; } -(void)setNetConnection:(NetConnection *)conn forPlayer:(int)pnum { id key = [NSNumber numberWithInt:pnum]; [aiPlayers removeObjectForKey:key]; if (conn==nil) { [networkPlayers removeObjectForKey:key]; } else { [networkPlayers setObject:conn forKey:key]; } } -(void)makePlayerHuman:(int)pnum { [self setAIName:nil forPlayer:pnum]; [self setNetConnection:nil forPlayer:pnum]; } -(void)makeAllPlayersHuman { [aiPlayers removeAllObjects]; [networkPlayers removeAllObjects]; } -(int)playerNumberForNetConnection:(NetConnection *)conn { NSArray *keys = [networkPlayers allKeysForObject:conn]; return ([keys count] ? [[keys lastObject] intValue] : 0); } -(NetConnection *)netConnectionForPlayer:(int)pnum { return [networkPlayers objectForKey:[NSNumber numberWithInt:pnum]]; } -(BOOL)hasNetConnections { return [networkPlayers count]>0; } -(NSArray *)allNetConnections { return [networkPlayers allValues]; } -(id)propertyList { NSMutableDictionary *plist = [NSMutableDictionary dictionary]; [plist setObject:[[self gameHistory] propertyList] forKey:@"history"]; { NSMutableDictionary *aiDict = [NSMutableDictionary dictionary]; int i; for(i=1; i<=[[self currentGame] numberOfPlayers]; i++) { NSString *aiName = [self aiNameForPlayer:i]; if ([aiName length]>0) { [aiDict setObject:aiName forKey:[[NSNumber numberWithInt:i] stringValue]]; } } [plist setObject:aiDict forKey:@"AIs"]; } return plist; } @end gridlock.app-1.10/LifeAI.m0000644000175000000000000000317410342202542014275 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "LifeAI.h" @implementation LifeAI -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { int mycells = [[game grid] numberOfCellsWithValue:pnum]; int oppcells = [[game grid] numberOfCellsWithValue:[game playerNumberMovingAfterPlayer:pnum]]; // convert ratio of cells to a utility if (mycells==oppcells) return 0; else if (mycells==0) return -1000; else if (oppcells==0) return 1000; else if (mycells>oppcells) { return (int)(100.0*mycells/oppcells); } else { return (int)(-100.0*oppcells/mycells); } } @end gridlock.app-1.10/LifeGame.m0000644000175000000000000000754310342202542014661 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "LifeGame.h" static int _fastGridValue(gridvalue_t *values, int r, int c, int maxr, int maxc) { return (int)values[r*maxc+c]; } @implementation LifeGame // private methods -(int)valueAtPosition:(id)pos afterMoveAtPosition:(id)movepos byPlayer:(int)pnum { int dr,dc; // HACK: for speed, this uses internal fields in DCHypergrid gridvalue_t *values = [[self grid] cHypergrid]->grid_data; int moverow = [movepos row], movecol=[movepos column]; int targetrow=[pos row], targetcol=[pos column]; int maxr = [self numberOfRows], maxc = [self numberOfColumns]; int origval = (moverow==targetrow && movecol==targetcol) ? pnum : _fastGridValue(values, targetrow, targetcol, maxr, maxc); // count neighbors, wrapping around edges int n1=0, n2=0; for(dr=-1; dr<=1; dr++) { int r = (targetrow+dr)%maxr; if (r<0) r+=maxr; for(dc=-1; dc<=1; dc++) { if (dr!=0 || dc!=0) { int c = (targetcol+dc)%maxc; int nval; if (c<0) c+=maxc; nval = (r==moverow && c==movecol) ? pnum : _fastGridValue(values, r, c, maxr, maxc); if (nval==1) ++n1; else if (nval==2) ++n2; } } } //NSLog(@"neighbors of %@: %d %d", pos, n1, n2); if (origval==0) { // empty cell with 3 neighbors becomes filled if (n1+n2==3) { return (n2>n1) ? 2 : 1; } else return 0; } else { // filled cell needs 2 or 3 neighbors to survive if ((n1+n2==2) || (n1+n2==3)) return origval; else return 0; } } // end private methods -(void)reset { [super reset]; [self createGridFromConfiguration]; { int p1cells = [[[self configurationInfo] objectForKey:@"player1RandomCells"] intValue]; int p2cells = [[[self configurationInfo] objectForKey:@"player2RandomCells"] intValue]; [self fillRandomEmptyCellsWithValue:1 count:p1cells]; [self fillRandomEmptyCellsWithValue:2 count:p2cells]; } } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self resetFutureGrid]; if ([positions count]==0) return YES; if ([positions count]!=1) return NO; else { id movepos = [positions objectAtIndex:0]; int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { int nextValue = [self valueAtPosition:pos afterMoveAtPosition:movepos byPlayer:pnum]; [[self futureGrid] setValue:nextValue atPosition:pos]; } return YES; } } -(BOOL)isGameOver { int s1=[[self grid] numberOfCellsWithValue:1]; int s2=[[self grid] numberOfCellsWithValue:2]; return ((s1==0 && s2==0) || s1>=s2*4 || s2>=s1*4); } -(NSArray *)allValidMoveSequences { return [[[self grid] allPositionsWithValue:0] valuesByObjectsPerformingSelector:@selector(arrayWithSelf_)]; } -(BOOL)showScores { return YES; } @end gridlock.app-1.10/NSFileHandle+Extensions.m0000644000175000000000000001572310342202542017576 0ustar gurkanroot//--------------------------------------------------------------------------------------- // NSFileHandle+NetExt.m created by erik // @(#)$Id: NSFileHandle+Extensions.m,v 2.0 2002/08/16 18:12:48 erik Exp $ // // Copyright (c) 1997,1999 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #import #import "osdep.h" #import "functions.h" #import "NSFileHandle+Extensions.h" #ifdef WIN32 #import // move this to osdep.h? #endif #ifdef WIN32 #define EDSOCKETHANDLE ((int)[self nativeHandle]) #else #define EDSOCKETHANDLE [self fileDescriptor] #endif //--------------------------------------------------------------------------------------- @implementation NSFileHandle(EDExtensions) //--------------------------------------------------------------------------------------- /*" Various useful extensions to #NSFileHandle. Most only work with file handles that represent sockets but this is in a category on NSFileHandle, and not in its subclass #EDIPSocket, because this functionality is also useful for plain NSFileHandles that represent sockets. The latter are often created through invocations such as #acceptConnectionInBackgroundAndNotify. "*/ /*" Returns the port of the local endpoint of the socket. "*/ - (unsigned short)localPort { int sockaddrLength; struct sockaddr_in sockaddr; sockaddrLength = sizeof(struct sockaddr_in); if(getsockname(EDSOCKETHANDLE, (struct sockaddr *)&sockaddr, &sockaddrLength) == -1) [NSException raise:NSFileHandleOperationException format:@"Cannot get local port number for socket: %s", strerror(ED_ERRNO)]; return sockaddr.sin_port; } /*" Returns the address of the local endpoint of the socket in the "typical" dotted numerical notation. "*/ - (NSString *)localAddress { int sockaddrLength; struct sockaddr_in sockaddr; sockaddrLength = sizeof(struct sockaddr_in); if(getsockname(EDSOCKETHANDLE, (struct sockaddr *)&sockaddr, &sockaddrLength) == -1) [NSException raise:NSFileHandleOperationException format:@"Cannot get local port number for socket: %s", strerror(ED_ERRNO)]; return EDStringFromInAddr(sockaddr.sin_addr); } /*" Returns the port of the remote endpoint of the socket. "*/ - (unsigned short)remotePort { int sockaddrLength; struct sockaddr_in sockaddr; sockaddrLength = sizeof(struct sockaddr_in); if(getpeername(EDSOCKETHANDLE, (struct sockaddr *)&sockaddr, &sockaddrLength) == -1) [NSException raise:NSFileHandleOperationException format:@"Failed to get peer: %s", strerror(ED_ERRNO)]; return sockaddr.sin_port; } /*" Returns the address of the remote endpoint of the socket in the "typical" dotted numerical notation. "*/ - (NSString *)remoteAddress { int sockaddrLength; struct sockaddr_in sockaddr; sockaddrLength = sizeof(struct sockaddr_in); if(getpeername(EDSOCKETHANDLE, (struct sockaddr *)&sockaddr, &sockaddrLength) == -1) [NSException raise:NSFileHandleOperationException format:@"Failed to get peer: %s", strerror(ED_ERRNO)]; return EDStringFromInAddr(sockaddr.sin_addr); } /*" Returns the host for the remote endpoint of the socket. "*/ - (NSHost *)remoteHost { return [NSHost hostWithAddress:[self remoteAddress]]; } /*" Causes the full-duplex connection on the socket to be shut down. "*/ - (void)shutdown { if(shutdown(EDSOCKETHANDLE, 2) == -1) [NSException raise:NSFileHandleOperationException format:@"Failed to shutdown socket: %s", strerror(ED_ERRNO)]; } /*" Causes part of the full-duplex connection on the socket to be shut down; further receives will be disallowed. "*/ - (void)shutdownInput { if(shutdown(EDSOCKETHANDLE, 0) == -1) [NSException raise:NSFileHandleOperationException format:@"Failed to shutdown input of socket: %s", strerror(ED_ERRNO)]; } /*" Causes part of the full-duplex connection on the socket to be shut down; further sends will be disallowed. "*/ - (void)shutdownOutput { if(shutdown(EDSOCKETHANDLE, 1) == -1) [NSException raise:NSFileHandleOperationException format:@"Failed to shutdown output of socket: %s", strerror(ED_ERRNO)]; } - (unsigned int)_availableByteCountNonBlocking { #ifdef WIN32 DWORD lpTotalBytesAvail; BOOL peekSuccess; peekSuccess = PeekNamedPipe(EDSOCKETHANDLE, NULL, 0L, NULL, &lpTotalBytesAvail, NULL); if (peekSuccess == NO) [NSException raise: NSFileHandleOperationException format: @"PeekNamedPipe() NT Error # %d", GetLastError()]; return lpTotalBytesAvail; #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(linux) int numBytes; if(ioctl(EDSOCKETHANDLE, FIONREAD, (char *) &numBytes) == -1) [NSException raise: NSFileHandleOperationException format: @"ioctl() error # %d", errno]; return numBytes; #else #warning Non-blocking I/O not supported on this platform.... abort(); return 0; #endif } /*" Calls #{readDataOfLengthNonBlocking:} with a length of !{UINT_MAX}, effectively reading as much data as is available. "*/ - (NSData *)availableDataNonBlocking { return [self readDataOfLengthNonBlocking:UINT_MAX]; } /*" Calls #{readDataOfLengthNonBlocking:} with a length of !{UINT_MAX}, effectively reading as far towards the end of the file as possible. "*/ - (NSData *)readDataToEndOfFileNonBlocking { return [self readDataOfLengthNonBlocking:UINT_MAX]; } /*" Tries to read length bytes of data. If less data is available it does not block to wait for more but returns whatever is available. If no data is available this method returns !{nil} and not an empty instance of #NSData. "*/ - (NSData *)readDataOfLengthNonBlocking:(unsigned int)length { unsigned int available; available = [self _availableByteCountNonBlocking]; if(available == 0) return nil; return [self readDataOfLength:((available < length) ? available : length)]; } //--------------------------------------------------------------------------------------- @end //--------------------------------------------------------------------------------------- gridlock.app-1.10/NSObject+Extensions.m0000644000175000000000000002130010342202542016775 0ustar gurkanroot//--------------------------------------------------------------------------------------- // NSObject+Extensions.m created by erik on Sun 06-Sep-1998 // @(#)$Id: NSObject+Extensions.m,v 2.2 2003/01/25 22:33:49 erik Exp $ // // Copyright (c) 1998-2000 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #import #import "NSObject+Extensions.h" #import "EDObjcRuntime.h" //--------------------------------------------------------------------------------------- @implementation NSObject(EDExtensions) //--------------------------------------------------------------------------------------- /*" Various common extensions to #NSObject. "*/ //--------------------------------------------------------------------------------------- // RUNTIME CONVENIENCES //--------------------------------------------------------------------------------------- /*" Raises an #NSInternalInconsistencyException stating that the method must be overriden. "*/ - (volatile void)methodIsAbstract:(SEL)selector { [NSException raise:NSInternalInconsistencyException format:@"*** -[%@ %@]: Abstract definition must be overriden.", NSStringFromClass([self class]), NSStringFromSelector(selector)]; } /*" Prints a warning that the method is obsolete. This warning is only printed once per method. "*/ - (void)methodIsObsolete:(SEL)selector { [self methodIsObsolete:selector hint:nil]; } /*" Prints a warning that the method is obsolete including the %hint supplied. This warning is only printed once per method. "*/ - (void)methodIsObsolete:(SEL)selector hint:(NSString *)hint { static NSMutableSet *methodList = nil; EDObjcMethodInfo method; NSValue *methodKey; if(methodList == nil) methodList = [[NSMutableSet alloc] init]; if((method = EDObjcClassGetInstanceMethod(isa, selector)) == NULL) method = EDObjcClassGetClassMethod(isa, selector); methodKey = [NSValue valueWithBytes:&method objCType:@encode(Method)]; if([methodList containsObject:methodKey] == NO) { [methodList addObject:methodKey]; if(hint == nil) NSLog(@"*** Warning: Compatibility method '%@' in class %@ has been invoked at least once.", NSStringFromSelector(selector), NSStringFromClass([self class])); else NSLog(@"*** Warning: Compatibility method '%@' in class %@ has been invoked at least once. %@", NSStringFromSelector(selector), NSStringFromClass([self class]), hint); } } - (NSString *)className { return NSStringFromClass([self class]); } //--------------------------------------------------------------------------------------- // EXTENDED INTROSPECTION //--------------------------------------------------------------------------------------- IMP EDGetFirstUnusedIMPForSelector(Class aClass, SEL aSelector, BOOL isClassMethod) { #ifndef GNU_RUNTIME IMP activeIMP; struct objc_method_list *mlist; void *iterator; int i; if(isClassMethod) aClass = aClass->isa; iterator = 0; activeIMP = [aClass instanceMethodForSelector:aSelector]; while((mlist = class_nextMethodList(aClass, &iterator)) != NULL) { for(i = 0; i < mlist->method_count; i++) { if((mlist->method_list[i].method_name == aSelector) && (mlist->method_list[i].method_imp != activeIMP)) return mlist->method_list[i].method_imp; } } return NULL; #else /* GNU_RUNTIME */ #warning ** implementation missing for GNU runtime return NULL; #endif } BOOL EDClassIsSuperclassOfClass(Class aClass, Class subClass) { Class class; class = subClass->super_class; while(class != nil) { if(class == aClass) return YES; class = class->super_class; } return NO; } NSArray *EDSubclassesOfClass(Class aClass) { #ifndef GNU_RUNTIME #ifdef EDCOMMON_OSXBUILD NSMutableArray *subclasses; Class *classes; int numClasses, newNumClasses, i; // cf. /System/Library/Frameworks/System.framework/Headers/objc/objc-runtime.h numClasses = 0, newNumClasses = objc_getClassList(NULL, 0); classes = NULL; while (numClasses < newNumClasses) { numClasses = newNumClasses; classes = realloc(classes, sizeof(Class) * numClasses); newNumClasses = objc_getClassList(classes, numClasses); } subclasses = [NSMutableArray array]; for(i = 0; i < numClasses; i++) { if(EDClassIsSuperclassOfClass(aClass, classes[i]) == YES) [subclasses addObject:classes[i]]; } free(classes); return subclasses; #else /* OSXS_BUILD */ NSMutableArray *subclasses; NXHashTable *subClasses; NXHashState subIterator; Class subClass; subClasses = objc_getClasses(); subIterator = NXInitHashState(subClasses); subclasses = [NSMutableArray array]; while(NXNextHashState(subClasses, &subIterator, (void **)&subClass)) { if(EDClassIsSuperclassOfClass(aClass, subClass) == YES) [subclasses addObject:subClass]; } return subclasses; #endif #else /* GNU_RUNTIME */ NSMutableArray *subclasses; Class subClass; void *es = NULL; subclasses = [NSMutableArray array]; while((subClass = objc_next_class(&es)) != Nil) if(EDClassIsSuperclassOfClass(aClass, subClass) == YES) [subclasses addObject:subClass]; return subclasses; #endif } /*" Returns all subclasses of the receiving class "*/ + (NSArray *)subclasses { return EDSubclassesOfClass(self); } //--------------------------------------------------------------------------------------- // MAPPING //--------------------------------------------------------------------------------------- /*" Invokes the method described by %selector in the receiver once for each object in %anArray and collects the return values in another array that is returned. Note that the selector is assumed to take one argument, the current object from the array, and return the corresponding object. Example: Assume you have an array !{a} which contains names and an object !{phoneBook} implementing a method !{lookupPhoneNumber:} which returns a phone number for a name. In this case you can use !{[phoneBook mapArray:a withSelector:@selector(lookupPhoneNumber:)]} to get the corresponding array of phone numbers."*/ - (NSArray *)mapArray:(NSArray *)anArray withSelector:(SEL)selector { NSMutableArray *mappedArray; unsigned int i, n = [anArray count]; mappedArray = [[[NSMutableArray allocWithZone:[self zone]] initWithCapacity:n] autorelease]; for(i = 0; i < n; i++) [mappedArray addObject:EDObjcMsgSend1(self, selector, [anArray objectAtIndex:i])]; return mappedArray; } //--------------------------------------------------------------------------------------- // REPEATED PERFORM //--------------------------------------------------------------------------------------- /*" Invokes the method described by %selector in the receiver once for each object in %array, passing the respective object as an argument. "*/ - (void)performSelector:(SEL)selector withObjects:(NSArray *)array { unsigned int i, n = [array count]; for(i = 0; i < n; i++) EDObjcMsgSend1(self, selector, [array objectAtIndex:i]); } /*" Invokes the method described by %selector in the receiver once for each object enumerated by %enumerator, passing the respective object as an argument. "*/ - (void)performSelector:(SEL)selector withObjectsEnumeratedBy:(NSEnumerator *)enumerator { id object; while((object = [enumerator nextObject]) != nil) EDObjcMsgSend1(self, selector, object); } //--------------------------------------------------------------------------------------- @end //--------------------------------------------------------------------------------------- gridlock.app-1.10/NetConnection.m0000644000175000000000000001375310342202542015756 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "NetConnection.h" // prevent hostile clients from sending arbitrarily large data by limiting length header to 5 chars static int MAX_PLIST_LENGTH_CHARS = 5; @implementation NetConnection -(id)init { [super init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gotData:) name:NSFileHandleReadCompletionNotification object:nil]; buffer = [[NSMutableData alloc] init]; return self; } +(NetConnection *)connectionWithSocket:(NSFileHandle *)sock { // for some reason, the autorelease pool doesn't get cleared in a reasonable amount of time // so we schedule a release manually NetConnection *conn = [[NetConnection alloc] init]; [conn setSocket:sock]; [conn performSelector:@selector(release) withObject:nil afterDelay:0.0]; return conn; } boolAccessor(isDisconnected, setIsDisconnected) boolAccessor(isDeallocating, setIsDeallocating) idAccessor(remoteUsername, setRemoteUsername) -(void)release { [super release]; } -(void)dealloc { [self setIsDeallocating:YES]; [[NSNotificationCenter defaultCenter] removeObserver:self]; if (![self isDisconnected]) [self sendDisconnect]; [self setSocket:nil]; [buffer release]; [super dealloc]; } -(void)setSocket:(NSFileHandle *)fh { if (socket!=fh) { id oldsocket = socket; socket = [fh retain]; //[oldsocket closeFile]; [oldsocket release]; [buffer setLength:0]; incomingPlistLength = 0; [socket readInBackgroundAndNotify]; } } -(NSFileHandle *)socket { return socket; } -(NSString *)remoteIPAddress { return [[self socket] remoteAddress]; } -(BOOL)processBuffer { //NSLog(@"NetConnection processBuffer:%@", [[[NSString alloc] initWithData:buffer encoding:NSUTF8StringEncoding] autorelease]); if (incomingPlistLength<=0) { // look for a colon and get the length from the preceding bytes char ch; int index = 0; BOOL found = NO; while (!found && index<[buffer length] && index0) { // remove the length field so we're left with just the data [buffer replaceBytesInRange:NSMakeRange(0,index+1) withBytes:NULL length:0]; found = YES; //NSLog(@"Read plist length:%d", incomingPlistLength); } } else { index++; if (index>=MAX_PLIST_LENGTH_CHARS) { NSLog(@"Failed to read plist length, terminating connection"); return NO; } } } } if (incomingPlistLength>0 && incomingPlistLength<=[buffer length]) { // extract plist from buffer NSData *bufferData = [buffer subdataWithRange:NSMakeRange(0,incomingPlistLength)]; NSString *plistStr = [[[NSString alloc] initWithData:bufferData encoding:NSUTF8StringEncoding] autorelease]; id plist = [plistStr propertyList]; [[NSNotificationCenter defaultCenter] postNotificationName:@"NetConnectionReadPropertyListNotification" object:self userInfo:[NSDictionary dictionaryWithObject:plist forKey:@"plist"]]; [buffer replaceBytesInRange:NSMakeRange(0,incomingPlistLength) withBytes:NULL length:0]; incomingPlistLength = 0; if ([buffer length]>0) { // we have data left over, call this method again return [self processBuffer]; } } return YES; } -(void)sendDisconnectNotification { if ([self isDeallocating]) return; [[NSNotificationCenter defaultCenter] postNotificationName:@"NetConnectionTerminatedNotification" object:self userInfo:nil]; } -(void)transmitPropertyList:(id)plist { NSString *plistString = [plist description]; NSString *stringToSend = [NSString stringWithFormat:@"%d:%@", [plistString length], plistString]; NSData *dataToSend = [stringToSend dataUsingEncoding:NSUTF8StringEncoding]; [[self socket] writeData:dataToSend]; } -(void)gotData:(NSNotification *)notification { if ([self isDeallocating]) return; if ([self socket]==[notification object]) { NSData *data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem]; if ([data length]>0) { [buffer appendData:data]; if ([self processBuffer]) { [[self socket] readInBackgroundAndNotify]; } else { [self sendDisconnect]; } } else { //NSLog(@"Connection terminated"); [self sendDisconnectNotification]; } } } -(void)sendDisconnect { NSDictionary *dict = [NSDictionary dictionaryWithObject:@"1" forKey:@"disconnect"]; [self transmitPropertyList:dict]; [self setIsDisconnected:YES]; [self sendDisconnectNotification]; } @end gridlock.app-1.10/RendezvousUtils.m0000644000175000000000000000466510342202543016400 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "RendezvousUtils.h" #include #include static NSString *rendezvousIdentifier = nil; Class nsNetServiceClass_() { return NSClassFromString(@"NSNetService"); } Class nsNetServiceBrowserClass_() { return NSClassFromString(@"NSNetServiceBrowser"); } BOOL isRendezvousAvailable_() { return (nsNetServiceClass_()!=Nil && nsNetServiceBrowserClass_()!=Nil); } void getHostAndPortForNetService_(id service, NSString **hostname, int *port) { // adopted from Apple's PicBrowserController sample code (http://developer.apple.com/samplecode/Sample_Code/Networking/PictureSharingBrowser/PicBrowserController.m.htm) int i; for(i=0; i<[[service addresses] count]; i++) { struct sockaddr_in *address = (struct sockaddr_in *)[[[service addresses] objectAtIndex:i] bytes]; if (address->sin_family==AF_INET) { // found IPv4 address unsigned char *bytes = (void *)&(address->sin_addr); *port = ntohs(address->sin_port); *hostname = [NSString stringWithFormat:@"%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]]; return; } } NSLog(@"Failed to find IPv4 address"); *port = 0; *hostname = nil; } NSString *rendezvousIdentifier_() { if (!rendezvousIdentifier) { long r = random(); rendezvousIdentifier = [[NSString stringWithFormat:@"%x",r] retain]; } return rendezvousIdentifier; } gridlock.app-1.10/ServerController.m0000644000175000000000000002612410342202543016517 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ServerController.h" #import "EDTCPSocket.h" #import "GameController.h" #import "NetConnection.h" #import "CocoaAdditions.h" #import "Preferences.h" #import "RendezvousUtils.h" @implementation ServerController idAccessor(netConnection, setNetConnection) idAccessor(rendezvousService, setRendezvousService) -(id)init { [super init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectionAccepted:) name:NSFileHandleConnectionAcceptedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readPropertyList:) name:@"NetConnectionReadPropertyListNotification" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gotNetworkConnection:) name:@"NetConnectionEstablishedNotification" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkConnectionTerminated:) name:@"NetConnectionTerminatedNotification" object:nil]; return self; } -(void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self setNetConnection:nil]; [super dealloc]; } -(void)awakeFromNib { isWindowExpanded = YES; windowHeightDelta = [windowSizerField frame].origin.y * [window userSpaceScaleFactor_]; [connectionStatusField setStringValue:@"Not listening"]; [self buildGamePopup]; [usernameField setStringValue:[[Preferences sharedInstance] networkUsername]]; [self gameSelectedFromPopup:nil]; [self showWindow]; } -(void)buildGamePopup { NSArray *displayNames = [GameConfiguration allGameDisplayNames]; NSArray *names = [GameConfiguration allGameNames]; [gamePopup setItemTitles:displayNames representedObjects_:names]; [gamePopup selectItemAtIndex:0]; } idAccessor(gameConfiguration, setGameConfiguration) -(IBAction)gameSelectedFromPopup:(id)sender { NSString *gameName = [[gamePopup selectedItem] representedObject]; GameConfiguration *newConfig = [[[GameConfiguration alloc] initWithName:gameName variation:nil] autorelease]; NSArray *varDisplayNames = [newConfig allVariationDisplayNames]; if ([varDisplayNames count]>1) { [variationPopup setItemTitles:varDisplayNames representedObjects_:[newConfig allVariationNames]]; [variationPopup setEnabled:YES]; } else { [variationPopup removeAllItems]; [variationPopup addItemWithTitle:NSLocalizedString(@"NoVariationsTitle", nil)]; [variationPopup setEnabled:NO]; } } -(void)showWindow { [self setWindowExpanded:NO display:NO]; [windowSizerField setStringValue:@""]; [window makeKeyAndOrderFront:nil]; } -(void)setWindowExpanded:(BOOL)isExp display:(BOOL)disp { if (isExp && !isWindowExpanded) { // expand NSRect frame = [window frame]; [window setFrame:NSMakeRect(frame.origin.x, frame.origin.y-windowHeightDelta, frame.size.width, frame.size.height+windowHeightDelta) display:disp animate:YES]; } else if (!isExp && isWindowExpanded) { // collapse NSRect frame = [window frame]; [window setFrame:NSMakeRect(frame.origin.x, frame.origin.y+windowHeightDelta, frame.size.width, frame.size.height-windowHeightDelta) display:disp animate:YES]; } isWindowExpanded = isExp; } -(NSFileHandle *)serverSocket { return serverSocket; } -(void)setServerSocket:(NSFileHandle *)fh { if (serverSocket!=fh) { id oldsocket = serverSocket; serverSocket = [fh retain]; [oldsocket closeFile]; [oldsocket release]; [serverSocket acceptConnectionInBackgroundAndNotify]; } } -(NSString *)rendezvousServiceName { NSMutableArray *fields = [NSMutableArray array]; int i; [fields addObject:([gamePopup titleOfSelectedItem]) ? [gamePopup titleOfSelectedItem] : @""]; [fields addObject:([variationPopup isEnabled]) ? [variationPopup titleOfSelectedItem] : @""]; [fields addObject:[[Preferences sharedInstance] networkUsername]]; [fields addObject:rendezvousIdentifier_()]; // replace any colons with dashes, join by colons for(i=0; i<[fields count]; i++) { id newValue = [[[fields objectAtIndex:i] componentsSeparatedByString:@":"] componentsJoinedByString:@"-"]; [fields replaceObjectAtIndex:i withObject:newValue]; } return [fields componentsJoinedByString:@":"]; } -(BOOL)publishRendezvousServiceOnPort:(int)port { if (isRendezvousAvailable_()) { id service = [[[nsNetServiceClass_() alloc] initWithDomain:@"" type:@"_gridlock._tcp" name:[self rendezvousServiceName] port:port] autorelease]; [self setRendezvousService:service]; [service setDelegate:self]; [service publish]; return YES; } return NO; } - (IBAction)beginHosting:(id)sender { int port = 0; [self updateUsername:nil]; if ([self serverSocket]) return; NS_DURING EDTCPSocket *sock = [EDTCPSocket socket]; port = [portField intValue]; [sock startListeningOnLocalPort:port]; [self setServerSocket:sock]; [self publishRendezvousServiceOnPort:port]; NS_HANDLER [self setServerSocket:nil]; [connectionStatusField setStringValue:[NSString stringWithFormat:@"Unable to listen on port %d",port]]; NS_ENDHANDLER if ([self serverSocket]) { [connectionStatusField setStringValue:[NSString stringWithFormat:@"Listening on port %d",port]]; } } -(void)connectionAccepted:(NSNotification *)notification { if ([self serverSocket]==[notification object]) { NSFileHandle *clientSocket = [[notification userInfo] objectForKey:NSFileHandleNotificationFileHandleItem]; if (clientSocket) { //[connectionStatusField setStringValue:@"Got connection"]; //[self setWindowExpanded:YES display:YES]; [self setNetConnection:[NetConnection connectionWithSocket:clientSocket]]; // wait for connect request from client } } } - (IBAction)abortHosting:(id)sender { [self setServerSocket:nil]; [self setNetConnection:nil]; [[self rendezvousService] stop]; [connectionStatusField setStringValue:@"Not listening"]; //[self setWindowExpanded:NO display:NO]; } -(IBAction)updateUsername:(id)sender { [[Preferences sharedInstance] setNetworkUsername:[usernameField stringValue]]; } - (IBAction)startGame:(id)sender { [[NSNotificationCenter defaultCenter] postNotificationName:@"NetConnectionEstablishedNotification" object:self userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[self gameConfiguration], @"configuration", [self netConnection], @"connection", [NSNumber numberWithInt:2], @"playerNumber", nil]]; [self abortHosting:nil]; [window orderOut:nil]; } -(void)readPropertyList:(NSNotification *)notification { if ([self netConnection]==[notification object]) { id plist = [[notification userInfo] objectForKey:@"plist"]; if ([plist objectForKey:@"connect"]) { NSString *username = [plist objectForKey:@"username"]; NSString *password = [plist objectForKey:@"password"]; NSString *requiredPassword = [passwordField stringValue]; if (([password length]==0 && [requiredPassword length]==0) || [password isEqual:requiredPassword]) { GameConfiguration *config = [[[GameConfiguration alloc] initWithName:[[gamePopup selectedItem] representedObject] variation:[[variationPopup selectedItem] representedObject]] autorelease]; NSMutableDictionary *startDict = [NSMutableDictionary dictionary]; [[self netConnection] setRemoteUsername:username]; [self setGameConfiguration:config]; [startDict setObject:@"" forKey:@"start"]; [startDict setObject:[[self gameConfiguration] propertyList] forKey:@"configuration"]; [startDict setObject:[[Preferences sharedInstance] networkUsername] forKey:@"username"]; [[self netConnection] transmitPropertyList:startDict]; // todo: require confirmation from both players before starting // stop listening [self setServerSocket:nil]; [self startGame:nil]; } else { // bad password // because of complex object graph interactions, we need to delay sending the failure message // and disconnecting until the next cycle of the run loop [self performSelector:@selector(handleFailedConnect) withObject:nil afterDelay:0.0]; } } } } -(void)handleFailedConnect { NSMutableDictionary *failDict = [NSMutableDictionary dictionary]; [failDict setObject:@"" forKey:@"refused"]; [[self netConnection] transmitPropertyList:failDict]; [self setNetConnection:nil]; [[self serverSocket] acceptConnectionInBackgroundAndNotify]; } // called when a connection is established (could be from connecting by this window or from client) -(void)gotNetworkConnection:(NSNotification *)notification { [self abortHosting:nil]; [window orderOut:nil]; } // called when connection is terminated (probably due to invalid input) -(void)networkConnectionTerminated:(NSNotification *)notification { if ([notification object]==[self netConnection]) { [self setNetConnection:nil]; [[self serverSocket] acceptConnectionInBackgroundAndNotify]; } } -(void)windowWillClose:(NSNotification *)notification { if (window==[notification object]) { [self abortHosting:nil]; } } // Rendezvous delegate methods -(void)netServiceWillPublish:(id)service { NSLog(@"Rendezvous service published"); } -(void)netService:(id)service didNotPublish:(NSDictionary *)errorDict { } -(void)netServiceDidStop:(id)service { NSLog(@"Rendezvous service stopped"); } @end gridlock.app-1.10/functions.m0000644000175000000000000000437710342202543015223 0ustar gurkanroot//--------------------------------------------------------------------------------------- // functions.m created by erik // @(#)$Id: functions.m,v 2.0 2002/08/16 18:12:49 erik Exp $ // // Copyright (c) 1997-2000 by Erik Doernenburg. All rights reserved. // // Permission to use, copy, modify and distribute this software and its documentation // is hereby granted, provided that both the copyright notice and this permission // notice appear in all copies of the software, derivative works or modified versions, // and any portions thereof, and that both notices appear in supporting documentation, // and that credit is given to Erik Doernenburg in all documents and publicity // pertaining to direct or indirect use of this code or its derivatives. // // THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE // SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS // "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY // DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE // OR OF ANY DERIVATIVE WORK. //--------------------------------------------------------------------------------------- #import #import "osdep.h" #import "functions.h" NSString *EDStringFromInAddr(struct in_addr address) { const unsigned char *bytes = (void *)&address; return [NSString stringWithFormat:@"%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]]; } struct in_addr EDInAddrFromString(NSString *string) { NSScanner *scanner; int byte, i; unsigned int numaddr; struct in_addr inaddr; scanner = [NSScanner scannerWithString:string]; numaddr = 0; for(i = 0; i < 4; i++) { if(([scanner scanInt:&byte] == NO) || (byte < 0) || (byte > 255)) [NSException raise:NSInvalidArgumentException format:@"Cannot interpret \"%@\" as an internet address.", string]; if((i < 3) && ([scanner scanString:@"." intoString:NULL] == NO)) [NSException raise:NSInvalidArgumentException format:@"Cannot interpret \"%@\" as an internet address.", string]; numaddr *= 256; numaddr += byte; } inaddr.s_addr = NSSwapHostIntToBig(numaddr); return inaddr; } gridlock.app-1.10/CatsAndDogsGame.m0000644000175000000000000000666310342202541016135 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "CatsAndDogsGame.h" static int BORDER_DIRECTIONS[] = {1,0, -1,0, 0,1, 0,-1}; @implementation CatsAndDogsGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; } -(BOOL)position:(id)pos bordersPositionWithValue:(int)value { // check up, down, left, right int r = [pos row]; int c = [pos column]; if ([self isValidRow:r+1 column:c] && value==[self valueAtRow:r+1 column:c]) return YES; if ([self isValidRow:r-1 column:c] && value==[self valueAtRow:r-1 column:c]) return YES; if ([self isValidRow:r column:c+1] && value==[self valueAtRow:r column:c+1]) return YES; if ([self isValidRow:r column:c-1] && value==[self valueAtRow:r column:c-1]) return YES; return NO; } -(BOOL)prepareMoveSequence:(NSArray *)positions { int i; id movepos = [positions lastObject]; int pnum = [self currentPlayerNumber]; int oppnum = [self nextPlayerNumber]; [self resetFutureGrid]; [[self futureGrid] setValue:pnum atPosition:movepos]; for(i=0; i<8; i+=2) { id pos = [DCHypergridPosition positionWithRow:[movepos row]+BORDER_DIRECTIONS[i] column:[movepos column]+BORDER_DIRECTIONS[i+1]]; if ([self isPositionValid:pos]) { int value = [self valueAtPosition:pos]; // value will change if position was uncontrolled or controlled only by enemy if (value==0) { // current player gains sole control [[self futureGrid] setValue:-pnum atPosition:pos]; } else if (value==-oppnum) { // both gain control [[self futureGrid] setValue:-3 atPosition:pos]; } } } return YES; } -(NSArray *)allValidMoveSequences { NSMutableArray *sequences = [NSMutableArray array]; int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { int value = [self valueAtPosition:pos]; if (value==0 || value==-pnum) { [sequences addObject:[pos arrayWithSelf_]]; } } return sequences; } -(BOOL)isGameOver { return !([[self grid] hasCellWithValue:0] || [[self grid] hasCellWithValue:0-[self currentPlayerNumber]]); } -(int)winningPlayer { return [self nextPlayerNumber]; } @end gridlock.app-1.10/QuadWrangleGame.m0000644000175000000000000000523610342202543016212 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "QuadWrangleGame.h" @implementation QuadWrangleGame -(BOOL)prepareMoveSequence:(NSArray *)positions { if ([positions count]==1) { // drops don't capture [self resetFutureGrid]; [[self futureGrid] setValue:[self currentPlayerNumber] atPosition:[positions lastObject]]; return YES; } else { // growth and slide moves flip the same as Ataxx return [super prepareMoveSequence:positions]; } } -(NSArray *)allValidMoveSequences { NSMutableArray *sequences = [NSMutableArray array]; // get growths and slides NSEnumerator *posEnum = [[self grid] enumeratorForPositionsWithValue:[self currentPlayerNumber]]; id position; while (position=[posEnum nextObject]) { int dr, dc; // find empty cells in all directions for(dr=-1; dr<=1; dr++) { for(dc=-1; dc<=1; dc++) { if (dr!=0 || dc!=0) { BOOL done = NO; int dist; for(dist=1; !done; dist++) { int r = [position row]+dist*dr; int c = [position column]+dist*dc; if ([self isValidRow:r column:c] && [self valueAtRow:r column:c]==0) { [sequences addObject:[NSArray arrayWithObjects:position, [DCHypergridPosition positionWithRow:r column:c], nil]]; } else done = YES; } } } } } // get simple drops posEnum = [[self grid] enumeratorForPositionsWithValue:0]; while (position=[posEnum nextObject]) { [sequences addObject:[position arrayWithSelf_]]; } if ([sequences count]==0) [sequences addObject:[NSArray array]]; return sequences; } @end gridlock.app-1.10/FiancoGame.h0000644000175000000000000000035410342202554015170 0ustar gurkanroot// // FiancoGame.h // Gridlock // // Created by Brian on Sun Mar 07 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "Game.h" @interface FiancoGame : Game { } @end gridlock.app-1.10/SabotageGame.m0000644000175000000000000000665610342202543015534 0ustar gurkanroot// // SabotageGame.m // Gridlock // // Created by Brian on 3/27/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "SabotageGame.h" @implementation SabotageGame -(void)reset { [super reset]; [self createGridFromConfiguration]; } -(DCHypergridPosition *)goalPositionForPlayer:(int)pnum { NSString *key = (pnum==1) ? @"p1Goal" : @"p2Goal"; NSArray *coords = [[self configurationInfo] objectForKey:key]; return [DCHypergridPosition positionWithRow:[[coords objectAtIndex:0] intValue] column:[[coords objectAtIndex:1] intValue]]; } -(int)playerWithGoalPosition:(DCHypergridPosition *)pos { int i; for(i=1; i<=[self numberOfPlayers]; i++) { if ([pos isEqual:[self goalPositionForPlayer:i]]) return i; } return 0; } -(int)rangeForPieceAtPosition:(DCHypergridPosition *)pos { int range=0; int c = [pos column]; int r; for(r=0; r<[self numberOfRows]; r++) { int value = [self valueAtRow:r column:c]; if (value==1 || value==2 || value==-1 || value==-2) ++range; } return range; } -(void)appendValidMovesFromPosition:(DCHypergridPosition *)pos forPlayer:(int)pnum intoArray:(NSMutableArray *)moves { int range = [self rangeForPieceAtPosition:pos]; int r = [pos row]; int c = [pos column]; int dr,dc; for(dr=-1; dr<=+1; dr++) { for(dc=-1; dc<=+1; dc++) { if (dr!=0 || dc!=0) { // destination must be empty, enemy, or neutral king if ([self isValidRow:r+range*dr column:c+range*dc]) { if (abs([self valueAtRow:r+range*dr column:c+range*dc])!=pnum) { // destination is valid, path must be clear BOOL good = YES; int d; for(d=1; d #import "Game.h" @interface CatsAndDogsGame : Game { } -(BOOL)position:(id)pos bordersPositionWithValue:(int)value; @end gridlock.app-1.10/GravityViewDelegate.m0000644000175000000000000000300010342202542017103 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "GravityViewDelegate.h" #import "Game.h" @implementation GravityViewDelegate // put a light gray background on cells in the diagonals -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(Game *)game { BOOL isDiagonalCell = (row==col || row+col==[game numberOfRows]-1); if (isDiagonalCell) { [[NSColor lightGrayColor] set]; NSRectFill(rect); } return NO; } @end gridlock.app-1.10/QuadWrangleGame.h0000644000175000000000000000227310342202555016206 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AtaxxGame.h" @interface QuadWrangleGame : AtaxxGame { } @end gridlock.app-1.10/HexapawnAI.m0000644000175000000000000001017210342202542015165 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "HexapawnAI.h" #import "HexapawnGame.h" @implementation HexapawnAI -(int)rowIncrementForPlayer:(int)pnum { return (pnum==1) ? 1 : -1; } -(int)piecesSupportingPostion:(id)pos forPlayer:(int)pnum inGame:(HexapawnGame *)game { BOOL canCaptureForward = [game forwardCapturesAllowed]; BOOL canCaptureDiagonally = [game diagonalCapturesAllowed]; int count=0; int dr = [self rowIncrementForPlayer:pnum]; int backr = [pos row]-dr; int c = [pos column]; if (backr>=0 && backr<[game numberOfRows]) { // straight behind if (canCaptureForward && [game valueAtRow:backr column:c]==pnum) count++; // behind left if (canCaptureDiagonally && c>0 && [game valueAtRow:backr column:c-1]==pnum) count++; // behind right if (canCaptureDiagonally && c<[game numberOfColumns]-1 && [game valueAtRow:backr column:c+1]==pnum) count++; } return count; } -(BOOL)position:(id)pos isControlledByPlayer:(int)pnum inGame:(HexapawnGame *)game { int cpnum = [game currentPlayerNumber]; int mysupport = [self piecesSupportingPostion:pos forPlayer:pnum inGame:game]; int oppsupport = [self piecesSupportingPostion:pos forPlayer:[game playerNumberMovingAfterPlayer:pnum] inGame:game]; BOOL hasControl = (mysupport>oppsupport || (mysupport==oppsupport && cpnum==pnum)); return hasControl; } -(int)controlFactorForPosition:(id)pos forPlayer:(int)pnum inGame:(HexapawnGame *)game { if (![self position:pos isControlledByPlayer:pnum inGame:game]) return 10; else { int c=[pos column]; int dr = [self rowIncrementForPlayer:pnum]; int maxr = [game numberOfRows]-1; int maxc = [game numberOfColumns]-1; int oppnum = [game nextPlayerNumber]; // check for opposing pieces ahead in this column and to sides BOOL oppAhead = NO; BOOL oppToSide = NO; int r; for(r=[pos row]+dr; r>=0 && r<=maxr; r+=dr) { if (!oppAhead && [game valueAtRow:r column:c]==oppnum) oppAhead = YES; if (!oppToSide) { if (c>0 && [game valueAtRow:r column:c-1]) oppToSide = YES; else if (cb) ? a : b; } @implementation ZoneshAI -(int)piecesSupportingPostion:(id)pos forPlayer:(int)pnum inGame:(ZoneshGame *)game { int count = 0; int maxr = [game numberOfRows]; int maxc = [game numberOfColumns]; int dr,dc; for(dr=-1; dr<=1; dr++) { int r = [pos row]+dr; for(dc=-1; dc<=1; dc++) { int c = [pos column]+dc; if (r>=0 && r=0 && coppsupport || (mysupport==oppsupport && cpnum==pnum)); return hasControl; } -(int)threatWeightForGame:(ZoneshGame *)game player:(int)pnum { int utility = 0; NSEnumerator *pe = [[game grid] enumeratorForPositionsWithValue:pnum]; id pos; int maxdc = 0; while (pos=[pe nextObject]) { int dist = [self distanceFromOriginForPosition:pos andPlayer:pnum inGame:game]; BOOL control = [self position:pos isControlledByPlayer:pnum inGame:game]; if (control) { utility += 2*dist+2; if (dist>maxdc) maxdc=dist; } else { utility += dist+1; } } utility += maxdc; return utility; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { return [self threatWeightForGame:game player:pnum] - [self threatWeightForGame:game player:[game nextPlayerNumber]]; } @end gridlock.app-1.10/ZoneshGame.m0000644000175000000000000000635010342202543015244 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ZoneshGame.h" @implementation ZoneshGame -(int)playerWithHomeZoneContainingPosition:(id)pos { int r = [pos row]; int c = [pos column]; int boardSize = [self numberOfRows]; // assumes square if (r+cboardSize) return 2; return 0; } -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; { NSEnumerator *pe = [grid positionEnumerator]; id pos; while(pos=[pe nextObject]) { [self setValue:[self playerWithHomeZoneContainingPosition:pos] atPosition:pos]; } } } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self resetFutureGrid]; [[self futureGrid] setValue:0 atPosition:[positions objectAtIndex:0]]; [[self futureGrid] setValue:[self currentPlayerNumber] atPosition:[positions objectAtIndex:1]]; return YES; } -(int)winningPlayer { if (![grid hasCellWithValue:2]) return 1; if (![grid hasCellWithValue:1]) return 2; // player 1 wins by getting to (maxr, maxc), player 2 wins by getting to (0,0) if ([self valueAtRow:0 column:0]==2) return 2; if ([self valueAtRow:[self numberOfRows]-1 column:[self numberOfColumns]-1]==1) return 1; return 0; } -(BOOL)isGameOver { return ([self winningPlayer]!=0); } -(NSArray *)allValidMoveSequences { int pnum = [self currentPlayerNumber]; NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:pnum]; id pos; while (pos=[pe nextObject]) { int zoneowner = [self playerWithHomeZoneContainingPosition:pos]; NSArray *neighbors = [[self grid] neighborsOfPosition:pos distance:1]; NSEnumerator *ne = [neighbors objectEnumerator]; id npos; while (npos=[ne nextObject]) { if ([self valueAtPosition:npos]!=pnum) { // if in home zone, must be a horizontal or vertical move if (zoneowner!=pnum || [npos row]==[pos row] || [npos column]==[pos column]) { [moves addObject:[NSArray arrayWithObjects:pos,npos,nil]]; } } } } return moves; } @end gridlock.app-1.10/ZoneshViewDelegate.m0000644000175000000000000000355310342202543016742 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "ZoneshViewDelegate.h" #import "Preferences.h" @implementation ZoneshViewDelegate // we want to tint the cell with the color of the player that owns the territory. We then return NO so // that the piece will be drawn as normal -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(ZoneshGame *)game { int owner = [game playerWithHomeZoneContainingPosition:[DCHypergridPosition positionWithRow:row column:col]]; if (owner>0) { NSColor *playerColor = [[Preferences sharedInstance] highlightColorForPlayerNumber:owner]; [[playerColor blendedColorWithFraction:0.75 ofColor:[NSColor whiteColor]] set]; NSRectFill(rect); } return NO; } @end gridlock.app-1.10/AutoplayController.h0000644000175000000000000000260010342202554017035 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GridlockGameState.h" #import "AccessorMacros.h" @interface AutoplayController : NSObject { GridlockGameState *gameState; NSMutableDictionary *playerWins; NSMutableDictionary *moveStatistics; } idAccessor_h(gameState, setGameState) -(void)run; @end gridlock.app-1.10/GravityAI.h0000644000175000000000000000241710342202555015041 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GravityGame.h" #import "GenericAI.h" @interface GravityAI : GenericAI { } -(int)threatWeightForGame:(GravityGame *)game player:(int)pnum; @end gridlock.app-1.10/GravityGame.h0000644000175000000000000000230610342202555015416 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AbstractLineGame.h" @interface GravityGame : AbstractLineGame { } @end gridlock.app-1.10/GravityViewDelegate.h0000644000175000000000000000224210342202555017111 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import @interface GravityViewDelegate : NSObject { } @end gridlock.app-1.10/CatsAndDogsViewDelegate.m0000644000175000000000000000222310342202541017615 0ustar gurkanroot// // CatsAndDogsViewDelegate.m // Gridlock // // Created by Brian on Mon Aug 18 2003. // Copyright (c) 2003 __MyCompanyName__. All rights reserved. // #import "CatsAndDogsViewDelegate.h" #import #import "CatsAndDogsGame.h" #import "Preferences.h" @implementation CatsAndDogsViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game { // +X: player X has placed a piece at this position // -X: player X has a piece bordering this position, opponent does not // -3: both players have pieces bordering this position NSColor *tintColor = nil; if (abs(value)>2) { tintColor = [NSColor grayColor]; } else if (abs(value)==1) { tintColor = [[[Preferences sharedInstance] highlightColorForPlayerNumber:1] blendedColorWithFraction:0.75 ofColor:[NSColor whiteColor]]; } else if (abs(value)==2) { tintColor = [[[Preferences sharedInstance] highlightColorForPlayerNumber:2] blendedColorWithFraction:0.75 ofColor:[NSColor whiteColor]]; } if (tintColor) { [tintColor set]; NSRectFill(rect); } return NO; } -(BOOL)disableAnimation { return YES; } @end gridlock.app-1.10/CatsAndDogsViewDelegate.h0000644000175000000000000000037210342202554017617 0ustar gurkanroot// // CatsAndDogsViewDelegate.h // Gridlock // // Created by Brian on Mon Aug 18 2003. // Copyright (c) 2003 __MyCompanyName__. All rights reserved. // #import @interface CatsAndDogsViewDelegate : NSObject { } @end gridlock.app-1.10/ZoneshAI.h0000644000175000000000000000226510342202556014664 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface ZoneshAI : GenericAI { } @end gridlock.app-1.10/ZoneshGame.h0000644000175000000000000000234110342202556015237 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface ZoneshGame : Game { } -(int)playerWithHomeZoneContainingPosition:(id)pos; @end gridlock.app-1.10/ZoneshViewDelegate.h0000644000175000000000000000245310342202556016737 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "ZoneshGame.h" @interface ZoneshViewDelegate : NSObject { } -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(ZoneshGame *)game; @end gridlock.app-1.10/HexapawnGame.m0000644000175000000000000001522010342202542015544 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "HexapawnGame.h" @implementation HexapawnGame -(BOOL)forwardMovesAllowed { return [[self configurationInfo] objectForKey:@"moveForward"]!=nil; } -(BOOL)diagonalMovesAllowed { return [[self configurationInfo] objectForKey:@"moveDiagonally"]!=nil; } -(BOOL)forwardCapturesAllowed { return [[self configurationInfo] objectForKey:@"captureForward"]!=nil; } -(BOOL)diagonalCapturesAllowed { return [[self configurationInfo] objectForKey:@"captureDiagonally"]!=nil; } -(BOOL)sidewaysCapturesAllowed { return [[self configurationInfo] objectForKey:@"captureSideways"]!=nil; } -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; { int rowsToFill = [[[self configurationInfo] objectForKey:@"fillRows"] intValue]; if (rowsToFill<=0) rowsToFill = 1; [self fillFirstRows:rowsToFill]; } } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self resetFutureGrid]; [[self futureGrid] setValue:0 atPosition:[positions objectAtIndex:0]]; [[self futureGrid] setValue:[self currentPlayerNumber] atPosition:[positions objectAtIndex:1]]; return YES; } -(int)playerAtLastRow { int rows = [self numberOfRows]; int cols = [self numberOfColumns]; int c; // check for player 1 on the top row or player 2 on the bottom row for(c=0; c0) { value = [self valueAtRow:r+dr column:c-1]; if ((canMoveDiagonally && value==0) || (canCaptureDiagonally && value==oppnum)) { [sequences addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+dr column:c-1],nil]]; } } if (c0 && [self valueAtRow:r column:c-1]==oppnum) { [sequences addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r column:c-1],nil]]; } if (c0) { value = [self valueAtRow:r+dr column:c-1]; if ((canMoveDiagonally && value==0) || (canCaptureDiagonally && value==oppnum)) return YES; } if (c0 && [self valueAtRow:r column:c-1]==oppnum) return YES; if (c0 && [self valueAtRow:r+1 column:c-1]==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c-1], nil]]; } if (c<[self numberOfColumns]-1 && [self valueAtRow:r+1 column:c+1]==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c+1], nil]]; } } } else { // Moray eels move forward or diagonally forward like Octopussies (down the board), // or up to 2 sideways or 2 sideways and 1 back int dr, dc; for(dr=-1; dr<=1; dr++) { for(dc=-2; dc<=2; dc++) { if (dr>=0 || (dc>-2 && dc<2)) { if (r+dr>=0 && r+dr<[self numberOfRows] && c+dc>=0 && c+dc<[self numberOfColumns] && [self valueAtRow:r+dr column:c+dc]==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+dr column:c+dc], nil]]; } } } } } } -(NSArray *)allValidMoveSequences { int pnum = [self currentPlayerNumber]; NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *posEnum = [[self grid] enumeratorForPositionsWithValue:pnum]; id position; while (position=[posEnum nextObject]) { [self appendMovesForPlayer:pnum fromPosition:position intoArray:moves]; } if ([moves count]==0) [moves addObject:[NSArray array]]; return moves; } -(BOOL)isGameOver { int pnum = [self currentPlayerNumber]; NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *posEnum = [[self grid] enumeratorForPositionsWithValue:pnum]; id position; while (position=[posEnum nextObject]) { [self appendMovesForPlayer:pnum fromPosition:position intoArray:moves]; if ([moves count]>0) return NO; } return YES; } -(int)winningPlayer { if ([self currentPlayerNumber]==1) { // Octopussies win if they can't move but have gotten a piece to the last row int r = [self numberOfRows]-1; int c; for(c=[self numberOfColumns]-1; c>=0; c--) { if ([self valueAtRow:r column:c]==1) return 1; } } return [self nextPlayerNumber]; } -(BOOL)showScores { return NO; } @end gridlock.app-1.10/HexapawnAI.h0000644000175000000000000000231710342202555015166 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface HexapawnAI : GenericAI { NSArray *searchDepths; } @end gridlock.app-1.10/HexapawnGame.h0000644000175000000000000000253710342202555015552 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface HexapawnGame : Game { } -(BOOL)forwardMovesAllowed; -(BOOL)diagonalMovesAllowed; -(BOOL)forwardCapturesAllowed; -(BOOL)diagonalCapturesAllowed; -(BOOL)sidewaysCapturesAllowed; -(int)playerAtLastRow; @end gridlock.app-1.10/MorayEelsGame.h0000644000175000000000000000227210342202555015673 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "AtaxxGame.h" @interface MorayEelsGame : AtaxxGame { } @end gridlock.app-1.10/SabotageViewDelegate.m0000644000175000000000000000263510342202543017221 0ustar gurkanroot// // SabotageViewDelegate.m // Gridlock // // Created by Brian on 3/27/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "SabotageViewDelegate.h" #import "SabotageGame.h" #import "Preferences.h" #import "ImageStore.h" @implementation SabotageViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(SabotageGame *)game { // tint the goal cells int owner = [game playerWithGoalPosition:[DCHypergridPosition positionWithRow:row column:col]]; if (owner>0) { NSColor *playerColor = [[Preferences sharedInstance] highlightColorForPlayerNumber:owner]; [[playerColor blendedColorWithFraction:0.75 ofColor:[NSColor whiteColor]] set]; NSRectFill(rect); } if (value>=0) { // regular piece, draw normally return NO; } else { // ball or ball carrier if (-value<=[game numberOfPlayers]) { // draw player piece NSImage *image = [[ImageStore defaultStore] pieceImageForPlayer:-value withSize:rect.size]; [image compositeToPoint:rect.origin operation:NSCompositeSourceOver]; } // draw ball indicator [[NSColor darkGrayColor] set]; NSRect ballRect = NSMakeRect(rect.origin.x+rect.size.width/2, rect.origin.y+rect.size.height/6, rect.size.width/3, rect.size.height/3); [[NSBezierPath bezierPathWithOvalInRect:ballRect] fill]; return NO; } } @end gridlock.app-1.10/TongaGame.m0000644000175000000000000000413710342202543015047 0ustar gurkanroot// // TongaGame.m // Gridlock // // Created by Brian on 11/6/04. // Copyright 2004 __MyCompanyName__. All rights reserved. // #import "TongaGame.h" @implementation TongaGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; } -(BOOL)appendValidMovesFromPosition:(id)startpos intoArray:(NSMutableArray *)moves { int r = [startpos row]; int c = [startpos column]; int dr,dc; BOOL found = NO; for(dr=-1; dr<=+1; dr++) { for(dc=-1; dc<=+1; dc++) { if (dr!=0 || dc!=0) { if ([self isValidRow:r+dr column:c+dc] && [self valueAtRow:r+dr column:c+dc]==0) { if (!moves) return YES; found = YES; [moves addObject:[NSArray arrayWithObjects:startpos, [DCHypergridPosition positionWithRow:r+dr column:c+dc], nil]]; } } } } return found; } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:0]; id pos; while(pos=[pe nextObject]) { [self appendValidMovesFromPosition:pos intoArray:moves]; } return moves; } -(BOOL)isGameOver { NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:0]; id pos; while(pos=[pe nextObject]) { if ([self appendValidMovesFromPosition:pos intoArray:nil]) return NO; } return YES; } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self resetFutureGrid]; [[self futureGrid] setValue:[self currentPlayerNumber] atPosition:[positions objectAtIndex:0]]; [[self futureGrid] setValue:[self nextPlayerNumber] atPosition:[positions objectAtIndex:1]]; return YES; } -(BOOL)showScores { return YES; } -(int)scoreForPlayer:(int)pnum { NSArray *groups = [[self grid] connectedGroupsWithValue:pnum onlyOrthoganal:YES]; int score = 0; int len = [groups count]; int i; for(i=0; i<3 && i0) { if (!moves) return YES; // if no array, we just want to know if there's a valid move found = YES; [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+dist*dr column:c+dist*dc], nil]]; } } return found; } +(NSArray *)allValidMoveSequences:(Game *)game fromPositionsWithValue:(int)sval { NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *pe = [[game grid] enumeratorForPositionsWithValue:sval]; id pos; while (pos=[pe nextObject]) { [self appendValidMovesForGame:game fromPosition:pos intoArray:moves]; } return moves; } +(NSArray *)allValidMoveSequences:(Game *)game { return [self allValidMoveSequences:game fromPositionsWithValue:[game currentPlayerNumber]]; } +(BOOL)gameHasAnyMoves:(Game *)game fromPositionsWithValue:(int)sval { NSEnumerator *pe = [[game grid] enumeratorForPositionsWithValue:sval]; id pos; while (pos=[pe nextObject]) { if ([self appendValidMovesForGame:game fromPosition:pos intoArray:nil]) return YES; } return NO; } +(BOOL)gameHasAnyMoves:(Game *)game { return [self gameHasAnyMoves:game fromPositionsWithValue:[game currentPlayerNumber]]; } @end gridlock.app-1.10/AtomicAI.m0000644000175000000000000000340010342202541014621 0ustar gurkanroot// // AtomicAI.m // Gridlock // // Created by Brian on Sat Feb 14 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "AtomicAI.h" #import "AtomicGame.h" static NSArray* convertArrayValuesToNSNumbers(NSArray *array) { NSMutableArray *result = [NSMutableArray array]; id obj; NSEnumerator *e = [array objectEnumerator]; while (obj=[e nextObject]) { if ([obj isKindOfClass:[NSArray class]]) { [result addObject:convertArrayValuesToNSNumbers(obj)]; } else if ([obj respondsToSelector:@selector(intValue)]) { [result addObject:[NSNumber numberWithInt:[obj intValue]]]; } else { [result addObject:obj]; } } return result; } @implementation AtomicAI -(void)dealloc { [utilityArray release]; [super dealloc]; } -(int)utilityForPlayer:(int)pnum inGame:(AtomicGame *)game { NSEnumerator *pe = [[game grid] positionEnumerator]; id pos; int utility = 0; while (pos=[pe nextObject]) { if ([game ownerOfPosition:pos]==pnum) { int numPieces = abs([game valueAtPosition:pos]); int maxStablePieces = [game maxStablePiecesForPosition:pos]; utility += (utilityArray==nil) ? 1 : [[[utilityArray objectAtIndex:maxStablePieces-1] objectAtIndex:numPieces-1] intValue]; } } return utility; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { return [self utilityForPlayer:pnum inGame:game] - [self utilityForPlayer:[game playerNumberMovingAfterPlayer:pnum] inGame:game]; } /* utilityArray values come in as strings. The setter converts them to NSNumbers to avoid repeated string conversions in utilityForPlayer:inGame: */ -(void)setUtilityArray:(NSArray *)array { [utilityArray autorelease]; utilityArray = [convertArrayValuesToNSNumbers(array) retain]; } @end gridlock.app-1.10/AtomicGame.m0000644000175000000000000001236210342202541015210 0ustar gurkanroot// // AtomicGame.m // Gridlock // // Created by Brian on Sun Feb 08 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "AtomicGame.h" @implementation AtomicGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; } -(int)ownerOfPosition:(DCHypergridPosition *)pos { int value = [self valueAtPosition:pos]; if (value==0) return 0; else if (value>0) return 1; else return 2; } -(int)ownerOfRow:(int)r column:(int)c { int value = [self valueAtRow:r column:c]; if (value==0) return 0; else if (value>0) return 1; else return 2; } -(int)numberOfPositionsOwnedByPlayer:(int)pnum { NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; int total = 0; while (pos=[pe nextObject]) { if (pnum==[self ownerOfPosition:pos]) ++total; } return total; } -(BOOL)isAnyPositionOwnedByPlayer:(int)pnum { NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { if (pnum==[self ownerOfPosition:pos]) return YES; } return NO; } -(int)maxStablePiecesForRow:(int)r column:(int)c { BOOL endrow = (r==0 || r==[self numberOfRows]-1); BOOL endcol = (c==0 || c==[self numberOfColumns]-1); if (endrow && endcol) return 1; if (endrow || endcol) return 2; return 3; } -(int)maxStablePiecesForPosition:(DCHypergridPosition *)pos { return [self maxStablePiecesForRow:[pos row] column:[pos column]]; } -(int)cellValueDelta { return ([self currentPlayerNumber]==1) ? 1 : -1; } -(void)removePieceFromGrid:(DCHypergrid *)theGrid atRow:(int)r column:(int)c { [theGrid setValue:[theGrid valueAtRow:r column:c]-[self cellValueDelta] atRow:r column:c]; } -(void)addCapturingPieceToGrid:(DCHypergrid *)theGrid atRow:(int)r column:(int)c { [theGrid setValue:[self cellValueDelta]*(1+abs([theGrid valueAtRow:r column:c])) atRow:r column:c]; } // returns YES if following the explostion there are more unstable positions *and* cells are owned by both players -(BOOL)performExplosionIterationInGrid:(DCHypergrid *)theGrid fromPositions:(NSArray *)positions nextUnstablePositions:(NSMutableArray *)nextUnstablePositions { // this method may be performance-sensitive, avoiding object allocations int i; int maxr = [self numberOfRows]; int maxc = [self numberOfColumns]; for(i=0; i<[positions count]; i++) { id pos = [positions objectAtIndex:i]; int r = [pos row]; int c = [pos column]; // distribute pieces to orthogonal adjacent positions if (r>0) { [self removePieceFromGrid:theGrid atRow:r column:c]; [self addCapturingPieceToGrid:theGrid atRow:r-1 column:c]; } if (r0) { [self removePieceFromGrid:theGrid atRow:r column:c]; [self addCapturingPieceToGrid:theGrid atRow:r column:c-1]; } if (c0) ? 1 : 2); if (owner==1) hasP1 = YES; if (owner==2) hasP2 = YES; if (abs(value)>[self maxStablePiecesForRow:r column:c]) { [nextUnstablePositions addObject:[DCHypergridPosition positionWithRow:r column:c]]; } } } return ([nextUnstablePositions count]>0 && hasP1 && hasP2); } } -(BOOL)prepareMoveSequence:(NSArray *)move { id pos = [move lastObject]; [self resetFutureGrid]; [self addCapturingPieceToGrid:[self futureGrid] atRow:[pos row] column:[pos column]]; if (abs([self valueAtPosition:pos])>=[self maxStablePiecesForPosition:pos]) { // move causes an explosion, compute resulting grid NSMutableArray *explodingPositions = [NSMutableArray arrayWithObject:pos]; BOOL stillGoing = YES; // repeat until explosions stop or opponent is dead while (stillGoing) { stillGoing = [self performExplosionIterationInGrid:[self futureGrid] fromPositions:explodingPositions nextUnstablePositions:explodingPositions]; } } return YES; } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { int owner = [self ownerOfPosition:pos]; if (owner==0 || owner==pnum) { [moves addObject:[pos arrayWithSelf_]]; } } return moves; } -(BOOL)isGameOver { return ([self moveCount]>2 && !([self isAnyPositionOwnedByPlayer:1] && [self isAnyPositionOwnedByPlayer:2])); } -(int)winningPlayer { if ([self isAnyPositionOwnedByPlayer:1]) return 1; return 2; } @end gridlock.app-1.10/AtomicViewDelegate.m0000644000175000000000000000562710342202541016712 0ustar gurkanroot// // AtomicViewDelegate.m // Gridlock // // Created by Brian on Fri Feb 13 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "AtomicViewDelegate.h" #import "ImageStore.h" #import "AtomicGame.h" @implementation AtomicViewDelegate -(void)drawPieceImageForPlayer:(int)pnum times:(int)numImages inRect:(NSRect)rect { NSImage *image; float scale = 1.0f/3; image = [[ImageStore defaultStore] pieceImageForPlayer:pnum withSize:NSMakeSize(rect.size.width*scale, rect.size.height*scale)]; if (numImages==1) { float offset = (1-scale)/2; [image compositeToPoint:NSMakePoint(rect.origin.x + offset*rect.size.width, rect.origin.y + offset*rect.size.height) operation:NSCompositeSourceOver]; } if (numImages==2) { float yoff = (1-scale)/2; float xgap = (1-2*scale)/3; [image compositeToPoint:NSMakePoint(rect.origin.x + xgap*rect.size.width, rect.origin.y + yoff*rect.size.height) operation:NSCompositeSourceOver]; [image compositeToPoint:NSMakePoint(rect.origin.x + (scale+2*xgap)*rect.size.width, rect.origin.y + yoff*rect.size.height) operation:NSCompositeSourceOver]; } if (numImages==3) { float coff = (1-scale)/2; float gap = (1-2*scale)/3; [image compositeToPoint:NSMakePoint(rect.origin.x + gap*rect.size.width, rect.origin.y + gap*rect.size.height) operation:NSCompositeSourceOver]; [image compositeToPoint:NSMakePoint(rect.origin.x + (scale+2*gap)*rect.size.width, rect.origin.y + gap*rect.size.height) operation:NSCompositeSourceOver]; [image compositeToPoint:NSMakePoint(rect.origin.x + coff*rect.size.width, rect.origin.y + (scale+2*gap)*rect.size.height) operation:NSCompositeSourceOver]; } if (numImages>3) { float gap = (1-2*scale)/3; [image compositeToPoint:NSMakePoint(rect.origin.x + gap*rect.size.width, rect.origin.y + gap*rect.size.height) operation:NSCompositeSourceOver]; [image compositeToPoint:NSMakePoint(rect.origin.x + (scale+2*gap)*rect.size.width, rect.origin.y + gap*rect.size.height) operation:NSCompositeSourceOver]; [image compositeToPoint:NSMakePoint(rect.origin.x + gap*rect.size.width, rect.origin.y + (scale+2*gap)*rect.size.height) operation:NSCompositeSourceOver]; [image compositeToPoint:NSMakePoint(rect.origin.x + (scale+2*gap)*rect.size.width, rect.origin.y + (scale+2*gap)*rect.size.height) operation:NSCompositeSourceOver]; } } -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(AtomicGame *)game { int owner = [game ownerOfRow:row column:col]; if (owner>0) { [self drawPieceImageForPlayer:owner times:abs([game valueAtRow:row column:col]) inRect:rect]; } return YES; } @end gridlock.app-1.10/BombardmentAI.m0000644000175000000000000001115110342202541015641 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "BombardmentAI.h" @interface BombardmentAIGoodMoveEnumerator : NSEnumerator { Game *game; NSMutableArray *startPositions; int movesReturned; int movedr; // 1 or -1 depending on player number // these ivars store where we are in the process of searching for moves int startPositionIndex; // which position we're starting from int directionIndex; // index of the neighbor (possible ending position) of the start position BOOL done; } @end @implementation BombardmentAIGoodMoveEnumerator -(id)initWithGame:(Game *)g { if (self=[super init]) { game = [g retain]; // get start positions, and randomize so that if the utilities are equal the same move won't always be made { NSEnumerator *pe = [[game grid] enumeratorForPositionsWithValue:[game currentPlayerNumber]]; id pos; startPositions = [[NSMutableArray alloc] init]; while (pos=[pe nextObject]) { [startPositions addObject:pos]; } [startPositions randomizeObjects_]; movedr = ([game currentPlayerNumber]==1) ? 1 : -1; } } return self; } -(void)dealloc { [game release]; [startPositions release]; [super dealloc]; } -(id)nextObject { id move = nil; if (done) return nil; while (move==nil && !done) { // check current possible move id startpos = [startPositions objectAtIndex:startPositionIndex]; int r = [startpos row]; int c = [startpos column]; if (directionIndex==0 && [game isValidRow:r+movedr column:c-1] && [game valueAtRow:r+movedr column:c-1]==0) { move = [NSArray arrayWithObjects:startpos, [DCHypergridPosition positionWithRow:r+movedr column:c-1], nil]; } else if (directionIndex==1 && [game isValidRow:r+movedr column:c] && [game valueAtRow:r+movedr column:c]==0) { move = [NSArray arrayWithObjects:startpos, [DCHypergridPosition positionWithRow:r+movedr column:c], nil]; } else if (directionIndex==2 && [game isValidRow:r+movedr column:c+1] && [game valueAtRow:r+movedr column:c+1]==0) { move = [NSArray arrayWithObjects:startpos, [DCHypergridPosition positionWithRow:r+movedr column:c+1], nil]; } else if (directionIndex==3 && [[game grid] numberOfNeighborsOfPosition:startpos withValue:[game nextPlayerNumber]]>0) { // only check detonation moves if move = [NSArray arrayWithObjects:startpos, startpos, nil]; } // increment counters and see if we're done ++directionIndex; if (directionIndex==4) { directionIndex = 0; if (++startPositionIndex==[startPositions count]) done=YES; } } return move; } @end @implementation BombardmentAI -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { int utility = 0; NSEnumerator *pe = [[game grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { int value = [game valueAtPosition:pos]; if (value>0) { int row = (value==1) ? [pos row] : [game numberOfRows]-1-[pos row]; int rweight = abs(row-1); // 2nd row is bad int friendlyNeighbors = [[game grid] numberOfNeighborsOfPosition:pos withValue:value]; rweight += [[game grid] numberOfNeighborsOfPosition:pos withValue:[game playerNumberMovingAfterPlayer:value]] - friendlyNeighbors; if (row>2 && friendlyNeighbors==0) rweight += 3; utility += (10+rweight)*((value==pnum) ? 1 : -1); } } return utility; } -(NSEnumerator *)enumeratorForMovesToConsiderForGame:(Game *)game { return [[[BombardmentAIGoodMoveEnumerator alloc] initWithGame:game] autorelease]; } @end gridlock.app-1.10/BombardmentGame.m0000644000175000000000000000371510342202541016230 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "BombardmentGame.h" @implementation BombardmentGame -(BOOL)prepareMoveSequence:(NSArray *)positions { if ([[positions objectAtIndex:0] isEqual:[positions objectAtIndex:1]]) { [self resetFutureGrid]; [[self futureGrid] setValue:0 atPositions:[[self grid] neighborsOfPosition:[positions objectAtIndex:0] distance:1]]; return YES; } else { return [super prepareMoveSequence:positions]; } } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [super allValidMoveSequences]; // add detonation moves NSEnumerator *pe = [[self grid] enumeratorForPositionsWithValue:[self currentPlayerNumber]]; id pos; while (pos=[pe nextObject]) { [moves addObject:[NSArray arrayWithObjects:pos,pos,nil]]; } return moves; } -(BOOL)isGameOver { return ([self playerAtLastRow]!=0 || ![[self grid] hasCellWithValue:[self currentPlayerNumber]]); } @end gridlock.app-1.10/DaggerAI.m0000644000175000000000000000174710342202541014612 0ustar gurkanroot// // DaggerAI.m // Gridlock // // Created by Brian on Sun Feb 29 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "DaggerAI.h" #import "DaggerGame.h" @implementation DaggerAI -(id)init { self = [super init]; p1DaggerWeight = 20; p2DaggerWeight = 30; crownPositionWeight = 5; return self; } -(int)utilityForGame:(DaggerGame *)game player:(int)pnum { int daggerWeight = (pnum==1) ? p1DaggerWeight : p2DaggerWeight; int baserow = (pnum==1) ? 0 : [game numberOfRows]-1; int utility = daggerWeight*[game numberOfDaggersForPlayer:pnum]; NSEnumerator *ce = [[game grid] enumeratorForPositionsWithValue:-pnum]; id crownPos; while (crownPos=[ce nextObject]) { utility += crownPositionWeight * abs([crownPos row]-baserow); } return utility; } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { return [self utilityForGame:game player:pnum] - [self utilityForGame:game player:[game playerNumberMovingAfterPlayer:pnum]]; } @end gridlock.app-1.10/DaggerGame.m0000644000175000000000000001024310342202541015161 0ustar gurkanroot// // DaggerGame.m // Gridlock // // Created by Brian on Sun Feb 29 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "DaggerGame.h" @implementation DaggerGame -(void)reset { [super reset]; [self createGridFromConfiguration]; } -(int)ownerOfPosition:(DCHypergridPosition *)pos { return abs([self valueAtPosition:pos]); } -(int)ownerOfRow:(int)r column:(int)c { return abs([self valueAtRow:r column:c]); } -(BOOL)isCrownAtPosition:(DCHypergridPosition *)pos { return ([self valueAtPosition:pos]<0); } -(BOOL)isCrownAtRow:(int)r column:(int)c { return ([self valueAtRow:r column:c]<0); } -(int)numberOfDaggersForPlayer:(int)pnum { return [[self grid] numberOfCellsWithValue:pnum]; } -(int)numberOfCrownsForPlayer:(int)pnum{ return [[self grid] numberOfCellsWithValue:-pnum]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self resetFutureGrid]; [[self futureGrid] setValue:0 atPosition:[positions objectAtIndex:0]]; [[self futureGrid] setValue:[self valueAtPosition:[positions objectAtIndex:0]] atPosition:[positions objectAtIndex:1]]; return YES; } -(int)winningPlayer { return [self nextPlayerNumber]; } -(void)appendValidDaggerMovesFromPosition:(id)pos forPlayer:(int)pnum intoArray:(NSMutableArray *)moves { int r = [pos row]; int c = [pos column]; // check diagonally uphill if ([self isValidRow:r+1 column:c-1] && [self ownerOfRow:r+1 column:c-1]!=pnum) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c-1], nil]]; } if ([self isValidRow:r+1 column:c+1] && [self ownerOfRow:r+1 column:c+1]!=pnum) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c+1], nil]]; } // check directly uphill, can't capture daggers if ([self isValidRow:r+1 column:c]) { int owner = [self ownerOfRow:r+1 column:c]; if (owner==0 || (owner!=pnum && [self isCrownAtRow:r+1 column:c])) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+1 column:c], nil]]; } } // check downhill int dc; int i; for(dc=-1; dc<=+1; dc++) { BOOL done = NO; for(i=1; !done; i++) { int endr = r-i; int endc = c+i*dc; if ([self isValidRow:endr column:endc]) { int owner = [self ownerOfRow:endr column:endc]; if (owner==0) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:endr column:endc], nil]]; } else { // we hit another piece, capture if we can if (owner!=pnum && (dc!=0 || [self isCrownAtRow:endr column:endc])) { [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:endr column:endc], nil]]; } done = YES; } } else done = YES; } } } -(void)appendValidCrownMovesFromPosition:(id)pos forPlayer:(int)pnum intoArray:(NSMutableArray *)moves { NSEnumerator *pe = [[[self grid] neighborsOfPosition:pos distance:1] objectEnumerator]; id npos; while (npos=[pe nextObject]) { if ([self ownerOfPosition:npos]!=pnum) { [moves addObject:[NSArray arrayWithObjects:pos,npos,nil]]; } } } -(NSArray *)allValidMoveSequences { int pnum = [self currentPlayerNumber]; NSMutableArray *moves = [NSMutableArray array]; NSEnumerator *posEnum = [[self grid] positionEnumerator]; id position; while (position=[posEnum nextObject]) { int value = [self valueAtPosition:position]; if (value==pnum) { [self appendValidDaggerMovesFromPosition:position forPlayer:pnum intoArray:moves]; } else if (value==-pnum) { [self appendValidCrownMovesFromPosition:position forPlayer:pnum intoArray:moves]; } } if ([moves count]==0) [moves addObject:[NSArray array]]; return moves; } -(int)playerWithCrownAtLastRow { int c; int maxr = [self numberOfRows]-1; for(c=[self numberOfColumns]-1; c>=0; c--) { if ([self valueAtRow:0 column:c]==-2) return 2; if ([self valueAtRow:maxr column:c]==-1) return 1; } return 0; } -(BOOL)isGameOver { return [self numberOfCrownsForPlayer:1]<2 || [self numberOfCrownsForPlayer:2]<2 || [self playerWithCrownAtLastRow]>0; } @end gridlock.app-1.10/FissionAI.m0000644000175000000000000000076610342202542015034 0ustar gurkanroot// // FissionAI.m // Gridlock // // Created by Brian on Sat Nov 22 2003. // Copyright (c) 2003 __MyCompanyName__. All rights reserved. // #import "FissionAI.h" @implementation FissionAI -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { // if we're doing the suicide option, negate the score if ([[game configurationInfo] objectForKey:@"suicide"]) { return -[super relativeUtilityForGame:game player:pnum]; } return [super relativeUtilityForGame:game player:pnum]; } @end gridlock.app-1.10/FissionGame.m0000644000175000000000000000446210342202542015411 0ustar gurkanroot// // FissionGame.m // Gridlock // // Created by Brian on Sat Nov 22 2003. // Copyright (c) 2003 __MyCompanyName__. All rights reserved. // #import "FissionGame.h" #import "AnyDirectionUntilBlockedMoveRule.h" @implementation FissionGame -(void)reset { [super reset]; [self createGridFromConfiguration]; if ([[self configurationInfo] objectForKey:@"randomCells"]) { int ncells = [[[self configurationInfo] objectForKey:@"randomCells"] intValue]; int p; for(p=1; p<=[self numberOfPlayers]; p++) { [self fillRandomEmptyCellsWithValue:p count:ncells]; } } [self setCurrentPlayerNumber:1]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { id pos0 = [positions objectAtIndex:0]; id pos1 = [positions objectAtIndex:1]; // get direction of move so we can tell if it ended by hitting an edge or another piece int dr = ([pos1 row]>[pos0 row]) ? 1 : (([pos1 row]<[pos0 row]) ? -1 : 0); int dc = ([pos1 column]>[pos0 column]) ? 1 : (([pos1 column]<[pos0 column]) ? -1 : 0); [self resetFutureGrid]; [[self futureGrid] setValue:0 atPosition:pos0]; // detonate if we hit a piece and not an edge if ([self isValidRow:[pos1 row]+dr column:[pos1 column]+dc]) { [[self futureGrid] setValue:0 atPositions:[[self futureGrid] neighborsOfPosition:pos1 distance:1]]; } else { [[self futureGrid] setValue:[self currentPlayerNumber] atPosition:pos1]; } return YES; } -(BOOL)isSuicideVariation { return ([[self configurationInfo] objectForKey:@"suicide"]!=nil); } -(int)winningPlayer { int n1 = [[self grid] numberOfCellsWithValue:1]; int n2 = [[self grid] numberOfCellsWithValue:2]; if (n1>0 && n2==0) return ([self isSuicideVariation]) ? 2 : 1; if (n2>0 && n1==0) return ([self isSuicideVariation]) ? 1 : 2; // either both have no pieces, are tied at 1, or current player has no move return 0; } -(BOOL)isGameOver { // game over if either player has no pieces, or both have exactly 1, or current player can't move int n1 = [[self grid] numberOfCellsWithValue:1]; int n2 = [[self grid] numberOfCellsWithValue:2]; return (n1==0 || n2==0 || (n1==1 && n2==1) || ![AnyDirectionUntilBlockedMoveRule gameHasAnyMoves:self]); } -(NSArray *)allValidMoveSequences { return [AnyDirectionUntilBlockedMoveRule allValidMoveSequences:self]; } -(BOOL)showScores { return YES; } @end gridlock.app-1.10/OrthokonGame.m0000644000175000000000000000514010342202542015574 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "OrthokonGame.h" #import "AnyDirectionUntilBlockedMoveRule.h" @implementation OrthokonGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; [self fillFirstRows:1]; } -(BOOL)prepareMoveSequence:(NSArray *)positions { static int ROW_DIRECTIONS[] = {+1, 0, 0,-1}; static int COL_DIRECTIONS[] = { 0,-1,+1, 0}; int pnum = [self currentPlayerNumber]; int oppnum = [self nextPlayerNumber]; id endpos = [positions objectAtIndex:1]; int r = [endpos row]; int c = [endpos column]; int i; [self resetFutureGrid]; [[self futureGrid] setValue:0 atPosition:[positions objectAtIndex:0]]; [[self futureGrid] setValue:pnum atPosition:endpos]; // flip opposing pieces up, down, left, right of destination for(i=0; i<4; i++) { if ([self isValidRow:r+ROW_DIRECTIONS[i] column:c+COL_DIRECTIONS[i]] && [self valueAtRow:r+ROW_DIRECTIONS[i] column:c+COL_DIRECTIONS[i]]==oppnum) { [[self futureGrid] setValue:pnum atRow:r+ROW_DIRECTIONS[i] column:c+COL_DIRECTIONS[i]]; } } return YES; } -(int)winningPlayer { // if the game is over, the current player has lost (can't move) return [self nextPlayerNumber]; } -(BOOL)isGameOver { return ![AnyDirectionUntilBlockedMoveRule gameHasAnyMoves:self]; } -(NSArray *)allValidMoveSequences { return [AnyDirectionUntilBlockedMoveRule allValidMoveSequences:self]; } @end gridlock.app-1.10/FiveFieldKonoAI.m0000644000175000000000000000310110342202542016070 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "FiveFieldKonoAI.h" @implementation FiveFieldKonoAI -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { // for player 1, all pieces in high rows are good // for player 2, the reverse is true so we can negate the sum of row values int utility = 0; NSEnumerator *pe = [[game grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { if ([game valueAtPosition:pos]>0) { utility += [pos row]; } } return (pnum==1) ? utility : -utility; } @end gridlock.app-1.10/FiveFieldKonoGame.m0000644000175000000000000000732610342202542016465 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "FiveFieldKonoGame.h" @implementation FiveFieldKonoGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:5 columns:5]]; [self fillFirstRows:1]; [self setValue:1 atRow:1 column:0]; [self setValue:1 atRow:1 column:4]; [self setValue:2 atRow:3 column:0]; [self setValue:2 atRow:3 column:4]; [self setCurrentPlayerNumber:1]; } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; int pnum = [self currentPlayerNumber]; int maxr = [self numberOfRows]; int maxc = [self numberOfColumns]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { if ([self valueAtPosition:pos]==pnum) { int r = [pos row]; int c = [pos column]; // check diagonals if (r+10 && [self valueAtRow:r+1 column:c-1]==0) { [moves addObject:[NSArray arrayWithObjects:pos,[DCHypergridPosition positionWithRow:r+1 column:c-1],nil]]; } if (r>0 && c+10 && c>0 && [self valueAtRow:r-1 column:c-1]==0) { [moves addObject:[NSArray arrayWithObjects:pos,[DCHypergridPosition positionWithRow:r-1 column:c-1],nil]]; } } } if ([moves count]==0) [moves addObject:[NSArray array]]; return moves; } -(BOOL)prepareMoveSequence:(NSArray *)positions { [self resetFutureGrid]; if ([positions count]==2) { [[self futureGrid] setValue:0 atPosition:[positions objectAtIndex:0]]; [[self futureGrid] setValue:[self currentPlayerNumber] atPosition:[positions objectAtIndex:1]]; } return YES; } -(int)hasPlayerWon:(int)pnum { int cols = [self numberOfColumns]; // check top rows for player 1, bottom for player 2 int lastr = (pnum==1) ? [self numberOfRows]-1 : 0; int dr = (pnum==1) ? -1 : 1; int c; // must occupy all positions in last row for(c=0; c0) return [DCHypergridPosition positionWithRow:r column:c0+(d-1)*dc]; else return nil; } -(id)positionForShotFiredFromColumn:(int)c ascending:(BOOL)asc { int numr = [self numberOfRows]; int r0 = (asc) ? 0 : numr-1; int dr = (asc) ? 1 : -1; int d = 0; BOOL hit = NO; while (!hit && d0) return [DCHypergridPosition positionWithRow:r0+(d-1)*dr column:c]; else return nil; } -(NSArray *)allValidMoveSequences { NSMutableArray *moves = [NSMutableArray array]; int i; int numr=[self numberOfRows], numc=[self numberOfColumns]; for(i=0; i0) { [[self futureGrid] setValue:0 atPosition:npos]; } } // restore moving neutron, can't be moved on next turn [[self futureGrid] setValue:-2 atPosition:pos1]; // neutron that couldn't be moved this turn can on next turn (inefficient to call -positionWithValue: every time) if (previousUnmoveable) [[self futureGrid] setValue:-1 atPosition:previousUnmoveable]; return YES; } -(int)winningPlayer { int n1 = [[self grid] numberOfCellsWithValue:1]; int n2 = [[self grid] numberOfCellsWithValue:2]; if (n1>0 && n2==0) return 1; if (n2>0 && n1==0) return 2; // either both have no pieces, are tied at 1, or current player has no move return 0; } -(BOOL)isGameOver { // game over if either player has no pieces, or both have exactly 1, or current player can't move int n1 = [[self grid] numberOfCellsWithValue:1]; int n2 = [[self grid] numberOfCellsWithValue:2]; return (n1==0 || n2==0 || ![AnyDirectionUntilBlockedMoveRule gameHasAnyMoves:self fromPositionsWithValue:-1] || [self moveCount]>100); } -(NSArray *)allValidMoveSequences { return [AnyDirectionUntilBlockedMoveRule allValidMoveSequences:self fromPositionsWithValue:-1]; } -(BOOL)showScores { return YES; } @end gridlock.app-1.10/ReactorViewDelegate.m0000644000175000000000000000110710342202543017064 0ustar gurkanroot// // ReactorViewDelegate.m // Gridlock // // Created by Brian on Tue Feb 17 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "ReactorViewDelegate.h" #import "ImageStore.h" @implementation ReactorViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game { if (value<0) { NSRect centerRect = NSInsetRect(rect,rect.size.width/3,rect.size.height/3); [[NSColor redColor] set]; [[NSBezierPath bezierPathWithOvalInRect:centerRect] fill]; return YES; } return NO; } @end gridlock.app-1.10/TourneyAI.m0000644000175000000000000000306210342202543015060 0ustar gurkanroot// // TourneyAI.m // Gridlock // // Created by Brian on Fri Jan 02 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import "TourneyAI.h" #import "TourneyGame.h" @implementation TourneyAI -(id)init { self = [super init]; regWeight = 4; kingMinWeight = 6; kingMaxWeight = 10; return self; } -(int)weightForKingAtPosition:(id)pos forPlayer:(int)pnum inGame:(Game *)game { int rowsFromBack = (pnum==1) ? [game numberOfRows]-[pos row]-1 : [pos row]; double ratio = 1.0*rowsFromBack/([game numberOfRows]-2); return kingMinWeight + ratio*(kingMaxWeight-kingMinWeight); } -(int)relativeUtilityForGame:(Game *)game player:(int)pnum { TourneyGame *cgame = game; int myutility = 0; int opputility = 0; int oppnum = [cgame playerNumberMovingAfterPlayer:pnum]; int total = 0; NSEnumerator *ke; id pos; // regular pieces myutility = regWeight*[cgame numberOfRegularPiecesForPlayer:pnum]; opputility = regWeight*[cgame numberOfRegularPiecesForPlayer:oppnum]; // kings are more valuable the closer they are to the first row ke = [[game grid] enumeratorForPositionsWithValue:-1]; while (pos=[ke nextObject]) { myutility += [self weightForKingAtPosition:pos forPlayer:1 inGame:game]; } ke = [[game grid] enumeratorForPositionsWithValue:-2]; while (pos=[ke nextObject]) { opputility += [self weightForKingAtPosition:pos forPlayer:2 inGame:game]; } total = (myutility-opputility)*1000; total += (int)(1000.0*[[self class] normalizedRatioOf:myutility to:opputility maxRatio:2.0]); return total; } @end gridlock.app-1.10/TourneyGame.m0000644000175000000000000002043210342202543015440 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "TourneyGame.h" static int ROW_DELTAS[] = {+1,+2,+2,+1}; static int COL_DELTAS[] = {-2,-1,+1,+2}; @implementation TourneyGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:[[[self configurationInfo] objectForKey:@"rows"] intValue] columns:[[[self configurationInfo] objectForKey:@"cols"] intValue]]]; [self fillFirstRows:2]; } -(int)rowIncrementForCurrentPlayer { return (playerNumber==1) ? 1 : -1; } -(int)rowIncrementForPlayer:(int)pnum { return (pnum==1) ? 1 : -1; } -(int)ownerOfPosition:(DCHypergridPosition *)pos { return abs([self valueAtPosition:pos]); } -(int)ownerOfRow:(int)r column:(int) c { return abs([self valueAtRow:r column:c]); } -(BOOL)isKingAtPosition:(DCHypergridPosition *)pos { return ([self valueAtPosition:pos]<0); } -(int)numberOfRegularPiecesForPlayer:(int)pnum { return [[self grid] numberOfCellsWithValue:pnum]; } -(int)numberOfKingsForPlayer:(int)pnum { return [[self grid] numberOfCellsWithValue:-pnum]; } -(int)firstRowForPlayer:(int)pnum { return (pnum==1) ? 0 : [self numberOfRows]-1; } -(int)lastRowForPlayer:(int)pnum { return (pnum==1) ? [self numberOfRows]-1 : 0; } -(BOOL)prepareMoveSequence:(NSArray *)positions { int pnum = [self currentPlayerNumber]; id lastpos = [positions lastObject]; // destination cell gets a king if a king was moved, or if a piece is promoted at the last row BOOL newPieceIsKing = [self isKingAtPosition:[positions objectAtIndex:0]] || [lastpos row]==[self lastRowForPlayer:pnum]; [self resetFutureGrid]; // last position is new, all others are removed [[self futureGrid] setValue:0 atPositions:positions]; [[self futureGrid] setValue:(newPieceIsKing ? -pnum : pnum) atPosition:lastpos]; return YES; } -(BOOL)insertCapturesForPlayer:(int)pnum fromPosition:(id)pos isKing:(BOOL)king ignoringCapturedPositions:(NSArray *)previousJumpedPositions startingPositions:(NSArray *)partialMove intoMoveArray:(NSMutableArray *)moves { return NO; } // returns true if the destination cell is valid, and the intermediate cell in a move is empty -(BOOL)canMoveRows:(int)dr columns:(int)dc fromRow:(int)r column:(int)c { if ([self isValidRow:r+dr column:c+dc]) { // the first forward or sideways move has to be clear as well int tr = r; int tc = c; if (abs(dr)>abs(dc)) { tr += (dr>0) ? 1 : -1; } else { tc += (dc>0) ? 1 : -1; } if ([self valueAtRow:tr column:tc]==0) return YES; } return NO; } -(BOOL)insertCapturesForPlayer:(int)pnum fromPosition:(id)pos isKing:(BOOL)king partialMove:(NSArray *)partialMove intoMoveArray:(NSMutableArray *)moves { int oppnum = [self playerNumberMovingAfterPlayer:pnum]; int dir = [self rowIncrementForCurrentPlayer]; int i; BOOL checkingBackwards = NO; int r = [pos row]; int c = [pos column]; BOOL done = NO; BOOL foundJump = NO; int initialMoveCount = [moves count]; // a king will run through the loop twice, setting checkingBackwards for the second iteration do { for(i=0; i<4; i++) { int dr = (checkingBackwards) ? -dir*ROW_DELTAS[i] : dir*ROW_DELTAS[i]; int dc = COL_DELTAS[i]; if ([self canMoveRows:dr columns:dc fromRow:r column:c] && [self ownerOfRow:r+dr column:c+dc]==oppnum) { id jpos = [DCHypergridPosition positionWithRow:r+dr column:c+dc]; if (![partialMove containsObject:jpos]) { // found a jump target, continue recursively looking for more jumps if (!moves) return YES; // if moves is nil we just wanted to see if any jump exists [self insertCapturesForPlayer:pnum fromPosition:jpos isKing:king partialMove:[partialMove arrayByAddingObject:jpos] intoMoveArray:moves]; foundJump = YES; } } } if (!checkingBackwards && king) checkingBackwards = YES; else done = YES; } while (!done); if (!foundJump && [partialMove count]>=2) { [moves addObject:partialMove]; } return ([moves count]>initialMoveCount); } -(BOOL)insertNonCapturesForPlayer:(int)pnum fromPosition:(id)pos isKing:(BOOL)king intoMoveArray:(NSMutableArray *)moves { int dir = [self rowIncrementForCurrentPlayer]; int i; BOOL checkingBackwards = NO; int r = [pos row]; int c = [pos column]; BOOL done = NO; BOOL foundMove = NO; // a king will run through the loop twice, setting checkingBackwards for the second iteration do { for(i=0; i<4; i++) { int dr = (checkingBackwards) ? -dir*ROW_DELTAS[i] : dir*ROW_DELTAS[i]; int dc = COL_DELTAS[i]; if ([self canMoveRows:dr columns:dc fromRow:r column:c] && [self valueAtRow:r+dr column:c+dc]==0) { if (!moves) return YES; [moves addObject:[NSArray arrayWithObjects:pos, [DCHypergridPosition positionWithRow:r+dr column:c+dc], nil]]; foundMove = YES; } } if (!checkingBackwards && king) checkingBackwards = YES; else done = YES; } while (!done); return foundMove; } -(NSArray *)allValidMoveSequences { NSMutableArray *jumps = [NSMutableArray array]; NSMutableArray *nonjumps = [NSMutableArray array]; int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { if (pnum==[self ownerOfPosition:pos]) { BOOL king = [self isKingAtPosition:pos]; // process jumps [self insertCapturesForPlayer:pnum fromPosition:pos isKing:king partialMove:[pos arrayWithSelf_] intoMoveArray:jumps]; // process nonjumps if no jumps found if ([jumps count]==0) { [self insertNonCapturesForPlayer:pnum fromPosition:pos isKing:king intoMoveArray:nonjumps]; } } } return ([jumps count]>0) ? jumps : nonjumps; } -(int)playerWithKingAtHomeRow { int c; int numc = [self numberOfColumns]; int maxr = [self numberOfRows]-1; for(c=0; c0) return YES; else { int pnum = [self currentPlayerNumber]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; while (pos=[pe nextObject]) { if (pnum==[self ownerOfPosition:pos]) { BOOL king = [self isKingAtPosition:pos]; // process jumps if ([self insertCapturesForPlayer:pnum fromPosition:pos isKing:king partialMove:[pos arrayWithSelf_] intoMoveArray:nil]) return NO; if ([self insertNonCapturesForPlayer:pnum fromPosition:pos isKing:king intoMoveArray:nil]) { return NO; } } } return YES; } } -(int)winningPlayer { int pnum = [self playerWithKingAtHomeRow]; if (pnum!=0) return pnum; // if no moves available, next player wins return [self nextPlayerNumber]; } @end gridlock.app-1.10/WallGameViewDelegate.m0000644000175000000000000000304410342202543017160 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import "WallGameViewDelegate.h" #import #import "ImageStore.h" @implementation WallGameViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game { if (value==-1) { NSImage *wallImage = [[ImageStore defaultStore] bitmapImageWithName:@"wall.tiff" size:rect.size]; [wallImage compositeToPoint:rect.origin operation:NSCompositeSourceOver]; return YES; } return NO; } @end gridlock.app-1.10/AnyDirectionUntilBlockedMoveRule.h0000644000175000000000000000101210342202553021535 0ustar gurkanroot// // AnyDirectionUntilBlockedMoveRule.h // Gridlock // // Created by Brian on Sat Nov 22 2003. // Copyright (c) 2003 __MyCompanyName__. All rights reserved. // #import #import "Game.h" @interface AnyDirectionUntilBlockedMoveRule : NSObject { } +(NSArray *)allValidMoveSequences:(Game *)game fromPositionsWithValue:(int)sval; +(NSArray *)allValidMoveSequences:(Game *)game; +(BOOL)gameHasAnyMoves:(Game *)game fromPositionsWithValue:(int)sval; +(BOOL)gameHasAnyMoves:(Game *)game; @end gridlock.app-1.10/AtomicAI.h0000644000175000000000000000041210342202553014617 0ustar gurkanroot// // AtomicAI.h // Gridlock // // Created by Brian on Sat Feb 14 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "GenericAI.h" @interface AtomicAI : GenericAI { NSArray *utilityArray; } @end gridlock.app-1.10/AtomicGame.h0000644000175000000000000000074610342202554015212 0ustar gurkanroot// // AtomicGame.h // Gridlock // // Created by Brian on Sun Feb 08 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "Game.h" @interface AtomicGame : Game { } -(int)ownerOfPosition:(DCHypergridPosition *)pos; -(int)ownerOfRow:(int)r column:(int)c; -(int)numberOfPositionsOwnedByPlayer:(int)pnum; -(int)maxStablePiecesForPosition:(DCHypergridPosition *)pos; -(int)maxStablePiecesForRow:(int)r column:(int)c; @end gridlock.app-1.10/AtomicViewDelegate.h0000644000175000000000000000034710342202554016703 0ustar gurkanroot// // AtomicViewDelegate.h // Gridlock // // Created by Brian on Fri Feb 13 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import @interface AtomicViewDelegate : NSObject { } @end gridlock.app-1.10/BombardmentAI.h0000644000175000000000000000227210342202554015644 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface BombardmentAI : GenericAI { } @end gridlock.app-1.10/BombardmentGame.h0000644000175000000000000000230110342202554016215 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "HexapawnGame.h" @interface BombardmentGame : HexapawnGame { } @end gridlock.app-1.10/DaggerAI.h0000644000175000000000000000047010342202554014601 0ustar gurkanroot// // DaggerAI.h // Gridlock // // Created by Brian on Sun Feb 29 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "GenericAI.h" @interface DaggerAI : GenericAI { int p1DaggerWeight; int p2DaggerWeight; int crownPositionWeight; } @end gridlock.app-1.10/DaggerGame.h0000644000175000000000000000065010342202554015161 0ustar gurkanroot// // DaggerGame.h // Gridlock // // Created by Brian on Sun Feb 29 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "Game.h" @interface DaggerGame : Game { } -(int)ownerOfPosition:(DCHypergridPosition *)pos; -(BOOL)isCrownAtPosition:(DCHypergridPosition *)pos; -(int)numberOfDaggersForPlayer:(int)pnum; -(int)numberOfCrownsForPlayer:(int)pnum; @end gridlock.app-1.10/FissionAI.h0000644000175000000000000000036410342202554015024 0ustar gurkanroot// // FissionAI.h // Gridlock // // Created by Brian on Sat Nov 22 2003. // Copyright (c) 2003 __MyCompanyName__. All rights reserved. // #import #import "GenericAI.h" @interface FissionAI : GenericAI { } @end gridlock.app-1.10/FissionGame.h0000644000175000000000000000041110342202554015375 0ustar gurkanroot// // FissionGame.h // Gridlock // // Created by Brian on Sat Nov 22 2003. // Copyright (c) 2003 __MyCompanyName__. All rights reserved. // #import #import "Game.h" @interface FissionGame : Game { } -(BOOL)isSuicideVariation; @end gridlock.app-1.10/FiveFieldKonoAI.h0000644000175000000000000000227410342202554016100 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "GenericAI.h" @interface FiveFieldKonoAI : GenericAI { } @end gridlock.app-1.10/FiveFieldKonoGame.h0000644000175000000000000000226310342202554016456 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface FiveFieldKonoGame : Game { } @end gridlock.app-1.10/OrthokonGame.h0000644000175000000000000000225610342202555015600 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface OrthokonGame : Game { } @end gridlock.app-1.10/PhotonicAttackGame.h0000644000175000000000000000226410342202555016707 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface PhotonicAttackGame : Game { } @end gridlock.app-1.10/ReactorGame.h0000644000175000000000000000035510342202555015372 0ustar gurkanroot// // ReactorGame.h // Gridlock // // Created by Brian on Sun Feb 15 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "Game.h" @interface ReactorGame : Game { } @end gridlock.app-1.10/ReactorViewDelegate.h0000644000175000000000000000035110342202555017062 0ustar gurkanroot// // ReactorViewDelegate.h // Gridlock // // Created by Brian on Tue Feb 17 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import @interface ReactorViewDelegate : NSObject { } @end gridlock.app-1.10/TourneyAI.h0000644000175000000000000000045710342202556015064 0ustar gurkanroot// // TourneyAI.h // Gridlock // // Created by Brian on Fri Jan 02 2004. // Copyright (c) 2004 __MyCompanyName__. All rights reserved. // #import #import "CheckersAI.h" @interface TourneyAI : GenericAI { int regWeight; int kingMinWeight; int kingMaxWeight; } @end gridlock.app-1.10/TourneyGame.h0000644000175000000000000000255510342202556015445 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import #import "Game.h" @interface TourneyGame : Game { } -(int)ownerOfPosition:(DCHypergridPosition *)pos; -(BOOL)isKingAtPosition:(DCHypergridPosition *)pos; -(int)numberOfRegularPiecesForPlayer:(int)pnum; -(int)numberOfKingsForPlayer:(int)pnum; @end gridlock.app-1.10/WallGameViewDelegate.h0000644000175000000000000000242410342202556017160 0ustar gurkanroot/* Gridlock Copyright (c) 2002-2003 by Brian Nenninger. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #import @interface WallGameViewDelegate : NSObject { } -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game; @end gridlock.app-1.10/Resources/0000755000175000000000000000000010342221763015001 5ustar gurkanrootgridlock.app-1.10/Resources/PrefsWindow.gorm/0000755000175000000000000000000010065376623020223 5ustar gurkanrootgridlock.app-1.10/Resources/PrefsWindow.gorm/objects.gorm0000644000175000000000000001700107671524747022554 0ustar gurkanrootGNUstep archive000029cc:0000001d:000000e3:00000002:01GSNibContainer1NSObject01NSMutableDictionary1 NSDictionary&01NSString&%NSOwner0±&%PrefsWindowController0±&% Button501NSButton1 NSControl1NSView1 NSResponder% C* A€ B` AÀ  B` AÀ&01 NSMutableArray1 NSArray&%01 NSButtonCell1 NSActionCell1NSCell0 ±&%Save0 1NSFont0 ±& % Helvetica A@A@&&&&&&&&%’°0 ±&0 ±&&&&0±& % TextField01 NSTextField% BF Cs B| A`  B| A`&0± &%01NSTextFieldCell0±& % Player 1:0±0±& % Helvetica A`A`&&&&&&&&%’°01NSColor0±&%NSNamedColorSpace0±&%System0±&%textBackgroundColor0±°°0±& % textColor’0±&%Button0±% A° C‰ A A€  A A€&0± &%0± 0±&0 1NSImage0!±&%common_SwitchOff° &&&&&&&&%’°0"±&0#±&0$±0%±&%common_SwitchOn&&&0&±& %  ColorWell10'1 NSColorWell% Bá BÄ BT Að  BT Að&0(± &%0)±0*±&° &&&&&&&&0+±0,±&%NSCalibratedWhiteColorSpace ?€’0-±&%GSCustomClassMap0.±&0/±& % ColorWell00±% Bá C BT Að  BT Að&01± &%02±03±&° &&&&&&&&04±°, ?€’05±&% GormNSPopUpButton1061 NSPopUpButton% Bá CJ B² A   B² A &07± &%081NSPopUpButtonCell1NSMenuItemCell09±&%Button° &&&&&&&&0:1NSMenu0;±&0<± &0=1 NSMenuItem0>±&%Item 10?±&&&ÿ%0@±0A±& % common_Nibble’%0B±0C±&%Item 2°?&&ÿ%’%0D±0E±&%Item 3°?&&ÿ%’%%2 orderFront:v12@0:4@8°60F±&0G±&&&&°:°=%%%%%0H±& %  TextField10I±% BF C B\ A`  B\ A`&0J± &%0K±0L±& % Player 1:°&&&&&&&&%’°I0M±°0N±&%System0O±&%textBackgroundColor0P±°°N0Q±& % textColor’0R±&%Window0S1NSWindow%  Ct C¢€&% C D5@0T±%  Ct C¢€  Ct C¢€&0U± &°0V±% A° C( A˜ A€  A˜ A€&0W± &%0X± 0Y±&° ° &&&&&&&&%’°V0Z±&0[±&°$&&&°°I0\±% BF CP Bt A`  Bt A`&0]± &%0^±0_±& % Player 2:°&&&&&&&&%’°\0`±°0a±&%System0b±&%textBackgroundColor0c±°°a0d±& % textColor’0e±% BF BÖ Bh A`  Bh A`&0f± &%0g±0h±& % Player 2:°&&&&&&&&%’°e0i±°0j±&%System0k±&%textBackgroundColor0l±°°j0m±& % textColor’0n±% B4 C‰ B¦ A`  B¦ A`&0o± &%0p±0q±& % Use Images°&&&&&&&&%’°n0r±°0s±&%System0t±&%textBackgroundColor0u±°°s0v±& % textColor’0w±% B4 C* BÞ A`  BÞ A`&0x± &%0y±0z±&%Use Solid Colors°&&&&&&&&%’°w0{±°0|±&%System0}±&%textBackgroundColor0~±°°|0±& % textColor’°0°'0€±% A¨ Bx C A€  C A€&0± &%0‚± 0ƒ±&%Animate Captured Cells° ° &&&&&&&&%’°€0„±&0…±&°$&&&0†±% Ap Ap B` AÀ  B` AÀ&0‡± &%0ˆ± 0‰±&%Apply° &&&&&&&&%’°†0б&0‹±&&&&0Œ±% Bº A€ B` AÀ  B` AÀ&0± &%0ޱ 0±&%Cancel° &&&&&&&&%2 cancel:v12@0:4@8°Œ0±&0‘±&&&&°0’±% Bá Cm B² A   B² A &0“± &%0”±0•±&%Button° &&&&&&&&0–±0—±&0˜± &0™±0š±&%Item 10›±&&&ÿ%°@’%0œ±0±&%Item 2°›&&ÿ%’%0ž±0Ÿ±&%Item 3°›&&ÿ%’%%²°’0 ±&0¡±&&&&°–°™%%%%%°60¢±°0£±&%System0¤±&%windowBackgroundColor0¥±&%Window0¦±& % Preferences°¦ A Aà F@ F@%0§±0¨±&%NSApplicationIcon0©±& %  TextField2°\0ª±&% Button1°V0«±& %  TextField3°e0¬±& %  TextField4°n0­±&% Button2°€0®±&%GormNSPopUpButton°’0¯±& %  TextField5°w0°±&% Button3°†0±±&% Button4°Œ0²± &!!0³1NSNibConnector°R0´±&%NSOwner0µ±°°R0¶±°ª°R0·±°°R0¸±°H°R0¹±°©°R0º±°«°R0»±°¬°R0¼±°¯°R0½±°/°R0¾±°&°R0¿±°­°R0À±°°°R0Á±°±°R0±°°R0Ã1NSNibOutletConnector°R°´0ı&%delegate0Å1NSNibControlConnector°ª°´0Ʊ&%radioButtonSelected:0DZ°°´°Æ0ȱ°°°´0ɱ&%applyPreferences:0ʱ°±°´0˱&%cancel:0̱°°´0ͱ&%savePreferences:0α°®0ϱ°50б°´°®0ѱ&%player1ImagePopup0Ò±°´°50Ó±&%player2ImagePopup0Ô±°´°0Õ±&%imageRadioButton0Ö±°´°ª0×±&%colorRadioButton0ر°´°­0Ù±&%animateCheckbox0Ú±°´°R0Û±&%window0ܱ°´°/0ݱ&%player1ColorWell0Þ±°´°&0ß±&%player2ColorWell0à±°®0á±&%NSFirst0â±& % orderFront:0ã±°5°á°âgridlock.app-1.10/Resources/PrefsWindow.gorm/data.classes0000644000175000000000000001741007671524747022531 0ustar gurkanroot{ FirstResponder = { Actions = ( "activateContextHelpMode:", "alignCenter:", "alignJustified:", "alignLeft:", "alignRight:", "arrangeInFront:", "cancel:", "capitalizeWord:", "changeColor:", "changeFont:", "checkSpelling:", "close:", "complete:", "copy:", "copyFont:", "copyRuler:", "cut:", "delete:", "deleteBackward:", "deleteForward:", "deleteToBeginningOfLine:", "deleteToBeginningOfParagraph:", "deleteToEndOfLine:", "deleteToEndOfParagraph:", "deleteToMark:", "deleteWordBackward:", "deleteWordForward:", "deminiaturize:", "deselectAll:", "fax:", "hide:", "hideOtherApplications:", "indent:", "loosenKerning:", "lowerBaseline:", "lowercaseWord:", "makeKeyAndOrderFront:", "miniaturize:", "miniaturizeAll:", "moveBackward:", "moveBackwardAndModifySelection:", "moveDown:", "moveDownAndModifySelection:", "moveForward:", "moveForwardAndModifySelection:", "moveLeft:", "moveRight:", "moveToBeginningOfDocument:", "moveToBeginningOfLine:", "moveToBeginningOfParagraph:", "moveToEndOfDocument:", "moveToEndOfLine:", "moveToEndOfParagraph:", "moveUp:", "moveUpAndModifySelection:", "moveWordBackward:", "moveWordBackwardAndModifySelection:", "moveWordForward:", "moveWordForwardAndModifySelection:", "ok:", "open:", "orderBack:", "orderFront:", "orderFrontColorPanel:", "orderFrontDataLinkPanel:", "orderFrontHelpPanel:", "orderFrontStandardAboutPanel:", "orderFrontStandardInfoPanel:", "orderOut:", "pageDown:", "pageUp:", "paste:", "pasteAsPlainText:", "pasteAsRichText:", "pasteFont:", "pasteRuler:", "performClose:", "performMiniaturize:", "performZoom:", "print:", "raiseBaseline:", "runPageLayout:", "runToolbarCustomizationPalette:", "scrollLineDown:", "scrollLineUp:", "scrollPageDown:", "scrollPageUp:", "scrollViaScroller:", "selectAll:", "selectLine:", "selectNextKeyView:", "selectParagraph:", "selectPreviousKeyView:", "selectText:", "selectText:", "selectToMark:", "selectWord:", "showContextHelp:", "showGuessPanel:", "showHelp:", "showWindow:", "stop:", "subscript:", "superscript:", "swapWithMark:", "takeDoubleValueFrom:", "takeFloatValueFrom:", "takeIntValueFrom:", "takeObjectValueFrom:", "takeStringValueFrom:", "terminate:", "tightenKerning:", "toggle:", "toggleContinuousSpellChecking:", "toggleRuler:", "toggleToolbarShown:", "toggleTraditionalCharacterShape:", "transpose:", "transposeWords:", "turnOffKerning:", "turnOffLigatures:", "underline:", "unhide:", "unhideAllApplications:", "unscript:", "uppercaseWord:", "useAllLigatures:", "useStandardKerning:", "useStandardLigatures:", "yank:", "zoom:" ); Super = NSObject; }; IBInspector = { Actions = ( "ok:", "revert:", "touch:" ); Outlets = ( window ); Super = NSObject; }; NSApplication = { Actions = ( "arrangeInFront:", "hide:", "hideOtherApplications:", "miniaturizeAll:", "orderFrontColorPanel:", "orderFrontDataLinkPanel:", "orderFrontHelpPanel:", "orderFrontStandardAboutPanel:", "orderFrontStandardInfoPanel:", "runPageLayout:", "stop:", "terminate:", "unhide:", "unhideAllApplications:" ); Outlets = ( delegate ); Super = NSResponder; }; NSBrowser = { Actions = ( "doClick:", "doDoubleClick:" ); Outlets = ( delegate ); Super = NScontrol; }; NSButton = { Super = NSControl; }; NSColorWell = { Actions = ( "takeColorFrom:" ); Super = NSControl; }; NSControl = { Actions = ( "takeDoubleValueFrom:", "takeFloatValueFrom:", "takeIntValueFrom:", "takeObjectValueFrom:", "takeStringValueFrom:" ); Outlets = ( target ); Super = NSView; }; NSDocument = { Actions = ( "printDocument:", "revertDocumentToSaved:", "runPageLayout:", "saveDocument:", "saveDocumentAs:", "saveDocumentTo:" ); Super = NSObject; }; NSDocumentController = { Actions = ( "clearRecentDocuments:", "newDocument:", "openDocument:", "saveAllDocuments:" ); Super = NSObject; }; NSDrawer = { Actions = ( "close:", "open:", "toggle:" ); Outlets = ( delegate ); Super = NSResponder; }; NSFontManager = { Actions = ( "addFontTrait:", "modifyFont:", "modifyFontViaPanel:", "orderFrontFontPanel:", "removeFontTrait:" ); Super = NSResponder; }; NSHelpManager = { Actions = ( "activateContextHelpMode:", "showHelp:" ); Super = NSResponder; }; NSMenu = { Super = NSObject; }; NSMenuItem = { Outlets = ( target ); Super = NSObject; }; NSPanel = { Super = NSWindow; }; NSProgressIndicator = { Actions = ( "animate:", "startAnimation:", "stopAnimation:" ); Super = NSObject; }; NSResponder = { Actions = ( "deselectAll:", "selectAll:", "selectText:" ); Super = NSObject; }; NSSlider = { Super = NSControl; }; NSTabView = { Actions = ( "selectFirstTabViewItem:", "selectLastTabViewItem:", "selectNextTabViewItem:", "selectPreviousTabViewItem:", "takeSelectedTabViewItemFromSender:" ); Outlets = ( delegate ); Super = NSView; }; NSText = { Actions = ( "alignCenter:", "alignLeft:", "alignRight:", "changeFont:", "changeSpelling:", "checkSpelling:", "copy:", "copyFont:", "copyRuler:", "cut:", "delete:", "ignoreSpelling:", "paste:", "pasteFont:", "pasteRuler:", "selectAll:", "showGuessPanel:", "subscript:", "superscript:", "toggleRuler:", "underline:", "unscript:" ); Outlets = ( delegate ); Super = NSView; }; NSTextField = { Outlets = ( delegate ); Super = NSControl; }; NSTextView = { Actions = ( "alignJustified:", "changeColor:", "loosenKerning:", "lowerBaseline:", "pasteAsPlainText:", "pasteAsRichText:", "raiseBaseline:", "tightenKerning:", "toggleContinuousSpellChecking:", "toggleTraditionalCharacterShape:", "turnOffKerning:", "turnOffLigatures:", "useAllLigatures:", "useStandardKerning:", "useStandardLigatures:" ); Super = NSText; }; NSView = { Actions = ( "fax:", "print:" ); Super = NSResponder; }; NSWindow = { Actions = ( "deminiaturize:", "fax:", "makeKeyAndOrderFront:", "miniaturize:", "orderBack:", "orderFront:", "orderOut:", "performClose:", "performMiniaturize:", "performZoom:", "print:", "runToolbarCustomizationPalette:", "selectNextKeyView:", "selectPreviousKeyView:", "toggleToolbarShown:", "zoom:" ); Outlets = ( delegate ); Super = NSResponder; }; NSWindowController = { Actions = ( "showWindow:" ); Outlets = ( document ); Super = NSResponder; }; PrefsWindowController = { Actions = ( "applyPreferences:", "cancel:", "radioButtonSelected:", "savePreferences:" ); Outlets = ( animateCheckbox, colorRadioButton, imageRadioButton, player1ColorWell, player1ImagePopup, player2ColorWell, player2ImagePopup, window, newOutlet ); Super = NSObject; }; }gridlock.app-1.10/Resources/GameWindow.gorm/0000755000175000000000000000000010065400702017777 5ustar gurkanrootgridlock.app-1.10/Resources/GameWindow.gorm/objects.gorm0000644000175000000000000004406610065400702022330 0ustar gurkanrootGNUstep archive00002a96:00000029:000001e5:00000001:01GSNibContainer1NSObject01NSMutableDictionary1 NSDictionary&'01NSString& %  TextField1301 NSTextField1 NSControl1NSView1 NSResponder% A CP B@ A  B@ A&01 NSMutableArray1 NSArray&%01 NSTextFieldCell1 NSActionCell1NSCell0±&% Status:01NSFont%0 ±& %  Helvetica A`A`&&&&&&&&%’0 1NSColor0 ±&%NSNamedColorSpace0 ±&% System0 ±&% textBackgroundColor0±° ° 0±& %  textColor’0±& %  TextField140±% B| CP Cª A  Cª A&0± &%0± 0±&% (status message)°&&&&&&&&%’0±° 0±&% System0±&% textBackgroundColor0±° °0±& %  textColor’0±&% GormCustomView01 GSCustomView1 GSNibItem0±& %  BoardView A8 A0 Cà CÃ&0±& %  TextField150±% A C0 B A  B A&0± &%0 ± 0!±&% Say:°&&&&&&&&%’0"±° 0#±&% System0$±&% textBackgroundColor0%±° °#0&±& %  textColor’0'±& %  TableColumn0(1 NSTableColumn0)±&% column1 BÜ A  GÃP0*1NSTableHeaderCell0+±&% Player 10,±%0-±&% Helvetica-Bold A@A@&&&&&&&&%’0.±° 0/±&% System00±&% controlShadowColor01±° 02±&% System03±&% windowFrameTextColor04± 05±&% neuf06±%07±& %  Helvetica A@A@°5&&&&&&&&%’08±° °209±&% textBackgroundColor0:±° °20;±& %  textColor0<±& %  TextField160=±% B@ C0 CÝ A¨  CÝ A¨&0>± &%0?± 0@±&°6&&&&&&&&%’0A±° 0B±&% System0C±&% textBackgroundColor0D±° °B0E±& %  textColor’0F±&% Button0G1NSButton% CÏ€ C„€ B` AÀ  B` AÀ& 0H± &%0I1 NSButtonCell0J±&% Pass°6&&&&&&&&%’0K±&0L±&&&&0M±& %  TextField0N±% A CÈ€ Cà A   Cà A & 0O± &%0P± 0Q±&% Status°&&&&&&&&%’0R±° 0S±&% System0T±&% textBackgroundColor0U±° °S0V±& %  textColor’0W±&% GSCustomClassMap0X±&0Y±& %  GormNSWindow0Z1NSWindow%  Ct C&% CÞ C¡0[±%  Ct C  Ct C&0\± &0]1NSBox% A A˜ C] Bæ  C] Bæ&0^± &0_±% @âhý @à CNÙp B®  CNÙp B®&0`± &0a±% A Bl C A  C A&0b± &%0c± 0d±&% Positions Evaluated°&&&&&&&&%’0e±° 0f±&% System0g±&% textBackgroundColor0h±° °f0i±& %  textColor’0j±% A B C A  C A&0k± &%0l± 0m±&% Time To Compute°&&&&&&&&%’0n±° 0o±&% System0p±&% textBackgroundColor0q±° °o0r±& %  textColor’0s±% A AP C A  C A&0t± &%0u± 0v±&% Positions/second°&&&&&&&&%’0w±° 0x±&% System0y±&% textBackgroundColor0z±° °x0{±& %  textColor’0|±% C Bl B\ A  B\ A&0}± &%0~± 0±&% 0°&&&&&&&&%’0€±° 0±&% System0‚±&% textBackgroundColor0ƒ±° °0„±& %  textColor’0…±% C B B\ A  B\ A&0†± &%0‡± 0ˆ±&% 0°&&&&&&&&%’0‰±° 0б&% System0‹±&% textBackgroundColor0Œ±° °Š0±& %  textColor’0ޱ% C AP B\ A  B\ A&0± &%0± 0‘±&% 0°&&&&&&&&%’0’±° 0“±&% System0”±&% textBackgroundColor0•±° °“0–±& %  textColor’0—± 0˜±& %  AI Statistics°6&&&&&&&&%’0™±° 0š±&% System0›±&% windowBackgroundColor0œ±° 0±&% System0ž±& %  textColor @¢hý @ %%°™0Ÿ±&% Window0 ±& %  Statistics°  ?€ B F@ F@%0¡1NSImage0¢±&%NSApplicationIcon0£±&% GormCustomView10¤±0¥±&% PlayerTurnIndicatorView CÞ@ C% B@ B@&!0¦±& %  GormNSWindow10§±%  Cú€ Cl&% C DÀ0¨±%  Cú€ Cl  Cú€ Cl&0©± &0ª±% CÎ CJ Bž AÀ  Bž AÀ&0«± &%0¬±0­±& %  Disconnect°6&&&&&&&&%’0®±&0¯±&&&&°°°°=0°1 NSScrollView% A A  Cð C!  Cð C!&0±± &0²1 NSClipView% A˜  Cæ€ C! A˜  Cæ€ C!&0³± &0´1 NSTextView1NSText% A˜  Cæ€ C!  Cæ€ C!&0µ± &0¶±° 0·±&% System0¸±&% textBackgroundColor  K–€ K–€0¹±° °·0º±& %  textColor Cæ€ K–€°¶0»1 NSScroller%  A C!  A C!&0¼± &%0½±0¾±&°6&&&&&&&&&°°2 _doScroll:v12@0:4@8°²% A A A A °»0¿±° 0À±&% System0Á±&% windowBackgroundColor0±&% Window0ñ&% Network°Ã ?€ B F@ F@%°¡0ı&% GormCustomView20ű0Ʊ&% PlayerTurnIndicatorView CÞ@ BX B@ B@&!0DZ& %  ScrollView°°0ȱ& %  NSVisible0ɱ &0ʱ%  D@ CÓ€&% B® D8€0˱%  D@ CÓ€  D@ CÓ€&0̱ &°°N0ͱ% CÎ@ C¿€ B¦ A`  B¦ A`& 0α &%0ϱ 0б&% Game°&&&&&&&&%’0ѱ° 0Ò±&% System0Ó±&% textBackgroundColor0Ô±° °Ò0Õ±& %  textColor’0Ö±% CÏ@ C£ B¬ A  B¬ A& 0×± &%0ر 0Ù±& %  Configuration°&&&&&&&&%’0Ú±° 0Û±&% System0ܱ&% textBackgroundColor0ݱ° °Û0Þ±& %  textColor’°G0ß±% Cð C„€ B` AÀ  B` AÀ& 0à± &%0á±0â±&% Restart°6&&&&&&&&%’0ã±&0ä±&&&&0å±% CÏ@ C BX A`  BX A`&!0æ± &%0ç± 0è±&% Player 1°&&&&&&&&%’0é±° 0ê±&% System0ë±&% textBackgroundColor0ì±° °ê0í±& %  textColor’0î±% CëÀ C Að A`  Að A`&!0ï± &%0ð± 0ñ±&% 999°&&&&&&&&%’0ò±° 0ó±&% System0ô±&% textBackgroundColor0õ±° °ó0ö±& %  textColor’0÷±% CÏ@ B  Bd A`  Bd A`&!0ø± &%0ù± 0ú±&% Player 2°&&&&&&&&%’0û±° 0ü±&% System0ý±&% textBackgroundColor0þ±° °ü0ÿ±& %  textColor’P±% CëÀ B  Aø A`  Aø A`&!P± &%P± P±&% 999°&&&&&&&&%’P±° P±&% SystemP±&% textBackgroundColorP±° ÐP±& %  textColor’°¤P 1 NSPopUpButton% CÏÀ C³ Bç A   Bç A & P ± &%P 1 NSPopUpButtonCell1!NSMenuItemCellP ±&% Button°6&&&&&&&&P 1"NSMenuP±&P± &P1# NSMenuItemP±&% Item 1P±&&&ÿ%P±P±& % common_Nibble’%P±#P±&% Item 2Ð&&ÿ%’%P±#P±&% Item 3Ð&&ÿ%’%%’P±&P±&&&&Ð Ð%%%%%P±% CÐ@ C–€ Bå A   Bå A & P± &%P± P±&% Button°6&&&&&&&&P±"P ±&P!± &P"±#P#±&% Item 1P$±&&&ÿ%Ð’%P%±#P&±&% Item 2Ð$&&ÿ%’%P'±#P(±&% Item 3Ð$&&ÿ%’%%’P)±&P*±&&&&ÐÐ"%%%%%P+±% CÎ@ Bò Bä A   Bä A &!P,± &%P-± P.±&% Button°6&&&&&&&&P/±"P0±&P1± &P2±#P3±&% Item 1P4±&&&ÿ%Ð’%P5±#P6±&% Item 2Ð4&&ÿ%’%P7±#P8±&% Item 3Ð4&&ÿ%’%%’P9±&P:±&&&&Ð/Ð2%%%%%P;±% CÏ@ A  Bì A   Bì A &!P<± &%P=± P>±&% Button°6&&&&&&&&P?±"P@±&PA± &PB±#PC±&% Item 1PD±&&&ÿ%Ð’%PE±#PF±&% Item 2ÐD&&ÿ%’%PG±#PH±&% Item 3ÐD&&ÿ%’%%’PI±&PJ±&&&&Ð?ÐB%%%%%°ÅPK±° PL±&% SystemPM±&% windowBackgroundColorPN±&% WindowPO±&% WindowPP±&%Window A Aà F@ F@%°¡PQ±&% Box°]PR±& %  TextField1°ÍPS±& %  TextField2°ÖPT±&% GormNSTableViewPU1$ NSTableView%  Cq C!  Cq C!&PV± &%PW±PX±&°6&&&&&&&&PY± &°(PZ±P[±&% column2 C A  GÃPP\±P]±&% Player 2°,&&&&&&&&%’°.°1P^± P_±&% nine°6Ð_&&&&&&&&%’°8°:P`±° °2Pa±& %  gridColorPb±° °/Pc±&% controlBackgroundColorPd1%NSTableHeaderView%  Cq A°  Cq A°&Pe± &Pf1&GSTableCornerView%  A˜ A°  A˜ A°&Pg± &%% A€’ @ @@Ph±& %  TextField3°åPi±& %  TextField4°îPj±& %  TextField5°÷Pk±& %  TextField6ÐPl±&%NSOwnerPm±&% GameControllerPn±& %  TextField7°aPo±&% GormNSPopUpButton1ÐPp±& %  TableColumn1ÐZPq±& %  TextField8°jPr±&% GormNSPopUpButton2Ð+Ps±& %  TextField9°sPt±&% Window°ÊPu±&% GormNSPopUpButton3Ð;Pv±&% Button1°ßPw±& %  TextField10°|Px±&% Button2°ªPy±&% TextView°´Pz±& %  TextField11°…P{±&% GormNSPopUpButtonÐ P|±& %  TextField12°ŽP}± &FFP~1'NSNibConnectorÐtP±&%NSOwnerP€±'°ÐtP±'°MÐtP‚±'ÐRÐtPƒ±'ÐSÐtP„±'°FÐtP…±'ÐvÐtP†±'ÐhÐtP‡±'ÐiÐtPˆ±'ÐjÐtP‰±'ÐkÐtPŠ1(NSNibOutletConnectorÐÐtP‹±&% windowPŒ±(аMP±& %  statusFieldPޱ(аP±& %  boardViewP±(ÐÐSP‘±&% configurationLabelP’±(ÐÐiP“±&% player1ScoreFieldP”±(ÐÐkP•±&% player2ScoreFieldP–±(ÐtÐP—±&% delegateP˜±(°ÐP™±& %  eventTargetPš1)NSNibControlConnector°FÐP›±&% passButtonClicked:Pœ±(ÐÐhP±&% player1LabelFieldPž±(ÐÐjPŸ±&% player2LabelFieldP ±'°£ÐtP¡±(а£P¢±&% player1TurnViewP£±(аFP¤±& %  passButtonP¥±'Ð{P¦±'ÐoP§±'ÐrP¨±'ÐuP©±(ÐÐuPª±&% player2TypePopupP«±(ÐÐrP¬±&% player1TypePopupP­±(ÐÐoP®±&% configurationPopupP¯±(ÐÐ{P°±& %  gamePopupP±±)Ð{ÐP²±&% gameSelectedFromPopup:P³±)ÐoÐP´±&% configurationSelectedFromPopup:Pµ±)ÐrÐP¶±&% playerTypeUpdated:P·±)ÐuÐжP¸±'°ÄP¹±(аÄPº±&% player2TurnViewP»±)ÐvÐP¼±& %  restartGame:P½±'°YÐP¾±(аYP¿±&% statisticsWindowPÀ±'ÐTPÁ±'°'P±'ÐpPñ'ÐQPı'ÐnPű'ÐqPƱ'ÐsPDZ'ÐwPȱ'ÐzPɱ'Ð|Pʱ(ÐÐzP˱& %  aiTimeFieldP̱(ÐÐ|Pͱ&% aiMovesPerSecondFieldPα'°¦ÐPϱ'ÐxPб'°Pѱ'°PÒ±'°PÓ±'°±&&&ÿ%°° ²%0?±°=0@± &0A±0B±&%Arrange In Front0C±&&&ÿ%°° 2 arrangeInFront:v12@0:4@8%0D±0E±&%Miniaturize Window0F±&%m&&ÿ%°° 2 performMiniaturize:v12@0:4@8%0G±0H±&%Show Statistics Window0I±&&&ÿ%°° ’%0J±0K±&%Show Network/Chat Window0L±&&&ÿ%°° ’%°0M±0N±&%Hide0O±&%h&&ÿ%°° 2 hide:v12@0:4@8%°0P±& %  MenuItem3°0Q±&%MenuItem°M0R±& %  MenuItem4°0S±& %  MenuItem5°0T±& %  MenuItem20°<0U±& %  MenuItem6°0V±& %  MenuItem10°10W±& %  MenuItem7°10X±& %  MenuItem21°A0Y±& %  MenuItem11°M0Z±& %  MenuItem8°60[±& %  MenuItem22°D0\±& %  MenuItem12°10]±& %  MenuItem9°90^±& %  MenuItem23°G0_±& %  MenuItem13°M0`±& %  MenuItem24°J0a±& %  MenuItem25°+0b±& % GormNSMenu°40c±& %  MenuItem14°10d±&%GSCustomClassMap0e±&0f±& %  MenuItem26°.0g±& %  MenuItem15°M0h±& %  MenuItem16°0i±& % NSVisible0j± &0k±& %  MenuItem17°%0l±& %  GormNSMenu1°0m±& %  GormNSMenu2°?0n±& %  MenuItem18°"0o±& %  MenuItem19°(0p±& % AppController0q1 GSNibItem°p  &0r±&%NSMenu°0s±&%Menu°0t± &''0u1 NSNibConnector°r0v±&%NSOwner0w± °g°r0x± °U°r0y± °S°r0z± °s°S0{± °P°s0|± °R°s0}± °p°v0~1 NSNibOutletConnector°v°p0±&%delegate0€1NSNibControlConnector°R°p0±&% showPreferences:0‚±°P°v0ƒ±&%orderFrontStandardAboutPanel:0„± °c°r0…± °b°c0†± °Z°b0‡± °]°b0ˆ±°Z0‰±&%NSFirst0б& %  undoMove:0‹±°]°‰0Œ±& %  redoMove:0± °h°r0ޱ °l°h0± °n°l0± °k°l0‘± °o°l0’±°n°‰0“±& %  restartGame:0”±°k°‰0•±& %  openDocument:0–±°o°‰0—±& %  saveDocument:0˜± °T°r0™± °m°T0š± °X°m0›± °[°m0œ± °^°m0±°[°‰0ž±&%performMiniaturize:0Ÿ±°X°‰0 ±&%arrangeInFront:0¡±°^°‰0¢±&%showStatisticsDrawer:0£± °`°m0¤±°`°‰0¥±&%showNetworkDrawer:0¦± °a°l0§± °f°l0¨±°a°‰0©±& % joinGame:0ª±°f°‰0«±& % hostGame:gridlock.app-1.10/Resources/Gridlock.gorm/data.classes0000644000175000000000000001727507671521130022010 0ustar gurkanroot{ AppController = { Actions = ( "showPreferences:" ); Outlets = ( ); Super = NSObject; }; FirstResponder = { Actions = ( "activateContextHelpMode:", "alignCenter:", "alignJustified:", "alignLeft:", "alignRight:", "arrangeInFront:", "cancel:", "capitalizeWord:", "changeColor:", "changeFont:", "checkSpelling:", "close:", "complete:", "copy:", "copyFont:", "copyRuler:", "cut:", "delete:", "deleteBackward:", "deleteForward:", "deleteToBeginningOfLine:", "deleteToBeginningOfParagraph:", "deleteToEndOfLine:", "deleteToEndOfParagraph:", "deleteToMark:", "deleteWordBackward:", "deleteWordForward:", "deminiaturize:", "deselectAll:", "fax:", "hide:", "hideOtherApplications:", "indent:", "loosenKerning:", "lowerBaseline:", "lowercaseWord:", "makeKeyAndOrderFront:", "miniaturize:", "miniaturizeAll:", "moveBackward:", "moveBackwardAndModifySelection:", "moveDown:", "moveDownAndModifySelection:", "moveForward:", "moveForwardAndModifySelection:", "moveLeft:", "moveRight:", "moveToBeginningOfDocument:", "moveToBeginningOfLine:", "moveToBeginningOfParagraph:", "moveToEndOfDocument:", "moveToEndOfLine:", "moveToEndOfParagraph:", "moveUp:", "moveUpAndModifySelection:", "moveWordBackward:", "moveWordBackwardAndModifySelection:", "moveWordForward:", "moveWordForwardAndModifySelection:", "ok:", "open:", "orderBack:", "orderFront:", "orderFrontColorPanel:", "orderFrontDataLinkPanel:", "orderFrontHelpPanel:", "orderFrontStandardAboutPanel:", "orderFrontStandardInfoPanel:", "orderOut:", "pageDown:", "pageUp:", "paste:", "pasteAsPlainText:", "pasteAsRichText:", "pasteFont:", "pasteRuler:", "performClose:", "performMiniaturize:", "performZoom:", "print:", "raiseBaseline:", "runPageLayout:", "runToolbarCustomizationPalette:", "scrollLineDown:", "scrollLineUp:", "scrollPageDown:", "scrollPageUp:", "scrollViaScroller:", "selectAll:", "selectLine:", "selectNextKeyView:", "selectParagraph:", "selectPreviousKeyView:", "selectText:", "selectText:", "selectToMark:", "selectWord:", "showContextHelp:", "showGuessPanel:", "showHelp:", "showWindow:", "stop:", "subscript:", "superscript:", "swapWithMark:", "takeDoubleValueFrom:", "takeFloatValueFrom:", "takeIntValueFrom:", "takeObjectValueFrom:", "takeStringValueFrom:", "terminate:", "tightenKerning:", "toggle:", "toggleContinuousSpellChecking:", "toggleRuler:", "toggleToolbarShown:", "toggleTraditionalCharacterShape:", "transpose:", "transposeWords:", "turnOffKerning:", "turnOffLigatures:", "underline:", "unhide:", "unhideAllApplications:", "unscript:", "uppercaseWord:", "useAllLigatures:", "useStandardKerning:", "useStandardLigatures:", "yank:", "zoom:", "undoMove:", "redoMove:", "restartGame:", "joinGame:", "hostGame:", "saveDocument:", "openDocument:", "showNetworkDrawer:", "showStatisticsDrawer:" ); Super = NSObject; }; IBInspector = { Actions = ( "ok:", "revert:", "touch:" ); Outlets = ( window ); Super = NSObject; }; NSApplication = { Actions = ( "arrangeInFront:", "hide:", "hideOtherApplications:", "miniaturizeAll:", "orderFrontColorPanel:", "orderFrontDataLinkPanel:", "orderFrontHelpPanel:", "orderFrontStandardAboutPanel:", "orderFrontStandardInfoPanel:", "runPageLayout:", "stop:", "terminate:", "unhide:", "unhideAllApplications:" ); Outlets = ( delegate ); Super = NSResponder; }; NSBrowser = { Actions = ( "doClick:", "doDoubleClick:" ); Outlets = ( delegate ); Super = NScontrol; }; NSButton = { Super = NSControl; }; NSColorWell = { Actions = ( "takeColorFrom:" ); Super = NSControl; }; NSControl = { Actions = ( "takeDoubleValueFrom:", "takeFloatValueFrom:", "takeIntValueFrom:", "takeObjectValueFrom:", "takeStringValueFrom:" ); Outlets = ( target ); Super = NSView; }; NSDocument = { Actions = ( "printDocument:", "revertDocumentToSaved:", "runPageLayout:", "saveDocument:", "saveDocumentAs:", "saveDocumentTo:" ); Super = NSObject; }; NSDocumentController = { Actions = ( "clearRecentDocuments:", "newDocument:", "openDocument:", "saveAllDocuments:" ); Super = NSObject; }; NSDrawer = { Actions = ( "close:", "open:", "toggle:" ); Outlets = ( delegate ); Super = NSResponder; }; NSFontManager = { Actions = ( "addFontTrait:", "modifyFont:", "modifyFontViaPanel:", "orderFrontFontPanel:", "removeFontTrait:" ); Super = NSResponder; }; NSHelpManager = { Actions = ( "activateContextHelpMode:", "showHelp:" ); Super = NSResponder; }; NSMenu = { Super = NSObject; }; NSMenuItem = { Outlets = ( target ); Super = NSObject; }; NSPanel = { Super = NSWindow; }; NSProgressIndicator = { Actions = ( "animate:", "startAnimation:", "stopAnimation:" ); Super = NSObject; }; NSResponder = { Actions = ( "deselectAll:", "selectAll:", "selectText:" ); Super = NSObject; }; NSSlider = { Super = NSControl; }; NSTabView = { Actions = ( "selectFirstTabViewItem:", "selectLastTabViewItem:", "selectNextTabViewItem:", "selectPreviousTabViewItem:", "takeSelectedTabViewItemFromSender:" ); Outlets = ( delegate ); Super = NSView; }; NSText = { Actions = ( "alignCenter:", "alignLeft:", "alignRight:", "changeFont:", "changeSpelling:", "checkSpelling:", "copy:", "copyFont:", "copyRuler:", "cut:", "delete:", "ignoreSpelling:", "paste:", "pasteFont:", "pasteRuler:", "selectAll:", "showGuessPanel:", "subscript:", "superscript:", "toggleRuler:", "underline:", "unscript:" ); Outlets = ( delegate ); Super = NSView; }; NSTextField = { Outlets = ( delegate ); Super = NSControl; }; NSTextView = { Actions = ( "alignJustified:", "changeColor:", "loosenKerning:", "lowerBaseline:", "pasteAsPlainText:", "pasteAsRichText:", "raiseBaseline:", "tightenKerning:", "toggleContinuousSpellChecking:", "toggleTraditionalCharacterShape:", "turnOffKerning:", "turnOffLigatures:", "useAllLigatures:", "useStandardKerning:", "useStandardLigatures:" ); Super = NSText; }; NSView = { Actions = ( "fax:", "print:" ); Super = NSResponder; }; NSWindow = { Actions = ( "deminiaturize:", "fax:", "makeKeyAndOrderFront:", "miniaturize:", "orderBack:", "orderFront:", "orderOut:", "performClose:", "performMiniaturize:", "performZoom:", "print:", "runToolbarCustomizationPalette:", "selectNextKeyView:", "selectPreviousKeyView:", "toggleToolbarShown:", "zoom:" ); Outlets = ( delegate ); Super = NSResponder; }; NSWindowController = { Actions = ( "showWindow:" ); Outlets = ( document ); Super = NSResponder; }; }gridlock.app-1.10/Resources/ServerWindow.gorm/0000755000175000000000000000000010065376623020412 5ustar gurkanrootgridlock.app-1.10/Resources/ServerWindow.gorm/objects.gorm0000644000175000000000000001727107671524777022757 0ustar gurkanrootGNUstep archive000029cc:0000001d:000000e9:00000001:01GSNibContainer1NSObject01NSMutableDictionary1 NSDictionary&01NSString&%NSOwner0±&%ServerController0±& %  TextField701 NSTextField1 NSControl1NSView1 NSResponder% B’ @à B² A¨  B² A¨&01 NSMutableArray1 NSArray&%01 NSTextFieldCell1 NSActionCell1NSCell0 ±&0 1NSFont0 ±& % Helvetica A@A@&&&&&&&&%’°0 1NSColor0 ±&%NSNamedColorSpace0±&%System0±&%textBackgroundColor0±° °0±& % textColor’0±& %  TextField80±% A A¨ C A  C A&0± &%0± 0±&%Connection status0±0±& % Helvetica A`A`&&&&&&&&%’°0±° 0±&%System0±&%textBackgroundColor0±° °0±& % textColor’0±& %  MenuItem101 NSMenuItem0 ±&%Item 20!±&&&ÿ%’%0"±& % TextField0#±% B¨ Bˆ A  Bˆ A&0$± &%0%± 0&±&%Game°&&&&&&&&%’°#0'±° 0(±&%System0)±&%textBackgroundColor0*±° °(0+±& % textColor’0,±& %  TextField90-±% C§ À B` A  B` A&0.± &%0/± 00±&%Sizer°&&&&&&&&%’°-01±° 02±&%System03±&%textBackgroundColor04±° °205±& % textColor’06±& %  MenuItem207±08±&%Item 3°!&&ÿ%’%09±&%Button0:1NSButton% C§ A¨ B` AÀ  B` AÀ&0;± &%0<1 NSButtonCell0=±&%Host° &&&&&&&&%’°:0>±&0?±&&&&0@±&%MenuItem0A±0B±& % Breakthrough°!&&ÿ%0C1NSImage0D±& % common_Nibble’%0E±& % GormNSWindow0F1NSWindow%  CÇ€ C>&% Co DÀ0G±%  CÇ€ C>  CÇ€ C>&0H± &0I1NSBox% A BH C¾ C   C¾ C &0J± &0K±% @Þff @à C· Í Bà  C· Í Bà&0L± &  °#0M±% B@ Bˆ A  Bˆ A&0N± &%0O± 0P±& % Variation°&&&&&&&&%’°M0Q±° 0R±&%System0S±&%textBackgroundColor0T±° °R0U±& % textColor’0V±% CP B¢ Bd A  Bd A&0W± &%0X± 0Y±&%Port°&&&&&&&&%’°V0Z±° 0[±&%System0\±&%textBackgroundColor0]±° °[0^±& % textColor’0_±% CG B@ B„ A  B„ A&0`± &%0a± 0b±&%Password°&&&&&&&&%’°_0c±° 0d±&%System0e±&%textBackgroundColor0f±° °d0g±& % textColor’0h±% A° @à B8 A  B8 A&0i± &%0j± 0k±&%Name:°&&&&&&&&%’°h0l±° 0m±&%System0n±&%textBackgroundColor0o±° °m0p±& % textColor’0q±% C‡ B¢ B` A¨  B` A¨&0r± &%0s± 0t±&%27500° &&&&&&&&%’°q0u±° 0v±&%System0w±&%textBackgroundColor0x±° °v0y±& % textColor’0z±% C‡ B8 B° A¨  B° A¨&0{± &%0|± 0}±&° &&&&&&&&%’°z0~±° 0±&%System0€±&%textBackgroundColor0±° °0‚±& % textColor’0ƒ1 NSPopUpButton% B’ B¤ BÎ A   BÎ A &0„± &%0…1NSPopUpButtonCell1NSMenuItemCell0†±&%Button° &&&&&&&&0‡1NSMenu0ˆ±&0‰± &°A°°7%’°ƒ0б&0‹±&&&&°‡°A%%%%%0Œ±% B’ B8 BÎ A   BÎ A &0± &%0ޱ0±&%Button° &&&&&&&&0±0‘±&0’± &0“±0”±&%Item 10•±&&&ÿ%°C’%0–±0—±&%Item 2°•&&ÿ%’%0˜±0™±&%Item 3°•&&ÿ%’%%2 orderFront:v12@0:4@8°Œ0š±&0›±&&&&°°“%%%%%°0œ± 0±&%Host Network Game° &&&&&&&&%’°I0ž±° 0Ÿ±&%System0 ±&%windowBackgroundColor0¡±° 0¢±&%System0£±& % textColor @žff @ %%°:0¤±% Cˆ€ A¨ B` AÀ  B` AÀ&0¥± &%0¦±0§±&%Stop° &&&&&&&&%’°¤0¨±&0©±&&&&°°-°ž0ª±&%Window0«±&%Host Network Game°« ?€ B F@ F@%0¬±0­±&%NSApplicationIcon0®±&%GSCustomClassMap0¯±&0°±&%Box°I0±±&% GormNSPopUpButton1°Œ0²±& %  TextField1°M0³±& %  TextField2°V0´±&% Button1°¤0µ±& %  TextField3°_0¶±& %  TextField4°h0·±&%GormNSPopUpButton°ƒ0¸±& %  TextField5°q0¹±& %  TextField6°z0º± &  0»1NSNibConnector°E0¼±&%NSOwner0½±°°0¾±°"0¿±°²0À±°³0Á±°µ0±°¶0ñ°¸0ı°¹0ű°·0Ʊ°±0DZ°0ȱ°90ɱ°´0ʱ°0˱°@0̱°0ͱ°60α°,0Ï1NSNibOutletConnector°¼°0б& % usernameField0ѱ°¼°E0Ò±&%window0Ó±°¼°·0Ô±& % gamePopup0Õ±°¼°±0Ö±&%variationPopup0×±°¼°¸0ر& % portField0Ù±°¼°¹0Ú±& % passwordField0Û±°¼°,0ܱ&%windowSizerField0ݱ°¼°0Þ±&%connectionStatusField0ß1NSNibControlConnector°·°¼0à±&% gameSelectedFromPopup:0á±°°¼0â±&% updateUsername:0ã±°9°¼0ä±& %  beginHosting:0å±°´°¼0æ±& %  abortHosting:0ç±°±0è±&%NSFirst0é±& % orderFront:gridlock.app-1.10/Resources/ServerWindow.gorm/data.classes0000644000175000000000000000730707671524777022727 0ustar gurkanroot{ FirstResponder = { Actions = ( "activateContextHelpMode:", "alignCenter:", "alignJustified:", "alignLeft:", "alignRight:", "arrangeInFront:", "cancel:", "capitalizeWord:", "changeColor:", "changeFont:", "checkSpelling:", "close:", "complete:", "copy:", "copyFont:", "copyRuler:", "cut:", "delete:", "deleteBackward:", "deleteForward:", "deleteToBeginningOfLine:", "deleteToBeginningOfParagraph:", "deleteToEndOfLine:", "deleteToEndOfParagraph:", "deleteToMark:", "deleteWordBackward:", "deleteWordForward:", "deminiaturize:", "deselectAll:", "fax:", "hide:", "hideOtherApplications:", "indent:", "loosenKerning:", "lowerBaseline:", "lowercaseWord:", "makeKeyAndOrderFront:", "miniaturize:", "miniaturizeAll:", "moveBackward:", "moveBackwardAndModifySelection:", "moveDown:", "moveDownAndModifySelection:", "moveForward:", "moveForwardAndModifySelection:", "moveLeft:", "moveRight:", "moveToBeginningOfDocument:", "moveToBeginningOfLine:", "moveToBeginningOfParagraph:", "moveToEndOfDocument:", "moveToEndOfLine:", "moveToEndOfParagraph:", "moveUp:", "moveUpAndModifySelection:", "moveWordBackward:", "moveWordBackwardAndModifySelection:", "moveWordForward:", "moveWordForwardAndModifySelection:", "newDocument:", "ok:", "openDocument:", "orderBack:", "orderFront:", "orderFrontColorPanel:", "orderFrontDataLinkPanel:", "orderFrontFontPanel:", "orderFrontHelpPanel:", "orderFrontStandardAboutPanel:", "orderFrontStandardInfoPanel:", "orderOut:", "pageDown:", "pageUp:", "paste:", "pasteAsPlainText:", "pasteAsRichText:", "pasteFont:", "pasteRuler:", "performClose:", "performMiniaturize:", "performZoom:", "print:", "raiseBaseline:", "revertDocumentToSaved:", "runPageLayout:", "runToolbarCustomizationPalette:", "saveAllDocuments:", "saveDocument:", "saveDocumentAs:", "saveDocumentTo:", "scrollLineDown:", "scrollLineUp:", "scrollPageDown:", "scrollPageUp:", "scrollViaScroller:", "selectAll:", "selectLine:", "selectNextKeyView:", "selectParagraph:", "selectPreviousKeyView:", "selectText:", "selectText:", "selectToMark:", "selectWord:", "showContextHelp:", "showGuessPanel:", "showHelp:", "showWindow:", "stop:", "subscript:", "superscript:", "swapWithMark:", "takeDoubleValueFrom:", "takeFloatValueFrom:", "takeIntValueFrom:", "takeObjectValueFrom:", "takeStringValueFrom:", "terminate:", "tightenKerning:", "toggle:", "toggleContinuousSpellChecking:", "toggleRuler:", "toggleToolbarShown:", "toggleTraditionalCharacterShape:", "transpose:", "transposeWords:", "turnOffKerning:", "turnOffLigatures:", "underline:", "unhide:", "unhideAllApplications:", "unscript:", "uppercaseWord:", "useAllLigatures:", "useStandardKerning:", "useStandardLigatures:", "yank:", "zoom:" ); Super = NSObject; }; ServerController = { Actions = ( "abortHosting:", "beginHosting:", "gameSelectedFromPopup:", "startGame:", "updateUsername:" ); Outlets = ( clientStatusField, connectionStatusField, gamePopup, passwordField, portField, usernameField, variationPopup, window, windowSizerField ); Super = NSObject; }; }gridlock.app-1.10/Resources/ClientWindow.gorm/0000755000175000000000000000000010065376623020362 5ustar gurkanrootgridlock.app-1.10/Resources/ClientWindow.gorm/objects.gorm0000644000175000000000000001774007671533205022712 0ustar gurkanrootGNUstep archive000029cc:0000001d:000000f4:00000000:01GSNibContainer1NSObject01NSMutableDictionary1 NSDictionary&01NSString&%NSOwner0±&%ClientController0±& %  TextField701 NSTextField1 NSControl1NSView1 NSResponder% CR @à BŒ A˜  BŒ A˜&01 NSMutableArray1 NSArray&%01 NSTextFieldCell1 NSActionCell1NSCell0 ±& % Password:0 1NSFont0 ±& % Helvetica A`A`&&&&&&&&%’°0 1NSColor0 ±&%NSNamedColorSpace0±&%System0±&%textBackgroundColor0±° °0±& % textColor’0±& %  TextField80±% CŒ @à Bö A¨  Bö A¨&0± &%0± 0±&0±0±& % Helvetica A@A@&&&&&&&&%’°0±° 0±&%System0±&%textBackgroundColor0±° °0±& % textColor’0±& % TextField0±% Aà B¤ Bx A  Bx A&0 ± &%0!± 0"±&%Address:° &&&&&&&&%’°0#±° 0$±&%System0%±&%textBackgroundColor0&±° °$0'±& % textColor’0(±& %  TextField90)±% A0 A€ C‡€ A  C‡€ A&0*± &%0+± 0,±&%Connection status message° &&&&&&&&%’°)0-±° 0.±&%System0/±&%textBackgroundColor00±° °.01±& % textColor’02±&%Button031NSButton% @  BD A A€  A A€&04± &%051 NSButtonCell06±&071NSImage08±&%common_SwitchOff°&&&&&&&&%’°309±&0:±&0;±0<±&%common_SwitchOn&&&0=±& % GormNSWindow0>1NSWindow%  CÚ€ CA&% C D$À0?±%  CÚ€ CA  CÚ€ CA&0@± &0A1NSBox% A BH CЀ C  CЀ C&0B± &0C±% @à @à CÉ€ BÒ  CÉ€ BÒ&0D± &  °30E±% @  B¨ A A€  A A€&0F± &%0G±0H±&°7°&&&&&&&&%’°E0I±&0J±&°;&&&°0K±% B¾ B¤ CK A¨  CK A¨&0L± &%0M± 0N±&°&&&&&&&&%’°K0O±° 0P±&%System0Q±&%textBackgroundColor0R±° °P0S±& % textColor’0T±% Aà BD C A  C A&0U± &%0V± 0W±&%Rendezvous Server:° &&&&&&&&%’°T0X±° 0Y±&%System0Z±&%textBackgroundColor0[±° °Y0\±& % textColor’0]±% C›€ B¤ Aø A  Aø A&0^± &%0_± 0`±&%Port:° &&&&&&&&%’°]0a±° 0b±&%System0c±&%textBackgroundColor0d±° °b0e±& % textColor’0f±% C­€ B¤ B` A¨  B` A¨&0g± &%0h± 0i±&%27500°&&&&&&&&%’°f0j±° 0k±&%System0l±&%textBackgroundColor0m±° °k0n±& % textColor’0o1 NSPopUpButton% C' BD Cl A   Cl A &0p± &%0q1NSPopUpButtonCell1NSMenuItemCell0r±&%Button°&&&&&&&&0s1NSMenu0t±&0u± &0v1 NSMenuItem0w±&%Item 10x±&&&ÿ%0y±0z±& % common_Nibble’%0{±0|±&%Item 2°x&&ÿ%’%0}±0~±&%Item 3°x&&ÿ%’%%’°o0±&0€±&&&&°s°v%%%%%0±% @  @à B4 A  B4 A&0‚± &%0ƒ± 0„±&%Name:° &&&&&&&&%’°0…±° 0†±&%System0‡±&%textBackgroundColor0ˆ±° °†0‰±& % textColor’0б% B\ @à Bî A¨  Bî A¨&0‹± &%0Œ± 0±&°&&&&&&&&%’°Š0ޱ° 0±&%System0±&%textBackgroundColor0‘±° °0’±& % textColor’°°0“± 0”±&%Connect to Server°&&&&&&&&%’°A0•±° 0–±&%System0—±&%windowBackgroundColor0˜±° 0™±&%System0š±& % textColor @  @ %%0›±% C¶€ A€ B| AÀ  B| AÀ&0œ± &%0±0ž±&%Connect°&&&&&&&&%’°›0Ÿ±&0 ±&&&&0¡±% C˜ A€ B` AÀ  B` AÀ&0¢± &%0£±0¤±&%Cancel°&&&&&&&&%’°¡0¥±&0¦±&&&&°)0§±% C°€ À B¦ A  B¦ A&0¨± &%0©± 0ª±&%Sizer° &&&&&&&&%’°§0«±° 0¬±&%System0­±&%textBackgroundColor0®±° °¬0¯±& % textColor’°•0°±&%Window0±±&%Join Network Game°± ?€ B F@ F@%0²±0³±&%NSApplicationIcon0´±& %  TextField10°§0µ±&%GSCustomClassMap0¶±&0·±&%Box°A0¸±& %  TextField1°K0¹±& %  TextField2°T0º±&% Button1°E0»±& %  TextField3°]0¼±& %  TextField4°f0½±&% Button2°›0¾±&% Button3°¡0¿±&%GormNSPopUpButton°o0À±& %  TextField5°0Á±& %  TextField6°Š0± &""0Ã1NSNibConnector°=0ı&%NSOwner0ű°·0Ʊ°20DZ°º0ȱ°0ɱ°¸0ʱ°¹0˱°»0̱°¼0ͱ°¿0α°À0ϱ°Á0б°0ѱ°0Ò±°½0Ó±°¾0Ô±°(0Õ±°´0Ö1NSNibOutletConnector°Ä°º0×±&%hostnameCheckbox0ر°Ä°¸0Ù±& % hostField0Ú±°Ä°¼0Û±& % portField0ܱ°Ä°20ݱ&%rendezvousCheckbox0Þ±°Ä°¿0ß±&%rendezvousHostsPopup0౰İÁ0á±& % usernameField0Ɒİ(0ã±&%connectionStatusField0䱰İ0å±& % passwordField0æ1NSNibControlConnector°½°Ä0ç±&%connect:0è±°¾°Ä0é±&%cancelConnect:0ê±°2°Ä0ë±&%connectMethodChanged:0ì±°º°Ä°ë0í±°¿°Ä0î±&%rendezvousHostSelected:0ï±°Á°Ä0ð±&%updateUsername:0ñ±°Ä°=0ò±&%window0ó±°Ä°´0ô±&%windowSizerFieldgridlock.app-1.10/Resources/ClientWindow.gorm/data.classes0000644000175000000000000000742407671533205022661 0ustar gurkanroot{ ClientController = { Actions = ( "connect:", "cancelConnect:", "connectMethodChanged:", "disconnect:", "rendezvousHostSelected:", "startGame:", "updateUsername:" ); Outlets = ( connectionStatusField, hostField, hostnameCheckbox, passwordField, rendezvousCheckbox, rendezvousHostsPopup, usernameField, window, windowSizerField, portField ); Super = NSObject; }; FirstResponder = { Actions = ( "activateContextHelpMode:", "alignCenter:", "alignJustified:", "alignLeft:", "alignRight:", "arrangeInFront:", "cancel:", "capitalizeWord:", "changeColor:", "changeFont:", "checkSpelling:", "close:", "complete:", "copy:", "copyFont:", "copyRuler:", "cut:", "delete:", "deleteBackward:", "deleteForward:", "deleteToBeginningOfLine:", "deleteToBeginningOfParagraph:", "deleteToEndOfLine:", "deleteToEndOfParagraph:", "deleteToMark:", "deleteWordBackward:", "deleteWordForward:", "deminiaturize:", "deselectAll:", "fax:", "hide:", "hideOtherApplications:", "indent:", "loosenKerning:", "lowerBaseline:", "lowercaseWord:", "makeKeyAndOrderFront:", "miniaturize:", "miniaturizeAll:", "moveBackward:", "moveBackwardAndModifySelection:", "moveDown:", "moveDownAndModifySelection:", "moveForward:", "moveForwardAndModifySelection:", "moveLeft:", "moveRight:", "moveToBeginningOfDocument:", "moveToBeginningOfLine:", "moveToBeginningOfParagraph:", "moveToEndOfDocument:", "moveToEndOfLine:", "moveToEndOfParagraph:", "moveUp:", "moveUpAndModifySelection:", "moveWordBackward:", "moveWordBackwardAndModifySelection:", "moveWordForward:", "moveWordForwardAndModifySelection:", "newDocument:", "ok:", "openDocument:", "orderBack:", "orderFront:", "orderFrontColorPanel:", "orderFrontDataLinkPanel:", "orderFrontFontPanel:", "orderFrontHelpPanel:", "orderFrontStandardAboutPanel:", "orderFrontStandardInfoPanel:", "orderOut:", "pageDown:", "pageUp:", "paste:", "pasteAsPlainText:", "pasteAsRichText:", "pasteFont:", "pasteRuler:", "performClose:", "performMiniaturize:", "performZoom:", "print:", "raiseBaseline:", "revertDocumentToSaved:", "runPageLayout:", "runToolbarCustomizationPalette:", "saveAllDocuments:", "saveDocument:", "saveDocumentAs:", "saveDocumentTo:", "scrollLineDown:", "scrollLineUp:", "scrollPageDown:", "scrollPageUp:", "scrollViaScroller:", "selectAll:", "selectLine:", "selectNextKeyView:", "selectParagraph:", "selectPreviousKeyView:", "selectText:", "selectText:", "selectToMark:", "selectWord:", "showContextHelp:", "showGuessPanel:", "showHelp:", "showWindow:", "stop:", "subscript:", "superscript:", "swapWithMark:", "takeDoubleValueFrom:", "takeFloatValueFrom:", "takeIntValueFrom:", "takeObjectValueFrom:", "takeStringValueFrom:", "terminate:", "tightenKerning:", "toggle:", "toggleContinuousSpellChecking:", "toggleRuler:", "toggleToolbarShown:", "toggleTraditionalCharacterShape:", "transpose:", "transposeWords:", "turnOffKerning:", "turnOffLigatures:", "underline:", "unhide:", "unhideAllApplications:", "unscript:", "uppercaseWord:", "useAllLigatures:", "useStandardKerning:", "useStandardLigatures:", "yank:", "zoom:" ); Super = NSObject; }; }gridlock.app-1.10/Resources/Info-gnustep.plist0000644000175000000000000000114310342222026020424 0ustar gurkanroot{ ApplicationDescription = "Collection of abstract strategy board games"; ApplicationIcon = Gridlock.tiff; ApplicationName = Gridlock; ApplicationRelease = 1.10; Copyright = "Copyright (C) 2005 Brian Nenninger"; CopyrightDescription = "Released under BSD License"; FullVersionID = "Gridlock 1.10"; Authors = ("Brian Nenninger "); NOTE = "Automatically generated!"; NSExecutable = Gridlock; NSIcon = Gridlock.tiff; NSMainNibFile = Gridlock.gorm; NSPrincipalClass = NSApplication; NSRole = Application; NSTypes = ( ); } gridlock.app-1.10/Resources/Games.plist0000644000175000000000000007536610342202633017126 0ustar gurkanroot( { name = "Ataxx"; class = "AtaxxGame"; viewDelegate = "WallGameViewDelegate"; aiTypes = ( {name="Easy"; class="AtaxxAI"; params={depth=1;}; }, {name="Medium"; class="AtaxxAI"; params={depth=2;}; }, {name="Hard"; class="AtaxxAI"; params={depth=3; useThreads=1; }; }, {name="Very Hard"; class="AtaxxAI"; params={depth=4; useThreads=1;}; }, ); variations = ( {name="Default"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), ); }; }, {name="Random"; params={rows=7; cols=7; randomWalls={count=8; symmetry=none;}; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), ); }; }, {name="Random-V Sym"; params={rows=7; cols=7; randomWalls={count=10; symmetry=horizontal;}; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), ); }; }, {name="Random-Full Sym"; params={rows=7; cols=7; randomWalls={count=12; symmetry=both;}; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), ); }; }, {name="Cross"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (3,3,-1), (3,2,-1), (3,4,-1), (2,3,-1), (4,3,-1), ); }; }, {name="Diamond"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (3,5,-1), (3,1,-1), (5,3,-1), (1,3,-1), (4,4,-1), (4,2,-1), (2,4,-1), (2,2,-1), ); }; }, {name="Bridge"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (3,0,-1), (3,1,-1), (3,2,-1), (3,4,-1), (3,5,-1), (3,6,-1), ); }; }, {name="Quadrants"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (3,0,-1), (3,1,-1), (3,2,-1), (3,4,-1), (3,5,-1), (3,6,-1), (0,3,-1), (1,3,-1), (2,3,-1), (4,3,-1), (5,3,-1), (6,3,-1), ); }; }, {name="Moat"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (1,1,-1), (1,2,-1), (1,3,-1), (1,4,-1), (1,5,-1), (5,1,-1), (5,2,-1), (5,3,-1), (5,4,-1), (5,5,-1), (1,1,-1), (2,1,-1), (3,1,-1), (4,1,-1), (5,1,-1), (1,5,-1), (2,5,-1), (3,5,-1), (4,5,-1), (5,5,-1), ); }; }, {name="Courtyard"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (1,1,-1), (1,2,-1), (1,4,-1), (1,5,-1), (5,1,-1), (5,2,-1), (5,4,-1), (5,5,-1), (1,1,-1), (2,1,-1), (4,1,-1), (5,1,-1), (1,5,-1), (2,5,-1), (4,5,-1), (5,5,-1), ); }; }, {name="City Streets"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (1,1,-1), (1,3,-1), (1,5,-1), (3,1,-1), (3,3,-1), (3,5,-1), (5,1,-1), (5,3,-1), (5,5,-1), ); }; }, {name="X"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (1,1,-1), (2,2,-1), (3,3,-1), (4,4,-1),(5,5,-1), (1,5,-1), (2,4,-1), (4,2,-1), (5,1,-1), ); }; }, {name="Slash"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (1,1,-1), (2,2,-1), (3,3,-1), (4,4,-1),(5,5,-1), ); }; }, {name="Arena"; params={rows=7; cols=7; positions = ( (0,0,2), (6,6,2), (6,0,1), (0,6,1), (0,2,-1),(0,3,-1),(0,4,-1),(6,2,-1),(6,3,-1),(6,4,-1), (2,0,-1),(3,0,-1),(4,0,-1),(2,6,-1),(3,6,-1),(4,6,-1), (1,5,-1),(5,1,-1),(1,1,-1),(5,5,-1), ); }; }, {name="Fortress"; params={rows=7; cols=7; positions = ( (0,0,1), (0,1,1), (0,2,1), (0,3,1), (0,4,1), (0,5,1), (0,6,1), (1,3,1), (6,1,-1),(6,5,-1),(5,1,-1),(5,5,-1),(4,1,-1),(4,2,-1),(4,4,-1),(4,5,-1), (6,2,2), (6,3,2), (6,4,2), (5,2,2), (5,3,2), (5,4,2), ); }; }, {name="8x8 Standard"; params={rows=8; cols=8; positions = ( (0,0,2), (7,7,2), (7,0,1), (0,7,1) ); }; }, {name="8x8 Bridge"; params={rows=8; cols=8; positions = ( (0,0,2), (7,7,2), (7,0,1), (0,7,1), (3,0,-1),(3,1,-1),(3,2,-1),(3,5,-1),(3,6,-1),(3,7,-1), (4,0,-1),(4,1,-1),(4,2,-1),(4,5,-1),(4,6,-1),(4,7,-1), ); }; }, {name="8x8 Pillars"; params={rows=8; cols=8; positions = ( (0,0,2), (7,7,2), (7,0,1), (0,7,1), (1,1,-1),(1,2,-1),(2,1,-1),(2,2,-1), (5,1,-1),(5,2,-1),(6,1,-1),(6,2,-1), (5,5,-1),(5,6,-1),(6,5,-1),(6,6,-1), (1,5,-1),(1,6,-1),(2,5,-1),(2,6,-1), ); }; }, {name="8x8 Rand"; params={rows=8; cols=8; randomWalls={count=10; symmetry=none;}; positions = ( (0,0,2), (7,7,2), (7,0,1), (0,7,1), ); }; }, {name="8x8 Rand-V Sym"; params={rows=8; cols=8; randomWalls={count=12; symmetry=horizontal;}; positions = ( (0,0,2), (7,7,2), (7,0,1), (0,7,1), ); }; }, {name="8x8 Rand-Full Sym"; params={rows=8; cols=8; randomWalls={count=16; symmetry=both;}; positions = ( (0,0,2), (7,7,2), (7,0,1), (0,7,1), ); }; }, ); }, { name = "Dominion"; class = "DominionGame"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=1; }; }, {name="Medium"; class="GenericAI"; params={depth=2; }; }, {name="Hard"; class="GenericAI"; params={depth=3; useThreads=1;}; }, ); variations = ( {name="Default"; params={rows=8; cols=8; positions = ( (0,0,2), (7,7,2), (7,0,1), (0,7,1), (3,3,2), (4,4,2), (3,4,1), (4,3,1), ); }; }, ); }, { name = "Five Field Kono"; class = "FiveFieldKonoGame"; aiTypes = ( {name="Easy"; class="FiveFieldKonoAI"; params={depth=2;}; }, {name="Medium"; class="FiveFieldKonoAI"; params={depth=3;}; }, {name="Hard"; class="FiveFieldKonoAI"; params={depth=5;}; }, {name="Very Hard"; class="FiveFieldKonoAI"; params={depth=7;}; }, ); }, { name = "Quad Wrangle"; class = "QuadWrangleGame"; viewDelegate = "WallGameViewDelegate"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=1; }; }, {name="Medium"; class="GenericAI"; params={depth=2; }; }, {name="Hard"; class="GenericAI"; params={depth=3; }; }, ); variations = ( {name="Default"; params={rows=7; cols=7; positions = ( (1,0,1),(2,0,1),(3,0,1),(4,0,1),(5,0,1), (6,1,1),(6,2,1),(6,3,1),(6,4,1),(6,5,1), (0,1,2),(0,2,2),(0,3,2),(0,4,2),(0,5,2), (1,6,2),(2,6,2),(3,6,2),(4,6,2),(5,6,2), ); }; }, ); }, { name = "Reversi"; class = "ReversiGame"; viewDelegate = "WallGameViewDelegate"; aiTypes = ( {name="Easy"; class="ReversiAI"; params={depth=2; }; }, {name="Medium"; class="ReversiAI"; params={depth=3; }; }, {name="Hard"; class="ReversiAI"; params={depth=4; }; }, {name="Very Hard"; class="ReversiAI"; params={depth=5; useThreads=1; }; }, ); variations = ( {name="8x8"; params={rows=8; cols=8; positions=((3,3,2),(4,4,2),(3,4,1),(4,3,1),);}; }, {name="6x6"; params={rows=6; cols=6; positions=((2,2,2),(3,3,2),(2,3,1),(3,2,1),);}; }, {name="10x10"; params={rows=10; cols=10; positions=((4,4,2),(5,5,2),(4,5,1),(5,4,1),);}; }, {name="Annexation"; params={rows=10; cols=10; // need to update AI since there are no "corners"? positions=((4,4,2),(5,5,2),(4,5,1),(5,4,1), (0,0,-1),(0,1,-1),(0,2,-1),(1,0,-1),(1,1,-1),(1,2,-1),(2,0,-1),(2,1,-1),(2,2,-1), (7,0,-1),(7,1,-1),(7,2,-1),(8,0,-1),(8,1,-1),(8,2,-1),(9,0,-1),(9,1,-1),(9,2,-1), (7,7,-1),(7,8,-1),(7,9,-1),(8,7,-1),(8,8,-1),(8,9,-1),(9,7,-1),(9,8,-1),(9,9,-1), (0,7,-1),(0,8,-1),(0,9,-1),(1,7,-1),(1,8,-1),(1,9,-1),(2,7,-1),(2,8,-1),(2,9,-1), );}; }, ); }, { name = "Checkers"; class = "CheckersGame"; viewDelegate = "CheckersViewDelegate"; viewDelegateParams = {alternateCellColorComponents = "0.2 0.8 0.2";}; aiTypes = ( {name="Easy"; class="CheckersAI"; params={depth=2; regWeight=2; kingWeight=3;}; }, {name="Medium"; class="CheckersAI"; params={depth=3; regWeight=2; kingWeight=3;}; }, {name="Hard"; class="CheckersAI"; params={depth=5; regWeight=2; kingWeight=3; }; }, {name="Very Hard"; class="CheckersAI"; params={depth=8; regWeight=2; kingWeight=3; useThreads=1; }; }, ); variations = ( {name="8x8"; params={rows=8; cols=8;}; }, {name="10x10"; params={rows=10; cols=10;}; }, ); }, { name = "Gomoku"; class = "GomokuGame"; aiTypes = ( {name="Easy"; class="GomokuAI"; params={depth=1;}; }, {name="Hard"; class="GomokuAI"; params={depth=2; useThreads=1; }; }, ); variations = ( {name="8x8"; params={rows=8; cols=8;}; }, {name="10x10"; params={rows=10; cols=10;}; }, {name="12x12"; params={rows=12; cols=12;}; }, ); }, { name = "Connect Four"; class = "ConnectFourGame"; aiTypes = ( {name="Easy"; class="ConnectFourAI"; params={depth=2;}; }, {name="Medium"; class="ConnectFourAI"; params={depth=3;}; }, {name="Hard"; class="ConnectFourAI"; params={depth=4; }; }, {name="Very Hard"; class="ConnectFourAI"; params={depth=5; useThreads=1; }; }, ); variations = ( {name="6x7"; params={rows=6; cols=7;}; }, ); }, { name = "Gravity"; class = "GravityGame"; viewDelegate = "GravityViewDelegate"; aiTypes = ( {name="Easy"; class="GravityAI"; params={depth=1;}; }, {name="Medium"; class="GravityAI"; params={depth=2;}; }, {name="Hard"; class="GravityAI"; params={depth=3; useThreads=1; }; }, ); variations = ( {name="8x8"; params={rows=8; cols=8;}; }, ); }, { name = "Hexapawn"; class = "HexapawnGame"; variations = ( {name="4x4 Standard"; params={rows=4; cols=4; moveForward=1; captureDiagonally=1; }; }, {name="5x5 Standard"; params={rows=5; cols=5; moveForward=1; captureDiagonally=1; }; }, {name="6x6 Standard"; params={rows=6; cols=6; moveForward=1; captureDiagonally=1; }; }, {name="4x4 Berolina"; params={rows=4; cols=4; moveDiagonally=1; captureForward=1; }; }, {name="5x5 Berolina"; params={rows=5; cols=5; moveDiagonally=1; captureForward=1; }; }, {name="6x6 Berolina"; params={rows=6; cols=6; moveDiagonally=1; captureForward=1; }; }, {name="4x4 Berolina+"; params={rows=4; cols=4; moveDiagonally=1; captureForward=1; captureSideways=1; }; }, {name="5x5 Berolina+"; params={rows=5; cols=5; moveDiagonally=1; captureForward=1; captureSideways=1; }; }, {name="6x6 Berolina+"; params={rows=6; cols=6; moveDiagonally=1; captureForward=1; captureSideways=1; }; }, ); aiTypes = ( {name="Easy"; class="HexapawnAI"; params={searchDepths=(4,3); }; }, {name="Medium"; class="HexapawnAI"; params={searchDepths=(5,4); }; }, {name="Hard"; class="HexapawnAI"; params={searchDepths=(6,5); useThreads=1; }; }, {name="Very Hard"; class="HexapawnAI"; params={searchDepths=(7,6); useThreads=1; }; }, ); }, { name = "Breakthrough"; class = "HexapawnGame"; variations = ( {name="8x8"; params={rows=8; cols=8; fillRows=2; moveForward=1; moveDiagonally=1; captureDiagonally=1; }; }, ); aiTypes = ( {name="Easy"; class="BreakthroughAI"; params={depth=1; pieceWeight=40; }; }, {name="Medium"; class="BreakthroughAI"; params={depth=2; pieceWeight=40; }; }, {name="Hard"; class="BreakthroughAI"; params={depth=3; pieceWeight=40; useThreads=1; }; }, ); }, { name = "Orthokon"; class = "OrthokonGame"; variations = ( {name="4x4"; params={rows=4; cols=4; }; }, {name="5x5"; params={rows=5; cols=5; }; }, {name="6x6"; params={rows=6; cols=6; }; }, ); aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=3; }; }, {name="Medium"; class="GenericAI"; params={depth=4; }; }, {name="Hard"; class="GenericAI"; params={depth=5; }; }, {name="Very Hard"; class="GenericAI"; params={depth=6; }; }, ); }, { name = "Photonic Attack"; class = "PhotonicAttackGame"; variations = ( {name="8x8"; params={rows=8; cols=8;}; }, ); aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=2; }; }, {name="Medium"; class="GenericAI"; params={depth=3; }; }, {name="Hard"; class="GenericAI"; params={depth=4; }; }, {name="Very Hard"; class="GenericAI"; params={depth=5; }; }, ); }, { name = "Fission"; class = "FissionGame"; variations = ( {name="Normal"; params={rows=8; cols=8; positions=((1,4,1),(2,3,1),(2,5,1),(3,2,1),(3,4,1),(3,6,1), (4,1,1),(4,3,1),(4,5,1),(5,2,1),(5,4,1),(6,3,1), (1,3,2),(2,2,2),(2,4,2),(3,1,2),(3,3,2),(3,5,2), (4,2,2),(4,4,2),(4,6,2),(5,3,2),(5,5,2),(6,4,2) ); }; }, {name="Suicide"; params={rows=8; cols=8; suicide=1; positions=((1,4,1),(2,3,1),(2,5,1),(3,2,1),(3,4,1),(3,6,1), (4,1,1),(4,3,1),(4,5,1),(5,2,1),(5,4,1),(6,3,1), (1,3,2),(2,2,2),(2,4,2),(3,1,2),(3,3,2),(3,5,2), (4,2,2),(4,4,2),(4,6,2),(5,3,2),(5,5,2),(6,4,2) ); }; }, {name="Random"; params={rows=8; cols=8; randomCells=12; }; }, {name="Suicide Random"; params={rows=8; cols=8; randomCells=12; suicide=1; }; }, ); aiTypes = ( {name="Easy"; class="FissionAI"; params={depth=2; }; }, {name="Medium"; class="FissionAI"; params={depth=3; }; }, {name="Hard"; class="FissionAI"; params={depth=4; }; }, ); }, { name = "Reactor"; class = "ReactorGame"; viewDelegate = "ReactorViewDelegate"; variations = ( {name="Normal"; params={rows=8; cols=8; p1pieces=13; p2pieces=14; neutrons=4; }; }, ); aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=1; }; }, {name="Medium"; class="GenericAI"; params={depth=2; }; }, {name="Hard"; class="GenericAI"; params={depth=3; }; }, {name="Very Hard"; class="GenericAI"; params={depth=4; }; }, ); }, { name = "Bombardment"; class = "BombardmentGame"; variations = ( {name="8x8"; params={rows=8; cols=8; moveForward=1; moveDiagonally=1; fillRows=2;}; }, ); aiTypes = ( {name="Easy"; class="BombardmentAI"; params={depth=1; }; }, {name="Medium"; class="BombardmentAI"; params={depth=2; }; }, {name="Hard"; class="BombardmentAI"; params={depth=3; }; }, ); }, { name = "Tourney"; class = "TourneyGame"; viewDelegate = "CheckersViewDelegate"; variations = ( {name="8x8"; params={rows=8; cols=8; fillRows=2;}; }, ); aiTypes = ( {name="Easy"; class="TourneyAI"; params={depth=2; }; }, {name="Medium"; class="TourneyAI"; params={depth=3; }; }, {name="Hard"; class="TourneyAI"; params={depth=5; }; }, {name="Very Hard"; class="TourneyAI"; params={depth=7; }; }, ); }, { name = "Daggers"; class = "DaggerGame"; viewDelegate = "CheckersViewDelegate"; variations = ( {name="8x8"; params={rows=8; cols=8; positions=((1,1,1),(1,2,1),(1,3,1),(1,4,1),(1,5,1),(1,6,1), (0,2,-1), (0,5,-1), (6,2,2),(6,3,2),(6,4,2),(6,5,2), (7,3,-2),(7,4,-2)); }; }, ); aiTypes = ( {name="Easy"; class="DaggerAI"; params={depth=1; }; }, {name="Medium"; class="DaggerAI"; params={depth=2; }; }, {name="Hard"; class="DaggerAI"; params={depth=3; }; }, {name="Very Hard"; class="DaggerAI"; params={depth=4; }; }, ); }, { name = "Fianco"; class = "FiancoGame"; variations = ( {name="Default"; params={rows=9; cols=9; positions=((0,0,1),(0,1,1),(0,2,1),(0,3,1),(0,4,1),(0,5,1),(0,6,1),(0,7,1),(0,8,1), (8,0,2),(8,1,2),(8,2,2),(8,3,2),(8,4,2),(8,5,2),(8,6,2),(8,7,2),(8,8,2), (1,1,1),(2,2,1),(3,3,1),(3,5,1),(2,6,1),(1,7,1), (7,1,2),(6,2,2),(5,3,2),(5,5,2),(6,6,2),(7,7,2), ); }; }, ); aiTypes = ( {name="Easy"; class="FiancoAI"; params={depth=2; }; }, {name="Medium"; class="FiancoAI"; params={depth=3; }; }, {name="Hard"; class="FiancoAI"; params={depth=4; useThreads=1;}; }, ); }, { name = "Zonesh"; class = "ZoneshGame"; viewDelegate = "ZoneshViewDelegate"; aiTypes = ( {name="Easy"; class="ZoneshAI"; params={depth=1; }; }, {name="Medium"; class="ZoneshAI"; params={depth=2; }; }, {name="Hard"; class="ZoneshAI"; params={depth=3; useThreads=1; }; }, {name="Very Hard"; class="ZoneshAI"; params={depth=4; useThreads=1; }; }, ); variations = ( {name="6x6"; params={rows=6; cols=6;}; }, {name="5x5"; params={rows=5; cols=5;}; }, {name="7x7"; params={rows=7; cols=7;}; }, ); }, { name = "Glass Bead"; class = "GlassBeadGame"; viewDelegate = "GlassBeadViewDelegate"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=1; }; }, {name="Medium"; class="GenericAI"; params={depth=2; }; }, {name="Hard"; class="GenericAI"; params={depth=3; useThreads=1; }; }, {name="Very Hard"; class="GenericAI"; params={depth=4; useThreads=1; }; }, ); variations = ( {name="8x8"; params={rows=8; cols=8;}; }, {name="9x9"; params={rows=9; cols=9;}; }, {name="10x10"; params={rows=10; cols=10;}; }, ); }, { name = "Cats & Dogs"; class = "CatsAndDogsGame"; viewDelegate = "CatsAndDogsViewDelegate"; aiTypes = ( {name="Easy"; class="CatsAndDogsAI"; params={depth=2; }; }, {name="Medium"; class="CatsAndDogsAI"; params={depth=3; useThreads=1; }; }, {name="Hard"; class="CatsAndDogsAI"; params={depth=4; useThreads=1; }; }, ); variations = ( {name="8x8"; params={rows=8; cols=8;}; }, ); }, { name = "Moray Eels"; class = "MorayEelsGame"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=2; }; }, {name="Medium"; class="GenericAI"; params={depth=3; }; }, {name="Hard"; class="GenericAI"; params={depth=4; }; }, {name="Very Hard"; class="GenericAI"; params={depth=5; }; }, ); variations = ( {name="5x7"; params={rows=5; cols=7; positions=((0,0,1),(0,1,1),(0,2,1),(0,4,1),(0,5,1),(0,6,1), (4,1,2),(4,5,2)); }; }, ); }, { name = "Atomic"; class = "AtomicGame"; viewDelegate = "AtomicViewDelegate"; aiTypes = ( {name="Easy"; class="AtomicAI"; params={depth=1; utilityArray=((60), (40,80), (30, 60, 90)); }; }, {name="Medium"; class="AtomicAI"; params={depth=2; utilityArray=((60), (40,80), (30, 60, 90)); }; }, {name="Hard"; class="AtomicAI"; params={depth=3; utilityArray=((60), (40,80), (30, 60, 90)); }; }, {name="Very Hard"; class="AtomicAI"; params={depth=4; utilityArray=((60), (40,80), (30, 60, 90)); useThreads=1; }; }, // current best utilityArray (at 3-ply): ((60), (40,80), (30, 60, 90)) // others tested: ((30), (20,30), (10, 20, 30)) // ((60), (35,70), (25, 50, 75)) (tie) ); variations = ( {name="Default"; params={rows=6; cols=6;};}, ); }, { name = "Life"; class = "LifeGame"; variations = ( {name="21x21"; params={rows=21; cols=21; positions=((3,3,1),(3,4,1),(4,3,1),(4,4,1), (17,3,1),(17,4,1),(16,3,1),(16,4,1), (3,9,1),(4,9,1),(5,9,1),(5,10,1),(4,11,1), (3,17,2),(3,16,2),(4,17,2),(4,16,2), (17,17,2),(17,16,2),(16,17,2),(16,16,2), (17,11,2),(16,11,2),(15,11,2),(15,10,2),(16,9,2), (10,9,1),(10,10,2),(10,11,1), (9,3,2),(10,3,1),(11,3,2), (9,17,2),(10,17,1),(11,17,2), ); }; }, {name="20x20 Random"; params={rows=20; cols=20; player1RandomCells=50; player2RandomCells=52;}; }, ); aiTypes = ( {name="Easy"; class="LifeAI"; params={depth=1; useThreads=1; }; }, ); }, { name = "Diagonals"; class = "DiagonalsGame"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=1; }; }, {name="Medium"; class="GenericAI"; params={depth=2; }; }, {name="Hard"; class="GenericAI"; params={depth=3; }; }, {name="Very Hard"; class="GenericAI"; params={depth=4; useThreads=1; }; }, ); variations = ( {name="8x8"; params={rows=8; cols=8;}; }, {name="6x6"; params={rows=6; cols=6;}; }, {name="10x10"; params={rows=10; cols=10;}; }, ); }, { name = "Tonga"; class = "TongaGame"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=1; }; }, {name="Hard"; class="GenericAI"; params={depth=2; }; }, ); variations = ( {name="9x9"; params={rows=9; cols=9;}; }, ); }, { name = "Think Ahead"; class = "ThinkAheadGame"; viewDelegate = "ThinkAheadViewDelegate"; aiTypes = ( {name="Easy"; class="ThinkAheadAI"; params={depths=(2,2,2,2); }; }, {name="Medium"; class="ThinkAheadAI"; params={depths=(4,5,6,7); }; }, {name="Hard"; class="ThinkAheadAI"; params={depths=(6,8,10,10); }; }, {name="Very Hard"; class="ThinkAheadAI"; params={depths=(8,9,10,11); useThreads=1; }; }, ); }, { name = "Ambivalence"; class = "AmbivalenceGame"; viewDelegate = "WallGameViewDelegate"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=2; }; }, {name="Medium"; class="GenericAI"; params={depth=3; }; }, {name="Hard"; class="GenericAI"; params={depth=4; }; }, ); variations = ( {name="6x6"; params={rows=6; cols=6;}; }, {name="8x8"; params={rows=8; cols=8;}; }, ); }, { name = "Sabotage"; class = "SabotageGame"; viewDelegate = "SabotageViewDelegate"; aiTypes = ( {name="Easy"; class="SabotageAI"; params={depth=2; }; }, {name="Medium"; class="SabotageAI"; params={depth=3; }; }, {name="Hard"; class="SabotageAI"; params={depth=4; }; }, ); variations = ( {name="Standard"; params={rows=9; cols=13; p1Goal = (4,1); p2Goal=(4,11); positions = ( (0,0,2), (0,1,2), (8,0,2), (8,1,2), (3,2,1), (3,3,1), (5,2,1), (5,3,1), (4,4,1), (4,6,-3), (0,11,1), (0,12,1), (8,11,1), (8,12,1), (3,9,2), (3,10,2), (5,9,2), (5,10,2), (4,8,2), );}; }, {name="Reverse Goals"; params={rows=9; cols=13; p1Goal = (4,11); p2Goal=(4,1); positions = ( (0,0,2), (0,1,2), (8,0,2), (8,1,2), (3,2,1), (3,3,1), (5,2,1), (5,3,1), (4,4,1), (4,6,-3), (0,11,1), (0,12,1), (8,11,1), (8,12,1), (3,9,2), (3,10,2), (5,9,2), (5,10,2), (4,8,2), );}; }, ); }, { name = "Fusion"; class = "FusionGame"; viewDelegate = "ReactorViewDelegate"; aiTypes = ( {name="Easy"; class="GenericAI"; params={depth=2; }; }, {name="Medium"; class="GenericAI"; params={depth=3; }; }, {name="Hard"; class="GenericAI"; params={depth=4; }; }, ); variations = ( {name="8x8"; params={rows=10; cols=10; protons = 20; positions = ( (4,4,1),(5,5,1),(4,5,2),(5,4,2) );}; }, ); }, // { // name = "Diagonals 2"; // class = "Diagonals2Game"; // viewDelegate = "WallGameViewDelegate"; // aiTypes = ( // {name="Easy"; class="GenericAI"; params={depth=2; }; }, // {name="Medium"; class="GenericAI"; params={depth=3; }; }, // {name="Hard"; class="GenericAI"; params={depth=4; }; }, // ); // variations = ( // {name="5x10"; params={rows=5; cols=10; // positions=((0,0,1),(1,0,1),(3,9,2),(4,9,2)); // }; // }, // {name="8x8"; params={rows=8; cols=8; // positions=((3,0,1),(4,0,1),(3,7,2),(4,7,2)); // }; // }, // ); // }, // { // name = "Nevo"; // class = "NevoGame"; // aiTypes = ( // {name="Easy"; class="NevoAI"; params={depth=2; }; }, // {name="Medium"; class="NevoAI"; params={depth=3; }; }, // {name="Hard"; class="NevoAI"; params={depth=4; }; }, // ); // variations = ( // {name="7x12"; params={rows=7; cols=12;}; }, // ); // }, ) gridlock.app-1.10/Resources/PieceImages.plist0000644000175000000000000000110107523137727020237 0ustar gurkanroot( { name = "Aqua"; file = "aqua.tiff"; highlight = cyanColor; }, { name = "Blue"; file = "blue.tiff"; highlight = blueColor; }, { name = "Graphite"; file = "graphite.tiff"; highlight = grayColor; }, { name = "Green"; file = "green.tiff"; highlight = greenColor; }, { name = "Purple"; file = "purple.tiff"; highlight = purpleColor; }, { name = "Red"; file = "red.tiff"; highlight = redColor; }, { name = "Yellow"; file = "yellow.tiff"; highlight = yellowColor; }, )gridlock.app-1.10/Resources/Localizable.strings0000644000175000000000000000145207735511732020651 0ustar gurkanrootHumanPlayer = "Human"; ComputerPlayerPrefix = "CPU: "; NetworkPlayer = "Network"; RestartTitle = "Restart"; RestartOK = "Restart"; RestartCancel = "Don't Restart"; RestartMessage = "The current game is in progress. Are you sure you want to restart?"; TieMessage = "The game is a tie"; WinMessage = "Player %d wins"; NetworkStatusNotConnected = "Not connected"; NetworkStatusConnected = "Connected to %@"; DisconnectTitle = "Disconnect"; DisconnectMessage = "Are you sure you want to disconnect from the network game?"; DisconnectOK = "Disconnect"; DisconnectCancel = "Don't Disconnect"; GameRestartedMessage = "Game Restarted"; SaveFailedTitle = "Save Failed"; SaveFailedMessage = "Unable to save game"; OpenFailedTitle = "Open Failed"; OpenFailedMessage = "Unable to open game"; NoVariationsTitle = "(None)"; gridlock.app-1.10/Resources/Gridlock.tiff0000644000175000000000000014031407735511425017425 0ustar gurkanrootMM*HHþ€€Ì€À(www¬¬¬¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯©©©xxx­­­¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯§§§ppy’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯‹‹¤mm{““¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯‰‰ oo~””¯’’¯’’¯’’¯’’°““°””°““°Ž­‰ˆ¨‹Šª’’¯””±““°’’¯’’¯’’¯’’¯““¯††rr””¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯’’¯““¯€€•§§§ôôôùùùùùùùùùùùùùùùúúúúúúùùùùùùùùùùùùùùùúúúúúúúúúùùùùùùúúúðð𨨨öööúúúùùùùùùùùùùùùùùùúúúúúúùùùùùùùùùùùùùùùúúúúúúúúúùùùúúúííì™™«¾¾ø¾¾ú¾¾ú½½ù½½ù½½ù½½ù½½ù¾¾ú¾¾ú¾¾ú½½ù½½ù½½ù½½ù½½ù¾¾ú¾¾ú¾¾ú··è’’®¿¿ú½½ù¾¾ú¾¾ú½½ù½½ù½½ù½½ù½½ù¾¾ú¾¾ú¾¾ú½½ù½½ù½½ù½½ù½½ù¾¾ú¾¾ú´´ã””±ÀÀú½½ù½½ù¿¿ú¿¿ú¸¸ö¨¦ë˜•á—•ã‹Ú’Þ––✜尰ñ½½ø¾¾ù½½ù½½ù¾¾ú°°Þ——¶ÀÀú½½ù½½ù½½ù¾¾ú¾¾ú¾¾ú½½ù½½ù½½ù½½ù½½ù¾¾ú¾¾ú½½ù½½ù½½ù½½ù¿¿ú¨¨Ô«««øøøþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¾¾ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í““²¿¿þ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––µÀÀþ½½ý¾¾þ½½ý¢Ÿï‚}ÞysÛvràspãqpäqqäqsâsuÜuxÙ‹ã²²ø¿¿þ½½þ¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««ùùùþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í””²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––µÀÀþ¾¾þ»ºü‘‹çja×qjãpkçmjékiéjiéikéiméjoèlsåemÛmrØ©ªó¿¿þ¿¿þ±±ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««øøøþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í““²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––µÁÁþ¾½þ‰è`UØngæojénjéliéjjéiléinéipéiqèitéjvé]jÞ`jÕ­®óÀÀÿ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««øøøþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í““²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––µÁÁÿ œðaVÙmeæoiémiékiéjièikèinéioéiqèisèiuèiwèjyéWiÜmwعºû±±ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««ùùùþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í””²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––¶½¼þwoâh^âpjémiékiéijêiléiméipéjqéitéiuèiwèiyèi{éh{èUiך ì²²ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««ùùùþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿòòñ››®¿¿ý¾¾ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ··í””²ÀÀÿ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ´´è——¶©§öf]ßnhçmièkièjjèikèilèinèiqéiséiuéiwèiyèi{èi|èjè]uàsÝ®®ß™™ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø«««ùùùþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿòòñ››®¿¿ý¾¾ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ··í““²ÀÀÿ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ´´è––µ’Žîc\àmièkjèjjéikéimèioèiqéisèiuèiwèiyèi{èj}éièj‚èf€ç_uÚ¡£×™™ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø«««øøøþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í””²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þµµè””´zvæd^ãljéijéiléiméioéiqéiréiuéivéiyèizéi}éi€éi‚éiƒéi…éUrÚŽ•Í™™ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««ùùùþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í””²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þµµè’’´nkáb^ãjjéhkéilèioèipéirèitçivéixèhzèi|éi~èh€èiƒéh…èh†èQrÙ…ŽÉššºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««øøøþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í““²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è““´sräa`äjkéiléjpêiqéiréitéiwéhxéhzèi}éièièi„éi†éi‡êi‰éTu؈ș™ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««øøøþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í““²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––µ‰ˆë^_áiméinèiqéiréisèiuéiwèizèi}éi~èi€èiƒéi†éh‡éiˆéf‰çZyÖ˜œÎ™™ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««ùùùþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í””²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è——¶¡¡ô]`ßhmèipèjréjuéivèjxéjzèi|éiéi€èi‚èi„éi‡éi‰éj‹èa‡åg€Ô§§×™™ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««ùùùþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿòòñ››®¿¿ý¾¾ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ··í””²ÀÀÿ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ´´è––¶¹¹üpsãekæjréjuêiwêjyéj{éi|éhéièiƒéi…éi†èj‰êj‹éjé\‚Þˆ”ܯ¯ß˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø«««ùùùþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿòòñ››®¿¿ý¾¾ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ··í““²ÀÀÿ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ´´è––µÁÁÿ—šïelãitèivèixéizéi}éi~èiéi‚èi„èi‡èiˆèiŠèiéf‹çh„Ö«­í²±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø«««ùùùþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿòòñ››®¿¿ý¾¾ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ··í””²ÀÀÿ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ´´è––µÁÁÿ¹¹û‡Žìjwèkzêizéi|éjéiéiƒéj…éj‡éj‰èiŠèiék‘ëjŠÞ—žß½½ü±±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø«««ùùùþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í””²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––µÀÀþ¿¾þ´µù‰‘ît„în‚ìjéhèh‚éi…èi†éiˆèiŠèlêq—ís’ä›Þ¹¹÷¿¿ÿ±±ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««øøøþþþýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþòòñ››®¿¿ý½½þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ··í““²ÀÀþ½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ´´è––µÀÀþ½½ý¿¾þ·¸ú˜Ÿï‡›ï‚œòvîpŒìnŽìoìs•í| ðƒ§ïƒ›à›¡á¹¹÷¾¾þ¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø«««ùùùþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿòòñ››®¿¿ý½½ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ··í““²ÀÀÿ½½þ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ´´è––µÀÀÿ½½þ½½þ¿¿ÿ¼¼ü­±ôŸ«î–ªí”¯ï’±ï‘²î‘®ë”¨äœ¦ã®¯í¼»û¾¾þ½½þ¾¾ÿ±±ã˜˜ºÀÀÿ½½þ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ¿¿ÿ©©Ø¥¥¥ïïïôôôôôôôôôôôôôôôõõõõõõôôôôôôôôôôôôôôôõõõõõõõõõôôôôôôõõõëë릦¦ñññõõõôôôôôôôôôôôôôôôõõõõõõôôôôôôôôôôôôôôôõõõõõõõõõôôôõõõééè––¨»»ôººõ»»õººôººôººôººôººô»»ö¼¼ö»¼öººõººôººôººôººô»»õ»»õ»»õ³³ä¬½½õ»»ô¼¼õ¼¼õ»»ô»»ô»»ô»»ô»»õ¼¼ö¼¼ö¼¼õ»»ô»»ô»»ô»»ô»»ô¼¼õ¼¼ö±±ß’’¯¾¾ö»»ô»»ô¼¼õ¼¼ö¼¼ö¹¹ò³´í®²é­²æ«°å­°æ³´ëº¹ò¼¼õ»»õ»»ô»»ô¼¼ö®®Û••³¾¾ö»»ô»»ô»»ô¼¼õ¼¼õ¼¼õ»»ô»»õ»»õ»»õ»»ô¼¼õ¼¼õ»»ô»»ô»»ô»»ô½½ö¦¦Ðuuu©©©­­­¬¬¬¬¬¬¬¬¬­­­®®¯­®®¬««¨¦¥¨¦¥¬««­®®®¯¯­­­­­­¬¬¬¬¬¬­­­§§§vvv«««­­­¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬­­­­­­¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬­­­­­­­­­¬¬¬­­­¤¤¤ttw¢¢­¢¢®££®¢¢®¢¢®¢¢®£¤®££®  ­›šªœ›ª¡¡­££®££®¢¢®¢¢®££®££®££®˜˜¢nnz’’®‘‘®‘‘®‘‘®‘‘®‘‘®’’®‘‘®Ž¬Œ‹ªŒ«‘®‘‘®’’®‘‘®‘‘®‘‘®‘‘®‘‘¯ˆˆŸnn|’’¯‘‘®‘‘®‘‘®‘‘®‘‘®‘‘®‘‘®‘‘®‘‘®‘‘®’’¯’’¯‘‘®‘‘®‘‘®‘‘®‘‘®’’¯……›pp““¯‘‘®‘‘®‘‘®‘‘®’’¯’’¯‘‘®ŽŽ¬‹Š©Œ«­’’¯’’¯‘‘®‘‘®‘‘®‘‘®’’¯~~”©©©öööüüüûûûûûûüýýù÷öïàÜãÀ¸ä·¯Þ©ŸÝ§ ã´¯ã½¹ïßÝú÷÷ýþþûûûûûûüüüòòòªªªøøøüüüûûûûûûûûûûûûûûûüüüüüüûûûûûûûûûûûûûûûüüüüüüüüüûûûüüüïïשּׁ«ûûúýýüýýüüüûþþüõôøÛØí¹¶â±¯ä¢žÝ¥£Þ±±ã¾¾äáâðùùúýýüýýüýýüýýüëëê™™¯ÁÁü¿¿ûÀÀüÀÀüÀÀü¸¸ø¨¥í–“▔䎉ݎߕ•㙘䭭ñ½½úÀÀü¿¿ûÀÀüÀÀüµµæ––³ÂÂü¿¿û¿¿ûÀÀüÀÀüÀÀü¿¿û¿¿û¿¿û¿¿û¿¿ûÀÀüÀÀü¿¿û¿¿û¿¿û¿¿û¿¿ûÀÀü±±à˜˜¸ÂÂü¿¿û¿¿û¿¿ûÀÀü·¶÷¥£ì•“â•“ä‰Ü‘à””ã››æ°°ó¾¾ûÀÀü¿¿û¿¿ûÁÁü©©Ö«««ùùùþþþþþþþþþñàÜߨۋ|àƒtã|oåyoåxoãwoßztÚ€}Ý¢ŸñßÞþÿÿþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿñññ­­­ýýýÿÿÿÿÿÿýýþ×Ôï—Þ{ÛwsàroäpoåopåpqãuwÞ‚Ù¥¨ßååôÿÿÿÿÿÿÿÿÿííìšš±¿¿ÿ½½þ¿¿ÿ½½þ žî€{ÝxrÜvrároäpoåppåprãruÞsvÙ…‡à­®õ¿¿þ¾¾ÿ¾¾ÿ´´è––µÀÀÿ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ±±ã˜˜ºÀÀÿ½½þ¾¾þ»»ýœ˜ë~xÜxrÜuráqoäpoåppåprâruÝtwÙ‰‹â±²÷¿¿ÿ½½þ¿¿ÿ©©Ø«««ùùùþþþþýýìÎÇÖƒqázhç|jéyjéviétiériépiènjçljàjhÕtsëÊÉýýýÿÿÿõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ­­­ýýýÿÿÿûûýÀ¼èul×piâojèmiékiéjjéiléiméjnèkrægpÞyÖÓÕîþþþþþþííìšš±¿¿þ¾¾þ»»ýŠçi`×qiãpkèmiékiéjjéiléiméjoèlsæfnÝgmÖ¢£ï¿¿þ¿¿þ´´è––µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±ã˜˜ºÀÀþ¾¾þ¸¸û‰ƒãi`×qjäojèmjéjiéjjéiléiméjoèlsædlÜlqب©ó¿¿þ¿¿þ©©Ø«««øøøþþþîÒÌ×vbäxdé{jéyjèwiéuiésiépiénièlièjiêjjãceÓbdêÍÍþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ­­­ýýýþþþþêh]×meåojénjélièjjéiléinéipéiqèitéjvé`náhtÓÙÛîÿÿþííìšš±ÀÀþ¾¾þŠè_UØnfæojénjélièjjéiléinéipéiqèitéjvé_máZeÔ¦©ð¿¿ÿ´´è––µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÁÁþ¼¼ý†€äaUÙohçojémjékièjjéiléinéipéirèitéjvé]jß`jÕ­®ôÀÀÿ©©Ø«««ùùúõèåÚnäuaéziéxiéwiètièrhépiéoièlièjjèjjèikéioâ^eÓnróåæõöö¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ­­­þþýÜÚòqfÙlcåoiémiéliéiièikèinéioéiqèjsèiuèiwèjyé\này†Õïð÷îîìšš±ÁÁÿ¡ŸðaVÙmeæoiémiékiéiièikèinéioéiqèjsèiuèiwèjzéZlÞeqÖµ¶ùµµè––µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÂÂÿ˜”í`TÙnfçoièmiékiéiièikèinéioéiqèitèiuéiwèjzéWiÛnyÙººü©©Ø«¬¬øùùè´©àp[è{jéyiéwiêuiériéqiéniémjékjéijèjléinéipéjrÜYcਭóõô¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ®®®ûûüŸ™åf\âpjèmiékiéjjêikéiméipéjqéiséiuèiwèiyèizéi|éZnÚ¹Áåîîì››±½½ýzrãg]âpjémiékiéjjêikéiméipéjqéitéiuèiwèiyèi{éi|èUjÙ’™èµµè––µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±ã™™ºººýrjái`äpiémiékiéijêiléinéipéiréitéivèixèizèi{égzèVj×¢íªªØ¬­­ôëèàˆxæweèxièuiètièsièpièniéliékièijèikéimèioèiqèjsäco×s~ëã䬭¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ¯¯®åäövnßlfçmièkièjjèikèilèinèiqéitéiuéivèiyèizèi|èj~è`xã‘Ùãäæœœ²«©öf^Þmhçmièkièjjèikèilèinèiqéitéitéiwèiyèizèi|èj~è_wâl{Û¯¯ã––¶ÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±âššº¤¡õe\ßniçmièkièjjèikèilèioèiréitèitéiwèiyèi{èi|èjè\tàvƒÞ§§Õ¬¯¯íÒÍÞucèyhèvjètjésièpièoiémièkièijèikèiméipéjrèitèivèhvÛ`nàÅȬ­­ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿñññ¯¯®ÆÃïg`ßmièkjèjjéikéimèinèiqéisèitèiwèiyèizèj}éi€èiègèf~ÚËÏܲ•‘ïc\ßmjèkjèjjéikéimèioèiqéisèitèiwèiyèizèj}éi€èjègç\sÚŸ¢Ú—–¶ÁÁÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±â™™º‹‡íd^áljèkjèijéikéinèioèiqéisèiuèiwèiyèi{éj~éi€èj‚èeæawÛ›œÍ¬¯°å´­àm[éxjéuiésiéqiéoiémiéliéjjéjlèimèioéiréitéiuéiwéiyÞYkÖ¤««­­ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿñññ®®­£ æb\ámjéijéikéiméioéipéiréjuéjvéiyèizèi}éi€éi‚éiƒéi…éZxÜ®·Òœ›±}yæc]âljéijéiléiméioéiqéiréjuéjvéiyèizéi}éi€éi‚éiƒéi…éUsÛ‹“З—¶ÁÁÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã••¸tpåe`ãljéijéiléiméioéiqéiréiuéivéiyèi{éi}éi€èi‚éiƒéh…èVsيŬ¯°á¦žàhXéujéthèphèoiémièkiçijèiléimèioèiqéiréhuéiwéiyèi{ÝVlÒ– ª¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ®®­“‘á_[âkjéhkéhlèioèiqéirèitèivéixéizèi|éi~éh€èiƒéi…éi‡èVwÛ¡¬Î›š°qoâa]ãkjéhkéhlèioèiqéirèitçivéixéizèi|éi~éh€èiƒéi…èi‡èRsÚ‚ŒÌ——µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ²²ã““·igád`äjjéhkéilèioèiqéirèitèivéixèizèi|éi~èièiƒéi…éh†çQr؃ŠÁ¬¯°ã®¨àh[étjèriépiêniékiéijéiléhmèhoèiréisèhtéixéiyéi|êj~ÜYoѦª¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ®®­›ä^]âjkéimèipéiqéiréitéiwéhxéhzèj|èiéièi„éi…éi‡éj‰êX{Ú¦±Í››°xwä_^ãjkéiméipêiqéiréitéiwéhxéhzèj}éièièi„éi…éi‡éiŠêTuن˗–µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â””¸onãbbåjkéiméjpêiqéiséiuéiwéhyéhzèj}éièiéj„éi†éi‡êh‰éTu׆ŒÀ¬¯°ìËÈßkbèphèniémiékièijéilèilèioèjrèirèitéiwéiyéh|èi}èh~Ù\s×¹¿«­¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ¯¯®¾¾í`aàiléimèiqèiréisèiuéiwèizèj}éi~èi€èiƒéi…éh‡éiˆèg‰èa‚×ÀÆÓ±Ží]^áiméinèiqéiréisèiuéixèi{èj}éi~èi€èiƒéi†éh‡éiˆèf‰èXyÖ˜œÑ—–¶ÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜¹……ë^`âiméinèiqéiréisèiuéixèi{èi}éi~èi€èiƒéi†éi‡éiˆèeˆç\zÕ•—Ǭ®®óåäàzsçlfèmiékiéjjéiléjnèjpéiréitéiuèiwéiyéi|éi~èiçe}ÔjáÖØ¬­­ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ¯¯®ßßõjmßgkèipèiréjtéivèjxéjzèi|éiéi€èiƒèi„éi‡éi‰éj‹ècˆæu‘ÓÙÚÝœ²¦¦õ^aßhmèipèiréjuéivèjxéjzèi|éjéi€èiƒèi„éi‡éi‰éi‹èb‡åeÓ¨©Û––¶ÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±ãššºžó\`ßinèipèjséjuéiwèjxéjzéi}éiéièiƒéi…éi‡éi‰éj‹è_…ãmƒÕ¢¢Ï¬¬¬ø÷÷觤ägbèljéijéikêioéjpéiréhtèivéiwéiyèi{éi~éi€éj‚â`zÕ–¤íîí¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ®®®ùùû•˜åciåjréiuéiwéiyêjzéi|éhéièiƒéi…éi†èi‰éi‹éjé_†à¦µØééç››²»»üuxädkåjréiuéiwéiyêj{éi|éhéièiƒéi…èi†èi‰éi‹éjé]ƒÞ…“Ú²²ä––¶ÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â™™º¸¸ünqâflæjréjuéiwêjyéj{éi}éhéièiƒéi…èi‡éj‰éi‹éié\ÜšÞ¨¨Ö«««ùúúõàßãywçhièikéhnéipéiqèiséiuèixèiyéi{èi}éiéièg‚Øo…äÑÕôõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿñññ­­­þþýÕÖópwãhrèivèiwéizéi}éi~èiéiƒèi„èi†èiˆèiŠèiéf‹çv“×Üàéîîìšš±ÁÀÿž òfmãisèivèiwéizéi}éi~èiéiƒéi„èi†èiˆèiŠèiéf‹çh„Ö©¬ëµµè––µÁÁÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±â˜˜ºÁÁÿ–˜îeläitèivèixéi{éi}èièiéiƒèi„èi‡èi‰éi‹èiéeŠæm†Õ°±ð©©Ø«««ùùùýýýñÆÆèsuêkoéipéiqéjsêiuéixéjyéj|éi~èi~éi‚ëk…âoˆÛµ½øøøööö¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿñññ­­­ýýýüüý¹¾ïo{èkzëizéi|éjéiêiƒéj…éi‡éiˆèiŠèiéj‘ër“àÀÉÝûûûîîíšš±ÀÀÿ»¼üŽ“îkxék{êizéi|éjéiéiƒéj…êj‡éi‰èiŠèiék‘ëjŠß–žß¼¼üµµè––µÁÁÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¹¹û‡ìjxék{êizéi|éj€éiéiƒéj†éi‡éj‰èi‹éjék‘ëmŠÜ£â¾¾ý©©Ø«««ùùùÿÿÿüúúð½¾î€…ípzêluèisèhuéixéizèh|èi~êl„îqŒèz’ܬ·óòòÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿñññ®®®ýýýÿÿÿ÷÷û²¹ï|‹ïpƒík€éhèh‚éi…éi†éiˆèiŠèlêr˜î}å¶ÁÝöööÿÿÿííìšš±ÀÀÿ¿¾þ·¸ûŽ•ïv…îp„ìk€éhèh‚èi…èi†éiˆèi‹èm‘ër˜ít“呜޹¹÷¿¿ÿ´´è––µÁÁÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¿¾þ´µù‰’îu…ïoƒìk€éhèh‚éi…èi‡éi‰èi‹én’ër˜íu’â—Ÿà»»ùÀÀÿ©©Ø«««øøøþþþþþþüûûñÒÔî¦ò‰˜ðzŠìrƒíoƒíp…ís‰ð{•ð‡£ã”¨ÞÂÈôôóþþþþþþõõõ¬¬¬ûûûþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýþþþñññ­­­ýýýþþþÿÿÿùúüËÐð™«î‡¡òx“ïqŽíoŽípís•í| ðˆ¬ï—°áÈÐà÷ööÿÿÿþþþííìšš±¿¿þ½½ý¿¿ÿººû£ð‰œï„Ÿòx“ïrŽìpíp‘ít–í}¡ð„§ï„œàœ¢á¹¹÷¿¿ÿ¾¾þ´´è––µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÀÀþ½½ý¿¿þ¸¹úš ï‰œïƒòw’ïqŽípíq’íu—í£ñ„§í…›ß ¥ã»»ù¾¾þ¿¿þ©©Ø«««ùùùÿÿÿþþþþþþýÿÿ÷îïðÑÖì´À隸ð¡·îŸ¸ë¢¹å®¿ãÆÎìäæúûûÿÿÿþþþÿÿÿõõõ¬¬¬ûûûÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþÿÿÿñññ­­­ýýýÿÿÿÿÿÿÿÿÿþþýëíöÍÖï±Ã쥿ê°ÃäÉÒäèéíüüûÿÿÿÿÿÿÿÿÿííìšš±¿¿ÿ½½þ¾¾ÿ¿¿ÿ½½ý±³õ¢¬ï—«í–¯ï”²ï”³î“¯ê•¨ãž§ä¯°î¼¼û¾¾ÿ¾¾ÿ¾¾ÿ´´è––µÀÀÿ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ±±ã˜˜ºÀÀÿ½½þ½½þ¾¾þ¼¼ü¯²ô¡«î—«í–°ï”²ï”²î“­é–§ã §ä±²ð½¼ü¾¾ÿ½½þ¿¿ÿ©©Ø¢££ëììðññïððïðððññðññïññëêêæàâãÜßáÚÝâÝßæææíïïñòòñòòïððïðððññçè裣£íííðððïïïïïïïïïïïïïïïðððñññðððððððððïððïïïðððððððððïïïðððää䥥¥ïïïððððððïïïðððñðððïïèèêßáåÚÞãÚÝâÝßâææçîîíðððððððððððððððààß””¨ººñ¸¸ñ¹¹ñ¹¹ñ¸¸ñ¹¸ñ··ï²²ë­°æ¬°äª®ã¬®ä±±è·¶î¸¸ñ¸¸ñ¸¸ñ¹¹ñ¹¹ò®®Ü¬¼¼ò¹¹ñ¹¹ñººñººñººñ¹¹ñ¹¹ñ¹¹ñ¹¹ñ¹¹ñººñººñ¹¹ñ¹¹ñ¹¹ñ¹¹ñ¹¹ñººò¬¬×““°¼¼ò¹¹ñ¹¹ñ¹¹ñººòººò¸¸ï²³ê®°æ¬°ä«¯â­¯ä³³é¹¸ð¹¹ñ¹¹ñ¹¹ñ¹¹ñ»»ò¤¤Íwnn«˜˜¯››®šš®šš®šš®šš¯››¯››¯››¯››¯››¯››¯››¯››¯››¯››®šš®šš¯››©––wtt­­­¯¯¯®®®®®®®®®¯¯¯¯°°¯¯¯­¬¬©¥£©¦¤­¬¬®¯¯¯°°¯¯¯¯¯¯¯¯¯®®®¯¯¯¦¦¦xxx®®®¯¯¯¯¯¯®®®®®®®®®®®®¯¯¯°°¯°°¯°°¯¯¯¯¯¯¯®®®®®®®®®¯¯¯¯¯¯¯¯¯£££wwz§§°¦¦°¦¦°¦¦°¦¦¯¦¦¯¦¦°¦¦°¦¦°§§±§§±§§±¦¦°¦¦°¦¦°¦¦¯¦¦¯¦¦°¦¦°™™ pp}““°’’¯’’¯““°““°““°’’¯’’¯’’¯’’¯’’¯““°““°’’¯’’¯’’¯’’¯’’¯““°††qq””±’’¯’’¯’’¯““°““°““°’’°’’°’’°’’°’’°““±““°’’¯’’¯’’¯’’¯““±€€•¬ø¿¿þ¿¿ý¿¿ý¿¿ý¿¿ý¿¿þÀÀþÀÀý¿¿ý¿¿ý¿¿ý¿¿ý¿¿þÀÀþÀÀþÀÀý¿¿ý¿¿þ¿¿õ¼¼¬¡¡úûûþþþýýýýýýþÿÿúõôîÚÖ㺳峫ޥ›ß¥žä¯«ãº¶ðÝÛûøøþÿÿþþþýýýþþþððð­­­üüüþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°¯þþþþþýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèæ››´ÁÁþ¿¿ý¿¿ýÀÀþÀÀþÀÀþ¿¿ý¿¿ý¿¿ý¿¿ý¿¿ýÀÀþÀÀþ¿¿ý¿¿ý¿¿ý¿¿ý¿¿ýÀÀþ²²â™™¹ÂÂþ¿¿ý¿¿ý¿¿ýÀÀþÀÀþÀÀþ¿¿ý¿¿ý¿¿ý¿¿ý¿¿ýÀÀþÀÀþ¿¿ý¿¿ý¿¿ý¿¿ýÁÁþªª×­ù½½þ½½þ½½þ½½þ½½þ½½ÿ¾¾ÿ¾¾þ½½þ½½þ½½þ½½þ½½ÿ¾¾ÿ¾¾ÿ¾¾þ½½þ½½ÿ½½ö»»­¡¡ûüüÿÿÿþþþýþýïØÒÝ ”Ûˆyásä{nåxnæwnävnßxsÚ}{ÝŸœñÝÜþÿÿþþþÿÿÿñññ­­­ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ±±ã˜˜ºÀÀÿ½½þ½½þ½½þ¾¾ÿ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ½½þ¾¾ÿ¾¾ÿ½½þ½½þ½½þ½½þ¿¿ÿ©©Ø­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö»»­¡¡ûüüÿÿÿýûûèû×~kã{hè|jéyjêviétiêriéoiènjçljàihÕsrêÈÈýýýÿÿÿñññ®®®ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¡¡ûüüþþþëÇÀ×r]æyeé{jéyjèviéuiériépiénièlièjiêjkãceÔaeêÎÏþþþñññ­­­ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¡¡ûýýóàÜÙzfåwcéyiéxiéviètiériépiénièlièjjèijèikéioâ^eÓotôèèñòò­­­ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¡¡úûúæªáq]è{jéxiéwiéuiériéqiéniémjékjèijèiléinéipéjqÜZcá­±ðññ®®®ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþííí°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¢¢õèæßqæxfèxièuiètièsièpièniéliékièijèikèinèioèirèjsäbnØw‚éâ㮯¯ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþííí°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¢£íÍÇßs`èyièviétjésièpièniémièkièijçikèimèipéjrèitèivèhvÚbpÞÆÉ®¯¯ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö»»­¢¢å®¥àm[éwjéuiésiéqiéoiémiékiéjkéjlèimèioéirèitéiuéiwéiyÜYkÔ§®­¯¯ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö»»­¢¢á¡˜áiYéujéshèphèoiémièkièijéiléinèioéiqéiséhuéixéiyèi{ÜVkЛ¤­¯®ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö»»­¢¢äª¤áh\étjèqiépiéniékiéijéiléhmèhoèjréisèiuéixéizéi|êj~ÛYoУ«¬®®ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿììì°°°ÿÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±â˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­££íÉÆài`èphèniémiékièijéilèimèipèjrèisèitéiwéizéh|èi}èg~×_u־í¯¯ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¢¢ôæäàwpçlfèmiéjiéjjèiléjnéjqéiréitèiuèixéizéi|éi~èi€çd}Óq…àÙÛ®¯¯ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþííí°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¡¡úúú裠ägbékjéijéilêioéjpèiréhtèivéiwéiyèi{éi~éi€éj‚à`zס­ëìì®®®ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþííí°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±ã˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¡¡ûýýõÞÝãxwèhhèiléhnéipéiqèiséivèixèiyèi{èi}èi€éièg‚×uŠçÚÝñññ­­­ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ»»­¡¡ûüüýýýðÅÅètuëkoéipéiqéjsêiuéixéiyéi|éi~èi~éi‚ëk†às‹Ý¿Æùúúñññ­­­ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþèèç››µÀÀþ½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ±±â˜˜ºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö»»­¡¡ûüüÿÿÿüùúð½¿î†îq{élvèiséhvéhyéhzèh|èiëm†îrå~•Þ¶¿öõõÿÿÿñññ®®®ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö»»­¡¡ûüüÿÿÿþþþüüüòÔÖòŠšð{Œît…îq…îq‡îuŒð~˜ïŠ¥áš«àÊÏ÷÷÷þþþÿÿÿñññ­­­ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù¾¾ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö»»­¡¡üüüÿÿÿþþþÿÿÿþÿÿøðñðÔÙì¸Ä謁碌ꧽä´ÂäÌÓîêëüýýÿÿÿþþþÿÿÿòòò®®®þþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿèèç››µÀÀÿ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ±±ã˜˜ºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø¡ˆˆè¶¶í¶¶ì¶¶ì¶¶ì¶¶ì¶¶í··í··ì¶¶ì··ì··ì¶¶ì¶¶í··í··í··ì¶¶ì¶¶í¶¶ä³³¡——èêêìííëììëììëììëííêììçççâßàßÚÜÞÙÛßÜÝãääéëëìííìííìííëìììííßàà¡¢¢êêêììììììëëëëëëëëëëëëëëëìììììììììëëëëëëëëëëëëëëëìììììììììÛÛÛ¤¤¤ìììëëëììììììëëëëëëëëëëëëëëëííìììììììëëëëëëëëëëëëëëëìììììì××Ö’’¨··íµµìµµì¶¶í¶¶í¶¶íµµìµµì¶¶ì¶¶ì¶¶ì¶¶í¶¶íµµìµµìµµìµµìµµì¶¶í¨¨Ó­¹¹í¶¶ì¶¶ì¶¶ì··í··í··í¶¶ì¶¶ì¶¶ì¶¶ì¶¶ì··í··í¶¶ì¶¶ì¶¶ì¶¶ì¸¸í¡¡Ézll¯’’³””²””²””²””³””´••²““°‘¬ŒŠ¬ŒŠ°‘²““´••³••³””²””²””³””­‘‘znn°šš²šš±šš±šš±šš±šš±šš²››²œœ²››²››²››²››±šš²››²››²››±šš²››©””zww±±±²²²²²²±±±±±±±±±±±±±±±²²²²²²²²²±±±±±±±±±±±±±±±²²²²²²²²²¦¦¦|||²²²±±±²²²²²²±±±²²²³³²°°°««¯¥£«§¦¬¯®°±±±³³²²²±±±±±±±²²²²²²¢¢¢||««³««²««²««³««³¬¬³¬¬³©©±¤¤¯œ« Ÿ­¨¨±««³¬¬³««²««²««²««²««³™™Ÿtt‚––³””²””²””²””³””³””³””²””²””²””²””²””³””³””²””²””²””²••³˜­‘‘ùÀÀÿÀÀþÀÀþÀÀÿÁÁú¹¸î¨£ã˜å˜à’ˆßˆä”ã”捻û¹¹ÿÂÂþÀÀþÀÀÿÀÀö¾¾®’’üÀÀÿ¿¿þ¿¿þ¿¿þ¿¿þ¿¿þ¿¿ÿÀÀÿÀÀþ¿¿þ¿¿þ¿¿þ¿¿þ¿¿ÿÀÀÿÀÀÿÀÀþ¿¿ÿ¿¿óºº¯¥¥þþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðïùÐÍ쮫⧥嚗ߞœá¨¨ä¶¶äÛÜñùùüÿÿÿþþþÿÿÿÿÿÿçççµµ´ÿÿÿÿÿþÿÿþÿÿÿÿÿÿïîøÎË뮫⧥囗ޠžá¨¨ã¹¸åÞÞñûûüÿÿÿÿÿþÿÿþÿÿÿääâ¹ÃÃÿÀÀþÀÀþÀÀþÁÁÿÁÁÿÁÁÿÀÀþÀÀþÀÀþÀÀþÀÀþÁÁÿÁÁÿÀÀþÀÀþÀÀþÀÀþÂÂÿªªØ­ù½½þ½½þ¾¾ý½½í£Ü…xÜ€pâ€qäznåxnæwnävnàwpÚspÛ|yí žþ¾¾þ¾¾þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþþþþÿÿÿúúüÇÄé‰Û{uÝtqâolänmæmnæmpärußz}Ú›žÜÞßñÿÿþÿÿÿþþþççç´´´þþþýýýþþþùøüÿ莇ÛzuÝtqãomånmåmnænpäsuß{~Ùž¢Ýâãóÿÿþþþþþþþãã✜¹ÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù¾¾þ¾¾ý¼¼è–×r_ã{hè|jéyjêviétiériéoièniçmjâjiÕ``çý¼¼ÿ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾ò¹¹®¤¤ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿÿÿþööû®¨ãoeØpiåojèmiékiéjjéilêiméioèkrçgpàszÕÌÎìþþþÿÿÿççç´´´ÿÿÿÿÿþôôú©¢áneØqiåojèmiékiéjjéilêiméjoèjsçfoßw}ÖÒÓíþÿþÿÿÿãã✜¹ÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù¾¾þ¾¾ë™’ØjTæyeé{jéyjèviéuiésiépiéniélièjiêjkåehÔSVç’“þ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾ò¹¹®¤¤ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿüûý±«ædYÙogèojémjékièjjéiléinéipéiréitéjvêaoãeqÔÕØíÿÿÿççç´´´ÿÿÿûúýª¤ädYÚohèojémjékièjjéiléinéipéiréitéjvê`náiuÓÛÞïÿÿÿãã✜¹ÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­ù¿¿ôª¦ÙlXåwcéziéxiéwiètiériépiénièlièjjèjkèikéjoãahÓV\ñ§¨ö½½®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°ÿÿÿÎËîi^Ùnfçoiémiékiéiièikéioéipéiqèjsèiuèiwèjzé\oàw„Õïð÷èèç´´´ÿÿÿÇÄíg[Ùnfçoiémiékiéijèikéioéipéiqèjsèiuèiwèjzé[nß}ŠÖóôùãã✜¹ÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ø½½ç‰~áp[èzjéxiéwiéuiériéqiéniémiékjéikèjléinéipéjrÝYcÞ|ó»»®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°ùøý’‹âh_äpjèmiékiéjjéiléiméipéiréitéiuèiwèiyèi{éi|è[oÚ»Âæéèç´´´÷÷ý‹„âi`äoiémiékiéijéiléiméipéjréitéivèiwèizèi{éh|è\pÙÃÊèää✜¹ÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø®’’ó²°ßrcæxfèxjèuiètièrièpiènhéliéjièijèikéinèipèirèjsådq×]h묭®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþííí²²±ÞÛõpgÞmgçmièkièjjèikèilèinèiqéitéiuéiwèiyèizèi|èj~è`xビÚßßá··µØÖõmdÞmhçlièkièijèikèilçinèiqéitèiuéixèiyèi{èi|èjè_wኚÛÜÝݹÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø®““í¡œßn[èyjèviétjésièpiéniémièkièijçikèiméipéjsèitèivèixÛXfߖ𮑑û¿¿þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì²²°¼¸íe^àmièkjèjjéikéimèioéiqéisèitèiwèiyèi{èj~éi€èj‚ègèh€ÚÈË×¶¶´µ±íe_àmièkjèjjéikéimèioéiqéisèiuèiwèiyèi{èj~éi€èj‚èfçl„ÚÈËÔºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø®““ä†àjXèwjétièsiépiéoiémièkiéikéjlèimèioéirèitéiuéiwéizÞVhÖ‡­‘‘û¿¿þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°¯š–äb]âljéijéiléiméioéiqéirèjuéjvéiyèi{éi}éi€èi‚éiƒéh…éZyÛ­µÎ³³³“äc^ãljéijéiléiméioéiqèirèiuéivéiyèi{éi}éi€èi‚éiƒéh…é\zÚ°·ËžžºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø®““á…}àgWéujéshèphèoiémièkiçijèiléinèioéiqéiséhuéiwéiyèi|ÝUkÒw‚¬‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾ò¹¹®¤¤ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí®®¯Œ‹á`]ãjjéhkéhmèioèiqéirèitèiwéixéizéi|éi~éhéiƒéi…éi‡èVwÚ£­Ë²±²†„áb^ãjjéhkéimèioèiqéisèitèiwéixèi{éi}éi~èhéi„éi…éh†èWxÙ§¯ÈŸžºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø®““ä‡àfZétjèqiéoiêniékiéijéiléimèhoèjréisèiuéixéizéi|êj~ÜVmÓ~ˆ¬‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾ò¹¹®¤¤ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°¯š˜å`_ãjléiméipêiqéiséitéiwéhyéhzéj}éièièi„éi†éi‡éi‰ê[|Ù«´Ë´³³“‘äa`äjléiméjpêiqéiséitéiwéhyéh{éj}éièièi„éi†éi‡êi‰é\}Ø®µÈžžºÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø®““í¡žße\èphèniémiékièijéilèimèjpéjrèisèiuéiwéizéh|èi}èh~ØVmÙ“™­‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾ò¹¹®¤¤ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿììì²²°¼¼î_aàiméinéiqéiréisèiuéixèi{èj}éièièiƒéi†éhˆéiˆèf‰èf…ÖÄÈÒ·¶´µµí_`áiméinéiqéiréisèiuéixèi{èi}éièièiƒéi†éhˆéi‰èeˆçj‰ÕÅÈκÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø­’’ó²±àlfælfèmiéjiéjjéiléjnéjpéiréitéiuèixéizéi|éi~èi€çe~Ó^rã§©®’’û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì²²°Þßõjmßglèipèiréjuéiwéjxéjzéi}éi€éièiƒèi…éi‡éi‰éj‹èa‡å€™ÓÙÚÛ¶¶µÙÚõgjßhmèipèjréjuéiwèjxéjzéi}éi€éièiƒèi…éi‡éi‰éj‹è`†ä‡žÔ×ØØºÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ø½½ê‰‡ãfbèkjéijéilêioéjpèiréhtèivéiwéiyèi{éi~éi€éjƒá_yÖ{‡ï··®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþííí°°°ùùý•˜æciäjrèiuéiwéiyêj{éi}èhéièiƒéi…èi‡èi‰éi‹éiŒé`…Ý´ÀÜååä´´´øøýŽ‘ädjåjrèiuéiwéiyéj{éi}éhéièi„éi…èi‡èj‰éi‹éiŒéa†Ü¼ÆÞâáß¹ÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù¿¿÷®­äpnçhièiléhnéipéiqèiséiuèixèiyéi{èi}éi€éiègƒØf{梥õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°ÿÿÿÖØóryähsèivèixéi{éi}éièiéiƒéi…èi‡èiˆèiŠèiŽéf‹ç›Öçéîèèç´´´ÿÿÿÏÒñpwähsèivèixéi{éi}éièiéiƒèi…èi‡èi‰èi‹èiŽéfŠæ†žÕëíñãã✜¹ÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù¾¾ý¾¾òŸŸèprëlpéipéiqéjsêiuéixéiyéi|éi~èiéi‚ìl‡àjƒÝ’™ùººö¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþììì°°°þþþüüý½Âðq~ék{ëizéi|éjéiéiƒéj†êj‡éi‰èi‹èjék‘ëy—ÝÎÔáýýýççç´´´þþþûûü·¼îp}ék{ëizéi|éjéi‚éiƒéj†éj‡éj‰èi‹èjŽék‘ë}™ÜÓØãþþýãã✜¹ÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù½½ÿ¾¾ý¼¼ñœî{€îs}ênxèitèhuèhxéizèh{èiën‡îtŽåu‹Þ—õ··ÿ¾¾õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½ò¹¹®¤¤ýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþííí°°°þþþÿÿÿ÷øüºÀð€Žîr†íl‚êhèh‚èh…èh†éhˆèj‹éo“ìtší„¡âÄÍàúúùÿÿÿççç´´´þþþþþþõöûµ»ï~îq…íléhèh‚èh…èh†èhˆèj‹éo“ìu›í‡¢áÉÐáûûúÿÿÿãã✜¹ÀÀþ½½ý½½ý½½ý¾¾þ¾¾þ¾¾þ½½ý½½ý½½ý½½ý½½ý¾¾þ¾¾þ½½ý½½ý½½ý½½ý¿¿þ©©Ø­ù¾¾þ¾¾þ¾¾ý½½ó©ªî—ò‰˜ñ~îw‰îsˆïtŠïwð™î‡¡á‡—ᜠ÷¹¸þ¿¿ÿ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾ò¹¹®¤¤ýýýÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿííí°°°ÿÿÿþþþÿÿÿûûüÒÖñ ±î‹¥ò|—ðu’îr’îs•îwšï‚¦ðŽ¯í¢¶ßÕÚäúúúÿÿÿÿÿÿççç´´´ÿÿÿþþþÿÿþúúüÎÓñž¯ïŠ¥ò{—ðu’îr“îs•îx›ïƒ¦ñŽ¯ì¤¸ÞÙÝåüûúþþþÿÿÿãã✜¹ÁÁÿ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¿¿ÿ¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þÀÀÿ©©Ø®ú¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¿¿ù·¸òª®í¨ïš«ï™­í˜®ê–«å—¥å¡§ð±±ý½½ÿ¿¿ÿ¾¾ÿ¾¾÷¼¼¯‘‘ý¿¿ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¿¿ÿ¿¿ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¿¿ÿ¿¿ÿ¿¿ÿ¾¾ÿ¾¾ó¹¹¯¥¥þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîîî±±±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñòøÖÝñºÊí®Åï©Äï¨Åî¬Åê»ÊãÕÛçðñóÿþþÿÿÿÿÿÿÿÿÿèèèµµµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðñøÔÜð¹Êí­Åï©Äî¨Åí­Åé¼ËäÖÜçòòôÿÿþÿÿÿÿÿÿÿÿÿääãºÁÁÿ¾¾ÿ¾¾ÿ¾¾ÿ¿¿ÿ¿¿ÿ¿¿ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¿¿ÿ¿¿ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿÀÀÿ©©Ù††â³³ç³³ç³³ç³³ç³³ç´´ç´´ä±±ß¬­Ýª«Û©«Üªªà®®æ³³èµ´è´´ç³³ç³³è³³ß±±ž‡‡å´´è³³ç³³ç³³ç³³ç³³ç³³è´´è´´ç´´ç´´ç³³ç³³ç³³è´´è´´è´´ç³³è³³Ü®®ž——åæææççæççæææææææææææææçççèèçèèçèèæççæççææææææææææççæççæççÖ××   ææææææææææææææææææææåáááÚÛÝ×ÙÛÖØÛÚÚÜàààæååææææææåååæææçççÑÑѤ¤¤çççæææææææææççççççæååáááÚÛÝ×ÙÛÖØÚÚÛÜáááææåææææææåååæææçççÍÍÍ‘‘©µµè²²ç²²ç²²ç³³è³³è³³è²²ç²²ç²²ç²²ç²²ç³³è³³è²²ç²²ç²²ç²²ç´´èžžÄ|mm³••¶––¶––¶––¶––¶––·——·——¶––¶––¶––¶––¶––·——·——·——¶––¶––·––°““}nn´––·––¶––¶––¶––¶——¶——µ•”³’‘®Œ‰®ŒŠ³’‘µ””·——·——·——·——¶––·––­‘‘}ppµœœ¶››¶œœµ››µ››µœœµœœ³™™²—–­‘®’²——´š™¶œœµ››µ››¶œœ¶œœ¶œœ©““{{¶¶¶µµµ¶¶¶¶¶¶µµµµµµµµµµµµ¶¶µ¶¶¶¶¶¶¶¶¶µµµµµµµµµµµµµµµ¶¶¶¶¶¶¥¥¥¶¶¶µµµµµµ¶¶¶¶¶¶¶¶¶µµµµµµ¶¶µ¶¶µ¶¶µ¶¶¶¶¶¶µµµµµµµµµµµµµµµ¶¶¶¢¢¢‚‚…±±·°°¶°°¶°°¶±±·±±·±±·°°¶°°¶°°¶°°¶°°¶±±·±±·°°¶°°¶°°¶°°¶±±·––𮑑ûÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÁÁÿÀÀÿÀÀÿÀÀ÷¾¾¯’’ýÁÁÿÀÀÿÀÀÿÀÀÿÁÁú¶µì¤žâ•‹å–à…á‡ä’Œâ’û¹¸ÿÂÂÿÁÁÿÀÀÿÀÀô¼¼°““ÿÂÂÿÀÀÿÁÁÿÀÀÿÀÀùµ³ì£â”‹å–à…á‡ä‘Œã’Žï¤£ü¹¹ÿÁÁÿÁÁÿÁÁÿÁÁ︸²ªªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèèèµµµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿããã¹¹¹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÙØ­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½þ¾¾ý¼»ê–Û‚tÜoãqåymæwmævmåumávpÛrpÚzwížþ¾¾þ¾¾þ½½òºº¯’’ý¿¿þ½½ÿ¿¿ü»ºéš“ÛtÝoãpåymæwmævmåumávqÚrpÚ{xî¡ þ¾¾ÿ¿¿þ¾¾í¶¶±©©þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾ÿ¾¾üº¹ä„Ør^å|iè|jéxiêviétiêqiéoièmiçljâihÕ__掎ý¼¼ÿ¾¾òºº¯’’ý¿¿ÿ¾¾û¹¸ãŒ€Ør^å|iè{jéxiêviétiêriéoièmièljâhhÕ``è’‘ý½½þ¿¿í¶¶±©©þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘û¿¿þ½½è’‰ØjTçzgé{iéxjèviéuiériépiénièlièjiêjkåehÔSVç“”þ¾¾òºº¯’’ýÀÀý½¼æŽ„ÙjTç{hé{iéxjèviéuiêriépiénièliéjiéjkädgÓTW阙þ¿¿í¶¶±©©þÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿççç´´´ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘üÀÀñ¥ŸÙjUæyeéyiéxiéviétiériépiénjèlièjjèikéiléioãahÓW]ò©ªò»»¯’’þÁÁð¡›ÙiTçyféyiéxiéviètiériépiénjèlièjjèikèiléjoã`gÔZ_ô­®í··±©©þÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿççç´´´ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘ú½½å„wâr]èzjéxiéviétiériéqiéniéljéjjéikèiléinéiqéjrÝYcà„𹹯’’ü¼¼ä€rãs_èzjéxiéviétiériépiéniéljéjjéikèiléinéiqéjrÜXbⅉ춶±©©þÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿççç´´´ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘’ô¯¬ßp_æygèxièuiètièrièpièniéliéjièijèikèinèipèirèjtäcpØ_j謭°““õ­©ßo^çyhèxièuièsièrièoièniéliéjièijèikèinèipèirèjtäboØcm嬬±ªªþþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®’’í—ßn[èyjèviétjérièpiéniémjèkièijçikèimèiqéjséitéivèiwÛXgÝ—›°””í™’ßn\èyjèvjétjérièpiéniémièkièijèikèimèiqéjséitéivèhwÚYgÚ™›±ªªþþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘’剀àkZèwjétièrièpiéoièmiékiéjkéjlèimèipéirèitéivéiwéizÜTgÓ‚‰¯’’å…{ál[éwjétièrièpiénièmiéjiéjkéjlèimèipéirèitéivéiwéiyÛTfÑ…‹°ªªþþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘’âyáhYéujéshèphèoiémièkièijéiléinèipéiqéiséhuéixéizèi|ÜTiÑ{„®’’â}tâj[éujéshèphèoiélièjièijéiméinèipéiqèiséhuéixéizèi|ÚShÎ~†±ªªþþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘’劄ág[étjèqiéoiémiékiéijéilèhmèhoèjrèisèiuéixéizéi|êj~ÛUlу‹®’’å†áh\étjèqiéoiémiékiéijéilèhmèhoèjrèisèiuéixéizéi|êj~ÚTkÏ…Œ±ªªþþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®’’ße\èpièniéliéjièijéilèimèipéjrèisèiuéixéizéi|èi}èg~×WmØ—›°””àd[épièniéliéjièijéilèinèipéjrèisèiuéixéizéi|èi}èg}ÖXnÖ˜œ±ªªþÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿççç´´´ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘’õ±°àkdçlgèmiéjiéjjéiméjoéjqéiréiuéiuéixéizêi|éi~éi€çd}Óbu⪫°““ö¯®àibèmgèmiêjiéjjéiméjoéjqéiréiuéiuéixéizêi}éi~éj€æb|Óew੪±ªªþÿÿþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿççç´´´ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘ú¾¾é‡„ãfbèkjéijéilêioéjpèiréiuèivéiwéiyèi{éi~éi€éjƒß]xÙ‚Œí··°’’ü¾¾èƒ€äfbèkjéijéilêioéjpèiréiuèivéiwéiyèi|éi~éiéjƒÞ]wڇ괴±©©þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘üÀÀö¬¬äpnèhièiléhnéipéirèiséivèixèizèi{èi}èi€éi‚èg‚Öi}ê§©òºº¯’’ýÀÀõ©©änlèiièiléioéiqéirèiséiwèjxèizèi{èi}èi€éi‚çf‚Öl~ì«¬í··±©©þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¿¿þ¾¾òŸŸèprëmqéiqèiréjsêivéixéiyéi|éi~èiéjƒìlˆßlƒß˜û¼¼òºº¯’’ýÀÀý¾¾ñœ›éoqìlqéipèiréjsêivéiyéjyéi|èi~èiéjƒìlˆÞm„ᜠü½½í¶¶±©©þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾ÿ¾¾ý¼¼òžî|îtênyèitèhvèhyéhzèh{éj€ìo‰îtãvŒà”›ø¹¹ÿ¾¾òºº¯’’ý¿¿ÿ¾¾ü»¼ñš›î{€ît~ênxèitèhvèhyéhzèh|éjìpŠîuâwŒà—ùººÿ¿¿í¶¶±©©þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½þ¾¾ý¾½ó©«î™ñŠ™ñ‘ïy‹ïuŠïvŒïy’ðœí‡¡ß‰˜ã ¤ùººþ¾¾þ½½òºº¯’’ý¿¿þ½½ÿ¿¿ý½½ó§©î˜ñ‰™ñ‘ïx‹ïuŠïvŒïz’ð‚숡߉˜ä¢¥ú»»ÿ¿¿þ¾¾í¶¶±©©þþþþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþççç´´´þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××®‘‘ú¿¿ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¿¿ÿ¿¿ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¾¾ÿ¿¿ÿ¿¿ÿ¿¿ÿ¾¾ÿ¾¾ÿ¾¾÷½½¯’’ýÀÀÿ¾¾ÿ¾¾ÿ¿¿ÿ¿¿ú¸¹ó«¯íŸ©ïœ¬ï›¯íš¯ê˜«äš¦è¤©ó´´þ¾¾ÿÀÀÿ¾¾ÿ¾¾ó»»°““ÿÁÁÿ¾¾ÿ¿¿ÿ¿¿ÿ¿¿ú¸¸ò«®íž©ïœ¬î›¯í™¯é˜ªäš¦è¥©ôµµÿ¾¾ÿÀÀÿ¿¿ÿ¿¿î··²ªªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèèèµµµÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿããã¹¹¹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØØØšƒƒÝ¯¯â°°á°°á°°á°°á°°â±±â±±á°°á°°á°°á°°á°°â±±â±±â±±á°°á°°â°°Ú®®š„„ß°°â°°á°°á°°á°°â±°á±°ß®®Ûª«Ù¨©×§¨Ø¨©Ü¬¬á°°ã±±â±±â±±á°°â°°×¬¬œ……ᱱⰰⱱᰰᰰⱰᰰޮ®Ûª«Ù¨ªØ§©Ù©©Ý­¬á°°â°°â°°â±±â±±â±±Ò¨¨——áââàáááââáââàááàááàááàááàáááâãáââáââàááàááàááàááàáááââáââÌÍÍ   áááààààààáááááááááàààààààààààààààááááááàààààààààààààààáááÈÈÈ£££áááàààààààààáááááááááàààààààààààààààááááááààààààààààààááá¾¾¾pp·˜˜»™™º™™º™™º™™º™™»™™»™™º™™º™™º™™º™™º™™»™™»™™»™™º™™º™™»™™´––€pp¹™™»™™º™™º™™º™™º™™º™™»šš»šš»™™»™™»™™»™™º™™»™™»™™»™™º™™»™™²””qqºšš»™™»™™º™™º™™º™™º™™º™™»šš»šš»šš»™™»™™º™™º™™º™™»™™»™™»™™®’’‚ttºžž¹œœºº¹œœºº·™˜µ–•°±’·˜—¸ššºº¹œœ¹œœººª’’„‚‚ººº¹¹¹¹¹¹ººººººººº¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹ºººººº¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹ººº¦¦¦‡‡‡ººº¹¹¹¹¹¹¹¹¹ººººººººº¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹ºººººº¹¹¹¹¹¹¹¹¹¹¹¹ºººžžž®‘‘ûÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÁÁÿÀÀÿÀÀÿÀÀø¾¾¯““þÁÁÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÁÁÿÀÀÿÀÀô¼¼±””ÿÂÂÿÀÀÿÁÁÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÁÁÿÀÀÿÀÀÿÀÀÿÀÀÿÀÀÿÁÁÿÁÁÿÁÁﺺ´••ÿÂÂÿÀÀÿÁÁÿÁÁÿÀÀ÷²¯êŸ˜á‘‡å“Šàƒâ†ãŽˆâ‹î¢ ü¸¸ÿÁÁÿÀÀÿÁÁÿÁÁê¶¶¶°°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿää人ºÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÙÙ­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²““þÀÀþ½½ÿ¿¿û¹¸å”ŒÚpÞoä~påxlçvlçulåtláupÛqoÙyví Ÿþ¾¾ÿ¿¿þ¾¾è³³´®®þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²””þÀÀþ¾¾ú¶´à…xÙr^æ|jé{jéxiéviésiêqiéoièmièljâhhÕ__è‘‘ý½½þ¿¿è´´´®®þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²””þÀÀü»ºâ†zÛlVè{hézjéxjèviétiériépiènièliéjiéikädgÔTW阙þ¿¿è´´´®®þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾òºº¯’’ýÀÀÿ¾¾ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿í··²““ÿÁÁ웓ÚiTçzhéyiéxiéviètiéqiépiénièlièjjèikèiléjpâ_fÔ[aö¯°è´´´®®ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾òºº¯’’ýÀÀÿ¾¾ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿í··²””ü»ºâ{låuaèzjéxiéviétiériépiéniéljéjjéikèiléinéiqéjrÜXb䈌紳´®®ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾òºº¯’’ýÀÀÿ¾¾ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿í··²••ô¨¤Þn\çyièwiètièsièrièoièmiéliéjiéijèilèioèipèirèjtãanÚfpá««µ¯¯ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²””씌ào\èyjéviésjérièpiéniêmjìlkëjkèikèinèiqéjsèitéivèhvÚZh×™›µ°¯þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··±’’ä€uâm]éwjétiérièpiéniémiÝed˜DE´RTèiméipéirèitéivéixéizÚSf·Œ´°¯þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··±’’âyoãk]éujérièpièniéliëlk§LM8Ücjéirèiséivéixéizèi|ÚRhˈ´°¯þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··±““æ‚{âi^ésjéqiéniémiéjiëjkÊ[^T%(€9>åhpéisèivéiyéizéi|éi~ÙUkÌ‰Ž´¯¯þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²””àd\èpièniélièjièijéilèjnãgnçiqèisèiuéixéizèh|èi~çe|ÕZoÓ›µ¯¯þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾òºº¯’’ýÀÀÿ¾¾ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿í··²””÷­¬ßhbèmhèliêjiéjjéiméjoéjqéiséjuéivèixéi{êi}éiéjäazÔk{ݪªµ¯¯ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾ÿ¾¾ö¼¼®‘‘û¿¿ÿ¾¾þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾ÿ¾¾òºº¯’’ýÀÀÿ¾¾ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿þ¾¾þ¾¾þ¾¾þ¾¾þ¾¾ÿ¿¿ÿ¿¿ÿ¿¿í··²””ý¾¾ç€}ägcèkjéikéilêioéjpéiséiuèivéixéizèi|éi~éiéiƒÜ]vÝŽ–æ³²´®®ÿÿÿþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿââ⸸¸ÿÿÿþþþþþþþþþÿÿÿÿÿÿÿÿÿþþþþþþþþþþþþþþþÿÿÿÿÿÿþþþþþþþþþþþþÿÿÿ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²““ÿÁÁõ¨§ånlèijèiléioéiqéirèitéiwéjxèizèi{èi}èi€éi‚æeÖqð¯±è´´´®®þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²““þÀÀý¾¾ñ››éorìlqéiqèiréjtéivéiyêjzéj|èi~èi€êjƒìlˆÜp„䡤ý¾¾è³³´®®þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²””þÀÀþ¾¾ý»»ò›œî|‚îu€ëoyèitèhvèhyéhzèh|ék‚írŒíuàyŒã¡ú¼¼ÿ¿¿è´´´®®þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××­ù½½þ½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½þ½½õ¼¼®‘‘û¾¾þ½½ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½þ½½òºº¯’’ý¿¿þ½½þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾ý½½ý½½ý½½ý½½ý½½þ¾¾þ¾¾þ¾¾í··²””þÀÀý½½ÿ¿¿ý½½ò©ªî‘šñ‹šñ€’ïzŽðwðxð|–ð„Ÿêˆ ÞŒ˜ç§©û¼¼ÿ¿¿þ¾¾è´´´®®þþþýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþââ⸸¸þþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýýýýþþþ×××®‘‘û¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿÀÀÿÀÀÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿÀÀÿÀÀÿÀÀÿ¿¿ÿ¿¿ÿ¿¿ø½½¯’’ýÀÀÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿÀÀÿÀÀÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿÀÀÿÀÀÿÀÀÿ¿¿ÿ¿¿ô»»°““ÿÁÁÿ¿¿ÿÀÀÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿÀÀÿÀÀÿÀÀÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿ¿¿ÿÀÀÿÀÀÿÀÀï¹¹³••ÿÁÁÿ¿¿ÿÀÀÿÀÀÿÀÀû¹ºó¬°î ªïž­îœ°í›¯éš«ä§ê©¬÷¸·ÿ¿¿ÿ¿¿ÿÀÀÿÀÀêµµ¶°°ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäää¹¹¹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙÙÙ’}}Ó§§×¨¨×¨¨×¨¨×¨¨×¨¨Ø©©Ø©©×¨¨×¨¨×¨¨×¨¨×¨¨Ø©©Ø©©Ø©©×¨¨×¨¨Ø¨¨Ð¦¦“~~Õ¨¨Ø¨¨×¨¨×¨¨×¨¨×¨¨×¨¨Ø©©Ø©©×¨¨×¨¨×¨¨×¨¨×¨¨Ø©©Ø©©Ø©©×¨¨Ø¨¨Í¤¤”Ö©©Ø¨¨Ø©©×¨¨×¨¨×¨¨×¨¨×¨¨Ø©©Ø©©Ø©©×¨¨×¨¨×¨¨×¨¨×¨¨Ø©©Ø©©Ø©©È¡¡–€€Øªª×¨¨Ø©©Ø©©×¨¨×¨¨×¨¨Ô¦¦Ñ££Ï¢¢Ï¡¡Ð¢¢Ó¦¥×¨¨×¨¨×¨¨×¨¨Ø©©Ø©©Äžž˜””ÖÖÖÕÕÕÕÕÕÖÖÖÖÖÖÖÖÖÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÖÖÖÖÖÖÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÖÖÖ¾¾¾œœœ×××ÕÕÕÕÕÕÕÕÕÖÖÖÖÖÖÖÖÖÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÖÖÖÖÖÖÕÕÕÕÕÕÕÕÕÕÕÕ×××µµµgridlock.app-1.10/Resources/aqua.tiff0000644000175000000000000002060207523137723016613 0ustar gurkanrootMM* ¬€ P8$ „BaP¸d6ˆDbQ8¤V-ŒFcQ¸äv=HdR9$–M'”JeR¸À !—%Á€Ä„s HG¹É ’“Ú„sŒe Ë„š¨@Psƒ aþ%6¬J:ND7 ¸n,>à@rcŠ9¶Î¼¢5Ê2ƒo*6ò±þ9À’”²éKŽ %K²YþJBÐs#Ã0‹ˆàD-sþ’à5µ1aœ†"“2öF” ’!‹0Ò³»¾î¿ƒù7Â%)­Hòl=.º’ÉŒàK ‘zÛŒrBàT2¼º5˵+¯TÔU=YST•mcPJnöçšÍ¼ÐåAî -#¹”òé:NÃÙ(ÇC›(¬/]gÚcBÒ´Qÿµ­œÏ.Èî[Ÿ0JuÅYÕtå]sBEÍuÕwMOIÜ·ˆ×x]N»Š1Ýôåïs¶N•Q/¶ó5w_B¶ú®€Á(Ö€5),  *vŽ-ªÊp¤¡ãg8!.ËÄÛÛ®|«pÔûeMÞYeë—™×uÙ|]—že~æµMù›^N._z_9Åí}T™ÕM€7Í}5œð„>ÛŠEªð˜dðñˆQËÓ‹ëŠÀBÐí,îÖ†$¤OLÁ7…!´J&UQÞWæá˜B]›î™îñ˜Þ×N¢è›î…yß[÷žpœÅÞúUþéºXK¦ò°bRÄà«d VRrÏÚïDŽÙÛîJàæÖ‰E*é"I”ÅS·Üy^k—eÛåQ½ç9¾ivî7Gƒáñþ‡½xýÿ‹ÃÞ™÷RyþMm%`а…©YØïu!Hb- tGñ¡¸Í¨ nø0BDöUuoÓ™fá»n½Ç…˜g?¾ïâxÙþêÎßë>h/-Å=ã¬W®1æ8ÆãšP„z§9´ 0æC>æLª>HBËá,Á,ª´s/h1ÁÆ·ÖŠ6 ÇŸÄJ^b¢m쩼¥Hfþ¼5Œ®ê7èuâ8p± æÃ¨çÞlGpÑÑÃÀ¸Ÿ£Û‹‰é=¥1¼mÁËØ Õd4 çÝ X> ?îcÍiÚ/¹-Æ$¯ R”,e±¡Û<×(—«Ê]îú98¦uÞt¬Ðú=Ähùb ׉éäÄ©rãúé‰oF ›pöõ…étsG~e½×¾ød‘[tÁ¬NIpæÑtKGÖÊgí7¥#»”o»?™M¬Ž.UÃh„ñd ±ˆrî\O8b<¼˜ |Ë©ù?“Jñ4Û„)’x2ÈŽ¡>8;4I1V%åÁ†ŸÀb' ¤ÜSÒ¢oÆiÉ % à”¯âsÎ[8¥Té–RÝÄNÖ;áÜIŸN6wÏI÷K%õ–Ó~ÓpÆ…‚ÑÒ cü½€'µ «µ<®ôê?ÏÙl†tQ¦Ä TíL¡Vb¤Ê§TòD¢ØkZ®¬ÕT~+Nµ«ŽéùMöç(} ¤ðæ’ÎëMKiSü¦©ÄÓºi=©Äñ§´æ›ÛY‡_­¤~®³þ½Wª‡`°!¥â£Øx¬×ìmŽ! åÑSÁ j¹Ö«¶zÐZ(aŸÝ(¯UN¸{ét?µ02µÖèñLëÄ÷¶’Ûªm­Ý{ nRŸWÔ·\(-<b⬀”„¥±—(ƒIE;À€„6 å×)å5V­ .Â4НÒK7v'6¥Ò¾8¼Ëe=o&!‰RÖÚ[™^oµ½Å8¡Rbº{}"x炎R¡ƒ‘Œ]@­Šbpñƒbðâš6@¸ˆJ hÁu¸>ÕÖùgé6´¸WUëI…§”zQ ´8+]z+~'Ä“âº_*á|qV/·˜Ã×\Û^Û” CYËcqþ1ÓÙ-&f¦"^L$“çhžË(ÉGläj”ÑxåF÷X^FXŽò•¿í#qY¬øŽ^ÇÜÅ{ô䂯òŸê3eŠóZé͇__lâp3™Ö4§`Öçˆ0ÀnB£y¯eD¥V³6êá E„.ÎÉÃ5“ é7‡£¦Ë[N¶mÃzñ.¦¾šÞ^ë{ªïžÝÍZ±Nn ì¯Õ¸‚q†SC³õÉPV@)±z6ÿÁ†•% ¯HÙnò‘ìûO•x4ì¼ÏhZØ™dÒÔ4ç/Þûo™¥þ,ã³qj}Ço±N2ãÛ‘-ò ´ÒÍúö°ö3ŒÈ)ÀJæøKE÷äŸÂZ&°aJAJ9þÌÙU–SG]-+\°áºj;ÄŒÇl8­µÄׯW>A¸õ-òÜÛ—Tõ­U×ù&ß8jCÔAŒ^1Ë™ AHNde‘1à†Æèðw¿ðžNÒjR]ÚÇÁ4—DáS×J[q§µ5éýK4[œÑÖöå{ë;‡ùNÅå\¦qŸýfà-{†²¦{*À癞îj;˜ÿrûó h½à.ܧÙÖ¦”ø(ÒúVÖÄW«ˆø}±¶µ¨âk4õï#ñ|·"Ûí×õÎÃò¾†3ŸýÛƒŽ, ]·\ï"¶³ƒ˜œöX% [2/}o;ÙŠ®t…íeM£áy{„ôŒ»Ã©‡¹§ÜOÅ|;pÍÏŽ®Ï&ÛÎBùʯϚùïœùnFù0䀯ä@”΋*ÎÀŒx lúbC:׬Œ¡î-†ÐÎtÉ®xÙ®òèk6ö Xá-0ï3®–¼Ïø÷ÏâͤÛL\ãŒòÐ Ðo£P„ú ÕíNj(P(js-ÜÞ×L„+ÃØÞ¡j,’j#n M…Í£ÐÆèj¾þŒþ ð­¦Ê¥ö÷ Ú«[°nâ«ÚÔÐïo†ë®®òP Þ¾n>äO&¾‘‹Q8&¸.΃.^ ndÞ"Xb`0ö°BRL”³/^…éÆè –PXöo°Ño ÷­¨ñ¢øM¶ÅM»o1Ï*Æ.ÁP‡žÕPò#ñ¾ß 1ì­bõO®<ZNÆ&FïºÐPPÀæj„DJ²“©P猨¤Ï`†°ÔþoîË0\µpâñæÿ±X¦O#1eÐ/ ù [ñyQ Q|:ñ‹уÑ“ ìåkˆíl-v$Eœ M18ü±°ýJ>» !«Jµ/ž’÷N˜Ó(çî¬Ìño‘Þù‹ aÑépPÿ±{æëpùQûNL챨(a£¨Ï‚ ÂB412ðD:Ò ed¾ï ެkƬk »ì;#ϵñ× DÍ é1Ýy1îÕqó±RËRÙ…Ó'1 &Ñ.°(úÌq§Rbc1!®#‹˜f0Ì–?±²m²3"®‚àŽüÒÒ11‹ÂëÆz0ØÓPrÓï÷$ø+Ó$°%.>¾Ñ %Ñ Íro&òkQý'~å95Œúƒ]€1cÈÀ†ûÂ6CQ ‚é)pHØ‘¶ànÿ*‰#ï#på’ºð²÷ðõ% g{sPòñéq.R_Rá-²tTŽE Q A½)P(3h Cüæ/J##Ö5Ï)$~üÃúJ°U*OÜàó!Ê_,¶–ñÆ÷è®3î2ÔŽ§:a:Po,ó·sEqÿ;ãe3]B²q4Pt2æ¡<¯TÉ”Ä3/I!5ÌŒ²Ør–ÊMÒ/*Ó¼N‰*/’¸¦,Á$N©2ÔN5AÎ-4Ó;:±y42ç'T'ó[C’Üì4>Jó]BÊD'-DŒî±4b@!/p«=¢&¹€æ ’zñ°›¤Ã0óŠèQK1ÔzÚKÂÿR>¼ïO+{3T9òÅO±²g:Ñ 4µCpBÓ¹J@×JóUÓÅDûRPœa!œ¸€” R Ïâ/7A19MS ¤¹?iRçðÒ•´u?´å?ñ[#±Ó9ÌB¦Î/•o4‡,Ž;HÕWÑ:³µP´›Qñ.T55³½Qô-<ƒ­R«+K„tí‚S¢2MëM{>€´³¬¤öSwNŒþ-¡@1WNõÆÓH EOP $o75€ãµ^³GJÑAô%Q5‰Q²]JòsQÓÁ5sÀJóÃQпD@•DSg µ¨ K(‚$*ÀÆÁ@cF¸\/ÞáâþH ŽÍ.pAdujêÓ•+ðè¯/øñçH±ï3­fû_uJ5`UùYQùYt­P¿RP&.€SKŒ"mubb]E´^:Ó~UTÚð/U¨9íjì½@“—+uO‘ß,5é‰-o^vsPõ Qvo4ô©Q”1`•!J¤K€shZ§R*Ñ¡S“p!J$õ]bò”@)KTôfèñFöÕQFÊÎáñÇ+’IO{,43–¿ln±´!f”—l•Æ•‘Xvu;– gmY`Öá7PäŽÉiÁ¼.€cnÖñLÄ×UVžÑ½q(ñR±#ÌÁkumdÑÑ]ôý-Á^ò[Aw¥B5—I÷©S»tÖÕsöát—µRKçg¤·5ÓaYÔF.Œñvb­LK/¢%À!i–/7· [¤¿JOUtìÒ°ßxÑÏËÛHI+T‹em·€0õHÖͲÕPÔ™IÕ‹`vÛ‚4©÷U{÷GRX/|4/uugØ;nbén²ï7×TÉoÖ–?vš.¦ÞK¶£IÔ•Páò8÷wýrW#€Ðu%Ms}WÖe%Ö_m6g_U—w³{×·Y–ß„7¹{Vqƒ˜?tøBÎxGnɪ34År|·á…—G÷êV¶6Ã7õ*ôodpê0k׎¦ÈAy-ˆ±oAðÿl—7m8—;QûY8+=‰×ÅŠ—Á‘9RLãa7]KnиLÙ…"oøX‘6…õ¾ ç;üÖÖw¿Ìp($* †Á ЈcZŠÄbÑtR5‹Åàæ8ädÖÞ‡I ’‰U½”Éå“ |¦Y1„Kf“3[žO!œIf°Iå +CÑfTzú‹H¥ÓÌnzmŸJ5»áÕ(#¾§V®Bíê¥^+_²X,UjÕž½E´Ù¬/ój£b%5™ÏñÍáþV©^à€@”à pÀF'Æ‚€B1Zï«ZÏòR÷2ccEsð¹‹I5Ã"q]LwM•Ç¡9¢I²Ë¶´,÷a¯ lw[Iÿ“ÃàÓ§s#þéÆªÚù•ší¯©e‡V*•ŸjÇØµYz};M®Íp±]h^{Œîßn–›Ù’“zò1k1¯ªÔã¿°Á 1Ð#2ƒ(w‡%«äÎ"Hæg!ÍCFÓÂÈŠÕCÜ Ö6ÐûpÚ6mã}6Ë|á&ÍÚrßűzŒ•9ÎL\œ9nC¨¬©1ÒÆ£(nâÔé;/"ºò¼*ÜŒð-L“&½’bØõÈòzâ9«î[äø¯Kà ¿°0;þ1 4À°8 d!z•«Ë6Ì‹M .…ˆ55mkpŒ6Sõ¸E6qdhŸÑDV›¸ñtdéÇ”‚¬è».d‘»ê܇NSò,ˆñÓK„•*½Ò‚Ô·¼ucÞs³+ºò¾çø0Ffsú!10 Ë3×ì0„)a àÍ«¤c-(T%PsÓs6© ùÐQ„OÐÍüT›[ÉÕDÜt|m<Æ’2çÓQüs<º²%M ¼”õá)IjSÑT®\§wÕ²–+<Ï|¶!/€Áœ^Ÿà¤%ŒHc^1,]3‰BÑ ³ÙVd;h¢sÄ>ÛÐv¥ ÛMu¹kÜ9=²à¸ªeÃsætŒwœÒ.E/]w,…gJõêë;·ü|ß·Åý¥i×ÛÛ'Ë…ûV¾ Îü5 - E+2ë‹@¬%‡7¯":<önI•P°ìû”DM¥™PíÕ´âQ·$aEGŽ+uvª·Eë£h ¿¡h±ö›Éi¥A©-²­W©àK®÷ Uyÿ­á œü¥ˆ0ìH1Šlð$ ¡j{†0n?3Üê0ÕÚ;Ã]>e±c—f1¿ŽœÜíÁR´u»ÄùwFo¡ò>½9yèú\‘íéõ%Q~`%õ«J:¯8­Õ¯Bîü/}9jÀ0]FÅvÈ‘…)ÏÜ%–{à vnÍåà¡‚6ÉÑ2ßyD‘¿ÀæhÌ£†f¨Å¸†zŽZ!ÍRe‚ªg&æK-‡•ö>rÎùœèï,N-UhÆÏÙIûg\a˜«øv!H1‰EŠÇ`!4ã,öôÞ{zeè©ä"ÇœàÙ²æ‹lýM½4b¥QûŽG¯uN½…ï!¥GÎ\¸¯¨Xú\Ë›ið¾®ønf£¤aEõ¯ŠÓXš¾ˆ‹ ¦Ôî[js€hU»š8ߢy%¿3‡˜ôW[yìíKè¼¥ÕŒ«Ú$bC)£"¦…GR7*†¨ùê*ï‘ÎÆ÷C |t¬, 5÷V˜ä‚¬XÈ€0'² ‰p ޒ瀶ü Š*L§˜²Îz3p/NP”¼½£+>”SŠPNhM(á,1„m2Îä¡ £›}iFO4§ Ï‘|.™Z¿!î‚Óu³ü&0Äbnw)Êgç4ÙDS[Œ±DÄø%6àŒÛŒNNNZ=£T¤ƒQ¨ëÂQHܬk–m*RúZÔg¬+sKí9º•ÁL}VÊàÄ«³ Ĥ% ¤9Ä‘ï"ÏxΉŠÀª-$¤Œ™9Sf.Éxºs¦üh'AwUצܪ^1¢6G Y.èi§ªZ>Yó'‹¡®fd¹ªÓæÛ¥;an % J€}D æ ‚J/G¸9Aë(μ7Fl‘£”eEÍÚ77¤Ý"Suz®YھОü Œê~6BIZ¼§„¦…1ÊzKYç,gÅ5žõܛǗàéè­/¦Ô ¬$Å„=зþf  o’mîÊU÷f¤\“µnIë79 ì¢Fë©Ç¯JTä-í]ï…©Óal©”ôžTÒ¹CÎTU‚´>ÍlFAœšj¨wƒb B•ˆ±U*Ç(J#6,y•bNàöÿu¢2‚±‚qÁ—¯8i*5¼v†SεC )rKÄV¦:âxVÒou°¶ÊتԮz­Â´#V| CÝlÞÿXGôD ­ö0ùTÊ–Z`=Í‹&ñmÎ ›u$ÓÐÃwtíáh)xk%¨_•Ž”ÚeØø—Åp­w¶8Ó[á[óAã®ÅÄø¤­ÈÞkgèþdÅP€AlØþƒ&›ŠƒŒ(<%\¼FC™Âex-iEdm“¢Õœ›—bp]Ì«I|©ÓQšÓ{Í ¯U®­X¡*^ºa=s33µÒ{Ó,Þf¯¦4 ai°˜ië/î~ÇóŠQj‚à¹ñbmY·V0–YŒ6~ÏlÛ92ÓŽÃó«0V]­içmk½rº™ê]»šï|´—í¶S¡j~Ì=Ç™ò!ëÍàb0ŒY )dŠà%ת™JÌA8¹u—NœU‡O/ ;:oÙ­8«„^ž«|°ŽÑÏ^ì]m’ƒXcñì!G°C­d¸Ý»Ã“ü‚!(X9Ñ ÂgÉ+£ðŽÊÒtƒK=›´Ð0ÓŒŒgwjR‰íXö橵ñƶ¤êГu]rÕõÄ™”¡ŒJ­Y1ï9«!)~îy˜{¿“õó€B–…Î(×ÙI5èüÁêJê8x¿³%/•n3jÞLA vÔ°­2Ûq÷üY|:‡MÍCr¤ÊrfgèµøçòMužû“M¤9ˆAkËЪÛöÊÝ{+ÀŽSÕ«¸bÒ=¬·—^Å£ït¯2ñ•š_GÅüZºtïÓÒ¯†ðpÕÐñóð D {Íšýç¦Ë×¼§Ë? „ìÞ]Ï=ÐÑ•g,ú.ßHyµ ô¥Bïwçic^ Û†xzÞ‹ß)wÅ>Ïo÷ïuàm¤·Íž#«[´Á»<…ü˜Ÿ3ÿ( È‚Ñèw³Šé‘{(°ƒcž³¸¹ºO¤óð4Ñ »ºÖµ ô#“¤µBô%“/J}6ûÃ<+Ý‹»'¸) – ¬ÈB$ ’¿üˆÆÀ)Óz2@-;E²£HÁûÏ»ƒœ¶‹0¹ãŸ«3N9ó-;Ðñ1©34¼Â<¸¸¹Ðº“ø§º]>Z¹.Á.1Aœ2¡€Ãh%7À”Aè¹;K>ñH9ÛÓ·-#„¸K'c£¶»·o?kö£ƒrÔ+A p‹’Ú˜ ÑЋá†14ºãȾT2Ĺ3“TH(Yƒ8œCp=й¾Ó¶9ëJ- t>âΣ"“©YîEK¼!j˜µ:×3;Ú±\)ÂÌ1l+§¸=ŠúÛ1t.Šû¯É0Âûþ4LFYØ Y¾sè@@¹ B¸‡øB|k= 02°±§,?!¹ÛÖGT«9ªœ›1+2-ˆ÷D#¿§”C¿|=Œ‹jˆ=‡¹ÇäG«üêCd¬fHëÓÀšu¶«ô5 Bkô¤'½”\3S©§¬_ˆBøƒÉxƒƒœÒ{‚c´Á{ý¾CH8€€€ P8$ „BaP¸`b9-—¬g¹iÎïžÞï÷úïFFã1wù­¼ç’É ryL¢M.’Kßò¹„ÖS5¹åÎùÄê[?œÎã9õ€ï›Q&Ôc]"RÞ’Ó§5 >­M”Q*ŽzÝR¥\™Ø*¶7}v£f±¹ÚÕ{-†×U=Ó’øÚÿ9½å«i Œµ{†#”$ sÀÃ0D3ÈdrY<~6 F%"1(Æ)Knùqÿ!Ž!4óœÆYL•kè³¥gKÚP¨û‰ÝfÅE©pwÕº]{l˜Z)Õ«e{a´X­¶NUC[PF—HíëYÞ¾TIÄcZ1=â=P! !”ø|~_?¦\÷Í!‹ÒSZ 1µhò8J#í:D#mj†Ù'­â€à'°j¤¶êŒ$¦8Ð{’ݪ0Û˜£Cî”6ê*íû¢ç©«2ˆ·ÄÈÉîí;‹š0%Îð”oÇøbBf0û‰OXĽsë#ÉL”‚2ÀB…è¤g-ð*í»„ã¸Ô#)ãXÜÂp|.Ÿ)IºŽœC0ÊãÄ*ôF°CêüÝijšÈ¿ñlS­q[›%Ú0¹¥ÒP»(oqJò  R$†Å1’]-KÓŒš0AÈÆ‰"ˆ´fÓ.hܵA´ÐD»ËÍ‚a1ÁÕtéBµ’± Vu¬ôÙÅ…vêΫ:¬Ñ¥ Ÿñ‘ÿCYk»X¯kéŒ^°, L2ÒˆßLÜ ĆSo8´³Æ5EKÙJî]îÔ £hÔ]6Î-aMIüC 9N‘`Îóú«6Ø6#ºŒ;6Mw¥ƒOhYèÇ$¡g<ïJÃÒ(Ú†Ò·M“åcûHR- D ”Z—§|†K6q[YÕ>ÔÀ·´» ¹n~DUÌì߸ø,ãWö…#QƒJŒY™Þ"ª”h’»Â‘zZùx¤R t€ä‹’2ùNå¹å2m6ÌËÑ(‹Fò¨‘;u6xŒghÅÞÙ\ »zè0+Z”aU´Ó2i˜´×«6ªY®‰ë~)­÷z¡fPI-¾Ç1Ü{¼ VÖBmÒtºwÏuMäW3:Ϧ–{Sœð·Ãg¶uK‰´¼f ËÍgèêi÷7êòŸ©bó¶EU†ñNÝ Š^=/É®ùÞ»Š.Ü…?XÖ8½³Ûyoä½×üÿÛ«ý[àžpÆ CXk­ˆcòòóVjîg„¡Ò8WÌñàŠÍt-YæA×–á$0qŸ(H4ùžDtp¬¨:GP³‹É{Zc¾1ZÇ_³²m¯é¸“`AˆNíý˜´Š}ÁË/ B1ø™ð´3†pïsÏ-òÁh+ áT*…0]ô¾v·âäW‹q^ÂÈ»_b~'³WâÆÁHR BQ€‡bþ#Ä;v‹vD8ýänÑò#6Öð¢TL(s¯YóŠÑ`‹XÌé$´Y‹°ª4I·Í'X’ÌYAìµøÚ;Ï”ÑÆ9·€µ]š“m½Û-çû eĹ—ÈY Y`9<ᮉÈÞ1ƒXÖÒ8g@Ðç3G|&YK*±IE5–sâaÎBfÈá¬EÎf¡(NJ bÜÐ9²ÆÔýå”ñv®Ö_Kyu=çÄù!.ò²8 ‹xRCƒ`''<éSÁŒRк„à9¢:‡P‘KA‚М•ÑÕ ¤ a·Lÿ'Õ)¥T­r@) 'ôþv´ÅüË8õMé6§3þZOè!bö¥•¢TSá/)-I§ô¾^ÔÉkSàQµ£UZ­U× TD­Uª±Wëa¬U޲VZÍYëE` dd!Z!bQ!j!r!z(R” ü€' ü€'gridlock.app-1.10/Resources/blue.tiff0000644000175000000000000002054207523137723016616 0ustar gurkanrootMM* Œ€ P8$ „BaP¸d6ˆDbQ8¤V-ŒFcQ¸äv=HdR9$–M'”JeR¸À !—@‚ˆærò %O§4!Ìî‡/¢Î'³‚Qîd!ËÀeV­W¬VeUAI*kF1­C£¼RF;Æ")h¤ÎۘוÌÇoº]¯2ÕÂùp)]_å"UÎ×eÚóûH k^×àUÙ…Jµ—ÌfsR œÔç/5­gèKP¥Jÿ%—¯óYŽà„B7ŸèÍ‹ÿa²N'ïýÎí(”Ýïw›®û‰¿Üq8HDfËnÿ=¡ÚÃ]ÃS«ˆSüc¾qÏL&•9ÆoÍçôIæt£ÜàÆ½ -$!ʵÿ|Õ¡}4¢3‚â°•¯ü À'{‹·0S…ÀmÙKÁpœ¶n ý®"Òæ‡%©þÇ-(Þ)©“ÆôÅ‘l\ƒ"˜¡‡:ÎÓ°Ì8N” °T·íÙÿ6rDŽÝŽc›d5mç(ŸòlŸ*JÒ¨æÝÊ”-7nd%I,+ Á£„J8ƒÜ8!5GøB¾ÈIˆb)&,_?Ð p‰NûD;k[ì1µÍä4áBÓLþÌmÜÝ/K’¥ÙSm`ÆÝÓ²…3P r½INSî¥OU>õ+î5Õc¨5ËîŒÂæŸó194Wr'Õ«€BΠ( C›"2%gÚZpõ€YZ—»lKNÖ®5#!Ç’3k,Êr}\ÖË—=a*ÝuÙ]×Ú5ÞëQº—½YY_uù}ÝRóe%×4}y M•ªƒÃNXñ1j§Ú8¬^Ç%⑜F¡ Ó®UÍqH¸M¦êU4™yåwħ}JwN]zU—FkuÑ—îiygWÕý–5’Ý_U˲Ó\RA` Pó¹Ùî(/-«ª¬u C%í8„ÄOÔ}^CT¼ÁOeWf[µSÛ^_¶Õ›~y|æùöw»ßWýâ9Á[ÕÛ¾fòç½î×Åe'Ö£Ûe„Ál7:aŒCdxe2sæ±Í£Ìu%%ä¡ï®°bRápäS÷tÜÛNm˜ð7ewv¦ï™n›œ¡Âö=ÞƒÞ^[Îÿàp{ÿ ãh8Se[6n;ˆ!0¼¦‡¼ô- s÷9í¡˜Å«kÑúÏrüÌÚmy·_Õ=†ß÷h¶aÛî?§ƒ¸~ý×ãûx·ïМ#Cf¯ýÁ@W“Ü;A9ÈiÆ7à "bŒÇ¬°ežä*fCšwÆ»H\­¡ü>ÕÖü[ó^™àBwØÎÃúS-Ù¾¯gzðàsoP8&|à!Úð‡°Z<¤«Ä"V‡L A¢ôÏSEpih#8|O°J%ͳ>W[ ‚ Œ/Ö1Bè`ìárõ…±©ºÆØeáüBx‘Ê8GX‹"´ˆPùßLj àrR6 ä!2\@@sÎf*"Å÷>(âBj—ÍjR-±õ³6} cr]ª¥xÊI7)c;¾gðÎ73†€ß£ä«ˆâ;ÄñϼC qä=ˉwƒ™µy¼3·1ž°/`˜HÒ²¡ £Õ‹ !½%(vQŽn4å)ŸL›”LöVÊÇuÛþŽ‘ÞÎØy.'d@3ÍxKØük'´ìžÒíN%ƒk1 .‚@!Ñ' ÆTfq(%΄ŀì×Ë„™J²’6éOEc#5œeùCyÈúŸÛ•/òΨs%£B‡qþO‰á<Òäû¦º\›°´¦’ø)‹k H‚ËÁ‹Ù¡$}ï2Äk.aJjšÀ´”¦Ìâ”ñ™ÙчÞÍ&ügœq¢sRs £Ót–ÚwËx)\}¬5†_Ïp×>`p¦3ÁÕÓJÛ[é‹ 7a(-DÀbjÀ‘D ›aê¡o}ÒT§JtÚ®ªñ•Ü;Z­V&óö4f­ÒcX*ôoœó®W@jÓZç¥n¦u¾zËéu/'¬Ÿ5Ö¼O…@—ëáÓ4î Ø5—aj‰!ÌdBCìjDÔ² ¬=ÕK# e ˜~wBŽÕš8üe44w6†Z3JÇZå}Ý–/ö³Oé]ë,ñ¶õÎ"[:é{'Õ­¦°`·Ô¿1…‚TõÊ!)B,E¨IílöÖ:¦\µ-T°n„Éš/'ÕÈov´v’ÊÒÇ ÒÜ;Y1_Ä”³iéíEšíf+Û8·4íŒÑlu&*¶¡ ¾§+xÔ ˜) äÊà­\NؽcÅÎ-êŸ%²d“–^éÝwÓ¢Ÿ¶TÊn‘»Ë¿Kx>™Ú7ªµZüQ3%Ÿ[‹nÛZï·ófnã:¡—¨B‘Ó¦Àö3‰€)ÇŠœ1¬‚?ÁÈ1ÞÒk_ìƒwÎüå{·%”àñÎ;i>£îdµzøí}··x¾Ÿâ›ƒnuN+>s€këñÁpåÐsÏöÿZÿíUÐ,§‹ýlPBc ,†:c oHº/¸Éq…q’ѯȆў´‘¦ü°ºÙŒ½ÐP¾ÏѲ$þÛ Kå®1 ÐÕQÅ#‘ÏðÛEñ]’Lù#d Pô+£¦‚àö‘lòú1ê#¢f×Aß«„‡Êß.yîn£P«² ŽÒ*TÃfápLÌðÆÍQ? ±ÇËݯ1ÍíÒK#ðñ$ÐgLâr1ˆzÈ.+ÒdǪˆ¤bΩ`”SîfÑŒõj« ˱0ïÒŽý®÷3|ÜQA Ó…1Oó¢ÿ±Ë³3½3SŸn´T:bÓ$À¤·ô0 ´®SZÝä '÷ É,û­•,© R„õð=6ÅöËJO)N™7ñ¶ýó)í´êðÞþ-8ò;2r£¡$1×AÈ s,5“¯:s¢J³®ñS³‘´â`órÒ#%¦,`qÓÍ5­ôõQ•Žå(Fú»3ç>ÿ02Ò‰l–´bËóðn¥”pðÒ7@’K$0ë#Ó•9Ò?9³¡$qAôͱdùQk,À!- ÐÁ0Ë8tw14{22¤êÓ‘’µ“!A´ó33¥HôüI””¦Êë3È™´¦¿â°È.#SR;#¦50%.k˜pj0³ÍRЯ(sÞüÎöá3ëMs áÓ€þÕE?”æÅr1H0k·@±Ó@t!9ÔBO²IB ×P3°¾ð3Z°/ž uƒ--£5‘øîp£'´Èè¸ö“é!Q/EðÁ!Õ?M”×"ty8U1I?ÐdëuUV/ùVÕqOÕo+‘_Võk+Ô'A³­Và´òT6@1;®ÇXQé-T®4azæ1õ5±‰Žç/“hœÑ£Òÿ!‘¨¬:ý0ÉT± ëäâsVyÕ]O›Hr«UµÍ\”û+uudT].;^pòÕ²Æ! Ð_b&¡tC&àsÆS=,'YqþÙOaFÒŽ¯k5CMTáTÞ¶”\OTõYc‹2‡OTÿAteGdõÝk$o®: @æ:`si”²ÌuQ1x!¶hqÖ0qg-ðîÏÃgÇ|ÒìÏΙZ2+0Ò—s÷¶—p³9/2–A•ËB5gj•Ó]ä¹d´õr”rµI±hܶʙ4§_u‰m€!t´EföàUbÑ”Töþx°E7pq3¡F÷´å*v›i–=j6§30aöQrv¹dÕsxÖµy¯^"ã”Ü  >¶ÏJ•4Ât£mÏD01øS/n§éo|¬v‡ ÖƒFsñT´Ý)Ôw1ò3b48Ó/*Ö?jñAW#]–©Oƒï$v·$ÕÛV”“r¥àIs:Š÷l.al€bqÂaJŽUK{VÝum$›>µ‘Ÿ7‘-uðÄð¯T6[Q¾áò18ÔëGÖ5GñY9õ×\÷‹†Uqsc“€ø:TIÛ;6ÅsØz¢‚uø!ê§¡ßm÷½=ÇS}ƒñ%a/e!0¾ïöù[6÷V(â1®Ö7~wNÒ¿N÷†˜´ñ‡uχÕo:×60w¢¿ bH8#_X)‰Bf³ÌÈÅZœ"ïšÍnx1 h$ÖsˆáPÈ´:%ŒDãq¨Î; ŒGb1ÉŽA‘ÇäÐãܶ/•LeЩI¬÷5˜Ä&R‰tþw4¡'“©Å×D˜ç4*LB•O¥Ói0ä%Z¡X¡Öªµº*¯^5£"H˜Ça®ÚìÖ8uµo¬¿Îw]„”sk?Ç%«Ø r­{€P)Äa1xÜv< ®ñÈÆöR%^Ìf8t^†ètz]–3%H¦zÈŒ’o ÔÍö’½}U·Ÿkv»ìâaG§U8“Ê-NL¤Tx•ÎmŠ©j¨ôàܪ÷Z×Ô±v»5nõžËs´Ûú¶«µŽË-ÛÏò‘ÏÚ1¿?Á® ‡Äqa {þÇ0 € ʈAË2)3ŒòèÔ´è£E¢¬úHÐ5Ðk`Ž&mËh“&ͳf•·pÚŒ™6î D©ë9)¼ZÜF;˜®)N⹸NøéÇ/4r¸,ûÐí¼«’Ï#È‹b 9’‹Ú)=‹àƽ‚ Â?@Ä?оÀ0B¡HRgâS6¥‹Pšé´mt MíËe;O‚a Cí„>à·ñ{m¥1©AÆ*DdçÄôlhä:yÒt³¶ñ:T¼”óI/;ÏMI àï‹KÀÖ½…0Iþ $aœüL[ù.Ëõ³(„! Ó5½¢Ð´ö´c›c ¡í\襴é<õÃPå>PN­E4 ãÅÕQ©ílÜ sµ»÷*¾»Òqô†¶Çî½B®¼u…QITûȺIÕÖöˆUEX%M 0)ŒXcY±`Eo[ÔÁ1^ R€¥`¡«X°Œ÷N©e“?ä†GfÛQcƒ¨Ô6OkQYtglÆÑÂ…¹Ñ®c˜Ò·EåNHÔÅæðh^‚¶^—µð®ß‡ýü½„5^-¬\¸VŒfÿ²RŒÏ^KÝ~ö³²e‰Ž4Ó´AìÛMžÔd9.YP´&Q”D›³‡»ÛVöqqæ×DfåÇ×^þépyî‰NèTüOqµšôŸõ2 ¦útÒiØ3ŃV°ÿÌ,ŒZžáÌ÷bŠXÆöØv*9ãÝ@YݬMCY›’—iw›œSßî6±š[έÅGp;í"ì¼NÍçð”ÝÛ|g—rÝtÔy÷±£Þ¼]Ey/+Øs*à€…Ò°€€¥©¿½Âáå)ÎËÁõ8l}~=;Ã[v©õÿ²D^ÝŠÑxмœS†¸JÆx¯)s•#ºô ´G«½v4g®¼£D{ëÙȳǾ׺ù NL÷þ _(B”wº'Øç Cž?½0€Æ%Ó3/áµ!göÚVbÊC®Ú<8î¼JoMÕ–­¸[Äg+Œã£¸³Û…qML¤—áÞä'„Oxê—g R˲Q=¥äö¹sèBЭ1`å„«Xt­Ó[%ì!5ç%–ch5I²»Øâ›,DPàI6õ¤¬ yŒÍäÅx)&—‚”goF/$V…`Úõ]БÇFv© ug¨°„"ôå‚’i¤-9´·À^ªÜȦ7Jéâ ¾uˆ17À&Û‰ ²cPÞÉüo‰Ò‡‰ê9jɶk'“2oÒl©A2Ã9S?zÎTÆYËcD®H‘ÈʾžÂòJ%îK€”é]Z`îv`äÂŒLÆa5&ÆÀLÝsešAj@I²Š 3q[(²Á ÅE¤Ã0›Ï)æ·÷ê”í0¸ªNâ¥l­žsÚxhU‡üº— ¹X…dbD| o½žö¸= ™-©QuSc+D-¨Ew6(ýSŠ”|¦ÍÚ@·g ›³‘çEøÇàûÖ{p„»Jª\ö^ëÝ„ÏV6 EñZÿ§™§ J~ÜýA}î‰]zé¤ RUs2DHŠ#b½‹mÎîKч}H`<Þo“jNN—H垌‚SÖ‰I^ã×­R®Îö‘=—ÒM<©A)>Fš…éô0´ŸP(s`#è ¦„PU ©l†ÇDÛ!U&ÝR‰”v‹¼i1W$Õ[º’v¯œ²µ9 µ¤´T® ÒªÙJ§¼î•tÊ—¾ñ-asMJ½0€Š{/j¾ h …%uadA3ŒYÜØø“5$s&eP%nQäQªÕ³e›ÊÈÏï #¼  Þ QjœfLJ ÚÉêäcmq=ÖÍ´áŒ=̈1uõª¾ëñoŸˆ)¯Òÿ€µRj|Õw ªǃt$æ £—`伌™w,ì^/F±ZYAxíEe¼ôÂ5B ×=]®žuÎY['Æã˜R>æ!-Sö_ñ¬Á¾wÂkˆ^î4Èb©1BÈ©l«%Á™")²‹°…“ºøN®Ì•ò„Ÿ¥³Æ89ä÷±C­ôÈ…NüÃ,q,õ_ š8ÞçÊasR1êKüß«Oì¹"ÔË$ |î[omÒ1D`œÿ®ð~¿£ª-»Á9E•v4_gXr”â·xÕ޼±¢õ/]§—ï^(Ÿ-.*­dú¡¨Íá«êí\®¡5GÖ­…ÌÜýVî²Z ÍU™¸Þð•$Ø[ã}h·9òžVŒœ·*2Ñ­Nͦpb‡¸¾±E°ÔHB[%û™œ´.§n-ÉÇo›™¸BôëI ºn?šÒ>kÉ#u‘¢ŽÀÑ8S}䨱²{‚àybÐåyK–¯&Üøóé­©§aCàöÏm„¡)NÏÎ2jÌ/Žõ3~‚•ÄM!I7:¸÷޼ÁÁp¼M罪îų2ŠO3¬/•`üfÙùrñpzßÝ6®Ò"ÓOÏLPøR”û|ÀcG—Û ú§‡@ ƒ-AÍH×3WxE+(ðµîúš/±ógó9Þý”›þOð%ã¤ïbì­6«¡W+[²îœâNSm„!1•PÍÞ#Ý0«q5JºÉ`Ê« °vˆÐð2Nŵſ²¥™çp> 4 i{ „fp·Ѳý1üˆmn‚š­˜c°§ãoê«í«=ßï@ Œ¾ò1z;–ëЈ¸|7ƒVùc³.ÊO"똢㛲¢s£3H>›¸="49ã/8;†;¸‡6«½'º¹ˆ) ò0w¨0„#Â-ÛÃ?„ƨ0-`!.;uˆÈ9®Ëy>T Kš6 },ûϧC´@; %2¶¹ûÕ¸C6l ´ûîb×@¢¥š<1¸È?c6:‹ÜÁ4+Œ"‚‹Æëà Šl(º ã¿ó|»*q,â ®ó¶ â”1¤'k×Àkƒ>óî¿+¾1!ì#kˆ˜N4؃P¦‹Ú2ù³[·,Dqø<Wì ‹ h=‹09”ƒ—®‘—¦ûÍÃcœ.ÓÎ)46C¹´»Ó;ƒHÃë»4»¼;Ü=8y}ÚËO% ø‚Rù -?aª&GƬ:“ÞËY?»=B ‡øB`{¢¼3>d4+5Æ»%ÀBr¶+dÁÒQ­#ê²ÊT6ƒ +‚ÂDX´óòEœe…,iE¬iliD(ƒ“ôŒ#o³d`B´aÇñ[“V‚Ôp{ÆHº$iFdgHXÄÄi>A—ÄÙFCS'-uEo§\S­3¸»«0ÃÌA½Â3ïº,‡Dg…,†lgD i01±lÁ A¯¼a€ P8$ „BaP¸`09-ŠLg¹hÖïžÑ÷ú)F'#‡´$`Ö{s¿äñƒ¢U.“ÊMrY|¦[2˜L&“Tîu8™!(2Éüö‡F˜èT‰›*FI©tú¥N£I«PfUsZ2mY¨VäÕéRRÇ[´Xl²Ë!­))=§# E¬q­ŽÓwùj®B5ÅÊ9Œ`aˆ"ÈdrY<¦C‘””cŒr“šù!H£©Kæ–M9œQ(Ú–Ö“EªÔ©Õ9ÞòJ­T,|:Ç©\¶ò,TÎL²Á]ât)<›MºÏkµuŸç;|uK§¼GUºÛÝöhB-'Ø1‰ïï`a ¯×í÷ü~sà¤b‘…è”-ÊHæ¾#Èá(Rµ+³Xí¦‰º^×¶j£pÞ»ƒ 7*cxÝCÎ2¬è©nÕ+®\Rì¹Qcª¶¬ÎÄV1º‹PöïŸäbê’…êG-Ëà”9À¡ˆ„BÌÀ”ø Sâù¿RŒ¥)ʈ#.ù^´F²_5D£ÂNGmB2š5ÊD8C)ä8Þ·q:ã¶ÑDG¸®YEéF“ì\麱ŠâðAQñþNË´v1ÁâÑ "‰RB% RtšÅ±²­=OÔ´®!ÁÈÆ‰"ˆ²0=£ñäÇÌPrø#š¸ß6“«7jýxæNNm]»3¼fçÆ®ÔWeÆ1[¹UÆ$$q£”e«F»pcÌŒ0 à B…4âúT7MÕu¡•‹AË>cUHÊ7W#…-±}$ ÍV5µÂfÙCÓ–[׳͉;9qE…eÙ1lþ²P6Ég»ÐCÇQE,¼”¦rAEvÒüŒ"¡œö=ÈL o’NÝ™®m›ÊÌkø/ð´J@eéÞ–£#TNQEnDéV­`ðèÕœZ`¸Tá«a8ƒ`ÅS¾ëáÑ{IãGü6Yå±wCÔgý Ðgý ´HU–%ÁþT–LV–§ýÏtÝwaqE‹©xÞw‘ÿz^÷µñ}Þ×%ÅvàEÜè\»[u¬_Ç1•¥CÙöU˜ØöM‡bÊEÄÄ%WµÞ=¡rÈ,ÁY^‘úSxþB¸Eab[P]°^H¥ÍYº—%Í{¡Re¤IrÐúAÿ¥eÜe¦éútC©jž£«êÚΕ­–ôfw\ZtçÔžyçXU¯šæY¦^áe“~PÙ VYK ÞA½Ë   Ø:áL!Ѐ#Ÿì)ufQÞ×BÑ”–Ëvè…f¿¥^Qf«Ïê±Ðt}³Òtý7Qªóº^»¢Äš'1rÒ´Ý?µÇ¥7#ÇüWÃGW{ð ïžJ¹1ÁJ\†°zŠ‚ÐÀ’äéG˜“ôeƒŸø)þS•Û%ߨieÅÕõ_oK÷õ?‡Ùù}ßíªÝú÷cóü—OÄø2Ïuì½·ªõÞ‹ÓyÀ¬^«g•Èé1 @,Á€4c؃ðŒ?Øz)áq"djøKBYЩ|4Çêüß¼/†OÒCk !ÃRiKá±.8Uê5U ŠÂ8;àÈ;ðT ˜$ „Q!­ø J h¯X`Ô~ ²õĈ˜8ÎQm(– ΀­kê9"Ã8máÌ7ÑÆ8G8ìÖ#aákðõ²°˜ÉN4^zñl~ÅpZ,â¡6ŠQJ*L\Eˆ7¡…0´žÀ£üX‹qzøE’⯢<ÇIMã¬r•R¦VJyW\Ò$”b®PÉÉ=&dÜ–“JJHð\." ‘míæ$Ô.AØAY!À<8ñ>)E\g‡°µ×Êé[*&´Ù›nUͦ±×´|v“>hÌÇ2VLÆ#1¹†—`¨ ¥Ôix?ÃÀ~ÏŽ5÷ʈ!ìjD“zkÍÙ¹AhE¡TªÐ(Ñ?…ª óö|Ϲï="Xá^wšX*Bp2’CÔ$…°?á‰â’Z.¦ m  Ô΄ÐÊmM)•u°õvÒÅ¡JGý%¤ôˆj>ÈP @Ž’0 SÀˆ6™#´$… NÃøˆâxRŠÊV+›fD–›ÓZqYiÍi­­K›Wë \«Õb­UZOT‚ð©à0 SHðoÀ(¬1` \áÈ=4*&…ÿœX>ßZ«=™¬ÖnÌYÊÙ+]o²vTIY cGýˆ±V‹»ÑvŠÅ@#Áh± %0ñí+ÛŽiôYÛgî=š¹6zšK¾-,{Û™ŽÝÛÛp.â£zLЈ  LÁðE ƒü/`Þ?Äp–8×è?›™{î]ñ¹ÎåV[Ý{/Eê¼—™Š^!ÿw„q+d ¥]  ¨NwÃÀ/†pà?Ä ŒNâ„T­]}pÅð¾˜k ß,;~ZE;àÜ„€’S,{ ÕÅתÇø€"H‰±GW…p¶O¸{d\‰‘ðÞHFY>ã꽎±æ7øÐ ö ˆäÊ ‚pV ÅpL al‡`ü!ÞÀ  ÜY ¤:.£nÎY$ç\ç’£~mE«6æœ×™³FbÌ™x‹¬¸HŠ)˜ 0‡IGèm¡öô q@øß:ásÙÛ:g}9ž5ÓZaqí,?ô–”ÑáDhÀº@ÀU²cö؃0p/BøhÁâ$H‰»$*“âÌ]ií§vF¡Øúƒbì-°uæ¾×8?Zƒ“.-càx‚Aª°ÿŸB?ŠD9-3udÙzvn½Ý²täyÝ•n1ÿ¸)>Ü‚L¼‚_Ïå{ÍÄt†pÞ`„˜œ“b› …¼7~ÊâO‰YÑ_Ãøc4á2oƒ&â;kØ4 `3š€0 úçÑ-³åé9ÇŠnÞkÄy· ûË>æ­‚!9pÿåa¢ÿ¸a*@æ”ôЛBPçAìBñ,'ŽP¥|¼;!óž½Î;7ìTç‹§Þ´ºz¹Êê}W¨ΚÁqø¯¦ …Ã@÷@Lù4‡CçÂý¯øNÃμ;õi^qwñÿÞûïx)ˆ20'–Ia/à ÀçÕ:·XC"®èPí‰â}G†õ^#ÕµM›C…¤ô'+Ïõ_8†I/Û$ ¢|À΂¢E‰Aÿd&‹äf—ÖúŸYóü/¬ùŸ+ãŠ)£ñ>6‚þü ùj’J7Ðr Á¸;á©Äý”_'Su|ßÝô>wÑæÑå|~›+ùô¿ãü»èF0(ÖHóJ¤n±¡á*¡Lôj¡Ìôýïäþ0% ßï`´0JPpaŽ%àR ` ä¢>'  )t¡ ÔϪù.ùáe0h³ï¦á¯ðVé*’áñÀˆ `,¯Â@éŒàÒêaü0²/ìæ$:æpg0§pjÎnxÍП ‹# öÐŒ¡$ d¶ Mb#À@\Aʲá"´Î} Û ð«ðí'M .a+# ʵ @dBE‚,``Aà´Ð8Ná0RáJ¯–áðõ Щp𬯙æiq+!ÿÁÛ@BÑ # žà0 À áa0á2!T]P_Q;19q>Øï˜ã1utÑs€Ð‘bâ»@éb.Û N–BðžÞpëQ‹±=楷Áÿaý(*®F#P¬Îîø²0çP¥‰ ͇Qçaÿ Ñ¡< `>é"+ Àô€úŸa‘ú챂 2 #ò=$* Í€ò3ò,Ÿr&BqZÖB‚@ „áo"íÈ4ö0lá rE R…,kòx8p5'ÿ&€Ž($pÉ‚é  @®¼¡æÒ31{a$,2‡$QŽá±w²µ2® Áï*€‡m"Œ.V ÁÜ¡’ÏÑ2벃,Ç,SjRÊf’÷/y.¡æxЂ @<ÛB.rë.òó+’øë“/ó530e0³-1„ àÍ1fþ 1ç2&ÿ.“E2’õR½703i0p'3Ó2³xÀ” `H `.SW2sA/sc/Ó96³g6ÏU7•4voóz S~ Sƒ5@ 5’í8³aó‘9S“9“À¹s³¡4SH³¦ª®!Ó%5³¹+³½<3—>óìâsÊóÏ4sy7Ó8S³8“+8Óë• ø`1ÀýEñ#¶‘dÖÐõOè^ПS¿l6¸5< @j jú PF©bAc Ð àîÁ0Z|th×m2e pa4öþö\) ‘n‘ F%à ¬ -03G/dôÍ›h÷Mq.(õòŒöPwAs€¸_jµ &ò¤$À2@8  â·áðø¡:8íÌYÏš·Qt÷æÏ|á9xw€0ë~Wr€õ^‚k""I@`È `â+ÒÒ÷šC‘.]6Gl÷Õy 7YåÓ|«òÒ÷¾!Ý{€œ vë1×0+€€nAîùp¬DÍ•Í}w-ŽþŒû€¶U€wüAL `v `[O¾+Àƒ`B )˜a*ôLÔ²µ]}˜MJ3ØGEƒÀð6b Uëbt(4×ûáyá?$±‘R8Q„÷’•ôöϱ‘‡­ƒyø"â‚x ´4à¯`0 `° ÁŠA6þAT¬-€:—IˆxŒÈquDIŒx¿Œ$+‹©+‹!¢¯`  `r `Më¶?€2`8 ¶¿`²¯HDŒøÍÅÊÓxш9†¹€ÇÂkùùØú€ù‰µv Kcfﯔf an´¸½Œ&ޏuö͈XÏ,(òkyT^áfD™Mj¦ –Âò[†õöW ÀJ I˜7äB‡ºá|Ç\}wK‘¹_ À¦ ázÒÌ×›aþ¡ŒÅ­ ¬á¤šWŸïYªz£Ÿª™©Aÿ¨À®*ö 95œÙÑŠL  íà@  ¤ Á{‹˜¼í©ºžáŠ¡«ª:HAw\ú­šŒ‰¯ÄPغI¯:÷«f—®ºåúÞÞ âØž `9zÒ ¬5`[˜Àî8‘®ÁžážÀáš»©¡Š…´šS¯ù«°JÖP›eµÛaµ{[´ûS©ÛK´{Aœ"{œ`IÖ#rô¡_[2!l š @öAáV©>Á¯µ!®áÐá¤AÄá°OAz{°ª»j»»¼»Ï¼;Ç»»¿»[Sºé?ºa¡¢¡à b€‘L %"€ P8$ „BaP€$ ˆL‡¤!ð¯\0_ìöÉþØpº_íÇ#­þËi¶ßëÆ-þ³]F–Szí…5›¬æÓ‰äês;ŸOh9ý…F Òh”ze*‘K§Sj:}V¥7™Æ¦©dºQ*’I¤(äz1Š"1 @Ž`bhN …ÞoW»åöý}ÀÁÁ°àxº[/™ê%ZÑþÃf5£òûg(Ô’?ØL¦“ýn¿c?ë5}%GMTÒê4õm^§YªØkèÚ<þ‡7Ì92¹K?"ÿÆc±Fv§Wª „@@°˜P*0RÉõ;ý€Éε[ÎwûuÊì¶œR&ŽYþ¾b³_ëEÛDš5° b×@eÀp3HÑ¿óðý>§ âù½¯yþõ=;:ñ¼®ø¨d»`œ‡ë‹˜ƒ(°ëE‘l]€ º€q¨U¤‰0P¥ùη¯YÚœD†k›ç1þd¾©Yˆf?ib^š4pT­Ë<¯-K)䪚’‘y'Érl‘%H²„ɤQó;Gñ€b{’Ë› Q”a?Ð ú;(@„A Ü=DIðX ¹¢mgù¾tò!ÒwæñÌøÔôÊlŸæ ’h3ͦ¬J…Úµ.ËpD¹YÖM\ÿ«EÒnÚÔµ=FÔ2U<øÝ-Lô+H&ôa|Ñ!‰" aêД½oÜ Êð.ã .R…¬–i,±ÂuS‰ ÕOÂgQþhþb%ù{2ïÅW\aŽXaœ©WLö ʧ}ß·Í;|^ÇýçN³Ð•]—s†â°®B  aê `ý \wm›çÁ `¨Ÿ†A°r“#áDå¡zÐÞ Õ/zÞ˜ñÕ!Í)K`Ç*7$_ø)‰§ùk1á ͇Õõ¥c³¦[F±˜›2bÚÙ¿¬kK ‰#jR?cÓšk÷¥Ÿú1xhAÙMŸ€B’DÈVƒ™æuœóÎs?X  `è â¾*˜‘2PŸÆ–j¾'áyÓ'×NZžWuààìwj¡h(© ˆ¬Ç f@°@£ö É <@à9€°2FW4ÎÈ Od Ê [ƒxB¡ Rˆq%xº2üjäˆ:”˲1(»gÎ:á~wíÞÈØ‚¾¡4ˆRFGÉY)%äœBj²n"È·Í!dD Hpv$©‘Á #ä~IB; Aá‚@«ŠÁú,'ðÓ/[/ö48ѦÁŒ€ËR@Œ d A¸• Aœ6 ¡(&ÅõuÌ^>›¥çÝ´®ÕÛÊ)Í!¤+º“ó®uNÙ:g|ë”3¢zNQÇ8å™›ò¤ÝM±ÿ5æÌÓ ƒ6gƒq;3ÚÖ @ñÈ€bžˆ˜³aQZ-0\à k–ˆ0C.È7à ðhЄ°b ÓTH q:<…ˆ¹øŽ7qº9ä<ƒ´xúwOg¼ƒpzBH)Kj%DœJfŸÓêy( Ý7HtÔÓgKi}* tœ‰ÚFá G(ÐÄð@Ám HQÀF“í®U΋€%¹1N|^t@ _Â1làø 1=5ˆËÂpQ16(E8ó±b„z©5üfñ ICdqþ4Æâ´JÎYë5á²ÃþÉ[dlX£– fØ@†(‹`~¯à)0“Y(YO$0NÌcXÕÜWjésî…Ñs‹ÏQrt G4ªËnÂb5<º0®Ð="aFAðA öŠPX Auö¿–úaK|¥½—úôÑAy@0\¼ARÝÛÒµH¹Â45ý ]q”5× WX9åÇ.Ž!ÄXŒ‚¹Ê(çY˜î„‚,0@dºÆÈ-‚ H8Æøçc¼}..× w "r‹ˆ—€b‚‰ñ$ÊYO*›¦@뀑žá @2Èõîì×Ë´3>g™Œf,¿—Œ9k,wÿ•sÆyÏIþç ‰à( yl\½ 1t5ÊÑ > ‰åþ}ÏzOJi]-¥ôÆ™ÓZoNiÒ@@dd$,Q4<D(R91= ü€' ü€'gridlock.app-1.10/Resources/green.tiff0000644000175000000000000002037007523137723016766 0ustar gurkanrootMM* "€ P8$ „BaP¸d6ˆDbQ8¤V-ŒFcQ¸äv=HdR9$–M'”JeR¸¸ K¦@`BæáÜÜ0„„(Iõrž§à =$!D%O%à a2–VkUºåvUXÐfà‰éŒ0µ%.ðÂ0rï¥Nò“8Öÿ)1®÷“›ü´Î¾ß/ öÿ½?ÉLcþãs¶ÚÁÁK¼k /lsÑH•1—×´Z=&–C0›¬ÂÔ„ÊŠT¤§ù {5³oô#y)¼ßp7éÇ:µÿÄã%ê^?/›Ìât9ÉF÷K¬ÿFpw»ô#YÿÜîöŬrprÿɈ]àXC4BN¥Óit»M÷ü~dډݗ2ɲ¡ÉZ)/Åêú=»ÎÁÎN9îkŒäAÇùJâÁ°8wÁît- B°££Âp˘RÃü>FAgüï‹LHrZ¶KÖ1½ÌòÈЦÏÔuLj2Âø**!œàÁJ!1M¼UºŽ“°Œ å9‘D+AP`æo¼ÝËrìÃ/Láþ9œòè×/Ìó4Ñ.‡;Ns‘ÿ*DäC¹Pd.¶Ð BV†'øBX”É€ˆ)4´{IÒ‰b3íhN,q[$ l$ñD’|9,KÙ¼ïÍó!þ1›Ëí`ÝŒg=i6 u³Á]VuÝn¾×-݃WÖ5õ‰`W–-a`MƒÙÎï»s¼S ºõ,îàÔ+½B€ !Cq«:Ͼ´­Ís¡‰¢lÌ´Ý;#<õ w¥¡ÌZ–¤¼_#ÆÍZ®Ÿcj<…‡¨êØg-\Øþ']Ùe˜ÝÕRìû C“ùÿ½<û½¾ø ÒÃHn=Ê:w”jÄJ'¾ïN‰Kµ¤æpµ{qo'ÅyØw%és\÷«ÎØ\·3Ëú\ïC¡ëÁ…ô½'ÍeÅWû”áÅ,\ ÙPÄà!á ´Ò]×ô…Ü£]»‡ùgI lï¯tR®Núµ`ÍDï¸w öàtq,58ç1œÛÓWPA©´×"ÕP„/™Î>g@âŸ'…NŽ«º±QDNÍ€³©ÕºAí3D˜?¸|þ`!e â‹TÐÃ@VF ÁWÕ¼ƒQF=Ø ÕÄ…0vEdz ]¡|°­òÂäÚ_SŒ ÅÞ¨aKcµ4æ®tMr„àäcG›`jfyŽFÄè¥!bc”ŠNV*4Ǧä äYƒ0Š/¾H?%áTa…Z2I¸NÔc&‹¯•- tÙ@®Ì9€Œ 븎§éK©€=À@¥P¡ÆHTªÜ$Ž&ÈɈöb|UhŽ1è=È;¤¬Vjòr Â8W"Ûß„ÒjNÉÙ@ùÇ;]œ)µÔ+ „3¢›Žp?@ýÈù–d±Gõ9.#ÓÅ1°b4iá ´˜ÐJE0÷£#œDÈ‚îjkMY%3æ„“rn:8K7e‘”3twÊJ:± ¼f”¦*tjíQ 1•iæIÊÃÀ=bµ¼ŒãÈò×ü ˜“&bÌÚ NÞ|Š“>¡´º‹"ÔÎŒtVM™EFèµL©ôi]Î%]æú¹¤#xÜ5Áþ F3±±ÀJƒÖM¬ñ¥äyr‡8„ÉÔ(!ÆÒs˜Ð´® ¬ÿ˜pF Hj óà„SŠó GÈÙ$öœý „R¤My1F_ž£ôb¨5û' ,½Vª•j©«S†±´3-ª±¨`׉s*4ªµ‘xLò툕ÈÚZ^ã`hïŸôþŸÐ*"ZE>š:£=Ëq,•Nšr~©Y)TêÍ—ªòŠÍU˜º×lÍU»QšÐJå ­)ìjÔÄ ZCÙyD¦ƒü SΆ±¸_é¢Ý×™P`¡£ÁK‹¬Õr¶ïM»s¢í²Ïf1ÙŒRèõP³Léݧg!,f¾¤´(kÃ-©u¬¼äZ©³Ô{89¦Óõ3¸:÷Omå~Æ&ßXH™CèŽ8©0z‹ÅÌ6*ÏǸG Ý{©f眅sЬ]›˜ÖÌn*<ìÙ‰ÀzߨkÄ6®—Ó*ÉÏ81È»µ÷o-Õ@Åï;×Ù™¡Q’._9àˆ·f– “ÖB¨ä ŸŸòuQÁ·W'h™v²Tã›áHk LÄ¡ok³™\ÐV“Cˆ¡òì®:¹—äÙ}Ú¬Í6÷Qã* 2íý ¿ýˆjzP®Fv¹8ï=d;‚ò-•qZêëdL•vn¶‡×øVÉŽý°qnf0:6¯ŒëÀr QÒy7.|/]´6±®æ}Jåo­ÔÚ§T©¹*%¢ROXÍk›E.UÒÏx?$a)·„4F»[#DÝ…±·ÞF¾xc6¡K´%…,Ë{UÚðÌȬ1ìgWm?šu1Í•öžfö§böt¸yçínÖ­ò³.e+Ðÿ$s/,s1,Ñu0)l1:Q‹As§4²o;RÛ ¶Êl¬ã@÷2 #Q2¦ß=k@1¯êŲ–’&ÀKƒ"Ñ»#lwo2Þsó*òE@Õ 2®fÉ0Žt35 PG³Ÿ3ÔHP©-«”#;rÎMp¯B¨Š~cC. Ž“Ê"²ò­Óf1PX̧1ø‰¯õÓ±ï›tÝÐôëð rÞ´Üô4á+¯QTÍ32Y ;,óC:óI´ùBRÎV³O³¾PÃ?5 µTª"“`HogD-=6ç®<ø3âÿÐwLóÖ8Qa‘gs“G4NTUQí,ARiAÒZÌÒeIuV”üœsµB ÆV»'a­<Ø U#2òâ³RŽìk…³æ°O7ìå1ÕŽÃT±×*î][tiÔU¯GGòXº1;PóBZô•Pt•I5q'0ÏQ Q ŽÿQ¯Û \5àB²ñ¯KìãSzùQÄÏ_1”ÓFOAFrHåõÃN’¿b0™AQí\Ó?OUeH•y]BïP”ùI6;rta¬S¢ž‰Uò"‚e(´?(ð[=´HÍSã1ÃlsTÙPíT–å³÷?ñå[ÒTû“›GÕg9ÕcIÁd-H¶C:•w,ö«]Ô& RÃÎä4Ÿ_¢‚§CÕÿDšµ0˜ï(ÿVÝLgó…³n®ÉT³ûNs-V%@–ý×bÖ1O–7]ý]µÛj””YÖ>…¼¦á¼@’à€6¿.–[â&Q™(Ñ:«ÔGޱDѼùU®¸ÖwÓƒMlì3ýMôvÈ´[¶)NÔpT-1&ÖAõs;7£ö¯qD²j¸X—%k…=J]JKU.â&iT=N—m*Å­]"1¿gVà±Ëu.QnÓ‰|5N×ÕQi'N7mAýGWsO·×]UqVP-dtÿc÷dwEW:ñkKky¼¬ÃAJSÈ"6_CÐW ×<ƒmPÀín591µ©1Õª|vañkF±qGé²Å}‘ î—:5ÓPW 4Uß~÷õW#qWíq·}q¬ÍDV·k¶¿yq+_BsVÌÙDRý•¥m¶áu4Ó{’µ|tÝ‚÷ÐÈô˜9@·m‰øK}SŸ~t…Y—u~Ø·YÅ™ˆÿk¨Þ=xqXu‡vÊ=Xfo=ÔÄ sÛüÖïBA PˆsƒAð¸I®'ˆÂŸðè”./9Æ!ˆüz! Ž»änyL®!,‡K ²“\Š[™É&1™DÖ)7sϦó¹ìêe M§Tz:g/¤ÒsøÍJ™S¦Îê5zmR¨ï­×éçºÅz­e¬¿ìS3ÝJŵڬ–{\~¢c–šÄ§ù)¬9ˆU ‡¸ %1œ@‹Çcñá@`­»Ç-b•í­v1Ê¡x¤›EŽFähÄjK4œEeÑÝãe0Ùíî’}¶Ú}¹ÞO*T=}9ápyJ&H¥ó,ôê­ŸŸÄ®Ý+•«7g·p·\{–û/ŠÛhÙ·³ÍìÝòüÀ»ñ˜lX‡…È}ñxЀC-˜Íâ“:³í#RŽ4°*BѤ “PÚ5 dÛ´é¤"妻\ÙÃ.+–Þ¸ ºG9ÑŽ ¹Q”®Å |M¹Š[Á©îŒVñ¬kå;«BÈò'kKƶ(ODõ3‹ó0lkľ¯Ä¢Æ²d R^…&p„Î.ÂÔ&A4õSØ51$ÛMP«k6·pÓ~ãF ¼>âº,éDîs¸ê¨Šƒ¯F±ÌmBPr°µQ2 E¬ ÄêâÒ⬟áI ψ„ùÊJ @@ö™Ëð•"‹Fò|†œíÂSeo3Öót2ÃI5s^·‹]<·Ö*I;¨*,]g8+$]eϱœc=Ð.³µ?ºNäuEG´uHGqúܶ\陬8&õ*¼/A‰œ à@¤ŒXcQ± mM(‹@ UÕ²(¥X´*œÁ^B >\¡3Ó6áðÃcbÖ-§9Ú³¬H¢Ã±e¥Ú4ŸmPJ¬cå6YpºtdƒoQ±í¿™f7BÊ5Ý´´´Ì„'ø -+Å1¥ù?€¤rĵLÝØ=}Z5µô0×ʼn bM~ÀÐb6L39â¶5› ãóÊ•‘Úè.Ýkå9,ý–»T>a¼[·%×pÒ2!À¼Ë‡ïgT¦z‡&u6 @…ñ'±Ãó¥éŒ˜ Z…'»2ÍàÏKs…Wx†´×ÌÉMƒdÃx¦3aÎ=‘ØãÓîÕŽnÕ“EëEoÛn†]fù}¼ç+–qG𙯘ºÀt»ÙN²[ SèÕ'/)€0R†'?=Uæó°ƒ¡Ý)…ÁV¿×u»#i´~]ÖÌävSÇm9®â¡2FæÛ]Ó|9Håÿ—ŠáÔ9åmõq¸wážiä*K¨ì“Ö_Gø1 „w½Åêö£–{Gà00%œR¬Y0„°ë©l¯µ¯6¶Êì:Ô&¬iޱ·h³ §X±£³cuî®,ÖFþ™TDw1 CDWv´Ô;À€Ó6GÀ—šò[û9Gð=¼¹+Jáž?á)VA±j¼ hf!}B9RåÀDë1+× »*(&\¬§M ÍÊlBÒüà1tÞêÓ²ó ÿ·)0ŸÍ ‰Q½#G…#f‹1’9âI†g6f¢@¢“bm¤c6œjœSÊ€Ä*)ÌögK—i `9¥€r=Ëänkjî^Çzo> {ˆ0ý³HGs b$C™ÙÝ­¸šŸèrxšÔJiQ8%tTª”zI¢Ï ÃR¤n< Eóí+FH‚{+ßR¦|ìCiq?)Ëó~Ô|?6;PŽ<‘ TFê¶d{™Ò-oÐögS¢¢><-ö¬IuË%¦£ƒ‹±¤X´€ Ð9­rVÐ|k$f„FÒ¥Ø54–ðÎ_Oøçkߣ³˜k>`6ÊB&M@˜öb2v_#"„ª.‹©)#S欖£•Z©¥Ç¢5ŒŠ®u€ŠQ))U£• @ÆŠÒ=ÔËŸ¨U«¶[?m•¯á“”;n_Ýn¼#ˆ“"à5‡¢´Bg@ËûT¬Ë¹QJ‹$ s¤¼Xyöe³áŒG½ÞîÐJk·w-!„0€Ì—©dÚ©—iÂõ^Š÷]ÐÒÌÅx¶ÚÛÈy^¯¶1eÍI߸4 ißšqF¬`+'s¬® y–X‘³ÀÆÕƒ>?¦-' ΫJÃS¦ëÚPƧg‚ZUÖ²^+YýŠ#ô¼®ÏÞùÐZ‡|› Ír†7K{,5þ™òK:U*%d0DÏXòÉQl‚?×Ré4 K$Z«¤§!h¦"1¹9Q•r©’ÄZƒ‘Þ†ö @F~µ˜èì)Ô˜”ò?‡q}[A‘TFáÈ|ï«ìM’xökÕ<% ­ÍÏ÷<‚d¡¼ÔœÜ0«Ú”ÚǤ¶P!Ñb3M9ô‹§¡–b½´jS·÷Qц6Æ+Ô¨ ~n㿘ëWÜ}u65åÐ2WAä] U2BGÉz(ÀF,/”öVû?3¬e¡ztÜó=%nGÍ­˜Øå·ž@6üÙ«fpˆÒ?rñh—Câ­Žf1ÁÑ“ÃU`žD‹»uŽrífw¨9‰`øäü£)öNüæ†ï…%â_‚“‰­ÛNŸæÚxõ˜©D‹jÝ®%ˆnúÆâq裺ºÌÏœ““õ,‹É7‰[ƒìg]=+…wÆß\׳ð D 9ªd½%ÜYµñNd [fÛí´Èx”IwÚÂe·Ë¸lT Üü†n܉F—OW׳dðVÝ‚âÒ¨ÆT8_™v0d'X!ÒÁwªã7ÏUýðÍÏTt:{ÜV‚ÕÛýâß_«N–xÖ7ÀÈìñbóõÈÝV?tɃŻþ d²½l©òž¸ Lzú:i3ôLx2‚Îyîv¥SÅÅŽžjH…AµO±¯U¦n+"|%Áêp6¨Øß‚¼N»È]kúˆZ1´À! `B;( [²¾” sd€À--3M;{”!éˆ"÷¦  ¡?+8³¢a¤I•¤CY:k¦?‹;1ÛÆ¨Û¬93ß<\´¬´ ™ªÐ´XVÀ˜¡"Ñ@,7èÉ‹µ…êÕŽjz’û¡-Û5&+Õ½‰þ¿e:SŒ¢|'&ƒ¨.3Ä*k‘;éi?<³ºF/ì(³É2#ÜÁvG¤)ÁSú¢¸Âà„äpÇôo„dnˆsü‚{¾£ÿA¢2DÜNˆ€ P8$ „BaP¸`r-˜Ä§¹iÞcžã/ô#ýÿJH#.øÑ­ÎsšÝæ¹KžY&—ËŸç7|¢a-˜Îfr¹Äîm2›ÐfSIÑ·CšÌèòÊ52‘N–é4ÚUB«#«ér9ER©Z¨ÌªV&Á±ZeˆIå 'IêYr9{×bïò“„÷‡1Ì c @ÁÌf7Èdq¸¸ 1ˆIH‘IÎZ™ÞcÚ8ü…÷Í$´ ò…LžM/T]f­²«Ñ74ýÞÚ¹;ÛÖìv‹-vűµV*ö~JQÍäó-³+g?©<·ÊxíÚ>œîG4R­I8Bk!ƒÞÝÀÂ/§×í÷üeA±HÅ—¢Q¼)ãîµ®é B£í::Ü(-sjž¦êò§ 6Ê|Þ¸â¼á,ÎCƒ·ë:¾é¬Ž$T·)+dRæ9.Ú:º#åjEtíÅq܈e>õ"Ë8c"ÈÅOV$Eêçh^ukHñAë‚7ªE}\ªuÅkDêÍwcEk5„áOËZ“<횘מ*ºFÐb6š#S8g]jÂÒ¨â†Ó7.U•å’ƒýHR-$ ¤^ŠIZ÷Ÿñ²íЯהmŸ^r;V-Ì1×Sn8àó»‹9«8V bYIBØP4GB^v{Š^w”½AQQÖpw†9¡JÒ€H[ÒNPÊå»Îõ–Ê4û,!Œ€^‹TrgÃìþÇ ^‹¥R‘cZ>ÐÓÖN~ªßøf«F;—?ë+ƹ´b Ÿ³ûmÕýF2»¦Ü4 ï╹’ [¬¥%o}ï}ßÓù5ЈÝi5ÝÃÁw§qš±Ñ»Gäò‹ÆŽ¹NºÜJ¸N¾ï¹û MŽë¾²@ðËü}Ÿ‹ì^ÇÖuKR¥c¸øBõä@·‘Û¹7xÙK¿€P ¾@ è `ä5ƒJµ™È{4N%Ö¸¸,ó¨P¥Ñg´Fˆ½žJ_„M|ºÂC¾jYð­x:‡Øë!ƒïlk=ù5Ø;à`1¬„¿¶äÿ[³»\DXŒðù‰I&,³0R# Ù c8‹>W ¡“îƒmÔÁ–-Ú _.Ž¢,EÈ_âìZ1­×=6Ðâ ïcÁg¤Í`¶‘íºD„ ”ÊÔÚiSè 5ª/þ§HyõRªÅY«KŽ«Z»WêÝa¬U޲VZÍYëEi­U¤€€dd Ð ØQ à è ð(R‹ƒ— ü€' ü€'gridlock.app-1.10/Resources/purple.tiff0000644000175000000000000002063207523137723017176 0ustar gurkanrootMM* Ä€ P8$ „BaP¸d6ˆDbQ8¤V-ŒFcQ¸äv=HdR9$–M'”JeR¸° K€„¼0BŽsÉîx„%(Iøä1Ÿ(sŠDà…@sP€†1—Íe•ºåv½_”K¦¤•N=˜À5ªP Œw£GzPCtc˜ÏûÍîû|½`/Øqi|-^׸é*÷v¸\®ˆÀEÀÖ5¯mK5е`ÐhtZ8ôÔ7¥Ívµª{w©E)Çþizÿgðíd#yþÞÞ¿÷›ç:qÎÿâñÛÉNW‘Îot:ÍÿK”„ãð÷¶¶àׇZ¶éÁÓ]pµfiÇ;bÅ2Ò|~_9%SPB´Ú×¹K¢´rV¶¢Ónk;ùæ¸îKŸ¹Ç9KAnyßÁN,' ºÎ¬ÃNAK º0½»nézÄŸïñj¼çzÔ1³JЦ™ƒ¤mÇ38! IÉBÜ ­¨•À®[ˆç60¼º‡šDGOxs…âÔZÉòøM¼ì0ãx-C¥;k|¶oöSí%<˜2ŸDiA&KɉRJPª›ÜeA’QbhëTª…‘Væ60ƒnèP3%‰ùÅWÈž\0ʳ 0”w]Üx8óɽÃÈy\'Ýtˆ±îBÐ)ó@+äýz²"h´Ú‰#l=H¸U*ÅÍ7«T¨Ž¹V.ÈÉsUl¢Ð«þÍFR_gg !,Œ)JN‘k*ÁÃÛ(w=kp¶‘ú¼<•$$‚˜R ë[ù‡3®Í¿6¢Ðè-Cj\Ô±·2 `Ls½PJèNªžº%(ÈÿZHœJ˜UW®Ñ• Œw‹Ð ŠÆp9­t¹RZÊm‰ë´úñöšO;ß@콉ò#ÄZ‘3"Z¹±WÔg·sœŽ h¶Jãä rÞ U'øÃá 4ì‡z„5t‚ÏÒ*IV¯ ¸ªæü)EIl©–.žx¦zWç÷olûÆê¿ã¨`o­‚¸tâÌê‘r*VxÀù<çÖ64çÐ8,Ú…#º+AŽMÃãþŽòÅWIžU…k„Z€(™^]ÌuÇMâiyqVh½Óò½ê9ôØ ;§ëûUÔZPó¥DιîÆä,ªv·’¸&KÑ,û¯µ¾¼NªÅÆRaÒ™ X£\0ê'0B»õžX(mŠ3`Û8žøé¼Õ^¢NmÜ6å¦î+÷2µŒÝYΤë­óõËÞºå\Ý€w·½Í8æj0ö,££úGg¨“<Ÿ–°Æ§úÚ§rúôµôÖômÇ‚Ï6ÿ‰šªanFÇ&=оÖuà]eQ³ÖAäûç>rÌÿ¼·»Ð5C™oUH1¸xµ'tNp±þZƒØÎ,E“*-ÆF„&Y¥1LJí«i|µb‰W¯©náÚOÎ9L©‹« Ï#¨øòÇöJ“C²&ê²Ç{o]ç¾;„–å×+œsd^Ì¢+ªG¢Ùãèg°à½²Ç òKvp¼ø­y½œ_SLq©8îl½÷ñëêŒo±í¹ä—&ãU{½ñþïí¶öžåÛ¦ÇsæšôÜdžè­Å­§¢à`½Ö!)£‰yFï§ÊîHˈ4Oñf××-±Mí†eÍVßÏÛé_qư¿´>áà??õ2+©|·˜z=ÌÚ/5ô¾“Òzè½¾ø~ˆÉ  Û“€µßÎïÅ€÷®1Ï(¥‡²ŽÉvóbÚêò Xÿéô§«tÍŠøòÐ úHŽÎ.Õ¨¬û ‚¨.Rú¯ºÏTÏ-„õïÀü õÄü)0Èj¯dOc¬F" m ¤"¼Ú+Âá¬á¡¼ÓOúêj½G„½ëÒùî­*ìÇ0„Üê‚ÜëüúíÒÈíÒßP*×ï¼ôð¡ÏY ÎíÎX¢NnU&²k ¬t àMšÒBR=ß̸Lnš¦Í@ñÐpë&‚ø­RÆkjãθ™kðÜPÝÏlÜó¯8×lŠÞ- ®^ôÎÙ0« +ž×®/‰0Vð«q"|K €ÂèŽ%CìP`ᡬÐÏ ŽðÞÓpøðrˆIýëçè좨ËóŒãÎû jìÍpÐPŸ nÞüoS ÎéÑ%Q ÷ M4Ѻ5Ä%À 'þK²$$z @æáD ªØ–aÎËðÚ⎪ԬÖÿèŽ wÏ1¨ªäíbÇo­nÔ©ñnâíÉp?‘!­pAC ÿ ð¶E0º-Âö(Ì-°Ä$ÈH!jÀR;¡¬ÿP֮Φ—+å#­Dˆlh‰.@°×Ї±n¹)±1tä­è¹.ÖÖŠ£1…2 Ñû-|ÉR Rs äNkK"ë¨H!Œ}-!ÂAçDðc#ôU!Þâ2BÛleoÆ°èÆ«zãëw%P’ó.JšÊžûP˜Èð™-màß1&Îß P:¹ñ‘.цôñ'òñ îjk(À1ž“áïD{" #‹¸aŒöƒ„ PÔfdâ/#ï˜È‚¶+q%¿Pò­^° úkŠûLîÀRÎÞRb‘-s’ÛÓ]1//Ã/Žá’ ‹Òë;7p«(rç€00òt3þb:c`´Î7oeo†ê0Ì’9Ñc+Œ×òFÇ©,rÂÝ’ËÏ·’ÙÏEð/é/Ñü“}(ý ³ØØsw!0Hç€B0ïÜv"_X"ãÞ¨Úò£1ëPé³(Ûn4ÌíM2ó³ÎBÍî´ëRÍÎÃRÕ4Ìù5ráfî2å=2qDnk7-/³uDò/Såo\YÇÀÓG<;°PâÄ÷Oâ#ƒí@A[*v7d¥æý1[#ðzÔ±S ¯ðùÓI®Çâ©0ôr÷b) æÓ†ð”2C‘A0l¶t‹ó¶ÜÓ6¿ˆ›1¸.Í’dû‘{-Ô·DQDroL®Û=tMSSá“ÞBa{>FTb ´8äñ8Sˆ*3Œ ;?â$ds— ò1Îpo]$ ÍN‰U +ÒÄÜt£BóI,ÓÃXp—}Qññ-‘Ô±TCLÒûS+LÓ}6Ò÷EÏSu»T±› £È;¢ŒýâUâ11s9ÔúìË$P{HÔ”ÔõQ.¼ ‹öìKþݲa_”§Jð&û3Ï-³eð¢æ5§'tËS’ƒE6[µ´h´aEt_T¯Ó2AOrþ ;)‚$5à÷Á­Mçi]¯–¦°u3o¡Pðù4,éB³ENUJMâô/» SÜÞ´¿g6 Z²ßZ•±>soEµ¿[’í7³âßpC7uBýPöA9(Àµd14 R–"ƒ<”{@³ ò¬Ôs¦Ÿ EAñØù¨" 3½_Õ•#Q Ñýg±‰a–ƒDÔ½gÔ×i4ÑSÖü“5@VóîOT~s,Q©UÒ"!c=GÞ¥#»d§W)ï+qÏB QAò]i‘IÏ)5Á`LÇt9Yt¹²åñ÷hqù6½uöEWcoö—M6Ž6¥ci³ãpwgTÃ|´ÝF—&tèþU`}¢² !G¬C# 5WÕHÎ<ñöVóJ3¯)V`úÏ75ŽÕ—[g{=-`¯½ SiLvý`÷{o6‰[•?Myw–EïÓxmy³ %ôè» *†P“÷"ø23]±ÃÒOVËX4#$p÷0… 2Óm÷Q`uŸ|–tæp3<´=.vwaµµL6!vvwspê²wwb6™…¶žŒ~=”z}4é?ËB+7!yã…z&hnÀŸöÍWvWlóCI¶Ó_u,1wUƒñ‡Y××|îcn–=vvöñ„÷ßbwkaø_…8`E1H¸g0˜mw!Wy¸ rr4Vm>§0ëP•ï×;4sA%ö×ts[fØ=|ÖãŠouw]EOWK¶‹}³k„Ôϋ։T—s~·w’¹&“IxÈ7Á9MãØCâÅì.!×€˜ykµt s[½þÞ5¹à°xL¼c„A¡ð8\M­„Äb0ÈTÖģЉ R-#ŽE$XTŽ=•È%ðFt¾EgE¦sYtíÿ7„Ng°©œÊ…6¢Ñ'ôwûqJ¡Ð`”ÊL!JªÒj0ª­f©Z‰/bÕz\J·c‚X+¶›5Ž»g¯[ª‡8E¡þ¥%5®£›ÁÌ­{‚P)Â0|V/À†·×{8cxg]à±h„]ÿF"y½A'“Ë3R¹Teÿ,˜ëf› ®Ïa<‘϶SÝ^ÖƒSÞP8]ô·B¦Õ8õ í³•@±s«ÕŽUŠ¥Ìêõ,_bÔ½íYl½ëœ[Äÿºy|¥©i¼ÿV”½©Ì«þø­wà< ‡Œÿ0ïÀ R‚±œ½'¢’ð†¡8æÏ³2>#­KX͵ bL‰4íŒ9 ¥-£ˆ×'éR\8± ¸Ã‚¤9qlTæÆQt`£*+ ¬ïÇ*ã¶ì­OJÚµ¼ë{Ì…<«£Ã"ÉKšµ卯ö½ïiKp"þÄ?@ Â1Ïûüü 0B¦0Rg'¬Á¼-4 ô! ”é 4Ì4ÚCÍkw·“üDØÐ.PÝ6Ž ODÐÔ]çÇê[“GºT›¦ïÒò!$Óõ2¸9’CµPÓï+Ö„.ËÁ8¯0FÏÀ„ÿ’üÃ[ ¤=˜Á Ök Oi¬ø3l ΰ¼çd´±éO3«]g¢±LI¦Sò`áµêXã7Î’§Æ.•§\îE3tºË$sJS’ :ó<•é!H—¼}.4û×*ˆKÁ Maˆ)Œ> ýÀ¼Â)Ñc`scÚgXme[M Ù–{NÔÚvͦ˜dÑ}¤åÅ‘,aqFVöS]š›ºñÕËH)îå-{Ç•Ý!Éjü‹Pß9þ‘#I¨AZö.¸þJ+Àsˆ¬<¼VŒFÿŠ@…u4Ífv¢kiðZ ¹c³»A AóæßhdÑ[_Bn´U oo6ÞeÜÛþg]÷wÃ-YæsvG·‹±ÆR ÑÈhºdRršZ—'Ô³~ ¼jsXs°á + ašóƒ §¹Œùâö ¤ÎÉøÌû3–¥ ‘7{ŽC›rÜOþ=¸ØÛ¼•Æ™}×Ò´|zçh\Mמç·£^¼¬™yò²Eí¡ü—Õú‹Uù9+õòÖ쿽LÓŒÎÊ2ÖÎöš6à´VDBiåà,ÖT¡CÅPMý’¼ç˜à\3gE›²ôpá\{„gÈø¬¸Æ„xa “iOˆô–åHù¡áI꘺¬3ä^Ì÷uŒ=Ò˜GNa Kõ?Áh1(/Uêlý<;Ôù ÊC«º@ÃTÞ+Ìp­Õ™A¦]ѪæqÜæ8u^Ë‹]‹ªFW2ø”Û—iMÌè?ÏQa…¤Y*U€?ÄdC - ÓÕ˜Zµ‡ŠÜ)†ÄªÉëfm ᧸›sÂp)ßøòÓ0y­íA™>¢¬ŒoV43DZ #CSMð•øTæ#r£ŽEµ¥šçE+Qtü!€´éê³~’0˜çZ)@ðÈÚÖÐÚÖ[¼‘Ìq‘E),ï^BÙZï=l7ÉE&%äœ1ŽTFµ9å\#SÑ’5Ç)Ú¦ß#BѪX$ØÙ-\̸…ꤦ°÷2Ëû¬ L%ÓLgR˜Ó(ŒM(c‡ü„{rnQ1j’„?àlSnÊEÉæc9bô[f‘‚PÒH6ŒÜ{Ö•Oz•¾xÒvTü&–Kî}KHá<„º"Q5õZ«Ì:²0Œ(ÀЉ ›sˆC9ØÈŃ5dƒ$cê(ÀiºmÍÜ‹*ONIÉWÞŒR1iÈBS#2ñî:7ÏHG _Dm^Ž]õ9Yø/[YåŽâr^S÷D„¥mv¤?WV­"õØ qŒ‚]ÒΉo hÍÈ¡F¬´•“s~‘*¿IY›7*Ò¦.ÁiVá©}.|v¥îÊØKMgÍ9_êÚùní…,0@âÆûAj-‡Vc&@CC‘–#:FÕ:±%ÔØxJ*­¼¥­H›õŸ”1Š#+½iâý-+¶µÖ{ÏLé­sHo™ÉW+ml¯x"ÂpÌCrU€aÈKRˆ!JÆXáŒÔl‰x‰ ®m@Ef.Vœ ©äÅiÅv©=¢Rb•VS—)±®ÕÆ3Ï(É[¯}:…tÝ¢–{ÜúcLui¶ð¼[áŒ=ÁNv­Ì\qÌ@–,sÌØ‹4*UnöfèÕª³gnådõuëÅŠL¸ï,fËU¨ëbkX÷¥}¯¾–WÛ;×|ܶkT©µ´ä«d’±ív,w˜t¹Q¡Í†È7þGàBèc³¹­<“Q9#u.ΣqR¯eZÂóQ‹µ Ê FµãŽ9…¢c Ïmš+žÖÆZÚpz£œø§YÂ<9óæ´ X0’ ÿÔ|û®LÉ"ÔwÌÓÛ‚ìšx:*ée%¢6FËœjSe|Cwédè¼ó´êNÌR¥ïUìr8Ë3f«nú3EôTùÈ!gMz}Ì 6éÔkàÄ4 ¯Üè!ÚÑy·7p¾yøUèN<=X4•¢‚õ®´â 3jmZGÛ×â¹f÷õfßÕçWšözš|w—g·Y9­qö{Þ<—? }rËiäÝÿàë7±îÛÉÍöoVKCY¥Z{N+.éÉNäôšÄÚ‘ÌSMMkcV1®Ù³‹ÓjôA®«=Ë9ðÖ D¢°Kxù®C¾KØj. BÖ ‡Úb„૘[f(Í¥†òÇ>î›O pšÝÞvÖÙ;¸“Rôî'Ô/—ÛÝ?r%íDgg8ò@¿8qؼ‘ÿìˆAj/P;gØÛæŽl®Ø·ù¾Éœ7†²e—ÂSÜËûYxJ®Ñ/g±Ü~}ôÏnB:xð]IÎ×ãÚü¸Æ‡Wú£uÿ'òLYø"”ëã/½÷åÂ{í–sm-I ­dôÓ©éÞZYÂôéZ蹃½ñ ?í½¦¨ð»‰(xn-¼9v=¢0Øãñ»5³ZL+ÿð€À£ûûµø) cë2’;‹Ò9ã¹=)s»³¼4ÛO6ª3™ëô6¸“5!;pË:“Þ¿zö8À‚x„?°cxÀB‚P 97jb.,1A¤2þÀ=‰3¾‰>ˆêi4Cо±¸"ÂB™êuÛl;Ѥ©‚Ö1Co¶ì'2ºÀû©1‹ÝDB7œÙµ†3p%@5ÃPc3û<¼ƒ>C,MhC@¨`^·©ã°p=Ãs™¸J¸$;›íÃÂ/Cä;½{ñ1b™)Šõ=¬ ¿Š}¼,5d \R2܈D-D™WÄ´/¿äMÆZ/àÄù5òȈy'‡8Bø‚„ {§(ä«f¸+Ó¯CÖ»»ò/I ­|t:S†'ŒuÅ£2¼v•+ÜG“úˆžÆÔ`FÜGFØ»@B‹ü Cv*4eCfH9¯DÀZ‚§¼jFÜkFĉˆ(=ÆÜ>Ôp­$;¤¸TrGKCÛôÄ?G„(ÄST³D^³XcFkF¼{ÆÄ}©Ø‚ !1Ì…Á{‘A‹°f€ P8$ „BaP¸Ä09--HLg»X´ï¹ÏoøÊ8çFGǸÃ8ÖçÉ£ c¢M.“ÊMrYŒ²a7™Jæ2§ûk?”O¦¹löFPh´*5fÿ^ÏãER¡1«OªtZµfŸ]®V,U;^«1ZÚ,«[ Hÿk%#Œèôôæ÷¨EßéH›Þ9B@Ç01Œ 1C1X¼f7Åâ`@H@bRB’ŒfqJPÞ»Æd/÷~΄¼5ŽsIÄòm2¡ÎvZù}7g;§Ó+[mÕ~—R¤pW»úu:“ÂàWy6Ú¼êÉ[³ôy¶nŸ*¦s—j.67i¡ZÞd$ãXRžðž¸†È|~_?§×&ü OcbõŒ%ˀƼË©¼¹4I´g5iꊞ6ªd"£Â ÊjâAÎ+‚Þ¸Í⎯C­ÚÀé8n”D±,ë$I:Š‹žê-‘Z\=µ-Ñ¢Œ¼°þ1†$!ŒÄSØ0¯kÞûI’l' Œ ?d!z^ŠF±þo kÃN‘Añ8‘4f²ÞÕ5Ël×(í¤,Ø·pä6àDNdO7ñTç=+ÓÔNèEªüYÐ),tgFÐA1¥+«‡ P× ˜ÈŒ†Èì;'(S”í<ùJL²1¢H¡œ½$s8kQ<ÔÌðl'8Mµ¬58Âõ½jã·µäYP±k˜åE4 ЬÁ±ÊKÑTeŽ;èãÂŒ‹ëÎÀ b…,4—OÜ ĆT/8b-Ë7S£L·0”µ]âí̉ì6 œ16WQ è¬C dJêN±59:ÑaÅŽý–¼.˜…y™Ø£¸9£…êô9ÝFuÌõ L1% TÐ)\yNU•Óo»ò)"Ñ(R‰EéÞg wjëV$EmWŸ.lk;S5a_(—ò•]Oж›¦Ã³ê¡<ØXE•ÖQÑ­FÖv€cb—œr¼'ËÁ()fÂVbRÒÖÚnä’›–n›®Y)T €#œ‚ÿR2Ø×zè9ÿ ¸^k ÕzÕî—Y5Ü<ªà.^¬äá¶N³ˆPð\Ëgbšþ)g;œþVð2…½–Ý$[–òønݯmÛÔ(Cs] ь״^wFÚ+yy*á¡´fôË­Ak|C$¼ÒƒYzË·«¬PÜãSèºâçâl6‡B¹ìK¬i(£›5=md=ŽãÚdûŸoýÿ›¦ð·À»= ±J)BÆæ©9÷’3šÅpïÄ*·‰Ü#[Ui–A¸<½ HŒF°X¹¬ØùÉKÆ…OŒ¹±rð'Ô @Ä5ŠÖ>¶]{p€.È?†PÿbAvÎå’»¤ˆ[PZ‡ŒÍºÚÓ‚pF˜&ùKƒÆ‹R A(²ú œU‚†2EbRé‚:¡j'ÄÁœHR‰×?Xì!Ô:dÏâ!GØýÙkùˆ²<:À•b[¾¡Œgqz¾ ÓÊ‹±Š‹XËÉL–ŒÒbNF(Qr¡ì”F¸Úy#|qް-C†Fì{º‡ú@KYm-ä¹dÒín€W0k PÐNDÁŒ+CXÖâ´9Äù™Ѽ%šQhBbS5”DÕ#“>e‡9”)d`ïa(NÐbÄá•!Î_)wæ‘ÒLx~ÍÊBCùq=çÄùJ0“æâɉø © ÂМ†s -Çès4!HNª' ( ¡ô..q9+ J¤2ºXRYãe“³Ræ{Oª]Ké…+ˆ“ÒšOÚS<›Œþ§î”K}O':¨Sò•ϺcQêEI>/þ•TØ{%䄪4ÖYÀ i jUY«UmOÒÚŒAim^«•޲VZÍYëEi­U®¶Râdd!r!zQ!‚!Š!’(R*"™ ü€' ü€'gridlock.app-1.10/Resources/red.tiff0000644000175000000000000002073607523137723016446 0ustar gurkanrootMM*!€ P8$ „BaP¸d6ˆDbQ8¤V-ŒFcQ¸äv=HdR9$–M'”JeR¸°"—`….9‚Ù0Bƒ„$ú€9ÏgèJDòu@%KsA i2–VkUºåvS1 eÄ©¼ðÇ?Z¥!z0bw¥"{8ÆR±®÷“]á}¾_°òÓÿ y½±‹D§ýÊèŒÜ‚C¼×0^ÙOb˜F_^ÐhtZ9îke9šíL£½JB¿×¥¢æc·‘ˆMÊSyºÞ9Ô©Çÿ ˆçN%8©Î?—Çæny<^w#‰ÀÜîßíd!ïlkÙ¶©Áˆ…þŒ¡å§y˜ÎcCLtŸ?§ÖI¦›RL~¼žUZ%-ÖšÄc¼äŽ£›ÁN)ZRÁ®1þ×A”)º®«¢áB±KÃpÙ)»Žòô–¢ô2£\^³ÊšŸ¾Ñ¬m «!3Ä!Ÿ¸AÈ0Ù1nÜ é9P´ :LFâÉç<žoc›r=¼¤³*ÊòܬsˆóS+ËòáÎíLðLÒåÉ.s]Ãî|Øínô`Ú•¡KÌB%Çx”-Ép¤˜¾QÅ C¤!ŠÆË€©8ªŸåjæÛ7Úâò]3MR›ºâ’´Å,mÄÅJ¶íÍRsÌud³UÌu;‹XT•EkYÔÕ+s]Tu¼ì9T/Bñ(å.ÍÄòó‰qþ÷ë83À D[Êša[G€ùJ·Ò“79®UŒßÔ2íUTTÕ\°âÞut'zßìwß7½õVÌg~ßõµg}WG8×[׳¾FS¶3Øì5tRƒ›pŒhjÓ*¶ÖEЂ’wH*ÖÄ/ñ9Üð•×2]Õ•YJß³õyߘ%é‚à÷öƒ›èx žè¹öŸ^ØV ¦×ƒsWÔQôå7»0K¼cÿ>ò°&¹̬†)€•F¥- Z‰A‹²ïf%-ÕOœ÷nl=çÞýzoº‰pWî‘}Þ¸yž`uƃ¥ñ×ßÉa!…r®.]Þ2ÜŠë´ê–¡ŽäRÙÖ…¤ [?\Ž pEZ„¢ª{í× ìÆX.\Õ#Ö[ÞqÀðœ&‘Ãçåo0@äd’é˜Ë%Åg‰qî BÒkõÿŠB5@¿·ÈMÍÛÞÊN ÎÞîŸÀ&þñ\4 €ïIâÀÅhàœ›Î‚OA ½W,«^ìs.aíAØ87š’»_MY). æ•…¨!cD†·b/J³ò†D?VÚOÝ#ùKIAô©SÄP曇žÐÜ[@±*¹gœs—‰°U„4ø0ÓÞÃA§!7½¢ü ^)|B"G7 R¥…¬ Óß ÖÒ:PÙ<€‚ò ºWíé¾.ø‰Þ3† æ!ÈÀûŒ«+nÐ%.ïL4´ÑòŽùu$yéÄÄ)ù#"\‹ S%êDÉ3š„™šsN=u+'\Ù–rÔB‰¹“,¨¡ bUIXg£Çã°” O¬1Ó?:‰)`•êeHQÖäð $ŸR8X•0(SqÇÌxöjY“’FhMG¹Cè´’¢’blŽpÇPâò_©æä-*j§*­ZÆ4óM9–µ(vÄ9–k,†0B<Ã:y3 `4Ÿòò$¹ë"i½s—´íéÄZ &¨u}‚uþjЉ±$Ø G©”JØÊRè¹Åªs]}B­G<Õj;FÅ¢LY a5ˆ‡–êƒÔ€ÆRcY"Ãúã= <}{×¹Ó+½>ŠÍŸL©`è$ÖŠö6KØú¡e,m“¶Mì\Ê&—êUÇsp€ðYrð1 ±³¶6ÚßixR)bµ·¨£·--µ³í¡^Ëm#+õ|‘Í#׋Òœe<¸6*‚XŠ¡Bì5H©·.#]Rn…Ϫ6JÊÁz1ugµ z­.UH©=¢¼V‰Â~;Ö“^Ñá+©UÛl+¥±ÅTÚ»b»Ý]Zm½—ÖúbÐ|m#dì—¡“bäcº+S.F=¹l#¹¤­df¾G“÷PÓk„šôäóšÏ‹G:©QUõž;QÓb7ŒyLµêÙ3ËÕ™(ý‰ë5_(§}^¬V™u£ÜY%޳¶šø Ç\ìnVEÉ6NU,‰R°Ö FgÇÚö䯰l4ü–ô)\5¤ófðÞa¹ÅÓÞ¿^éq@ñ„¿®(Û« DhE†’eã¼ù¬uÊ¿ø§`©«Ÿ´ Ø9þæ%ù?¢´`)»Ul9­h`Œîû¯v òiºÔvõ½:йbœY11†áy¦œë:`÷;Û·Øú£MaE³µIÞV/^T­ò+ Þ÷C#÷ÑÛœ`ØÆ¨ì´é6VÒêØ“ öOÅèÆm&&# =£$»¦TÇqmíÁ›^rr:ªûãŒêöóÕè7ÿx¹­oóö¿Á@Æ rwæ àû^ð —UNÞN6@A!‡µ¬3‰ŠÓáJ“ ¸a›Š»­òâ‰{}­œø¯8²½òKíp`}ñÖ;›wëKž{4Öì¹ yÜl®po8çV?|ï퇠÷ïyÏüó¾%þV&î´NNü `\üÚ͵lº¦äÛÝ^ÛÓÞC@³t{3t\:¬¦fðÝݶþY —»Ö€×Ú½è}‡À}‡vîÁÍóʧu‹È64ˆÊ“s O·M‹K.…&ä«+zõê«âÚb¾7{57’ÍÖóÍyÜiØûM‡å¸÷zmwÜ{§4æ‡Øú¾s’6/{ç>Ç%{UEÐ4iµÉ ÷xR8Y[P‹€séͰw…VÌîµiÆNºx‰‚¾o,°‡˜§LäË~¡O<ôítåÌ€›o¼îNzõíìînûÏÖöOÎöÏSæ@ïn Bü&äœC* m*4-¦ËîÑHòÌ/”òN¬ò«Þ½¬dë½Ï¬ìíղƋ Ï ~íŒ °8×pG®fïÕ ¯Øßã,ýȼ@ïh7*¦À¤7¬Â.ˆîþí¢%EFAj›í:/n,—Šhë‰~¯PÍ­R§2Š0†¸Læûýð,À 8ÏKÈmèæWp<üDàÒülüзBºPº ”0«°nNŒœ n”ÒÂR?ë¬HÂö® @®0{ï&·-ÆÕ ̘Ðô¸,ݱtÝ‹õI²î ’üp*õçm…Ñà0© ‘” pQð±Ñ*U… ðÂ;`bOHcLPÐÊâJ3ÀæâF¼ñΤ¦'ö½i¦«ëMXư‘ÎD¿ªtÎðþôHÁЖíp) nbæ®dÞöüP51“Žw­û O` q0ßðÁ @„ºà <ÏÃËA bвãcPù-B‚ ‡L[òóäð-Òš@ÎŽÌ’k ŽÝ&íxØý °£1 ý -‰(1¥ñ§(ñ¤ÀµD$áŒÒ‘¾ÿ"5̵ÏþÎ0ãÐx˜òMI…0ûÈ ¿h°ÏŽZÝ‘|±‘€©Ìõ'Nëk¤õÒæò.Ò¯¦é)J¥!ïcã·á¬#”€0ãLOí¡#B6é öµD†„Ì’ÄÌŽˆnÄܲdz=g1¿‘på‘ñ±†À5q…òñ rï(£/ó6ò²RsRÿ7ó}"šàMå"òªñ2 FNËVµ°q$gò¬_40 ‘NÀäR_;o· Qó ‘y³ÁËG¹!Sw/³j©ÒøöRR‰0sÓ(ò‚°µ"#·c þ}À ub8P†ÜÏ+R@UN¦ÈíHy*k;%Qß ~åPåk;ÌöæŽ_°Ÿ<Ñ笓 ‰/Sç7²ýÓÓ>´S=“ƒ>2”ö¦ècƒÐÅ1 Â&AÎ÷Òª#%¸¼ƒ+A‹4hÍt¯/%ëüÕîȨ‘tíRè° êô‘ýD2äîNîï”M'Óy ÔY6²‰FPï“E³ëFe ij0ÔpcàC1ƒ;*±H"…ç9ćÓ0r,N§“P,­×µ 5¡´52qJЛTCK«”ÅÑL“wMR“!õ5S`R8pÇ8¦äOà# CN¢& B\­9ãkO§ŒmOB ]Ulú¯¯ò`Îj…Ô0û‹¥C­T=RQ‰DtE6SbýoÓR’/´ÃL³s>T]Sôc85±Mr‘?F;`B@3üðÕR#îmOt†@tüúRSHÓGIrW”ŸiœÖÍ_-O¿5ø²2ßK5—R0¥RrwÕ§vSÓÝ7TSLu³Zóá>”Ö`Cƒ)s†ÓôÓŒðbe\“’"bˆ(az²æäµ“/]‘aIJûÐó‘jÖ«‹&2×&4«ukD£°ÇÓÃðsHÕ¶“Ü57q$üÚDÓå ßÄqs‚å¸ñ«ºz¬ëÒÕ ®ÈÓ I«½ »²ÏPTÃOï[0¼3K6FI-ˆLKõ0LUÀ)0ÃÙœ„/K4ôŒpR&=§“œ2†Î­m™Ã¼;Cv¤AB·q581=E·‘K‘F8‘tiIF×DyG,nŒŠ¢Rî´…xIŽìy'Ï*é|Þ*ü 9Ô¯RrkHaœ @õØ N1!jÄËuËú->Ä%| X,ÛÕ3Í <ÏЫ‹¥ºg¤-Í Pt5·”¦±c‹m[ê{}ÜwJÇÒn*é©Ĉá,ñíïžhW¢×Pß•6–´iµ*Ù€³âk"þ-@+/€³ÿˆ±¢0W³\Û¬ÊsŠ(sØöTñ;d9oidùNïiP9tOEe›ý½›\ù‹·ÁðÎÅ×çô¦•yÝ.ƒÇ«ºïI×Ü™ÊßÚSàºÁþ)ñ Ʊ¿ €®Ì{àl¾4ôÄ»ƒW’µÕ ”wv¹’xVÄø1І_Gï–ý%™¹î7èç¾—éS¼51ì]÷f‘£{ׯ2ìÞß ƒÍüÉõUJËáj, ]ôõ¿W1K`Jƒ?i`—ÆØAŠwJ fêgã(D-í7æ^nRà[°QH’µÍÑ£5]M ñ©UÎÐ ò›hJqî4G"Ó¹èsG…Ì/‡Ò©—³œ h¨¥S0|Gø¥`ã½Ö€‡æ—Cª~Çø1ºÑ(3JÀɹÿ¡fPÞ #Èz*ÁRÉ™loUæ²Ç–Œœ<Q„á½ró¡fqŠf¸èTÑ’T,rÑÑ~Ç¡¡‹OJ0 åV3 2&$°çëUÃeì½&ÈšÚÃmXÌ@dž´Þcw‹ru›×—'\Îp®& A•Öõ%S^1­íÇNø%ƒNޝª’3ÎùÒty.+þ*†Áü‚k!iX:h„~OÜŠW&=Ø&wf;¶€-½ÀÄõV{&Šð6L& |ŒO ˜®S¡:#dih²¥ì½Ø;,\|®o}y¾CÈÓ%ÃMrÂϹ÷.á„M jùö°sëšÙ†a¦ÔÌÆÆ™bg²=6±™'ÞoIÚ-ÑÖúà) ¸‚±v0<¦oJ\i‚w³º^§¬õTj~›$ˆK¡}–2òž y !±é TVõ^ Fq‰V”2eÑŠÙ@€sWÀ…Ù…)%%›v6Ór®EšÁ“Ȥ%š85´ô޳Ό°ipR¹âŽc|j•²Á¢Â”’ùe»ã¦³þ9Ë–¡/ábF—ÓìöÌ QÝ!Œ2D6* Øáø!±.h xš‚–„ÚŠónqA)=+'­UµS P£mRíž4³=úg)Ä÷¦­&ËIû^Õ*K†qí&Ûùz”8/IÄ^ºBÀ 2ÈÄP#"].Ö'ªµë "›Ö~ÑV˜/'Ög”.SÁêã)­dfkººÆ×±^%”ò†Uö=4úpEù°ñ—ró¨˜9VNº¦Ì”sîx1@)YZ¬]ÚÍ™S[ É“R¡+%#ÑrrJθ”„¥µV¡Êk^rTu„ŽHµß‹ï³â·)>úÓûõo#½Ž‹øFGà¤ÀÊqÍ`{àÉc¦T‰ÁS1ü Ø–ÿf”Oš°&“Uø¹8Y– yŒ¶“AºÑgF&Äײ˜½«Ó,é¤ú–³òÁ$\i~ï¾=ÇúþÔ¤çqé$1!ÞbRíÌ¡öC&Ý\!"0ø]j0ÛIcp³ÖŽ®áÙÆ¡âñÔËAË]+%.ƒ®2×âèWm)²§ŽkîÛçf—޳•ý zÂÀ5<SŽ‹-tÃHwé‚t>Ãu¦@ZƒR;ÆöS3(+-1ûÇ—¶•e¼Y^”ʹÝi­\¯½ªY¥=ÌÍ‹OàÅ‘ã6*Låœ-ôw¨:ÚßkBížöY ª¶?,•sL3Ø{÷EèÙÚ–ÎPußRLµ¦vŒ£QÛJ¬ÇKoG®—²W´HO=µ]óÆçUÏ‹o»3¥<··û‘Kƒ OT7ÞS Eƒ[!·Î…ß¼×}ºà!t¬ Þ3L-'¦… äœoúj1F;iÙ´_µ+“4~š÷­‹I½ußqñµá Ü®5·5þ|×¹û@‰>?Îä?²X>X@ùá €¤!+#ï¾[üæÝÖåàФ¯Œ¸çàx]g]ϵ)E%ƒµøZá¨u&¡¾Tºyõ‰g|ºæéÍØòÀnÜëæs¹S}R‚ìù–ÁæÛӴ˲©zk%M8áå¸óï/†ÌZw‡½#;­OþópcÛ¹ufq¿ËâS¬ç-¯Õþ¿¹ÓËCXnˆ„ äc+>ås½?ÛßgäZÝ]”“z%AÈ£,åÏd¸iO‰Ôûø»×ïs=vã;«ª|+q ¾]|óV÷Ì;‘­û²›³¼ê¢‡ø^‹Ø{’Ú ¶ î@ˆÆÉ3‚ÔÈw»à¾ûgº+k­"³#±[Ý©c6ú¹‹ ¡Ù¼‚>3›É¯ËW>KY‰ów>{ͬ ) ˆc2wÈ B=å¢ BHþ·âcÀF6[Ö¹ù¾ƒ™½›Â:z·)+Üžªõ<;Ç+›‹¸ÑO5KsC´<¤<Óý¼»ç>[Z©ü1ò*y‡ø1•ƒ˜µûì¾ì>BT?y×ÀBˆ…èöŒÙB ƒË…2ëÛ‘â¶Âés'l.?yë·#ÆÄ³à«Â|8òž³sY9 þ±Ü7|8@¯ÄÄ!>¹×4¯>Ô?Å™û¨pFD$C7¶ydó†"û¥D’Õ¸“S¼|b­«ü:Ë-zݾCæ·DA»À ”“ˆ@Nk².é*@»{D’ìüE¤tÉ×>ôB@˾ˆxœ‡øB1ø{„ óºCŠ4ã¶ÛO½Ã4¯ƒr3YIÃ!$½ûâDëüÁ|6‹’¿óçC{æFÀǬm‡¸=Ȭ8‡8% È^ŒŒ2 ®dsE”tÉ,uB Ðg?{•A8‡¸9ŠŒy1ü™È˜=ŠêR1,CÝ1‹n¿‰É¸üL)¼fÆ„¥»’ƲÀÁÃܚ$mÇRȘ9„ ƒªc¨{ÉD"ÃÒ§2[aI(€€€ P8$ „BaP¸ä0-1ˆD§»¼´Z¿ÏhHÊF%îóÙíþç5œär™9Œ×'–J%NùŒÄÇ*™L&sYÜšs?žJçÓy„úY4£N(’Š4š‘E¡T)•#]8×s˜éµ ¥b«-£W£•Úå^ab³Úl•šô~I¥±Õ+ýîs‘E¤Ñ"ÓÞ!B@Ç01Œ 1C1X¼f7Åâ`@ˆ@ RJˆLg9J1w•?ä2 Ý c9ÒgRºT⯫kusš~Ò¿¶ÕTö´ºý?}·­U*Õ»^öÍS”XøüL¯•ϰZy¼^‡OŽsé“’ ®›»Ø‘–¥IÂI¬1 OxOdCd>_?§×í“~E(ÁˆÅzo BRì—#«(í´M*<‘Žm’h×B š‚ß·-ãdÜ*‰ë… ·K3jà+jˈã¶î2ÐäD‹BÈê%±:Ì{iDº®+œ`ížë4—‹6É Oh½σï#ÉL”‚2@1¿Æ³<»%‡ù ‘¡8¹Á)KB°Œ?«0Ô11¬±†èñ @¨Ã®¬K9*Ϋ™:NZÂç.Ñ‹¸Œ’…ª2N«¤ŽÏ­È‚H’ ÄIt­-K¾rh ‡$Š"Ã2ÐÔ¹,®ÐZHÔ7-„%VµÍT>¡Ö0Ýg4Ñ,Ý:ªSº½=ÅŽ´Tð-õL@Ðt)ÿB#+ýˆCüô°(„Á aM&>4ŽoÜe4ô" rÍÔ58¸Æ…-•w$CG#ç;S\L·Åu}MnCyÎ÷î>ES‚OS͆ìÊõLidå)œŒ”¦2A.YËÒâŠFsÐõ[‚÷ L;'påNT‚ɯËô-!I(^‰B‘ÞwÀ’´dNPGù[‹gÚ·@G]é/Wó‚‰[ß3mq[¸±’µ¸:ŒÙ9«–#ÁFDdi¯Y(É[‰â;&+>Ç 1z) h°R”´vB[R.KJe{Îõ•e¯€ ü‡2ƒþ-TGú¾ÑAæÅ gø¥”¹^(ëJ=»5%ì§^ø,á}ÄU¶jq%€9µæ¹>ÁW”µwñ›6ÈNhd¸5£ôJU³{ø)ntŽë'HÛß…áø”ÖGr LË6¬¥çÿHŽñ6Wˆè>#eqWg#.èí2ÝÊA‹Hwù÷·Kð¤þÈÔ-ÞO÷á®ÔþÑK–g©ŠuÛÍ ˜ÂDçLËcç­k77~ÉÝ õâ@ØÞ`d xä<—rÅ[`ï.ë­°,¶zõ›ú„O]Ç(6zö^ÌŽ©í¦¿ Ë´+~oÙˆ=—¬Ä¡­Íгç^²‘vYÃ-²i…j䀀kÕ²ÈÖÜdð>*EXñ›¹î2@å˜Bf†0Έ°i?#XK¡Ëd„1¢6CwõcƒŽ1²5ÂÕ¡ìk‡PñA»Çübc¾Œà¤ÛÄ¡’w‘:F7HŸb”V’RNJ7ˆY3twA)˜³2£ 7ëØ¸D–ë#ätl‚Ö<Ç‚3+%L{gÑæZ?‰S[@Y?H!Þyì‡"QÝ¢T“" P(À¤›%f„ÑšFLÍU²ËÊä a® É>1†±Uã8ÔŽùÈ!yqg¬A™¶âö|ð$­ANA=Ʊ؜ej_³Qœæé•Í—(ø˜ôxBgÍ*Cè ‹,@ˆ&L©ùRnM…£ú'(9¤ œR†:H—8œ¥ ‘„*KI)¥£ÔŠb¤1èBBwó1nIh#DjA¨D*À©­$(µ ©3.…Sº›Sêcv¢±BžÐÂCjY«UlùTWƒ$j=¬5ŽfÕù%ªåi­U­pÕ†YUë…l®UκWZí]ëÅy¯Uî¼dd!¶!¾Q!Æ!Î!Ö(RYQ® ü€' ü€'gridlock.app-1.10/Resources/wall.tiff0000644000175000000000000000655407523137723016635 0ustar gurkanrootMM* –€ P8$’ gøü@Àgø,ÿ‰ãhÔf7ŽGäQé$†K ”HäÒ¹LžU-–KæR餯k0œLæÓ¹ÌÞu=žOèSê$Æ%‹b1'ø{@Ñ3Ä /¬VkPP´ _~ÃÀoñˆHÿ ÈÏòŠÿ!-d2)ÿt»^.÷[ÝæùzÀ_ðWì%÷ Ââ0ø<^'ŠÈcòXì¦7-‘Êæ2ù<Þg9šÐgó—]¦Þ8à°`2›×€02¤[Ü °=žÀ<?ÉDÂ{ü²\/¿Ì3/+™Îæòú<þ—C­Õìu;]>ç_·Þîö|=ÿƒÍåôy=^?gŸ×îöú~>ÿ—Ãíõü}:†.i|Ä2☪,áÀvŸà@¶'êY `ƒrˆ(êŸá(NŸð¶¿ã;¬/ 0ID§üOE1\]ÆDeFq|kÆ‘ÌmGÜ}ȼ…Hqü‹ È’L%I\&Ê<¥$Ä'ø¿®+³X×Cl² eꎃÁD¸¢L+ 'ø¬- §ø¨,Câ”àÏBÔù9Ïóôû@Д @PôEÑTm FQôuHÒ”-HRô•1MÓTí+NSôõ3PÔ•MPTõ +Îè°.âp¢*Ÿá€dŸà€" ¶'ò2 `R@€€*•5§øx gø˜( ¯Š¢Ìëk ø¸0@Ý»n[W½pÛ÷-ÉsÜwMÅuÜ×UÛv]…ÝxÝ÷­é{ÞwÍå}Þ×Õû~_ý€ßø. ƒàw˜¶/Œs´/Cµm¡ÂPš…õ½r‚M‰â†î @áþ¢ „&Š8v .Œ/èÇa™¦g+fù®q›g™Þ}hÎ…žè:&‡Ÿèú.‘£iš^¥jN¥¦ê:¦§§êú®±«kšÞ½­lÎn-a‡þ&¸b§øX†iFMaþ5Æ*'ZPþ†ì:îû¯ì[÷Àp\/ ÃïüOÅpÜgÅònn/ C1ÿi¹9ei”­àØ:ŸêxPõÑþ†áÙÿЏ¢¦ï|%Ùö]¯Ûò=·sÜvçuÞ÷~{ØõÐþïZ†Áþî'ÏJôýOV%u½cß{íû>½î{^ïÁïüZW‰×õžUçŸÿgQÕ}>/a²ü¿íò~ÿõúÿïöþ_çxÏQõ>×Lûž“ñzÏÒ@×üÿüÐF A,î`Ó8¯¾=ü #òzðN Á(Ma$)„ð–=ø2ú`ãìƒði¼¿6ù ¡l9…îCÈWaÄ/€Æºh9›Ô ‡ñ.D™¢lO‰Î!A·¥ ¢4 „0.Å(½cPŒQN1Âx«bÃЈñn$ÅØÃ#„_Œ±¾9Gkâ$‹0êÆØéãœŽÒ :ÈV}"¼EQj>Ãi 䄆’>IE9úäT‰:IÉÙ#%%ž’®ÒKÁÙMäl#”r†OÊ)Y*åsæl¯ÊH˜õ"ãä5•R¾^K[/å„À‘ÒÒ!ËiO#%ÔJ—³ _L2âd¥2j6IÉ™5æ|ÍšnM)3*&Ln›SŽlMÉË94Þ–óRTÌ©Ñ9¦ÌçžSŮΩ.aîžsÂ~Nùý9g´3“rîÏIû>è,¼ 1îO™ÅB(…¡4NOйqCbå¢TFQÙ'E§dá£ÔrŠQºMéà¡ÔŽ“ÒZYKà ³}LNºUFiu9¤”î–Á:S2)]:§µ˜SÇ·OçÅ8¨Õ ¢ÔJ˜ÖªEÕ>¥ÕZUšõQ sê«ÕÚ›WêeZš´¬UJ½Y¨íb´>³ÖZÝ[j%j¤U¢ºVúÁ>ë•A®ÕÖ¸Wz ^jU}¯•úÂJëTë݉°V*…S(©¬÷ªSZÅÙ[ c(ýކ‘æÉUºÙe쵃´QÍK[#@«\´®ÑÚ}ii¤¦µ®ÖY‹mk¦°²ʆYëkn-ýÁ¦,6b[¹§MìEÀµ· ÛÔ{u&ý@°72å\Û–ã¬=”º—nëÝf¯vk%Õ¼Wrï4ÛÁj®íã½7‘^{?zï…å»wºö_[ãxï¥÷¾×Êõß›ùïV÷>Î[:ç€¯Ö ¹·ûàÛ÷~0$ÆÀÕë`¬+‚ð§·¶¦÷àŒ=…ëî Áø RüE‰qFÄØfÞQ{}Šq$«Ÿc eIñ¦1ÆØî¼bËt®N7ÈXòg㜇rEÇ×F¤ä‰‘ñÕÉtÛ ]¬Ÿ•òL ÈÙc(åÛq)ÆÉ–Nðå Í—!Î[Ë9£6ZLÁcî†Tɹ[5ç\½6³VwÎÙž;gœùž´`ÏÙ·@èK›ìÞÃvÓChÜ÷7rÙÿJhçý ô~™Ð¹ºÚl[Hp¦•ÓZ‹Ké€ÂøÌn;‘‰D÷ùL®[–Ëæ7üLÏ1ÅâшÔf9ÈcÒ(ì–A#”I¤’yT¦Y/•ÌeÓ)lÖa3œM¦“yÔæy?ÐgÔ)í_ŠC¢¨d‚T °xL.ˆÄè:å‰[¯Wl:ý–Åf°Úl–{eªÑk›R*ôºµ9ÿR©]©—:ÌRß¶Ü0X v ƒÃbp¸¼F3¹Rª´Ú¥âS„^òW,~+ŸÎã³ÚM¢ÔihÙÅîí–‚^ªÙºÖ“m§ÕnvúÞëq½àOµ—L¥?/yªf«Íÿ7yÎßsú]§§¤áäó~>_e Ú_ºn¯Í×óù}½Ïg]•îìy;>^×Óäü}ÿ^ÏÏóöê=˫਻ϛÀú¼OôõAìÿÁЊŸ®äù3/¢ æAp”;DüEÁp£¶P³¶åCo´GD‘ŒaÄ1“¹ B°´ˆ¢Pœ†A°t‚àÀ4|‚` * áùþ$ ‚‚ùFÑ|kJÒÌ«-‹ÃÌ¡âùþ' B¹þ ˆ¢Iþ…aqþ€À1Xð!G§ø¨, ‡øº0Œ§øÀ2 ŠËÇü»/‹ôMEQÔŒ¿GÒ”•!IÒÔ­1MÒôí5OS5 9OÔ•AQÔÕ-QUÔõmUWU5YWÖ••aYÖÔz'/Ðt*6,˧ø–'Šˆ(lŸàHÀXá¨râ­€CxèÃîŽ#¨õnC±þ4 ƒ‰ÿ/ Gú25ÝÃ=áwÞ7åzߥõ{ßwµý|ߘ ÿ~à‚á&ƒáx6„ᘎ†âž%Šã¦5‹ãw°Ø£€ër[ã€è<ä‡ývˆâ\¤„!ææ‚¾h‚r(2bHQþ2Û'øð>GùB‘GþGŸäcùš>©«j¤.¯­k:Þ½®ìÆÅ®lzþ˰ì›N͵m^ݶî>å¶n{~ë¸î›Îí½oÞý¾ð¿µiqþA‘n¨@Çý¼>OBȺ…¡€füÉ s÷9Π͇¸¬-Œøò?jd9HŸäQIö$y%Úöý—sÛwïußwÿ…àøßàxþ“âùo•çyž¥èúž_­èzþŸ³êûïµï{žÿÅðø$‡nDݹÄÛ~Fg§ø$ fG>#sáÏ>só„âÁ+¤¨é1±!Çø‰w‚,H»Aù‡üvðJÁ)à´‚pj Á¸=aƒðŠÁÈI á4)„pª¸] a„(…ðÊÂÈi á´9†pêÂ8Dˆ”âE þÂæ€ü!Ô’F;Ÿ î|¹ðZçâÀsàAσT”…ð>Mø3ÀàÕ‚TˆÁ%£tl¢LKñ%DÄvê<Çxûãô|RBH äDƒò*DÈY"ätŒ’RFJI -#äÄ“’òjLÉY;&äôœ”R„G A.?ãœlÑ ÷\ìˆv\n1dØ<ÈŽ|$9ð~çÁƒŸÑbb9ÀçÀ£Ÿ©ÄÐ"üÄÐ*€¸h€–SQX¡$¡þBªfá"ùÇ9g<朓ªtN¹Ó;çtñ³ÎvOYá='¼öžSê|O¹ó?çõŸ´~PZA(= T*„PºCèXG A0„ð¤GøD¢TT)Ñ€{8ÇÈ hVЄûŸ n|!¹ðy0ø‹ddd D LQ T \ d(RNFH ü€' ü€'gridlock.app-1.10/Resources/yellow.tiff0000644000175000000000000002062407523137723017203 0ustar gurkanrootMM* ¾€ P8$ „BaP¸d6ˆDbQ8¤V-ŒFcQ¸äv=HdR9$–M'”JeR¸¸ K‚‰€`bBÅ3ƒÜì„’ ÂB9Oh´zLÞ~9%Rf€ g2–VkUºåvU2 @©ñì”c-Mi@ƒ¼ÖŒ [’‚zµœR©X׋Õâí|½¿ïø&qk †Vàq$§ùÎçn¸;ÎhÀC¼¤k/iÇ» ŒX¯htZ=$~§aœÉF»Ii •=©E/ôâô„ÿZ³Œoö3yÿgo·œ&³8ÿâñø©NG›Êçry îgK¥Áßö7cÛýzÎ5ÞvÏô"pBÿ·årà Ö§> {åÚ_§×í%ÓæìþÃQÞF¡ËÄîã€s‘Ž|ë9ÆñÎRÁpiÞèB‡ù½ ÁPt*éAЄ8wÃÎŒE˜Ð3Ã…¬ô²ËAz¨*I«ïÆ‘ª ΈAŠ¢B5ÀÎØƒ ¡zÆ@®ë‚êÂQ 6sÉI9±!¼9¸o {+Jr«‡*Iò¤®àK2ëšìÊ,9Ô-BÐ|"æD®éJñ’…kÎ5€ßHb O”mAЉ C?‰MZÒ5“€É;0Û—ͼ!'ÉÒƒzî˜Ç<¼o<%é¼Ý·µ!ÏRTp;Ã'Ë ÝXáÕÕ=UXVu,TWÂ⻦³…4Mn<ÕK:nc¾Ýί8öJQÂÐæö+„—>t-­k¡-=VÑ”t€Ü7P<Ó6AŽc´ÞÓõkyYVÕ}ÜsÕkugwÞ5]àä^W¥ñ{Ww¼ŸI^î-íXÕuKƒ‚Ê“4ÛqØPl˜ï\$¡K Ùtp¤´ ‚`ªÛìij"’~)O1ùJ/, ƒ3ÜŽszßÝÕES`—]ùyß7öuššÙÎyçuž{›àZ|æçú.‹ÌuA0a5ûœs܆ôZ°$fNôO'x…½àÆ=±«48Dµ‹QKG…¨bá×¹làoS”ó½TÓ¹­õ¼çµewhü‰ÀÞZ÷ `ÞsÄðúVÂñ÷ï%¤:zv îØ¥/»qÿ­Y¶yz¬YÉÓ£•±­`î9íkÉœÆI÷4¡'»¹i¾o•};¿^®x7}]áø¾&Åyš•Ãiu—¡€ò<§~ñš]S^M³>¬6ýÉFžóð- v¯Qõ¡v¥¶1ѯ!k ÔXN'æ¿y¿Þ_ß’Í×ÐÎpꯧ Ó|zê´§ äÞœr1 Áõ˜ Ûiè8߬|•ëYƒü1™zUŸd) ´†·b!›w_¨%Q.§ö©ž}fÏ ¿ìa)ìl0©l#…-C˜­Ðc %6–Û¹»wN À(]ü:Ž‘Ú"8XÜœ°6#HH%`|TrU6ž#"dVzÑe,µ„cXcYãÒ(ÈŒÝY—Y޼RƲôm߬pwQæ>G—zþ—óGw° Z·öƒ`#z€­(@¦“/$R‰’õYIï1¢”’8¦îIH÷¨öbÊ?b…øˆÇÈùŸA}R|•º³Vù#L¦ÆÝ˜Ê·ùecý–0YNµ×.§cÿhÎz9IqàLOÐYæ´Yã`¼Æ‚“c¯)#¨-‘Î E„¨wͺ)bQ¾bÐ@‰„Ü?ÉÖŽðö+TpœÍ½Ý ÕÙIçDî•ñÞ”ÏyžT@gðáÄç›=çÌü Ú)¸êy?çü‘¡16FÔYœÓŒ2¾7m`Ù‰Ê@y`ïc@?ͪ4GOJYâÖF±(19v•xÃK:YgTññé|Ϊ])Äî§.¦@éûçÔ‡‰TêHº _æM¡t*)ÌÚ `¬,ű.-˜Áj/R¥©ñ„^žö8L_MW"¼-·`Û+‚ɃVÚ[ßõ/wÕʘÚÚoM\DóˆRùçS§¡"le>¯ÖÚÜX»#ì=¸V&ÂPzUu£;Ö†§(ë)e¬Íš!Ì„ŸÑõWmä–žV×*ÓL,Av¶[+i\k½3˜3Ùé[‰÷"ª€¨“úÞÌ›ƒao½†°RÁ¦Ù™AZÉ6îv5ÜÑþ™Ì£FéIB·Gx„¬ RŒä9’åßµpþíÒù]- $ò¼x†"K¹'íy‘S€ÛÛÿjþ¨s6ßã[û1}Ç<7ò¢ŽuîÕ0 ¼ÂÆZƹ¬žŠ5˜.«Q«9GnÅ"6bÔo…:—°í݇ª×eÉåJíãg‘&»W»ÙO+¬ƒ‚—ÖÝæÛuŒ®}¿Xëß|yŽ3¢Ç9ä l­Hò#(•D÷ÕR_ƒbÛbÖÐuE•²Î¥ZNòÚ¶õ-+†&¶UÆ$K7!³4ý×Ú f¹o¦0ÆøÎbß›ªñÚòÎøþÃç¶ì5³ó6vIG·D@ÛMtî¬!FvmF“x8i-›‰1^Óôßf\YŠvÆ¡½z§7[íaq*5ùÕÚÆýî<ëŽõ¥Å±8kJ‹˜ìdíÐû BYÀ¤Ïe_™ QVS%²rÞÒørµ7¼A]%½äÚw³jH¥zóN¥ÛµòDÌ®·ìf4Î;šIk=Õžõv¶¡ïn†¢a·fÂcü=ïœ{ËLP·PBe¿vNË»ÜêìÁ¦x.š–ßOf^#@+ÖÖz²CmÝM"ñެÆ÷˵Ʒzë{›®xÞ¼•3ÆìHƒ ‰MKŠG2>¼ÐFYWeI=eÒ<÷ºb^ƒˆº»Ìx¢ÚômÒºOñX¯¨ñŽ¥¸xÞêø^OÅü>»Ø:¿aøû£æu½iæ&?cÚÇöwÑÚ†ˆ+‡È9¨Ô™hE­Ê¤Ü,ì¬=9ã­1¼\*ApÞà 7²‘]Qjz‰Pqnqñ>C9ÿÝZøn¬äoœãð¯”ÎÏ’ëïšùG¤¹AŒÃÎŽÞ m £"¼ØŠºáZÌ.ʮ컯`îí ïÍ4ŠÚöðLé-FâoxÕ fÍ‹€ø¯€Ï/Ü­Èë-eqÌðsîLìE$×-p6ájc!þÞ-€ûBPZî-*D<ì¨/pÙŠ×²Ó `—OfÌ.úè°ZxÌÎÛI„Ú¯ö⮚·OüÿO|™x¸ìròP…P 0îVO–ø|ä¬ú1Œ´.Zœ nbÞbTª`0£àáKƒp×+SpFõ®~ýPBÚKh¼ïä®m¬ðÔ÷/ì·/lòÜPhò gpoŽÃñ°0õðêî¾ó¶×/¦máZAþªbp M‚³NGBrŒe6¬oTT̰¼®¯^õ̸¥Ñ<§‘:«y ñJñ/ *øê1\Ûï$ÿâÿ‘_‘_1opñupÏš×ñë–eÐ û-è$ä Mð±"ÊoÄõ/ÒçN³NÏå-©Z÷ ´éñPã+PkPÎlîêñYpöò°sЃmÑ qëÉìmp1p6q Í ²#cNºÂëOÃKJË Ï*hö½"obáÐXâLÞ÷°ÍòBé®-n8ã-%ÐíaqgÈ<2g&p,2É¢ñãAîªb£М#K¨Yo87¼´‘¢]l2àªÜ¼ ž¯ým²ð0U12©#¯tÿ I*ðrLÝ0lä’Q+Î;2ÑhëòÃ%ïþåï4‘í&ª’Ý£€ăòîØ#@„}Ë&´ »Œ»"‘7)Obq‘AKl‰ðиqÆêÑïóÑÙ%qpÎÏ-ê -Qå4ñé4­-/œJ‘cË”úcÎ GД¢]0,#E¨6 ð6@RŠ8nPnÑ,ªÞàí3 ïã1)þ‰€Å.žðëã*K}+OƒÓ91οα%‘a,´Ò_&&MBp -4“¸U!½Í¼=ïC B5R‡=Ð¥ÚJá0’–Óïàá/Üè’«#G§§’BÕ”u9~ëÐ{3té4?:´:ó­CÌÇåSB±k„-CÆÞ¡Zâ&çD“Î"‹¨û³Yq¡"2ÿ0JeMKYF­¶ÍÛtÞâ”|âÑÑ+qW#ô‹+´™HÔ›%394³±BNÃJ/4tÇÔ6Çrlœc/% ²ôÂ"sf'ñ# “U ébKŽÌ¶Ä³ð‚ëÑ ²5?‘À÷sŽÎ æ÷ò<°•^ò4õ2ô:l{VÑiQ5ÇÔ)IU 3E;3KAÔ;uÓl NÓRhP"à„d@ö¤Dƒ=å;/®óM³ ¥ôm ŽŒ÷I‰?R¢öó‚p\Îm¸ÿ®©VÑdÕô‘³-r½,cB5sI• &UJ1íB”¥_•Jã C§i/1þû /6&Æ5á{t³ÎÆõ¨ý×7ËÒö´âi3…*ÕÎð’¨ã/G” ñÒ¹AÛOo›$ô!P•}PÕ Q5_Uiô©JU©'f9œ6a`âÐÑŽ"+9Dã+=¦îÊÆ >P¶s['£•Å1“ýÔj‹\õgV+9¯"ò‘ç]nAXUíP/›eÕóBÕïl•lô2nÁÎ{vsY©Jãߢ©.¥²&Dhᬤ”Vxò‘TQ±¶4Ä•ºÍ½8¯ðV¯ ÏïòA6K]´A”ªëm:–ÕmöÝQƒwJ†ŸJ·Mt;`"ïgQnòå'Ñ!«8@Ûi ­iXËÏ0–£iÕÃ85ÁjÓ‰dSþÖ»r³•Hô‰W™779õíWeåPÖk,Õwf6ÛX.·töiXqy`4°0FOo]Kë/6%²&!hÂêæö!>&¶c[Ç?¨‡G1”‚Û’§@²³5`ÿô$uÕ]õq:P%5};V×Q§{Vãt—»‚Ö_w¼RVæÈaZƒ*=ô¿<Ë7oÔQw=bu<žWx ñx§ctqUÉU•Ñ2tó93s39l8eu×A5zô{x#ƒE{•{õ‚Õ‘XÖë„Ì,qo‚v´·(w(Óây1´¶…±A  s—Øa\ÕÙ ´$Uk&Çw¥B÷³ló=BXn7AtÖe‚¸/yºó­|QöÆÞ¸@øEYD!˜´2¯Ã²Û>Âï5¿ÙÎxÖAæ8d& ˆAá¯ö´-‰FbqÈ´F5C¢ð6ô.O&‘¿ÛÒTš1)–Le¤Â-—¿Üò‰¬æmžÐ£9åkD¡OèôºtòçŠÔ©U «¾£wÑk:Ý ½ª?ëöJÕÃMµYlvÆõzÑD9Ï--fq*,οժPCÜ €QNÄbñ˜°F0ŒV‚êÖ°Åþ½k^Ñ\ìR;‡Çô9.šEÓÅä’lïW©la4dûkµ n¦s¹Ö÷o0áp7ûú5‹S›nêÖ®5f«céV¡uŽ*‰bêuîËSžßk³Ø,/ƒÍݺIšÅ©c8¥cf©Ì #„ˆq,kþ¿ Éyjk/lÓâ‚¡ÆqÞ¹´M7 ¢(\Ó$ ,0µp³r&M:e"±4Ù¢±"nฑcžßEJC†ä¬Nƒšä+±Äg»J{¦ì¬Ê»ÆïÈ‹lŒ´¼T”õ®ˆrÜõJj¶¹›Æ²rk>+²ö¾‚¼ý ; ÿ@ l d 0^•¦pR̳gû:÷BPº1O sIµSÛi>Ï‹_@ı¢“D üOFTjžãG”çG‹[H±ütëSTô!;òLu#»Ò“¤ó¼ëŠÉT¼‰ãÚ¼¯±8ƒØ0g@BþL“5~B=ÍÁ 2o3†ô=.pëdÓÏ1¥>Z”5 ZídB×8‰[‹D91Æ™¹‘«Ó.=IK]² @©S+c°²Fõç%­ME}­×íW&I’¤›+=˰„‚ Áþ)0„ã׌C`@P´…)…—¶Lçe´p’+ ´°ìQgÄMe4YFE¹ŒGæ©ÍÃGE±ƒ›Òyå$©Æôÿ{*1½;{è÷ÕCT^UZË)TêUv ùaŽ-Xe+1€ëŠâÂ!bÍóŽcÓ®HsÙÙF]“nyU¡¼QVͳ=Åmƒm¿g\Ò—] ÛpñÛ££ÞÕ'SS—eóÊT\®­VUÇ}[)î2iÏXVxAœcXâ–χ°Ì@1‰ì¯û¡k/A Æ<øí©$ Ô"”&WjPqéáÑVîcEç>MÍœPô¦‡ž¹wG¤éqÜc½x­|uÔ®iÞÄèÉ:žñUÏG;ósœßÒ’Õ‘Œ½–¥,¼À€U_uÓ4 ÀçvÌܶä2ÝÓôPH}¨DKã\ˆÜ"㘺WCÍgî!´bªÐÞªï]Í«´¢¼uWcÞIljȹ¦ž‘[Ÿ|­2¹²æèpÞ>ÈÌ Q8x?Ý1:·ZþR ` J,dâ²–bDÏ•¨=Ãwfï+.%½\FÎÂ8,õ¡EIñ™|)ø\äßD0Iï‘%¹ÆÔßé<¥š¥sÞ|aÁxÂõ® +L@9bOæ#+ð”€À{A ÀÍ6ÈÈàDU#0:EwŠpD_“1uDÊ7)a Ñ‚±™x4UMŠÊò•NI!¾*Àš\¶À¯>¥SˡΎAöºLC?göE¬&0µÝ¶ÛØ3žZ,¾M²¸Ë$ÜÝ‹‹n..œ¹\b'‘zJ³‡œTì(ïrB¸UXcä‚…jÇ¡v:‡Ä[#€@{€„^ÀÚ²¨Õ\xô½M»µ(ge””²uRÙÓZ ÕiµïiïÂ9ç^í´§töÞ[[æù-ô»ŸÒæÞ:ÚûÌÀŒ€…\ŸŠ—2͹ Ä¥eA —m–jÏ͉´Î œâ»µ J ‹AL¥R² ÎÖ€º â=SîB÷SyócrmR\ßJý éý‚¿)NÁªòsUœÔ¸ãß6‹”تn¢/ò%‚Îf‹ØÎd9BëÅ:?hjÕ`y> Zx7¬©µ6±x)êöãEê¾­ÏâêìÓc}ó 7ëÇA¬X¨Î`Ã??ø'ï1 †‡Lë™’$Yø?h1‚fŒÅÕª×\“¥RVÌèý[ÃYnñ"¼Á:£#ƒ6·.Ïh?1„&¶)F[Ç{äZq”÷Íú²¾¯ÜéP蹇æÿðÆ¬¤‡lCd‰š(µ#½¶ÍL%…tµ¡Œ‘jN®|¹¨u+>¥TžÔ×-JÒsVc–¶»WVœµÀ¯:¶üSìã|¨$9‡ Z‰Í“¶E¢Caï·í¢ÄfPtl‡ Íõ»WðÄ^Úz³N™Q¨±Mm½ùn/JgªkœûTÏUÇøþ±Æ{¶þxë/ê¯ëuÄñÁHÆb˜AöŸ?õX™Š²ž\wf?8©ËÜ7¢zûTŽ1=nŒþÉÅðî+mõFgñ]C‹×Y^Ú‡¿·]cvT?!ºëë¯!J¢“h’øÅ"–°12¾´ŒXÈ ÐZ…è¾Øs£ño›é½c…;ãò¯3P)‹ˆ ö¼R7-šÜ:š½Ûú¾Y72 ([¾Câ<’À¹yÜ…l @p #Í»j"@d!½Å‚- ‹€ËÔ *¶ŠQ;ÙÀúÓ<ì1o:böÁ"71‹Œ¥¬û9šæ;T"C³D$xB‹¸ø“ŠJBs„?#…¯D+/"´£ˆ=ÂÛBì˜r?“t§Óà-ët7k¹3Ä»¹ÁÄ3““æ‹èÃA6 ôTpÅAðFCÛîC¡¨wƒØ¨D ž-+¿¸z˜%S2·Ø-´µSŽº¬ÃK?óZ®¾J€DðsŬN¹o>[‹€A0ÀA°ÀTUGŠ´A±68À¨ø‰è¹‡»æ {„#O?"ò»ûô'y¡-r¸?ƒÃºt}1kŒ:Š|ŸRûFTÈ‘ÁƒÉÈD¸sÇ|…Ŭ…¡¨»ŒÈVŒ·»—@KBÇ ÇÀx-;€!¸‹ˆw‡¼uG`wÇ`s‡¼iÅÌC¼ ¿8›Q—»2F úI›©%£XŒK¸ÛýÈ#È¿ôiø²G|£üˆ`÷0ZÉÁû–;CaG€€€ P8$ „BaP¸Är-/XÄ'»ÞZ½ßç¸ËÝ £ñhãyÎk‘»åcŽNÿ“J"Ò¹|²]2—Ìæï÷|ªvçœÐeÙĶ8¡Ð¥ÔjS¾rޤ̪:›ž«S§T¨ÕzRµ^°;ë“ËZdÖ©Pê­jÝ&9J?ç‘ø©ÎÉc-bƒ˜z9Œ`aˆ"‡ÄbqX¼f#  F!’1(BcIŠSǽÚå"HñéMÚc?ŸM¨ò™”úu@¦R5“º&Ò•«¬Õ63É~çsVÝî)´úíšÃO¶Ù-\½Õƒb´ò¬5{³Ýߌè÷G=ÚÅN#MaˆÄ0{Àú`BCïø|~_<€#ì)B#+Ö³x”Î%¨Òè{®- :¢Í1Σ5ͼ¡µÐjŠŸÁm¤$Û6M\4ª·°ë¢à'æó’߬nƒœ²ÄªÂʶDéC¬·žéyœèâ*•™Ïù=†&3ì OPÁ=oké#ÉL”‚1à0BÙœk3g¹î”.NĹäâ@Ñèä 80¼5 µíê|߸m“|ä8ðú®–ÄŠìë8Ï4@çÅk2×óäuu*#Ä“1Ð2E¸¤Hãç±’H-'%dÄaН™ÑÅõ²ËˆçÑ¢5*ƒ/c{¬ PÙ‘»Üî¡Ô<²ÎZKXÿ-Ù4¹[‡Ù½®h „ãîÃXg±î3†0só"e5O3äl#“ó:h¨Bã3¸Ö™3^†9L†pc˜”9x¤ŸšBH‘Õû7e´ñžSÍ&@L{ƒ&2mè!H9̈œœTq‘KAE,n"r…P ÇA¨E´NJ¤~¨¼¬•ÔnuÇi`ìßÔ·žÒ’RZMHbî¥SÞÎÆá>)u1£Ò¾šS)ÛL)Äö¤3Ö“ÓÚ}OÏ{ÿ¤éu j=+–0YGêSê…QSTŽžZGU*•Y«Un®UÚ½Wëa¬T€€dd!l!tQ!|!„!Œ(R2*Œ ü€' ü€'gridlock.app-1.10/Resources/README.GNUstep0000644000175000000000000000506410342227630017211 0ustar gurkanrootGridlock.app Version 1.10 This file describes how to build and run Gridlock on GNUstep. See the readme.html file for information on how to play. Differences from the Mac OS X version are noted below. In order to compile and run Gridlock, you must have the GNUstep core libraries installed. You can download GNUstep from http://www.gnustep.org. Gridlock was built with gcc 3.3 against the CVS snapshot of GNUstep as of November 26 2005. Earlier or later versions may or may not work correctly. Building -------- You can build Gridlock either from the command line or using ProjectCenter. To build from the command line, make sure you have executed the GNUstep configuration script in (GNUstep root)/System/Makefiles/GNUstep.sh for sh or bash, or (GNUstep root)/System/Makefiles/GNUstep.sh for csh. Once this is done, run: make To build from ProjectCenter, open the PC.pcproj project file, and build from the Build panel. If the build succeeds, it should create the Gridlock.app GNUstep application. Running ------- To run from a command line, execute: openapp Gridlock.app You can also run the application from GWorkspace by double-clicking it. Known Issues ------------ The GNUstep version of Gridlock is built from the same source code as version 1.10 for Mac OS X. Network play between GNUstep and Mac OS X machines should work, and games saved on one platform should be readable on the other. The GNUstep version has the following limitations: - The Mac OS X version detects the number of processors and creates one thread per processor to determine the best move for computer players. The GNUstep version cannot automatically detect the number of processors. To use multiple threads for computing moves, you can set the "CPUPlayerThreads" default to a value greater than 0. (For example, "defaults write Gridlock CPUPlayerThreads 2"). - Resizing the game window does not constrain the game board to maintaining equal width and height, as it does in Mac OS X. - Animations of captured pieces may be slower than they should, due to issues with view redrawing and offscreen images. - Statistics and chat/network information are shown in separate windows rather than in drawers. Also, the statistics window does not display the record of moves that appears in Mac OS X. - Rendezvous support is not available. Feedback -------- The GNUstep port of Gridlock is not well tested. I have built and run it only on an Athlon machine running Debian 3.0 (kernel 2.4.18). Please let me know if it does not work on your system. Email me at brian@dozingcatsoftware.com with any bugs, comments, or suggestions. gridlock.app-1.10/Resources/readme.html0000644000175000000000000007464110342202650017132 0ustar gurkanroot Gridlock

Gridlock

v1.10 Copyright (c) 2002-2005 by Brian Nenninger

Gridlock is free, but your support is welcome.
Gridlock source code is available at http://www.dozingcatsoftware.com.

Overview

Gridlock is a collection of over 30 grid-based strategy games, including Ataxx, Reversi, Checkers, Gomoku, Connect Four, and more. They are individually described in the "Games" section.

After launching the application, the game window will appear. Select the game you want to play from the "Game" popup menu in the upper right. Some games have different variations (board size, layout, etc); when one of those games are selected a "Variations" popup menu will appear from which you can select a variation.

The bottom right displays the color and status of the two players. Each player's color is shown by a circle; the player whose turn it is has a filled circle. For games in which players have a score, the scores are shown next to the player labels. Popup windows underneath each player's label allow you to specify whether each player is human or computer-controlled, and the difficulty of computer players. (Note that "Hard" and "Very Hard" computer opponents may take several seconds to make each move).

The rest of the window contains the game board. To make a move, click on the cell where you wish to place a piece. Some games require that you move from one cell to another; to do this first click on the cell you wish to move from, then click on the cell you wish to move to. (In some games such as Checkers you may be able to make a move containing several jumps; to do this click on each cell you wish to jump to in sequence). For all games, cells that are legal moves will become highlighted when you move the mouse over them. A black dot indicates the position of the last move. If you are unable to make a move, you can pass by clicking the "Pass" button on the right. The "Restart" button will restart the game, requiring confirmation if a game is in progress.

The "Preferences..." menu item in the main Gridlock menu opens the Preferences window, which allows you to change the appearance of the game pieces, and to enable or disable the animation when they are captured. Game pieces can either be bitmap images chosen from the popup menus, or solid colors chosen from the color wells.

Games can be saved and restored using the "Save" and "Open" commands in the Game menu. Games are saved with their full move history, so you can save a game after it is finished, open it later, and undo moves back to the beginning.

The Edit menu contains Undo and Redo commands. Selecting Undo will back the game up to the last time it was a human player's turn. There is no limit to how many moves can be undone. Selecting Redo will redo a move that was previously undone, but only if no new moves were made after the undo.

The Window menu contains commands to toggle the display of network and statistics drawers. The network drawer is described below and is primarily used to chat with your opponent during a network game. The statistics drawer shows a table listing all the moves that have been made in the current game, and information on the analysis performed during the last move made by a computer player.

Games

Additional information for many of these games is available at The World of Abstract Games.

Ataxx: The object of this game is to capture your opponent's pieces by moving your pieces next to them. There are two types of moves you can make. A normal move consists of starting from a piece that you own and creating another piece one cell away from it (horizontally, vertically, or diagonally). The starting piece remains, and you capture any of your opponent's pieces that your new piece borders. A jump move consists of moving a piece you own two cells in any direction. As with a normal move, any opponent's pieces that border the ending position are captured. To make either kind of move, first click on a piece that you own, then click on the empty cell you want to move to. The game is over when all the cells are filled, and the player owning the most pieces is the winner.

There are several variations with different starting configurations and board sizes, most of which place barriers in some of the cells. There are also 3 random variations for the 7x7 and 8x8 boards. The "V Sym" random variations will place the barriers in a pattern with vertical symmetry, and the "Both Sym" variations will place the barriers with both horizontal and vertical symmetry.

Quad Wrangle: This game is similar to Ataxx. There are three types of moves. The first type consists of starting from a piece that you own and creating another piece one cell away from it. The starting piece remains, and you capture any of your opponent's pieces that your new piece borders. (This is the same as non-jump move in Ataxx). The second type consists of sliding a piece you own any number of squares horizontally, vertically, or diagonally. Any opponent's pieces that border the ending position are captured. The third type is a drop of a piece to any empty cell. Unlike the other move types, no pieces are captured with this move type. To make a normal or slide move, first click on a piece that you own, then click on the empty cell you want to move to. To make a drop, click on an empty cell. The game is over when all the cells are filled, and the player owning the most pieces is the winner.

Reversi: (also known as Othello). The object is to capture the other player's pieces by enclosing them between two of your pieces. You make a move by placing a piece in an empty cell. You capture any of your opponent's pieces that are in a horizontal, vertical, or diagonal line between the new piece and another of your pieces. Every move must result in the capture of at least one piece; you must pass if you cannot capture any pieces. The game is over when the board is full or neither player can move; the player owning the most pieces is the winner.

Checkers: The object is to remove your opponent's pieces or prevent them from moving. Pieces move forward and diagonally, and can jump and remove opposing pieces by landing in the empty space directly behind them. When a piece reaches the last row, it is promoted to a king (represented by two stacked game pieces). Kings can move backwards and well as forwards. Whenever you can make a jump, you must do so. See http://www.triplejump.net/usrules.shtml for more detailed rules.

Gomoku: This is an expanded form of tic-tac-toe. Players move by placing a piece at any empty cell. A player wins by forming a straight line of 5 pieces horizontally, vertically, or diagonally.

Connect Four: Similar to Gomoku, a player wins by forming a straight line of 4 pieces horizontally, vertically, or diagonally. However, you may only place a piece at the lowest empty cell in each column.

Gravity: A player wins by forming a straight line of 4 pieces horizontally, vertically, or diagonally. The board has a "gravity field", which pulls pieces toward the edges or corners. If a cell is on a main diagonal (indicated by a gray background), a piece may be placed there only if there are no empty cells between that cell and the nearest corner. If a cell is not on a diagonal, a piece may be placed there only if there are no empty cells between that cell and the nearest edge.

Hexapawn: The object of this game is to move one of your pieces (pawns) to the other side of the board. In the normal game, pawns move as standard chess pawns; moving forward one square to an empty position, or capturing diagonally forward. Berolina and Berolina Plus pawns can be used in variations of this game. Berolina pawns move diagonally forward and capture directly forward. Berolina Plus pawns are the same as Berolina pawns, except they can also capture sideways. For all variations, a player wins when one of his pawns reaches the final row, or when his opponent is unable to move.

Breakthrough: The object of this game is to move one of your pieces to the other side of the board. Player 1's pieces start in the bottom two rows and move up; player 2's pieces start in the top two rows and move down. Pieces move one cell forward or diagonally forward. Pieces may capture opposing pieces when making a diagonal move, but not when making a direct forward move. A player wins when one of his pieces reaches the final row. Breakthrough was designed by Dan Troyka, the winner of the 2001 8x8 Game Design Competition; thanks to Dan for permission to include it.

Zonesh: The object of this game is to move one of your pieces to the opposite corner. The set of cells where a player's pieces start the game is that player's home zone; these cells are indicated with a tinted background. Pieces in their home zone move and capture one square horizontally or vertically. Pieces outside their home zone may additionally move and capture one square diagonally. A player wins by moving one of his pieces to the corner cell in his opponent's home zone. Zonesh was also created by Dan Troyka.

Glass Bead: The object of this game is to control the most cells. You control a cell if either you have placed a piece on the cell, or if the cell borders more of your pieces than your opponent's pieces. Players alternate placing pieces on cells that are not controlled by either player. Cells which do not contain pieces but which are controlled by a player are tinted with that player's color. The game ends when all cells are controlled by one of the players, and the player controlling the most cells wins. See here for more detailed information.

Cats & Dogs: Players take turns placing pieces ("cats" and "dogs") on empty cells. A piece cannot be placed in a cell that is horizontally or vertically adjacent to an opposing piece. When a player places a piece on a cell, the adjacent cells will be tinted with his color to indicate that his opponent can no longer play there. If an empty cell becomes adjacent to pieces of both players, it will turn gray to indicate that neither player can play there. A player wins when his opponent is unable to move.

Moray Eels: The object of this game is to capture the opposing pieces. Player 1's pieces are "Octopussies". They move one cell forward or diagonally forward. Player 2's pieces are "Eels". Like Octopussies, they can move one cell forward or diagonally forward. They can also move one or two cells sideways, or one or two cells sideways and one cell back. All moves must be to empty cells, and Eels can jump over friendly or opposing pieces. After a player moves, he gains control of all his opponent's pieces that are adjacent (horizontally, vertically, or diagonally) to his moved piece.

Life: This game is based on the Game of Life cellular automaton. Both players take turns placing a piece on an empty cell. After a player places a piece, an iteration of the Life algorithm is executed. A piece survives if it has exactly 2 or 3 neighbors (pieces adjacent to it horizontally, vertically, or diagaonally). A piece is removed if it has less than 2 or more than 3 neighbors. A new piece will be created in an empty cell if it has exactly 3 neighbors; the new piece will be owned by the player who owns the majority of the neighbors. A player wins by owning at least three times as many pieces as the other player after a Life iteration.

Atomic: Each player alternates dropping a piece in one of the cells. You may drop a piece in an empty cell or a cell in which you already have pieces. Each cell has a maximum number of pieces that it can hold. Corner cells can hold 1 piece, other edge cells can hold 2 pieces, and cells not on an edge can hold 3. When you drop a piece on a cell which exceeds the cell's limit, the cell will "explode". This causes the pieces in that cell to move to adjacent cells. Any enemy pieces in the adjacent cells are captured and change to the color of the exploding piece. Chain reactions of multiple explosions can occur when the result of the first explosion causes more cells to exceed their piece limit. A player wins by capturing all his opponent's pieces.

Five Field Kono: The object of this game is to move all of your pieces into the cells that your opponent occupies at the start of the game. Pieces move one cell diagonally forward or backward. There is no capturing. Surprisingly, stalemates are not possible; one player can always force a wiin.

Fission: The object of this game is to destroy all your opponent's pieces. Each piece slides horizontally, vertically, or diagonally until it hits either an edge of the board or another piece. If it hits an edge, nothing happens, but if it hits another piece it explodes, destroying itself and all adjacent pieces of both colors. There are 4 variations of this game; you can choose to use the standard starting positions, or have them randomized. In the "suicide" variations you win by destroying all of your pieces instead of your opponent's. If each player is reduced to a single piece, the game is a tie.

Orthokon: Each piece slides horizontally or vertically as far as possible before hitting an edge of the board or another piece. After a piece is moved, any enemy pieces horizontally or vertically adjacent to its new location are captured. A player wins when he captures all his opponent's pieces, or when his opponent cannot move.

Bombardment: The object is to destroy all your opponent's pieces, or to move one of your pieces to the other side of the board. Pieces move one cell forward or diagonally forward. A piece can also "detonate", destroying itself and all adjacent pieces of either color. To detonate a piece, click on it twice. (Be careful, this is easy to do accidentally).

Reactor: The object of the game is to destroy your opponent's pieces. The pieces begin in random cells and never move. The only objects which do move are "neutrons", indicated by small red circles. During each player's turn, he must move one of the neutrons. They move by sliding horizontally, vertically, or diagaonally until they reach an edge of the board, or another piece or neutron. After the move, any pieces adjacent to the neutron's new location are destroyed. Neutrons themselves are never destroyed, and you can't move the same neutron that your opponent moved in his last turn.

Tourney: The object is to either capture all your opponent's pieces, or "promote" one of your pieces by reaching the opposite side, and returning the promoted piece to your side. Pieces move like chess knights; two cells vertically and one horizontally, or two cells horizontally and one vertically. However, unlike chess knights, they cannot jump over pieces in the way. When moving two cells vertically and one horizontally, the adjacent cell in the vertical direction must be empty; likewise for horizontal moves. Additionally, non-promoted pieces cannot move backwards. For example, the first move of a game must be to take a piece in the second row and move it two vertically and one horizontally. The pieces in the back row can't move at all because the pieces in the second row are in the way, and the pieces in the second row can't move two horizontally because they block each other. Enemy pieces are captured and removed from the game by landing on them. Captures are mandatory, and as in checkers the capturing piece may make multiple captures in the same turn. When a piece reaches the opposite side, it is promoted and gains the ability to move backwards. A player wins by returning a promoted piece to his first row, or by capturing all his opponent's pieces.

Daggers: This is a game with unequal forces. Player 1 has more pieces, but player 2's pieces are more powerful, at least at first. Each player has two "crowns", represented by two stacked pieces, and several "daggers", represented by single pieces. A player wins by either capturing one of his opponent's crowns, or by moving one of his crowns to the opposite side of the board. Crowns move and capture one cell in any direction, like chess kings. Daggers can slide any number of squares down (towards the bottom of the board), either straight down or diagonally down. They may also move one cell up or diagonally up. This makes daggers at high positions more valuable since they can move further. A dagger can capture an enemy dagger or crown when moving diagonally, and can capture crowns (but not daggers) when moving vertically.

Fianco: The object is to move one of your pieces to the last row. A piece moves one cell either forward or sideways. A piece may capture an enemy piece by jumping diagonally forward over it, landing in the next cell (which must be empty). Captures are mandatory, and there are no multiple captures.

Diagonals: The object of the game is to achieve the highest score by completing diagonal lines. Each turn, each player drops a piece on an empty cell. If that piece forms a diagonal line of pieces from one edge of the board to another, the player scores points equal to the number of his own pieces in that line. Note that a single piece can complete two diagonal lines at once. The game ends when all cells are filled, and the player with the highest score wins.

Photonic Attack: Each turn, a player "fires" a piece from one of the board edges, which travels until it hits the other edge or another piece. To make a move, click on the cell where the fired piece would end. After a piece is placed, all enemy pieces in a horizontal or vertical line starting from the new piece are captured and converted to the new piece's color. The game is over when no more moves are possible (you can't fire a piece from an edge if the edge cell is occupied), and the player who owns the most pieces is the winner.

Dominion: This game is a combination of Ataxx and Reversi. Moves are the same as Ataxx; you can create a new piece in an empty cell adjacent to one of your existing pieces, or jump one of your pieces two cells to an empty cell. Also as in Ataxx, any opposing pieces adjacent to the destination cell are captured. Like Reversi, all opposing pieces that are in a line between the moved piece and another of your pieces are also captured. The game is over when the board is full and the winner is the player with the most pieces.

Tonga: The object of this game is to score points by arranging your pieces in large groups. Each move consists of simultaneously placing one of your pieces and one of your opponent's pieces on adjacent empty cells. To make a move, first click on the cell you want your piece to go, then on a neighboring cell where you want your opponent's piece to go. Each player's score is determined by their three largest groups of connected pieces. Only horizontal and vertical connections count; diagonals don't. A player's score is the sum of the squares of the sizes of her three largest connected groups. For example, if you have groups of 8, 6, 5, and 3, your score would be (8*8)+(6*6)+(5*5)=125. The game is over when no more moves are possible, and the highest score wins.

Think Ahead: The board is randomly filled with positive and negative numbers, and a single black ball. Player 1 moves the ball horizontally, and player 2 moves the ball vertically. Each turn, each player moves the ball to a cell with a number in it. That number is removed from the board and added to the player's score. The game is over when a player cannot move (because all the cells in the ball's row or column have been used), and the highest score wins.

Sabotage: The object of this game is to capture the "ball" in the middle of the board and deliver it to the goal. Each turn, a player moves one of her pieces. Pieces move in a straight line horizontally, vertically, or diagonally, and move a number of cells equal to the total number of all pieces (friendly and opposing) in the starting column. Pieces may capture and remove opposing pieces by landing on them, and may pick up the ball by landing on it. Pieces may not jump over friendly or opposing pieces when moving. If a piece captures an opposing piece which was carrying the ball, the capturing piece takes the ball. A player wins by moving her piece carrying the ball into her goal, which is designated by being shaded in her piece's colors.

Ambivalence: The object of the game is to "capture" opposing pieces and turn them into walls. Each turn, a player drops a piece into any empty cell. If the new piece traps an opposing piece between it and another friendly piece, the opposing piece is captured and turns into a wall. Also, if the new piece is placed between two opposing pieces, *both* opposing pieces become walls. The game is over when the board is full, and the player with the most pieces wins.

Fusion: Each player starts owning two pieces called "atoms". Several "protons" (small red circles) are placed randomly on the board. Protons are the only pieces that move. Each turn, a player moves a proton any number of empty cells horizontally, vertically, or diagonally. The ending cell must be adjacent to at least one atom (owned by either player). The proton changes itself and any adjacent protons and atoms into atoms owned by the current player. When all protons are gone, the player with the most atoms wins.

Network Play

To host a network game, select "Host Network Game" from the Gridlock menu. A window will appear allowing you to select the game and variation (if applicable) that you wish to play. If you want to restrict who can join your game, you may enter a password in the "Password" text field. Anyone attempting to join your game must provide this password or they will be unable to connect. (Obviously, do not use any of your real passwords). The "Port" field should usually be left at the default value of 27500; change it only if you get an error when attempting to host. The "Username" field is the name you will be identified as to your opponent. The default is your user account name, but you can change it to anything. To begin hosting, click the "Host" button. The game will automatically begin when someone connects to your computer. Close the window or click the Stop button to stop waiting for connections.

To join a network game, select "Join Network Game" from the Gridlock menu. Enter the hostname or IP address of the computer you wish to connect to in the "Address" field, and change the port number if the computer is not using the default of 27500. If your machine supports Rendezvous and one or more Rendezvous-enabled machines are hosting games on your local network, you will see a popup menu listing all of them. To connect to one of them, select the "Rendezvous" radio button and choose the game you want to join from the popup menu. If the game you are joining requires a password, enter it in the "Password" field. The "Username" field has the same purpose as when hosting, to identify you to your opponent. Once you have manually entered an address or selected a Rendezvous host, click the "Connect" button to connect to the selected machine. If the connection is successfully established, the game will begin immediately.

When a network game begins, a drawer will open from the game window allowing you to chat with your opponent. To send a message, type into the text field at the top of the drawer and press the Return key. Game moves are made in the same way as when playing against a computer opponent. Either player may restart the game or start a different game and/or variation. The player who initially hosted the game is always player 1, and the player who connected is player 2. When playing against a network opponents, the popup menu next to their player labels will have "Network" selected. Changing either player's type will end the network game and disconnect. You can also disconnect from a network game using the "Disconnect" button in the network drawer.

Tip Jar

Gridlock is completely free, but if you find it useful you can support its development by:

  • Donating via PayPal
  • Signing up for a pokerroom.com account using this link. Pokerroom.com is an excellent Mac-friendly poker site, where you can play Texas Hold'em and other games for real or play money.

    Version History

    1.10, Nov 26 2005

    • Added 6 new games.
    • Built as universal binary for PowerPC and Intel processors. (Intel version is completely untested; if you have access to OS X for x86 let me know how it runs).
    • Fixed display bugs when user interface scaling is active in Tiger.

    1.9, Aug 14 2004

    • Added 11 new games.
    • Added random starting positions and other variations for several games.
    • The application UI no longer hangs when the computer opponent is considering a move.
    • Improved performance and use of multiple processors.

    1.8, Sep 28 2003

    • Added Hexapawn, Quad Wrangle, Cats & Dogs, and Moray Eels games.
    • Implemented alpha-beta search algorithm for computer opponents, greatly improving performance.
    • Added harder computer opponents for several games.
    • New icon.
    • Miscellaneous interface improvements.

    1.7, Aug 10 2003

    • Added Gravity and Zonesh games.
    • Computer opponents are faster and use multiple processors more effectively.
    • Checkers no longer ends in a tie after 100 moves without capture; Connect Four is now the correct 6x7 size.

    1.6.1, Jul 1 2003

    • Computer opponents are much faster and take advantage of multiple processors. (Thanks to the Apple engineers at WWDC for their assistance).
    • Minor bug fixes

    1.6, Jun 15 2003

    • Added Life game
    • Improved speed of computer opponents
    • Many bug fixes
    • GNUstep version synced

    1.5, Apr 27 2003

    • Added network support
    • Added saving and loading of games
    • Added statistics drawer
    • Added indicator for previous move

    1.3, Nov 16 2002

    • Added Checkers game
    • Added undo and redo of moves
    • Minor bug fixes

    1.2, Aug 25 2002

    • Game pieces can be bitmap images
    • More configurations added
    • Game window is resizeable and remembers its position
    • Pass button is enabled and disabled as appropriate
    • Drawing methods optimized
    • Application builds and runs under GNUstep

    1.1, Jul 20 2002

    • Added Breakthrough and Glass Bead games
    • Added multiple starting configurations for several games
    • Improved speed and skill of computer opponents
    • Redesigned UI to use a single window
    • Added cell highlighting when mouse moves over a legal position

    1.0, Apr 2 2002: initial release

    Feedback

    Contact me with any bug reports, comments, or suggestions at brian@dozingcatsoftware.com.

    License

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    Gridlock contains code from the EDCommon framework, which is Copyright (c) 1997-2001 by Erik Doernenburg. The following applies to such code:

    Permission to use, copy, modify and distribute this software and its documentation is hereby granted, provided that both the copyright notice and this permission notice appear in all copies of the software, derivative works or modified versions, and any portions thereof, and that both notices appear in supporting documentation, and that credit is given to Erik Doernenburg in all documents and publicity pertaining to direct or indirect use of this code or its derivatives.

    THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF ANY DERIVATIVE WORK.

    gridlock.app-1.10/ThinkAheadAI.m0000644000175000000000000000065010342202543015413 0ustar gurkanroot// // ThinkAheadAI.m // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "ThinkAheadAI.h" @implementation ThinkAheadAI -(int)searchDepthForGame:(Game *)game { int numUsed = [[game grid] numberOfCellsWithValue:-11]; int index=numUsed/16; int d = [[depths objectAtIndex:index] intValue]; //NSLog(@"Using search depth:%d", d); return d; } @end gridlock.app-1.10/ThinkAheadGame.m0000644000175000000000000000751510342202543016002 0ustar gurkanroot// // ThinkAheadGame.m // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "ThinkAheadGame.h" static int MOVE_START_VALUE = -10; static int USED_CELL_VALUE = -11; static id valueStrings[] = { @"-9", @"-7", @"-6", @"-6", @"-5", @"-5", @"-4", @"-4", @"-4", @"-3", @"-3", @"-3", @"-2", @"-2", @"-2", @"-2", @"-1", @"-1", @"-1", @"-1", @"-1", @"0", @"0", @"0", @"0", @"0", @"1", @"1", @"1", @"1", @"1", @"2", @"2", @"2", @"2", @"2", @"2", @"3", @"3", @"3", @"3", @"3", @"4", @"4", @"4", @"4", @"5", @"5", @"5", @"5", @"6", @"6", @"6", @"7", @"7", @"7", @"8", @"8", @"9", @"9", @"10", @"15", @"-10", @"0"}; // -10 is starting position, last one should eventually be "mystery box" static NSArray *gGridValues=nil; static NSArray *gridValues() { if (!gGridValues) { gGridValues = [[NSArray alloc] initWithObjects:valueStrings count:64]; } return gGridValues; } @implementation ThinkAheadGame -(void)reset { [super reset]; [self setGrid:[DCHypergrid gridWithRows:8 columns:8]]; NSArray *randomValues = [gridValues() arrayWithObjectsInRandomOrder_]; NSEnumerator *pe = [[self grid] positionEnumerator]; id pos; int index=0; while(pos=[pe nextObject]) { [self setValue:[[randomValues objectAtIndex:index++] intValue] atPosition:pos]; } p1Score = p2Score = 0; } -(NSArray *)allValidMoveSequences { id startpos = [[self grid] positionWithValue:MOVE_START_VALUE]; if (!startpos) return nil; NSMutableArray *moves = [NSMutableArray array]; // player 1 moves horizontally, 2 moves vertically if ([self currentPlayerNumber]==1) { int r = [startpos row]; int c; for(c=0; c<[self numberOfColumns]; c++) { if ([self valueAtRow:r column:c]>MOVE_START_VALUE) { [moves addObject:[[DCHypergridPosition positionWithRow:r column:c] arrayWithSelf_]]; } } } else { int c = [startpos column]; int r; for(r=0; r<[self numberOfRows]; r++) { if ([self valueAtRow:r column:c]>MOVE_START_VALUE) { [moves addObject:[[DCHypergridPosition positionWithRow:r column:c] arrayWithSelf_]]; } } } return moves; } -(BOOL)prepareMoveSequence:(NSArray *)positions { if ([positions count]!=1) return NO; id movepos = [positions lastObject]; id startpos = [[self grid] positionWithValue:MOVE_START_VALUE]; [self resetFutureGrid]; [[self futureGrid] setValue:USED_CELL_VALUE atPosition:startpos]; [[self futureGrid] setValue:MOVE_START_VALUE atPosition:movepos]; return YES; } -(void)updateFromPreparedMove { id movepos = [[self futureGrid] positionWithValue:MOVE_START_VALUE]; if (movepos) { int value = [self valueAtPosition:movepos]; if ([self currentPlayerNumber]==1) p1Score+=value; else p2Score+=value; } [super updateFromPreparedMove]; } -(BOOL)isGameOver { return [[self allValidMoveSequences] count]==0; } -(BOOL)showScores { return YES; } -(int)scoreForPlayer:(int)pnum { return (pnum==1) ? p1Score : p2Score; } // these methods deal with the score ivars (since they can't be derived from the state of the board) -(Game *)copy { ThinkAheadGame *newGame = (ThinkAheadGame *)[super copy]; newGame->p1Score = p1Score; newGame->p2Score = p2Score; return newGame; } -(void)copyValuesToGame:(ThinkAheadGame *)newGame { [super copyValuesToGame:newGame]; newGame->p1Score = p1Score; newGame->p2Score = p2Score; } -(id)propertyList { id plist = [super propertyList]; // assume mutable? [plist setObject:[[NSNumber numberWithInt:p1Score] stringValue] forKey:@"p1Score"]; [plist setObject:[[NSNumber numberWithInt:p2Score] stringValue] forKey:@"p2Score"]; return plist; } -(void)updateFromPropertyList:(id)plist { [super updateFromPropertyList:plist]; p1Score = [[plist objectForKey:@"p1Score"] intValue]; p2Score = [[plist objectForKey:@"p2Score"] intValue]; } @end gridlock.app-1.10/ThinkAheadViewDelegate.m0000644000175000000000000000343210342202543017470 0ustar gurkanroot// // ThinkAheadViewDelegate.m // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "ThinkAheadViewDelegate.h" #import "ImageStore.h" @implementation ThinkAheadViewDelegate -(BOOL)drawCellWithValue:(int)value atRow:(int)row column:(int)col inRect:(NSRect)rect forGame:(id)game { if (value==-11) { NSRect changeRect = NSInsetRect(rect, rect.size.width/3, rect.size.height/3); NSImage *wallImage = [[ImageStore defaultStore] bitmapImageWithName:@"wall.tiff" size:changeRect.size]; [wallImage compositeToPoint:changeRect.origin operation:NSCompositeSourceOver]; } else { if (value==-10) { // bigger move indicator NSRect changeRect = NSInsetRect(rect, rect.size.width/3, rect.size.height/3); [[NSColor blackColor] set]; [[NSBezierPath bezierPathWithOvalInRect:changeRect] fill]; } else { NSString *str = [[NSNumber numberWithInt:value] stringValue]; // get text size at 12 points NSMutableDictionary *attrs = [NSMutableDictionary dictionary]; [attrs setObject:[NSFont labelFontOfSize:12] forKey:NSFontAttributeName]; [attrs setObject:((value>=0) ? [NSColor greenColor] : [NSColor redColor]) forKey:NSForegroundColorAttributeName]; NSSize size = [str sizeWithAttributes:attrs]; // scale to take 80% of the height double ratio = 0.6*rect.size.height/size.height; [attrs setObject:[NSFont labelFontOfSize:12*ratio] forKey:NSFontAttributeName]; // draw in center size = [str sizeWithAttributes:attrs]; [str drawAtPoint:NSMakePoint(rect.origin.x+(rect.size.width-size.width)/2, rect.origin.y+(rect.size.height-size.height)/2) withAttributes:attrs]; } } return YES; } @end gridlock.app-1.10/AmbivalenceGame.h0000644000175000000000000000031010342221337016167 0ustar gurkanroot// // AmbivalenceGame.h // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "Game.h" @interface AmbivalenceGame : Game { } @end gridlock.app-1.10/DominionGame.h0000644000175000000000000000031410342221354015540 0ustar gurkanroot// // DominionGame.h // Gridlock // // Created by Brian on 9/23/04. // Copyright 2004 __MyCompanyName__. All rights reserved. // #import "AtaxxGame.h" @interface DominionGame : AtaxxGame { } @end gridlock.app-1.10/FusionGame.h0000644000175000000000000000027710342221365015241 0ustar gurkanroot// // FusionGame.h // Gridlock // // Created by Brian on 11/24/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "Game.h" @interface FusionGame : Game { } @end gridlock.app-1.10/SabotageAI.h0000644000175000000000000000031010342221405015122 0ustar gurkanroot// // SabotageAI.h // Gridlock // // Created by Brian on 3/28/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "GenericAI.h" @interface SabotageAI : GenericAI { } @end gridlock.app-1.10/SabotageGame.h0000644000175000000000000000046510342221415015516 0ustar gurkanroot// // SabotageGame.h // Gridlock // // Created by Brian on 3/27/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "Game.h" @interface SabotageGame : Game { } -(DCHypergridPosition *)goalPositionForPlayer:(int)pnum; -(int)playerWithGoalPosition:(DCHypergridPosition *)pos; @end gridlock.app-1.10/SabotageViewDelegate.h0000644000175000000000000000034710342221437017215 0ustar gurkanroot// // SabotageViewDelegate.h // Gridlock // // Created by Brian on 3/27/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import @interface SabotageViewDelegate : NSObject { } @end gridlock.app-1.10/ThinkAheadAI.h0000644000175000000000000000033610342221452015407 0ustar gurkanroot// // ThinkAheadAI.h // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "GenericAI.h" @interface ThinkAheadAI : GenericAI { NSArray *depths; } @end gridlock.app-1.10/ThinkAheadGame.h0000644000175000000000000000034310342221461015765 0ustar gurkanroot// // ThinkAheadGame.h // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import "Game.h" @interface ThinkAheadGame : Game { int p1Score; int p2Score; } @end gridlock.app-1.10/ThinkAheadViewDelegate.h0000644000175000000000000000035310342221500017454 0ustar gurkanroot// // ThinkAheadViewDelegate.h // Gridlock // // Created by Brian on 3/26/05. // Copyright 2005 __MyCompanyName__. All rights reserved. // #import @interface ThinkAheadViewDelegate : NSObject { } @end gridlock.app-1.10/TongaGame.h0000644000175000000000000000027410342221506015040 0ustar gurkanroot// // TongaGame.h // Gridlock // // Created by Brian on 11/6/04. // Copyright 2004 __MyCompanyName__. All rights reserved. // #import "Game.h" @interface TongaGame : Game { } @end gridlock.app-1.10/readme.html0000644000175000000000000007464110342202616015162 0ustar gurkanroot Gridlock

    Gridlock

    v1.10 Copyright (c) 2002-2005 by Brian Nenninger

    Gridlock is free, but your support is welcome.
    Gridlock source code is available at http://www.dozingcatsoftware.com.

    Overview

    Gridlock is a collection of over 30 grid-based strategy games, including Ataxx, Reversi, Checkers, Gomoku, Connect Four, and more. They are individually described in the "Games" section.

    After launching the application, the game window will appear. Select the game you want to play from the "Game" popup menu in the upper right. Some games have different variations (board size, layout, etc); when one of those games are selected a "Variations" popup menu will appear from which you can select a variation.

    The bottom right displays the color and status of the two players. Each player's color is shown by a circle; the player whose turn it is has a filled circle. For games in which players have a score, the scores are shown next to the player labels. Popup windows underneath each player's label allow you to specify whether each player is human or computer-controlled, and the difficulty of computer players. (Note that "Hard" and "Very Hard" computer opponents may take several seconds to make each move).

    The rest of the window contains the game board. To make a move, click on the cell where you wish to place a piece. Some games require that you move from one cell to another; to do this first click on the cell you wish to move from, then click on the cell you wish to move to. (In some games such as Checkers you may be able to make a move containing several jumps; to do this click on each cell you wish to jump to in sequence). For all games, cells that are legal moves will become highlighted when you move the mouse over them. A black dot indicates the position of the last move. If you are unable to make a move, you can pass by clicking the "Pass" button on the right. The "Restart" button will restart the game, requiring confirmation if a game is in progress.

    The "Preferences..." menu item in the main Gridlock menu opens the Preferences window, which allows you to change the appearance of the game pieces, and to enable or disable the animation when they are captured. Game pieces can either be bitmap images chosen from the popup menus, or solid colors chosen from the color wells.

    Games can be saved and restored using the "Save" and "Open" commands in the Game menu. Games are saved with their full move history, so you can save a game after it is finished, open it later, and undo moves back to the beginning.

    The Edit menu contains Undo and Redo commands. Selecting Undo will back the game up to the last time it was a human player's turn. There is no limit to how many moves can be undone. Selecting Redo will redo a move that was previously undone, but only if no new moves were made after the undo.

    The Window menu contains commands to toggle the display of network and statistics drawers. The network drawer is described below and is primarily used to chat with your opponent during a network game. The statistics drawer shows a table listing all the moves that have been made in the current game, and information on the analysis performed during the last move made by a computer player.

    Games

    Additional information for many of these games is available at The World of Abstract Games.

    Ataxx: The object of this game is to capture your opponent's pieces by moving your pieces next to them. There are two types of moves you can make. A normal move consists of starting from a piece that you own and creating another piece one cell away from it (horizontally, vertically, or diagonally). The starting piece remains, and you capture any of your opponent's pieces that your new piece borders. A jump move consists of moving a piece you own two cells in any direction. As with a normal move, any opponent's pieces that border the ending position are captured. To make either kind of move, first click on a piece that you own, then click on the empty cell you want to move to. The game is over when all the cells are filled, and the player owning the most pieces is the winner.

    There are several variations with different starting configurations and board sizes, most of which place barriers in some of the cells. There are also 3 random variations for the 7x7 and 8x8 boards. The "V Sym" random variations will place the barriers in a pattern with vertical symmetry, and the "Both Sym" variations will place the barriers with both horizontal and vertical symmetry.

    Quad Wrangle: This game is similar to Ataxx. There are three types of moves. The first type consists of starting from a piece that you own and creating another piece one cell away from it. The starting piece remains, and you capture any of your opponent's pieces that your new piece borders. (This is the same as non-jump move in Ataxx). The second type consists of sliding a piece you own any number of squares horizontally, vertically, or diagonally. Any opponent's pieces that border the ending position are captured. The third type is a drop of a piece to any empty cell. Unlike the other move types, no pieces are captured with this move type. To make a normal or slide move, first click on a piece that you own, then click on the empty cell you want to move to. To make a drop, click on an empty cell. The game is over when all the cells are filled, and the player owning the most pieces is the winner.

    Reversi: (also known as Othello). The object is to capture the other player's pieces by enclosing them between two of your pieces. You make a move by placing a piece in an empty cell. You capture any of your opponent's pieces that are in a horizontal, vertical, or diagonal line between the new piece and another of your pieces. Every move must result in the capture of at least one piece; you must pass if you cannot capture any pieces. The game is over when the board is full or neither player can move; the player owning the most pieces is the winner.

    Checkers: The object is to remove your opponent's pieces or prevent them from moving. Pieces move forward and diagonally, and can jump and remove opposing pieces by landing in the empty space directly behind them. When a piece reaches the last row, it is promoted to a king (represented by two stacked game pieces). Kings can move backwards and well as forwards. Whenever you can make a jump, you must do so. See http://www.triplejump.net/usrules.shtml for more detailed rules.

    Gomoku: This is an expanded form of tic-tac-toe. Players move by placing a piece at any empty cell. A player wins by forming a straight line of 5 pieces horizontally, vertically, or diagonally.

    Connect Four: Similar to Gomoku, a player wins by forming a straight line of 4 pieces horizontally, vertically, or diagonally. However, you may only place a piece at the lowest empty cell in each column.

    Gravity: A player wins by forming a straight line of 4 pieces horizontally, vertically, or diagonally. The board has a "gravity field", which pulls pieces toward the edges or corners. If a cell is on a main diagonal (indicated by a gray background), a piece may be placed there only if there are no empty cells between that cell and the nearest corner. If a cell is not on a diagonal, a piece may be placed there only if there are no empty cells between that cell and the nearest edge.

    Hexapawn: The object of this game is to move one of your pieces (pawns) to the other side of the board. In the normal game, pawns move as standard chess pawns; moving forward one square to an empty position, or capturing diagonally forward. Berolina and Berolina Plus pawns can be used in variations of this game. Berolina pawns move diagonally forward and capture directly forward. Berolina Plus pawns are the same as Berolina pawns, except they can also capture sideways. For all variations, a player wins when one of his pawns reaches the final row, or when his opponent is unable to move.

    Breakthrough: The object of this game is to move one of your pieces to the other side of the board. Player 1's pieces start in the bottom two rows and move up; player 2's pieces start in the top two rows and move down. Pieces move one cell forward or diagonally forward. Pieces may capture opposing pieces when making a diagonal move, but not when making a direct forward move. A player wins when one of his pieces reaches the final row. Breakthrough was designed by Dan Troyka, the winner of the 2001 8x8 Game Design Competition; thanks to Dan for permission to include it.

    Zonesh: The object of this game is to move one of your pieces to the opposite corner. The set of cells where a player's pieces start the game is that player's home zone; these cells are indicated with a tinted background. Pieces in their home zone move and capture one square horizontally or vertically. Pieces outside their home zone may additionally move and capture one square diagonally. A player wins by moving one of his pieces to the corner cell in his opponent's home zone. Zonesh was also created by Dan Troyka.

    Glass Bead: The object of this game is to control the most cells. You control a cell if either you have placed a piece on the cell, or if the cell borders more of your pieces than your opponent's pieces. Players alternate placing pieces on cells that are not controlled by either player. Cells which do not contain pieces but which are controlled by a player are tinted with that player's color. The game ends when all cells are controlled by one of the players, and the player controlling the most cells wins. See here for more detailed information.

    Cats & Dogs: Players take turns placing pieces ("cats" and "dogs") on empty cells. A piece cannot be placed in a cell that is horizontally or vertically adjacent to an opposing piece. When a player places a piece on a cell, the adjacent cells will be tinted with his color to indicate that his opponent can no longer play there. If an empty cell becomes adjacent to pieces of both players, it will turn gray to indicate that neither player can play there. A player wins when his opponent is unable to move.

    Moray Eels: The object of this game is to capture the opposing pieces. Player 1's pieces are "Octopussies". They move one cell forward or diagonally forward. Player 2's pieces are "Eels". Like Octopussies, they can move one cell forward or diagonally forward. They can also move one or two cells sideways, or one or two cells sideways and one cell back. All moves must be to empty cells, and Eels can jump over friendly or opposing pieces. After a player moves, he gains control of all his opponent's pieces that are adjacent (horizontally, vertically, or diagonally) to his moved piece.

    Life: This game is based on the Game of Life cellular automaton. Both players take turns placing a piece on an empty cell. After a player places a piece, an iteration of the Life algorithm is executed. A piece survives if it has exactly 2 or 3 neighbors (pieces adjacent to it horizontally, vertically, or diagaonally). A piece is removed if it has less than 2 or more than 3 neighbors. A new piece will be created in an empty cell if it has exactly 3 neighbors; the new piece will be owned by the player who owns the majority of the neighbors. A player wins by owning at least three times as many pieces as the other player after a Life iteration.

    Atomic: Each player alternates dropping a piece in one of the cells. You may drop a piece in an empty cell or a cell in which you already have pieces. Each cell has a maximum number of pieces that it can hold. Corner cells can hold 1 piece, other edge cells can hold 2 pieces, and cells not on an edge can hold 3. When you drop a piece on a cell which exceeds the cell's limit, the cell will "explode". This causes the pieces in that cell to move to adjacent cells. Any enemy pieces in the adjacent cells are captured and change to the color of the exploding piece. Chain reactions of multiple explosions can occur when the result of the first explosion causes more cells to exceed their piece limit. A player wins by capturing all his opponent's pieces.

    Five Field Kono: The object of this game is to move all of your pieces into the cells that your opponent occupies at the start of the game. Pieces move one cell diagonally forward or backward. There is no capturing. Surprisingly, stalemates are not possible; one player can always force a wiin.

    Fission: The object of this game is to destroy all your opponent's pieces. Each piece slides horizontally, vertically, or diagonally until it hits either an edge of the board or another piece. If it hits an edge, nothing happens, but if it hits another piece it explodes, destroying itself and all adjacent pieces of both colors. There are 4 variations of this game; you can choose to use the standard starting positions, or have them randomized. In the "suicide" variations you win by destroying all of your pieces instead of your opponent's. If each player is reduced to a single piece, the game is a tie.

    Orthokon: Each piece slides horizontally or vertically as far as possible before hitting an edge of the board or another piece. After a piece is moved, any enemy pieces horizontally or vertically adjacent to its new location are captured. A player wins when he captures all his opponent's pieces, or when his opponent cannot move.

    Bombardment: The object is to destroy all your opponent's pieces, or to move one of your pieces to the other side of the board. Pieces move one cell forward or diagonally forward. A piece can also "detonate", destroying itself and all adjacent pieces of either color. To detonate a piece, click on it twice. (Be careful, this is easy to do accidentally).

    Reactor: The object of the game is to destroy your opponent's pieces. The pieces begin in random cells and never move. The only objects which do move are "neutrons", indicated by small red circles. During each player's turn, he must move one of the neutrons. They move by sliding horizontally, vertically, or diagaonally until they reach an edge of the board, or another piece or neutron. After the move, any pieces adjacent to the neutron's new location are destroyed. Neutrons themselves are never destroyed, and you can't move the same neutron that your opponent moved in his last turn.

    Tourney: The object is to either capture all your opponent's pieces, or "promote" one of your pieces by reaching the opposite side, and returning the promoted piece to your side. Pieces move like chess knights; two cells vertically and one horizontally, or two cells horizontally and one vertically. However, unlike chess knights, they cannot jump over pieces in the way. When moving two cells vertically and one horizontally, the adjacent cell in the vertical direction must be empty; likewise for horizontal moves. Additionally, non-promoted pieces cannot move backwards. For example, the first move of a game must be to take a piece in the second row and move it two vertically and one horizontally. The pieces in the back row can't move at all because the pieces in the second row are in the way, and the pieces in the second row can't move two horizontally because they block each other. Enemy pieces are captured and removed from the game by landing on them. Captures are mandatory, and as in checkers the capturing piece may make multiple captures in the same turn. When a piece reaches the opposite side, it is promoted and gains the ability to move backwards. A player wins by returning a promoted piece to his first row, or by capturing all his opponent's pieces.

    Daggers: This is a game with unequal forces. Player 1 has more pieces, but player 2's pieces are more powerful, at least at first. Each player has two "crowns", represented by two stacked pieces, and several "daggers", represented by single pieces. A player wins by either capturing one of his opponent's crowns, or by moving one of his crowns to the opposite side of the board. Crowns move and capture one cell in any direction, like chess kings. Daggers can slide any number of squares down (towards the bottom of the board), either straight down or diagonally down. They may also move one cell up or diagonally up. This makes daggers at high positions more valuable since they can move further. A dagger can capture an enemy dagger or crown when moving diagonally, and can capture crowns (but not daggers) when moving vertically.

    Fianco: The object is to move one of your pieces to the last row. A piece moves one cell either forward or sideways. A piece may capture an enemy piece by jumping diagonally forward over it, landing in the next cell (which must be empty). Captures are mandatory, and there are no multiple captures.

    Diagonals: The object of the game is to achieve the highest score by completing diagonal lines. Each turn, each player drops a piece on an empty cell. If that piece forms a diagonal line of pieces from one edge of the board to another, the player scores points equal to the number of his own pieces in that line. Note that a single piece can complete two diagonal lines at once. The game ends when all cells are filled, and the player with the highest score wins.

    Photonic Attack: Each turn, a player "fires" a piece from one of the board edges, which travels until it hits the other edge or another piece. To make a move, click on the cell where the fired piece would end. After a piece is placed, all enemy pieces in a horizontal or vertical line starting from the new piece are captured and converted to the new piece's color. The game is over when no more moves are possible (you can't fire a piece from an edge if the edge cell is occupied), and the player who owns the most pieces is the winner.

    Dominion: This game is a combination of Ataxx and Reversi. Moves are the same as Ataxx; you can create a new piece in an empty cell adjacent to one of your existing pieces, or jump one of your pieces two cells to an empty cell. Also as in Ataxx, any opposing pieces adjacent to the destination cell are captured. Like Reversi, all opposing pieces that are in a line between the moved piece and another of your pieces are also captured. The game is over when the board is full and the winner is the player with the most pieces.

    Tonga: The object of this game is to score points by arranging your pieces in large groups. Each move consists of simultaneously placing one of your pieces and one of your opponent's pieces on adjacent empty cells. To make a move, first click on the cell you want your piece to go, then on a neighboring cell where you want your opponent's piece to go. Each player's score is determined by their three largest groups of connected pieces. Only horizontal and vertical connections count; diagonals don't. A player's score is the sum of the squares of the sizes of her three largest connected groups. For example, if you have groups of 8, 6, 5, and 3, your score would be (8*8)+(6*6)+(5*5)=125. The game is over when no more moves are possible, and the highest score wins.

    Think Ahead: The board is randomly filled with positive and negative numbers, and a single black ball. Player 1 moves the ball horizontally, and player 2 moves the ball vertically. Each turn, each player moves the ball to a cell with a number in it. That number is removed from the board and added to the player's score. The game is over when a player cannot move (because all the cells in the ball's row or column have been used), and the highest score wins.

    Sabotage: The object of this game is to capture the "ball" in the middle of the board and deliver it to the goal. Each turn, a player moves one of her pieces. Pieces move in a straight line horizontally, vertically, or diagonally, and move a number of cells equal to the total number of all pieces (friendly and opposing) in the starting column. Pieces may capture and remove opposing pieces by landing on them, and may pick up the ball by landing on it. Pieces may not jump over friendly or opposing pieces when moving. If a piece captures an opposing piece which was carrying the ball, the capturing piece takes the ball. A player wins by moving her piece carrying the ball into her goal, which is designated by being shaded in her piece's colors.

    Ambivalence: The object of the game is to "capture" opposing pieces and turn them into walls. Each turn, a player drops a piece into any empty cell. If the new piece traps an opposing piece between it and another friendly piece, the opposing piece is captured and turns into a wall. Also, if the new piece is placed between two opposing pieces, *both* opposing pieces become walls. The game is over when the board is full, and the player with the most pieces wins.

    Fusion: Each player starts owning two pieces called "atoms". Several "protons" (small red circles) are placed randomly on the board. Protons are the only pieces that move. Each turn, a player moves a proton any number of empty cells horizontally, vertically, or diagonally. The ending cell must be adjacent to at least one atom (owned by either player). The proton changes itself and any adjacent protons and atoms into atoms owned by the current player. When all protons are gone, the player with the most atoms wins.

    Network Play

    To host a network game, select "Host Network Game" from the Gridlock menu. A window will appear allowing you to select the game and variation (if applicable) that you wish to play. If you want to restrict who can join your game, you may enter a password in the "Password" text field. Anyone attempting to join your game must provide this password or they will be unable to connect. (Obviously, do not use any of your real passwords). The "Port" field should usually be left at the default value of 27500; change it only if you get an error when attempting to host. The "Username" field is the name you will be identified as to your opponent. The default is your user account name, but you can change it to anything. To begin hosting, click the "Host" button. The game will automatically begin when someone connects to your computer. Close the window or click the Stop button to stop waiting for connections.

    To join a network game, select "Join Network Game" from the Gridlock menu. Enter the hostname or IP address of the computer you wish to connect to in the "Address" field, and change the port number if the computer is not using the default of 27500. If your machine supports Rendezvous and one or more Rendezvous-enabled machines are hosting games on your local network, you will see a popup menu listing all of them. To connect to one of them, select the "Rendezvous" radio button and choose the game you want to join from the popup menu. If the game you are joining requires a password, enter it in the "Password" field. The "Username" field has the same purpose as when hosting, to identify you to your opponent. Once you have manually entered an address or selected a Rendezvous host, click the "Connect" button to connect to the selected machine. If the connection is successfully established, the game will begin immediately.

    When a network game begins, a drawer will open from the game window allowing you to chat with your opponent. To send a message, type into the text field at the top of the drawer and press the Return key. Game moves are made in the same way as when playing against a computer opponent. Either player may restart the game or start a different game and/or variation. The player who initially hosted the game is always player 1, and the player who connected is player 2. When playing against a network opponents, the popup menu next to their player labels will have "Network" selected. Changing either player's type will end the network game and disconnect. You can also disconnect from a network game using the "Disconnect" button in the network drawer.

    Tip Jar

    Gridlock is completely free, but if you find it useful you can support its development by:

  • Donating via PayPal
  • Signing up for a pokerroom.com account using this link. Pokerroom.com is an excellent Mac-friendly poker site, where you can play Texas Hold'em and other games for real or play money.

    Version History

    1.10, Nov 26 2005

    • Added 6 new games.
    • Built as universal binary for PowerPC and Intel processors. (Intel version is completely untested; if you have access to OS X for x86 let me know how it runs).
    • Fixed display bugs when user interface scaling is active in Tiger.

    1.9, Aug 14 2004

    • Added 11 new games.
    • Added random starting positions and other variations for several games.
    • The application UI no longer hangs when the computer opponent is considering a move.
    • Improved performance and use of multiple processors.

    1.8, Sep 28 2003

    • Added Hexapawn, Quad Wrangle, Cats & Dogs, and Moray Eels games.
    • Implemented alpha-beta search algorithm for computer opponents, greatly improving performance.
    • Added harder computer opponents for several games.
    • New icon.
    • Miscellaneous interface improvements.

    1.7, Aug 10 2003

    • Added Gravity and Zonesh games.
    • Computer opponents are faster and use multiple processors more effectively.
    • Checkers no longer ends in a tie after 100 moves without capture; Connect Four is now the correct 6x7 size.

    1.6.1, Jul 1 2003

    • Computer opponents are much faster and take advantage of multiple processors. (Thanks to the Apple engineers at WWDC for their assistance).
    • Minor bug fixes

    1.6, Jun 15 2003

    • Added Life game
    • Improved speed of computer opponents
    • Many bug fixes
    • GNUstep version synced

    1.5, Apr 27 2003

    • Added network support
    • Added saving and loading of games
    • Added statistics drawer
    • Added indicator for previous move

    1.3, Nov 16 2002

    • Added Checkers game
    • Added undo and redo of moves
    • Minor bug fixes

    1.2, Aug 25 2002

    • Game pieces can be bitmap images
    • More configurations added
    • Game window is resizeable and remembers its position
    • Pass button is enabled and disabled as appropriate
    • Drawing methods optimized
    • Application builds and runs under GNUstep

    1.1, Jul 20 2002

    • Added Breakthrough and Glass Bead games
    • Added multiple starting configurations for several games
    • Improved speed and skill of computer opponents
    • Redesigned UI to use a single window
    • Added cell highlighting when mouse moves over a legal position

    1.0, Apr 2 2002: initial release

    Feedback

    Contact me with any bug reports, comments, or suggestions at brian@dozingcatsoftware.com.

    License

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    Gridlock contains code from the EDCommon framework, which is Copyright (c) 1997-2001 by Erik Doernenburg. The following applies to such code:

    Permission to use, copy, modify and distribute this software and its documentation is hereby granted, provided that both the copyright notice and this permission notice appear in all copies of the software, derivative works or modified versions, and any portions thereof, and that both notices appear in supporting documentation, and that credit is given to Erik Doernenburg in all documents and publicity pertaining to direct or indirect use of this code or its derivatives.

    THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF ANY DERIVATIVE WORK.