Account
0 APT
Balance
SCORE4
score4
11 entry functions | Bytecode: 5.71 KB
Code
The source code is plain text uploaded by the deployer, which can be different from the actual bytecode.
1module martian::score4 {
2 use std::error;
3 use std::string;
4 use std::vector;
5 use aptos_std::table::{Self, Table};
6 use std::signer;
7 use std::string::String;
8 use aptos_framework::account::SignerCapability;
9 use aptos_framework::resource_account;
10 use aptos_framework::timestamp;
11 use aptos_framework::coin;
12 use coordinator::coordinator::{Self, request};
13 use mint_nft::create_nft;
14 use aptos_framework::event;
15 use aptos_framework::aptos_coin::AptosCoin;
16
17 struct Game has key, store, drop {
18 game_id: u64,
19 expiration_timestamp: u64,
20 player_turn: bool,
21 player: address,
22 grid: vector<vector<u8>>,
23 winner_nft_prompt: String,
24 }
25
26 struct ModuleData has key {
27 signer_cap: SignerCapability,
28 module_enabled: bool,
29 games_count: u64,
30 request_count: u64,
31 games: Table<address, Game>, // address of user -> expiration timestamp
32 active_requests: Table<u64, bool>,
33 model_address: String,
34 usage_fee: u64,
35 fee_account: address,
36 admin_addresses: vector<address>,
37 mint_nft_model_address: String,
38 }
39
40 #[event]
41 struct GameEvent has drop, store {
42 game_id: u64,
43 player: address,
44 outcome: String, // 0 for draw, 1 for win and 2 for lose
45 }
46
47 const ENOT_AUTHORIZED: u64 = 1;
48 const EMODULE_DISABLED: u64 = 2;
49 const EMOVE_NOT_ALLOWED: u64 = 3;
50 const ECANNOT_START_GAME: u64 = 4;
51 const EGAME_EXPIRED: u64 = 5;
52 const EGAME_NOT_STARTED: u64 = 6;
53
54 fun init_module(resource_signer: &signer) {
55 let resource_signer_cap = resource_account::retrieve_resource_account_cap(resource_signer, @source_addr);
56 let admin_addresses = vector::empty();
57 vector::push_back(&mut admin_addresses, @admin_addr);
58 move_to(resource_signer, ModuleData {
59 signer_cap: resource_signer_cap,
60 module_enabled: true,
61 games_count: 0,
62 request_count: 0,
63 games: table::new<address, Game>(),
64 active_requests: table::new<u64, bool>(),
65 model_address: string::utf8(b"0x3"),
66 usage_fee: 1000000,
67 fee_account: @admin_addr,
68 admin_addresses: admin_addresses,
69 mint_nft_model_address: string::utf8(b"0x1"),
70 });
71 }
72
73 fun check_admin(caller: &signer) acquires ModuleData{
74 let module_data = borrow_global<ModuleData>(@martian);
75 let caller_address = signer::address_of(caller);
76 assert!(vector::contains(&module_data.admin_addresses, &caller_address), error::permission_denied(ENOT_AUTHORIZED));
77 }
78
79 public entry fun restart_game(caller: &signer) acquires ModuleData {
80 let module_data = borrow_global_mut<ModuleData>(@martian);
81 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
82 assert!(table::contains<address, Game>(&module_data.games, signer::address_of(caller)), error::permission_denied(EGAME_NOT_STARTED));
83 let game = table::borrow_mut(&mut module_data.games, signer::address_of(caller));
84 game.expiration_timestamp = timestamp::now_seconds() + 6000;
85 game.player_turn = true;
86 game.grid = vector::empty();
87 for (i in 0..6) {
88 let row = vector::empty();
89 for (j in 0..7) {
90 vector::push_back(&mut row, 0);
91 };
92 vector::push_back(&mut game.grid, row);
93 };
94 }
95
96 public entry fun stop_game(caller: &signer) acquires ModuleData {
97 let module_data = borrow_global_mut<ModuleData>(@martian);
98 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
99 assert!(table::contains<address, Game>(&module_data.games, signer::address_of(caller)), error::permission_denied(EGAME_NOT_STARTED));
100 table::remove(&mut module_data.games, signer::address_of(caller));
101 }
102
103 public entry fun start_game(caller: &signer, prompt: String) acquires ModuleData{
104 let module_data = borrow_global_mut<ModuleData>(@martian);
105 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
106 if (table::contains<address, Game>(&module_data.games, signer::address_of(caller))) {
107 let game = table::borrow_mut(&mut module_data.games, signer::address_of(caller));
108 if (game.expiration_timestamp < timestamp::now_seconds()) {
109 table::remove(&mut module_data.games, signer::address_of(caller));
110 };
111 };
112 assert!(!table::contains<address, Game>(&module_data.games, signer::address_of(caller)), error::permission_denied(ECANNOT_START_GAME));
113 let grid = vector::empty();
114 for (i in 0..6) {
115 let row = vector::empty();
116 for (j in 0..7) {
117 vector::push_back(&mut row, 0);
118 };
119 vector::push_back(&mut grid, row);
120 };
121 table::add(&mut module_data.games, signer::address_of(caller), Game {
122 game_id: module_data.games_count,
123 expiration_timestamp: timestamp::now_seconds() + 6000,
124 player_turn: true,
125 player: signer::address_of(caller),
126 grid: grid,
127 winner_nft_prompt: prompt,
128 });
129 module_data.games_count = module_data.games_count + 1;
130 }
131
132 fun transfer_fee(caller: &signer, fee_account: address, amount: u64) {
133 coin::transfer<AptosCoin>(caller, fee_account, amount);
134 }
135
136 public entry fun request_ai(caller: &signer, type: String, model_id: String, input_params: String) acquires ModuleData{
137 let module_data = borrow_global_mut<ModuleData>(@martian);
138 module_data.request_count = module_data.request_count+1;
139 transfer_fee(caller, module_data.fee_account, module_data.usage_fee);
140 table::add(&mut module_data.active_requests, module_data.request_count, true);
141 request(
142 caller,
143 type,
144 model_id,
145 input_params,
146 @martian,
147 module_data.request_count,
148 string::utf8(b"score4::response_ai"),
149 );
150 }
151
152 fun check_game_over(grid: vector<vector<u8>>): bool {
153 let result = true;
154 for (i in 0..6) {
155 for (j in 0..7) {
156 let row_vector = vector::borrow(&grid, i);
157 let value = vector::borrow(row_vector, j);
158 if (*value == 0) {
159 result = false;
160 };
161 };
162 };
163
164 result
165 }
166
167 fun check_win_lose(grid: vector<vector<u8>>, flag: u8): bool {
168 let result = false;
169
170 // Check rows
171 for (i in 0..6) {
172 for (j in 0..4) {
173 if (*vector::borrow(vector::borrow(&grid, i), j) == flag &&
174 *vector::borrow(vector::borrow(&grid, i), j + 1) == flag &&
175 *vector::borrow(vector::borrow(&grid, i), j + 2) == flag &&
176 *vector::borrow(vector::borrow(&grid, i), j + 3) == flag) {
177 result = true;
178 };
179 };
180 };
181
182 // Check columns
183 for (i in 0..3) {
184 for (j in 0..7) {
185 if (*vector::borrow(vector::borrow(&grid, i), j) == flag &&
186 *vector::borrow(vector::borrow(&grid, i + 1), j) == flag &&
187 *vector::borrow(vector::borrow(&grid, i + 2), j) == flag &&
188 *vector::borrow(vector::borrow(&grid, i + 3), j) == flag) {
189 result = true;
190 };
191 };
192 };
193
194 // Check diagonals (bottom left to top right)
195 for (i in 0..3) {
196 for (j in 0..4) {
197 if (*vector::borrow(vector::borrow(&grid, i), j) == flag &&
198 *vector::borrow(vector::borrow(&grid, i + 1), j + 1) == flag &&
199 *vector::borrow(vector::borrow(&grid, i + 2), j + 2) == flag &&
200 *vector::borrow(vector::borrow(&grid, i + 3), j + 3) == flag) {
201 result = true;
202 };
203 };
204 };
205
206 // Check diagonals (top left to bottom right)
207 for (i in 0..3) {
208 for (j in 3..7) {
209 if (*vector::borrow(vector::borrow(&grid, i), j) == flag &&
210 *vector::borrow(vector::borrow(&grid, i + 1), j - 1) == flag &&
211 *vector::borrow(vector::borrow(&grid, i + 2), j - 2) == flag &&
212 *vector::borrow(vector::borrow(&grid, i + 3), j - 3) == flag) {
213 result = true;
214 };
215 };
216 };
217
218 result
219 }
220
221 fun convert_grid_to_string(grid: vector<vector<u8>>): String {
222 let result = string::utf8(b"");
223 for (i in 0..6) {
224 let row_vector = vector::borrow(&grid, i);
225 string::append(&mut result, string::utf8(*row_vector));
226 };
227 result
228 }
229
230 public entry fun play_move(caller: &signer, column: u64) acquires ModuleData {
231 let module_data = borrow_global_mut<ModuleData>(@martian);
232 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
233 assert!(table::contains<address, Game>(&module_data.games, signer::address_of(caller)), error::permission_denied(EGAME_NOT_STARTED));
234 {
235 let game = table::borrow_mut(&mut module_data.games, signer::address_of(caller));
236 let row = get_empty_row(game.grid, column);
237 assert!(row != 10, error::permission_denied(EMOVE_NOT_ALLOWED));
238 let row_vector = vector::borrow_mut(&mut game.grid, row);
239 let value = vector::borrow_mut(row_vector, column);
240 assert!(game.player == signer::address_of(caller), error::permission_denied(ENOT_AUTHORIZED));
241 assert!(game.expiration_timestamp > timestamp::now_seconds(), error::permission_denied(EGAME_EXPIRED));
242 assert!(game.player_turn == true, error::permission_denied(EMOVE_NOT_ALLOWED));
243 *value = 1;
244 game.player_turn = !game.player_turn;
245 game.expiration_timestamp = timestamp::now_seconds() + 6000;
246 };
247 let game = table::borrow(& module_data.games, signer::address_of(caller));
248 let player = game.player;
249 let grid = game.grid;
250 let game_id = game.game_id;
251 let outcome = string::utf8(b"3");
252 if (check_win_lose(grid, 1)) {
253 outcome = string::utf8(b"1");
254 create_nft::request_ai(caller, string::utf8(b"inference"), module_data.mint_nft_model_address, game.winner_nft_prompt);
255 } else if (check_win_lose(grid, 2)) {
256 outcome = string::utf8(b"2");
257 } else if (check_game_over(grid)) {
258 outcome = string::utf8(b"0");
259 };
260 if (outcome != string::utf8(b"3")) {
261 event::emit(
262 GameEvent {
263 game_id: game_id,
264 player: player,
265 outcome: outcome,
266 }
267 );
268 table::remove(&mut module_data.games, player);
269 } else {
270 request_ai(
271 caller,
272 string::utf8(b"inference"),
273 module_data.model_address,
274 convert_grid_to_string(grid),
275 );
276 }
277 }
278
279 fun get_empty_row(grid: vector<vector<u8>>, column: u64): u64 {
280 let ret = 10;
281 for (i in 0..6) {
282 let row_vector = vector::borrow(&grid, i);
283 let value = vector::borrow(row_vector, column);
284 if (*value == 0) {
285 ret = i;
286 };
287 };
288 ret
289 }
290
291 public entry fun response_ai(caller: &signer, coordinator_request_id: u64, client_request_id: u64, requestor_address: address, column: u64) acquires ModuleData {
292 check_admin(caller);
293
294 let module_data = borrow_global_mut<ModuleData>(@martian);
295 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
296
297 assert!(table::contains<address, Game>(&module_data.games, requestor_address), error::permission_denied(EGAME_NOT_STARTED));
298
299 {
300 let game = table::borrow_mut(&mut module_data.games, requestor_address);
301 let row = get_empty_row(game.grid, column);
302 assert!(row != 10, error::permission_denied(EMOVE_NOT_ALLOWED));
303 let row_vector = vector::borrow_mut(&mut game.grid, row);
304 let value = vector::borrow_mut(row_vector, column);
305 assert!(game.expiration_timestamp > timestamp::now_seconds(), error::permission_denied(EGAME_EXPIRED));
306 assert!(*value == 0, error::permission_denied(EMOVE_NOT_ALLOWED));
307 assert!(game.player_turn == false, error::permission_denied(EMOVE_NOT_ALLOWED));
308 *value = 2;
309 game.player_turn = !game.player_turn;
310 game.expiration_timestamp = timestamp::now_seconds() + 6000;
311 };
312 let game = table::borrow(& module_data.games, requestor_address);
313 let player = game.player;
314 let grid = game.grid;
315 let game_id = game.game_id;
316 let outcome = string::utf8(b"3");
317 if (check_win_lose(grid, 1)) {
318 outcome = string::utf8(b"1");
319 };
320 if (check_win_lose(grid, 2)) {
321 outcome = string::utf8(b"2");
322 };
323 if (check_game_over(grid)) {
324 outcome = string::utf8(b"0");
325 };
326 if (outcome != string::utf8(b"3")) {
327 event::emit(
328 GameEvent {
329 game_id: game_id,
330 player: player,
331 outcome: outcome,
332 }
333 );
334 table::remove(&mut module_data.games, player);
335 };
336 table::remove(&mut module_data.active_requests, client_request_id);
337 coordinator::response(caller, coordinator_request_id, requestor_address, outcome);
338 transfer_fee(caller, @coordinator, 100);
339 }
340
341 #[view]
342 public fun get_grid(player: address): String acquires ModuleData {
343 let module_data = borrow_global<ModuleData>(@martian);
344 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
345 assert!(table::contains<address, Game>(&module_data.games, player), error::permission_denied(EGAME_NOT_STARTED));
346 let game = table::borrow(&module_data.games, player);
347 convert_grid_to_string(game.grid)
348 }
349
350 #[view]
351 public fun get_game(player: address): u64 acquires ModuleData {
352 let module_data = borrow_global<ModuleData>(@martian);
353 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
354 assert!(table::contains<address, Game>(&module_data.games, player), error::permission_denied(EGAME_NOT_STARTED));
355 table::borrow(&module_data.games, player).game_id
356 }
357
358 #[view]
359 public fun get_player_turn(player: address): bool acquires ModuleData {
360 let module_data = borrow_global<ModuleData>(@martian);
361 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
362 assert!(table::contains<address, Game>(&module_data.games, player), error::permission_denied(EGAME_NOT_STARTED));
363 table::borrow(&module_data.games, player).player_turn
364 }
365
366 #[view]
367 public fun get_game_expiration(player: address): u64 acquires ModuleData {
368 let module_data = borrow_global<ModuleData>(@martian);
369 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
370 assert!(table::contains<address, Game>(&module_data.games, player), error::permission_denied(EGAME_NOT_STARTED));
371 table::borrow(&module_data.games, player).expiration_timestamp
372 }
373
374 #[view]
375 public fun get_game_count(): u64 acquires ModuleData {
376 let module_data = borrow_global<ModuleData>(@martian);
377 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
378 module_data.games_count
379 }
380
381 #[view]
382 public fun get_request_count(): u64 acquires ModuleData {
383 let module_data = borrow_global<ModuleData>(@martian);
384 assert!(module_data.module_enabled, error::permission_denied(EMODULE_DISABLED));
385 module_data.request_count
386 }
387
388 public entry fun set_module_enabled(caller: &signer, module_enabled: bool) acquires ModuleData {
389 // Abort if the caller is not the admin of this module.
390 check_admin(caller);
391 let module_data = borrow_global_mut<ModuleData>(@martian);
392 module_data.module_enabled = module_enabled;
393 }
394
395 public entry fun change_model_address(caller: &signer, model_address: String) acquires ModuleData {
396 // Abort if the caller is not the admin of this module.
397 check_admin(caller);
398 let module_data = borrow_global_mut<ModuleData>(@martian);
399 module_data.model_address = model_address;
400 }
401
402 public entry fun set_fee_details(caller: &signer, usage_fee: u64, fee_account: address) acquires ModuleData {
403 // Abort if the caller is not the admin of this module.
404 check_admin(caller);
405 let module_data = borrow_global_mut<ModuleData>(@martian);
406 module_data.usage_fee = usage_fee;
407 module_data.fee_account = fee_account;
408 }
409
410 public entry fun add_admin(caller: &signer, admin: address) acquires ModuleData {
411 // Abort if the caller is not the admin of this module.
412 check_admin(caller);
413 let module_data = borrow_global_mut<ModuleData>(@martian);
414 if (!vector::contains(&module_data.admin_addresses, &admin)) {
415 vector::push_back(&mut module_data.admin_addresses, admin);
416 }
417 }
418
419 public entry fun remove_admin(caller: &signer, admin: address) acquires ModuleData {
420 // Abort if the caller is not the admin of this module.
421 check_admin(caller);
422 let module_data = borrow_global_mut<ModuleData>(@martian);
423 vector::remove_value(&mut module_data.admin_addresses, &admin);
424 }
425}
ABI
{
address:
"0x6fe167c9ea99f6ed855311d7d6aafa6be87ee2e0b5218f0d57633b5f24c2c4c1"
name:
"score4"
friends:[]
exposed_functions:[
0:{
name:
"add_admin"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"address"
return:[]
1:{
name:
"change_model_address"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"0x1::string::String"
return:[]
2:{
name:
"get_game"
visibility:
"public"
is_entry:
false
is_view:
true
generic_type_params:[]
params:[
0
:
"address"
return:[
0
:
"u64"
3:{
name:
"get_game_count"
visibility:
"public"
is_entry:
false
is_view:
true
generic_type_params:[]
params:[]
return:[
0
:
"u64"
4:{
name:
"get_game_expiration"
visibility:
"public"
is_entry:
false
is_view:
true
generic_type_params:[]
params:[
0
:
"address"
return:[
0
:
"u64"
5:{
name:
"get_grid"
visibility:
"public"
is_entry:
false
is_view:
true
generic_type_params:[]
params:[
0
:
"address"
return:[
0
:
"0x1::string::String"
6:{
name:
"get_player_turn"
visibility:
"public"
is_entry:
false
is_view:
true
generic_type_params:[]
params:[
0
:
"address"
return:[
0
:
"bool"
7:{
name:
"get_request_count"
visibility:
"public"
is_entry:
false
is_view:
true
generic_type_params:[]
params:[]
return:[
0
:
"u64"
8:{
name:
"play_move"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"u64"
return:[]
9:{
name:
"remove_admin"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"address"
return:[]
10:{
name:
"request_ai"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"0x1::string::String"
2
:
"0x1::string::String"
3
:
"0x1::string::String"
return:[]
11:{
name:
"response_ai"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"u64"
2
:
"u64"
3
:
"address"
4
:
"u64"
return:[]
12:{
name:
"restart_game"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
return:[]
13:{
name:
"set_fee_details"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"u64"
2
:
"address"
return:[]
14:{
name:
"set_module_enabled"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"bool"
return:[]
15:{
name:
"start_game"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
1
:
"0x1::string::String"
return:[]
16:{
name:
"stop_game"
visibility:
"public"
is_entry:
true
is_view:
false
generic_type_params:[]
params:[
0
:
"&signer"
return:[]
structs:[
0:{
name:
"Game"
is_native:
false
is_event:
false
abilities:[
0
:
"drop"
1
:
"store"
2
:
"key"
generic_type_params:[]
fields:[
0:{
name:
"game_id"
type:
"u64"
1:{
name:
"expiration_timestamp"
type:
"u64"
2:{
name:
"player_turn"
type:
"bool"
3:{
name:
"player"
type:
"address"
4:{
name:
"grid"
type:
"vector<vector<u8>>"
5:{
name:
"winner_nft_prompt"
type:
"0x1::string::String"
1:{
name:
"GameEvent"
is_native:
false
is_event:
true
abilities:[
0
:
"drop"
1
:
"store"
generic_type_params:[]
fields:[
0:{
name:
"game_id"
type:
"u64"
1:{
name:
"player"
type:
"address"
2:{
name:
"outcome"
type:
"0x1::string::String"
2:{
name:
"ModuleData"
is_native:
false
is_event:
false
abilities:[
0
:
"key"
generic_type_params:[]
fields:[
0:{
name:
"signer_cap"
type:
"0x1::account::SignerCapability"
1:{
name:
"module_enabled"
type:
"bool"
2:{
name:
"games_count"
type:
"u64"
3:{
name:
"request_count"
type:
"u64"
4:{
name:
"games"
type:
"0x1::table::Table<address, 0x6fe167c9ea99f6ed855311d7d6aafa6be87ee2e0b5218f0d576 ..."
5:{
name:
"active_requests"
type:
"0x1::table::Table<u64, bool>"
6:{
name:
"model_address"
type:
"0x1::string::String"
7:{
name:
"usage_fee"
type:
"u64"
8:{
name:
"fee_account"
type:
"address"
9:{
name:
"admin_addresses"
type:
"vector<address>"
10:{
name:
"mint_nft_model_address"
type:
"0x1::string::String"