COMP1511 17s1 Introduction to Programming

Objectives

In this Lab, you will practice:

Preparation

Before the lab you should re-read the relevant lecture slides and their accompanying examples. You should also have read the lab assessment guidelines.

Getting Started

One member of your programming pair should login and run the following commands inside a Linux terminal

Create a new directory for this lab called lab10 by typing:

mkdir lab10
Change to this directory by typing:
cd lab10

Introduction

In this week's lab you will write functions useful for assignment 2.

You can use these functions for the assignment (make sure you include a comment acknowledging your lab partner's contribution). Solutions for these functions will also be made available after the lab deadline and you are permitted to use these for the assignment (again with a comment indicating the authorship of the functions).

First download a copy of trader_bot.h and read through carefuly the types used to represent the Trader Bot world.

Exercise: Printing the World

Create a file named print_world.c which includes trader_bot.h and defines a function with exactly this prototype:

void print_world(struct bot *b);

print_world should print a description of all locations in the bot's world in the format below.

You should start by printing the bot's location and then print locations going in a forward direction (following next pointers).

Do not add a main function to print_world.c.

test_print_world0.c can be used to test your print_world function. The main function in test_print_world0.c creates structures representing a tiny Trader Bot world with only 6 locations, 1 commodity and 1 bot. It links the structures together with pointers and then calls print_world with a pointer to the structure representing the bot.

 dcc print_world.c test_print_world0.c -o print_world0
./print_world0
CSE: start
Samsung: will sell 18291 units of Mobiles for $220
Dump: dump
Coogee Beach: other
Shell: Petrol station 639 units of available fuel for $76
J&B Hifi: will buy 6375 units of Mobiles for $400
The file test_print_world1.c has a main function which creates structures representing a Trader Bot world with more locations and commodities and then calls print_world.
dcc print_world.c test_print_world1.c -o print_world1
./print_world1
Quadrangle: other
Harvey-Norman: will buy 1015 units of Books for $977
Physics Lawn: other
Aldi: will buy 3778 units of Televisions for $255
MSY: will buy 166 units of Computers for $3117
J&B Hifi: will buy 176 units of Computers for $3262
Batch Brewing: will sell 6433 units of Beer for $92
4 Pines: will sell 11933 units of Beer for $91
Good Guys: will buy 826 units of Books for $1305
LG: will sell 905 units of Books for $616
Apple: will sell 434 units of Computers for $2116
Sony: will sell 313 units of Books for $1100
Prentice-Hall: will sell 5340 units of Mars Bars for $149
O'Reilly: will sell 8382 units of Mars Bars for $100
Regent Hotel: will buy 4285 units of Beer for $121
Coles: will buy 2409 units of Televisions for $292
James Squires: will sell 7547 units of Beer for $106
Addison-Wesley: will sell 6064 units of Mars Bars for $215
Dell: will sell 107 units of Computers for $1953
Caltex: Petrol station 477 units of available fuel for $151
Racecourse: other
Umart: will buy 318 units of Computers for $2739
Dump: dump
CSE: start
BP: Petrol station 318 units of available fuel for $194
Mars: will sell 2997 units of Televisions for $130
Whitehouse: will buy 4623 units of Beer for $158
Lenovo: will sell 356 units of Computers for $1600
IGA UNSW: will buy 2768 units of Televisions for $362
UNSW Bookshop: will buy 2376 units of Mars Bars for $224
As usual autotest is available to help you test your program.
 ~cs1511/bin/autotest lab10 print_world.c
Sample solution for print_world.c
#include <stdio.h>
#include "trader_bot.h"

// print details of all locations in the Trader Bot world
// starting from bot's current location and going forwards
void print_world(struct bot *b) {

    struct location *bot_location = b->location;
    int n_printed = 0; // sentinal variable for loop

    // locations are linked in a circular list
    struct location *l =  bot_location;
    while (n_printed == 0 || l != bot_location) {
        printf("%s: ", l->name);
        if (l->type == LOCATION_START) {
            printf("start\n");
        } else if (l->type == LOCATION_BUYER) {
            printf("will buy %d units of %s for $%d\n" , l->quantity, l->commodity->name, l->price);
        } else if (l->type == LOCATION_SELLER) {
            printf("will sell %d units of %s for $%d\n" , l->quantity, l->commodity->name, l->price);
        } else if (l->type == LOCATION_PETROL_STATION) {
            printf("Petrol station %d units of available fuel for $%d\n", l->quantity, l->price);
        } else if (l->type == LOCATION_DUMP) {
            printf("dump\n");
        } else if (l->type == LOCATION_OTHER) {
            printf("other\n");
        }
        l = l->next;
        n_printed++;
    }
}

Exercise: Distance to the Nearest Petrol Station

Create a file named nearest_fuel.c which defines a function with exactly this prototype:
int nearest_fuel(struct bot *b);
nearest_fuel should return the distance to the nearest Petrol Station.

If the nearest Petrol Station is backwards, it should return a negative number.

If its current location is a petrol station it should return 0.

You can assume the world contains a Petrol Station - every trader Bot world contains at least one Petrol Station.

If 2 Petrol stations are equally close (forwards and backwards), you may return either a positive or negative number. As usual autotest is available to help you test your program.

 ~cs1511/bin/autotest lab10 nearest_fuel.c
Sample solution for nearest_fuel.c
#include <stdio.h>
#include "trader_bot.h"
#include "assert.h"

// return distance to nearest fuel station
// if nearest fuel station is backwards return negative int
// if nearest fuel is current location return 0

int nearest_fuel(struct bot *b) {

    // locations are linked in a circular list
    // move a pointer forwards around list
    // and move a pointer backwards around the list
    // stop when either reaches a PETROL_STATION

    struct location *start = b->location;
    struct location *forwards = b->location;
    struct location *backwards = b->location;
    int distance = 0;
    while (distance == 0 || forwards != start) {
        if (forwards->type == LOCATION_PETROL_STATION) {
            return distance;
        }
        if (backwards->type == LOCATION_PETROL_STATION) {
            return -distance;
        }
        forwards = forwards->next;
        backwards = backwards->previous;
        distance++;
    }

    // we should never reach here
    // there should be a petrol station in every world
    assert(0);
}

Exercise: Fuel Bot

Create a file named fuel_bot.c which defines a simple bot. A bot must include functions with these prototype:
char *get_bot_name(void);
void get_action(struct bot *b, int *action, int *n);
The get_bot_name should just return the bot's name, e.g:
char *get_bot_name(void) {
    return "Fuel Bot";
}
get_action is called each turn to get a bot's move.

It is given b, a pointer to the struct representing the current state of the bot (don't change these structs).

It should set *action and *n to appropriate values indicating the bot's move for this turn.

See trader_bot.h for more information.

Your get_action functon should implement a very simple bot which we will call Fuel Bot, with the following behaviour.

Use your nearest_fuel function to simplify the task.

You can use the ~cs1511/bin/bot_test script to generate a random world and run your Fuel Bot in it like this:

 ~cs1511/bin/bot_test fuel_bot.c nearest_fuel.c|more
*** Trader Bot Parameters ***
maximum_cargo_volume=1770245
fuel_tank_capacity=50
maximum_move=8
maximum_cargo_weight=145278
turns_left=14
n_bots=1

*** Turn 0 ***

CSE: start
Shell: Petrol station 37 units of available fuel for $243
J&B Hifi: will buy 225 units of Mobiles for $513
Coogee Beech: other
Dump: dump
Samsung: will sell 360 units of Mobiles for $217

"Fuel Bot" is at CSE with $155398 and 50 fuel: action =  Move 1

*** Turn 1 ***

CSE: start
Shell: Petrol station 37 units of available fuel for $243
J&B Hifi: will buy 225 units of Mobiles for $513
Coogee Beech: other
Dump: dump
Samsung: will sell 360 units of Mobiles for $217

"Fuel Bot" is at Shell with $155398 and 49 fuel: action =  Buy 1

*** Turn 2 ***

CSE: start
Shell: Petrol station 36 units of available fuel for $243
J&B Hifi: will buy 225 units of Mobiles for $513
Coogee Beech: other
Dump: dump
Samsung: will sell 360 units of Mobiles for $217

"Fuel Bot" is at Shell with $155155 and 50 fuel: action =  Move 8

...
If your Fuel Bot seems to working in random worlds, try checking it with autotest:
 ~cs1511/bin/autotest lab10 fuel_bot.c
Sample solution for fuel_bot.c
    #include <stdio.h>
#include "trader_bot.h"

char *get_bot_name(void) {
    return "Fuel Bot";
}

// If not at a Petrol station, should move to the closest Petrol station.
//
// If the closest Petrol station can not be reached in a single move,
// move the maximum permitted distance towards the closest Petrol station.
//
// If  at at a Petrol station, and fuel tank not full, buy exactly enough fuel to fill fuel tank.
//
// If at at a Petrol station, and  fuel tank is  full, move the maximum permitted distance forward.

void get_action(struct bot *b, int *action, int *n) {

    int max_move = b->maximum_move;
    int fuel_distance = nearest_fuel(b);
    int fuel_needed = b->fuel_tank_capacity - b->fuel;

    if (fuel_distance == 0) {
        if (fuel_needed > 0) {
            *action = ACTION_BUY;
            *n = fuel_needed;
        } else {
            // no fuel needed - move forward maximum possible distance
            *action = ACTION_MOVE;
            *n = max_move;
        }
    } else {
        *action = ACTION_MOVE;

        if (fuel_distance > max_move) {
            *n = max_move;
        } else if (fuel_distance < -max_move) {
            *n = max_move;
        } else {
            *n = fuel_distance;
        }
    }
}

Challenge Exercises

No challenge exercises this week (maximum grade your tutor will award is A)

Submission/Assessment

When you are satisfied with your work, ask your tutor to assess it. You also need to submit your work electronically by typing (run this command in the lab10 directory):
give cs1511 lab10 print_world.c nearest_fuel.c fuel_bot.c
Submit the challenge exercises only if you attempt them.

If you are working at home, you may find it more convenient to upload your work via give's web interface.

Remember the lab assessment guidelines - if you don't finish the exercises you can finish them in your own time, submit them by Monday 11:00am using give and ask your tutor to assess them at the start of the following lab.

Either or both members of a programming pair can submit the work (make sure each program lists both of you as authors in the header comment).