From 84792c5aaf2822afcd54a57c41be618cb8789787 Mon Sep 17 00:00:00 2001 From: tprats <tommy.prats@inria.fr> Date: Fri, 5 Jul 2024 09:29:44 +0200 Subject: [PATCH] Revert "remove file not use in this branch" This reverts commit 638be90b066b53a407f1c0e6498bc52270bed2af. --- levels/harder/avoid_monster/avoid_monster.py | 238 +++++++++++++++++ levels/harder/avoid_monster/custom_map.c | 106 ++++++++ levels/harder/avoid_monster/custom_map.h | 33 +++ levels/harder/avoid_monster/default.in | 75 ++++++ levels/harder/avoid_monster/first_room.tmx | 63 +++++ levels/harder/avoid_monster/input_manager.c | 261 +++++++++++++++++++ levels/harder/avoid_monster/input_manager.h | 48 ++++ levels/harder/avoid_monster/main.c | 147 +++++++++++ levels/harder/avoid_monster/second_room.tmx | 63 +++++ levels/harder/avoid_monster/third_room.tmx | 79 ++++++ 10 files changed, 1113 insertions(+) create mode 100644 levels/harder/avoid_monster/avoid_monster.py create mode 100644 levels/harder/avoid_monster/custom_map.c create mode 100644 levels/harder/avoid_monster/custom_map.h create mode 100644 levels/harder/avoid_monster/default.in create mode 100644 levels/harder/avoid_monster/first_room.tmx create mode 100644 levels/harder/avoid_monster/input_manager.c create mode 100644 levels/harder/avoid_monster/input_manager.h create mode 100644 levels/harder/avoid_monster/main.c create mode 100644 levels/harder/avoid_monster/second_room.tmx create mode 100644 levels/harder/avoid_monster/third_room.tmx diff --git a/levels/harder/avoid_monster/avoid_monster.py b/levels/harder/avoid_monster/avoid_monster.py new file mode 100644 index 00000000..cd21e222 --- /dev/null +++ b/levels/harder/avoid_monster/avoid_monster.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 + +from level.level_abc import AbstractLevel +from lib.loader.loader import load_level, run_level, test_level +from lib.level.objects import find_var_in_frame, get_top_map +from lib.utils import lvl +import graphic.constants as cst +import arcade + +class Level(AbstractLevel): + """avoid_monster""" + + def reset_skeletons(self): + skeletons = [self.map.named_objects[f"skeleton_{i}"] for i in range(1,5)] + for skeleton in skeletons: + payload = { + "topic": "object_update", + "object_name": skeleton.name, + "action": "change_color", + "color": arcade.color.WHITE, + } + self.send_to_gui(payload) + + skeleton.visible = False + skeleton.send_update() + + def arcade_custom_restart(self): + wop = self.map.named_objects["wop"] + wop.place_at(6, 6) + wop.visible = True + wop.send_update() + + self.reset_skeletons() + + if self.door_open: + payload = { + "topic": "sprites", + "action": "hide", + "layer": "decorations", + "locations": [ + (1, 5), (1, 4) + ], + } + self.send_to_gui(payload) + self.door_open = False + + def arcade_custom_first_start(self): + player = self.map.player + self.current_map = "main" + skeletons = [self.map.named_objects[f"skeleton_{i}"] for i in range(1,5)] + wop = self.map.named_objects["wop"] + self.door_open = False + self.wop_spawn = False + + def change_map(map_name): + self.reset_skeletons() + self.current_map = map_name + + payload = { + "topic": "map_change", + "map": map_name, + } + player.send_update(payload) + + def detect_map_change(): + if wop.visible: + wop.visible = False + wop.send_update() + + map_name = "third_room" + if self.current_map == "main": + map_name = "second_room" + + change_map(map_name) + + + def to_direction(direction): + if direction == "DIR_UP": + return cst.Direction.UP + elif direction == "DIR_DOWN": + return cst.Direction.DOWN + elif direction == "DIR_LEFT": + return cst.Direction.LEFT + elif direction == "DIR_RIGHT": + return cst.Direction.RIGHT + + def post_update(player, memory): + if not self.wop_spawn: + wop.visible = True + wop.place_at(6, 6) + wop.direction = cst.Direction.LEFT + wop.send_update() + + wop.place_at(5, 6) + wop.send_update() + + wop.talk("intro") + + wop.direction = cst.Direction.RIGHT + wop.place_at(6, 6) + wop.send_update() + + wop.direction = cst.Direction.DOWN + wop.send_update() + + self.wop_spawn = True + + if not self.door_open: + payload = { + "topic": "sprites", + "action": "hide", + "layer": "decorations", + "locations": [ + (1, 5), (1, 4) + ], + } + self.send_to_gui(payload) + self.door_open = True + + frames = memory["stack"] + for frame in frames: + if frame.name == "main": + monsters = find_var_in_frame(frame, "monsters_data") + try: + for m in monsters[0].info: + if m.id != -1: + skeletons[m.id].visible = True + skeletons[m.id].direction = to_direction(m.dir) + skeletons[m.id].place_at(m.x, m.y) + skeletons[m.id].send_update() + + if m.player_seen: + payload = { + "topic": "object_update", + "object_name": f"skeleton_{m.id+1}", + "action": "change_color", + "color": arcade.color.RED, + } + self.send_to_gui(payload) + else: + skeletons[m.id].visible = False + skeletons[m.id].send_update() + except: + pass + + + player.post_update = post_update + self.register_breakpoint("change_map", detect_map_change) + + + def pre_validation(self): + self.checker.append_inputs( + [ + "LEFT", + "LEFT", + "UP", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "UP", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "UP", + "UP", + "UP", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "DOWN", + "DOWN", + "DOWN", + "DOWN", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "RIGHT", + "DOWN", + "DOWN", + "WAIT", + "WAIT", + "WAIT", + "WAIT", + "DOWN", + "UP", + "DOWN", + "DOWN", + "DOWN", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + "LEFT", + ] + ) + + def test(self): + pass + +if __name__ == "__main__": + # run_level(Level, __file__, level_type="text") + # run_level(Level, __file__, level_type="arcade") + test_level(Level, __file__) \ No newline at end of file diff --git a/levels/harder/avoid_monster/custom_map.c b/levels/harder/avoid_monster/custom_map.c new file mode 100644 index 00000000..50baebd1 --- /dev/null +++ b/levels/harder/avoid_monster/custom_map.c @@ -0,0 +1,106 @@ +#include "custom_map.h" +#include "input_manager.h" + + +const char *str_map1 = +"\ ++---------------+\n\ +| M @|\n\ +| M |\n\ +| M |\n\ +| M |\n\ +| --------------|\n\ +| >| | | | |\n\ ++---------------+\n\ +"; + +//5 UP 12 RIGHT + + +const char *str_map2 = +"\ ++---------------+\n\ +|> |\n\ +| |\n\ +| |\n\ +| M M |\n\ +| @ |\n\ +| M M |\n\ ++---------------+\n\ +"; + +// 4 DOWN 7 RIGHT + +const char *str_map3 = // the monster can move two tiles for 1 movement of the player + follow him +"\ ++---------------+\n\ +| |\n\ +|M| > |\n\ +| | |\n\ +| |\n\ +| | | |\n\ +| +-+ |\n\ +| @ |\n\ ++---------------+\n\ +"; + +// initialize the monsters : first stat : id, direction and coordinates +monsters* init_monsters(map * m, monsters* monsters_data){ + monsters_data->length = 0; + for (int y = 0; y < m->height; y++) + { + for(int x = 0; x<m->width; x++){ + if (m->tiles[y][x] == 'M') {; + monsters_data->info[monsters_data->length].id = monsters_data->length; + monsters_data->info[monsters_data->length].dir = DIR_DOWN; + monsters_data->info[monsters_data->length].x = x; + monsters_data->info[monsters_data->length].y = y; + monsters_data->info[monsters_data->length].player_seen = false; + monsters_data->length++; + } + } + } + + for (int i = monsters_data->length; i < MAX_MONSTERS; i++) + { + monsters_data->info[i].id = -1; + } + + return monsters_data; +} + +void show_map(map *m) { + for (int y = 0; y < m->height; y++) + { + for(int x = 0; x<m->width; x++){ + printf("%c", m->tiles[y][x]); + } + printf("\n"); + } +} + +void update_monster(monsters* mon, map* m, int fy, int fx, int ty, int tx) { + if (m->tiles[fy][fx] == 'M' && can_move_to(m, fy, fx, ty, tx)) { + move_without_check(m, fy, fx, ty, tx); + int id = search_monster(mon, m, fy, fx); + if (fx < tx) + mon->info[id].dir = DIR_RIGHT; + else if (fx>tx) + mon->info[id].dir = DIR_LEFT; + else if (fy<ty) + mon->info[id].dir = DIR_DOWN; + else + mon->info[id].dir = DIR_UP; + + mon->info[id].x = tx; + mon->info[id].y = ty; + } +} + +void verify_monster(game_instance* game, monsters* mon) { + map *m = current_map(game->map_stack); + if (m->tiles[m->player_y][m->player_x] == 'M') { + message("A monster catches you !"); + exit(EXIT_FAILURE); + } +} \ No newline at end of file diff --git a/levels/harder/avoid_monster/custom_map.h b/levels/harder/avoid_monster/custom_map.h new file mode 100644 index 00000000..0c180caf --- /dev/null +++ b/levels/harder/avoid_monster/custom_map.h @@ -0,0 +1,33 @@ +#ifndef CUSTOM_MAP_H +#define CUSTOM_MAP_H + +#define MAX_MONSTERS 4 + +#include "engine/agdbentures.h" + +extern const char * str_map1; +extern const char * str_map2; +extern const char * str_map3; + +typedef struct monster_s { + int id; + int x; + int y; + direction dir; + bool player_seen; +} monster; + +typedef struct monsters_s { + monster info[MAX_MONSTERS]; + int length; +} monsters; + +monsters* init_monsters(map *m, monsters* monsters_data); + +void show_map(map *m); + +void update_monster(monsters *mon, map *m, int fy, int fx, int ty, int tx); + +void verify_monster(game_instance* game, monsters* mon); + +#endif // CUSTOM_MAP_H diff --git a/levels/harder/avoid_monster/default.in b/levels/harder/avoid_monster/default.in new file mode 100644 index 00000000..56d5dffa --- /dev/null +++ b/levels/harder/avoid_monster/default.in @@ -0,0 +1,75 @@ +LEFT +LEFT +UP +WAIT +WAIT +WAIT +WAIT +WAIT +WAIT +WAIT +WAIT +WAIT +WAIT +UP +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +UP +UP +UP +RIGHT +RIGHT +RIGHT +RIGHT +DOWN +DOWN +DOWN +DOWN +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +RIGHT +DOWN +DOWN +WAIT +WAIT +WAIT +WAIT +DOWN +UP +DOWN +DOWN +DOWN +LEFT +LEFT +LEFT +LEFT +LEFT +LEFT +LEFT +LEFT +LEFT +LEFT +LEFT \ No newline at end of file diff --git a/levels/harder/avoid_monster/first_room.tmx b/levels/harder/avoid_monster/first_room.tmx new file mode 100644 index 00000000..a5d422f7 --- /dev/null +++ b/levels/harder/avoid_monster/first_room.tmx @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<map version="1.8" tiledversion="1.8.0" orientation="orthogonal" renderorder="right-down" width="20" height="10" tilewidth="32" tileheight="32" infinite="0" backgroundcolor="#000000" nextlayerid="5" nextobjectid="11"> + <tileset firstgid="1" source="../../../resources/tiles/[Base]BaseChip_pipo.json"/> + <tileset firstgid="1065" source="../../../resources/tiles/[A]Grass_pipo.json"/> + <tileset firstgid="1593" source="../../../resources/tiles/[A]Water_pipo.json"/> + <layer id="1" name="floor" width="20" height="10"> + <data encoding="csv"> +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 +</data> + </layer> + <layer id="2" name="decorations" width="20" height="10"> + <data encoding="csv"> +326,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +326,0,0,0,0,0,0,0,0,0,0,0,0,0,0,336,0,0,2814,2815, +326,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +326,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +326,552,0,0,551,0,0,551,0,0,551,0,0,551,0,0,0,0,2814,2815, +326,560,554,558,559,554,558,559,554,558,559,554,558,559,554,558,0,0,2814,2815, +326,0,0,874,0,0,874,0,725,874,961,0,874,0,0,874,0,0,2814,2815, +326,326,326,326,326,326,326,326,326,0,0,0,0,0,0,0,0,0,2814,2815, +326,326,326,326,326,326,326,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,2814,2815 +</data> + </layer> + <layer id="3" name="walls" width="20" height="10"> + <data encoding="csv"> +449,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,451,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +449,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,451,556,0,0, +457,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,459,556,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,0 +</data> + </layer> + <layer id="3" name="decorations_top" width="20" height="10"> + <data encoding="csv"> +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,551,546,550,552,546,550,552,546,550,552,546,550,552,546,550,0,0,0,0, +0,559,0,0,560,0,0,560,0,0,560,0,0,560,0,0,0,0,0,0, +0,0,0,556,0,0,556,0,1003,556,1055,0,556,0,0,556,0,0,0,0, +0,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,0,0,0,0, +909,908,0,0,0,0,0,925,925,925,0,0,0,0,0,908,909,0,0,0, +917,916,0,0,0,0,0,933,933,933,0,0,0,0,0,916,917,0,0,0 +</data> + </layer> + <objectgroup id="4" name="objects"/> +</map> diff --git a/levels/harder/avoid_monster/input_manager.c b/levels/harder/avoid_monster/input_manager.c new file mode 100644 index 00000000..81146737 --- /dev/null +++ b/levels/harder/avoid_monster/input_manager.c @@ -0,0 +1,261 @@ +#include "input_manager.h" + + +extern int defeat; +extern int win; + +//return 1 if the value given in parameter is in the list. +int in_list(int value, int *list, int len){ + for (int i = 0; i<len; i++){ + if (list[i]==value){ + return 1; + } + } + return 0; +} + +// apply the movement from (y,x) and to direction d1 first then d2 if possible. +void make_move(monsters* mon, map* m, int y, int x, direction d1, direction d2){ + int y1=y, x1=x; + switch (d1) + { + case DIR_UP: + y1 = y - 1; + break; + case DIR_DOWN: + y1 = y + 1; + break; + case DIR_RIGHT: + x1 = x + 1; + break; + case DIR_LEFT: + x1 = x - 1; + break; + default: + break; + } + int y2=y1, x2=x1; + switch (d2){ + case DIR_UP: y2 = y1-1; break; + case DIR_DOWN: y2 = y1+1; break; + case DIR_RIGHT: x2 = x1+1; break; + case DIR_LEFT: x2 = x1-1; break; + default : break; + } + update_monster(mon,m,y,x,y1,x1); + //apply_events(game); + if (d2 != DIR_UNKNOWN){ + update_monster(mon,m,y1,x1,y2,x2); + } +} + +// verify if a move is possible and apply it if so +int ok_move(monsters* mon, map* m, int y, int x, direction d1, direction d2){ + int y1 = y, x1 = x; + switch (d1){ + case DIR_UP: y1 = y-1; break; + case DIR_DOWN: y1 = y+1; break; + case DIR_RIGHT: x1 = x+1; break; + case DIR_LEFT: x1 = x-1; break; + default : break; + } + int y2=y1, x2=x1; + switch (d2){ + case DIR_UP: y2 = y1-1; break; + case DIR_DOWN: y2 = y1+1; break; + case DIR_RIGHT: x2 = x1+1; break; + case DIR_LEFT: x2 = x1-1; break; + default : break; + } + if (d2 == DIR_UNKNOWN){ + if (!is_obstacle(m->tiles[y1][x1])){ + make_move(mon,m,y,x,d1,d2); + return 1; + } + } else if (!is_obstacle(m->tiles[y1][x1]) && !is_obstacle(m->tiles[y2][x2])){ + make_move(mon,m,y,x,d1,d2); + return 1; + } else if (!is_obstacle(m->tiles[y1][x1])){ + make_move(mon,m,y,x,d1,DIR_UNKNOWN); + return 1; + } + return 0; +} + +// move the monster to the right or the left depending on the player's position +int move_up_or_down(monsters* mon, map* m, int y_monster, int x_monster, int y_player){ + if (y_monster > y_player) + return ok_move(mon, m, y_monster,x_monster, DIR_UP, DIR_UP); + else if (y_monster < y_player) + return ok_move(mon, m, y_monster,x_monster, DIR_DOWN, DIR_DOWN); + return 0; +} + +// move the monster to the right or the left depending on the player's position +int move_left_or_right(monsters* mon, map* m, int y_monster, int x_monster, int x_player){ + if (x_monster > x_player) + return ok_move(mon, m, y_monster,x_monster, DIR_LEFT, DIR_LEFT); + else if (x_monster < x_player) + return ok_move(mon, m, y_monster,x_monster, DIR_RIGHT, DIR_RIGHT); + return 0; +} + +// move the monster to one of the four corners +int move_to_corner(monsters* mon, map* m, int y_monster, int x_monster, int y_player, int x_player){ + if (x_monster > x_player && y_monster > y_player) + return ok_move(mon, m, y_monster,x_monster, DIR_UP, DIR_LEFT) || ok_move(mon, m, y_monster,x_monster, DIR_LEFT, DIR_UP); + else if (x_monster > x_player && x_monster < y_player) + return ok_move(mon, m, y_monster,y_player, DIR_DOWN, DIR_LEFT) || ok_move(mon, m, y_monster,x_monster, DIR_LEFT, DIR_DOWN); + else if (x_monster < x_player && y_monster > y_player) + return ok_move(mon, m, y_monster,x_monster, DIR_RIGHT, DIR_UP) || ok_move(mon, m, y_monster,x_monster, DIR_UP, DIR_RIGHT); + else if (x_monster < x_player && y_monster < y_player) + return ok_move(mon, m, y_monster,x_monster, DIR_RIGHT, DIR_DOWN) || ok_move(mon, m, y_monster,x_monster, DIR_DOWN, DIR_RIGHT); + return 0; +} + +int follow_player(monsters* mon, map* m, int * y, int * x){ + int y_monster = *y; + int x_monster = *x; + int y_player = m->player_y, x_player = m->player_x; + if (x_player == x_monster){ // same column + return move_up_or_down(mon, m, y_monster, x_monster, y_player); + } else if (y_monster==y_player){ // same line + return move_left_or_right(mon, m, y_monster, x_monster, x_player); + } else if ((x_player==x_monster+1 || x_player==x_monster-1) && (y_player==y_monster+1 || y_player==y_monster-1)){ // corners + return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player); + } else if (x_player==x_monster+1 || x_player==x_monster-1){ // one tile to the left or the right + #ifdef line_first + return move_up_or_down(mon, m, y_monster, x_monster, x_player) || move_to_corner(mon, m, y_monster, x_monster, y_player, x_player); + #else + return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player) || move_up_or_down(mon, m, y_monster, x_monster, y_player); + #endif + } else if (y_player==y_monster+1 || y_player==y_monster-1){ // one tile upper or lower + #ifdef line_first + return move_left_or_right(mon, m, y_monster, x_monster, x_player) || move_to_corner(mon, m, y_monster, x_monster, y_player, x_player); + #else + return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player) || move_left_or_right(mon, m, y_monster, x_monster, x_player); + #endif + } else { + #ifdef line_first + return move_left_or_right(mon, m, y_monster, x_monster, x_player) || move_up_or_down(mon, m, y_monster, x_monster, y_player) || move_to_corner(mon, m, y_monster, x_monster, y_player, x_player); + #else + #endif + return move_to_corner(mon, m, y_monster, x_monster, y_player, x_player) || move_up_or_down(mon, m, y_monster, x_monster, y_player) || move_left_or_right(mon, m, y_monster, x_monster, x_player); + } +} + +void circle(monsters* mon, map* m, int y, int x) { + if (y == 6 && x != 6 && m->tiles[y][x-1] != 'M') + update_monster(mon,m,y,x,y,x-1); // left + else if (y == 4 && x!=10 && m->tiles[y][x+1] != 'M') + update_monster(mon,m,y,x,y,x+1); //right + else if(x == 6 && y!=4 && m->tiles[y-1][x] != 'M') + update_monster(mon,m,y,x,y-1,x); //up + else if(x == 10 && y!=6 && m->tiles[y+1][x] != 'M') + update_monster(mon,m,y,x,y+1,x); //down +} + +int search_monster(monsters* mon, map* m, int y, int x) { + for (int i = 0; i < mon->length; i++) + { + if (mon->info[i].x == x && mon->info[i].y == y) + return i; + } + return -1; +} + +void come_and_go(monsters* mon, map * m, int y, int x){ + int monster_id = search_monster(mon, m, y, x); + if (monster_id == -1) + return; + int dir = mon->info[monster_id].dir; + + if(x==m->width-2 || m->tiles[y][x+1] == '@' || m->tiles[y][x+1] == 'M') { + mon->info[monster_id].dir = DIR_LEFT; + update_monster(mon,m,y,x,y,x-1); + } + else if (x == 2 || m->tiles[y][x-1] == 'M') { + mon->info[monster_id].dir = DIR_RIGHT; + update_monster(mon,m,y,x,y,x+1); + } + else if (dir == DIR_RIGHT) + update_monster(mon,m,y,x,y,x+1); + else if (dir == DIR_LEFT) + update_monster(mon,m,y,x,y,x-1); + else if (dir == DIR_DOWN) { + mon->info[monster_id].dir = DIR_LEFT; + update_monster(mon,m,y,x,y,x-1); + } +} + +// verify if the player is seen by the monster +void is_player_seen(monsters* mon, map * m, int y, int x){ + int monster_id = search_monster(mon, m, y, x); + if (monster_id == -1) + return; + int dir = mon->info[monster_id].dir; +#ifndef BUG + if (dir == DIR_RIGHT && m->player_x > x && m->player_y == y) +#else + if (dir == DIR_RIGHT && m->player_y == y) +#endif + mon->info[monster_id].player_seen = true; +#ifndef BUG + else if (dir == DIR_LEFT && m->player_x < x && m->player_y == y) +#else + else if (dir == DIR_LEFT && m->player_y == y) +#endif + mon->info[monster_id].player_seen = true; +#ifndef BUG + else if (dir == DIR_UP && m->player_y < y && m->player_x == x) +#else + else if (dir == DIR_UP && m->player_x == x) +#endif + mon->info[monster_id].player_seen = true; +} + +// move the monster to the player's position +void catch_player(monsters* mon, map * m, int y, int x){ + int monster_id = search_monster(mon, m, y, x); + if (y < m->player_y && !is_obstacle(m->tiles[y+1][x]) && m->tiles[y+1][x] != 'M' && m->tiles[y+1][x] != '@') { + mon->info[monster_id].dir = DIR_DOWN; + update_monster(mon,m,y,x,y+1,x); + } else if (y > m->player_y && !is_obstacle(m->tiles[y-1][x]) && m->tiles[y-1][x] != 'M' && m->tiles[y-1][x] != '@') { + mon->info[monster_id].dir = DIR_UP; + update_monster(mon,m,y,x,y-1,x); + } else if (x < m->player_x && !is_obstacle(m->tiles[y][x+1]) && m->tiles[y][x+1] != 'M' && m->tiles[y][x+1] != '@') { + mon->info[monster_id].dir = DIR_RIGHT; + update_monster(mon,m,y,x,y,x+1); + } else if (x > m->player_x && !is_obstacle(m->tiles[y][x-1]) && m->tiles[y][x-1] != 'M' && m->tiles[y][x-1] != '@') { + mon->info[monster_id].dir = DIR_LEFT; + update_monster(mon,m,y,x,y,x-1); + } +} + +// move the monster once and verify to not move twice a monster. +void move_monsters(monsters* mon, map * m){ + int done[8], len = 0; + for (int y = 0; y < m->height; y++){ + for (int x = 0; x < m->width; x++){ + if (m->tiles[y][x] == 'M'){ + int id = search_monster(mon, m, y, x); + if (id != -1 && !in_list(id, done, len)){ + if (strcmp(m->name, "third_room") != 0) + is_player_seen(mon,m,y,x); + + if (mon->info[id].player_seen && strcmp(m->name, "third_room") != 0) + catch_player(mon,m,y,x); + else if (!strcmp(m->name, "first_room")) + come_and_go(mon,m,y,x); + else if (!strcmp(m->name, "second_room")) + circle(mon,m,y,x); + else if (!strcmp(m->name, "third_room")) + follow_player(mon,m,&y,&x); + + done[len] = id; + len++; + } + } + } + } +} diff --git a/levels/harder/avoid_monster/input_manager.h b/levels/harder/avoid_monster/input_manager.h new file mode 100644 index 00000000..c7604329 --- /dev/null +++ b/levels/harder/avoid_monster/input_manager.h @@ -0,0 +1,48 @@ +#ifndef INPUT_MANAGER_H +#define INPUT_MANAGER_H + +#include "engine/agdbentures.h" +#include "custom_map.h" +#include <unistd.h> + +//return 1 if the value given in parameter is in the list. +int in_list(int value, int *list, int len); + +// apply the movement from (y,x) and to direction d1 first then d2 if possible. +void make_move(monsters* mon, map *m, int y, int x, direction d1, direction d2); + +// verify if a move is possible and apply it if so +int ok_move(monsters* mon, map *m, int y, int x, direction d1, direction d2); + +// move the monster to the right or the left depending on the player's position +int move_up_or_down(monsters* mon, map *m, int y_monster, int x_monster, int y_player); + +// move the monster to the right or the left depending on the player's position +int move_left_or_right(monsters* mon, map *m, int y_monster, int x_monster, int x_player); + +// move the monster to one of the four corners +int move_to_corner(monsters* mon, map *m, int y_monster, int x_monster, int y_player, int x_player); + +// follow movement (3rd monster pattern) +int follow_player(monsters* mon, map *m, int *y, int *x); + +// circle movement (2nd monster pattern) +void circle(monsters* mon, map *m, int y, int x); + +// returns the id of the monster located at coordinates (x,y) or -1 +int search_monster(monsters *mon, map *m, int y, int x); + +// come and go movement (1st monster pattern) +void come_and_go(monsters *mon, map *m, int y, int x); + +// search for the monster at coordinates (x,y) and return its id or -1 +int search_monster(monsters* mon, map* m, int y, int x); + +// move every monster once and verify not to move twice a monster. +void move_monsters(monsters *mon, map *m); + +// examine la commande c et appelle les fonctions d'action ou de déplacement correspondantes +// void parse_input(game_instance* game, monsters* mon, command * c); + + +#endif \ No newline at end of file diff --git a/levels/harder/avoid_monster/main.c b/levels/harder/avoid_monster/main.c new file mode 100644 index 00000000..3a251dfe --- /dev/null +++ b/levels/harder/avoid_monster/main.c @@ -0,0 +1,147 @@ +/** @AGDB + * level_title: Avoid Monster + * program_name: avoid_monster + * exec_name: avoid_monster + * engine_name: map_stack + * + * available_commands: edit next step continue interrupt + * + * player_mode: map_stack + * + * interactive: True + * + * characters: skeleton:4 + * + * OBJskeleton_1: char_rep M + * OBJskeleton_2: char_rep M + * OBJskeleton_3: char_rep M + * OBJskeleton_4: char_rep M + * + * verify_exit: cond exit_x == 4 + * verify_exit: cond exit_y == 7 + * verify_always: must_call init_monsters + * verify_always: must_call move_monsters + * verify_always: must_call verify_monster + * verify_always: must_call is_player_seen + * + * WOP: messageFR intro + * Enfuis toi de cette prison, j'ai récupéré cette clé sur un monstre, + * prends là et échappe toi ! + * Fais attention aux monstres, ils sont très dangereux ! + * S'ils te vois, ils te poursuivront jusqu'à ce qu'ils t'attrapent ! + * EndOfMessage + * + * WOP: messageEN intro + * Escape from this prison, I got this key off a monster, take it and escape! + * Watch out for monsters, they're very dangerous! + * If they see you, they'll chase you until they catch you! + * EndOfMessage + * + * arcade_maps: main first_room.tmx + * arcade_maps: second_room second_room.tmx + * arcade_maps: third_room third_room.tmx + */ + +#include "engine/agdbentures.h" +#include "custom_map.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int exit_x = 15; +int exit_y = 1; + +extern int win, defeat; + +void init_maps(game_instance* game) { + char* head_names[3] = {"third", "second", "first"}; + char *tail_name = "_room"; + char name[15]; + for (int i = 0; i < 3; i++) { + strcpy(name, head_names[i]); + strcat(name, tail_name); + map *m = load_map(name, i == 0 ? str_map3 : i == 1 ? str_map2 : str_map1); + push_on_stack(game->map_stack, m); + } +} + +void execute_loop(game_instance* game, monsters* mon) { + int dest_y, dest_x; + map* room_map = current_map(game->map_stack); + // inputs loop + while (!game->exit_main_loop) { + // read command + command * input_command = get_next_command(); + char* command = input_command->command_buffer; + direction dir = direction_from_string(command); + // if the direction is meaningful try to move + if (dir != DIR_UNKNOWN) { + // Lookup for the predicted destination + room_map->player_direction = dir; + player_look_forward(room_map, &dest_y, &dest_x); + + // If the destination is empty, go there + if (room_map->tiles[dest_y][dest_x] == ' ') { + move_player(room_map, dest_y, dest_x, dir); + // if there's a monster, player loses + } else if (room_map->tiles[dest_y][dest_x] == '-' || room_map->tiles[dest_y][dest_x] == '|' || room_map->tiles[dest_y][dest_x] == '+') { + continue; + } else if (room_map->tiles[dest_y][dest_x] == 'M') { + move_player(room_map, dest_y, dest_x, dir); + message("The monster catches you!\n"); + level_failed(game,1); + exit(EXIT_FAILURE); + // if player reaches the exit, exit the loop + } else if (room_map->tiles[dest_y][dest_x] == '@') { + printf("You reached the exit!\n"); + move_player(room_map, dest_y, dest_x, dir); + game->exit_main_loop = true; + break; + } + } else if (!strcmp(command,"W") || !strcmp(command,"w") || !strcmp(command,"WAIT") || !strcmp(command,"wait")) { + message("You stand still and wait"); // wait one turn + } else { + printf("Unknown command %s\n", command); + continue; + } + printf("player x=%d y=%d\n", room_map->player_x, room_map->player_y); + move_monsters(mon, room_map); + verify_monster(game, mon); + show_map(room_map); + } +} + +void change_map(game_instance* game, monsters* mon, int i) { + pop_from_stack(game->map_stack); + game->exit_main_loop = false; + + if (i == 0) { + exit_x = 8; + exit_y = 5; + } else if (i == 1) { + exit_x = 4; + exit_y = 7; + } +} + +int main() { + game_instance* game = init_game(); + monsters* monsters_data = malloc(sizeof(monsters)); + map *room; + init_maps(game); + message("You have to avoid the monsters using the directional arrows and W(ait)."); + + // rooms loop + for (int i = 0; i < 3; i++) { + room = current_map(game->map_stack); + init_monsters(room, monsters_data); + printf("Room n°%d\n", i+1); + execute_loop(game, monsters_data); + change_map(game, monsters_data, i); + } + + free(monsters_data); + free_map_stack(game->map_stack); + + verify_exit(room); +} diff --git a/levels/harder/avoid_monster/second_room.tmx b/levels/harder/avoid_monster/second_room.tmx new file mode 100644 index 00000000..564c794a --- /dev/null +++ b/levels/harder/avoid_monster/second_room.tmx @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<map version="1.8" tiledversion="1.8.0" orientation="orthogonal" renderorder="right-down" width="20" height="10" tilewidth="32" tileheight="32" infinite="0" backgroundcolor="#000000" nextlayerid="5" nextobjectid="11"> + <tileset firstgid="1" source="../../../resources/tiles/[Base]BaseChip_pipo.json"/> + <tileset firstgid="1065" source="../../../resources/tiles/[A]Grass_pipo.json"/> + <tileset firstgid="1593" source="../../../resources/tiles/[A]Water_pipo.json"/> + <layer id="1" name="floor" width="20" height="10"> + <data encoding="csv"> +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 +</data> + </layer> + <layer id="2" name="decorations" width="20" height="10"> + <data encoding="csv"> +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +</data> + </layer> + <layer id="3" name="walls" width="20" height="10"> + <data encoding="csv"> +449,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,451,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,336,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +449,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,451,556,0,0, +457,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,459,556,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,0 +</data> + </layer> + <layer id="3" name="decorations_top" width="20" height="10"> + <data encoding="csv"> +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,0,0,2814,2815, +909,908,0,0,0,0,0,925,925,925,0,0,0,0,0,908,909,0,2814,2815, +917,916,0,0,0,0,0,933,933,933,0,0,0,0,0,916,917,0,2814,2815 +</data> + </layer> + <objectgroup id="4" name="objects"/> +</map> diff --git a/levels/harder/avoid_monster/third_room.tmx b/levels/harder/avoid_monster/third_room.tmx new file mode 100644 index 00000000..3ed550b9 --- /dev/null +++ b/levels/harder/avoid_monster/third_room.tmx @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<map version="1.8" tiledversion="1.8.0" orientation="orthogonal" renderorder="right-down" width="20" height="14" tilewidth="32" tileheight="32" infinite="0" backgroundcolor="#000000" nextlayerid="5" nextobjectid="11"> + <tileset firstgid="1" source="../../../resources/tiles/[Base]BaseChip_pipo.json"/> + <tileset firstgid="1065" source="../../../resources/tiles/[A]Grass_pipo.json"/> + <tileset firstgid="1593" source="../../../resources/tiles/[A]Water_pipo.json"/> + <layer id="1" name="floor" width="20" height="14"> + <data encoding="csv"> +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 +</data> + </layer> + <layer id="2" name="decorations" width="20" height="14"> + <data encoding="csv"> +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,488,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,496,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1453,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,1461,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,1465,1451,1451,1451,1451,1451,1451,1451,1451,1451,1451,1458,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1461,0,0,2814,2815 +</data> + </layer> + <layer id="3" name="walls" width="20" height="14"> + <data encoding="csv"> +449,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,451,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,210,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,218,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,210,0,210,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,219,217,220,0,452,556,0,0, +452,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,452,556,0,0, +449,450,450,450,0,450,450,450,450,450,450,450,450,450,450,450,451,556,0,0, +457,458,458,458,0,458,458,458,458,458,458,458,458,458,458,458,459,556,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,0 +</data> + </layer> + <layer id="3" name="decorations_top" width="20" height="14"> + <data encoding="csv"> +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2814,2815, +0,455,455,828,487,828,455,455,455,455,455,455,455,455,455,455,0,0,2814,2815, +909,908,0,836,0,836,0,925,925,925,0,0,0,0,0,908,909,0,2814,2815, +917,916,0,0,0,0,0,933,933,933,0,0,0,0,0,916,917,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +</data> + </layer> + <objectgroup id="4" name="objects"/> +</map> -- GitLab