Skip to content

Commit

Permalink
added celestia to debris + battle report event
Browse files Browse the repository at this point in the history
  • Loading branch information
ametel01 committed Oct 29, 2023
1 parent 9129188 commit 7a102fd
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 12 deletions.
96 changes: 92 additions & 4 deletions src/game/main.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// TODOS:
// - Make contract upgradable
// - Add events for battle reports
// - Add celestia to battle
// - Adjust players points after battle

#[starknet::contract]
mod NoGame {
Expand Down Expand Up @@ -101,6 +102,7 @@ mod NoGame {
TechSpent: TechSpent,
FleetSpent: FleetSpent,
Upgraded: Upgraded,
BattleReport: BattleReport,
}

#[derive(Drop, starknet::Event)]
Expand All @@ -126,6 +128,17 @@ mod NoGame {
implementation: ClassHash
}

#[derive(Drop, starknet::Event)]
struct BattleReport {
time: u64,
attacker: u16,
attacker_fleet_loss: Fleet,
defender: u16,
defender_fleet_loss: Fleet,
defences_loss: DefencesLevels,
debris: Debris,
}

#[constructor]
fn constructor(ref self: ContractState) {
self.owner.write(get_caller_address());
Expand Down Expand Up @@ -669,26 +682,31 @@ mod NoGame {
self.check_enough_ships(planet_id, f);
// Calculate distance
let distance = fleet::get_distance(self.planet_position.read(planet_id), destination);

// Calculate time
let techs = self.get_tech_levels(planet_id);
let speed = fleet::get_fleet_speed(f, techs);
let travel_time = fleet::get_flight_time(speed, distance);

// Check numeber of mission
let active_missions = self.active_missions_len.read(planet_id);
assert(active_missions < techs.digital.into() + 1, 'max active missions');

// Pay for fuel
let consumption = fleet::get_fuel_consumption(f, distance);
let mut cost: ERC20s = Default::default();
cost.tritium = consumption;
self.check_enough_resources(caller, cost);
self.pay_resources_erc20(caller, cost);

// Write mission
let time_now = get_block_timestamp();
let mut mission: Mission = Default::default();
mission.time_start = time_now;
mission.destination = self.get_position_slot_occupant(destination);
mission.time_arrival = time_now + travel_time;
mission.fleet = f;

if is_debris_collection {
mission.is_debris = true;
self.add_active_mission(planet_id, mission);
Expand All @@ -704,13 +722,15 @@ mod NoGame {

self.add_hostile_mission(destination_id, hostile_mission);
}

// Write new fleet levels
self.fleet_leave_planet(planet_id, f);
self.last_active.write(planet_id, get_block_timestamp());
}

fn attack_planet(ref self: ContractState, mission_id: usize) {
let origin = self.get_owned_planet(get_caller_address());
let caller = get_caller_address();
let origin = self.get_owned_planet(caller);
let mut mission = self.active_missions.read((origin, mission_id));
assert(!mission.is_zero(), 'the mission is empty');
let time_now = get_block_timestamp();
Expand All @@ -719,17 +739,22 @@ mod NoGame {
let defences = self.get_defences_levels(mission.destination);
let t1 = self.get_tech_levels(origin);
let t2 = self.get_tech_levels(mission.destination);
let celestia_before = self.get_celestia_available(mission.destination);

let (f1, f2, d) = fleet::war(mission.fleet, t1, defender_fleet, defences, t2);

// calculate debris and update field
let debris1 = fleet::get_debris(mission.fleet, f1);
let debris2 = fleet::get_debris(defender_fleet, f2);
let debris1 = fleet::get_debris(mission.fleet, f1, 0);
let debris2 = fleet::get_debris(defender_fleet, f2, celestia_before - d.celestia);
let total_debris = debris1 + debris2;
let current_debries_field = self.planet_debris_field.read(mission.destination);
self
.planet_debris_field
.write(mission.destination, current_debries_field + total_debris);

self.update_fleet_levels_after_attack(mission.destination, f2);
self.update_defences_after_attack(mission.destination, d);

if f1.is_zero() {
self.active_missions.write((origin, mission_id), Zeroable::zero());
} else {
Expand All @@ -746,7 +771,22 @@ mod NoGame {
mission.fleet = f1;
self.active_missions.write((origin, mission_id), Zeroable::zero());
}

self.remove_hostile_mission(mission.destination, mission_id);

let attacker_loss = self.calculate_fleet_loss(mission.fleet, f1);
let defender_loss = self.calculate_fleet_loss(defender_fleet, f2);
let defences_loss = self.calculate_defences_loss(defences, d);
self
.emit_battle_report(
time_now,
origin,
attacker_loss,
mission.destination,
defender_loss,
defences_loss,
total_debris
);
}

fn recall_fleet(ref self: ContractState, mission_id: usize) {
Expand Down Expand Up @@ -1601,6 +1641,54 @@ mod NoGame {
return 10;
}
}

fn calculate_fleet_loss(self: @ContractState, a: Fleet, b: Fleet) -> Fleet {
Fleet {
carrier: a.carrier - b.carrier,
scraper: a.scraper - b.scraper,
sparrow: a.sparrow - b.sparrow,
frigate: a.frigate - b.frigate,
armade: a.armade - b.armade,
}
}

fn calculate_defences_loss(
self: @ContractState, a: DefencesLevels, b: DefencesLevels
) -> DefencesLevels {
DefencesLevels {
celestia: a.celestia - b.celestia,
blaster: a.blaster - b.blaster,
beam: a.beam - b.beam,
astral: a.astral - b.astral,
plasma: a.plasma - b.plasma,
}
}

fn emit_battle_report(
ref self: ContractState,
time: u64,
attacker: u16,
attacker_fleet_loss: Fleet,
defender: u16,
defender_fleet_loss: Fleet,
defences_loss: DefencesLevels,
debris: Debris
) {
self
.emit(
Event::BattleReport(
BattleReport {
time,
attacker,
attacker_fleet_loss,
defender,
defender_fleet_loss,
defences_loss,
debris
}
)
)
}
}
}

5 changes: 3 additions & 2 deletions src/libraries/fleet.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ fn get_distance(start: PlanetPosition, end: PlanetPosition) -> u32 {
}

#[inline(always)]
fn get_debris(f_before: Fleet, f_after: Fleet) -> Debris {
fn get_debris(f_before: Fleet, f_after: Fleet, celestia: u32) -> Debris {
let mut debris: Debris = Default::default();
let costs = Dockyard::get_ships_unit_cost();
let steel = ((f_before.carrier - f_after.carrier).into() * costs.carrier.steel)
Expand All @@ -443,7 +443,8 @@ fn get_debris(f_before: Fleet, f_after: Fleet) -> Debris {
+ ((f_before.scraper - f_after.scraper).into() * costs.scraper.quartz)
+ ((f_before.sparrow - f_after.sparrow).into() * costs.sparrow.quartz)
+ ((f_before.frigate - f_after.frigate).into() * costs.sparrow.quartz)
+ ((f_before.armade - f_after.armade).into() * costs.sparrow.quartz);
+ ((f_before.armade - f_after.armade).into() * costs.sparrow.quartz)
+ (celestia * 2000).into();

debris.steel = steel / 3;
debris.quartz = quartz / 3;
Expand Down
1 change: 1 addition & 0 deletions src/libraries/types.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,4 @@ impl MissionPrint of PrintTrait<Mission> {
self.fleet.print();
}
}

6 changes: 4 additions & 2 deletions src/mocks/mock_upgradable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -829,10 +829,12 @@ mod NoGameUpgraded {
let defences = self.get_defences_levels(mission.destination);
let t1 = self.get_tech_levels(origin);
let t2 = self.get_tech_levels(mission.destination);
let celestia_before = self.get_celestia_available(mission.destination);

let (f1, f2, d) = fleet::war(mission.fleet, t1, defender_fleet, defences, t2);
// calculate debris and update field
let debris1 = fleet::get_debris(mission.fleet, f1);
let debris2 = fleet::get_debris(defender_fleet, f2);
let debris1 = fleet::get_debris(mission.fleet, f1, 0);
let debris2 = fleet::get_debris(defender_fleet, f2, celestia_before - d.celestia);
let total_debris = debris1 + debris2;
let current_debries_field = self.planet_debris_field.read(mission.destination);
self
Expand Down
2 changes: 1 addition & 1 deletion tests/internal_functions/fleet.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,6 @@ fn test_get_debris() {
let mut after: Fleet = Default::default();
before.carrier = 10;
after.carrier = 0;
let res = fleet::get_debris(before, after);
let res = fleet::get_debris(before, after, 10);
}

12 changes: 9 additions & 3 deletions tests/write_tests/fleet_write.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use starknet::info::{get_block_timestamp, get_contract_address};

use snforge_std::{declare, ContractClassTrait, PrintTrait, start_prank, start_warp};
use snforge_std::{
declare, ContractClassTrait, PrintTrait, start_prank, start_warp, spy_events, SpyOn, EventSpy,
EventAssertions, EventFetcher, event_name_hash, Event
};

use nogame::game::main::NoGame;

use nogame::game::interface::{INoGameDispatcher, INoGameDispatcherTrait};
use nogame::libraries::types::{Fleet, Unit, TechLevels, PlanetPosition, ERC20s, DefencesLevels};
Expand Down Expand Up @@ -324,7 +329,8 @@ fn test_attack_planet() {
dsp.game.generate_planet();
build_basic_mines(dsp.game);
advance_game_state(dsp.game);
dsp.game.blaster_build(1);
dsp.game.celestia_build(5);
// dsp.game.blaster_build(1);
let defences_before = dsp.game.get_defences_levels(2);
start_prank(dsp.game.contract_address, ACCOUNT1());
build_basic_mines(dsp.game);
Expand All @@ -347,7 +353,7 @@ fn test_attack_planet() {
let (fleetA_after, fleetB_after, defences_after) = fleet::war(
fleet_a, a_techs, fleet_b, defences_before, b_techs
);
let expected_debris = fleet::get_debris(fleetA_before, fleetA_after);
let expected_debris = fleet::get_debris(fleetA_before, fleetA_after, 5);
let debris_field = dsp.game.get_debris_field(2);
assert(debris_field == expected_debris, 'wrong after debris');

Expand Down

0 comments on commit 7a102fd

Please sign in to comment.