diff options
author | John Fultz <jfultz@wolfram.com> | 2016-07-03 03:07:52 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-03 03:07:52 -0500 |
commit | 50c4a8cd619d0da78a1a4012d2f688dea4c7ec27 (patch) | |
tree | a40498693dc3b56005c96c35c7c38aa816782662 | |
parent | da2f20720facda706be06b5813ab20057d5b4de9 (diff) | |
parent | 147b22ae1225863cac9f07b3906415713afdcf02 (diff) |
Merge pull request #35 from gokceneraslan/master
Generate Python, Lua and Go bindings through SWIG
-rw-r--r-- | bindings/Makefile | 56 | ||||
-rw-r--r-- | bindings/go/quackle.go | 6 | ||||
-rw-r--r-- | bindings/lua/test_selfplay.lua | 90 | ||||
-rw-r--r-- | bindings/python/test1_position.py | 78 | ||||
-rw-r--r-- | bindings/python/test2_selfplay.py | 84 | ||||
-rw-r--r-- | bindings/quackle.i | 111 | ||||
-rw-r--r-- | quackleio/gcgio.cpp | 18 | ||||
-rw-r--r-- | quackleio/gcgio.h | 1 |
8 files changed, 444 insertions, 0 deletions
diff --git a/bindings/Makefile b/bindings/Makefile new file mode 100644 index 0000000..9cdb6a3 --- /dev/null +++ b/bindings/Makefile @@ -0,0 +1,56 @@ +CC=g++ + +QTFLAGS := $(shell pkg-config QtCore --cflags) +QTLIBS := $(shell pkg-config QtCore --libs) +PYTHONFLAGS := $(shell pkg-config python2 --cflags) +PHPFLAGS := $(shell php-config --includes) +PHPLIBS := $(shell php-config --libs) +LUAFLAGS := $(shell pkg-config lua5.1 --cflags) + +INCLUDES=-I.. +QUACKLELIBS=../lib/release/libquackle.a ../quackleio/lib/release/libquackleio.a + +php/quackle_wrap.cxx: + @test -d php || mkdir php + swig -c++ -o $@ $(INCLUDES) $(QTFLAGS) -php quackle.i + +php/quackle_wrap.o: php/quackle_wrap.cxx + $(CC) -std=c++11 -fPIC $(QTFLAGS) $(PHPFLAGS) $(PHPLIBS) $(INCLUDES) -c $< -o $@ + +php: php/quackle_wrap.o + $(CC) -std=c++11 -shared -Wl,--whole-archive $(QUACKLELIBS) -Wl,--no-whole-archive $(QTLIBS) $< -o php/quackle.so + +python/quackle_wrap.cxx: + @test -d python || mkdir python + swig -c++ -o $@ $(INCLUDES) $(QTFLAGS) -python quackle.i + +python/quackle_wrap.o: python/quackle_wrap.cxx + $(CC) -std=c++11 -fPIC $(QTFLAGS) $(PYTHONFLAGS) $(INCLUDES) -c $< -o $@ + +python: python/quackle_wrap.o + $(CC) -std=c++11 -shared -Wl,--whole-archive $(QUACKLELIBS) -Wl,--no-whole-archive $(QTLIBS) $< -o python/_quackle.so + +go: + ln -sf ../quackle.i go/quackle.swigcxx + go build ./go/... + +lua/quackle_wrap.cxx: + @test -d lua || mkdir lua + swig -c++ -o $@ $(INCLUDES) $(QTFLAGS) -lua quackle.i + +lua/quackle_wrap.o: lua/quackle_wrap.cxx + $(CC) -std=c++11 -fPIC $(LUAFLAGS) $(QTFLAGS) $(INCLUDES) -c $< -o $@ + +lua: lua/quackle_wrap.o + $(CC) -std=c++11 -shared $(LUAFLAGS) -Wl,--whole-archive $(QUACKLELIBS) -Wl,--no-whole-archive $(QTLIBS) $< -o lua/quackle.so + +.PHONY: clean go + +clean: + -rm -rf python/quackle.py + -rm -rf php/*php* + -rm -rf */*_wrap.cxx + -rm -rf */*.o + -rm -rf */*.so + -rm -rf */*.pyc + -rm -rf go/quackle.swigcxx diff --git a/bindings/go/quackle.go b/bindings/go/quackle.go new file mode 100644 index 0000000..6c40a84 --- /dev/null +++ b/bindings/go/quackle.go @@ -0,0 +1,6 @@ +package quackle + +// #cgo CXXFLAGS: -I../.. +// #cgo pkg-config: QtCore +// #cgo LDFLAGS: -L${SRCDIR}/../../lib/release -L${SRCDIR}/../../quackleio/lib/release -lquackle -lquackleio -lQtCore +import "C" diff --git a/bindings/lua/test_selfplay.lua b/bindings/lua/test_selfplay.lua new file mode 100644 index 0000000..9209f52 --- /dev/null +++ b/bindings/lua/test_selfplay.lua @@ -0,0 +1,90 @@ +require 'quackle' + +function startUp(lexicon, alphabet, datadir) + + local lexicon = lexicon or 'twl06' + local alphabet = alphabet or 'english' + local datadir = datadir or '../../data' + + -- Set up the data manager + local dm = quackle.DataManager() + dm:setComputerPlayers(quackle.ComputerPlayerCollection.fullCollection()) + dm:setBackupLexicon(lexicon) + dm:setAppDataDirectory(datadir) + + -- Set up the alphabet + local abc = quackle.AlphabetParameters.findAlphabetFile(alphabet) + local abc2 = quackle.Util.stdStringToQString(abc) --convert to qstring + local fa = quackle.FlexibleAlphabetParameters() + + assert(fa:load(abc2)) + dm:setAlphabetParameters(fa) + + -- Set up the board + local board = quackle.BoardParameters() + dm:setBoardParameters(board) + + -- Find the lexicon + local dawg = quackle.LexiconParameters.findDictionaryFile(lexicon .. '.dawg') + local gaddag = quackle.LexiconParameters.findDictionaryFile(lexicon .. '.gaddag') + dm:lexiconParameters():loadDawg(dawg) + dm:lexiconParameters():loadGaddag(gaddag) + + dm:strategyParameters():initialize(lexicon) + return dm + +end + + +function getComputerPlayer(dm, name) + + local name = name or 'Speedy Player' + + local player, found = dm:computerPlayers():playerForName(name) + assert(found) + player = player:computerPlayer() + + return player + +end + +dm = startUp() + +p1 = getComputerPlayer(dm) +p2 = getComputerPlayer(dm) + +-- Create computer players +player1 = quackle.Player('Compy1', quackle.Player.ComputerPlayerType, 0) +player1:setComputerPlayer(p1) +print(player1:name()) + +player2 = quackle.Player('Compy2', quackle.Player.ComputerPlayerType, 1) +player2:setComputerPlayer(p2) +print(player2:name()) + +dm:seedRandomNumbers(42) + +game = quackle.Game() +players = quackle.PlayerList() + +players:push_back(player1) +players:push_back(player2) + +game:setPlayers(players) +game:associateKnownComputerPlayers() +game:addPosition() + +for i=1, 50 do + if game:currentPosition():gameOver() then + print "GAME OVER" + break + end + + player = game:currentPosition():currentPlayer() + move = game:haveComputerPlay() + --print("Player: " .. player:name()) + print("Rack : " .. player:rack():toString()) + print('Move: ' .. move:toString()) + print('Board: \n' .. game:currentPosition():board():toString()) + +end diff --git a/bindings/python/test1_position.py b/bindings/python/test1_position.py new file mode 100644 index 0000000..e04081a --- /dev/null +++ b/bindings/python/test1_position.py @@ -0,0 +1,78 @@ +# coding: utf-8 + +import quackle + +def startUp(lexicon='twl06', + alphabet='english', + datadir='../../data'): + + # Set up the data manager + dm = quackle.DataManager() + dm.setComputerPlayers(quackle.ComputerPlayerCollection.fullCollection()) + dm.setBackupLexicon(lexicon) + dm.setAppDataDirectory(datadir) + + # Set up the alphabet + abc = quackle.AlphabetParameters.findAlphabetFile(alphabet) + abc2 = quackle.Util.stdStringToQString(abc) #convert to qstring + fa = quackle.FlexibleAlphabetParameters() + + assert fa.load(abc2) + dm.setAlphabetParameters(fa) + + # Set up the board + board = quackle.BoardParameters() + dm.setBoardParameters(board) + + # Find the lexicon + dawg = quackle.LexiconParameters.findDictionaryFile(lexicon + '.dawg') + gaddag = quackle.LexiconParameters.findDictionaryFile(lexicon + '.gaddag') + dm.lexiconParameters().loadDawg(dawg) + dm.lexiconParameters().loadGaddag(gaddag) + + dm.strategyParameters().initialize(lexicon) + return dm + + +def getComputerPlayer(dm, name='Speedy Player'): + player, found = dm.computerPlayers().playerForName(name) + assert found + player = player.computerPlayer() + return player + + +dm = startUp() + +# Create a computer player +player1 = getComputerPlayer(dm) +print player1.name() + +# Create the Game file (.gcg) reader +gamereader = quackle.GCGIO() +gamePath = quackle.Util.stdStringToQString('../../test/positions/short_game_with_bad_moves.gcg') +game = gamereader.read(gamePath, quackle.Logania.MaintainBoardPreparation) + +# Get the current position +position = game.currentPosition() + +player1.setPosition(position) + +racks = quackle.ProbableRackList() +unseenbag = position.unseenBag() +if unseenbag.size() <= dm.parameters().rackSize() + 3: + enum = quackle.Enumerator(unseenbag) + enum.enumerate(racks) + for rack in racks: + print rack + +movesToShow = 10 + +print "Board state: \n%s" % position.board().toString() +print "Move made: %s" % position.moveMade().toString() +print "Current player: %s" % position.currentPlayer().storeInformationToString() +print "Turn number: %i" % position.turnNumber() + +movelist = player1.moves(10) + +# Show 10 moves suggested by computer player +for move in movelist: print move.toString() diff --git a/bindings/python/test2_selfplay.py b/bindings/python/test2_selfplay.py new file mode 100644 index 0000000..bb6e889 --- /dev/null +++ b/bindings/python/test2_selfplay.py @@ -0,0 +1,84 @@ +# coding: utf-8 + +import time + +import quackle + +def startUp(lexicon='twl06', + alphabet='english', + datadir='../../data'): + + # Set up the data manager + dm = quackle.DataManager() + dm.setComputerPlayers(quackle.ComputerPlayerCollection.fullCollection()) + dm.setBackupLexicon(lexicon) + dm.setAppDataDirectory(datadir) + + # Set up the alphabet + abc = quackle.AlphabetParameters.findAlphabetFile(alphabet) + abc2 = quackle.Util.stdStringToQString(abc) #convert to qstring + fa = quackle.FlexibleAlphabetParameters() + + assert fa.load(abc2) + dm.setAlphabetParameters(fa) + + # Set up the board + board = quackle.BoardParameters() + dm.setBoardParameters(board) + + # Find the lexicon + dawg = quackle.LexiconParameters.findDictionaryFile(lexicon + '.dawg') + gaddag = quackle.LexiconParameters.findDictionaryFile(lexicon + '.gaddag') + dm.lexiconParameters().loadDawg(dawg) + dm.lexiconParameters().loadGaddag(gaddag) + + dm.strategyParameters().initialize(lexicon) + return dm + + +def getComputerPlayer(dm, name='Speedy Player'): + player, found = dm.computerPlayers().playerForName(name) + assert found + player = player.computerPlayer() + return player + + +dm = startUp() + +p1 = getComputerPlayer(dm) +p2 = getComputerPlayer(dm) + +# Create computer players +player1 = quackle.Player('Compy1', quackle.Player.ComputerPlayerType, 0) +player1.setComputerPlayer(p1) +print player1.name() + +player2 = quackle.Player('Compy2', quackle.Player.ComputerPlayerType, 1) +player2.setComputerPlayer(p2) +print player2.name() + +dm.seedRandomNumbers(42) + +game = quackle.Game() +players = quackle.PlayerList() + +players.append(player1) +players.append(player2) + +game.setPlayers(players) +game.associateKnownComputerPlayers() +game.addPosition() + +for i in range(50): + if game.currentPosition().gameOver(): + print "GAME OVER" + break + + player = game.currentPosition().currentPlayer() + move = game.haveComputerPlay() + #print "Player: " + player.name() + print "Rack : " + player.rack().toString() + print 'Move: ' + move.toString() + print 'Board: \n' + game.currentPosition().board().toString() + + time.sleep(1) diff --git a/bindings/quackle.i b/bindings/quackle.i new file mode 100644 index 0000000..e45eb88 --- /dev/null +++ b/bindings/quackle.i @@ -0,0 +1,111 @@ +%module quackle +%{ +#include "fixedstring.h" +#include "uv.h" +#include "alphabetparameters.h" +#include "move.h" +#include "rack.h" +#include "bag.h" +#include "board.h" +#include "boardparameters.h" +#include "evaluator.h" +#include "catchall.h" +#include "player.h" +#include "game.h" +#include "gameparameters.h" +#include "sim.h" +#include "computerplayer.h" +#include "computerplayercollection.h" +#include "datamanager.h" +#include "endgame.h" +#include "endgameplayer.h" +#include "enumerator.h" +#include "bogowinplayer.h" +#include "clock.h" +#include "generator.h" +#include "gaddag.h" +#include "lexiconparameters.h" +#include "preendgame.h" +#include "reporter.h" +#include "resolvent.h" +#include "strategyparameters.h" + +#include <QString> +#include "quackleio/flexiblealphabet.h" +#include "quackleio/util.h" +#include "quackleio/logania.h" +#include "quackleio/gcgio.h" +%} + + +%include "std_string.i" +%include "std_vector.i" +%include "typemaps.i" + +%include "fixedstring.h" +%include "uv.h" +%include "alphabetparameters.h" + +/*Needed to generate proper iterable types */ +%template(MoveVector) std::vector<Quackle::Move>; +%template(PlayerVector) std::vector<Quackle::Player>; +%template(ProbableRackList) std::vector<Quackle::ProbableRack>; +%template(PositionList) std::vector<Quackle::GamePosition>; +%template(LetterParameterVector) std::vector<Quackle::LetterParameter>; +%template(LetterStringVector) std::vector<Quackle::LetterString>; + +%include "move.h" +%include "rack.h" +%include "bag.h" +%include "board.h" +%include "boardparameters.h" +%include "evaluator.h" +%include "catchall.h" +%include "player.h" + +using namespace std; +namespace Quackle +{ + class PlayerList : public vector<Player> + { + public: + PlayerList(); + + const Player &playerForId(int id, bool &OUTPUT) const; + const Player &playerForName(const UVString &name, bool &OUTPUT) const; + }; +} + +%include "game.h" +%include "gameparameters.h" +%include "sim.h" +%include "computerplayer.h" +%include "computerplayercollection.h" + +%apply SWIGTYPE *DISOWN {Quackle::AlphabetParameters *alphabetParameters}; +%apply SWIGTYPE *DISOWN {Quackle::BoardParameters *boardParameters}; +%apply SWIGTYPE *DISOWN {Quackle::StrategyParameters *lexiconParameters}; +%apply SWIGTYPE *DISOWN {Quackle::LexiconParameters *lexiconParameters}; +%apply SWIGTYPE *DISOWN {Quackle::Evaluator *evaluator}; +%apply SWIGTYPE *DISOWN {Quackle::GameParameters *parameters}; +%apply SWIGTYPE *DISOWN {const Quackle::PlayerList &playerList}; + +%include "datamanager.h" +%include "endgame.h" +%include "endgameplayer.h" +%include "enumerator.h" +%include "bogowinplayer.h" +%include "clock.h" +%include "generator.h" +%include "gaddag.h" +%include "lexiconparameters.h" +%include "preendgame.h" +%include "reporter.h" +%include "resolvent.h" +%include "strategyparameters.h" + +%include <QString> +%include "quackleio/flexiblealphabet.h" +%include "quackleio/util.h" +%include "quackleio/logania.h" +%include "quackleio/gcgio.h" diff --git a/quackleio/gcgio.cpp b/quackleio/gcgio.cpp index 9209be5..8f8112f 100644 --- a/quackleio/gcgio.cpp +++ b/quackleio/gcgio.cpp @@ -30,6 +30,24 @@ GCGIO::GCGIO() { } +Quackle::Game *GCGIO::read(const QString &filename, int flags) +{ + QFile file(filename); + Quackle::Game *ret = new Quackle::Game; + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + UVcerr << "Could not open gcg " << QuackleIO::Util::qstringToString(filename) << endl; + return ret; + } + + QTextStream in(&file); + ret = read(in, flags); + file.close(); + + return ret; +} + Quackle::Game *GCGIO::read(QTextStream &stream, int flags) { Quackle::Game *ret = new Quackle::Game; diff --git a/quackleio/gcgio.h b/quackleio/gcgio.h index 477f84f..a219c9f 100644 --- a/quackleio/gcgio.h +++ b/quackleio/gcgio.h @@ -30,6 +30,7 @@ public: GCGIO(); ~GCGIO() {}; + virtual Quackle::Game *read(const QString &filename, int flags); virtual Quackle::Game *read(QTextStream &stream, int flags); virtual bool canRead(QTextStream &stream) const; virtual void write(const Quackle::Game &game, QTextStream &stream); |