Browse Source

more levels

master
flyingsparx 8 years ago
parent
commit
70936bb611
  1. 31
      README.md
  2. 38
      cardiff_drone.py
  3. 1
      manager.py
  4. 44
      maps.json
  5. 66
      templates/level.html

31
README.md

@ -56,6 +56,7 @@ This will cause the drone to look in its current area for any items. If it finds
The Drone understands the following commands:
- `takeoff()` - Lift the Drone off the ground.
- `land()` - Land the drone in its current square.
- `hover()` - Stay hovering in the current square and altitude.
- `pick_up()` - Pick up items in the Drone's current square and altitude.
- `move_forward()` - Move forward one square.
- `move_backward()` - Move backward one square.
@ -71,8 +72,10 @@ The Drone understands the following commands:
- `y` - The current Y-coordinate.
- `z` - The current height.
- `a` - The current bearing angle.
- `fuel` - The Drone's remaining fuel.
- `inventory` - The list of items the Drone is holding.
- `status` - The current status of the Drone (Ready, Landed, Flying, Crashed, etc.).
- `map` - The Drone's knowledge of the map.
### Standard Python routines:
@ -100,6 +103,32 @@ if drone.status == "Flying":
drone.move_forward()
```
Python's `while` construct can also be useful repeating commands or checking for values. The following code moves the Drone to the right until it is in column 8, as long as it starts in a column to the left of this and `drone.a = 90`.
```
while drone.x < 8:
drone.move_forward()
```
Multiple boolean expressions can be combined. The following snippet repeats the two functions until the drone is in cell (8,10) and also assumes `drone.a = 90`:
```
while drone.x < 8 and drone.y < 10:
drone.move_forward()
drone.move_right()
```
Be careful - if the Drone never arrives in cell (8,2), then the loop will still continue until the Drone crashes or runs out of fuel!
All of Python's constructs can be nested. Loops can be exited prematurely using the `break` keyword. For example, to stop the previous command moving the Drone too far in *either* direction, use an 'ORd' if-statement inside your while-loop:
```
while drone.x < 8 and drone.y < 10:
if drone.x > 10 or drone.y > 12:
break
drone.move_forward()
drone.move_right()
```
Functions allow you to bundle many commands into a single, callable, routine. For example, this function moves the drone 3 squares forward and turns right:
```
@ -150,6 +179,8 @@ Maps can be managed directly through the `maps.json` file. Each map is rectangul
- `ammo` - `int`: the initial ammo held by the drone (currently un-used but necessary for construction).
- `items` - `[{item }]`: List of item objects. Each item should have a `name` (string) and `location` ([x,y,z]) attribute. Fuel is a valid collection item, and should be given a name like `fuel (x)`, where `x` is an integer representing the amount of fuel to be replenished upon collection.
- `finish_items` - `[str]`: List of item names required to complete the level. All of the names in this array must be present in the `items` array.
- `drone_visible` - `bool`: Set whether the drone and its sensors should be visible to the player on this map. (Setting to `false` requires the player to use the Drone's locational attributes to find their way).
- `wind` - `{wind}`: Set the map's wind as an object containing the keys `towards` (values: "N", "E", "S", "W") and `frequency` (`int` or "random"). Setting the `frequency` to "random" causes a frequency to be generated randomly betwen 1-5 on each turn. A `frequency` of 1 means that the wind effect is applied every turn, a value of 2 applies every other turn, and so on. If you don't want to apply wind, just set `frequency` to a high number. Wind moves the Drone one square towards the direction given by `towards`.
Note that the Drone will crash if it leaves the map's bounds or if it flies higher than z=9. Therefore, keep relevant items and the finish and start squares to a lower height.

38
cardiff_drone.py

@ -1,3 +1,5 @@
import random
class Drone:
def __init__(self, m):
self.map = m
@ -46,15 +48,27 @@ class Drone:
self.z = 0
self.crashed = True
if self.moves % self.map['wind']['frequency'] == 0:
if self.map['wind']['towards'] == 'N':
self.y-=1
if self.map['wind']['towards'] == 'E':
self.x+=1
if self.map['wind']['towards'] == 'S':
self.y+=1
if self.map['wind']['towards'] == 'W':
self.x-=1
if type(self.map['wind']['frequency']) == 'int':
if self.moves % self.map['wind']['frequency'] == 0:
if self.map['wind']['towards'] == 'N':
self.y-=1
if self.map['wind']['towards'] == 'E':
self.x+=1
if self.map['wind']['towards'] == 'S':
self.y+=1
if self.map['wind']['towards'] == 'W':
self.x-=1
elif self.map['wind']['frequency'] == 'random':
amount = int(random.random()*4)+1
if self.moves % amount == 0:
if self.map['wind']['towards'] == 'N':
self.y-=1
if self.map['wind']['towards'] == 'E':
self.x+=1
if self.map['wind']['towards'] == 'S':
self.y+=1
if self.map['wind']['towards'] == 'W':
self.x-=1
if self.finished == True:
self.status = "Finished"
@ -96,6 +110,12 @@ class Drone:
self.moves+=1
self.get_state()
def hover(self):
if self.can_move():
self.moves+=1
self.fuel -= 1
self.get_state()
def move_up(self):
if self.can_move():
self.z += 1

1
manager.py

@ -46,6 +46,7 @@ def complete_level(map_number, map_name, code_lines):
def home():
validate_session()
levels = app.maps
print session['levels_complete']
return render_template('dashboard.html', levels=levels, complete_levels=complete_levels, num_levels=len(levels), num_completed_levels=len(complete_levels))
@app.route('/level/<map_number>')

44
maps.json

@ -7,11 +7,12 @@
"start": [4,3,0,90],
"size": [10,10],
"fuel": 8,
"wind": { "towards": "N", "frequency": 1},
"wind": { "towards": "N", "frequency": 10},
"ammo": 0,
"finish_items": [],
"items": [
]
],
"drone_visible": true
},
{
"name": "Obstacles!",
@ -25,7 +26,8 @@
"ammo": 0,
"finish_items": [],
"items": [
]
],
"drone_visible": true
},
{
"name": "Recovery Position",
@ -41,7 +43,38 @@
"items": [
{ "name": "crate", "location": [9,8,0] },
{ "name": "crashed UAV", "location": [2,11,0] }
]
],
"drone_visible": true
},
{
"name": "Which way to go?",
"description": "Your positional sensors have been destroyed! Blindly make your way to the finish.",
"obstacles": [],
"finish": [8,4,0],
"fuel": 35,
"wind": { "towards": "N", "frequency": 100},
"start": [17,14,0,90],
"size": [20,20],
"ammo": 0,
"finish_items": [],
"items": [
],
"drone_visible": false
},
{
"name": "If and while",
"description": "No tricks - just get to the finish ;)",
"obstacles": [],
"finish": [15,18,0],
"fuel": 35,
"wind": { "towards": "E", "frequency": "random"},
"start": [4,3,0,0],
"size": [20,20],
"ammo": 0,
"finish_items": [],
"items": [
],
"drone_visible": true
},
{
"name": "Frugal Droning",
@ -57,6 +90,7 @@
"items": [
{ "name": "fuel (7)", "location": [17,2,0] },
{ "name": "fuel (10)", "location": [10,19,0] }
]
],
"drone_visible": true
}
]

66
templates/level.html

@ -41,12 +41,14 @@ drone = Drone(maps[{{level['id']-1}}])
<div class="half">
<h2>Mission information</h2>
<p id="map_desc"></p>
<h3>Starting position</h3>
<p>The drone starts at position (<span id="drone_start"></span>) facing <span id="drone_start_angle"></span>.</p>
<div id="starting_info">
<h3>Starting position</h3>
<p>The drone starts at position (<span id="drone_start"></span>) facing <span id="drone_start_angle"></span>.</p>
</div>
<h3>Finish position</h3>
<p>Get the drone to position (<span id="drone_finish"></span>) to finish.
<h3>Wind</h3>
<p>Wind will blow to <span id="wind_direction"></span> every <span id="wind_frequency"></span> Drone move(s).
<p>Wind will blow to <span id="wind_direction"></span> <span id="wind_frequency"></span>.
<div id="available_items_info">
<h3>Items available</h3>
<p>The following items can be collected:</p>
@ -64,7 +66,7 @@ drone = Drone(maps[{{level['id']-1}}])
{% endblock %}
{% block scripts %}
<script>
var obstacles, items, finish_items, finish_tile, start_tile, map_size, drone, tile_width, tile_height, selected_cell, map_desc, wind;
var obstacles, items, finish_items, finish_tile, start_tile, map_size, drone, tile_width, tile_height, selected_cell, map_desc, wind, map;
function Drone(x,y,z,a,fuel){
this.x = x;
@ -117,8 +119,17 @@ drone = Drone(maps[{{level['id']-1}}])
}
function draw_ui(){
$("#drone_start").html(start_tile[0]+","+start_tile[1]+","+start_tile[2]);
$("#drone_start_angle").html(start_tile[3]+"&deg; from North");
if(map.drone_visible == true){
$("#drone_start").html(start_tile[0]+","+start_tile[1]+","+start_tile[2]);
$("#drone_start_angle").html(start_tile[3]+"&deg; from North");
}
if(finish_items.length == 0){
$("#finish_items_info").css({'display':'none'});
}
if(items.length == 0){
$("#available_items_info").css({'display':'none'});
}
$("#drone_finish").html(finish_tile[0]+","+finish_tile[1]+","+finish_tile[2]);
for(var i = 0; i < items.length; i++){
var item = items[i];
@ -142,7 +153,7 @@ drone = Drone(maps[{{level['id']-1}}])
var t = '<div data-obstacles="'+obstacles_here.join()+'"data-x="'+(i+1)+'" data-y="'+(j+1)+'" style="width:'+tile_width+'%;height:'+tile_height+'%;left:'+(tile_width*i)+'%;top:'+(tile_height*j)+'%;" class="tile';
if(obstacles_here.length > 0){t = t+' obstacle ';}
if(finish_tile[0]==(i+1) && finish_tile[1]==(j+1)){t = t+' finish ';}
if(start_tile[0]==(i+1) && start_tile[1]==(j+1)){t = t+' spawn ';}
if(start_tile[0]==(i+1) && start_tile[1]==(j+1) && map.drone_visible == true){t = t+' spawn ';}
t = t+'"></div';
$("#map").append(t);
}
@ -167,10 +178,32 @@ drone = Drone(maps[{{level['id']-1}}])
$("#map_desc").html(map_desc);
$("#wind_direction").html(wind.towards);
$("#wind_frequency").html(wind.frequency);
if(wind.frequency == "random"){
$("#wind_frequency").html("randomly");
}else{
$("#wind_frequency").html(wind.frequency+" every Drone move(s)");
}
}
function draw_drone(){
$("#current_fuel").html(drone.fuel);
$("#current_inventory").html('');
for(var i = 0; i < drone.inventory.length; i++){
$("#current_inventory").append('<li>'+drone.inventory[i]+'</li>');
}
if(drone.inventory.length == 0){$("#current_inventory").html('Empty');}
$("#status").removeClass("green").removeClass("red").addClass(drone.status);
$("#status_label").html(drone.status_label);
// If invisible drone, show no more:
if(map.drone_visible == false){
$("p.position").css({'display':'none'});
$("p.altitude").css({'display':'none'});
$("p.bearing").css({'display':'none'});
$("#altimeter .current_level").css({'display':'none'});
$("#starting_info").css({'display':'none'});
$("#cell_info").css({'display':'none'});
return;
}
$("#drone").removeClass("crashed");
$("#drone").animate({width:tile_width+'%',height:tile_height+'%',left:(tile_width*(drone.x-1))+'%',top:(tile_height*(drone.y-1))+'%'},400, function(){
if(drone.status_label == "Crashed"){
@ -181,29 +214,16 @@ drone = Drone(maps[{{level['id']-1}}])
$("#altimeter .current_level").animate({'top':(9*(9-drone.z))+'%'},500, "easeOutBounce");
$("#current_position").html(drone.x+','+drone.y);
$("#current_fuel").html(drone.fuel);
$("#current_altitude").html(drone.z);
$("#current_bearing").html(drone.a+'&deg; from North');
$("#current_inventory").html('');
for(var i = 0; i < drone.inventory.length; i++){
$("#current_inventory").append('<li>'+drone.inventory[i]+'</li>');
}
if(drone.inventory.length == 0){$("#current_inventory").html('Empty');}
$("#status").removeClass("green").removeClass("red").addClass(drone.status);
$("#status_label").html(drone.status_label);
if(finish_items.length == 0){
$("#finish_items_info").css({'display':'none'});
}
if(items.length == 0){
$("#available_items_info").css({'display':'none'});
}
analyse_cell(selected_cell);
}
function get_map(map_id){
$.get("/level/"+map_id+"/json", function(data){
data = JSON.parse(data);
map = data;
console.log(data);
obstacles = data.obstacles
items = data.items;

Loading…
Cancel
Save