diff --git a/.gitignore b/.gitignore
index 3f2a73f..d176978 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
*.swp
*.dump
*.beam
+Mnesia.*
diff --git a/HOWTO b/HOWTO
index 064d127..2d28ea8 100644
--- a/HOWTO
+++ b/HOWTO
@@ -3,7 +3,7 @@ python version 2.x set to default.
INSTALL
1. Cd into directory where you to have the project
-2. git-clone git@github.com:jeena/GGS.git (remember to have a local key)
+2. git clone git@github.com:jeena/GGS.git (remember to have a local key)
3. cd GGS/
4. git submodule init
5. git submodule update
diff --git a/build b/build
index d468113..a9c1c79 100755
--- a/build
+++ b/build
@@ -3,4 +3,4 @@
for i in `find src -name "*.erl"`
do
erlc -o ebin $i
-done
+done
\ No newline at end of file
diff --git a/client b/client
new file mode 100644
index 0000000..dff11aa
--- /dev/null
+++ b/client
@@ -0,0 +1,17 @@
+#!/usr/bin/env ruby -wKU
+
+require 'socket' # Sockets are in standard library
+
+hostname = 'localhost'
+port = 7000
+
+s = TCPSocket.open(hostname, port)
+
+
+
+s.print(q.chop)
+
+while line = s.gets # Read lines from the socket
+ puts "Got Echo: " + line.chop # And print with platform line terminator
+end
+s.close # Close the socket when done
diff --git a/games/tic-tac-toe-js/index.html b/games/tic-tac-toe-js/index.html
index 97d3c4f..5bdb286 100644
--- a/games/tic-tac-toe-js/index.html
+++ b/games/tic-tac-toe-js/index.html
@@ -12,8 +12,16 @@
function init() {
GameServer.addGame(game_name, main());
- GameServer.addClient(game_name, new TicTacToeClient(frames.player1.document.getElementById("p1"), GameServer));
- GameServer.addClient(game_name, new TicTacToeClient(frames.player2.document.getElementById("p2"), GameServer));
+ GameServer.addClient(
+ game_name,
+ new TicTacToeClient(frames.player1.document.getElementById("p1"),
+ GameServer
+ ));
+ GameServer.addClient(
+ game_name,
+ new TicTacToeClient(frames.player2.document.getElementById("p2"),
+ GameServer
+ ));
}
diff --git a/games/tic-tac-toe-js/js/TicTacToeClient.js b/games/tic-tac-toe-js/js/TicTacToeClient.js
index 80f8ef1..79e4064 100644
--- a/games/tic-tac-toe-js/js/TicTacToeClient.js
+++ b/games/tic-tac-toe-js/js/TicTacToeClient.js
@@ -90,4 +90,4 @@ TicTacToeClient.prototype.updateBoard = function(gameBoardData) {
this.spots[k++].innerHTML = t;
}
}
-}
\ No newline at end of file
+}
diff --git a/games/tic-tac-toe-js/proxy.rb b/games/tic-tac-toe-js/proxy.rb
new file mode 100644
index 0000000..e69de29
diff --git a/games/tic-tac-toe/TODO b/games/tic-tac-toe/TODO
index 07c0710..a957a1f 100644
--- a/games/tic-tac-toe/TODO
+++ b/games/tic-tac-toe/TODO
@@ -1,12 +1,6 @@
-- background image
-- subimages for game_area:s
-- subimages for game markers (X or 0)
-- rectangle collision on game_area:s
+- background
- redraw background then all game_area:s
-- board_state: a hashtable where key is game_area_index
- and value is either'x' 'o' or ' '
- board contains nr_of_squares = 9
board contains array of squares with nr_of_squares elements
board contains x, y, width and height
board contains a frame
diff --git a/games/tic-tac-toe/data.py b/games/tic-tac-toe/data.py
new file mode 100644
index 0000000..b83c3ad
--- /dev/null
+++ b/games/tic-tac-toe/data.py
@@ -0,0 +1,15 @@
+def greatest_sequence(match, pattern):
+ m = match
+ p = pattern
+ size = 0
+ max_size = 0
+
+ for p in pattern:
+ if m == p:
+ size += 1
+ else:
+ if size > max_size:
+ max_size = size
+ size = 0
+
+ return max_size
diff --git a/games/tic-tac-toe/data.pyc b/games/tic-tac-toe/data.pyc
new file mode 100644
index 0000000..682dfaa
Binary files /dev/null and b/games/tic-tac-toe/data.pyc differ
diff --git a/games/tic-tac-toe/e.png b/games/tic-tac-toe/e.png
index 4cbf977..1b1d7f7 100644
Binary files a/games/tic-tac-toe/e.png and b/games/tic-tac-toe/e.png differ
diff --git a/games/tic-tac-toe/player.py b/games/tic-tac-toe/player.py
new file mode 100644
index 0000000..081112c
--- /dev/null
+++ b/games/tic-tac-toe/player.py
@@ -0,0 +1,15 @@
+from pygame.mouse import get_pos
+from point import Point
+
+class Player(object):
+ def __init__(self, id, shape, board):
+ self.shape = shape
+ self.board = board
+ self.id = id
+
+
+ def turn(self):
+ #Ask mouse for position
+ board.make_turn(Point(get_pos()[0],get_pos()[1]))
+
+
diff --git a/games/tic-tac-toe/server.py b/games/tic-tac-toe/server.py
new file mode 100644
index 0000000..91e32b5
--- /dev/null
+++ b/games/tic-tac-toe/server.py
@@ -0,0 +1,23 @@
+#server.py
+import json
+from socket import socket, AF_INET, SOCK_STREAM
+
+
+class server(object):
+ def __init__(self, port=None):
+ self.port = port
+ self.world = GGS.init()
+ self.socket = socket(AF_INET, SOCK_STREAM)
+ self.socket.connect(("www.???.com", 80))
+
+ def turn(self, id, index):
+ rows = sqrt(board.nr_of_rectangles)
+ x = int(index / rows)
+ y = int(index % rows)
+
+ json.dumps({"x": x, "y": y}
+ world.callCommand("tictactoe", "set", json.dumps({"x": x, "y": y}))
+
+ sent = 0
+ length = len(
+ while sent
diff --git a/games/tic-tac-toe/test_data.py b/games/tic-tac-toe/test_data.py
new file mode 100644
index 0000000..38282f0
--- /dev/null
+++ b/games/tic-tac-toe/test_data.py
@@ -0,0 +1,14 @@
+import unittest
+import data
+
+
+class TestData(unittest.TestCase):
+ def setUp(self):
+ array = [0,1,1,1,3,4,5,2,2,3,3,3,3,3,33,4,2,2]
+
+ self.assertTrue(data.greatest_sequence(array, 3) == 5)
+
+if __name__ == '__main__':
+ unittest.main()
+
+
diff --git a/games/tic-tac-toe/tictactoeboard.py b/games/tic-tac-toe/tictactoeboard.py
index ee1c057..10562dd 100644
--- a/games/tic-tac-toe/tictactoeboard.py
+++ b/games/tic-tac-toe/tictactoeboard.py
@@ -4,6 +4,7 @@ from point import Point
from pygame.image import load
from pygame.rect import Rect
from pygame import Surface
+from data import greatest_sequence
#inherits Board.
#Used for displaying the board on the screen and interact with it
@@ -47,4 +48,14 @@ class TicTacToeBoard(Board):
game_rectangle.state = 'o'
self.players_turn = (self.players_turn + 1) % 2
+ """
+ def turn(self, mouse_point):
+ if player.id != players_turn:
+ print "Other players turn"
+ else:
+ for game_rectangle in self.game_rectangles:
+ if (mouse_point.inside(game_rectangle) and
+ game_rectangle.state == ' '):
+ server.turn(player.id, game_rectangle.index)
+ """
diff --git a/games/tic-tac-toe/tictactoeboard.pyc b/games/tic-tac-toe/tictactoeboard.pyc
index 1243dc1..8913f16 100644
Binary files a/games/tic-tac-toe/tictactoeboard.pyc and b/games/tic-tac-toe/tictactoeboard.pyc differ
diff --git a/mnesia/.gamedb.erl.swp b/mnesia/.gamedb.erl.swp
new file mode 100644
index 0000000..469b1f8
Binary files /dev/null and b/mnesia/.gamedb.erl.swp differ
diff --git a/Mnesia/gamedb.erl b/mnesia/gamedb.erl
similarity index 50%
rename from Mnesia/gamedb.erl
rename to mnesia/gamedb.erl
index 9d6bbbe..751eb92 100644
--- a/Mnesia/gamedb.erl
+++ b/mnesia/gamedb.erl
@@ -1,26 +1,45 @@
-%Test Mnesia
+%%%%----------------------------------------------------
+%%% @author Mattias Pettersson
+%%% @copyright 2011 Mattias Pettersson
+%%% @doc Database for runtime game variable storage.
+%%% @end
+
+ Test Mnesia
-module(gamedb).
-import(mnesia).
-export([init/0,insert_player/1,example_player/0,read_player/1,test_player/0]).
-include("gamedb.hrl").
+%%-----------------------------------------------------
+%% Creation
+%%-----------------------------------------------------
init() ->
mnesia:create_table(player, [{attributes, record_info(fields, player)}]).
+%%-----------------------------------------------------
+%% Test
+%%-----------------------------------------------------
test_player() ->
insert_player(example_player()),
read_player(0001).
+example_player() ->
+ #player{id = 0001,
+ name = "Tux"}.
+
+%%-----------------------------------------------------
+%% Insertions
+%%-----------------------------------------------------
insert_player(Player) ->
Fun = fun() ->
mnesia:write(Player)
end,
mnesia:transaction(Fun).
-example_player() ->
- #player{id = 0001,
- name = "Tux"}.
+%%-----------------------------------------------------
+%% Querries
+%%-----------------------------------------------------
read_player(Player_Key) ->
Fun = fun() ->
[P] = mnesia:read(player, Player_Key),
diff --git a/Mnesia/gamedb.hrl b/mnesia/gamedb.hrl
similarity index 100%
rename from Mnesia/gamedb.hrl
rename to mnesia/gamedb.hrl
diff --git a/Mnesia/gamedb_usage.txt b/mnesia/gamedb_usage.txt
similarity index 100%
rename from Mnesia/gamedb_usage.txt
rename to mnesia/gamedb_usage.txt
diff --git a/python_client b/python_client
index e707115..3db0751 100755
--- a/python_client
+++ b/python_client
@@ -29,9 +29,9 @@ s.send(
"Token: %s\n\
Server-Command: define\n\
Content-Type: text\n\
-Content-Length: 42\n\
+Content-Length: 49\n\
\n\
-function myFun() {return 'Hello world!' ;}" % token)
+function myFun() {return 'Hello World!' ;}" % token)
fs = s.makefile()
data = fs.readline()
print "Token:", token
@@ -54,6 +54,8 @@ print "Data: ", ' '.join(data.split(" ")[1:])
s.close()
+time.sleep(2)
+
HOST = 'localhost' # The remote host
PORT = int(sys.argv[1]) # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
diff --git a/python_client_reconnect b/python_client_reconnect
new file mode 100755
index 0000000..2a41b70
--- /dev/null
+++ b/python_client_reconnect
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+import sys, time, socket
+
+HOST = 'localhost' # The remote host
+PORT = int(sys.argv[1]) # The same port as used by the server
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+s.connect((HOST, PORT))
+# Call that function!
+
+print "Calling myFun"
+s.send(
+"Token: %s\n\
+Server-Command: call\n\
+Content-Type: text\n\
+Content-Length: 6\n\
+\n\
+myFun" % raw_input("Token >> "))
+fs = s.makefile()
+data = fs.readline()
+print "Data: ", ' '.join(data.split(" ")[1:])
+
+s.close()
diff --git a/src/.ggs_connection.erl.swp b/src/.ggs_connection.erl.swp
new file mode 100644
index 0000000..0c009f8
Binary files /dev/null and b/src/.ggs_connection.erl.swp differ
diff --git a/src/ggs_network.erl b/src/ggs_network.erl
new file mode 100644
index 0000000..be1b9d1
--- /dev/null
+++ b/src/ggs_network.erl
@@ -0,0 +1,170 @@
+%%%----------------------------------------------------
+%%% @author Jonatan Pålsson
+%%% @copyright 2010 Jonatan Pålsson
+%%% @doc RPC over TCP server
+%%% @end
+%%%----------------------------------------------------
+%%% @author Mattias Pettersson
+%%% @doc Socket module for GGS
+%%% @end
+%%%----------------------------------------------------
+
+
+-module(ggs_network).
+
+-behaviour(gen_server).
+
+%define
+-define(SERVER, ?MODULE).
+-define(DEFAULT_PORT, 1055).
+
+
+% export
+-export([start_link/0,start_link/1]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
+%-export([get_count/1,crash/0,vms/0,hello/0,echo/0]).
+-export([get_count/1]).
+-export([send/3, send/4]).
+-export([stop/0]).
+
+%% gen_server callbacks
+-export([terminate/2, code_change/3]).
+
+%state
+-record(state, {port, lsock, client_vm_map = []}).
+
+
+%%-----------------------------------------------------
+%% @doc Starts gen_server
+%% @end
+%%-----------------------------------------------------
+start_link() ->
+ start_link(?DEFAULT_PORT).
+
+start_link(Port) ->
+ process_flag(trap_exit, true),
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).
+
+%%-----------------------------------------------------
+%% Creation
+%%-----------------------------------------------------
+init([Port]) ->
+ {ok, LSock} = gen_tcp:listen(Port, [{active, true},
+ {reuseaddr, true}]),
+ {ok, #state{port = Port, lsock = LSock}, 0}.
+
+%%-----------------------------------------------------
+%% @doc Fetches the number of requests made to this server
+%% @spec get_count() -> {ok, Count}
+%% where
+%% Count = integer()
+%% @end
+%%-----------------------------------------------------
+get_count(get_count) ->
+ gen_server:call(?SERVER, get_count).
+
+%crash() -> gen_server:call(?SERVER, crash).
+%vms() -> gen_server:call(?SERVER, vms).
+%hello() -> gen_server:call(?SERVER, hello).
+%echo() -> gen_server:call(?SERVER, {echo, RefID, _, MSG}).
+
+
+
+
+%%-----------------------------------------------------
+%% @doc Stops the server.
+%% @spec stop() -> ok
+%% @end
+%%-----------------------------------------------------
+stop() ->
+ gen_server:cast(?SERVER, stop).
+
+%%-----------------------------------------------------
+%% Handlers
+%%-----------------------------------------------------
+handle_call(get_count, _From, State) ->
+ {reply, {ok, State#state.client_vm_map}, State}.
+
+handle_cast(stop, State) ->
+ {stop, normal, State}.
+
+handle_info({tcp, Socket, RawData}, State) -> %parameters coming from gen_server
+ NewState = do_JSCall(Socket, RawData, State), %TODO
+ OldMap = State#state.client_vm_map,
+ io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]),
+ {noreply, State#state{client_vm_map = OldMap ++ [NewState]}};
+
+handle_info(timeout, #state{lsock = LSock} = State) ->
+ {ok, _Sock} = gen_tcp:accept(LSock),
+ {noreply, State}.
+
+
+%%-----------------------------------------------------
+%% TCP Calls
+%%-----------------------------------------------------
+send(Socket, RefID, String) ->
+ gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [RefID,String])).
+
+send(Socket, RefID, String1, String2) ->
+ gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [RefID, String1, String2])).
+
+
+%%-----------------------------------------------------
+%% gen_server callbacks
+%%-----------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%-----------------------------------------------------
+%% Internal functions
+%%-----------------------------------------------------
+do_JSCall(Socket, Data, State) ->
+ JSVM = js_runner:boot(),
+ js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"),
+ Parsed = ggs_protocol:parse(Data),
+ NewState = case Parsed of
+ {cmd, Command, Parameter} ->
+ % Set the new state to []
+ Ret = js_runner:call(JSVM, "userCommand",
+ [list_to_binary(Command),
+ list_to_binary(Parameter)]),
+ send(Socket, "RefID", "JS says: ", Ret),
+ [];
+ % Set the new state to the reference generated, and JSVM associated
+ {hello} ->
+ Client = getRef(),
+ send(Socket, Client, "__ok_hello"),
+ {Client, JSVM};
+ {echo, RefID, _, MSG} ->
+ send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)),
+ [];
+ {crash, Zero} ->
+ 10/Zero;
+ {vms} ->
+ send(Socket, "RefID", State);
+ % Set the new state to []
+ Other ->
+ send(Socket, "RefID", "__error"),
+ []
+ end,
+ % Return the new state
+ NewState.
+
+%%-----------------------------------------------------
+%% Helpers
+%%-----------------------------------------------------
+getRef() ->
+ {A1,A2,A3} = now(),
+ random:seed(A1, A2, A3),
+ random:uniform(1000).
+
+%%-----------------------------------------------------
+%% Helpers
+%%-----------------------------------------------------
+getJSVM(RefID, State) ->
+ VMs = State#state.client_vm_map,
+ {value, {_,VM}} = lists:keysearch(RefID, 1, VMs),
+ VM.
diff --git a/src/ggs_server.erl b/src/ggs_server.erl
index f8eae1e..ab9b8f8 100644
--- a/src/ggs_server.erl
+++ b/src/ggs_server.erl
@@ -90,8 +90,8 @@ handle_cast(stop, State) ->
% Handle javascript defines
handle_cast({srv_cmd, "define", Headers, Data}, State) ->
Token = ggs_protocol:getToken(Headers),
- JSVM = getJSVM(Token, State),
- js_runner:define(JSVM, Data),
+ GameVM = getJSVM(Token, State),
+ ggs_vm_runner:define(GameVM, Data),
send(State#state.lsock, "Token", "Okay, defined that for you!"),
{noreply, State};
@@ -99,21 +99,21 @@ handle_cast({srv_cmd, "define", Headers, Data}, State) ->
handle_cast({srv_cmd, "call", Headers, Data}, State) ->
Token = ggs_protocol:getToken(Headers),
io:format("Got call request: ~p~n", [Data]),
- JSVM = getJSVM(Token, State),
- erlang:display(erlang:port_info(JSVM)),
- {ok, Ret} = js_runner:call(JSVM, Data, []),%Payload, []),
+ GameVM = getJSVM(Token, State),
+ Ret = ggs_vm_runner:user_command(GameVM, "User", Data, []),
send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)),
{noreply, State};
-
+
% Set the new state to the reference generated, and JSVM associated
handle_cast({srv_cmd, "hello", Headers, Data}, State) ->
- JSVM = js_runner:boot(),
+ GameVM = ggs_vm_runner:start_link(),
Client = getRef(),
send(State#state.lsock, Client, "This is your refID"),
OldMap = State#state.client_vm_map,
- NewState = State#state{client_vm_map = OldMap ++ [{Client, JSVM}]},
- gen_server:cast(ggs_backup, {set_backup, NewState}),
+ NewState = State#state{client_vm_map = OldMap ++ [{Client, GameVM}]},
+ gen_server:cast(ggs_backup, {set_backup, NewState}),
{noreply, NewState}.
+
%%-----------------------------------------------------
%% Helpers
%%-----------------------------------------------------
diff --git a/src/ggs_vm_runner.erl b/src/ggs_vm_runner.erl
new file mode 100644
index 0000000..e149c51
--- /dev/null
+++ b/src/ggs_vm_runner.erl
@@ -0,0 +1,42 @@
+-module(ggs_vm_runner).
+-export([start_link/0, define/2, user_command/4]).
+
+%Mattias
+start_link() ->
+ erlang_js:start(),
+ PortPid = spawn_link( fun() ->
+ process_flag(trap_exit, true),
+ {ok, Port} = js_driver:new(),
+ js:define(Port, <<"function userCommand(user, command, args){return 'Hello world';}">>),
+ loop(Port)
+ end ),
+ PortPid.
+
+
+loop(Port) ->
+ receive
+ {define, SourceCode} ->
+ ok = js:define(Port, list_to_binary(SourceCode)),
+ loop(Port);
+ {user_command, User, Command, Args, From, Ref} ->
+ {ok, Ret} = js:call(Port, <<"userCommand">>,
+ [ list_to_binary(User),
+ list_to_binary(Command),
+ list_to_binary(Args)
+ ]),
+ From ! {Ref, Ret},
+ loop(Port)
+ end.
+
+
+define(GameVM, SourceCode) ->
+ GameVM ! {define,SourceCode}.
+
+user_command(GameVM, User, Command, Args) ->
+ Ref = make_ref(),
+ GameVM ! {user_command, User, Command, Args, self(), Ref},
+ receive
+ {Ref, RetVal} ->
+ RetVal;
+ Other -> Other
+ end.
diff --git a/src/js_runner.erl b/src/js_runner.erl
deleted file mode 100644
index ca866c4..0000000
--- a/src/js_runner.erl
+++ /dev/null
@@ -1,13 +0,0 @@
--module(js_runner).
--export([define/2,call/3, boot/0]).
-
-boot() ->
- erlang_js:start(),
- {ok, Port} = js_driver:new(),
- Port.
-
-define(Port, Data) ->
- ok = js:define(Port, list_to_binary(Data)).
-
-call(Port, Func, Params) ->
- js:call(Port, list_to_binary(Func), Params).