Skip to content

Commit

Permalink
add bool to challenge (#14)
Browse files Browse the repository at this point in the history
* add bool to challenge

* fix

* remove warning + test

* fix
  • Loading branch information
dubzn authored Nov 1, 2024
1 parent 9a7f275 commit 3f6506f
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 66 deletions.
2 changes: 1 addition & 1 deletion src/models/data/challenge.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
struct Challenge {
#[key]
game_id: u32,
active_ids: Span<u32>,
active_ids: Span<(u32, bool)>,
}

#[derive(Copy, Drop, IntrospectPacked, Serde)]
Expand Down
9 changes: 9 additions & 0 deletions src/models/data/events.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,15 @@ struct ChallengeCompleted {
game_id: u32
}

#[derive(Copy, Drop, Serde)]
#[dojo::event]
#[dojo::model]
struct ItemChallengeCompleted {
#[key]
game_id: u32,
challenge_id: u32
}

#[derive(Copy, Drop, Serde)]
#[dojo::event]
#[dojo::model]
Expand Down
2 changes: 1 addition & 1 deletion src/models/status/round/beast.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl BeastImpl of BeastTrait {
_ => Option::None
}.unwrap();
IRageSystemDispatcher { contract_address: rage_system_address.try_into().unwrap() }.calculate(game.id);
// create_level(world, ref store, game); TODO:
// create_level(world, ref store, game); TODO:
} else if player_beast.energy.is_zero() {
_attack_beast(world, ref store, ref game, ref player_beast, ref beast, ref game_mode_beast);
} else {
Expand Down
137 changes: 95 additions & 42 deletions src/models/status/round/challenge.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ use jokers_of_neon::{
data::{
challenge::{Challenge, ChallengeStore, ChallengePlayer, ChallengePlayerStore}, card::{Card, Suit, Value},
game_deck::{GameDeckStore, GameDeckImpl},
events::{ChallengeCompleted, PlayGameOverEvent, ModifierCardSuitEvent, SpecialModifierSuitEvent},
events::{
ChallengeCompleted, ItemChallengeCompleted, PlayGameOverEvent, ModifierCardSuitEvent,
SpecialModifierSuitEvent
},
poker_hand::PokerHand
},
status::{
Expand All @@ -26,7 +29,9 @@ use jokers_of_neon::{
},
},
store::{Store, StoreTrait},
utils::{game::{play as calculate_hand_score}, shop::generate_unique_random_values, calculate_hand::calculate_hand}
utils::{
game::{play as calculate_hand_score}, calculate_hand::calculate_hand, random::{Random, RandomImpl, RandomTrait}
}
};
use starknet::get_caller_address;

Expand All @@ -45,7 +50,7 @@ impl ChallengeImpl of ChallengeTrait {
let mut game = store.get_game(game_id);

let mut challenge = ChallengeStore::get(world, game_id);
challenge.active_ids = generate_unique_random_values(world, 3, challenges_all(), array![]).span();
challenge.active_ids = _generate_random_challenges(world, 3, challenges_all(), array![]).span();
ChallengeStore::set(@challenge, world);
emit!(world, (challenge));

Expand Down Expand Up @@ -75,7 +80,7 @@ impl ChallengeImpl of ChallengeTrait {
let hand_score = calculate_hand_score(world, ref game, @cards_index, @modifiers_index);

let mut challenge = ChallengeStore::get(world, game_id);
_resolve_challenges(ref challenge, result_hand, ref hit_cards, @cards, hand_score);
_resolve_challenges(world, ref challenge, result_hand, ref hit_cards, @cards, hand_score);
ChallengeStore::set(@challenge, world);

if Self::is_completed(@world, game_id) {
Expand Down Expand Up @@ -153,38 +158,39 @@ impl ChallengeImpl of ChallengeTrait {
}

fn _resolve_challenges(
world: IWorldDispatcher,
ref challenge: Challenge,
result_hand: PokerHand,
ref hit_cards: Felt252Dict<bool>,
cards: @Array<Card>,
hand_score: u32,
) {
match result_hand {
PokerHand::RoyalFlush => _complete(ref challenge, CHALLENGE_ROYAL_FLUSH),
PokerHand::StraightFlush => _complete(ref challenge, CHALLENGE_STRAIGHT_FLUSH),
PokerHand::FiveOfAKind => _complete(ref challenge, CHALLENGE_FIVE_OF_A_KIND),
PokerHand::FourOfAKind => _complete(ref challenge, CHALLENGE_FOUR_OF_A_KIND),
PokerHand::FullHouse => _complete(ref challenge, CHALLENGE_FULL_HOUSE),
PokerHand::Straight => _complete(ref challenge, CHALLENGE_STRAIGHT),
PokerHand::Flush => _complete(ref challenge, CHALLENGE_FLUSH),
PokerHand::ThreeOfAKind => _complete(ref challenge, CHALLENGE_THREE_OF_A_KIND),
PokerHand::TwoPair => _complete(ref challenge, CHALLENGE_DOUBLE_PAIR),
PokerHand::OnePair => _complete(ref challenge, CHALLENGE_PAIR),
PokerHand::HighCard => _complete(ref challenge, CHALLENGE_HIGH_CARD),
PokerHand::RoyalFlush => _complete(world, ref challenge, CHALLENGE_ROYAL_FLUSH),
PokerHand::StraightFlush => _complete(world, ref challenge, CHALLENGE_STRAIGHT_FLUSH),
PokerHand::FiveOfAKind => _complete(world, ref challenge, CHALLENGE_FIVE_OF_A_KIND),
PokerHand::FourOfAKind => _complete(world, ref challenge, CHALLENGE_FOUR_OF_A_KIND),
PokerHand::FullHouse => _complete(world, ref challenge, CHALLENGE_FULL_HOUSE),
PokerHand::Straight => _complete(world, ref challenge, CHALLENGE_STRAIGHT),
PokerHand::Flush => _complete(world, ref challenge, CHALLENGE_FLUSH),
PokerHand::ThreeOfAKind => _complete(world, ref challenge, CHALLENGE_THREE_OF_A_KIND),
PokerHand::TwoPair => _complete(world, ref challenge, CHALLENGE_DOUBLE_PAIR),
PokerHand::OnePair => _complete(world, ref challenge, CHALLENGE_PAIR),
PokerHand::HighCard => _complete(world, ref challenge, CHALLENGE_HIGH_CARD),
PokerHand::None => (),
};

if hand_score >= 5000 {
_complete(ref challenge, CHALLENGE_5000_POINTS);
_complete(world, ref challenge, CHALLENGE_5000_POINTS);
}
if hand_score >= 2000 {
_complete(ref challenge, CHALLENGE_2000_POINTS);
_complete(world, ref challenge, CHALLENGE_2000_POINTS);
}
if hand_score >= 1000 {
_complete(ref challenge, CHALLENGE_1000_POINTS);
_complete(world, ref challenge, CHALLENGE_1000_POINTS);
}
if hand_score >= 500 {
_complete(ref challenge, CHALLENGE_500_POINTS);
_complete(world, ref challenge, CHALLENGE_500_POINTS);
}

let mut idx = 0;
Expand All @@ -197,29 +203,29 @@ fn _resolve_challenges(
if hit {
let card = *cards.at(idx);
match card.value {
Value::Two => { _complete(ref challenge, CHALLENGE_TWO); },
Value::Three => { _complete(ref challenge, CHALLENGE_THREE); },
Value::Four => { _complete(ref challenge, CHALLENGE_FOUR); },
Value::Five => { _complete(ref challenge, CHALLENGE_FIVE); },
Value::Six => { _complete(ref challenge, CHALLENGE_SIX); },
Value::Seven => { _complete(ref challenge, CHALLENGE_SEVEN); },
Value::Eight => { _complete(ref challenge, CHALLENGE_EIGHT); },
Value::Nine => { _complete(ref challenge, CHALLENGE_NINE); },
Value::Ten => { _complete(ref challenge, CHALLENGE_TEN); },
Value::Jack => { _complete(ref challenge, CHALLENGE_JACK); },
Value::Queen => { _complete(ref challenge, CHALLENGE_QUEEN); },
Value::King => { _complete(ref challenge, CHALLENGE_KING); },
Value::Ace => { _complete(ref challenge, CHALLENGE_ACE); },
Value::Joker => { _complete(ref challenge, CHALLENGE_JOKER); },
Value::NeonJoker => { _complete(ref challenge, CHALLENGE_JOKER); },
Value::Two => { _complete(world, ref challenge, CHALLENGE_TWO); },
Value::Three => { _complete(world, ref challenge, CHALLENGE_THREE); },
Value::Four => { _complete(world, ref challenge, CHALLENGE_FOUR); },
Value::Five => { _complete(world, ref challenge, CHALLENGE_FIVE); },
Value::Six => { _complete(world, ref challenge, CHALLENGE_SIX); },
Value::Seven => { _complete(world, ref challenge, CHALLENGE_SEVEN); },
Value::Eight => { _complete(world, ref challenge, CHALLENGE_EIGHT); },
Value::Nine => { _complete(world, ref challenge, CHALLENGE_NINE); },
Value::Ten => { _complete(world, ref challenge, CHALLENGE_TEN); },
Value::Jack => { _complete(world, ref challenge, CHALLENGE_JACK); },
Value::Queen => { _complete(world, ref challenge, CHALLENGE_QUEEN); },
Value::King => { _complete(world, ref challenge, CHALLENGE_KING); },
Value::Ace => { _complete(world, ref challenge, CHALLENGE_ACE); },
Value::Joker => { _complete(world, ref challenge, CHALLENGE_JOKER); },
Value::NeonJoker => { _complete(world, ref challenge, CHALLENGE_JOKER); },
Value::None => {},
};

match card.suit {
Suit::Clubs => { _complete(ref challenge, CHALLENGE_CLUBS); },
Suit::Hearts => { _complete(ref challenge, CHALLENGE_HEARTS); },
Suit::Spades => { _complete(ref challenge, CHALLENGE_SPADES); },
Suit::Diamonds => { _complete(ref challenge, CHALLENGE_DIAMONDS); },
Suit::Clubs => { _complete(world, ref challenge, CHALLENGE_CLUBS); },
Suit::Hearts => { _complete(world, ref challenge, CHALLENGE_HEARTS); },
Suit::Spades => { _complete(world, ref challenge, CHALLENGE_SPADES); },
Suit::Diamonds => { _complete(world, ref challenge, CHALLENGE_DIAMONDS); },
Suit::Joker => {},
Suit::None => {},
};
Expand All @@ -228,13 +234,19 @@ fn _resolve_challenges(
};
}

fn _complete(ref challenge: Challenge, challenge_id: u32) {
fn _complete(world: IWorldDispatcher, ref challenge: Challenge, _challenge_id: u32) {
let mut remaining_challenges = array![];
loop {
match challenge.active_ids.pop_front() {
Option::Some(challenge) => { if *challenge != challenge_id {
remaining_challenges.append(*challenge);
} },
Option::Some(challenge_pop) => {
let (challenge_id, completed) = *challenge_pop;
if challenge_id == _challenge_id && !completed {
remaining_challenges.append((challenge_id, true));
emit!(world, ItemChallengeCompleted { game_id: challenge.game_id, challenge_id: challenge_id });
} else {
remaining_challenges.append((challenge_id, completed));
}
},
Option::None => { break; },
}
};
Expand Down Expand Up @@ -355,3 +367,44 @@ fn _has_repeated(array: @Array<u32>) -> bool {
};
}
}


fn item_in_array<
T,
impl TPartialEq: core::traits::PartialEq<T>,
impl TCopy: core::traits::Copy<T>,
impl TDrop: core::traits::Drop<T>,
>(
array: @Array<T>, item: T
) -> bool {
let mut array_span = array.span();
let result = loop {
match array_span.pop_front() {
Option::Some(seen_elem) => { if *seen_elem == item {
break true;
} },
Option::None => { break false; }
};
};
result
}

fn _generate_random_challenges(
world: IWorldDispatcher, size: u32, values: Array<u32>, exclude: Array<u32>
) -> Array<(u32, bool)> {
let mut elements: Array<(u32, bool)> = ArrayTrait::new();
let mut randomizer = RandomImpl::new(world);

assert(size <= values.len(), 'error size unique values');
loop {
if elements.len() == size {
break;
}
let new_elem = *values.at(randomizer.between::<u32>(0, values.len() - 1));
if item_in_array(@exclude, new_elem) || item_in_array(@elements, (new_elem, false)) {
continue;
}
elements.append((new_elem, false));
};
elements
}
21 changes: 18 additions & 3 deletions src/tests/test_challenge.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ mod test_challenge {
ChallengeStore::set(
@Challenge {
game_id: game.id,
active_ids: array![CHALLENGE_STRAIGHT, CHALLENGE_CLUBS, CHALLENGE_HEARTS, CHALLENGE_TEN].span()
active_ids: array![
(CHALLENGE_STRAIGHT, false),
(CHALLENGE_CLUBS, false),
(CHALLENGE_HEARTS, false),
(CHALLENGE_TEN, false)
]
.span()
},
world
);
Expand All @@ -48,7 +54,16 @@ mod test_challenge {
set_contract_address(PLAYER());
systems.game_system.play(game.id, array![0, 1, 2, 3, 4], array![100, 100, 100, 100, 100]);

let challenge = ChallengeStore::get(world, game.id);
assert(challenge.active_ids.len().is_zero(), 'wrong len');
let mut challenge = ChallengeStore::get(world, game.id);
assert(challenge.active_ids.len() == 4, 'wrong len');
loop {
match challenge.active_ids.pop_front() {
Option::Some(challenge) => {
let (_, completed) = *challenge;
assert(completed, 'challenge should be completed');
},
Option::None => { break; }
}
};
}
}
20 changes: 10 additions & 10 deletions src/tests/test_game_play.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -649,48 +649,48 @@ mod test_rage_cards {
let round_after = store.get_round(game.id);
assert(round_after.player_score == 40, 'wrong round player_score');
}
// #[test]
// #[test]
// #[available_gas(30000000000000000)]
// fn test_play_rage_card_diminished_hold() {
// let (world, systems) = setup::spawn_game();
// let mut store = StoreTrait::new(world);
// let mut game = mock_game(ref store, PLAYER());
// mock_round(ref store, @game, 300);

// // Mock RageRound
// // Mock RageRound
// let len_hand_before = game.len_hand;
// mock_rage_round(world, game.id, array![RAGE_CARD_DIMINISHED_HOLD]);

// // Set game state in shop
// // Set game state in shop
// game.state = GameState::AT_SHOP;
// store.set_game(game);

// set_contract_address(PLAYER());
// set_contract_address(PLAYER());
// systems.shop_system.skip_shop(game.id);

// let game_after = store.get_game(game.id);
// let game_after = store.get_game(game.id);
// assert(game_after.len_hand == len_hand_before - 2, 'wrong game_after len_hand');
// }

// #[test]
// #[test]
// #[available_gas(30000000000000000)]
// fn test_play_rage_card_zero_waste() {
// let (world, systems) = setup::spawn_game();
// let mut store = StoreTrait::new(world);
// let mut game = mock_game(ref store, PLAYER());
// mock_round(ref store, @game, 300);

// // Mock RageRound
// // Mock RageRound
// mock_rage_round(world, game.id, array![RAGE_CARD_ZERO_WASTE]);

// // Set game state in shop
// // Set game state in shop
// game.state = GameState::AT_SHOP;
// store.set_game(game);

// set_contract_address(PLAYER());
// set_contract_address(PLAYER());
// systems.shop_system.skip_shop(game.id);

// let round = store.get_round(game.id);
// let round = store.get_round(game.id);
// assert(round.discard == 0, 'wrong round discard');
// }
}
Expand Down
8 changes: 4 additions & 4 deletions src/tests/test_game_play_beast.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -280,23 +280,23 @@ mod test_play_beast_special_cards {
player_beast_after.energy == player_beast_before.energy - game_mode_beast.cost_play, 'wrong player energy'
);
}
// #[test]
// #[test]
// #[available_gas(30000000000000000)]
// fn test_play_special_initial_advantage() {
// let (world, systems) = setup::spawn_game();
// let mut store = StoreTrait::new(world);
// let mut game = mock_game(ref store, PLAYER());
// mock_round(ref store, @game, 300);

// // Mock special card
// // Mock special card
// let special_cards_ids = array![SPECIAL_INITIAL_ADVANTAGE_ID];
// mock_special_cards(ref store, ref game, special_cards_ids);

// // Mock hand
// // Mock hand
// let hand_cards_ids = array![ACE_CLUBS_ID, ACE_HEARTS_ID, ACE_DIAMONDS_ID, ACE_SPADES_ID];
// mock_current_hand_cards_ids(ref store, game.id, hand_cards_ids);

// set_contract_address(PLAYER());
// set_contract_address(PLAYER());
// systems.game_system.play(game.id, array![0, 1, 2, 3], array![100, 100, 100, 100]);
// // Four of a Kind - points: 60, multi: 7
// // points: 11 + 11 + 11 + 11 + 100
Expand Down
9 changes: 4 additions & 5 deletions src/tests/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,11 @@ fn mock_game(ref store: Store, owner: ContractAddress) -> Game {
fn mock_level_best(world: IWorldDispatcher, game_id: u32) {
let game_mode_beast = GameModeBeast { game_id, cost_discard: 1, cost_play: 2, energy_max_player: 3 };
GameModeBeastStore::set(@game_mode_beast, world);
// let beast = Beast { game_id, tier: 5, level: 5, health: 300, attack: 15 };
// BeastStore::set(@beast, world);

let beast = Beast { game_id, tier: 5, level: 5, health: 300, attack: 15 };
BeastStore::set(@beast, world);

let player_beast = PlayerBeast { game_id, health: 100, energy: game_mode_beast.energy_max_player };
PlayerBeastStore::set(@player_beast, world);
// let player_beast = PlayerBeast { game_id, health: 100, energy: game_mode_beast.energy_max_player };
// PlayerBeastStore::set(@player_beast, world);
}

fn mock_game_deck(world: IWorldDispatcher, game_id: u32) -> GameDeck {
Expand Down

0 comments on commit 3f6506f

Please sign in to comment.