[the-feebs-war-cvs] r11 -
gmilare at common-lisp.net
gmilare at common-lisp.net
Mon Dec 31 21:35:36 UTC 2007
Author: gmilare
Date: Mon Dec 31 16:35:35 2007
New Revision: 11
Added:
images.lisp
rules.lisp
Modified:
feebs.tex
main.lisp
mazes.lisp
package.lisp
system.lisp
Log:
Modified: feebs.tex
==============================================================================
--- feebs.tex (original)
+++ feebs.tex Mon Dec 31 16:35:35 2007
@@ -60,10 +60,9 @@
\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 PAL \url{http://common-lisp.net/project/pal/}'s libraries,
+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 simpler both to make
-a feeb and to read the code.
+not exist anymore. Also the code is cleaner and more extensible.
\end{abstract}
\tableofcontents{}
@@ -72,16 +71,17 @@
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, and, after that, they
-can eat the carcass left. But throwing flames have an energy cost,
-so they must keep tracking for food.
+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.
+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}}
@@ -100,22 +100,22 @@
So, these are (some of) the changes:
\begin{itemize}
-\item The graphics are not based on X Window Sistem anymore, but on PAL,
+\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 without those hundreds of lines
-that the original version has. Just creating some .bmp or .jpg files
-of a feeb and your feeb is much more personalized!
+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 (except 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 Someone watching the game can control a Feeb with the keyboard, if
-he/she wants to, and say when the game must finish.
+\item Many functions and variables are changed and others were added
\item This document 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 search for some information.
+is easier to understand 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. This manual
+is just the beginning!
\end{itemize}
\section{The Game}
@@ -130,27 +130,34 @@
After all feebs move, the flames thrown before also move (or dissipate),
carcasses may rot and mushrooms may grow, accordingly to some rules.
-To see what values are taken, one can use \textsf{\textbf{(list-parameter-settings)}}.
-Using \textsf{\textbf{setf}} gives the possibility to change them
-and \textsf{\textbf{documentation}} can be used to know them. Just
-remember that every probability must be a rational number (like 1/2).
-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 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, or nil if there is a human player.
-\item [{\textsf{\textbf{{*}points-for-killing{*}}}}] How many points some
+\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
+\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.
-\item [{\textsf{\textbf{(get-maze-map)}}}] This command can be used to
-get the map (see section \ref{sub:Map}).
+\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}
@@ -162,28 +169,27 @@
to see its own flame exactly in front of it, so it shouldn't move
forward. 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 will turn 180 degrees.
+is a wall, the flame can reflect, and, if so, it will turn 180 degrees.
-Once a feeb is killed, in it's place in the maze there will appear
-a carcass. The feeb goes to the end of the killed feebs line. Whenever
-a carcass rots, the first feeb in line will reincarnate. So, dying
-is not so terrible.
+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. After a while
+the first feeb in line will reincarnate. 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
+\item [{\textsf{\textbf{'flame-energy}}}] Amount of energy lost after
throwing a flame.
-\item [{\textsf{\textbf{{*}fireball-guaranteed-lifetime{*}}}}] Number of
+\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
+\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
+\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
+\item [{\textsf{\textbf{'flame-no-recovery-time}}}] Number of turns
that a feeb cannot fire.
-\item [{\textsf{\textbf{{*}flame-recovery-probability{*}}}}] Probability
+\item [{\textsf{\textbf{'flame-recovery-probability}}}] Probability
of the feeb to recover the hability to throw a flame, after the apropriate
time.
\end{lyxlist}
@@ -199,38 +205,36 @@
These are the quantities:
\begin{lyxlist}{00.00.0000}
-\item [{\textsf{\textbf{{*}mushroom-energy{*}}}}] Amount of energy recovered
+\item [{\textsf{\textbf{'mushroom-energy}}}] Amount of energy recovered
when the feeb eats a mushroom.
-\item [{\textsf{\textbf{{*}carcass-energy{*}}}}] Amount of energy recovered
+\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 stay there. After these turns, it
+\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
+\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
+\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
+\item [{\textsf{\textbf{'starting-energy}}}] Amount of energy a feeb
has when it reincarnates.
-\item [{\textsf{\textbf{{*}number-of-mushrooms{*}}}}] Quantity of mushrooms
+\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, an initialize function
-(optional) and a set of graphics (optional).
+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 initializer is invoked when the game is about to start, so it
-can analyze the map, global parameters, and so on.
+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~}}\textsf{name~brain~}\textsf{\textbf{:initializer}}\textsf{~prepare~}\textsf{\textbf{:graphics}}\textsf{~graphics}\textsf{\textbf{)}}.
+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
@@ -261,21 +265,22 @@
\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. This is used so a feeb can analize a corridor
+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 of \textsf{\textbf{:peek-left}}.
+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 \textsf{\textbf{{*}carcass-energy{*}}}
-is restored to the feeb's energy.
+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 \textsf{\textbf{{*}mushroom-energy{*}}}
-is restored to the feeb's energy.
+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 mus take five arguments; I'll call them \textsf{\emph{status}},
+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}}.
@@ -291,51 +296,43 @@
\begin{lyxlist}{00.00.0000}
\item [{\textsf{\textbf{(name}}\textsf{\emph{~status}}\textsf{\textbf{)}}}] \begin{flushleft}
-The
-name of the feeb.
+The name of the feeb.
\par\end{flushleft}
-\item [{\textsf{\textbf{(facing~}}\textsf{\emph{status}}\textsf{\textbf{)}}}] \begin{flushleft}
-Where
-the feeb is facing, one of the constants provided: \textsf{\textbf{north}},
-\textsf{\textbf{south}}, \textsf{\textbf{east}} or \textsf{\textbf{west}},
+\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~}}\textsf{\emph{status}}\textsf{\textbf{)}}}] \begin{flushleft}
-The
-horizontal position of the feeb, increasing to east. If \textsf{\textbf{{*}sense-location{*}}}
-is nil, it returns nil instead.
-\par\end{flushleft}
-\item [{\textsf{\textbf{(y-position~}}\textsf{\emph{status}}\textsf{\textbf{)}}}] \begin{flushleft}
-The
-vertical position of the feeb, increasing to north. If \textsf{\textbf{{*}sense-location{*}}}
-is nil, it returns nil instead.
-\par\end{flushleft}
-\item [{\textsf{\textbf{(peeking~}}\textsf{\emph{status}}\textsf{\textbf{)}}}] \begin{flushleft}
-If
-it is \textsf{\textbf{:left}} or \textsf{\textbf{:right}}, it means
+\item [{\textsf{\textbf{(x-position}\emph{~status}\textbf{)}}}] \begin{flushleft}
+The horizontal position of the feeb, 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, increasing to north.
+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}}.
+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~}}\textsf{\emph{status}}\textsf{\textbf{)}}}] \begin{flushleft}
-Indicates
-the amount of valid entries in \textsf{\emph{vision}}. It actually
-means that \textsf{\textbf{(aref~}}\textsf{\emph{vision~}}\textsf{\textbf{(line-of-sight~}}\textsf{\emph{status}}\textsf{\textbf{))}}
+\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~}}\textsf{\emph{status}}\textsf{\textbf{)}}}] \begin{flushleft}
-\textsf{\textbf{T}}
-indicates that the feeb is ready to fire. \textsf{\textbf{Nil}} indicates
-it is not.
-\par\end{flushleft}
-\item [{\textsf{\textbf{(aborted}}\textsf{\emph{~status}}\textsf{\textbf{)}}}] \begin{flushleft}
-Related
-with timing. Returns \textsf{\textbf{T}} if the last move of feeb
-was aborted because of speed.
-\par\end{flushleft}
-\item [{\textsf{\textbf{(last-move~}}\textsf{\emph{status}}\textsf{\textbf{)}}}] \begin{flushleft}
-The
-feeb's previous move, or \textsf{\textbf{:dead}} if it has just reincarnated.
+\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}
@@ -345,45 +342,43 @@
what the feeb sees.
The structure \textsf{\emph{proximity}} has the contents of the squares
-near the feeb, with these fields:
+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.
+\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.
+\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.
+\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.
+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~}}\textsf{\emph{vision~}}\textsf{0}\textsf{\textbf{)}}
-will return the contents of the square in front of the feeb, \textsf{\textbf{(aref~}}\textsf{\emph{vision~}}\textsf{1}\textsf{\textbf{)}}
+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~}}\textsf{\emph{vision~}}\textsf{\textbf{(line-of-sight~}}\textsf{\emph{status}}\textsf{\textbf{))}}
+\textsf{\textbf{(aref}\emph{~vision~}\textbf{(line-of-sight}\emph{~status}\textbf{))}}
will be the first :rock encountered. All subsequents square, like
-\textsf{\textbf{(aref~}}\textsf{\emph{vision~}}\textsf{\textbf{(+~}}\textsf{1~}\textsf{\textbf{(line-of-sight~}}\textsf{\emph{status}}\textsf{\textbf{)))}},
+\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
-:rock or a list of elements, or maybe \textsf{\textbf{nil}} if the
+:rock or a list of elements, 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~}}\textsf{element}\textsf{\textbf{)}}
+\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~}}\textsf{element}\textsf{\textbf{)}}
+\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{)}}),
+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 (mushroom patchs) previouly
@@ -399,24 +394,20 @@
These are the fields available:
\begin{lyxlist}{00.00.0000}
-\item [{\textsf{\textbf{(feeb-image-name}}\textsf{~feeb-image}\textsf{\textbf{)}}}] \begin{flushleft}
-The
-name of the feeb. Maybe you can know it's weakpoints.
-\par\end{flushleft}
-\item [{\textsf{\textbf{(feeb-image-facing~}}\textsf{feeb-image}\textsf{\textbf{)}}}] \begin{flushleft}
-The
-facing of the feeb. This way the brain function can see if the feeb-image
-either sees it or not.
-\par\end{flushleft}
-\item [{\textsf{\textbf{(feeb-image-peeking~}}\textsf{feeb-image}\textsf{\textbf{)}}}] \begin{flushleft}
-Returns
-\textsf{\textbf{:peek-left}} or \textsf{\textbf{:peek-right}} if the
+\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~}}\textsf{fireball-image}\textsf{\textbf{)}}}] \begin{flushleft}
-The
-direction that the fireball image is going to.
+\item [{\textsf{\textbf{(fireball-image-direction}~fireball-image\textbf{)}}}] \begin{flushleft}
+The direction that the fireball image is going to.
\par\end{flushleft}
\end{lyxlist}
@@ -424,8 +415,8 @@
\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~}}\textsf{\emph{status}}\textsf{\textbf{)}},
-so \textsf{\textbf{(aref~}}\textsf{\emph{vision-left~}}\textsf{\textbf{(line-of-sight~}}\textsf{\emph{status}}\textsf{\textbf{))}},
+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
@@ -451,6 +442,20 @@
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{*}}}
+throw \textsf{\textbf{{*}maze-5{*}}}. If you want to create a new
+map, you can start by an empty template of any size provided by
+\textsf{\textbf{(make-template}~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
@@ -466,7 +471,7 @@
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~}}\textsf{path-to-image-file~nil}\textsf{\textbf{)}}
+\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.
@@ -476,11 +481,12 @@
The game loop is started by calling (feebs).
+
\section{Contests}
I sugest that you see this chapter only after you have created at
-least a basic brain feeb, wich is better than the (simple) provided
-brain, and when you want to participate of a contest or a game with
+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.
@@ -495,18 +501,18 @@
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 \textsf{\textbf{{*}may-get-maze-p{*}}}
+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}}\textsf{~map~x~y}\textsf{\textbf{)}}
+so that calling \textsf{\textbf{(aref}~map~x~y\textbf{)}}
will get the contents in the euclidean position (x,y) . 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 eaten it can come out here.
+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 in this place.
+\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}
@@ -514,19 +520,23 @@
\subsection{Timing}
There are also some timing atributes that can be given to the game.
-If the feeb takes too long to make a decision, there is more probability
+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:
+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. Not applied to the human controlled feeb.
-\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 for the total time taken
-by all the feebs in the current turn.
+\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 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}
@@ -537,30 +547,25 @@
These are the parameters:
\begin{lyxlist}{00.00.0000}
-\item [{\textsf{\textbf{{*}sense-location-p{*}}}}] Tells if the actual
-position of the feeb can be determinated accessing \textsf{\textbf{x-position}}
-and \textsf{\textbf{y-position}}.
+\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, and change the strategies
-after this could not be fair.
+of the variables to make a global strategy.
-All the parameters that can be listed using \textsf{\textbf{(list-parameter-settings)}}
-can be changed using setf. Also, they all have documentation about
-themselves, so feel free to use \textsf{\textbf{(documentation~}}\textsf{parameter~'variable}\textsf{\textbf{)}}
+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 too.
-
-It is possible to change the layout of the map by calling \textsf{\textbf{(change-layout}}\textsf{~new-layout}\textsf{\textbf{)}}.
-There are a few predefined mazes that are \textsf{\textbf{{*}maze-0{*}}}
-throw \textsf{\textbf{{*}maze-5{*}}}. If you want to create a new
-map, take the template (commented) inside the same file, or create
-maybe a bigger template (of any size, because the values of \textsf{\textbf{{*}maze-x-size{*}}}
-and \textsf{\textbf{{*}maze-y-size{*}}} will be changed accordingly).
+functions as well.
\section{Reference}
Added: images.lisp
==============================================================================
--- (empty file)
+++ images.lisp Mon Dec 31 16:35:35 2007
@@ -0,0 +1,121 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007 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 :feebs)
+
+;;; This file is an extension of system.lisp which handles vision
+
+
+
+;;; -*- Vision Calculation -*-
+
+;;; Computes what the feeb is seeing
+
+(defun compute-vision (feeb)
+ (let ((proximity (feeb-proximity feeb))
+ (vision (feeb-vision feeb))
+ (vision-left (feeb-vision-left feeb))
+ (vision-right (feeb-vision-right feeb))
+ (facing (feeb-facing feeb))
+ vision-dx
+ vision-dy
+ (x (feeb-x-position feeb))
+ (y (feeb-y-position feeb)))
+ ;; First fill in proximity info.
+ (setf (my-square proximity)
+ (imagify feeb (aref *maze* x y) 'proximity)
+ (left-square proximity)
+ (imagify feeb
+ (aref *maze* (+ x (left-dx facing)) (+ y (left-dy facing)))
+ :proximity)
+ (right-square proximity)
+ (imagify feeb
+ (aref *maze* (+ x (right-dx facing)) (+ y (right-dy facing)))
+ :proximity)
+ (rear-square proximity)
+ (imagify feeb
+ (aref *maze* (+ x (behind-dx facing)) (+ y (behind-dy facing)))
+ :proximity))
+ ;; The vision vector starts in the square the feeb is facing.
+ (setf x (+ x (forward-dx facing))
+ y (+ y (forward-dy facing)))
+ ;; Figure out which direction to scan in.
+ (case (feeb-peeking feeb)
+ (:peek-left (setf facing (left-of facing)))
+ (:peek-right (setf facing (right-of facing))))
+ (setf vision-dx (forward-dx facing)
+ vision-dy (forward-dy facing))
+ ;; compute vision, vision-left and vision-right
+ (do* ((x x (+ x vision-dx))
+ (y y (+ y vision-dy))
+ (left-wall-x (+ x (left-dx facing)) (+ left-wall-x vision-dx))
+ (left-wall-y (+ y (left-dy facing)) (+ left-wall-y vision-dy))
+ (right-wall-x (+ x (right-dx facing)) (+ right-wall-x vision-dx))
+ (right-wall-y (+ y (right-dy facing)) (+ right-wall-y vision-dy))
+ (index 0 (1+ index)))
+ ((wallp (aref *maze* x y))
+ (setf (aref vision index) :rock
+ (aref vision-left index) :unknown
+ (aref vision-right index) :unknown
+ (line-of-sight status) index))
+ (setf (aref vision index) (imagify feeb (aref *maze* x y) :vision)
+ (aref vision-left index)
+ (imagify feeb
+ (aref *maze* left-wall-x left-wall-y)
+ :left-vision)
+ (aref vision-right index)
+ (imagify feeb
+ (aref *maze* right-wall-x right-wall-y)
+ :right-vision)))))
+
+(defstruct feeb-image
+ name facing peeking)
+
+(defstruct fireball-image
+ direction)
+
+;;; This transforms what the feeb is seeing;
+
+(defgeneric imagify (feeb thing type)
+ (:documentation "Defines how FEEB sees or feels THING.
+TYPE could be :vision, :left-vision :right-vision or :proximity")
+ (:method (feeb thing type)
+ thing)
+
+ (:method (feeb (thing feeb)
+ (type (or (eql :vision) (eql :proximity))))
+ (make-feeb-image :name (feeb-name thing)
+ :facing (feeb-facing feeb)
+ :peeking (feeb-peeking feeb)))
+
+ (:method (feeb (thing fireball)
+ (type (or (eql :vision) (eql :proximity))))
+ (make-fireball-image :direction (fireball-direction thing)))
+
+ (:method (feeb thing
+ (or (eql :left-vision) (eql :right-vision)))
+ nil)
+
+ (:method (feeb (thing feeb)
+ (or (eql :left-vision) (eql :right-vision)))
+ (and (feeb-image-p thing)
+ (= facing (feeb-image-facing thing))
+ (feeb-image-peeking thing))))
Modified: main.lisp
==============================================================================
--- main.lisp (original)
+++ main.lisp Mon Dec 31 16:35:35 2007
@@ -21,38 +21,67 @@
(in-package :feebs)
-;;; Some functions
+;; These are defined provisorily here
+;; the definitive version is in rules.lisp
-(defmacro define-parameter (name &optional value doc)
- `(progn
- (defvar ,name ,value
- ,@(if doc '(doc)))
- (export ,name)
- (pushnew ',name *feeb-parameters*)))
-
-(defun list-parameter-settings ()
- (let ((settings nil))
- (dolist (parm *feeb-parameters*)
- (push (cons parm (symbol-value parm)) settings))
- settings))
+(defun rot-carcass-p (time)
+ t)
+
+(defun reincarnate-feeb-p (feeb)
+ t)
+
+(defun finish-game-p ()
+ ;; This is a little dangerous...
+ nil)
+
+
+
+;;; Parameters
+
+(let ((parameters (make-hash-table :test 'eq)))
+
+ (defun def-feeb-parm (name value &optional doc)
+ (aif (gethash name parameters)
+ (progn
+ (warn "Change parameter ~a to ~a: ~
+parameter already existed with value ~a." name value (car it))
+ (setf (gethash name parameters) (cons value (or doc (cdr it)))))
+ (setf (gethash name parameters) (cons value doc)))
+ name)
+
+ (defun get-feeb-parm (name)
+ (gethash name parameters))
+
+ (defun change-parameter (name value)
+ (setf (car (gethash name parameters)) value))
+
+ (defmethod documentation (name (type (eql 'feeb-parameter)))
+ (cdr (gethash name parameters)))
+
+ (defun list-parameter-settings ()
+ (let (params)
+ (maphash #'(lambda (key value)
+ (push (list key (car value) (cdr value)) params))
+ parameters)
+ params)))
;;; Characteristics of the maze:
-(define-parameter *may-get-maze-map-p* t
- "Tells if the function (get-maze-map) returns the map layout of nil
- during the game.")
+(def-feeb-parm 'may-get-maze-map-p t
+ "Tells if the function (get-maze-map) returns the map layout
+instead of nil during the game.")
;;; Tests that behavior functions might use
-(declare (inline feeb-image-p fireball-image-p))
+;; (declare (inline feeb-image-p fireball-image-p))
-(defun feeb-image-p (thing)
- (typep thing 'feeb))
+;; (defun feeb-image-p (thing)
+;; (typep thing 'feeb))
-(defun fireball-image-p (thing)
- (typep thing 'fireball))
+;; (defun fireball-image-p (thing)
+;; (typep thing 'fireball))
@@ -72,8 +101,8 @@
(if (/= (length string) y)
(error "Not all the strings in ~a have the same size." layout)))
(setf *layout* layout
- *maze-y-size* y
- *maze-x-size* x))
+ *maze-y-size* (change-feeb-parm 'maze-y-size y)
+ *maze-x-size*(change-feeb-parm 'maze-x-size x)))
(init-maze))
(defun get-maze-map ()
@@ -85,12 +114,13 @@
:feeb-entry-place -place where a feeb can reincarnate
nil - nothing special
Just remember that if *may-get-maze-map-p* is nil,
-this function return an array of nils"
- (let ((new-maze (make-array (list *maze-x-size* *maze-y-size*))))
- (dotimes (x *maze-x-size*)
- (dotimes (y *maze-y-size*)
- (setf (aref new-maze x y) (aref *fake-maze* x y))))
- new-maze)))
+this function return nil."
+ (and (get-feeb-parm 'may-get-maze-map-p)
+ (let ((new-maze (make-array (list *maze-x-size* *maze-y-size*))))
+ (dotimes (x *maze-x-size*)
+ (dotimes (y *maze-y-size*)
+ (setf (aref new-maze x y) (aref *fake-maze* x y))))
+ new-maze)))
(defun init-maze ()
(setf *maze* (make-array (list *maze-x-size* *maze-y-size*))
@@ -108,18 +138,15 @@
(aref *fake-maze* j i) nil)
(case (schar str j)
(#\X
- (setf (aref *fake-maze* j i)
- (and *may-get-maze-map-p* :rock)
+ (setf (aref *fake-maze* j i) :rock
(aref *maze* j i) :rock))
(#\*
- (setf (aref *fake-maze* j i)
- (and *may-get-maze-map-p* :mushroom-place))
+ (setf (aref *fake-maze* j i) :mushroom-place)
(incf *number-of-mushroom-sites*)
(push (make-pos j i) *mushroom-sites*))
(#\e
(setf (aref *fake-maze* j i)
- (and *may-get-maze-map-p*
- :feeb-entry-place))
+ :feeb-entry-place)
(incf *number-of-entry-points*)
(push (make-pos j i) *entry-points*))
(#\space nil)
@@ -181,7 +208,6 @@
(let ((feeb (make-instance class
:name name
:brain brain
- :direction (random 4)
:graphics graphs
:x-position x-pos
:y-position y-pos)))
@@ -202,15 +228,14 @@
;;; The Game
-(let ((mushrooms 0))
+(let ((mushrooms 1))
(defun number-of-mushrooms (n)
- (setf *mushrooms-to-grow* n))
+ (setf mushrooms n))
(defun play-one-turn ()
- (setf mushrooms 0) ; restart the count
;; This is defined by rules:
- (start-turn)
+ (start-turn) ; possible call to number-of-mushrooms
;; Maybe grow up mushrooms:
(let ((m-sites (sort *mushroom-sites*
#'(lambda (x y)
@@ -218,32 +243,35 @@
(zerop (random 2))))))
(dotimes (i mushrooms)
(let ((site (pop m-sites)))
- (create-mushroom (car site) (cdr site)))))
+ (unless (member #'fireball-p)
+ (create-mushroom (car site) (cdr site)))))
;; Maybe rot some carcasses
- ;; FIXME: Ugly code code, and
- (loop for carc in *carcasses*
- with ncarcasses do
- (if (rot-carcass-p (first carc))
- (progn
- (delete-object :carcass (second carc) (third carc))
- (reincarnate-feeb (pop *dead-feebs*)))
- (progn
- (push carc ncarcasses)
- (incf (first carc)))))
+ (dolist (carc (prog1 *carcasses*
+ (setf *carcasses* nil)))
+ (unless (rot-carcass (first carc) (second carc) (third carc))
+ (progn
+ (incf (first carc))
+ (push carc *carcasses*))))
;; Move some fireballs:
(dolist (fireball *fireballs-flying*)
(move-object fireball (make-move-choice fireball)))
(dolist (feeb *feebs*)
- (unless (feeb-dead-p feeb)
- ;; Starve the feeb:
- (when (<= (decf (feeb-energy-reserve feeb)) 0)
- (destroy-object feeb :starve))
- ;; Compute vision for the feeb:
- (compute-vision feeb)))
- (dolist (feeb *feebs*)
- (unless (feeb *feebs*)
+ (if (feeb-dead-p feeb)
+ ;; Reincarnate some feebs (if the rules allow it)
+ (reincarnate-feeb feeb)
+ (progn
+ ;; Starve the feeb:
+ (when (<= (decf (feeb-energy-reserve feeb)) 0)
+ (destroy-object feeb :starve))
+ ;; Compute vision for the feeb:
+ (compute-vision feeb))))
+ (dolist (*playing-feeb* *feebs*)
+ (unless (feeb-dead-p *playing-feeb*)
;; Collect the feeb's move
- (setf (feeb-peeking feeb) nil)
- (move-object feeb (setf (feeb-last-move feeb)
- (make-move-choice feeb))))))
-)
\ No newline at end of file
+ (move-object *playing-feeb*
+ (prog1
+ (setf (feeb-last-move *playing-feeb*)
+ (make-move-choice *playing-feeb*))
+ (setf (feeb-peeking *playing-feeb*) nil))))))))
+
+) ; end of let ((mushrooms 1))
Modified: mazes.lisp
==============================================================================
--- mazes.lisp (original)
+++ mazes.lisp Mon Dec 31 16:35:35 2007
@@ -316,7 +316,7 @@
#\X
#\Space))))))
-;;; This one generates a almost ready-to-use map
+;;; This one generates an almost ready-to-use map
(defun generate-maze (x-size y-size
&key (density 0.4)
@@ -333,7 +333,8 @@
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."
+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
@@ -371,10 +372,11 @@
(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))))
- ((or (>= (density map x-size y-size) density)
+ corridor-y-avg corridor-y-max)))
+ (real-dens ))
+ ((or (>= real density)
(> i (* density x-size y-size))) ; quits after trying TOO MUCH
- (translate map x-size y-size))
+ (values (translate map x-size y-size) real-dens))
(if x1
(setf map (horiz-corridor map y x1
(bound x2 1 (- x-size 2)))))
Modified: package.lisp
==============================================================================
--- package.lisp (original)
+++ package.lisp Mon Dec 31 16:35:35 2007
@@ -33,8 +33,7 @@
(defpackage :feebs
(:use :common-lisp)
;; Export everything we want the players to get their hands on.
- (:export *number-of-feebs* *game-length*
- *number-of-auto-feebs*
+ (:export *game-length*
;; Strategic quantities
*points-for-killing* *points-for-dying*
@@ -48,8 +47,6 @@
*number-of-mushrooms*
;; Probabilities
- *carcass-guaranteed-lifetime*
- *carcass-rot-probability*
*fireball-guaranteed-lifetime*
*fireball-dissipation-probability*
*fireball-reflection-probability*
@@ -80,9 +77,12 @@
feeb-image-p feeb-image-name
feeb-image-facing feeb-image-peeking
fireball-image-p fireball-image-direction
-
- ;; Functions
+
+ ;; Parameters
+ get-feeb-parm change-feeb-parm
list-parameter-settings
+
+ ;; Settings
define-feeb delete-feeb
feebs
change-layout
@@ -93,7 +93,7 @@
;; Some layouts (can be find in mazes.lisp)
*maze-1* *maze-2* *maze-3* *maze-4* *maze-5*
- *maze-template*
+ make-template generate-maze
;; Graphics
create-graphics
@@ -119,6 +119,9 @@
;;; Directions
+(deftype direction ()
+ `(integer 0 3))
+
(defconstant north 0)
(defconstant east 1)
(defconstant south 2)
@@ -178,10 +181,18 @@
"XXXXX XXXXXXXXXXXXX X"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"))
-(defparameter *maze-x-size* 32
- "Horizontal size of the maze")
-(defparameter *maze-y-size* 32
- "Vertical size of the maze")
+
+
+;;; Map size
+
+(def-feeb-parm 'maze-x-size 32
+ "Horizontal size of the maze.")
+
+(def-feeb-parm 'maze-y-size 32
+ "Vertical size of the maze.")
+
+(defvar *maze-x-size* 32)
+(defvar *maze-y-size* 32)
;;; Quantities during the game
@@ -197,5 +208,13 @@
(defvar *dead-feebs*)
(defvar *carcasses*)
-(defvar *continue*)
+;;; Current feeb playing
+(defvar *playing-feeb*)
+(defmacro aif (test then &optional else)
+ `(let ((it ,test))
+ (if it ,then ,else)))
+
+(defmacro awhen (test &rest body)
+ `(let ((it ,test))
+ (when it , at body)))
Added: rules.lisp
==============================================================================
--- (empty file)
+++ rules.lisp Mon Dec 31 16:35:35 2007
@@ -0,0 +1,119 @@
+;;; -*- Common Lisp -*-
+
+#| Copyright (c) 2007 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 :feebs)
+
+
+
+(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)
+ (defun start-round ()
+ (setf turn-number 0)
+ (number-of-mushrooms
+ (random (1+ (get-feeb-parm 'number-of-mushrooms)))))
+
+ (defun start-turn ()
+ (incf turn-number))
+
+ (defun finish-game-p ()
+ (>= (get-feeb-parm 'game-length) turn-number)))
+
+(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 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 'sense-location-p t
+ "If nil, x-position and y-position will return nil when
+ someone tries to invoke it. Otherwise return the position.")
+
+;;; Scoring:
+
+(def-feeb-parm 'points-for-killing 5
+ "How many points some feeb earn for killing someone.")
+
+(def-feeb-parm 'points-for-dying -3
+ "How many points some feeb earn for dying (usually negative).")
+
+(def-feeb-parm 'points-for-slow-down -1
+ "Points earned when a feeb's move is aborted due to slowness.")
+
+
+;;; Energies:
+
+(def-feeb-parm 'flame-energy 10
+ "Amount of energy lost after throwing a flame.")
+
+(def-feeb-parm 'mushroom-energy 50
+ "Amount of energy recovered when the feeb eats a mushroom.")
+
+(def-feeb-parm 'carcass-energy 30
+ "Amount of energy recovered each turn that the feeb
+eats a carcass.")
+
+(def-feeb-parm 'maximum-energy 100
+ "The most energy a feeb can accumulate.")
+
+(def-feeb-parm 'starting-energy 50
+ "Smallest amount of energy a feeb will start with.")
+
+;;; 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.")
+
+
+;;; 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.")
+
+(deef-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.")
Modified: system.lisp
==============================================================================
--- system.lisp (original)
+++ system.lisp Mon Dec 31 16:35:35 2007
@@ -27,24 +27,21 @@
;;; This class is used by the system
(defclass object ()
- ((direction :accessor object-direction)
- (x-position :accessor object-x-position)
- (y-position :accessor object-y-position)))
+ ((direction :accessor object-direction :initarg :direction)
+ (x-position :accessor object-x-position :initarg :x-position)
+ (y-position :accessor object-y-position :initarg :y-position)))
(defclass feeb (object)
(;; These are structures accessible from behavior functions.
;; These (whose :reader start with feeb-image)
;; are intended to be accessed by other feebs
- (name :accessor feeb-name :reader name :initarg :name
- :reader feeb-image-name)
- (direction :reader facing :reader feeb-image-facing
- :initform (random 4))
- (peeking :accessor feeb-peeking :reader peeking
- :reader feeb-image-peeking)
+ (name :accessor feeb-name :reader name :initarg :name)
+ (direction :reader facing :initform (random 4))
+ (peeking :accessor feeb-peeking :reader peeking)
;; These are intended to be accessed only by the feeb itself
- (x-position :reader x-position :initform 0 :initarg :x-position)
- (y-position :reader y-position :initform 0 :initarg :y-position)
+ (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)
(energy-reserve :accessor feeb-energy-reserve :reader energy-reserve
@@ -55,7 +52,7 @@
(last-move :accessor feeb-last-move :reader last-move
:initform :dead)
- ;; These are available for the system only
+ ;; These are available for the system
(brain :accessor feeb-brain :initarg :brain)
(graphics :accessor feeb-graphics :initarg :graphics)
(time :accessor feeb-time :initform 0)
@@ -64,7 +61,6 @@
(score :accessor feeb-score :initform 0)
(kills :accessor feeb-kills :initform 0)
(dead-p :accessor feeb-dead-p)
- (playing-p :accessor feeb-playing-p)
(turns-since-flamed :accessor feeb-turns-since-flamed :initform 0)
(proximity :accessor feeb-proximity :initform (make-proximity))
(vision :accessor feeb-vision
@@ -74,6 +70,21 @@
(vision-right :accessor feeb-vision-right
:initform (make-array (list (max *maze-y-size* *maze-x-size*))))))
+(defclass fireball (object)
+ ((owner :accessor fireball-owner :initarg :owner)
+ (x-position :accessor fireball-x-position)
+ (y-position :accessor fireball-y-position)
+ (direction :accessor fireball-direction)))
+
+(declaim
+ (inline fireball-p feeb-p))
+
+(defun fireball-p (x)
+ (typep x 'fireball))
+
+(defun feeb-p (x)
+ (typep x 'feeb))
+
;;; These make sure that these accessors are just available
;;; for the feeb itself
@@ -161,8 +172,13 @@
;;; -*- General Rules -*-
-(defgeneric start-turn (&key &allow-other-keys)
- (:method () t))
+;; These will be redefined by rules
+
+(defun start-turn ()
+ t)
+
+(defun start-round ()
+ t)
@@ -202,79 +218,13 @@
-;;; -*- Vision Calculation -*-
-
-;;; Computes what the feeb is seeing
-
-(defun compute-vision (feeb)
- (let ((proximity (feeb-proximity feeb))
- (vision (feeb-vision feeb))
- (vision-left (feeb-vision-left feeb))
- (vision-right (feeb-vision-right feeb))
- (facing (feeb-facing feeb))
- vision-dx
- vision-dy
- (x (feeb-x-position feeb))
- (y (feeb-y-position feeb)))
- ;; First fill in proximity info.
- (setf (my-square proximity)
- (aref *maze* x y)
- (left-square proximity)
- (aref *maze* (+ x (left-dx facing)) (+ y (left-dy facing)))
- (right-square proximity)
- (aref *maze* (+ x (right-dx facing)) (+ y (right-dy facing)))
- (rear-square proximity)
- (aref *maze* (+ x (behind-dx facing)) (+ y (behind-dy facing))))
- ;; The vision vector starts in the square the feeb is facing.
- (setf x (+ x (forward-dx facing))
- y (+ y (forward-dy facing)))
- ;; Figure out which direction to scan in.
- (case (feeb-peeking feeb)
- (:left (setf facing (left-of facing)))
- (:right (setf facing (right-of facing))))
- (setf vision-dx (forward-dx facing)
- vision-dy (forward-dy facing))
- ;; compute vision, vision-left and vision-right
- (do* ((x x (+ x vision-dx))
- (y y (+ y vision-dy))
- (left-wall-x (+ x (left-dx facing)) (+ left-wall-x vision-dx))
- (left-wall-y (+ y (left-dy facing)) (+ left-wall-y vision-dy))
- (right-wall-x (+ x (right-dx facing)) (+ right-wall-x vision-dx))
- (right-wall-y (+ y (right-dy facing)) (+ right-wall-y vision-dy))
- (index 0 (1+ index)))
- ((wallp (aref *maze* x y))
- (setf (aref vision index) (aref *maze* x y)
- (aref vision-left index) :unknown
- (aref vision-right index) :unknown
- (line-of-sight status) index))
- (setf (aref vision index) (aref *maze* x y)
- (aref vision-left index)
- (side-imagify (aref *maze* left-wall-x left-wall-y)
- (right-of facing))
- (aref vision-right index)
- (side-imagify (aref *maze* right-wall-x right-wall-y)
- (left-of facing))))))
-
-;;; Compute the info to be put into the vision-left and vision-right vectors.
-;;; A peeking feeb must be facing in the specified direction in order to count.
-
-(defun side-imagify (stuff facing)
- (if (wallp stuff)
- stuff
- (loop for thing in stuff
- and elt = (and (feeb-image-p thing)
- (= facing (feeb-image-facing thing))
- (feeb-image-peeking thing))
- if elt
- return it)))
-
-
-
;;; -*- Movement -*-
;;; Lets the feeb make a choice
-(defgeneric make-move-choice (object &key &allow-other-keys)
+(defgeneric make-move-choice (object)
+ (:documentation "Lets object make its move choice.")
+
(:method ((feeb feeb))
(funcall (feeb-brain feeb)
(feeb-status feeb)
@@ -286,6 +236,9 @@
;;; Moving
(defgeneric make-move (object move)
+ (:documentation "Applies the move MOVE to OBJECT. The MOVE is
+returned from MAKE-MOVE-CHOICE for the same object.")
+
(:method (object (move (eql :turn-right)))
(setf (object-direction object)
(right-of (object-direction object)))
@@ -316,7 +269,7 @@
;;; Feeb moves
(:method ((feeb feeb) (move (eql :move-forward)))
- (let ((thing (find-if #'fireball-image-p stuff)))
+ (let ((thing (find-if #'fireball-p stuff)))
(when thing (destroy-object feeb thing)
(return-from make-move t)))
(call-next-method))
@@ -325,9 +278,9 @@
(let ((x (feeb-x-position feeb))
(y (feeb-y-position feeb))
(fireball
- (make-fireball-image (feeb-facing feeb)
- feeb x y (forward-dx facing)
- (forward-dy facing))))
+ (make-instace 'fireball (feeb-facing feeb)
+ feeb x y (forward-dx facing)
+ (forward-dy facing))))
(push fireball *fireballs-flying*)
t))
@@ -344,17 +297,10 @@
(when (member :carcass (aref *maze* x y))
t)))
- (:method ((feeb feeb) (move (eql :peek-left)))
+ (:method ((feeb feeb) (move (or (eql :peek-left) (eql :peek-right))))
(multiple-value-bind (x y stuff)
(get-forward-pos feeb)
(unless (wallp stuff)
- (setf (peeking feeb) move)))
- t)
+ (setf (feeb-peeking feeb) move)))
- (:method make-move ((feeb feeb) (move (eql :peek-right)))
- (multiple-value-bind (x y stuff)
- (get-forward-pos feeb)
- (unless (wallp stuff)
- (setf (peeking feeb) move)))
- t)
) ; end of make-move generic function
More information about the The-feebs-war-cvs
mailing list