aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/api.org16
-rw-r--r--doc/api.pdfbin119891 -> 119335 bytes
-rw-r--r--server/api/api.lisp64
-rw-r--r--server/api/game-manager.lisp8
-rw-r--r--server/game/game.lisp7
-rw-r--r--server/packages.lisp7
6 files changed, 91 insertions, 11 deletions
diff --git a/doc/api.org b/doc/api.org
index cd7dec3..25eb9a0 100644
--- a/doc/api.org
+++ b/doc/api.org
@@ -22,8 +22,8 @@
"syn": 1,
"game-id": 1,
"game-over": false,
- "snake": [(1,2),(1,3)],
- "food": [(6,7)]
+ "snake": [[1,2],[1,3]],
+ "food": [[6,7]]
}
#+END_SRC
Note that, syn entry is used to keep packet ordering consistent and detecting packet inversion on the network. Thus,
@@ -46,8 +46,8 @@
"syn": 2,
"game-id": 1,
"game-over": false,
- "snake": [(0,2),(1,2)],
- "food": [(6,7)]
+ "snake": [[0,2],[1,2]],
+ "food": [[6,7]]
}
#+END_SRC
*** Refresh Screen
@@ -67,8 +67,8 @@
"syn": 3,
"game-id": 1,
"game-over": false,
- "snake": [(1,2),(0,2)],
- "food": [(6,7)]
+ "snake": [[1,2],[0,2]],
+ "food": [[6,7]]
}
#+END_SRC
*** End Game
@@ -79,8 +79,8 @@
"syn": null,
"game-id": 1,
"game-over": true,
- "snake": [(0,2),(1,2)],
- "food": [(6,7)]
+ "snake": [[0,2],[1,2]],
+ "food": [[6,7]]
}
#+END_SRC
- No reply is expected from the client and server will be in charge to free local memory. Note that syn=null.
diff --git a/doc/api.pdf b/doc/api.pdf
index a02a350..b2b5cc9 100644
--- a/doc/api.pdf
+++ b/doc/api.pdf
Binary files differ
diff --git a/server/api/api.lisp b/server/api/api.lisp
index 186076c..3bd7e49 100644
--- a/server/api/api.lisp
+++ b/server/api/api.lisp
@@ -4,6 +4,68 @@
(defclass api ()
((gm
- :initform (make-instance 'game-manager))))
+ :initform (make-instance 'game-manager))
+ (games-syn
+ :initform '())))
+
+
+(defmethod create-syn ((api api) game-id &optional (initial-value 0))
+ (unless (eq nil (get-syn api game-id)) (error "This game ~a already have a syn !" game-id))
+ (with-slots (games-syn) api
+ (push (list :game-id game-id :syn initial-value) games-syn)
+ initial-value))
+
+(defmethod refresh-syn ((api api) game-id)
+ (with-slots (games-syn) api
+ (incf (getf (first (remove-if-not #'(lambda (entry) (eql game-id (getf entry :game-id))) games-syn)) :syn))))
+
+(defmethod get-syn ((api api) game-id)
+ (with-slots (games-syn) api
+ (getf (first (remove-if-not #'(lambda (entry) (eql game-id (getf entry :game-id))) games-syn)) :syn)))
+
+
+
+;;; TODO: Handle errors (valid json etc..)
+(defun parse-request (request)
+ (flet ((normalizer (key)
+ (string-upcase key)))
+ (let ((p-request (parse request :normalize-all t :keyword-normalizer #'normalizer )))
+ p-request)))
+
+(defmethod handle-new-game ((api api) data)
+ (with-slots (gm) api
+ (let* ((game-id (create-game gm))
+ (game-syn (create-syn api game-id 1))) ; Create syn with 1 (since first packet already receive)
+ (let ((game-dump (dump gm game-id)))
+ (setf (getf game-dump :game-over) :null) ; Define nil as null (for json)
+ (to-json
+ (append (list :type "state" :syn game-syn) game-dump))))))
+
+;;; TODO: RETURN JSON !!!!
+(defmethod handle-update ((api api) data)
+ (with-slots (gm) api
+ (let* ((dir (getf data :direction))
+ (game-id (getf data :game-id))
+ (game (get-game gm game-id)))
+ (cond
+ ((equal dir "up") (setf dir :up))
+ ((equal dir "down") (setf dir :down))
+ ((equal dir "left") (setf dir :left))
+ ((equal dir "right") (setf dir :right))
+ (t (setf dir nil)))
+ (if dir
+ (refresh game :dir dir)
+ (refresh game)))))
+
+
+
+(defmethod handle-request ((api api) request)
+ (let* ((data (parse-request request))
+ (type (getf data :type)))
+ (cond
+ ((equal type "new-game") (handle-new-game api data))
+ ((equal type "update") (handle-update api data))
+ (t (format t "Unknow type")))))
+
diff --git a/server/api/game-manager.lisp b/server/api/game-manager.lisp
index e5355d1..751aae1 100644
--- a/server/api/game-manager.lisp
+++ b/server/api/game-manager.lisp
@@ -24,6 +24,14 @@
(with-slots (games) gm
(setf games (remove-if #'(lambda (entry) (eql game-id (getf entry :id))) games))))
+(defgeneric dump (g game-id)
+ (:documentation "Dump a game in the Game manager. Return a plist."))
+
+(defmethod dump ((g game-manager) game-id)
+ (with-slots (games) g
+ (append (list :id game-id) (remote-snake-server-game:dump (get-game g game-id)))))
+
+
(defmethod get-game ((gm game-manager) game-id)
(with-slots (games) gm
(let ((game (remove-if-not #'(lambda (entry) (eql game-id (getf entry :id))) games)))
diff --git a/server/game/game.lisp b/server/game/game.lisp
index f909f36..9ea2029 100644
--- a/server/game/game.lisp
+++ b/server/game/game.lisp
@@ -39,6 +39,13 @@
(format t "~%Direction: ~a" dir)
(format t "~%Food: ~a" food)))
+(defgeneric dump (g)
+ (:documentation "Dump a game. Return a plist."))
+
+(defmethod dump ((g game))
+ (with-slots (snake food game-over) g
+ (list :snake snake :food food :game-over game-over)))
+
;;; Note that there is no waranty that nb food are added (ex: if food position collide with snake position)
(defgeneric add-food (g nb)
(:documentation "Add food on the game grid."))
diff --git a/server/packages.lisp b/server/packages.lisp
index 788083d..3f3788d 100644
--- a/server/packages.lisp
+++ b/server/packages.lisp
@@ -2,10 +2,13 @@
(:nicknames :rsg)
(:use :common-lisp)
(:export
- #:game))
+ #:game
+ #:dump
+ #:refresh))
(defpackage :remote-snake-server-api
(:nicknames :rsapi)
- (:use :common-lisp :jonathan)
+ (:use :common-lisp :jonathan :remote-snake-server-game)
+ (:shadow #:dump) ; Because game-manager also has a dump method
(:export
#:api))