the-feebs-war-cvs
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
February 2008
- 1 participants
- 3 discussions
Author: gmilare
Date: Sun Feb 17 15:29:26 2008
New Revision: 16
Added:
utils.lisp
Removed:
definitions/utils.lisp
Modified:
graphics/graphics.lisp
images.lisp
package.lisp
the-feebs-war.asd
Log:
Modified: graphics/graphics.lisp
==============================================================================
--- graphics/graphics.lisp (original)
+++ graphics/graphics.lisp Sun Feb 17 15:29:26 2008
@@ -18,8 +18,11 @@
along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
|#
+
(in-package :the-feebs-war)
+
+
(defun print-direction (dir)
(case dir
(0 #\N)
Modified: images.lisp
==============================================================================
--- images.lisp (original)
+++ images.lisp Sun Feb 17 15:29:26 2008
@@ -40,10 +40,6 @@
left-square
right-square)
-(defun rcurry (func &rest args)
- #'(lambda (x)
- (apply func x args)))
-
;;; Computes what the feeb is seeing
Modified: package.lisp
==============================================================================
--- package.lisp (original)
+++ package.lisp Sun Feb 17 15:29:26 2008
@@ -122,6 +122,7 @@
(in-package :the-feebs-war)
+
;;; Directions
(deftype direction ()
Modified: the-feebs-war.asd
==============================================================================
--- the-feebs-war.asd (original)
+++ the-feebs-war.asd Sun Feb 17 15:29:26 2008
@@ -13,22 +13,24 @@
; :depends-on (lispbuilder-sdl lispbuilder-sdl-image lispbuilder-sdl-gfx)
:components
- (:cl-source-file "package")
- (:cl-source-file "system" :depends-on ("package"))
- (:cl-source-file "images" :depends-on ("system"))
- (:cl-source-file "main" :depends-on ("images" "system"))
+ ((:cl-source-file "package")
+ (:cl-source-file "utils" :depends-on ("package"))
+ (:cl-source-file "system" :depends-on ("utils"))
+ (:cl-source-file "images" :depends-on ("system"))
+ (:cl-source-file "main" :depends-on ("images"))
- (:module "definitions"
- :components
- (:cl-source-file "utils")
- (:cl-source-file "rules" :depends-on ("main"))
- (:cl-source-file "mazes" :depends-on ("package" "utils"))
- (:cl-source-file "extra" :depends-on ("package"))
- (:cl-source-file "brains" :depends-on ("package")))
+ (:module "definitions"
+ :depends-on ("main")
+ :components
+ ((:cl-source-file "rules")
+ (:cl-source-file "mazes")
+ (:cl-source-file "extra")
+ (:cl-source-file "brains")))
(:module "graphics"
+ :depends-on ("main")
:components
- (:file "graphics" :depends-on ("main")))
+ ((:file "graphics"))))
;; GPL
(:doc-file "licence")
Added: utils.lisp
==============================================================================
--- (empty file)
+++ utils.lisp Sun Feb 17 15:29:26 2008
@@ -0,0 +1,55 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
+
+ This file is part of The Feebs War.
+
+ The Feebs War is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ The Feebs War is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+|#
+
+
+(in-package :the-feebs-war)
+
+
+
+(defun bound-random (start min avg max)
+ (+ start
+ (* (expt -1 (random 2))
+ (let ((sort (random 2.0)))
+ (round
+ (if (< sort 1.0)
+ (+ min (* sort (- avg min)))
+ (+ avg (* (1- sort) (- max avg)))))))))
+
+(defun random-elt (seq)
+ (if seq
+ (elt seq (random (length seq)))))
+
+(defmacro ensure-bound (elt min max)
+ `(setf ,elt (bound ,elt ,min ,max)))
+
+(defun bound (elt min max)
+ (max min (min max elt)))
+
+(defmacro aif (test then &optional else)
+ `(let ((it ,test))
+ (if it ,then ,else)))
+
+(defmacro awhen (test &rest body)
+ `(let ((it ,test))
+ (when it ,@body)))
+
+(defun rcurry (func &rest args)
+ #'(lambda (x)
+ (apply func x args)))
1
0

16 Feb '08
Author: gmilare
Date: Sat Feb 16 15:01:42 2008
New Revision: 15
Added:
definitions/brains.lisp (contents, props changed)
definitions/extra.lisp (contents, props changed)
definitions/mazes.lisp (contents, props changed)
definitions/rules.lisp (contents, props changed)
definitions/utils.lisp
documentation/feebs.tex (contents, props changed)
graphics/graphics.lisp (contents, props changed)
Modified:
/ (props changed)
definitions/ (props changed)
Log:
Added: definitions/brains.lisp
==============================================================================
--- (empty file)
+++ definitions/brains.lisp Sat Feb 16 15:01:42 2008
@@ -0,0 +1,65 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
+
+ This file is part of The Feebs War.
+
+ The Feebs War is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ The Feebs War is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+|#
+
+
+(in-package :the-feebs-war)
+
+
+;;; Modified from "cautious-brain"
+
+(defun auto-brain (status proximity vision vision-left vision-right)
+ (declare (ignore vision-left vision-right))
+ (let ((stuff (my-square proximity)))
+ (cond ((and (member :mushroom stuff :test #'eq)
+ (< (energy-reserve status)
+ (- (get-feeb-parm 'maximum-energy) 20)))
+ :eat-mushroom)
+ ((member :carcass stuff :test #'eq)
+ :eat-carcass)
+ ((and (ready-to-fire status)
+ (> (energy-reserve status) 30)
+ (dotimes (index (min (line-of-sight status) 5))
+ (let ((feeb (find-if #'feeb-image-p (svref vision index))))
+ (if (and feeb
+ (not (eq (feeb-image-facing feeb)
+ (facing status))))
+ (return t)))))
+ :flame)
+ ((and (not (wallp (left-square proximity)))
+ (or (member :mushroom (left-square proximity))
+ (> 3 (random 10))))
+ :turn-left)
+ ((and (not (wallp (right-square proximity)))
+ (or (member :mushroom (right-square proximity))
+ (> 3 (random 10))))
+ :turn-right)
+ ((and (> (line-of-sight status) 0)
+ (not (dotimes (index (min (line-of-sight status) 7))
+ (if (find #'fireball-image-p (svref vision index))
+ (return t)))))
+ :move-forward)
+ (t
+ :turn-around))))
+
+(defun make-auto-feebs (n)
+ (dotimes (i n)
+ (define-feeb
+ (format nil "System Feeb # ~d" i)
+ #'auto-brain)))
Added: definitions/extra.lisp
==============================================================================
--- (empty file)
+++ definitions/extra.lisp Sat Feb 16 15:01:42 2008
@@ -0,0 +1,128 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
+
+ This file is part of The Feebs War.
+
+ The Feebs War is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ The Feebs War is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+|#
+
+
+;;; Usefull for creating a feeb
+;;; These are optimized so someone can use them without
+;;; complaining that they slow down your feeb !!!
+
+(in-package :the-feebs-war)
+
+(declaim (optimize (speed 3) (safety 0))
+
+ (inline left-of right-of behind
+ forward-dx forward-dy
+ left-dx left-dy
+ right-dx right-dy
+ behind-dx behind-dy
+
+ relative-facing
+
+ wallp chance)
+
+ ((function ((integer 0 3)) (integer 0 3))
+ left-of right-of behind
+ relative-facing)
+
+ ((function ((integer 0 3)) (integer -1 1))
+ forward-dx forward-dy
+ left-dx left-dy
+ right-dx right-dy
+ behind-dx behind-dy)
+
+ ((function (rational) boolean)
+ chance))
+
+;;; Directional arithmetic.
+
+(defun right-of (facing)
+ (mod (+ facing 3) 4))
+
+(defun left-of (facing)
+ (mod (+ facing 1) 4))
+
+(defun behind (facing)
+ (mod (+ facing 2) 4))
+
+(defun relative-facing (my-facing other-facing)
+ (mod (- my-facing other-facing) 4))
+
+(defun forward-dy (facing)
+ (if (oddp facing)
+ 0
+ (rem (1- facing) 4)))
+
+(defun forward-dx (facing)
+ (if (oddp facing)
+ (rem (- 2 facing) 4)
+ 0))
+
+(defun left-dy (facing)
+ (forward-dy (left-of facing)))
+
+(defun left-dx (facing)
+ (forward-dx (left-of facing)))
+
+(defun right-dy (facing)
+ (forward-dy (right-of facing)))
+
+(defun right-dx (facing)
+ (forward-dx (right-of facing)))
+
+(defun behind-dy (facing)
+ (forward-dy (behind facing)))
+
+(defun behind-dx (facing)
+ (forward-dx (behind facing)))
+
+;;; Tests
+
+(defun wallp (thing)
+ (the boolean
+ (eq :rock (car thing))))
+
+(defun chance (ratio)
+ (< (random (denominator ratio)) (numerator ratio)))
+
+#|
+;;; Handling the vision, vision-left and vision-right objects
+ (defmacro with-visible-elements ((count line-of-sight)
+ ((vis vision) &body vis-body)
+ ((vis-l vision-left) &body vis-l-body)
+ ((vis-r vision-right) &body vis-r-body)
+ &body finalize)
+ (let ((v (gensym))
+ (vl (gensym))
+ (vr (gensym)))
+ `(do* ((,count 1 (1+ ,count))
+ (,v (svref ,vision ,count))
+ (,vl (svref ,vision ,count))
+ (,vr (svref ,vision ,count)))
+ ((= ,count line-of-sight)
+ ,@finalize)
+ (declare (list ,v ,vl ,vr)
+ (fixnum ,count))
+ (dolist (,vis ,v)
+ ,@vis-body)
+ (dolist (,vis-l ,vl)
+ ,@vis-l-body)
+ (dolist (,vis-r ,vr)
+ ,@vis-r-body))))
+|#
\ No newline at end of file
Added: definitions/mazes.lisp
==============================================================================
--- (empty file)
+++ definitions/mazes.lisp Sat Feb 16 15:01:42 2008
@@ -0,0 +1,359 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
+
+ This file is part of The Feebs War.
+
+ The Feebs War is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ The Feebs War is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+|#
+
+;;; The mazes were
+;;; Created by Jim Healy, July 1987.
+;;;
+;;; **************************************************
+;;; Maze guidelines:
+;;; X represents a wall.
+;;; * represents a mushroom patch.
+;;; e is a feeb entry point.
+;;;
+;;; The maze should be a rectangle bounded by walls
+;;; in each side.
+;;; These mazes are all 32x32, but you may build
+;;; a maze of any size you wish.
+;;; **************************************************
+
+;;; Maze1 has a good number of dead ends and little nooks.
+
+(in-package :the-feebs-war)
+
+(defparameter *maze-1*
+ '("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXX *eXXXX *e ** X"
+ "XXX XXXXX XXXX XXXXXXXXXXXX XX X"
+ "XXX XXX XXXXXX X X"
+ "XXXXX XXXXXXX XXXXXXX XXXXXXX XX"
+ "X * XXX XX * XeXX XX"
+ "X XXXXXXX XXX XXXXXXX X XXX XXXX"
+ "X XXXXXX XXX XX X *XX"
+ "X XXXXXXX XXX XXXXXXX XXXXXXXXXX"
+ "X XXXXXXX XXX* e XXXXXX XXX"
+ "X XXXXX XXXXXXXXX * XXX"
+ "X XXXXX XXXXXX XXXXXX XX XX"
+ "X eXXXX XXXXXX XXX XXXXX XX XXX"
+ "X XXXXX* XXXXe XXXX XX XX"
+ "X XXXXX XXXXXX XXXXX XXX XXX XX"
+ "X eXXXX e XXXXXX *XX XX XX"
+ "X XXXXX XXXXXX XXXXXXX X XXeXXX"
+ "X XXX XXXXXXXX XX XX"
+ "X XXXXX XXXXXX XXXXXXXXXX XXXXXX"
+ "X XXXXX * XXXXX XX"
+ "X* XXX XXXXXX XXXXX XXXXXX X XX"
+ "X XXXXX e XXXXX X e X XX"
+ "X XX XX XXXXXX XXXXX X XXXXXX XX"
+ "X *XXX XXXXX * XX"
+ "X XX XX XXXXXX XXXXXXXXXX XXXXXX"
+ "X XXXXX XXXXXX * * XX"
+ "X XXX XXXXXXXXXXXXXXXXXXXXX XX"
+ "X XXXX X X eX X XX"
+ "X XXX XX X XX X XX X XX X XX XX"
+ "X XXXX XX X XX X XX X XX*X XX XX"
+ "X e * XX XX * XX XX XXeXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"))
+
+;;; Maze2 doesn't have any really long corridors.
+
+(defparameter *maze-2*
+ '("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "X eXXXXX * X XXXXXX X e XXXXX"
+ "X XXXX X X XXXX X X XXXXX"
+ "X XX XXXX XXXX X* X X XXXXX"
+ "XX XX XXX XXXX XX XX X X"
+ "XX e XXX XXXXXXX XX XXXXXXXX*X"
+ "XXXX XXX XXXXX X e XXX XX X"
+ "XXXX XXX XXXXXXXX XXXX X X"
+ "XX * XX XXe XXXXXXXXXX XX XXX"
+ "XX XXXX X XX X XXX XXXXX XXX"
+ "XX XX XXX X XX XXXXX"
+ "XXXXX XXX *XXX X XXXXXXXX"
+ "XX* XXXXXX XXXX XXXX XXXXXXXX"
+ "XXXXX XX XXXX XXXXXXXXX XXXXXXXX"
+ "XXXXX e XXXX *XXXXXX eXXXXX"
+ "XXXXXXXX XXXXXXX XXXXXXXXX XXXXX"
+ "XXXXXX XXXXX eXXXXX XXXXX"
+ "XXXXXX XXX XXXXXXX XXXXX XXXXXXX"
+ "XX XXX X XXX XX X XX"
+ "XX XXX XXXXX XX XX XXX XX XX"
+ "XX XXXXX *X XX X XX XXXXXX*XX"
+ "X XXXXX XXXX X XX XX"
+ "X XX XXXXXXX XXXXX*X X Xe XXXX"
+ "X XXXX e X XXXXX*XX XX XXXX"
+ "X XX XXXXXX XX XXX*XXX XXX"
+ "XXXX eXXX XXXX XX XXXXX X X"
+ "XXXXXX XXXXXXXXX XX XXXX XXX X"
+ "XXX * X X XX XXXX XXX X X"
+ "XX XXXX X XX XXXX XXX X e X"
+ "XX XX * X * X XXXX XX XXX*X"
+ "XX XXX XXX XX eXXX XXX*X"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"))
+
+;;; Maze3 has the minimum number of mushroom sites, most
+;;; of which are between a rock and a hard place. Those
+;;; poor feebs!
+
+(defparameter *maze-3*
+ '("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "X e XXXXXX XXXXXXX*XXXXXXXXX"
+ "X X XXX XXXXX e XXXX XXX e X"
+ "X XXX XXXXXX XX XX XXX XXX X"
+ "XXX XXX XXXXXX XX XX X X e X"
+ "Xe XXX*XXXX* XX XXeX X XXXXX X"
+ "X X XXX XXXXXX XX XX X XXXXX X"
+ "X XXX XXXXXX XX* XXXXXXXXX X"
+ "X XXXXX XX e XX XXXXXXXX XXX X"
+ "X X XXX XXX XXXXX XXXXXX XXX X"
+ "Xe XXX XXXX XXXX X X X"
+ "XXX XXXX XXXXXXXX X XXX XXX"
+ "XXX eXX XXXXXXXXX XXXXX XXXXX"
+ "XXXXX XXXXXXXXXXXX XXXXXX XXX"
+ "XXXXX * XX eXX XXX XX XXX"
+ "XX*XXXX XXXXXX XX XXX XXX XX XXX"
+ "XX X XXXXX X XXX eXX XXX"
+ "X XXXXXXXX XX XXXX XXX XX XXX"
+ "X XXXXeXXXXXX XXXX XXX XX XXX"
+ "X XX*XXXXX XXXXXXXXX XXX"
+ "XXXXXX XXX XXXX XXXXXX XXX"
+ "XXXXXXXXX XXX XXXXXX XXXXXX XXX"
+ "XXX XX e eX XXXX"
+ "XX XXXXX XXXX XXXX XXXX XXXX"
+ "XX XXXXX XX XXXX XXXX XXXX XX"
+ "XX eXXXX XX XXXX XXXX XXXXXX XX"
+ "XXX XX XXX * XXX XX"
+ "XX XX XXXX* XXXX XXXX XXXXXX XX"
+ "XXX X XXXXX XXXX XXXX X XX"
+ "XXXX e XXXX XXXX X XX X X"
+ "XXXXXXXXXXXX *e X e XX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"))
+
+
+;;; Maze4 is symmetric about the vertical axis. (Wow...)
+
+(defparameter *maze-4*
+ '("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "X* eXXXXXXXXXXe *X"
+ "X XXXXXXXX XXXXXXXX X"
+ "X XX XXXXXXX XX XXXXXXX XX X"
+ "X XeXXXXXXX XX XXXXXXXeX X"
+ "XX X XXXXXXX eXXe XXXXXXX X XX"
+ "XX X XXXXXXX XXXXXX XXXXXXX X XX"
+ "XX * XXXXXXX XXXXXX XXXXXXX * XX"
+ "XX X XXXe eXXX X XX"
+ "XX X XXX XXXXXXXXXXXXXX XXX X XX"
+ "XX e XXX XXXXXXXX XXX e XX"
+ "XX X XXXXXX XXXXXXXX XXXXXX X XX"
+ "XX X XXXX XXXXXXXX XXXX X XX"
+ "XX XXXX XXXe eXXXX XXXX XX"
+ "XXX XXXXX XXX XXX XXXX XXXXX XXX"
+ "XXX XXXXX XXX XXX XXXXX XXX"
+ "X* XXXXX XXXX XXXXX *X"
+ "X XXXXX XX XX ** XX XX XXXXX X"
+ "X XXXXX XX XX XXXX XX XX XXXXX X"
+ "X XXX e XX XX XXXX XX XX e XXX X"
+ "X XXXXX XX XXXX XX XXXXX X"
+ "X XXXXX XXXXX XXXX XXXXX XXXXX X"
+ "X X XXXXX XXXX XXXXX X X"
+ "XXXXX * * XXXXX"
+ "XXXXX XXXXXXXX XX XXXXXXXX XXXXX"
+ "XXXXX XXXXXXXX XX XXXXXXXX XXXXX"
+ "XXXXX XXXXX XX XXXXX XXXXX"
+ "XXXX XX XXXXeXXeXXXX XX XXXX"
+ "XXX XXXX XXX XX XXX XXXX XXX"
+ "XXX XXXXXX XXX XX XXX XXXXXX XXX"
+ "XX* e XX e *XX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"))
+
+;;; Maze5 has a lot of long corridors good for feeb showdowns.
+;;; Furthermore, all the feeb entry-points are in the corridors.
+;;; You can run but you can't hide!
+
+(defparameter *maze-5*
+ '("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "X e e X"
+ "X XXXXXXX*XXXXXXXXXXXX XXXXXXX X"
+ "X e X"
+ "X X XXXXX XXXXXXXXXXXX XXXXX X X"
+ "X * X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX XXXXXXXXXXXX XXeXX X X"
+ "X X XX XX * XX XX X X"
+ "XeX XX XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX e XX XXeX X"
+ "X X XXeXX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX XXXXXXXXXXXX XX XX XeX"
+ "X*X XX XX XX XX X X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X XeXX XX XXXXXXXXXXXX*XX XX X X"
+ "X X XX XX * XX XX*X X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX e XX XX*X X"
+ "X X XX*XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX XX XXeX X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X X XX XX XXXXXXXXXXXX XX XX X X"
+ "X e X"
+ "X*X XXXXX XXXXXXXXXXXX XXXXX X*X"
+ "X e * X"
+ "X XXXXXXX XXXXXXXXXXXX XXXXXXX X"
+ "X e * X"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"))
+
+;;; Use this function to create new mazes
+;;; of any size.
+
+(defun make-template (x-size y-size)
+ "Prints map template of the requested size.
+Use this to create new mazes."
+ (loop repeat y-size collect
+ (make-string x-size :initial-element #\X)))
+
+(defun density (maze xs ys)
+ (let ((sum 0))
+ (dotimes (x xs)
+ (dotimes (y ys)
+ (if (not (aref maze x y))
+ (incf sum))))
+ (float (/ sum (* xs ys)))))
+
+(defun horiz-corridor (map y x1 x2)
+ (do ((x x1 (if (< x1 x2) (1+ x) (1- x))))
+ ((= x x2))
+ ;; we need to guarantee that everything in map is
+ ;; corridors, that is, can't have something like
+ ;; XXXXXXXX
+ ;; XXX X
+ ;; X XXX
+ ;; XXXXXXXX
+ ;; that big blank square isn't good due
+ ;; to the limited vision of the feebs
+ (and (not (aref map x (1- y))) ; blank square up
+ (or (and (not (aref map (1+ x) y)) ; blank square to the right
+ (not (aref map (1+ x) (1- y)))) ; blank square up-right
+ (and (not (aref map (1- x) (1- y))) ; blank square up-left
+ (not (aref map (1- x) y)))) ; blank square to the left
+ (return)) ; can't make a blank square here, stop
+ (and (not (aref map x (1+ y))) ; blank square down
+ (or (and (not (aref map (1+ x) y)) ; blank square to the right
+ (not (aref map (1+ x) (1+ y)))) ; blank square down-right
+ (and (not (aref map (1- x) (1+ y))) ; blank square down-left
+ (not (aref map (1- x) y)))) ; blank square to the left
+ (return)) ; can't make a blank square here, stop
+ (setf (aref map x y) nil))
+ map)
+
+(defun vert-corridor (map x y1 y2)
+ (do ((y y1 (if (< y1 y2) (1+ y) (1- y))))
+ ((= y y2))
+ (and (not (aref map (1- x) y))
+ (or (and (not (aref map x (1+ y)))
+ (not (aref map (1- x) (1+ y))))
+ (and (not (aref map (1- x) (1- y)))
+ (not (aref map x (1- y)))))
+ (return))
+ (and (not (aref map (1+ x) y))
+ (if (or (and (not (aref map x (1+ y)))
+ (not (aref map (1+ x) (1+ y))))
+ (and (not (aref map (1+ x) (1- y)))
+ (not (aref map x (1- y)))))
+ (return)))
+ (setf (aref map x y) nil))
+ map)
+
+(defun translate (map xs ys)
+ (loop for y from (1- ys) downto 0 collect
+ (let ((str (make-string xs)))
+ (dotimes (x xs str)
+ (setf (aref str x)
+ (if (aref map x y)
+ #\X
+ #\Space))))))
+
+;;; This one generates an almost ready-to-use map
+
+(defun generate-maze (x-size y-size
+ &key (density 0.4)
+ (corridor-x-min 1)
+ (corridor-x-max (- x-size 2))
+ (corridor-x-avg (floor x-size 4))
+ (corridor-y-min 1)
+ (corridor-y-max (- y-size 2))
+ (corridor-y-avg (floor y-size 4)))
+ "Generates a maze of size X-SIZE x Y-SIZE (at least 10x10)
+with no entry points and no mushroom sites.
+DENSITY decides aproximatelly the ratio
+ (blank squares) / (total squares)
+recomended to be between 0.25 and 0.45.
+The horizontal corridors will be between CORRIDOR-X-MIN
+and CORRIDOR-X-MAX around CORRIDOR-X-AVG, when
+possible; similarly for vertical corridors.
+It returns two values, a layout like *maze-0* and its density."
+ (if (or (< x-size 10) (< y-size 10))
+ (error "Too small - should be at least 10x10."))
+ ;; Certifying the values to be acceptable
+ (ensure-bound corridor-x-avg
+ (ensure-bound corridor-x-min 1 (- x-size 2))
+ (ensure-bound corridor-x-max 3 (- x-size 2)))
+ (ensure-bound corridor-y-avg
+ (ensure-bound corridor-y-min 1 (- y-size 2))
+ (ensure-bound corridor-y-max 3 (- y-size 2)))
+ ;; Beginning with an array of walls
+ (let ((map (make-array (list x-size y-size)
+ :initial-element t
+ :element-type 'boolean)))
+ (do* ((i 1 (1+ i))
+ (y 1 y*) ; position of horizontal corridor
+ (y* (- y-size 2) (1+ (random (- y-size 2))))
+ (x1 (1+ (random (- x-size 2))) ; start position of horiz corridor
+ x1*)
+ (x1* (1+ (random (- x-size 2)))
+ (random-elt
+ (loop for x from 1 to (- x-size 2) ; any blank space
+ if (not (aref map x y)) collect x))) ; in line
+ (x2 (if x1 (bound-random x1 corridor-x-min
+ corridor-x-avg corridor-x-max))
+ (if x1 (bound-random x1 corridor-x-min
+ corridor-x-avg corridor-x-max)))
+ (x 1 x*) ; position of vertical corridor
+ (x* (- x-size 2) (1+ (random (- x-size 2))))
+ (y1 (1+ (random (- y-size 2)))
+ y1*)
+ (y1* (1+ (random (- y-size 2)))
+ (random-elt
+ (loop for y from 1 to (- y-size 2)
+ if (not (aref map x y)) collect y)))
+ (y2 (if y1 (bound-random y1 corridor-y-min
+ corridor-y-avg corridor-y-max))
+ (if y1 (bound-random y1 corridor-y-min
+ corridor-y-avg corridor-y-max)))
+ (real-dens (density map x-size y-size)))
+ ((or (>= real-dens density)
+ (> i (* density x-size y-size))) ; quits after trying TOO MUCH
+ (values (translate map x-size y-size) real-dens))
+ (if x1
+ (setf map (horiz-corridor map y x1
+ (bound x2 1 (- x-size 2)))))
+ (if y1
+ (setf map (vert-corridor map x y1
+ (bound y2 1 (- x-size 2))))))))
Added: definitions/rules.lisp
==============================================================================
--- (empty file)
+++ definitions/rules.lisp Sat Feb 16 15:01:42 2008
@@ -0,0 +1,247 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
+
+ This file is part of The Feebs War.
+
+ The Feebs War is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ The Feebs War is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+|#
+
+
+(in-package :the-feebs-war)
+
+
+
+;;; -*- General Rules -*-
+
+(def-feeb-parm 'game-length 320
+ "Number of turns the game will last.")
+
+(def-feeb-parm 'number-of-mushrooms 3
+ "Maximum number of mushrooms created each turn.")
+
+(let (turn-number total-time)
+
+ (defun start-round ()
+ (setf turn-number 0))
+
+ (defun start-turn ()
+ (incf turn-number)
+ (setf total-time 0)
+ (number-of-mushrooms
+ (random (1+ (get-feeb-parm 'number-of-mushrooms)))))
+
+ (defun finish-game-p ()
+ (= (get-feeb-parm 'game-length) turn-number))
+
+ (defun inc-total-time (time)
+ (incf time total-time))
+
+ (defun total-time ()
+ total-time))
+
+;;; Detecting if feeb is playing
+
+(def-feeb-parm 'sense-location-p t
+ "If nil, x-position and y-position will return nil when
+ someone tries to invoke it. Otherwise return the position.")
+
+(defmethod x-position :around ((fb feeb))
+ (if (get-feeb-parm 'sense-location-p)
+ (call-next-method)))
+
+(defmethod y-position :around ((fb feeb))
+ (if (get-feeb-parm 'sense-location-p)
+ (call-next-method)))
+
+
+
+;;; -*- Being Born and Dying -*-
+
+;;; Being Born / Reincarnating
+
+(def-feeb-parm 'starting-energy 50
+ "Amount of energy a feeb will start with.")
+
+(defmethod create-object :before ((feeb feeb) x y)
+ (setf (feeb-energy-reserve feeb)
+ (get-feeb-parm 'starting-energy)
+ (feeb-ready-to-fire feeb) t))
+
+;;; Dying and Killing
+
+(def-feeb-parm 'points-for-dying -3
+ "How many points some feeb earn for dying (usually negative).")
+
+(defmethod destroy-object :before ((feeb feeb) cause)
+ (incf (feeb-score feeb) (get-feeb-parm 'points-for-dying)))
+
+(def-feeb-parm 'points-for-killing 5
+ "How many points some feeb earn for killing someone.")
+
+(defmethod destroy-object :before ((feeb feeb) (fireball fireball))
+ (let ((owner (fireball-owner fireball)))
+ (unless (eq owner feeb)
+ (incf (feeb-score owner) (get-feeb-parm 'points-for-killing))
+ (incf (feeb-kill-counter owner)))))
+
+;;; Carcasses:
+
+(def-feeb-parm 'carcass-guaranteed-lifetime 5
+ "Number of turns that a carcass will surely not rot.
+After these turns, it can rot, depending on probabilities.")
+
+(def-feeb-parm 'carcass-rot-probability 1/3
+ "Probability of the carcass to rot, after the apropriate time.")
+
+(defun rot-carcass-p (time)
+ (and (> time (get-feeb-parm 'carcass-guaranteed-lifetime))
+ (chance (get-feeb-parm 'carcass-rot-probability))))
+
+
+
+;;; -*- Movement Choice -*-
+
+;;; Fireballs:
+
+(def-feeb-parm 'fireball-dissipation-probability 1/5
+ "Probability of the flame to dissipate each turn after the
+apropriate time.")
+
+(def-feeb-parm 'fireball-reflection-probability 2/3
+ "Probability of the flame to reflect when encountering a wall.")
+
+(defmethod make-move-choice ((fireball fireball))
+ (cond
+ ((wallp (get-forward-pos fireball))
+ (if (chance (get-feeb-parm 'fireball-reflection-probability))
+ :turn-around
+ :dissipate))
+ ((chance (get-feeb-parm 'fireball-dissipation-probability))
+ :dissipate)
+ (t :move-forward)))
+
+
+;;; Feebs
+
+(def-feeb-parm 'flame-no-recovery-time 2
+ "Probability
+of the feeb to recover the hability to throw a flame, after the apropriate
+time.")
+
+(def-feeb-parm 'flame-recovery-probability 1/3
+ "Probability of the feeb to recover the hability to throw a flame,
+after the apropriate time.")
+
+(defmethod make-move-choice :around ((feeb feeb))
+ (unless (feeb-ready-to-fire feeb)
+ (and (> (feeb-turns-since-flamed feeb)
+ (get-feeb-parm 'flame-no-recovery-time))
+ (chance (get-feeb-parm 'flame-recovery-probability))
+ (setf (feeb-ready-to-fire feeb) t)))
+ (let (choice)
+ (inc-total-time
+ (setf (feeb-time feeb)
+ (+ (- (get-internal-real-time))
+ (progn
+ (setf choice (call-next-method))
+ (get-internal-real-time)))))
+ choice))
+
+
+
+;;; -*- Moving -*-
+
+;;; Fireball
+
+(defmethod make-move :before ((fireball fireball) (move (eql :move-forward)))
+ (multiple-value-bind (stuff x-pos y-pos)
+ (get-forward-pos fireball)
+ (dolist (thing stuff)
+ (typecase thing
+ (feeb (destroy-object thing fireball))
+ ((eql :mushroom)
+ (delete-object thing x-pos y-pos))))))
+
+
+;;; Feebs
+
+(def-feeb-parm 'slow-feeb-noop-switch nil
+ "If is non-nil, there is a possibility that the move
+of a feeb is aborted according to its function evaluation
+time.")
+
+(def-feeb-parm 'slow-feeb-noop-factor 1/4
+ "The probability of the feeb to abort will be this factor
+times the amount of time the feeb takes to have a decision,
+divided by the total time taken by all the feebs in the
+current turn, or divided by a reference time.")
+
+(def-feeb-parm 'reference-time nil
+ "Time taken by reference if non-nil. See slow-feeb-noop-factor.")
+
+(def-feeb-parm 'points-for-slow-down -1
+ "Points earned when a feeb's move is aborted due to slowness.")
+
+(defmethod make-move :around ((feeb feeb) move)
+ (if (get-feeb-parm 'slow-feeb-noop-switch)
+ (if (chance (* (get-feeb-parm 'slow-feeb-noop-factor)
+ (/ (feeb-time feeb)
+ (or (get-feeb-parm 'reference-time)
+ (total-time)))))
+ (prog1 nil ; in case that the move was eating something
+ (incf (feeb-score feeb) (get-feeb-parm 'points-for-slow-down)))
+ (call-next-method))
+ (call-next-method)))
+
+(defmethod make-move :around ((feeb feeb) (move (eql :move-forward)))
+ (let ((thing (find-if #'fireball-p (get-forward-pos feeb))))
+ (if thing
+ (destroy-object feeb thing)
+ (call-next-method))))
+
+
+;;; Eating
+
+(def-feeb-parm 'maximum-energy 100
+ "The most energy a feeb can accumulate.")
+
+(def-feeb-parm 'mushroom-energy 50
+ "Amount of energy recovered when the feeb eats a mushroom.")
+
+(defmethod make-move :around ((feeb feeb) (move (eql :eat-mushroom)))
+ (when (call-next-method) ; was eating successfull?
+ (setf (feeb-energy-reserve feeb)
+ (min (+ (feeb-energy-reserve feeb)
+ (get-feeb-parm 'mushroom-energy))
+ (get-feeb-parm 'maximum-energy)))))
+
+(def-feeb-parm 'carcass-energy 30
+ "Amount of energy recovered each turn that the feeb
+eats a carcass.")
+
+(defmethod make-move :around ((feeb feeb) (move (eql :eat-carcass)))
+ (when (call-next-method)
+ (setf (feeb-energy-reserve feeb)
+ (min (+ (feeb-energy-reserve feeb)
+ (get-feeb-parm 'carcass-energy))
+ (get-feeb-parm 'maximum-energy)))))
+
+(def-feeb-parm 'flame-energy 10
+ "Amount of energy lost after throwing a flame.")
+
+(defmethod make-move :around ((feeb feeb) (move (eql :flame)))
+ (when (>= (feeb-energy-reserve feeb) (get-feeb-parm 'flame-energy))
+ (decf (feeb-energy-reserve feeb) (get-feeb-parm 'flame-energy))
+ (call-next-method)))
Added: definitions/utils.lisp
==============================================================================
--- (empty file)
+++ definitions/utils.lisp Sat Feb 16 15:01:42 2008
@@ -0,0 +1,49 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
+
+ This file is part of The Feebs War.
+
+ The Feebs War is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ The Feebs War is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+|#
+
+
+(in-package :the-feebs-war)
+
+(defun bound-random (start min avg max)
+ (+ start
+ (* (expt -1 (random 2))
+ (let ((sort (random 2.0)))
+ (round
+ (if (< sort 1.0)
+ (+ min (* sort (- avg min)))
+ (+ avg (* (1- sort) (- max avg)))))))))
+
+(defun random-elt (seq)
+ (if seq
+ (elt seq (random (length seq)))))
+
+(defmacro ensure-bound (elt min max)
+ `(setf ,elt (bound ,elt ,min ,max)))
+
+(defun bound (elt min max)
+ (max min (min max elt)))
+
+(defmacro aif (test then &optional else)
+ `(let ((it ,test))
+ (if it ,then ,else)))
+
+(defmacro awhen (test &rest body)
+ `(let ((it ,test))
+ (when it ,@body)))
Added: documentation/feebs.tex
==============================================================================
--- (empty file)
+++ documentation/feebs.tex Sat Feb 16 15:01:42 2008
@@ -0,0 +1,593 @@
+
+% Copyright (c) 2007,2008 Gustavo Henrique Milar�
+%
+% This file is part of The Feebs War.
+%
+% The Feebs War is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 3 of the License, or
+% (at your option) any later version.
+%
+% The Feebs War is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+
+\documentclass[english]{article}
+\usepackage[T1]{fontenc}
+\usepackage[latin1]{inputenc}
+\IfFileExists{url.sty}{\usepackage{url}}
+ {\newcommand{\url}{\texttt}}
+
+\makeatletter
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
+\newenvironment{lyxlist}[1]
+{\begin{list}{}
+{\settowidth{\labelwidth}{#1}
+ \setlength{\leftmargin}{\labelwidth}
+ \addtolength{\leftmargin}{\labelsep}
+ \renewcommand{\makelabel}[1]{##1\hfil}}}
+{\end{list}}
+
+
+\IfFileExists{url.sty}{\usepackage{url}
+}
+ {\newcommand{\url}{\texttt}}
+
+\makeatletter
+
+
+
+
+\makeatother
+
+\usepackage{babel}
+\makeatother
+
+\begin{document}
+
+\title{\textbf{\huge The Feebs War}}
+
+
+\author{Gustavo Henrique Milar�}
+
+\maketitle
+\begin{abstract}
+\textit{The Feebs War} is a modified version of Planet of the Feebs
+\url{http://www.cliki.net/}, a game made for people learn and improve
+their lisp and code manipulation tecniques. The graphics are now displayed
+using Lispbuilder \url{http://lispbuilder.sourceforge.net}'s libraries,
+so the problems with portability from CMUCL and X Window Sistem do
+not exist anymore. Also the code is cleaner and more extensible.
+\end{abstract}
+\tableofcontents{}
+
+
+\section{Introduction}
+
+The Feebs are intelligent and hostile creatures that live inside maze
+tunnels. They also have no mercy with each other, so they frequently
+throw a letal flame from through their mouth, getting rid of their
+opponent and eatting the carcass left. But throwing flames have an
+energy cost, so they must keep tracking for food.
+
+This game is intended to help lisp newbies (or maybe a little more
+advanced lispers) to learn lisp. A player must create a function that
+receives what his/her feeb is seeing and feeling, and returns what
+it will do next. To create the better feeb, one can create variables
+to store data from previous moves (or not), and can also use all the
+power of lisp to improve his/her creature. But the most important
+is to make good choices and be aware of danger!
+
+
+\subsection{Changes from \emph{Planet of the Feebs}}
+
+Many changes were made from the original game, but, if you have any
+feeb definition and you want to use it, it should be easy to adapt
+the brain function to the new rules.
+
+The main reason of this project is that \textit{Planet of the Feebs}
+is really interesting for (not just) newbies to learn lisp, but the
+difficulties to install, unportability and the ausence of competitors
+make it difficult to someone to be interested in making a feeb. So,
+I hope that making these adjustments and maybe creating some contests
+over the web make people be more interested in learning lisp.
+
+So, these are (some of) the changes:
+
+\begin{itemize}
+\item The graphics are not based on X Window Sistem anymore, but on \textit{Lispbuilder},
+and there are no CMUCL's event handler. This way, the code is more
+portable and graphics can be improved. Just creating some image
+files of a feeb and your feeb is much more personalized!
+\item Every element of the map (including walls) is a list, so the brain of
+a feeb doesn't need to test all the time if the element is an atom
+or a list (wich, in my opinion, is really boring, unlispy and unnecessary
+in this case). That was only a reason to duplicate code and work,
+adding no results at all...
+\item Many functions and variables are changed and others were added
+\item Documentation is more objective than the one provided with \textit{Planet
+of the Feebs}, and is fully compatible with the code. This way it
+is easier to understand the game.
+\item Security is improved. Now it the behavior functions are allowed to store
+and change structures and vectors passed to it.
+The parameters can't be change by those functions while inside the game.
+\item It is possible now to extend the rules: the code is object oriented and
+new rules, special moves, change the behavior of flames, etc, can be done
+by adding new classes and/or methods. This manual is just the beginning!
+end{itemize}
+
+\section{The Game}
+
+
+\subsection{Overview}
+
+Your feeb's objective is to survive and kill other feebs. It is inside
+a maze of tunnels. Every turn, all feebs lose one unit of energy,
+and maybe starves. Your feeb is able to move forward, turn left, right
+or around, flame, peek around a corner, eat something or just wait.
+After all feebs move, the flames thrown before also move (or dissipate),
+carcasses may rot and mushrooms may grow, accordingly to some rules.
+
+The game rules are defined by parameters. These parameters can be read
+by the command \textsf{\textbf{(get-feeb-parm~}'parameter\textbf{)}}
+To see all parameters, values and also all the documentation, one can use
+\textsf{\textbf{(list-parameter-settings)}}. Using
+\textsf{\textbf{(change-feeb-parm}'parameter~value\textbf{)}}
+gives the possibility to change them (but not during the game) and
+\textsf{\textbf{(documentation~}'parameter~'feeb-parm\textbf{)}}
+can be used to know them. Just remember that every probability
+must be a rational number (like 1/2).
+
+But don't panic! These parameters are just for one to know how
+the game is going to be, but in the begining there is no need
+to explicitly use them when creating the brain of a feeb.
+The best way to create a feeb is watching a game (among system feebs),
+improving it (it is defined in file brains.lisp) a little more,
+testing the changes...
+
+These are some global parameters:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{'game-length}}}] Number of turns the game
+will last.
+\item [{\textsf{\textbf{'points-for-killing}}}] How many points some
+feeb earn for killing someone.
+\item [{\textsf{\textbf{'points-for-dying}}}] How many points some
+feeb earn for dying (usually negative).
+\item [{\textsf{\textbf{'maze-x-size}}}] Horizontal size of the maze.
+\item [{\textsf{\textbf{'maze-y-size}}}] Vertical size of the maze.
+\end{lyxlist}
+
+\subsection{Throwing flame}
+
+If a feeb decides to throw a flame, if it is prepared to and has
+enough energy, the next turn there will be a flame in the square
+in front of the feeb, and it will see it, so the feeb shouldn't move
+forward. For a few turns, the feeb will not be able to
+throw flames. Each turn, the flame moves forward destroing mushrooms and
+killing feebs it encounters, transforming them into carcass. If there
+is a wall, the flame can reflect, and, if so, it will turn 180 degrees.
+
+Once a feeb is killed (or starves), in it's place in the maze there will appear
+a carcass. The feeb goes to the end of the dead feebs line. When the
+carcass rots, the first feeb in line reincarnates. So, dying is not so terrible.
+
+These are the parameters related to flames:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{'flame-energy}}}] Amount of energy lost after
+throwing a flame.
+\item [{\textsf{\textbf{'fireball-guaranteed-lifetime}}}] Number of
+turns that a fireball is guaranteed not to dissipate, unless it encounters
+a wall.
+\item [{\textsf{\textbf{'fireball-dissipation-probability}}}] Probability
+of the flame to dissipate each turn after the apropriate time.
+\item [{\textsf{\textbf{'fireball-reflection-probability}}}] Probability
+of the flame to reflect when encountering a wall.
+\item [{\textsf{\textbf{'flame-no-recovery-time}}}] Number of turns
+that a feeb cannot fire.
+\item [{\textsf{\textbf{'flame-recovery-probability}}}] Probability
+of the feeb to recover the hability to throw a flame, after the apropriate
+time.
+\end{lyxlist}
+
+\subsection{Eating food}
+
+There are two kinds of food, carcasses and mushrooms. Carcasses usually
+give less energy than mushrooms, and may rot, but, while it does not
+rot, a feeb can feed as long as it wishes. Mushrooms disapear after
+being eaten. By eating food, the feeb
+will be able to recover energy, wich is important because, if a feeb
+stays with 0 or less units of energy, it starves.
+
+These are the quantities:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{'mushroom-energy}}}] Amount of energy recovered
+when the feeb eats a mushroom.
+\item [{\textsf{\textbf{'carcass-energy}}}] Amount of energy recovered
+each turn that the feeb eats a carcass.
+\item [{\textsf{\textbf{'carcass-guaranteed-lifetime}}}] Number of
+turns that a carcass will surely not rot. After these turns, it
+can rot, depending on probabilities.
+\item [{\textsf{\textbf{'carcass-rot-probability}}}] Probability of
+the carcass to rot, after the apropriate time.
+\item [{\textsf{\textbf{'maximum-energy}}}] Maximum amount of energy
+that a feeb can have eating.
+\item [{\textsf{\textbf{'starting-energy}}}] Amount of energy a feeb
+has when it reincarnates.
+\item [{\textsf{\textbf{'number-of-mushrooms}}}] Quantity of mushrooms
+that exist in the maze.
+\end{lyxlist}
+
+\section{The Feeb}
+
+A feeb needs four things: a name, a brain and a set of graphics (optional).
+
+\begin{itemize}
+\item The name, a string.
+\item The brain is a function that decides what the feeb will do next, based
+on what it is seeing and feeling.
+\item The set of graphics is an image file (of format BMP, JPEG, PNG, and
+any others that supported by SDL\_image).
+\end{itemize}
+One can create a feeb calling
+\textsf{\textbf{(define-feeb}~name~brain~\textbf{:graphics}~graphics\textbf{)}}.
+If name is already used, a warning will be signaled, and the old feeb
+will be substituted. Calling \textsf{\textbf{(list-of-feebs)}} will
+return the list of the feebs (names only) that will be defined when
+the game begins. \textsf{\textbf{(delete-feeb}}\textsf{~name}\textsf{\textbf{)}}
+will delete the feeb with this name from this list, and \textsf{\textbf{(delete-all-feebs)}}
+will clear it.
+
+
+\subsection{Possible decisions}
+
+After processing the information available, the brain will take a
+decision. If this decision is not one of the decisions listed down,
+a warning will be signaled, and the result will be like \textsf{\textbf{:wait}}.
+Then, if someone are testing a brain function, he or she will be able
+to know if something goes wrong.
+
+The possible values that the brain function can return are these:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{:move-forward}}}] Move one square forward, unless
+there is a wall in front of the feeb.
+\item [{\textsf{\textbf{:turn-left}}}] Turn 90 degrees to the left.
+\item [{\textsf{\textbf{:turn-right}}}] Turn 90 degrees to the right.
+\item [{\textsf{\textbf{:turn-around}}}] Turn 180 degrees.
+\item [{\textsf{\textbf{:flame}}}] Throw a flame. The flame will be created
+next turn in the front square of the feeb.
+\item [{\textsf{\textbf{:wait}}}] Do nothing in this turn.
+\item [{\textsf{\textbf{:peek-left}}}] Peek to the left around a corner.
+The creature does note actually move, but, in the next turn, the creature
+will have the same vision that it would have if he had moved one step
+foward and turned left (and one step back because the feeb needs to see
+what is actually in front of it). Peeking used so a feeb can analize a corridor
+before trespassing it.
+\item [{\textsf{\textbf{:peek-right}}}] Peek to the right around a corner,
+analogous to \textsf{\textbf{:peek-left}}.
+\item [{\textsf{\textbf{:eat-carcass}}}] Eat a carcass if there is any
+available in the feeb's square. The amount of the parameter
+\textsf{\textbf{'carcass-energy}} is restored to the feeb's energy.
+\item [{\textsf{\textbf{:eat-mushroom}}}] Eat a mushroom if there is any
+available in the feeb's square. The amount of the parameter
+\textsf{\textbf{'mushroom-energy}} is restored to the feeb's energy.
+\end{lyxlist}
+
+\subsection{Information available}
+
+The brain of a feeb must take five arguments; I'll call them \textsf{\emph{status}},
+\textsf{\emph{proximity}}, \textsf{\emph{vision}}, \textsf{\emph{vision-left}}
+and \textsf{\emph{vision-right}}.
+
+
+\subsubsection{Status}
+
+Every time the brain is called, it receives some useful information
+through \textsf{\textbf{status}}.
+
+The structure \textsf{\textbf{status}} keeps information about the
+feeb itself. Also it has information of the previous movement of the
+feeb. To access them, one must call:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{(name}}\textsf{\emph{~status}}\textsf{\textbf{)}}}] \begin{flushleft}
+The name of the feeb.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(facing}}\textsf{\emph{~status}}\textsf{\textbf{)}}}] \begin{flushleft}
+Where the feeb is facing to, one of the constants provided: \textsf{\textbf{north}},
+\textsf{\textbf{east}}, \textsf{\textbf{south}} or \textsf{\textbf{west}},
+wich are 0, 1, 2 and 3 respectivelly.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(x-position}\emph{~status}\textbf{)}}}] \begin{flushleft}
+The horizontal position of the feeb, starting with 0 and increasing to east.
+If \textsf{\textbf{'sense-location-p}} is nil, it returns nil instead.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(y-position}\emph{~status}\textbf{)}}}] \begin{flushleft}
+The vertical position of the feeb, starting with 0 and increasing to south.
+If \textsf{\textbf{'sense-location-p}} is nil, it returns nil instead.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(peeking}\emph{~status}\textbf{)}}}] \begin{flushleft}
+If it is \textsf{\textbf{:peek-left}} or \textsf{\textbf{:peek-right}}, it means
+that the current \textsf{\emph{vision}} provided is result of a previous
+\textsf{\textbf{:peek-left}} or \textsf{\textbf{:peek-right}} command
+of the same feeb. Otherwise, it is \textsf{\textbf{nil}}. Note that
+\textsf{\emph{proximity}} is \emph{not} affected.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(line-of-sight}\emph{~status}\textbf{)}}}] \begin{flushleft}
+Indicates the amount of valid entries in \textsf{\emph{vision}}. It actually
+means that \textsf{\textbf{(aref}\emph{~vision~}\textbf{(line-of-sight}\emph{~status}\textbf{))}}
+will return \textsf{\textbf{'(:rock)}}.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(ready-to-fire}\emph{~status}\textbf{)}}}] \begin{flushleft}
+If \textsf{\textbf{T}} indicates that the feeb is ready to fire.
+If \textsf{\textbf{Nil}} indicates it is not.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(aborted}\emph{~status}\textbf{)}}}] \begin{flushleft}
+Related with timing. Returns \textsf{\textbf{T}} if the last move of feeb
+was aborted because of timing issues.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(last-move}\emph{~status}\textbf{)}}}] \begin{flushleft}
+The feeb's previous move, or \textsf{\textbf{:dead}} if it has just reincarnated.
+\par\end{flushleft}
+\end{lyxlist}
+
+\subsubsection{Proximity and vision}
+
+The brain receives also information about what is near the feeb and
+what the feeb sees. We note that, contrary to \emph{Planet of the Feebs},
+it is safe to change anything inside these structures, so you are
+alowed to keep them stored and to modify them as you wish.
+
+The structure \textsf{\emph{proximity}} has the contents of the squares
+near the feeb (not affected by peeking) with these fields:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{(my-square}}\textsf{\emph{~proximity}}\textsf{\textbf{)}}}] \begin{flushleft}
+Contents of the feeb's current square.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(left-square}}\textsf{\emph{~proximity}}\textsf{\textbf{)}}}] \begin{flushleft}
+Contents of the right square of the feeb.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(right-square}}\textsf{\emph{~proximity}}\textsf{\textbf{)}}}] \begin{flushleft}
+Contents of the left square of the feeb.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(rear-square}}\textsf{\emph{~proximity}}\textsf{\textbf{)}}}] \begin{flushleft}
+Contents of the square behind the feeb.
+\par\end{flushleft}
+\item [{The}] vector \textsf{\emph{vision}} has the contents of the squares
+that are in front of the feeb. For example,
+\textsf{\textbf{(aref}\emph{~vision~}0\textbf{)}}
+will return the contents of the square in front of the feeb,
+\textsf{\textbf{(aref}\emph{~vision~}1\textbf{)}}
+will return the contents of the next square, and so on. As said before,
+\textsf{\textbf{(aref}\emph{~vision~}\textbf{(line-of-sight}\emph{~status}\textbf{))}}
+will be the first \textsf{\textbf{'(:rock)}} encountered. All subsequents square, like
+\textsf{\textbf{(aref}\emph{~vision~}\textbf{(+}~1~\textbf{(line-of-sight}\emph{~status}\textbf{)))}},
+will be garbage and should not be used.
+\end{lyxlist}
+The contents of one square returned by any of these calls is either
+a list of elements, a wall \textsf{\textbf{'(:rock)}} (i.e. a list with
+one element, a \textsf{\textbf{:rock}}) or \textsf{\textbf{()}} if the
+square is empty. Each element of the square is one of these:
+
+\begin{itemize}
+\item \textbf{Feeb image.} One can call \textsf{\textbf{(feeb-image-p}~element\textbf{)}}
+to see if element is a feeb image.
+\item \textbf{Fireball image.} One can call \textsf{\textbf{(fireball-image-p}~element\textbf{)}}
+to check if element is a fireball image.
+\item \textsf{\textbf{:carcass}}. If there is a \textsf{\textbf{:carcass}}
+in the square of the feeb (i.e. in \textsf{\textbf{(my-square}}\textsf{\emph{~proximity}}\textsf{\textbf{)}}),
+the call \textsf{\textbf{:eat-carcass}} will make the feeb eat it.
+\item \textsf{\textbf{:mushroom}}. Analogous to \textsf{\textbf{:carcass}}.
+A mushroom appears randomly in places previously marked in the map.
+\end{itemize}
+
+\subsubsection{Feebs and fireballs images}
+
+Both fireballs and feebs that are given to the brain function are
+not the real ones, but just images with contents that the brain function
+can access. It is allowed to keep and change its contents because they
+won't be used internally.
+
+These are the accessors available (they read and change the fiels):
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{(feeb-image-name}~feeb-image\textbf{)}}}] \begin{flushleft}
+The name of the feeb. (Maybe you know it's weakpoints?)
+\par\end{flushleft}
+\item [{\textsf{\textbf{(feeb-image-facing}~feeb-image\textbf{)}}}] \begin{flushleft}
+The facing of the feeb. This way the brain function can
+see if the feeb-image either sees the feeb which is playing or not.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(feeb-image-peeking}~feeb-image\textbf{)}}}] \begin{flushleft}
+Returns \textsf{\textbf{:peek-left}} or \textsf{\textbf{:peek-right}} if the
+feeb is peeking to (its) left or right, or \textsf{\textbf{nil}} if
+not.
+\par\end{flushleft}
+\item [{\textsf{\textbf{(fireball-image-direction}~fireball-image\textbf{)}}}] \begin{flushleft}
+The direction where the fireball image is going to.
+\par\end{flushleft}
+\end{lyxlist}
+
+\subsubsection{Vision-left and vision-right}
+
+\textsf{\emph{vision-left}} and \textsf{\emph{vision-right}} are vectors
+similar to vision, but they are less precise in the contents. Also
+their valid contents are limited by \textsf{\textbf{(line-of-sight}~\emph{status}\textbf{)}},
+so \textsf{\textbf{(aref}~\emph{vision-left}~\textbf{(line-of-sight}~\emph{status}\textbf{))}},
+for example, will return \textsf{\textbf{:unknown}}.
+
+Note that feebs that are not peeking, mushrooms and carcasses are
+\emph{not} be detected by these vectors. Also, if there is a feeb
+peeking to the opposite side, it won't be detected either. The
+elements in \textsf{\textbf{vision-left}} and \textsf{\textbf{vision-right}}
+are lists containing these elements:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{:peek-letf}}}] This means that in that square there
+is a feeb peeking to (its) left.
+\item [{\textsf{\textbf{:peek-right}}}] This means that in that square
+there is a feeb peeking to (its) right.
+\item [{\textsf{\textbf{:rock}}}] This square is just a wall. In this case,
+this is the only element in the square.
+\end{lyxlist}
+
+\subsection{Extra functions provided}
+
+Before making the brain of your feeb, you might want to take a look
+at the Extra functions that are available at the end of the feebs.lisp
+file. The only thing you need so you can use them is to see their
+code and know what they do.
+
+
+\subsection{Changing the map layout}
+
+It is possible to change the layout of the map by calling
+\textsf{\textbf{(change-layout}~new-layout\textbf{)}}.
+There are a few predefined mazes that are in variables \textsf{\textbf{{*}maze-0{*}}}
+(which is set by default) throw \textsf{\textbf{{*}maze-5{*}}}.
+In a layout, `X' represents a wall, `e' represents a feeb entry point
+(there will be as many entry points as feebs in the maze at the same time),
+`m' represents a mushroom site and ` ' is a blank space.
+
+If you want to create a new map, you can start by an empty template
+of any size that is provided by \textsf{\textbf{(make-template}~x-size~y-size\textbf{)}},
+or you can get a reandom map calling
+\textsf{\textbf{(generate-maze}~x-size~y-size~\textbf{:density}~density\textbf{)}}
+The density is a number, recomended to be between 0.25 and 0.45,
+which tells the portion of the maze should be blank spaces.
+The function quits after a while if it doesn't meet this portion. See
+its documentation for more details and options.
+
+
+\subsection{Graphics}
+
+With this version of the game, it's possible to choose the graphics
+of a feeb when creating it, so your feeb will be more personalized.
+
+The graphic of a feeb is defined by an image file, which should have
+three colunms by eight lines of pictures of the same size. The four
+first lines must be the animations of the feeb walking up, left, down
+and right, respectively. The next four lines must be the pictures
+of the feeb flaming up, left, down and right, respectively. To see
+an example, see {}``default-feeb.png''.
+
+After creating the image file, you must call \textsf{\textbf{(create-graphics}}\textsf{~path-to-image-file}\textsf{\textbf{)}}.
+If you now how to work with sdl surfaces in lispbuilder, you may use
+the function with a surface instead of a image file; or you can call
+\textsf{\textbf{(create-graphics}~path-to-image-file~nil\textbf{)}}
+if the surface should not be freed after the call. The result must
+be the third argument given to define-feeb.
+
+
+\subsection{Starting the game}
+
+The game loop is started by calling \textsf{\textbf{(simple-play)}}.
+
+
+
+\section{Contests}
+
+I sugest that you see this chapter only after you have created at
+least a basic brain feeb, which is better than the (simple) provided
+brain, or if you want to participate of a contest or a game with
+your friends.
+
+
+\subsection{\label{sub:Map}Map}
+
+It is possible to get the maze map during the game, but with only
+the corridors. Note that the function that gets the map is purposely
+a little slow, so, invoking it too many times in a contest that uses
+timing atributes is not a good idea; anyway, it is possible to invoke
+this function before defining the feeb, and store its value somewhere.
+Also note that the map returned does not have any information about
+what is really in the maze, but only the possible ways.
+
+To get the map, one can call \textsf{\textbf{(get-maze-map)}}. This
+function will return \textsf{\textbf{nil}} if parameter
+\textsf{\textbf{'may-get-maze-map-p}} is also \textsf{\textbf{nil}}.
+Otherwise, the map returned is an array, so that calling
+\textsf{\textbf{(aref}~map~x~y\textbf{)}} will get the contents
+in the position (x,y) (like euclidean but inverting the y axis).
+The contents of a cell could be one of these:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{:mushroom-place}}}] A mushroom patch, i.e. when
+a mushroom is reincarnate, it could reincarnate here.
+\item [{\textsf{\textbf{:feeb-entry-place}}}] A feeb entry, i.e. if a carcass
+rots a feeb can appear here.
+\item [{\textsf{\textbf{:rock}}}] A wall. Feebs cannot come to this place.
+\item [{\textsf{\textbf{nil}}}] An {}``empty'' place, i.e. neither of
+the previous.
+\end{lyxlist}
+
+This map can safelly be used since \textsf{\textbf{(get-maze-map)}} makes
+a new copy every time it is called.
+
+\subsection{Timing}
+
+There are also some timing atributes that can be given to the game.
+The more time the feeb takes make a decision, greater is the probability
+of its command to be aborted.
+
+To make this available, someone must set these parameters:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{'slow-feeb-noop-switch}}}] If is non-nil,
+there is a possibility that the move of a feeb is aborted according
+to its function time.
+\item [{\textsf{\textbf{'slow-feeb-noop-factor}}}] The probability
+of the feeb to abort will be this factor times the amount of time
+the feeb takes to have a decision, divided by the total time taken
+by all the feebs in the current turn or divided by a reference time.
+\item [{\textsf{\textbf{'reference-time}}}] Time taken by reference
+if non-nil.
+\item [{\textsf{\textbf{'points-for-slow-down}}}] Points earned when
+a feeb's move is aborted due to slowness.
+\end{lyxlist}
+
+\subsection{Sense of location}
+
+Some accessors related to position and orientation of the feeb can
+be turned off.
+
+These are the parameters:
+
+\begin{lyxlist}{00.00.0000}
+\item [{\textsf{\textbf{'sense-location-p}}}] If nil,
+\textsf{\textbf{x-position}} and \textsf{\textbf{y-position}}
+will return nil when someone tries to invoke it.
+Otherwise return the position.
+\end{lyxlist}
+
+\subsection{Changing the rules}
+
+To change the rules of the contest, they must be changed before the
+feebs are defined, because in a feeb definition it could use the values
+of the variables to make a global strategy.
+
+All the parameters, values and documentation that can be listed using
+\textsf{\textbf{(list-parameter-settings)}} can be changed using
+\textsf{\textbf{(change-feeb-parm name value)}}, which is deactivated
+during the game. Also, they all have documentation about themselves, so feel free to use
+\textsf{\textbf{(documentation~}}\textsf{'parameter~'feeb-parm}\textsf{\textbf{)}}
+and see what each parameter does. Documentation is available to external
+functions as well.
+
+
+\section{Reference}
+
+\begin{quote}
+Fahlman, S. E. \textbf{\emph{Planet of the Feebs -}} \emph{A Somewhat
+Educational Game.} \url{ftp://ftp.csl.sri.com/pub/users/gilham/feebs/feebs.tex}.
+\end{quote}
+
+\end{document}
Added: graphics/graphics.lisp
==============================================================================
--- (empty file)
+++ graphics/graphics.lisp Sat Feb 16 15:01:42 2008
@@ -0,0 +1,216 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
+
+ This file is part of The Feebs War.
+
+ The Feebs War is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ The Feebs War is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The Feebs War. If not, see <http://www.gnu.org/licenses/>.
+|#
+
+(in-package :the-feebs-war)
+
+(defun print-direction (dir)
+ (case dir
+ (0 #\N)
+ (1 #\E)
+ (2 #\S)
+ (3 #\W)))
+
+(defun print-map ()
+ (dotimes (y *maze-y-size*)
+ (dotimes (x *maze-x-size*)
+ (let ((elt (aref *maze* x y)))
+ (apply 'format t
+ (cond
+ ((wallp elt)
+ (list " XX"))
+ ((feeb-p (car elt))
+ (list "F~1d~a"
+ (position (feeb-name (car elt)) *feebs* :key #'feeb-name)
+ (print-direction (feeb-facing (car elt)))))
+ ((fireball-p (car elt))
+ (list " *~a" (print-direction (fireball-direction (car elt)))))
+ ((eq (car elt) :mushroom)
+ (list " mm"))
+ ((eq (car elt) :carcass)
+ (list " cc"))
+ (t (list " "))))))
+ (format t "~%")))
+
+(defun simple-play (&optional layout)
+ (if layout
+ (change-layout layout))
+ (make-auto-feebs (- 10 (length *feebs-to-be*)))
+ (initialize-feebs)
+ (start-round)
+ (loop do
+ (play-one-turn)
+ (print-map)
+ (sleep 0.7)
+ (format t "~%~%")
+ (if (finish-game-p) (return)))
+ (format t "Game Over!!~%~%Scores:~%~%")
+ (dolist (feeb *feebs*)
+ (format t "~a: ~d~%" (feeb-name feeb) (feeb-score feeb))))
+
+
+#|
+
+
+(defconst *default-graphics*
+ (make-feeb-graphics
+ (load-and-convert-image "default-feeb.bmp")))
+
+(defvar *cell-width* 32)
+(defvar *cell-heigth* 32)
+
+(defstruct graphic
+ (walk (make-direction))
+ (flaming (make-direction)))
+
+(defstruct (direction (:conc-name nil))
+ (up (make-array 3))
+ (left (make-array 3))
+ (down (make-array 3))
+ (right (make-array 3)))
+
+(defun make-feeb-graphics (surface)
+
+ (let ((graphic (make-graphic)))
+ (progn
+ (loop for field in '(walk flaming)
+ and y0 from 0 by (* 4 *cell-heigth*) do
+ (loop for dir in '(up left right down)
+ and y from y0 by *cell-heigth* do
+ (loop for ind below 3
+ and x from 0 by *cell-width*
+ for aux = (surface :width *cell-width* :heigth *cell-heigth*) do
+ (set-cell :x x :y y :width *cell-width* :heigth *cell-heigth* :surface surface)
+ (draw-surface surface :surface aux)
+ (setf (svref (slot-value (slot-value graphic field)
+ dir)
+ ind)
+ aux))))
+ graphic)))
+
+(defgeneric create-graphics (feeb) &key (free-p t))
+
+(defmethod create-graphics ((feeb pathname))
+ (let ((surf (load-and-convert-image feeb)))
+ (make-feeb-grahpics surf)
+ (free-surface surf)))
+
+(defmethod create-graphics ((feeb surface) &key free-p)
+ (with-surface feeb
+ (make-feeb-graphics))
+ (if free-p
+ (fre-surface feeb)))
+
+
+(defvar *time* 0)
+
+(defun human-player (&rest args)
+ (declare (ignore args))
+ (sdl:with-events (:wait)
+ (:key-down-event (:key key)
+ (case key
+ (:sdl-key-up
+ (return-from human-player :move-forward))
+ (:sdl-key-left
+ (return-from human-player :turn-left))
+ (:sdl-key-right
+ (return-from human-player :turn-right))
+ (:sdl-key-up
+ (return-from human-player :turn-around))
+ (:sdl-key-space
+ (return-from human-player :flame))
+ (:sdl-key-return
+ (return-from human-player :wait))))
+ (:video-expose-event
+ (sdl:update-display))))
+
+
+(defun feebs (&key (delay 5) ; 4 min of game
+ human-player
+ files &aux (time 0))
+ "The main loop program. Single-step is no longer available.
+If human-player is supplied, it is taken as the name of human player,
+wich will controll a feeb with the keyboard. The end of the game
+only occurs if the player press ESC.
+If there is no human, *game-length* is used instead.
+A number of auto-feebs feebs are created by the system.
+Also, if there are more feebs supplied than places,
+the feeb wich is killed gives room to another feeb to be born."
+ (initialize-feebs)
+ (setf (sdl:frame-rate) 10)
+
+ (init-maze *layout*)
+
+ (dolist (file files)
+ (load file))
+ (if human-player
+ (define-feeb
+ human-player
+ #'human-player))
+
+ (sdl:with-init ()
+ (sdl:with-display ()
+ (sdl:with-events ()
+ (:idle ()
+ (sdl:update-display)
+ (if zerop time
+ (progn
+ (setf time delay)
+ (play-one-turn)
+ (when (not *continue*)
+ (return)))
+ (decf time)))
+ ))
+
+ (setf *feebs-to-be* nil))
+
+;;; Feeb creation.
+
+;; This a little better version of conservative-brain
+;; all others (stupid or redundant) brains of original
+;; feebs.lisp were eliminated
+(defun simple-brain (status proximity vision vision-left vision-right)
+ (declare (ignore vision-left vision-right))
+ (let ((stuff (my-square proximity)))
+ (cond ((and (consp stuff) (member :mushroom stuff :test #'eq))
+ :eat-mushroom)
+ ((and (consp stuff) (member :carcass stuff :test #'eq))
+ :eat-carcass)
+ ((and (ready-to-fire status)
+ (> (energy-reserve status) 30)
+ (dotimes (index (min (line-of-sight status) 5))
+ (if (find-if #'feeb-image-p (aref vision index))
+ (return t))))
+ :flame)
+ ((and (not (eq (left-square proximity) :rock))
+ (> 2 (random 10)))
+ :turn-left)
+ ((and (not (eq (right-square proximity) :rock))
+ (> 2 (random 10)))
+ :turn-right)
+ ((plusp (line-of-sight status))
+ :move-forward)
+ ((not (wallp (left-square proximity)))
+ :turn-left)
+ ((not (wallp (right-square proximity)))
+ :turn-right)
+ ((not (wallp (rear-square proximity)))
+ :turn-around))))
+
+|#
1
0

16 Feb '08
Author: gmilare
Date: Sat Feb 16 14:59:50 2008
New Revision: 14
Added:
definitions/
documentation/
graphics/
the-feebs-war.asd (contents, props changed)
Removed:
brains.lisp
extra.lisp
feebs.asd
feebs.tex
graphics.lisp
mazes.lisp
rules.lisp
Modified:
images.lisp
main.lisp
package.lisp
system.lisp
Log:
Modified: images.lisp
==============================================================================
--- images.lisp (original)
+++ images.lisp Sat Feb 16 14:59:50 2008
@@ -1,6 +1,6 @@
;;; -*- Common Lisp -*-
-#| Copyright (c) 2007 Gustavo Henrique Milar�
+#| Copyright (c) 2007,2008 Gustavo Henrique Milar�
This file is part of The Feebs War.
@@ -19,7 +19,7 @@
|#
-(in-package :feebs)
+(in-package :the-feebs-war)
;;; This file is an extension of system.lisp which handles vision
Modified: main.lisp
==============================================================================
--- main.lisp (original)
+++ main.lisp Sat Feb 16 14:59:50 2008
@@ -1,6 +1,6 @@
;;; -*- Common Lisp -*-
-#| Copyright (c) 2007 Gustavo Henrique Milar�
+#| Copyright (c) 2007,2008 Gustavo Henrique Milaré
This file is part of The Feebs War.
@@ -19,7 +19,7 @@
|#
-(in-package :feebs)
+(in-package :the-feebs-war)
Modified: package.lisp
==============================================================================
--- package.lisp (original)
+++ package.lisp Sat Feb 16 14:59:50 2008
@@ -1,6 +1,6 @@
;;; -*- Common Lisp -*-
-#| Copyright (c) 2007 Gustavo Henrique Milar��
+#| Copyright (c) 2007,2008 Gustavo Henrique Milaré
This file is part of The Feebs War.
@@ -30,95 +30,96 @@
;; Graphics ported to X11 by Fred Gilham 8-FEB-1998.
-(defpackage :feebs
+(defpackage :the-feebs-war
+ (:nicknames :feebs)
(:use :common-lisp)
;; Export everything we want the players to get their hands on.
(:export ;; Slots accessors
- name facing
- x-position y-position peeking line-of-sight
- energy-reserve
- score kills
- ready-to-fire
- aborted last-move
-
- my-square left-square right-square rear-square
-
- ;; Images
- feeb-image-p feeb-image-name
- feeb-image-facing feeb-image-peeking
- fireball-image-p fireball-image-direction
-
- ;; Parameters
- get-feeb-parm change-feeb-parm
- list-parameter-settings
-
- game-length
-
- ;; Pontuation
- points-for-killing points-for-dying
- points-for-slow-down
-
- ;; Energy
- flame-energy mushroom-energy carcass-energy
- maximum-energy
- starting-energy
- carcass-rot-probability
- carcass-guaranteed-lifetime
-
- ;; Game quantities
- maze-x-size
- maze-y-size
- number-of-mushrooms
-
- ;; Probabilities
- fireball-guaranteed-lifetime
- fireball-dissipation-probability
- fireball-reflection-probability
- flame-no-recovery-time
- flame-recovery-probability
-
- ;; Difficulty variables
- slow-feeb-noop-switch
- slow-feeb-noop-factor
- reference-time
- sense-location-p
- may-get-maze-map-p
-
- ;; Settings
- define-feeb delete-feeb
- feebs
- change-layout
- get-maze-map
-
- ;; Constants
- north south east west
-
- ;; Some layouts (can be find in mazes.lisp)
- *maze-0* *maze-1* *maze-2*
- *maze-3* *maze-4* *maze-5*
- make-template generate-maze
-
- ;; Graphics
- create-graphics
-
- ;; Extras
-
- ;; Directional arithmetic
- left-of right-of behind-of
- relative-facing
-
- forward-dx forward-dy
- left-dx left-dy
- right-dx right-dy
- behind-dx behind-dy
+ name facing
+ x-position y-position peeking line-of-sight
+ energy-reserve
+ score kills
+ ready-to-fire
+ aborted last-move
+
+ my-square left-square right-square rear-square
+
+ ;; Images
+ feeb-image-p feeb-image-name
+ feeb-image-facing feeb-image-peeking
+ fireball-image-p fireball-image-direction
+
+ ;; Parameters
+ get-feeb-parm change-feeb-parm
+ list-parameter-settings
+
+ game-length
+
+ ;; Pontuation
+ points-for-killing points-for-dying
+ points-for-slow-down
+
+ ;; Energy
+ flame-energy mushroom-energy carcass-energy
+ maximum-energy
+ starting-energy
+ carcass-rot-probability
+ carcass-guaranteed-lifetime
+
+ ;; Game quantities
+ maze-x-size
+ maze-y-size
+ number-of-mushrooms
+
+ ;; Probabilities
+ fireball-guaranteed-lifetime
+ fireball-dissipation-probability
+ fireball-reflection-probability
+ flame-no-recovery-time
+ flame-recovery-probability
+
+ ;; Difficulty variables
+ slow-feeb-noop-switch
+ slow-feeb-noop-factor
+ reference-time
+ sense-location-p
+ may-get-maze-map-p
+
+ ;; Settings
+ define-feeb delete-feeb
+ feebs
+ change-layout
+ get-maze-map
+
+ ;; Constants
+ north south east west
+
+ ;; Mazes
+ *maze-0* *maze-1* *maze-2*
+ *maze-3* *maze-4* *maze-5*
+ make-template generate-maze
+
+ ;; Graphics
+ create-graphics
+
+ ;; Extras
+
+ ;; Directional arithmetic
+ left-of right-of behind-of
+ relative-facing
+
+ forward-dx forward-dy
+ left-dx left-dy
+ right-dx right-dy
+ behind-dx behind-dy
+
+ ;; Others
+ wallp chance
+
+ ;; Graphics for alpha release
+ simple-play))
- ;; Others
- wallp chance
-
- ;; Graphics for alpha release
- simple-play))
-
-(in-package :feebs)
+(in-package :the-feebs-war)
;;; Directions
@@ -207,13 +208,6 @@
;;; Current feeb playing
+
(defvar *playing-feeb* nil)
(defvar *feebs-to-be* ())
-
-(defmacro aif (test then &optional else)
- `(let ((it ,test))
- (if it ,then ,else)))
-
-(defmacro awhen (test &rest body)
- `(let ((it ,test))
- (when it ,@body)))
Modified: system.lisp
==============================================================================
--- system.lisp (original)
+++ system.lisp Sat Feb 16 14:59:50 2008
@@ -1,6 +1,6 @@
;;; -*- Common Lisp -*-
-#| Copyright (c) 2007 Gustavo Henrique Milar�
+#| Copyright (c) 2007,2008 Gustavo Henrique Milaré
This file is part of The Feebs War.
@@ -19,7 +19,7 @@
|#
-(in-package :feebs)
+(in-package :the-feebs-war)
;;; We start defining the main system rules by defining the classes
@@ -39,13 +39,13 @@
(x-position :reader x-position :accessor feeb-x-position)
(y-position :reader y-position :accessor feeb-y-position)
(line-of-sight :accessor feeb-line-of-sight :reader line-of-sight
- :initform 0)
+ :initform 0)
(energy-reserve :accessor feeb-energy-reserve :reader energy-reserve)
(ready-to-fire :accessor feeb-ready-to-fire :reader ready-to-fire
- :initform t)
+ :initform t)
(aborted :accessor feeb-aborted :reader aborted)
(last-move :accessor feeb-last-move :reader last-move
- :initform :dead)
+ :initform :dead)
;; These are available for the system
(brain :accessor feeb-brain :initarg :brain)
@@ -57,11 +57,11 @@
(turns-since-flamed :accessor feeb-turns-since-flamed :initform 0)
(proximity :accessor feeb-proximity :initform (make-proximity))
(vision :accessor feeb-vision
- :initform (make-array (list (max *maze-y-size* *maze-x-size*))))
+ :initform (make-array (list (max *maze-y-size* *maze-x-size*))))
(vision-left :accessor feeb-vision-left
- :initform (make-array (list (max *maze-y-size* *maze-x-size*))))
+ :initform (make-array (list (max *maze-y-size* *maze-x-size*))))
(vision-right :accessor feeb-vision-right
- :initform (make-array (list (max *maze-y-size* *maze-x-size*))))))
+ :initform (make-array (list (max *maze-y-size* *maze-x-size*))))))
(defclass fireball (object)
((owner :accessor fireball-owner :initarg :owner)
@@ -89,23 +89,23 @@
(defun delete-object (thing x y)
(setf (aref *maze* x y)
- (delete thing (aref *maze* x y))))
+ (delete thing (aref *maze* x y))))
(defun place-object (thing x j)
(push thing (aref *maze* x j)))
(defun change-object-pos (obj x y)
(delete-object obj (object-x-position obj)
- (object-y-position obj))
+ (object-y-position obj))
(place-object obj x y)
(setf (object-x-position obj) x
- (object-y-position obj) y))
+ (object-y-position obj) y))
(defun get-forward-pos (object)
(let ((new-x (+ (forward-dx (object-direction object))
- (object-x-position object)))
- (new-y (+ (forward-dy (object-direction object))
- (object-y-position object))))
+ (object-x-position object)))
+ (new-y (+ (forward-dy (object-direction object))
+ (object-y-position object))))
(values (aref *maze* new-x new-y) new-x new-y)))
@@ -124,7 +124,7 @@
(:method (object x-pos y-pos)
(place-object object x-pos y-pos)
(setf (object-x-position object) x-pos
- (object-y-position object) y-pos))
+ (object-y-position object) y-pos))
(:method ((feeb feeb) x-pos y-pos)
(setf (feeb-last-move feeb) :dead)
@@ -134,7 +134,7 @@
(:method ((fireball fireball) x-pos y-pos)
(push fireball *fireballs-flying*)
(setf (object-x-position object) x-pos
- (object-y-position object) y-pos))) ; don't place it yet, only after first move
+ (object-y-position object) y-pos))) ; don't place it yet, only after first move
;;; Reincarnating
@@ -150,18 +150,18 @@
or :dissipate (for fireballs)."
(:method (object cause)
(delete-object object (object-x-position object)
- (object-y-position object)))
+ (object-y-position object)))
(:method ((fireball fireball) cause)
(setf *fireballs-flying*
- (delete fireball *fireballs-flying*))
+ (delete fireball *fireballs-flying*))
(call-next-method))
(:method ((feeb feeb) cause)
(setf *dead-feebs* (nconc *dead-feebs* (list feeb))
- *feebs* (delete feeb *feebs*))
+ *feebs* (delete feeb *feebs*))
(let* ((x (feeb-x-position feeb))
- (y (feeb-y-position feeb)))
+ (y (feeb-y-position feeb)))
(push (list 0 x y) *carcasses*)
(place-object :carcass x y))
(call-next-method)))
@@ -176,11 +176,11 @@
(:documentation "Lets object make its move choice.")
(:method ((feeb feeb))
(funcall (feeb-brain feeb)
- feeb
- (feeb-proximity feeb)
- (feeb-vision feeb)
- (feeb-vision-left feeb)
- (feeb-vision-right feeb))))
+ feeb
+ (feeb-proximity feeb)
+ (feeb-vision feeb)
+ (feeb-vision-left feeb)
+ (feeb-vision-right feeb))))
@@ -195,21 +195,21 @@
(:method (object (move (eql :turn-right)))
(setf (object-direction object)
- (right-of (object-direction object))))
+ (right-of (object-direction object))))
(:method (object (move (eql :turn-left)))
(setf (object-direction object)
- (left-of (object-direction object))))
+ (left-of (object-direction object))))
(:method (object (move (eql :turn-around)))
(setf (object-direction object)
- (behind (object-direction object))))
+ (behind (object-direction object))))
(:method (object (move (eql :move-forward)))
(multiple-value-bind (stuff new-x new-y)
- (get-forward-pos object)
+ (get-forward-pos object)
(unless (wallp stuff)
- (change-object-pos object new-x new-y))))
+ (change-object-pos object new-x new-y))))
(:method ((fireball fireball) (move (eql :dissipate)))
(destroy-object fireball :dissipate))
@@ -218,19 +218,19 @@
(setf (feeb-turns-since-flamed feeb) 0)
(create-object
(make-instance 'fireball :direction (feeb-facing feeb)
- :owner feeb)
+ :owner feeb)
(feeb-x-position feeb) (feeb-y-position feeb)))
(:method ((feeb feeb) (move (eql :eat-mushroom)))
(let ((x (feeb-x-position feeb))
- (y (feeb-y-position feeb)))
+ (y (feeb-y-position feeb)))
(when (find :mushroom (aref *maze* x y))
- (delete-object :mushroom x y)
- t)))
+ (delete-object :mushroom x y)
+ t)))
(:method ((feeb feeb) (move (eql :eat-carcass)))
(when (find :carcass (aref *maze* (feeb-x-position feeb)
- (feeb-y-position feeb)))
+ (feeb-y-position feeb)))
t))
(:method ((feeb feeb) (move (eql :peek-left)))
@@ -242,3 +242,4 @@
(setf (feeb-peeking feeb) move)))
) ; end of make-move generic function
+
Added: the-feebs-war.asd
==============================================================================
--- (empty file)
+++ the-feebs-war.asd Sat Feb 16 14:59:50 2008
@@ -0,0 +1,39 @@
+;;; -*- Common Lisp -*-
+
+(defpackage :feebs-system
+ (:use :cl :asdf))
+
+(in-package :feebs-system)
+
+(defsystem the-feebs-war
+ :description "The Feebs War is a continuation of Planet of the Feebs."
+ :version "0.1"
+ :author "Gustavo Henrique Milaré <gugamilare(a)gmail.com>"
+ :licence "GPL"
+; :depends-on (lispbuilder-sdl lispbuilder-sdl-image lispbuilder-sdl-gfx)
+
+ :components
+ (:cl-source-file "package")
+ (:cl-source-file "system" :depends-on ("package"))
+ (:cl-source-file "images" :depends-on ("system"))
+ (:cl-source-file "main" :depends-on ("images" "system"))
+
+ (:module "definitions"
+ :components
+ (:cl-source-file "utils")
+ (:cl-source-file "rules" :depends-on ("main"))
+ (:cl-source-file "mazes" :depends-on ("package" "utils"))
+ (:cl-source-file "extra" :depends-on ("package"))
+ (:cl-source-file "brains" :depends-on ("package")))
+
+ (:module "graphics"
+ :components
+ (:file "graphics" :depends-on ("main")))
+
+ ;; GPL
+ (:doc-file "licence")
+
+ ;; documentation
+ (:module "documentation"
+ :components
+ (:doc-file "feebs.tex")))
1
0