Jon Aquino's Mental Garden

Engineering beautiful software jon aquino labs | personal blog

Friday, February 25, 2005

First Video Game Written In Ant

Presenting the world's first video game written in Ant. This is a cross-platform downhill skiing game in which you use the < and > keys to race down a dangerous ski slope. System requirements: Ant 1.6 and the Ant-Contrib library.

And yes, it's written in Ant.

How this came to be: Some co-workers and I were chatting today about some Ant features we learned about, in particular the very useful macrodef and import tags. Then it dawned on me that with the function-like behaviour that macrodef tags give us, we could do virtually anything. Heck, we could write a video game in Ant if we wanted to! My coworkers laughed at me.

Well, laugh no more, my friends. Below is a screenshot showing the first-ever Ant video game in action:



In the above screenshot, I have crashed into the trees on the right. As this is an Ant script, the bad news begins with "Build Failed".

Note: If you succeed in skiing through the entire course and arriving at the bottom of the mountain, there is a pretty end-game screen as your reward!

Simply copy the code below and fire up Ant using the command "ant -quiet". Note that you will need Ant 1.6 and the Ant-Contrib library.


<?xml version="1.0"?>
<!--
To start the game, type "ant -quiet". Requires Ant 1.6
and the Ant-Contrib Tasks [Jon Aquino 2005-02-24]
-->
<project name="ski" default="run" basedir=".">
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<taskdef name="for" classname="net.sf.antcontrib.logic.For"/>
<typedef name="isgreaterthan" classname="net.sf.antcontrib.logic.condition.IsGreaterThan"/>
<typedef name="islessthan" classname="net.sf.antcontrib.logic.condition.IsLessThan"/>
<var name="skiier-position" value="5"/>
<!-- Generated using random numbers from http://www.random.org.
Make your own course up! [Jon Aquino 2005-02-25] -->
<property name="course" value="1,0,1,2,1,2,3,2,3,4,3,4,5,4,3,4,3,2,3,4,3"/>
<property name="course-width" value="13"/>
<property name="skiier-width" value="7"/>
<target name="run">
<echo/>
<echo message="Use the &lt; and &gt; keys to move left and right."/>
<for list="${course}" param="tree-position">
<sequential>
<var name="tree-position" value="@{tree-position}"/>
<update-clearances/>
<check-crash/>
<paint/>
<get-input/>
</sequential>
</for>
<success/>
</target>
<macrodef name="paint">
<sequential>
<!-- Graphics from http://www.chris.com/ascii/ [Jon Aquino 2005-02-24] -->
<paint-line tree=" " skiier="+ + "/>
<paint-line tree=" /\ /\" skiier="\ O \ "/>
<paint-line tree=" / \\ /\ /\\\" skiier="\_/|\_\"/>
<paint-line tree="/ \\/ \\ / \\\" skiier=" \\ "/>
<paint-line tree="/ / \/ \\\" skiier="\/' "/>
<paint-line tree="/ / / \\\" skiier="\\_ "/>
<paint-line tree="/ / / \\\" skiier="- "/>
</sequential>
</macrodef>
<macrodef name="get-input">
<sequential>
<var name="input" unset="true"/>
<input addproperty="input"/>
<if><equals arg1="${input}" arg2=","/>
<then><subtract a="${skiier-position}" b="1" result="skiier-position"/></then>
<elseif><equals arg1="${input}" arg2="."/>
<then><add a="${skiier-position}" b="1" result="skiier-position"/></then></elseif></if>
</sequential>
</macrodef>
<macrodef name="update-clearances">
<sequential>
<subtract a="${skiier-position}" b="${tree-position}" result="left-clearance"/>
<add a="${tree-position}" b="${course-width}" result="right-clearance"/>
<subtract a="${right-clearance}" b="${skiier-position}" result="right-clearance"/>
<subtract a="${right-clearance}" b="${skiier-width}" result="right-clearance"/>
</sequential>
</macrodef>
<macrodef name="paint-line">
<attribute name="tree"/>
<attribute name="skiier"/>
<sequential>
<spaces n="${tree-position}" result="left-margin"/>
<spaces n="${left-clearance}" result="left-space"/>
<spaces n="${right-clearance}" result="right-space"/>
<echo message="${left-margin}@{tree}${left-space}@{skiier}${right-space}@{tree}"/>
</sequential>
</macrodef>
<macrodef name="spaces">
<attribute name="n"/>
<attribute name="result"/>
<sequential>
<math result="2n" operation="*" operand1="@{n}" operand2="2" datatype="int"/>
<var name="@{result}" unset="true"/>
<propertyregex
property="@{result}"
input=" "
regexp="( {${2n}}).*"
select="\1"/>
</sequential>
</macrodef>
<macrodef name="add">
<attribute name="a"/>
<attribute name="b"/>
<attribute name="result" default="result"/>
<sequential>
<math result="@{result}" operation="+" operand1="@{a}" operand2="@{b}" datatype="int"/>
</sequential>
</macrodef>
<macrodef name="subtract">
<attribute name="a"/>
<attribute name="b"/>
<attribute name="result" default="result"/>
<sequential>
<add a="@{a}" b="-@{b}" result="@{result}"/>
</sequential>
</macrodef>
<macrodef name="check-crash">
<sequential>
<if><islessthan arg1="${left-clearance}" arg2="0"/>
<then><die/></then></if>
<if><islessthan arg1="${right-clearance}" arg2="0"/>
<then><die/></then></if>
</sequential>
</macrodef>
<macrodef name="die">
<sequential>
<!-- Sound effects from http://collection.nlc-bnc.ca/100/200/300/ktaylor/kaboom-revised/bzzurkk.htm [Jon Aquino 2005-02-25] -->
<fail message=" *** BOINK! POINK! THUMP! You smashed into a tree and died. ***"/>
</sequential>
</macrodef>
<macrodef name="success">
<sequential>
<!-- Graphics from http://www.chris.com/ascii/ [Jon Aquino 2005-02-24] -->
<echo message="Hooray! Hooray! You are the champion! Congratulations!"/>
<echo message=" *"/>
<echo message=" XX"/>
<echo message=" MMMMM"/>
<echo message=" //(00 "/>
<echo message=" .:....."/>
<echo message=" .:::::::::"/>
<echo message=" :: %%%%%% ::."/>
<echo message=" :: :::::: :::::::I)"/>
<echo message=" (% ::::: |"/>
<echo message=" / | /______ |"/>
<echo message=" / |______ )) |"/>
<echo message=" / / // |"/>
<echo message=" / / // |"/>
<echo message=" / / // |"/>
<echo message="* ZZZZ *"/>
<echo message=" _________ZZZZZZ_________//_//"/>
</sequential>
</macrodef>
</project>


Here is a complete picture of a successful ski run:



And Ant gives us a nice report of the time it took to reach the bottom of the slope:

BUILD SUCCESSFUL
Total time: 17 seconds

15 Comments:

Post a Comment

<< Home