Newer
Older
atlantis / lisp / atlantis.lisp
;;;
;;; Atlantis is a framework for creating multi-user dungeon worlds.
;;; This is the Common Lisp implementation.
;;;
;;; Licensed under the terms of the MIT license.
;;; author: Daniel Vedder
;;; date: 09/05/2015
;;;

(defconstant ATLANTIS-VERSION '(0 1 3))

(load "util.lisp")
(load "game-objects.lisp")
(load "player.lisp")
(load "world.lisp")
(load "interpreter.lisp")
(load "ui.lisp")
(load "creator.lisp")

(defvar *debugging* NIL)

(defun development ()
	"A method to easily test whatever feature I am currently developing"
	(setf *debugging* T)
	(load-file "../ATL/lisp-test.atl")
	(let ((player (make-player :name "Bilbo"
					  :race "Hobbit" :class "Burglar"
					  :place (world-starting-place *world*)
					  :strength 6 :constitution 12
					  :dexterity 19 :intelligence 14
					  :game-admin T)))
		(add-game-object player)
		(set-object-attribute (get-game-object 'place (player-place player))
			'player (player-name player))
		(play-game (player-name player))))

(defun not-available ()
	"Before I tackle networking..."
	(format t "~&Sorry, multiplayer is currently not supported!")
	(format t "~&Please press ENTER")
	(y-or-n-p "~&OK?")
	(start-menu))

(defun start-server ()
	"Start a new game on a server"
	;; TODO Doesn't actually start a server yet
	(format t "~&What world file do you want to load?")
	(input-string world-file) 
	(format t "~&What port should the game run on?")
	(while (not (numberp (input port)))
		(format t "~&Not a number: ~A. Please reenter:" port))
	(debugging "~&Loading file ~S on port ~A" world-file port)
	(load-file world-file))

(defun join-game ()
	"Join a running game on the server"
	(format t "~&What is the IP address of the server you want to join?")
	(input-string server-ip)
	(while (not (= (count-instances #\. server-ip) 3))
		(format t "~&Not an IP address: ~A. Please reenter:" server-ip)
		(input-string server-ip))
	;(setf (cassoc ip *server-address*) server-ip)
	(format t "~&What port does the game run on?")
	(while (not (numberp (input server-port)))
		(format t "~&Not a number: ~A. Please reenter:" server-port))
	;(setf (cassoc port *server-address*) server-port)
	(format t "~&What is your player name?")
	(input-string name)
	(debugging "~&Joining game on ~A:~A as ~A" server-ip server-port name)
	(play-game name))


(defun single-player ()
	"Start a single-player game"
	(format t "~&What do you want to do?")
	(setf options '("Start a new game" "Load a game" "Back to menu"))
	(case (choose-number-option options)
		(0 (format t "~&What world file do you want to load?")
			(input-string world-file)
			(format t "~&What is your name?")
			(input-string name)
			(load-file world-file)
			(play-game name))
		(1 (format t "~&What game file do you want to load?")
			(input-string game)
			(format t "~&What is your name?")
			(input-string name)
			(load-game game)
			(play-game name))
		(2 (start-menu))))

(defun print-version ()
	(format t "~&Atlantis ~A.~A.~A"
		(first ATLANTIS-VERSION)
		(second ATLANTIS-VERSION)
		(third ATLANTIS-VERSION))
	(format t "~&Copyright (c) 2015 Daniel Vedder")
	(format t "~&Licensed under the terms of the MIT license.~%"))

(defun start-menu ()
	"Show the start menu and take a choice from the user"
	(clear-screen)
	(print-text-file "banner.txt")
	(format t "~&~%Welcome! What do you want to do?")
	(setf options '("Start a server" "Join a game" "Play single-player"
					   "Create worlds" "Develop" "About" "Exit"))
	(case (choose-number-option options)
		(0 (not-available))
		(1 (not-available))
		(2 (single-player))
		(3 (world-creator))
		(4 (development))
		(5 (print-version)
			(when (y-or-n-p "Show the license text?")
				(print-text-file "../LICENSE"))
			(start-menu))
		(6 (format t "~&Goodbye!")
			(quit))))
 
(defun cmd-parameter (name &optional truth-value)
	"Return the value of the parameter 'name'. Or T for present if truth-value."
	(let ((argument (member name *args* :test #'equalp)))
		(if argument
			(if truth-value T (second argument))
			NIL)))

(defun print-help ()
	(print-version)
	(setf help-text "
Commandline options:
-v --version          Show the version number and exit
-h --help             Show this help text and exit
--license             Show the license text
--debugging           Switch on debug mode
--single-player       Start a single-player game
--server <port>       Start a server on <port> (requires --world)
--world <world-file>  The ATL file to load (requires --server)
--client <ip>:<port>  Connect to the game server at <ip>:<port>")
	(format t "~A" help-text))

(defun parse-commandline-args ()
	;; TODO clean this up? (should give error message with unknown params)
	(cond ((or (cmd-parameter "--version" T) (cmd-parameter "-v" T))
			  (print-version) (quit))
		((or (cmd-parameter "--help" T) (cmd-parameter "-h" T))
			(print-help) (quit))
		((cmd-parameter "--license" T)
			(dolist (line (load-text-file "../LICENSE"))
				(unless (null line) (format t "~%~A" line)))
			(quit))
		((cmd-parameter "--debugging")
			(setf *debugging* T))
		((cmd-parameter "--single-player" T)
			(single-player)))
	(let ((server (cmd-parameter "--server"))
			 (world-file (cmd-parameter "--world"))
			 (client (cmd-parameter "--client")))
		(unless (or server world-file client)
			(format t "~&Invalid commandline parameter!") (quit))
		(if (and world-file server)
			(load-file world-file)
			(join-game))))


;; Initialize the random state (which would otherwise not be very random...)
(setf *random-state* (make-random-state t))

;; Only show the interactive menu if no commandline parameters are given
(if *args*
	(parse-commandline-args)
	(start-menu))