Skip to content

Commit

Permalink
Changes for level 3
Browse files Browse the repository at this point in the history
Enemies can be killed
Upon player death, game ends
Upon boss death, player gains ability to traverse water
Refactoring for SwitchGrid and related functions
Added properties to agents missing those
  • Loading branch information
budnyric committed Dec 6, 2023
1 parent efc63b2 commit 0eea153
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 62 deletions.
10 changes: 5 additions & 5 deletions assets/grids/third_floor.grid
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
####### #######
####### #######
###### ######
##### #####
#### ####
### ###
## g ##
####################
##### ww#####
#### ww ####
### ww ###
## ww g ##
####################
4 changes: 3 additions & 1 deletion assets/scripts/g4_agent_attack.ws
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ diff=str-def
if (diff<=0){
diff=1
}
damage=rand(1,diff)
damage=rand(1,2*diff)
print(damage," damage")

hp=getProperty(opponent,"Health")-damage
if (hp<0){
hp=0
setProperty(opponent,"Dead",1)
setProperty(opponent,"symbol","x")
}
setProperty(opponent,"Health",hp)
13 changes: 12 additions & 1 deletion assets/scripts/g4_world_2_load.ws
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
# Load the actual world
loadWorld("assets/grids/second_floor.grid")

# Place items
# Load the agents for this world
loadAgents("assets/second_floor_input.json")

# Reset player position
print(player)
setAgentPosition(player,0,0)

# Place items for second floor
addItem("Hammer","H",20,43,"Damage",35)
addItem("Dagger","D",12,1,"Damage",10)
addItem("Leather Armor","+",1,6,"Armor",6)

# Set link to next world
next_world = "assets/scripts/g4_world_3_load.ws"

12 changes: 12 additions & 0 deletions assets/scripts/g4_world_3_load.ws
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Load the actual world
loadWorld("assets/grids/third_floor.grid")

# Load the agents for this world
loadAgents("assets/third_floor_input.json")

# Reset player position
setAgentPosition(player,0,0)

# Set game end indicator
next_world = "GAME_END"

6 changes: 5 additions & 1 deletion assets/scripts/g4_world_load.ws
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ player=addAgent("Player","PlayerAgent","@",0,0)
setProperty(player,"Health",100.0)
setProperty(player,"Strength",7.0)
setProperty(player,"Defense",7.0)
setAgentPosition(player,0,0)

# Place items
addItem("Sword of Power","S",1,2,"Damage",20)
addItem("Inferno Slicer","S",3,4,"Damage",12.5,"Speed",15.0,"Burning Duration",2.5)
addItem("Daedric Armor","+",5,0,"Health",99,"ExtraSpace",5)
addItem("Daedric Armor","+",5,0,"Armor",20,"ExtraSpace",5)
addItem("Axe of Health","A",1,3,"Damage",8.5,"Health",35)
addItem("Electric Dagger","D",6,2,"Damage",25)
chest = addItem("Ender Chest","C",0,4,"Chest",1)
fire_dagger = addItem("Fire Dagger","D",-1,-1,"Damage",15.0)
addInventoryItem(chest,fire_dagger)

# Set link to next world
next_world = "assets/scripts/g4_world_2_load.ws"

16 changes: 13 additions & 3 deletions assets/second_floor_input.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
"entities": [
"chocolate_bar"
],
"hasInventory": false
"hasInventory": false,
"properties":{
"Health":30.0,
"Defense":5.0,
"Strength":3.0
}
},
{
"name": "Pinky",
Expand All @@ -15,6 +20,11 @@
"entities": [

],
"hasInventory": false
"hasInventory": false,
"properties":{
"Health":70.0,
"Defense":15.0,
"Strength":10.0
}
}
]
]
11 changes: 8 additions & 3 deletions assets/third_floor_input.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
"name": "Jim Harbaugh",
"x": 7,
"y": 8,
"hp": 1000,
"entities": [
"invisibility_cloak"
],
"hasInventory": false
"hasInventory": false,
"properties":{
"Health":1000.0,
"Defense":24.0,
"Strength":36.0,
"Boss":1.0
}
}
]
]
122 changes: 74 additions & 48 deletions source/Worlds/SecondWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,9 @@ class SecondWorld : public cse491::WorldBase {
/// @brief File name for agent input JSON file.
std::string agents_filename = "";

/**
* Switches to the next grid file
* and resets player position and item map.
* @param agent The player agent
* @param pos The player position
*/
void SwitchGrid(cse491::AgentBase& agent, cse491::GridPosition& pos) {

void LoadWorldScript(std::string source){
// Clear items on the current grid, unless held by a player
for (auto it = item_map.begin(); it != item_map.end();) {
auto& item = it->second;
if (item->IsOnGrid()) {
Expand All @@ -83,16 +79,7 @@ class SecondWorld : public cse491::WorldBase {
}
}

if (world_filename == FIRST_FLOOR_FILENAME) {
pe.runFile(WORLD_LOAD_SCRIPT_2);
agents_filename = "../assets/second_floor_input.json";
} else if (world_filename == SECOND_FLOOR_FILENAME) {
pe.runFile(WORLD_LOAD_SCRIPT_3);
agents_filename = "../assets/third_floor_input.json";
}

agent.Notify("Going to " + world_filename, "world_switched");

// Clear agents, unless they are the player (an interface)
std::vector<size_t> agents_to_remove = {};
for (auto& [agent_id, agent_ptr] : agent_map) {
if (!agent_ptr->IsInterface()) {
Expand All @@ -103,10 +90,31 @@ class SecondWorld : public cse491::WorldBase {
for (auto agent_id : agents_to_remove) {
RemoveAgent(agent_id);
}

// Initialize level
pe.runFile(source);
}


/**
* Switches to the next grid file
* and resets player position and item map.
* @param agent The player agent
* @param pos The player position
*/
void SwitchGrid(cse491::AgentBase& agent, cse491::GridPosition& pos) {

// This value initialized by each world load script to point to the next level
auto next_world_script = pe.var<std::string>("next_world");

// Resetting the current new_position to the top left of the new grid.
pos = cse491::GridPosition(0, 0);
LoadFromFile(agents_filename);
agent.Notify("Going to " + world_filename, "world_switched");
if (next_world_script == "GAME_END") {
agent.Notify("Congrats, you won the game!", "congrats_msg");
run_over = true;
return;
}

LoadWorldScript(next_world_script);
}

protected:
Expand Down Expand Up @@ -156,7 +164,15 @@ class SecondWorld : public cse491::WorldBase {
* Constructor with no arguments
*/
SecondWorld() : world_filename(FIRST_FLOOR_FILENAME), pe{*this} {
pe.runFile(WORLD_LOAD_SCRIPT);
pe.registerFunction("loadAgents", [this](worldlang::ProgramExecutor& pe){
auto args = pe.popArgs();
if (args.size() != 1) { pe.error("Wrong number of arguments!"); return; }
auto path = pe.as<std::string>(args[0]);

this->LoadFromFile(path);
});

LoadWorldScript(WORLD_LOAD_SCRIPT);
}

/**
Expand Down Expand Up @@ -224,6 +240,7 @@ class SecondWorld : public cse491::WorldBase {
int additional_max_health = 0;
std::vector<std::string> entities = agent.at("entities");


for (const auto& entity : entities) {
// TODO: How should we set the entity properties here?
// Just adding to MaxHealth now, but this doesn't seem very scalable.
Expand All @@ -232,9 +249,16 @@ class SecondWorld : public cse491::WorldBase {
}
}

AddAgent<cse491::PacingAgent>(agent_name)
auto& a = AddAgent<cse491::PacingAgent>(agent_name)
.SetPosition(x_pos, y_pos)
.SetProperty("MaxHealth", BASE_MAX_HEALTH + additional_max_health);

auto properties = agent.at("properties");
for (const auto& p : properties.items()){
std::cout << p.value().is_number() << std::endl;
a.SetProperty(p.key(), p.value().get<double>());
}

}
}

Expand Down Expand Up @@ -326,48 +350,31 @@ class SecondWorld : public cse491::WorldBase {
* Checks to see if there is a flag or item at the agent's current position
* @param agent The agent
* @param pos The position
* @return true if agent should update position on return
*/
void CheckPosition(cse491::AgentBase& agent, cse491::GridPosition& pos) {
bool CheckPosition(cse491::AgentBase& agent, cse491::GridPosition& pos) {
// First check to see if agent is on win flag
if ((type_options[main_grid.At(pos)].HasProperty("Goal")) &&
(agent.IsInterface())) {
// Set win flag to true

agent.Notify("Flag found ", "item_alert");

agent.Notify("Leaving " + world_filename, "world_switched");

if (world_filename == FIRST_FLOOR_FILENAME ||
world_filename == SECOND_FLOOR_FILENAME) {
// We are currently on floor 1 or 2,
// so switch to the next world
// and reset the item_map and player position.
SwitchGrid(agent, pos);
} else if (world_filename == FINAL_FLOOR_FILENAME) {
agent.Notify("Congrats, you won the game!", "congrats_msg");
run_over = true;
}
SwitchGrid(agent, pos);

return false;

// then checks if agent is on any items
} else if ((type_options[main_grid.At(pos)].HasProperty("Warp")) &&
(agent.IsInterface())) {
// Agent used the hidden warp tile action
// std::cout << "Hidden warp tile activated! Warping to floor 3."
// << std::endl;
agent.Notify("Hidden warp tile activated! Warping to floor 3.",
"hidden_warp");

agent.Notify("Leaving " + world_filename, "world_switched");

// Update the world to floor 3
world_filename = FINAL_FLOOR_FILENAME;
agents_filename = "../assets/third_floor_input.json";

SwitchGrid(agent, pos);

// Update the agent's position on the new floor
agent.SetPosition(pos);

LoadWorldScript(WORLD_LOAD_SCRIPT_3); // skip right to the end
return false;
} else {
auto items_found = FindItemsAt(pos, 0);
// If there are items at this position
Expand Down Expand Up @@ -422,6 +429,7 @@ class SecondWorld : public cse491::WorldBase {
}
}
}
return true;
}

/**
Expand All @@ -431,6 +439,10 @@ class SecondWorld : public cse491::WorldBase {
* @return An int that declares if the move is legal or illegal (true / false)
*/
int DoAction(cse491::AgentBase& agent, size_t action_id) override {
if (agent.HasProperty("Dead")){
return false; // Can't move when dead!
}

cse491::GridPosition new_position;
bool IsDropped = false;
switch (action_id) {
Expand All @@ -452,7 +464,8 @@ class SecondWorld : public cse491::WorldBase {
case DROP_ITEM:
new_position = agent.GetPosition();
DropItem(agent, new_position);
IsDropped = true;
// IsDropped = true;
return true;
break;
}

Expand All @@ -473,14 +486,27 @@ class SecondWorld : public cse491::WorldBase {
pe.setVariable("opponent", res[0]);
pe.runFile(COMBAT_SCRIPT);

auto& opponent = GetAgent(res[0]);
if (opponent.HasProperty("Dead") && opponent.IsInterface()){
// game over!
opponent.Notify("You have died.", "game_over");
run_over = true;
} else if (opponent.HasProperty("Dead") && opponent.HasProperty("Boss")){
// level up: i.e. you can go on water now
agent.Notify("You have defeated the boss! You now can walk on water.", "message");
agent.SetProperty("Swimmer", true);
}

// The movement was not legal, so we return false.
// TODO: Should this return a status indicating that an attack occured,
// to distinguish moves that do nothing from attacks?
return false;
}

if (!IsDropped) {
CheckPosition(agent, new_position);
if (!CheckPosition(agent, new_position))
//does not set position if grid changed, but move is considered successful
return true;
}

IsDropped = false;
Expand Down

0 comments on commit 0eea153

Please sign in to comment.