Commits

Mort Yao committed d3651eb

initial commit

Comments (0)

Files changed (22)

+lifter
Empty file added.
+(・U・)
+
+Mort Yao
+#!/bin/sh
+(cd src; make)
+exit 0
+
+SOURCES=main.c io.c simulator.c datatypes/metadata.c datatypes/matrix.c datatypes/status.c datatypes/cell.c core/british_museum.c core/bb.c
+HEADERS=lifter.h io.h simulator.h datatypes/metadata.h datatypes/matrix.h datatypes/status.h datatypes/cell.h core.h
+PRODUCT=../lifter
+CC=gcc
+CFLAGS=-std=c99 -static
+
+all: $(PRODUCT)
+
+$(PRODUCT): $(SOURCES) $(HEADERS)
+	$(CC) $(CFLAGS) -o $(PRODUCT) $(SOURCES)
+
+.PHONY: clean
+clean:
+	rm -f *.o ${PRODUCT}
+#ifndef LIFTER_CORE
+#define LIFTER_CORE
+
+#include "datatypes/metadata.h"
+#include "datatypes/matrix.h"
+#include "datatypes/status.h"
+
+int core_british_museum(char *solution, Metadata, Matrix, Status, int time_limit);
+
+int core_bb(char *solution, Metadata, Matrix, Status, int time_limit);
+
+#endif /* LIFTER_CORE */
+#include <string.h>
+#include <time.h>
+
+#include "../core.h"
+#include "../simulator.h"
+
+typedef struct node {
+    char *str;
+    struct node *next;
+} Queue;
+
+int core_bb(char *solution, Metadata env, Matrix map, Status stat, int time_limit)
+{
+    int full_score = 75 * env.lambdas;
+    
+    int best_score = 0;
+    char *best_solution = malloc((map.width * map.height) * sizeof(char));
+    memset(best_solution, 0, strlen(best_solution));
+    
+    int score = 0;
+    char *attempt = malloc((map.width * map.height) * sizeof(char));
+    memset(attempt, 0, strlen(attempt));
+    
+    Matrix *newMap;
+    Status *newStat;
+    
+    Queue *head = malloc(1 * sizeof(Queue));
+    Queue *tail = head;
+    
+    head->str = malloc((map.width * map.height) * sizeof(char));
+    strcpy(head->str, "");
+    head->next = NULL;
+    
+    while (head != NULL && clock() / CLOCKS_PER_SEC < time_limit) {
+        
+        strcpy(attempt, head->str);
+        strcat(attempt, "A");
+        
+        newMap = cloneMatrix(map);
+        newStat = cloneStatus(stat);
+        score = simulateRobot(attempt, env, map, stat, &newMap, &newStat);
+        
+        if (score > best_score) {
+            best_score = score;
+            
+            if (newStat->report == MISSION_ABORTED)
+                strcpy(best_solution, attempt);
+            else
+                strcpy(best_solution, head->str);
+        }
+        
+        if (newStat->report != MISSION_COMPLETED
+            && newStat->report != MISSION_FAILED) {
+            
+            if (isMoveValid('R', env, *newMap, *newStat)) {
+                strcpy(attempt, head->str);
+                strcat(attempt, "R");
+                tail = tail->next = malloc(1 * sizeof(Queue));
+                if (tail == NULL) break;
+                tail->str = malloc((map.width * map.height) * sizeof(char));
+                if (tail->str == NULL) break;
+                strcpy(tail->str, attempt);
+                tail->next = NULL;
+            }
+            
+            if (isMoveValid('L', env, *newMap, *newStat)) {
+                strcpy(attempt, head->str);
+                strcat(attempt, "L");
+                tail = tail->next = malloc(1 * sizeof(Queue));
+                if (tail == NULL) break;
+                tail->str = malloc((map.width * map.height) * sizeof(char));
+                if (tail->str == NULL) break;
+                strcpy(tail->str, attempt);
+                tail->next = NULL;
+            }
+            
+            if (isMoveValid('D', env, *newMap, *newStat)) {
+                strcpy(attempt, head->str);
+                strcat(attempt, "D");
+                tail = tail->next = malloc(1 * sizeof(Queue));
+                if (tail == NULL) break;
+                tail->str = malloc((map.width * map.height) * sizeof(char));
+                if (tail->str == NULL) break;
+                strcpy(tail->str, attempt);
+                tail->next = NULL;
+            }
+            
+            if (isMoveValid('U', env, *newMap, *newStat)) {
+                strcpy(attempt, head->str);
+                strcat(attempt, "U");
+                tail = tail->next = malloc(1 * sizeof(Queue));
+                if (tail == NULL) break;
+                tail->str = malloc((map.width * map.height) * sizeof(char));
+                if (tail->str == NULL) break;
+                strcpy(tail->str, attempt);
+                tail->next = NULL;
+            }
+            
+            if (isMoveValid('S', env, *newMap, *newStat)) {
+                strcpy(attempt, head->str);
+                strcat(attempt, "S");
+                tail = tail->next = malloc(1 * sizeof(Queue));
+                if (tail == NULL) break;
+                tail->str = malloc((map.width * map.height) * sizeof(char));
+                if (tail->str == NULL) break;
+                strcpy(tail->str, attempt);
+                tail->next = NULL;
+            }
+            
+            /*
+            strcpy(attempt, head->str);
+            strcat(attempt, "W");
+            tail = tail->next = malloc(1 * sizeof(Queue));
+            if (tail == NULL) break;
+            tail->str = malloc((map.width * map.height) * sizeof(char));
+            if (tail->str == NULL) break;
+            strcpy(tail->str, attempt);
+            tail->next = NULL;
+            */
+            
+        }
+        
+        Queue *temp = head->next;
+        free(head->str);
+        free(head);
+        head = temp;
+        
+        destructMatrix(*newMap);
+        free(newMap);
+        free(newStat);
+        
+        if (best_score == full_score - strlen(head->str))
+            break;
+    }
+    
+    while (head != NULL) {
+        Queue *temp = head->next;
+        free(head->str);
+        free(head);
+        head = temp;
+    }
+    
+    free(attempt);
+    
+    strcpy(solution, best_solution);
+    free(best_solution);
+    
+    return best_score;
+}

src/core/british_museum.c

+#include <string.h>
+#include <time.h>
+
+#include "../core.h"
+#include "../simulator.h"
+
+int core_british_museum(char *solution, Metadata env, Matrix map, Status stat, int time_limit)
+{
+    int full_score = 75 * env.lambdas;
+    
+    int best_score = 0;
+    char *best_solution = malloc((map.width * map.height) * sizeof(char));
+    memset(best_solution, 0, strlen(best_solution));
+    
+    int score = 0;
+    char *attempt = malloc((map.width * map.height) * sizeof(char));
+    memset(attempt, 0, strlen(attempt));
+    
+    int digits = 0;
+    while (++digits > 0 && clock() / CLOCKS_PER_SEC < time_limit) {
+        int d = 0, temp;
+        do {
+            memset(attempt, 0, strlen(attempt));
+            memset(attempt, 'R', digits);
+            
+            temp = d;
+            for (int i = 0; temp && i < digits; i++) {
+                switch (temp % 6) {
+                    case 0:
+                        attempt[i] = 'R'; break;
+                    case 1:
+                        attempt[i] = 'L'; break;
+                    case 2:
+                        attempt[i] = 'D'; break;
+                    case 3:
+                        attempt[i] = 'U'; break;
+                    case 4:
+                        attempt[i] = 'S'; break;
+                    case 5:
+                        attempt[i] = 'W'; break;
+                }
+                temp /= 6;
+            }
+            
+            if (temp)
+                break;
+            
+            score = simulate(attempt, env, map, stat, false);
+            if (score > best_score) {
+                best_score = score;
+                strcpy(best_solution, attempt);
+            }
+            
+            strcat(attempt, "A");
+            score = simulate(attempt, env, map, stat, false);
+            if (score > best_score) {
+                best_score = score;
+                strcpy(best_solution, attempt);
+            }
+            
+            if (best_score == full_score - digits)
+                break;
+        } while (++d > 0 && clock() / CLOCKS_PER_SEC < time_limit);
+        
+        if (best_score == full_score - digits)
+            break;
+    }
+    
+    free(attempt);
+    
+    strcpy(solution, best_solution);
+    free(best_solution);
+    
+    return best_score;
+}

src/datatypes/cell.c

+#include <stdlib.h>
+
+#include "cell.h"
+#include "matrix.h"
+#include "../lifter.h"
+
+char *cell(Matrix m, int x, int y)
+{
+    return &m.elem[m.height - y][x - 1];
+}
+
+Cells *getCells(Matrix m, char ch)
+{
+    int size = 0;
+    Cells *c = malloc(1 * sizeof(Cells));
+    c->size = size;
+    c->elem = NULL;
+    
+    for (int i = 0; i < m.height; i++)
+        for (int j = 0; j < m.width; j++)
+            if (m.elem[i][j] == ch) {
+                Cell *p = realloc(c->elem, ++size * sizeof(Cell));
+                if (p == NULL)
+                    ERR_OUT_OF_MEMORY
+                c->elem = p;
+                
+                c->size = size;
+                c->elem[size - 1].x = j + 1;
+                c->elem[size - 1].y = m.height - i;
+            }
+    
+    return c;
+}

src/datatypes/cell.h

+#ifndef DATATYPE_CELL
+#define DATATYPE_CELL
+
+#include "matrix.h"
+
+typedef struct {
+    int x;
+    int y;
+    int val;
+} Cell;
+
+typedef struct {
+    int size;
+    Cell *elem;
+} Cells;
+
+char *cell(Matrix, int x, int y);
+
+Cells *getCells(Matrix, char);
+
+#endif /* DATATYPE_CELL */

src/datatypes/matrix.c

+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "matrix.h"
+#include "../lifter.h"
+
+void printMatrix(Matrix m)
+{
+    for (int i = 0; i < m.height; i++)
+        printf("%s", m.elem[i]);
+    printf("\n");
+    
+    return;
+}
+
+void destructMatrix(Matrix m)
+{
+    for (int i = 0; i < m.height; i++)
+        free(m.elem[i]);
+    free(m.elem);
+    
+    return;
+}
+
+Matrix *cloneMatrix(Matrix m)
+{
+    Matrix *n = malloc(sizeof(Matrix));
+    if (n == NULL)
+        ERR_OUT_OF_MEMORY
+    
+    n->width = m.width;
+    n->height = m.height;
+    n->elem = malloc(m.height * sizeof(char *));
+    if (n->elem == NULL)
+        ERR_OUT_OF_MEMORY
+    
+    for (int i = 0; i < m.height; i++) {
+        n->elem[i] = malloc((m.width + 2) * sizeof(char));
+        if (n->elem[i] == NULL)
+            ERR_OUT_OF_MEMORY
+        
+        strcpy(n->elem[i], m.elem[i]);
+    }
+    
+    return n;
+}

src/datatypes/matrix.h

+#ifndef DATATYPE_MATRIX
+#define DATATYPE_MATRIX
+
+typedef struct {
+    int width, height;
+    char **elem;
+} Matrix;
+
+void printMatrix(Matrix);
+
+void destructMatrix(Matrix);
+
+Matrix *cloneMatrix(Matrix);
+
+#endif /* DATATYPE_MATRIX */

src/datatypes/metadata.c

+#include <stdio.h>
+
+#include "metadata.h"
+
+void printMetadata(Metadata d)
+{
+    printf("Water: %d\n", d.water);
+    printf("Flooding: %d\n", d.flooding);
+    printf("Waterproof: %d\n", d.waterproof);
+    printf("Growth: %d\n", d.growth);
+    printf("Razors: %d\n", d.razors);
+    printf("Lambdas: %d\n", d.lambdas);
+    
+    printf("Trampoline: \n");
+    for (int i = 0; i < 9; i++)
+        if (d.trampoline[i])
+            printf("  %c <- %c\n", d.trampoline[i], 'A' + i);
+    
+    printf("\n");
+    
+    return;
+}

src/datatypes/metadata.h

+#ifndef DATATYPE_METADATA
+#define DATATYPE_METADATA
+
+typedef struct {
+    int water;
+    int flooding;
+    int waterproof;
+    int growth;
+    int razors;
+    int lambdas;
+    char trampoline[10];
+} Metadata;
+
+void printMetadata(Metadata);
+
+#endif /* DATATYPE_METADATA */

src/datatypes/status.c

+#include <stdio.h>
+#include <stdlib.h>
+
+#include "status.h"
+#include "../lifter.h"
+
+void printStatus(Status s)
+{
+    printf("STEP: #%d\n", s.steps);
+    printf("Robot: (%d, %d)\n", s.robot.x, s.robot.y);
+    printf("Razors: %d\n", s.razors);
+    printf("Lambdas: %d\n", s.lambdas);
+    printf("Underwater time: %d\n", s.underwater_time);
+    printf("Report: %d\n", s.report);
+    printf("\n");
+    
+    return;
+}
+
+Status *cloneStatus(Status s)
+{
+    Status *t = malloc(sizeof(Status));
+    if (t == NULL)
+        ERR_OUT_OF_MEMORY
+    
+    t->robot.x = s.robot.x;
+    t->robot.y = s.robot.y;
+    t->razors = s.razors;
+    t->steps = s.steps;
+    t->lambdas = s.lambdas;
+    t->underwater_time = s.underwater_time;
+    t->report = s.report;
+    
+    return t;
+}

src/datatypes/status.h

+#ifndef DATATYPE_STATUS
+#define DATATYPE_STATUS
+
+#include "cell.h"
+#include "../lifter.h"
+
+typedef struct {
+    Cell robot;
+    int razors;
+    int steps;
+    int lambdas;
+    int underwater_time;
+    MISSION_REPORT report;
+} Status;
+
+void printStatus(Status);
+
+Status *cloneStatus(Status);
+
+#endif /* DATATYPE_STATUS */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "io.h"
+#include "lifter.h"
+#include "datatypes/metadata.h"
+#include "datatypes/matrix.h"
+#include "datatypes/status.h"
+#include "datatypes/cell.h"
+
+void readStdIn(Metadata *env, Matrix *map, Status *stat)
+{
+    char temp[MAX_WIDTH];
+    fgets(temp, MAX_WIDTH, stdin);
+    
+    map->height = 0;
+    map->elem = malloc(++map->height * sizeof(char *));
+    if (map->elem == NULL)
+        ERR_OUT_OF_MEMORY
+    
+    map->width = strlen(temp) - 1;
+    map->elem[map->height - 1] = malloc((map->width + 2) * sizeof(char));
+    if (map->elem[map->height - 1] == NULL)
+        ERR_OUT_OF_MEMORY
+    strcpy(map->elem[map->height - 1], temp);
+    
+    fgets(temp, MAX_WIDTH, stdin);
+    
+    while (temp != NULL && temp[0] != '\n') {
+        char **p = realloc(map->elem, ++map->height * sizeof(char *));
+        if (p == NULL)
+            ERR_OUT_OF_MEMORY
+        map->elem = p;
+        
+        if (strlen(temp) - 1 > map->width)
+            map->width = strlen(temp) - 1;
+        map->elem[map->height - 1] = malloc((map->width + 2) * sizeof(char));
+        if (map->elem[map->height - 1] == NULL)
+            ERR_OUT_OF_MEMORY
+        strcpy(map->elem[map->height - 1], temp);
+        
+        if (fgets(temp, MAX_WIDTH, stdin) == NULL)
+            break;
+    }
+    
+    while (fgets(temp, 64, stdin)) {
+        char metadata_n[16] = "", metadata_k = 0, metadata_v = 0;
+        
+        if (sscanf(temp, "Trampoline %c%*s %c", &metadata_k, &metadata_v) != 0)
+            env->trampoline[metadata_k - 'A'] = metadata_v;
+        else if (sscanf(temp, "Water %d", &metadata_v) != 0)
+            env->water = metadata_v;
+        else if (sscanf(temp, "Flooding %d", &metadata_v) != 0)
+            env->flooding = metadata_v;
+        else if (sscanf(temp, "Waterproof %d", &metadata_v) != 0)
+            env->waterproof = metadata_v;
+        else if (sscanf(temp, "Growth %d", &metadata_v) != 0)
+            env->growth = metadata_v;
+        else if (sscanf(temp, "Razors %d", &metadata_v) != 0)
+            env->razors = metadata_v;
+    }
+    
+    Cells *c = getCells(*map, '\\');
+    env->lambdas = c->size;
+    
+    c = getCells(*map, '@');
+    env->lambdas += c->size;
+    
+    c = getCells(*map, 'R');
+    if (c->size != 1)
+        ERR_ILLEGAL_INPUT
+    
+    stat->robot.x = c->elem[0].x;
+    stat->robot.y = c->elem[0].y;
+    stat->razors = env->razors;
+    
+    free(c);
+    
+    return;
+}
+#ifndef LIFTER_IO
+#define LIFTER_IO
+
+#include "datatypes/metadata.h"
+#include "datatypes/matrix.h"
+#include "datatypes/status.h"
+
+void readStdIn(Metadata *, Matrix *, Status *);
+
+#endif /* LIFTER_IO */
+#ifndef LIFTER
+#define LIFTER
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX_WIDTH 10001
+
+#define ERR_OUT_OF_MEMORY { fprintf(stderr, "FATAL ERROR: out of memory\n"); exit(EXIT_FAILURE); }
+#define ERR_ILLEGAL_INPUT { fprintf(stderr, "FATAL ERROR: illegal input\n"); exit(EXIT_FAILURE); }
+
+#define MISSION_REPORT int
+#define MISSION_RUNNING 0
+#define MISSION_COMPLETED 1
+#define MISSION_ABORTED 2
+#define MISSION_FAILED 3
+
+#endif /* LIFTER */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "io.h"
+#include "core.h"
+#include "simulator.h"
+#include "datatypes/metadata.h"
+#include "datatypes/matrix.h"
+#include "datatypes/status.h"
+#include "datatypes/cell.h"
+
+void mapTesting(Metadata env, Matrix map, Status stat)
+{
+    printf("Width: %d\n", map.width);
+    printf("Height: %d\n\n", map.height);
+    printMetadata(env);
+    printf("\n");
+    
+    printf(">> %d\n", simulate("", env, map, stat, true));
+    
+    return;
+}
+
+int main()
+{
+    Metadata env = {0, 0, 10, 25, 0, 0, {}};
+    Matrix map = {0, 0, NULL};
+    Status stat = {{0, 0}, 0, 0, 0, 0, MISSION_RUNNING};
+    
+    readStdIn(&env, &map, &stat);
+    //mapTesting(env, map, stat); // for testing
+    
+    int score;
+    char *solution = malloc((map.width * map.height) * sizeof(char));
+    memset(solution, 0, strlen(solution));
+    
+    score = core_bb(solution, env, map, stat, 140);
+    
+    printf("%s\n", solution);
+    //printf("%d\n", score); // for testing
+    
+    free(solution);
+    
+    destructMatrix(map);
+    
+    return 0;
+}
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "lifter.h"
+#include "simulator.h"
+#include "datatypes/metadata.h"
+#include "datatypes/matrix.h"
+#include "datatypes/status.h"
+#include "datatypes/cell.h"
+
+bool isMoveValid(char command, Metadata env, Matrix map, Status stat)
+{
+    /*
+    if (stat.report != MISSION_RUNNING)
+        return false;
+    */
+    
+    if (command == 'S')
+        return (stat.razors > 0);
+    
+    if (command == 'W' || command == 'A')
+        return true;
+    
+    int x = stat.robot.x;
+    int y = stat.robot.y;
+    if (command == 'L')
+        x = x - 1;
+    else if (command == 'R')
+        x = x + 1;
+    else if (command == 'U')
+        y = y + 1;
+    else if (command == 'D')
+        y = y - 1;
+    else
+        return false;
+    
+    char dest = *cell(map, x, y);
+    
+    if (dest == ' ' || dest == '.' ||
+        dest == '\\' || dest == '!' || dest == 'O')
+        return true;
+    
+    if (dest == '*' && command == 'R'
+        && *cell(map, x + 1, y) == ' ')
+        return true;
+    
+    if (dest == '@' && command == 'R'
+        && *cell(map, x + 1, y) == ' ')
+        return true;
+    
+    if (dest == '*' && command == 'L'
+        && *cell(map, x - 1, y) == ' ')
+        return true;
+    
+    if (dest == '@' && command == 'L'
+        && *cell(map, x - 1, y) == ' ')
+        return true;
+    
+    if (dest >= 'A' && dest <= 'I')
+        return true;
+    
+    return false;
+}
+
+int moveRobot(char command, Metadata env, Matrix oldMap, Status oldStat, Matrix *newMap, Status *newStat)
+{
+    
+    if (oldStat.report != MISSION_RUNNING) {
+        
+        int points = -1 * newStat->steps + 25 * newStat->lambdas;
+        if (newStat->report == MISSION_ABORTED)
+            points += 25 * newStat->lambdas;
+        else if (newStat->report == MISSION_COMPLETED)
+            points += 50 * newStat->lambdas;
+        
+        return points;
+        
+    }
+    
+    if (command == 'L' || command == 'R'
+        || command == 'U' || command == 'D') {
+        
+        int x = oldStat.robot.x;
+        int y = oldStat.robot.y;
+        if (command == 'L')
+            x = x - 1;
+        else if (command == 'R')
+            x = x + 1;
+        else if (command == 'U')
+            y = y + 1;
+        else if (command == 'D')
+            y = y - 1;
+        
+        if (x >= 1 && x <= oldMap.width
+            && y >= 1 && y <= oldMap.height) {
+            
+            char dest = *cell(oldMap, x, y);
+            
+            if (dest == ' ' || dest == '.'
+                || dest == '\\' || dest == '!' || dest == 'O') {
+                
+                newStat->robot.x = x;
+                newStat->robot.y = y;
+                
+                *cell(*newMap, oldStat.robot.x, oldStat.robot.y) = ' ';
+                *cell(*newMap, newStat->robot.x, newStat->robot.y) = 'R';
+                
+                if (dest == '\\')
+                    newStat->lambdas++;
+                
+                if (dest == '!')
+                    newStat->razors++;
+                
+                if (dest == 'O')
+                    newStat->report = MISSION_COMPLETED;
+                
+            } else if (dest == '*' && command == 'R'
+                && x + 1 <= oldMap.width
+                &&*cell(oldMap, x + 1, y) == ' ') {
+                
+                newStat->robot.x = x;
+                newStat->robot.y = y;
+                
+                *cell(*newMap, oldStat.robot.x, oldStat.robot.y) = ' ';
+                *cell(*newMap, newStat->robot.x, newStat->robot.y) = 'R';
+                *cell(*newMap, newStat->robot.x + 1, newStat->robot.y) = '*';
+                
+            } else if (dest == '@' && command == 'R'
+                && x + 1 <= oldMap.width
+                &&*cell(oldMap, x + 1, y) == ' ') {
+                
+                newStat->robot.x = x;
+                newStat->robot.y = y;
+                
+                *cell(*newMap, oldStat.robot.x, oldStat.robot.y) = ' ';
+                *cell(*newMap, newStat->robot.x, newStat->robot.y) = 'R';
+                *cell(*newMap, newStat->robot.x + 1, newStat->robot.y) = '@';
+                
+            } else if (dest == '*' && command == 'L'
+                && x - 1 >= 1
+                && *cell(oldMap, x - 1, y) == ' ') {
+                
+                newStat->robot.x = x;
+                newStat->robot.y = y;
+                
+                *cell(*newMap, oldStat.robot.x, oldStat.robot.y) = ' ';
+                *cell(*newMap, newStat->robot.x, newStat->robot.y) = 'R';
+                *cell(*newMap, newStat->robot.x - 1, newStat->robot.y) = '*';
+                
+            } else if (dest == '@' && command == 'L'
+                && x - 1 >= 1
+                && *cell(oldMap, x - 1, y) == ' ') {
+                
+                newStat->robot.x = x;
+                newStat->robot.y = y;
+                
+                *cell(*newMap, oldStat.robot.x, oldStat.robot.y) = ' ';
+                *cell(*newMap, newStat->robot.x, newStat->robot.y) = 'R';
+                *cell(*newMap, newStat->robot.x - 1, newStat->robot.y) = '@';
+                
+            } else if (dest >= 'A' && dest <= 'I') {
+                
+                newStat->robot.x = x;
+                newStat->robot.y = y;
+                
+                *cell(*newMap, oldStat.robot.x, oldStat.robot.y) = ' ';
+                *cell(*newMap, newStat->robot.x, newStat->robot.y) = ' ';
+                
+                Cells *c = getCells(*newMap, env.trampoline[dest - 'A']);
+                if (c->size != 1)
+                    ERR_ILLEGAL_INPUT
+                
+                newStat->robot.x = c->elem[0].x;
+                newStat->robot.y = c->elem[0].y;
+                *cell(*newMap, newStat->robot.x, newStat->robot.y) = 'R';
+                
+            } else { // wait
+                ;
+            }
+            
+        } else { // wait
+            ;
+        }
+        
+    } else if (command == 'S' && oldStat.razors > 0) {
+        
+        int x = oldStat.robot.x;
+        int y = oldStat.robot.y;
+        
+        if (x - 1 > 0 && y - 1 > 0) {
+            if (*cell(*newMap, x - 1, y - 1) == 'W')
+                *cell(*newMap, x - 1, y - 1) = ' ';
+        }
+        if (y - 1 > 0) {
+            if (*cell(*newMap, x, y - 1) == 'W')
+                *cell(*newMap, x, y - 1) = ' ';
+        }
+        if (y - 1 > 0 && x + 1 <= oldMap.width) {
+            if (*cell(*newMap, x + 1, y - 1) == 'W')
+                *cell(*newMap, x + 1, y - 1) = ' ';
+        }
+        if (x - 1 > 0) {
+            if (*cell(*newMap, x - 1, y) == 'W')
+                *cell(*newMap, x - 1, y) = ' ';
+        }
+        if (x + 1 <= oldMap.width) {
+            if (*cell(*newMap, x + 1, y) == 'W')
+                *cell(*newMap, x + 1, y) = ' ';
+        }
+        if (x - 1 > 0 && y + 1 <= oldMap.height) {
+            if (*cell(*newMap, x - 1, y + 1) == 'W')
+                *cell(*newMap, x - 1, y + 1) = ' ';
+        }
+        if (y + 1 <= oldMap.height) {
+            if (*cell(*newMap, x, y + 1) == 'W')
+                *cell(*newMap, x, y + 1) = ' ';
+        }
+        if (y + 1 <= oldMap.height && x + 1 <= oldMap.width) {
+            if (*cell(*newMap, x + 1, y + 1) == 'W')
+                *cell(*newMap, x + 1, y + 1) = ' ';
+        }
+        
+        newStat->razors--;
+        
+    } else if (command == 'A') {
+        
+        newStat->report = MISSION_ABORTED;
+        
+    } else { // wait
+        ;
+    }
+    
+    
+    
+    if (newStat->report == MISSION_ABORTED) {
+        
+        int points = -1 * newStat->steps + 25 * newStat->lambdas;
+        if (newStat->report == MISSION_ABORTED)
+            points += 25 * newStat->lambdas;
+        else if (newStat->report == MISSION_COMPLETED)
+            points += 50 * newStat->lambdas;
+        
+        return points;
+        
+    } else if (newStat->report == MISSION_COMPLETED) {
+        
+        newStat->steps++;
+        
+        int points = -1 * newStat->steps + 25 * newStat->lambdas;
+        if (newStat->report == MISSION_ABORTED)
+            points += 25 * newStat->lambdas;
+        else if (newStat->report == MISSION_COMPLETED)
+            points += 50 * newStat->lambdas;
+        
+        return points;
+        
+    } else if (newStat->report == MISSION_RUNNING) {
+        
+        newStat->steps++;
+        
+    }
+    
+    
+    
+    for (int y = 1; y <= newMap->height; y++) {
+        for (int x = 1; x <= newMap->width; x++) {
+            
+            if (*cell(oldMap, x, y) == '*'
+                && y - 1 >= 1
+                && *cell(oldMap, x, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x, y - 1) = '*';
+                
+            } else if (*cell(oldMap, x, y) == '@'
+                && y - 1 >= 1
+                && *cell(oldMap, x, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x, y - 1) = '@';
+                
+                if (y - 2 >= 1
+                    && *cell(oldMap, x, y - 2) != ' ')
+                    *cell(*newMap, x, y - 1) = '\\';
+                
+            } else if (*cell(oldMap, x, y) == '*'
+                && y - 1 >= 1
+                && (*cell(oldMap, x, y - 1) == '*' || *cell(oldMap, x, y - 1) == '@')
+                && x + 1 <= oldMap.width
+                && *cell(oldMap, x + 1, y) == ' '
+                && *cell(oldMap, x + 1, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x + 1, y - 1) = '*';
+                
+            } else if (*cell(oldMap, x, y) == '@'
+                && y - 1 >= 1
+                && (*cell(oldMap, x, y - 1) == '*' || *cell(oldMap, x, y - 1) == '@')
+                && x + 1 <= oldMap.width
+                && *cell(oldMap, x + 1, y) == ' '
+                && *cell(oldMap, x + 1, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x + 1, y - 1) = '@';
+                
+                if (y - 2 >= 1
+                    && *cell(oldMap, x + 1, y - 2) != ' ')
+                    *cell(*newMap, x + 1, y - 1) = '\\';
+                
+            } else if (*cell(oldMap, x, y) == '*'
+                && y - 1 >= 1
+                && (*cell(oldMap, x, y - 1) == '*' || *cell(oldMap, x, y - 1) == '@')
+                && x + 1 <= oldMap.width
+                && (*cell(oldMap, x + 1, y) != ' ' || *cell(oldMap, x + 1, y - 1) != ' ')
+                && x - 1 >= 1
+                && *cell(oldMap, x - 1, y) == ' '
+                && *cell(oldMap, x - 1, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x - 1, y - 1) = '*';
+                
+            } else if (*cell(oldMap, x, y) == '@'
+                && y - 1 >= 1
+                && (*cell(oldMap, x, y - 1) == '*' || *cell(oldMap, x, y - 1) == '@')
+                && x + 1 <= oldMap.width
+                && (*cell(oldMap, x + 1, y) != ' ' || *cell(oldMap, x + 1, y - 1) != ' ')
+                && x - 1 >= 1
+                && *cell(oldMap, x - 1, y) == ' '
+                && *cell(oldMap, x - 1, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x - 1, y - 1) = '@';
+                
+                if (y - 2 >= 1
+                    && *cell(oldMap, x - 1, y - 2) != ' ')
+                    *cell(*newMap, x - 1, y - 1) = '\\';
+                
+            } else if (*cell(oldMap, x, y) == '*'
+                && y - 1 >= 1
+                && *cell(oldMap, x, y - 1) == '\\'
+                && x + 1 <= oldMap.width
+                && *cell(oldMap, x + 1, y) == ' '
+                && *cell(oldMap, x + 1, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x + 1, y - 1) = '*';
+                
+            } else if (*cell(oldMap, x, y) == '@'
+                && y - 1 >= 1
+                && *cell(oldMap, x, y - 1) == '\\'
+                && x + 1 <= oldMap.width
+                && *cell(oldMap, x + 1, y) == ' '
+                && *cell(oldMap, x + 1, y - 1) == ' ') {
+                
+                *cell(*newMap, x, y) = ' ';
+                *cell(*newMap, x + 1, y - 1) = '@';
+                
+                if (y - 2 >= 1
+                    && *cell(oldMap, x + 1, y - 2) != ' ')
+                    *cell(*newMap, x + 1, y - 1) = '\\';
+                
+            } else if (*cell(oldMap, x, y) == 'L'
+                && oldStat.lambdas == env.lambdas) {
+                
+                *cell(*newMap, x, y) = 'O';
+                
+            } else if (*cell(oldMap, x, y) == 'W') {
+                
+                if ((oldStat.steps + 1) % env.growth == 0) {
+                    
+                    if (x - 1 > 0 && y - 1 > 0) {
+                        if (*cell(*newMap, x - 1, y - 1) == ' ')
+                            *cell(*newMap, x - 1, y - 1) = 'W';
+                    }
+                    if (y - 1 > 0) {
+                        if (*cell(*newMap, x, y - 1) == ' ')
+                            *cell(*newMap, x, y - 1) = 'W';
+                    }
+                    if (y - 1 > 0 && x + 1 <= oldMap.width) {
+                        if (*cell(*newMap, x + 1, y - 1) == ' ')
+                            *cell(*newMap, x + 1, y - 1) = 'W';
+                    }
+                    if (x - 1 > 0) {
+                        if (*cell(*newMap, x - 1, y) == ' ')
+                            *cell(*newMap, x - 1, y) = 'W';
+                    }
+                    if (x + 1 <= oldMap.width) {
+                        if (*cell(*newMap, x + 1, y) == ' ')
+                            *cell(*newMap, x + 1, y) = 'W';
+                    }
+                    if (x - 1 > 0 && y + 1 <= oldMap.height) {
+                        if (*cell(*newMap, x - 1, y + 1) == ' ')
+                            *cell(*newMap, x - 1, y + 1) = 'W';
+                    }
+                    if (y + 1 <= oldMap.height) {
+                        if (*cell(*newMap, x, y + 1) == ' ')
+                            *cell(*newMap, x, y + 1) = 'W';
+                    }
+                    if (y + 1 <= oldMap.height && x + 1 <= oldMap.width) {
+                        if (*cell(*newMap, x + 1, y + 1) == ' ')
+                            *cell(*newMap, x + 1, y + 1) = 'W';
+                    }
+                    
+                }
+                
+            } else { // unchanged
+                ;
+            }
+            
+        }
+    }
+    
+    if (newStat->robot.y + 1 <= oldMap.height
+        && (*cell(*newMap, newStat->robot.x, newStat->robot.y + 1) == '*'
+        || *cell(*newMap, newStat->robot.x, newStat->robot.y + 1) == '@')
+        && *cell(oldMap, newStat->robot.x, newStat->robot.y + 1) == ' ') {
+        
+        newStat->report = MISSION_FAILED;
+        
+        int points = -1 * newStat->steps + 25 * newStat->lambdas;
+        if (newStat->report == MISSION_ABORTED)
+            points += 25 * newStat->lambdas;
+        else if (newStat->report == MISSION_COMPLETED)
+            points += 50 * newStat->lambdas;
+        
+        return points;
+        
+    }
+    
+    if (env.flooding) {
+        int water_level = env.water + newStat->steps / env.flooding;
+        if (newStat->robot.y <= water_level) {
+            
+            newStat->underwater_time++;
+            if (newStat->underwater_time > env.waterproof) {
+                
+                newStat->report = MISSION_FAILED;
+                
+                int points = -1 * newStat->steps + 25 * newStat->lambdas;
+                if (newStat->report == MISSION_ABORTED)
+                    points += 25 * newStat->lambdas;
+                else if (newStat->report == MISSION_COMPLETED)
+                    points += 50 * newStat->lambdas;
+                
+                return points;
+                
+            }
+            
+        } else {
+            newStat->underwater_time = 0;
+        }
+    }
+    
+    int points = -1 * newStat->steps + 25 * newStat->lambdas;
+    if (newStat->report == MISSION_ABORTED)
+        points += 25 * newStat->lambdas;
+    else if (newStat->report == MISSION_COMPLETED)
+        points += 50 * newStat->lambdas;
+    
+    return points;
+}
+
+int simulate(const char *commands, Metadata env, Matrix initMap, Status initStat, bool doPrint)
+{
+    Matrix *map1 = cloneMatrix(initMap), *map2;
+    Status *stat1 = cloneStatus(initStat), *stat2;
+    
+    if (doPrint) {
+        printMatrix(*map1);
+        printStatus(*stat1);
+        printf("\n");
+    }
+    
+    for (int i = 0; i < strlen(commands) && stat1->report == MISSION_RUNNING; i++) {
+        
+        map2 = cloneMatrix(*map1);
+        stat2 = cloneStatus(*stat1);
+        
+        moveRobot(commands[i], env, *map1, *stat1, map2, stat2);
+        
+        destructMatrix(*map1);
+        free(map1);
+        free(stat1);
+        
+        map1 = cloneMatrix(*map2);
+        stat1 = cloneStatus(*stat2);
+        
+        destructMatrix(*map2);
+        free(map2);
+        free(stat2);
+        
+        if (doPrint) {
+            printMatrix(*map1);
+            printStatus(*stat1);
+            printf("\n");
+        }
+        
+    }
+    
+    int points = -1 * stat1->steps + 25 * stat1->lambdas;
+    if (stat1->report == MISSION_ABORTED)
+        points += 25 * stat1->lambdas;
+    else if (stat1->report == MISSION_COMPLETED)
+        points += 50 * stat1->lambdas;
+    
+    destructMatrix(*map1);
+    free(map1);
+    free(stat1);
+    
+    return points;
+}
+
+int simulateRobot(const char *commands, Metadata env, Matrix initMap, Status initStat, Matrix **newMap, Status **newStat)
+{
+    Matrix *map1 = cloneMatrix(initMap), *map2;
+    Status *stat1 = cloneStatus(initStat), *stat2;
+    
+    for (int i = 0; i < strlen(commands) && stat1->report == MISSION_RUNNING; i++) {
+        
+        map2 = cloneMatrix(*map1);
+        stat2 = cloneStatus(*stat1);
+        
+        moveRobot(commands[i], env, *map1, *stat1, map2, stat2);
+        
+        destructMatrix(*map1);
+        free(map1);
+        free(stat1);
+        
+        map1 = cloneMatrix(*map2);
+        stat1 = cloneStatus(*stat2);
+        
+        destructMatrix(*map2);
+        free(map2);
+        free(stat2);
+        
+    }
+    
+    int points = -1 * stat1->steps + 25 * stat1->lambdas;
+    if (stat1->report == MISSION_ABORTED)
+        points += 25 * stat1->lambdas;
+    else if (stat1->report == MISSION_COMPLETED)
+        points += 50 * stat1->lambdas;
+    
+    *newMap = map1;
+    *newStat = stat1;
+    
+    return points;
+}
+#ifndef LIFTER_SIMULATOR
+#define LIFTER_SIMULATOR
+
+#include <stdbool.h>
+
+#include "datatypes/metadata.h"
+#include "datatypes/matrix.h"
+#include "datatypes/status.h"
+
+bool isMoveValid(char command, Metadata, Matrix, Status);
+
+int moveRobot(char command, Metadata env, Matrix oldMap, Status oldStat, Matrix *newMap, Status *newStat);
+
+int simulate(const char *commands, Metadata, Matrix initMap, Status initStat, bool doPrint);
+
+int simulateRobot(const char *commands, Metadata env, Matrix initMap, Status initStat, Matrix **newMap, Status **newStat);
+
+#endif /* LIFTER_SIMULATOR */